diff --git a/src/hollander_bringup/config/perception.config.yaml b/src/hollander_bringup/config/perception.config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..186db237f95cc862dfebd2c738624d0e9b034b3d
--- /dev/null
+++ b/src/hollander_bringup/config/perception.config.yaml
@@ -0,0 +1,113 @@
+/**:
+  ros__parameters:
+    # SETTINGS
+    base_frame_id: "link" # Define the frame_id all static transformations refers to.
+    odom_frame_id: "odom" # Define the origin coordinate system in ROS convention (X-Forward, Y-Left, Z-Up). Pose topic defines the pose relative to that system.
+    initial_reset: true # Allows resetting the device before using it. Recommended to be used for example, when a glitch prevented the device from being properly closed.
+    wait_for_device_timeout: -1.0 # Timeout for waiting for device to connect [seconds]
+    reconnect_timeout: 5.0 # Timeout between consecutive reconnection attempts [seconds]
+    enable_sync: false # ??
+
+hollander:
+  cameras:
+    front:
+      camera_1571: # LINK https://dev.intelrealsense.com/docs/ros-wrapper#section-launch-parameters
+        ros__parameters:
+          # CAMERA IDENTITY
+          serial_no: "008222071571" # Attach to the device with the given serial number (serial_no) number.
+          camera_name: "camera_1571"
+
+          # TF
+          publish_tf: true # A Boolean parameter, publish or not TF at all.
+          tf_prefix: "front_camera" # This parameter allows changing the frames' IDs prefix per camera.
+          tf_publish_rate: 0.0 # A double parameter, positive values mean dynamic transform publication with specified rate, all other values mean static transform publication.
+          publish_odom_tf: true # A Boolean parameter, publish if True TF from odom_frame to pose_frame.
+
+          # IMU
+          unite_imu_method: 2 # [0-None, 1-copy, 2-linear_interpolation]
+          linear_accel_cov: 0.01 # Set the variance given to the Imu readings.
+          angular_velocity_cov: 0.01
+
+          enable_gyro: true # Enable gyro stream
+          gyro_fps: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          enable_accel: true # Enable accel stream
+          accel_fps: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+
+          # DEPTH
+          enable_depth: true # Enable depth stream
+          depth_width: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          depth_height: 0
+          depth_fps: 0
+          clip_distance: 5.0 # Remove from the depth image all values above a given value (meters).
+          align_depth: true # If set to true, will publish additional topics with all the images aligned to the depth image.
+
+          pointcloud.enable: true
+          depth_module.visual_preset: 3
+
+          #COLOR
+          enable_color: true # Enable color stream
+          color_width: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          color_height: 0
+          color_fps: 0
+
+          # INFRA
+          enable_infra1: false # Enable infra1 stream
+          enable_infra2: false # Enable infra2 stream
+          infra_width: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          infra_height: 0
+          infra_fps: 0
+
+    back:
+      camera_1502: # LINK https://dev.intelrealsense.com/docs/ros-wrapper#section-launch-parameters
+        ros__parameters:
+          # CAMERA IDENTITY
+          serial_no: "008222071502" # Attach to the device with the given serial number (serial_no) number.
+          camera_name: "camera_1502"
+
+          # SETTINGS
+          base_frame_id: "link" # Define the frame_id all static transformations refers to.
+          odom_frame_id: "odom" # Define the origin coordinate system in ROS convention (X-Forward, Y-Left, Z-Up). Pose topic defines the pose relative to that system.
+          initial_reset: false # Allows resetting the device before using it. Recommended to be used for example, when a glitch prevented the device from being properly closed.
+          wait_for_device_timeout: -1.0 # Timeout for waiting for device to connect [seconds]
+          reconnect_timeout: 5.0 # Timeout between consecutive reconnection attempts [seconds]
+          enable_sync: false # ??
+
+          # TF
+          publish_tf: true # A Boolean parameter, publish or not TF at all.
+          tf_prefix: "back_camera" # This parameter allows changing the frames' IDs prefix per camera.
+          tf_publish_rate: 0.0 # A double parameter, positive values mean dynamic transform publication with specified rate, all other values mean static transform publication.
+          publish_odom_tf: true # A Boolean parameter, publish if True TF from odom_frame to pose_frame.
+
+          # IMU
+          unite_imu_method: 2 # [0-None, 1-copy, 2-linear_interpolation]
+          linear_accel_cov: 0.01 # Set the variance given to the Imu readings.
+          angular_velocity_cov: 0.01
+
+          enable_gyro: true # Enable gyro stream
+          gyro_fps: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          enable_accel: true # Enable accel stream
+          accel_fps: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+
+          # DEPTH
+          enable_depth: true # Enable depth stream
+          depth_width: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          depth_height: 0
+          depth_fps: 0
+          clip_distance: 5.0 # Remove from the depth image all values above a given value (meters).
+          align_depth: true # If set to true, will publish additional topics with all the images aligned to the depth image.
+
+          pointcloud.enable: true
+          depth_module.visual_preset: 3
+
+          #COLOR
+          enable_color: true # Enable color stream
+          color_width: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          color_height: 0
+          color_fps: 0
+
+          # INFRA
+          enable_infra1: false # Enable infra1 stream
+          enable_infra2: false # Enable infra2 stream
+          infra_width: 0 # Setting a value to 0, will choose the first format in the inner list. (i.e. consistent between runs but not defined).
+          infra_height: 0
+          infra_fps: 0
\ No newline at end of file
diff --git a/src/hollander_bringup/config/teleop.joy.config.yaml b/src/hollander_bringup/config/teleop.joy.config.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1a2c8a6b0c78b8ba8cce771683a294faa48134e2
--- /dev/null
+++ b/src/hollander_bringup/config/teleop.joy.config.yaml
@@ -0,0 +1,29 @@
+hollander:
+  joy_node:
+    ros__parameters:
+      dev: "/dev/input/js0"
+      deadzone: 0.15
+      autorepeat_rate: 20.0
+
+  teleop_hollander_joy:
+    ros__parameters:
+      buttons_publish_frequency: 10.0
+
+  teleop_twist_joy:
+    ros__parameters:
+      axis_linear: # Left thumb stick vertical
+        x: 1
+      scale_linear:
+        x: 0.3
+      scale_linear_turbo:
+        x: 0.7
+
+      axis_angular: # Left thumb stick horizontal
+        yaw: 0
+      scale_angular:
+        yaw: 0.2
+      scale_angular_turbo:
+        yaw: 0.4
+
+      enable_button: 5 # Left trigger button
+      enable_turbo_button: 4 # Right trigger button
diff --git a/src/hollander_bringup/launch/perception.launch.py b/src/hollander_bringup/launch/perception.launch.py
new file mode 100644
index 0000000000000000000000000000000000000000..155fb368cc1013ea756671d61d5ac459842627fa
--- /dev/null
+++ b/src/hollander_bringup/launch/perception.launch.py
@@ -0,0 +1,62 @@
+import os
+
+from ament_index_python.packages import get_package_share_directory
+from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
+from launch_ros.actions import Node
+from launch.substitutions import LaunchConfiguration
+from launch import LaunchDescription
+from launch.conditions import IfCondition
+from launch.launch_description_sources import PythonLaunchDescriptionSource
+
+
+def generate_launch_description():
+    # Get launch configuration
+    launch_dir = get_package_share_directory('hollander_bringup')
+    default_config_file = os.path.join(launch_dir, 'config', 'perception.config.yaml')
+
+    # Parameters
+    configurable_parameters = [
+        {'name': 'front_camera_name', 'default': 'camera_1571',             'description': 'camera unique name'},
+        {'name': 'back_camera_name',  'default': 'camera_1502',             'description': 'camera unique name'},
+        {'name': 'front_namespace',   'default': 'hollander/cameras/front', 'description': 'Namespace to avoide conflicts'},
+        {'name': 'back_namespace',    'default': 'hollander/cameras/back',  'description': 'Namespace to avoide conflicts'},
+        {'name': 'config',            'default': default_config_file,       'description': 'Namespace to avoide conflicts'},
+        {'name': 'log_level',         'default': 'info',                    'description': 'debug log level [DEBUG|INFO|WARN|ERROR|FATAL]'},
+    ]
+
+    def declare_configurable_parameters(parameters):
+        return [DeclareLaunchArgument(param['name'], default_value=param['default'], description=param['description']) for param in parameters]
+
+    front_camera = Node(
+        package='realsense2_camera',
+        executable='realsense2_camera_node',
+        name=LaunchConfiguration("front_camera_name"),
+        namespace=LaunchConfiguration("front_namespace"),
+        parameters=[LaunchConfiguration("config")],
+        output='screen',
+        arguments=['--ros-args', '--log-level', LaunchConfiguration('log_level')],
+        emulate_tty=True,
+    )
+
+    back_camera = Node(
+        package='realsense2_camera',
+        executable='realsense2_camera_node',
+        name=LaunchConfiguration("back_camera_name"),
+        namespace=LaunchConfiguration("back_namespace"),
+        parameters=[LaunchConfiguration("config")],
+        output='screen',
+        arguments=['--ros-args', '--log-level', LaunchConfiguration('log_level')],
+        emulate_tty=True,
+    )
+
+    pointclouds_to_laserscan = IncludeLaunchDescription(
+        PythonLaunchDescriptionSource(os.path.join(get_package_share_directory('hollander_bringup'), 'launch', 'ptl.launch.py')),
+        condition=IfCondition(LaunchConfiguration('need_description'))
+    )
+
+    return LaunchDescription( declare_configurable_parameters(configurable_parameters) + [
+            front_camera,
+            back_camera,
+
+            pointclouds_to_laserscan,
+        ])
diff --git a/src/hollander_bringup/launch/teleop.joy.launch.py b/src/hollander_bringup/launch/teleop.joy.launch.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d86e623027b8c3bc9e179a6cd1a744dc2abf2db
--- /dev/null
+++ b/src/hollander_bringup/launch/teleop.joy.launch.py
@@ -0,0 +1,54 @@
+import os
+
+from ament_index_python.packages import get_package_share_directory
+from launch.actions import DeclareLaunchArgument
+from launch_ros.actions import Node
+from launch import LaunchDescription
+from launch.substitutions import LaunchConfiguration
+
+def generate_launch_description():
+
+        # Get launch configuration
+    launch_dir = get_package_share_directory('hollander_bringup')
+    default_config_file = os.path.join(launch_dir, 'config', 'teleop.joy.config.yaml')
+
+    # Parametersros
+    configurable_parameters = [
+        {'name': 'namespace',         'default': 'hollander',            'description': 'Namespace to avoide conflicts'},
+        {'name': 'config',            'default': default_config_file,    'description': 'Namespace to avoide conflicts'},
+        {'name': 'log_level',         'default': 'info',                 'description': 'debug log level [DEBUG|INFO|WARN|ERROR|FATAL]'},
+    ]
+
+    def declare_configurable_parameters(parameters):
+        return [DeclareLaunchArgument(param['name'], default_value=param['default'], description=param['description']) for param in parameters]
+
+
+    joy_node = Node(
+        package='joy',
+        executable='joy_node',
+        name='joy_node',
+        namespace=LaunchConfiguration("namespace"),
+        parameters=[default_config_file],
+    )
+
+    hollander_teleop_joy_node = Node(
+        package='hollander_teleop',
+        executable='hollander_teleop_joy',
+        name='teleop_hollander_joy',
+        namespace=LaunchConfiguration("namespace"),
+        parameters=[default_config_file],
+    )
+
+    teleop_twist_joy_node = Node(
+        package='teleop_twist_joy',
+        executable='teleop_node',
+        name='teleop_twist_joy',
+        namespace=LaunchConfiguration("namespace"),
+        parameters=[default_config_file],
+    )
+
+    return LaunchDescription( declare_configurable_parameters(configurable_parameters) + [
+        joy_node,
+        hollander_teleop_joy_node,
+        teleop_twist_joy_node,
+    ])
diff --git a/src/puntenwolk_fusie/include/puntenwolk_fusie/puntenwolk_fusie.hpp b/src/puntenwolk_fusie/include/puntenwolk_fusie/puntenwolk_fusie.hpp
index 529daba51855cfdeed591501f846b9dd2fbdd50d..6e66e2bbf1c9f2f79980d5e726cd157255d30aea 100644
--- a/src/puntenwolk_fusie/include/puntenwolk_fusie/puntenwolk_fusie.hpp
+++ b/src/puntenwolk_fusie/include/puntenwolk_fusie/puntenwolk_fusie.hpp
@@ -65,7 +65,7 @@ class PuntenwolkFusie : public lc::LifecycleNode {
     lc::LifecyclePublisher<sensor_msgs::msg::PointCloud2>::SharedPtr cloud_publisher;
 
     // TF Listener
-    std::shared_ptr<tf2_ros::TransformListener> transform_listener_;
+    std::shared_ptr<const tf2_ros::TransformListener> transform_listener_;
     std::unique_ptr<tf2_ros::Buffer> tf_buffer_;
 
     // Subscribe
diff --git a/src/puntenwolk_fusie/package.xml b/src/puntenwolk_fusie/package.xml
index 29b53b7877e399f9854fa5cd003ccd3c7d8f9ff7..b34622328eaeebe628f4adbe916467237fb4a15e 100644
--- a/src/puntenwolk_fusie/package.xml
+++ b/src/puntenwolk_fusie/package.xml
@@ -3,9 +3,9 @@
 <package format="3">
   <name>puntenwolk_fusie</name>
   <version>0.0.0</version>
-  <description>TODO: Package description</description>
-  <maintainer email="galambos.mihaly@hallgato.ppke.hu">galmi</maintainer>
-  <license>TODO: License declaration</license>
+  <description>Node for merging two sensor_msgs/PointCloud2 message.</description>
+  <maintainer email="galambos.mihaly@hallgato.ppke.hu">Mihaly Galambos</maintainer>
+  <license>Apache 2.0</license>
 
   <buildtool_depend>ament_cmake_auto</buildtool_depend>
 
@@ -13,6 +13,7 @@
   <depend>rclcpp_components</depend>
   <depend>rclcpp_lifecycle</depend>
   <depend>lifecycle_msgs</depend>
+  <depend>tf2</depend>
   <depend>tf2_ros</depend>
   <depend>sensor_msgs</depend>
   <depend>pcl_conversions</depend>
diff --git a/src/puntenwolk_fusie/src/puntenwolk_fusie.cpp b/src/puntenwolk_fusie/src/puntenwolk_fusie.cpp
index 8e0369144a9836212d602c56d9ac0112c0789de0..e8e03ca2ea11a70a4823a207d1b852f32418fc5a 100644
--- a/src/puntenwolk_fusie/src/puntenwolk_fusie.cpp
+++ b/src/puntenwolk_fusie/src/puntenwolk_fusie.cpp
@@ -2,11 +2,12 @@
 // INCLUDE - Common
 #include "pcl_conversions/pcl_conversions.h"
 #include "pcl_ros/transforms.hpp"
+#include "tf2/exceptions.h"
 
 // INCLUDE - Header
 #include "puntenwolk_fusie/puntenwolk_fusie.hpp"
 
-PuntenwolkFusie::PuntenwolkFusie(rclcpp::NodeOptions options) : lc::LifecycleNode("odometry_publisher", options) {
+PuntenwolkFusie::PuntenwolkFusie(rclcpp::NodeOptions options) : lc::LifecycleNode("puntenwolk_fusie", options) {
     /// Parameters
     this->declare_all_parameters();
 
@@ -18,7 +19,7 @@ LNI::CallbackReturn PuntenwolkFusie::on_configure(const lc::State& state) {
     (void)state;
 
     // Publisher
-    cloud_publisher = this->create_publisher<sensor_msgs::msg::PointCloud2>(cloud_out_topic_name, 10);
+    cloud_publisher = this->create_publisher<sensor_msgs::msg::PointCloud2>(cloud_out_topic_name, rclcpp::SensorDataQoS());
 
     // Timers
     cloud_publisher_timer = this->create_wall_timer(std::chrono::milliseconds((int)(1000.0 / publish_frequency)), std::bind(&PuntenwolkFusie::merge_clouds, this));
@@ -84,10 +85,12 @@ void PuntenwolkFusie::declare_all_parameters() {
 
 void PuntenwolkFusie::cloud_in_1_callback(const sensor_msgs::msg::PointCloud2::SharedPtr msg) {
     cloud_in_1 = msg;
+    RCLCPP_DEBUG(this->get_logger(), "Cloud in 1 was received!");
 }
 
 void PuntenwolkFusie::cloud_in_2_callback(const sensor_msgs::msg::PointCloud2::SharedPtr msg) {
     cloud_in_2 = msg;
+    RCLCPP_DEBUG(this->get_logger(), "Cloud in 2 was received!");
 }
 
 void PuntenwolkFusie::merge_clouds() {
@@ -95,16 +98,24 @@ void PuntenwolkFusie::merge_clouds() {
     sensor_msgs::msg::PointCloud2 transformed_cloud_2;
 
     if (cloud_in_1 != NULL && cloud_in_2 != NULL) {
+        RCLCPP_DEBUG(this->get_logger(), "Both cloud are OK");
+
         bool success = false;
 
-        success &= pcl_ros::transformPointCloud(target_frame_id, *cloud_in_1, transformed_cloud_1, *tf_buffer_);
-        success &= pcl_ros::transformPointCloud(target_frame_id, *cloud_in_2, transformed_cloud_2, *tf_buffer_);
+        success = pcl_ros::transformPointCloud(target_frame_id, *cloud_in_1, transformed_cloud_1, *tf_buffer_);
+        RCLCPP_DEBUG(this->get_logger(), "First transform: %d", success);
+
+        success = pcl_ros::transformPointCloud(target_frame_id, *cloud_in_2, transformed_cloud_2, *tf_buffer_);
+        RCLCPP_DEBUG(this->get_logger(), "Second transform: %d", success);
 
         sensor_msgs::msg::PointCloud2 msg;
 
-        success &= pcl::concatenatePointCloud(transformed_cloud_1, transformed_cloud_2, msg);
+        success = pcl::concatenatePointCloud(transformed_cloud_1, transformed_cloud_2, msg);
+        RCLCPP_DEBUG(this->get_logger(), "Merge: %d", success);
 
         if (success && cloud_publisher->is_activated()) {
+            RCLCPP_DEBUG(this->get_logger(), "Publishing merged cloud");
+
             cloud_publisher->publish(msg);
         }
     }