This code is mainly the original paper's example code modified to use more
recent API calls. It takes a prompt (i.e. context) and a query, sends it to
OpenAI, and returns a response.


####  Navigate


_I suggest setting` parking_brake:=true ` initially, as it takes time for the
robot to initialize before the system can even accept commands. _


* This tutorial is only available in Humble


####  User Input Validation


**If you are using the simulator, call:**


        # Subscribe to the /battery_state topic
    self.battery_state_subscriber = self.create_subscription(
        BatteryState,
        'battery_state',
        self.battery_state_callback,
        qos_profile_sensor_data)


     [ __ ](https://www.youtube.com/c/Clearpath "Clearpath Robotics Youtube")
     [ __ ](https://www.facebook.com/ClearpathInc/ "Clearpath Robotics Facebook")
     [ __ ](https://ca.linkedin.com/company/clearpathinc "Clearpath Robotics Linkedin")
     [ __ ](https://twitter.com/clearpathrobots "Clearpath Robotics Twitter")


The Publish Point tool allows you to click on a point on the map, and have the
coordinates of that point published to the ` /clicked_point ` topic.


    if not navigator.getDockedStatus():
        navigator.info('Docking before initialising pose')
        navigator.dock()


###  Running


ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true rviz:=true


TurtleBot 4 is the next-generation of the world’s most popular open source robotics platform for education and research, offering better computing power, better sensors and a world class user experience at an affordable price point.


The user input is verified to be an integer which is within the allowable
range. If it is not a number or if the number does not correspond to a valid
option then the loop will restart, prompting the user for a new input.


Once the simulation has started, open another terminal and run:


bt_navigator_navigate_to_pose_rclcpp_node:
  ros__parameters:
    use_sim_time: True


A Global Interpreter Lock (GIL) is used to ensure that the main function and
battery monitoring functions do not access or modify that member variable at
the same time.


Let's take a look at the main function.


###  SLAM


As the path is created, you will see the robot being placed at the position
you click on. This is normal and gets cleared up when the initial pose is set
by the TurtleBot 4 Navigator.


It is very important that the examples found in this file are bug-free. For
further details, see the [ original paper ](https://arxiv.org/abs/2209.07753)
.


[ Mechanical ](/turtlebot4-user-manual/mechanical/)


Then, ` spin() ` is entered and we are ready to receive commands!


` parking_brake ` serves the purpose outlined above in the **Running** section


####  Wait for Nav2


[ User Manual ](/turtlebot4-user-manual/)


* This example demonstrates the [ Navigate Through Poses ](https://navigation.ros.org/behavior_trees/trees/nav_through_poses_recovery.html) behaviour tree. The Nav2 stack is given a set of poses on the map and creates a path that goes through each pose in order until the last pose is reached. The robot then attempts to drive along the path. This example is demonstrated in the ` warehouse ` world of the TurtleBot 4 simulation.


ros2 launch turtlebot4_navigation localization.launch.py map:=office.yaml


For example:


#####  User Input


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/galactic/turtlebot4_python_tutorials/turtlebot4_python_tutorials/follow_waypoints.py) .


TurtleBot 4 comes in two models – TurtleBot 4 Standard and TurtleBot 4 Lite. Both are equipped with an iRobot® Create3 mobile base, a powerful Raspberry Pi 4 running ROS 2, OAK-D spatial AI stereo camera, 2D LiDAR and more. All components have been seamlessly integrated to deliver an out-of-the-box development and learning platform. Tap into the thriving open source ROS developer community and get started learning robotics on day one.


Based on the battery charge level, the program chooses an action:


Once the robot has reached the goal, we call ` rclpy.shutdown() ` to
gracefully destroy the rclpy context.


ros2 run turtlebot4_python_tutorials create_path


##  Create Path


You can visualise the navigation process in Rviz. If Rviz wasn't already
launched, launch it by calling:


  * galactic
  * humble


  * [ 1\. Features ](/turtlebot4-user-manual/overview/features.html)
  * [ 2\. Resources ](/turtlebot4-user-manual/overview/resources.html)


####  Main Script


![Publish Point](media/clicked_point.gif) Getting a point coordinate


This example starts the same as  navigate to pose  . We initialise the node,
make sure the robot is docked, and set the initial pose. Then we wait for Nav2
to become active.


        else:
        # Navigate to requested position
        navigator.startToPose(goal_options[selected_index]['pose'])


Let's take a look at the main function.


        def main():
        rclpy.init()

        navigator = TurtleBot4Navigator()

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Set goal poses
        goal_pose = []
        goal_pose.append(navigator.getPoseStamped([0.0, -1.0], TurtleBot4Directions.NORTH))
        goal_pose.append(navigator.getPoseStamped([1.7, -1.0], TurtleBot4Directions.EAST))
        goal_pose.append(navigator.getPoseStamped([1.6, -3.5], TurtleBot4Directions.NORTH))
        goal_pose.append(navigator.getPoseStamped([6.75, -3.46], TurtleBot4Directions.NORTH_WEST))
        goal_pose.append(navigator.getPoseStamped([7.4, -1.0], TurtleBot4Directions.SOUTH))
        goal_pose.append(navigator.getPoseStamped([-1.0, -1.0], TurtleBot4Directions.WEST))

        # Undock
        navigator.undock()

        # Navigate through poses
        navigator.startThroughPoses(goal_pose)

        # Finished navigating, dock
        navigator.dock()

        rclpy.shutdown()


##  Large Language Model Integration


ros2 launch turtlebot4_viz view_robot.launch.py


            if (battery_percent is not None):
                navigator.info(f'Battery is at {(battery_percent*100):.2f}% charge')

                # Check battery charge level
                if (battery_percent < BATTERY_CRITICAL):
                    navigator.error('Battery critically low. Charge or power down')
                    break
                elif (battery_percent < BATTERY_LOW):
                    # Go near the dock
                    navigator.info('Docking for charge')
                    navigator.startToPose(navigator.getPoseStamped([-1.0, 1.0],
                                          TurtleBot4Directions.EAST))
                    navigator.dock()

                    if not navigator.getDockedStatus():
                        navigator.error('Robot failed to dock')
                        break

                    # Wait until charged
                    navigator.info('Charging...')
                    battery_percent_prev = 0
                    while (battery_percent < BATTERY_HIGH):
                        sleep(15)
                        battery_percent_prev = floor(battery_percent*100)/100
                        with lock:
                            battery_percent = battery_monitor.battery_percent

                        # Print charge level every time it increases a percent
                        if battery_percent > (battery_percent_prev + 0.01):
                            navigator.info(f'Battery is at {(battery_percent*100):.2f}% charge')

                    # Undock
                    navigator.undock()
                    position_index = 0

                else:
                    # Navigate to next position
                    navigator.startToPose(goal_pose[position_index])

                    position_index = position_index + 1


        ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true \
    rviz:=true world:=depot map:=/opt/ros/humble/share/turtlebot4_navigation/maps/depot.yaml


###  Code breakdown


* This example demonstrates the [ Navigate Through Poses ](https://navigation.ros.org/behavior_trees/trees/nav_through_poses_recovery.html) behaviour tree. The Nav2 stack is given a set of poses on the map and creates a path that goes through each pose in order until the last pose is reached. The robot then attempts to drive along the path. This example is demonstrated in the ` depot ` world of the TurtleBot 4 simulation.


__ Note


The TurtleBot 4 Navigator uses cardinal directions to set the orientation of
the robot relative to the map. You can use actual integers or floating points
if you need a more precise direction.


  * [ 1\. Driving your TurtleBot 4 ](/turtlebot4-user-manual/tutorials/driving.html)
  * [ 2\. Creating your first node (C++) ](/turtlebot4-user-manual/tutorials/first_node_cpp.html)
  * [ 3\. Creating your first node (Python) ](/turtlebot4-user-manual/tutorials/first_node_python.html)
  * [ 4\. Generating a map ](/turtlebot4-user-manual/tutorials/generate_map.html)
  * [ 5\. Navigation ](/turtlebot4-user-manual/tutorials/navigation.html)
  * [ 6\. TurtleBot 4 Navigator ](/turtlebot4-user-manual/tutorials/turtlebot4_navigator.html)
  * [ 7\. Multiple robots ](/turtlebot4-user-manual/tutorials/multiple_robots.html)


robot_state_publisher:
  ros__parameters:
    use_sim_time: True


ros2 run turtlebot4_python_tutorials nav_through_poses


[ Next __ ](/turtlebot4-user-manual/tutorials/multiple_robots.html "Multiple
robots")


ros2 launch turtlebot4_navigation nav_bringup.launch.py slam:=off localization:=true map:=office.yaml


[ Troubleshooting ](/turtlebot4-user-manual/troubleshooting/)


` openai_api_key ` must be altered here or set on the command line at launch
time


Once the navigation has started, open another terminal and run:


####  Battery Monitoring Node


You can visualise the navigation process in Rviz. If Rviz wasn't already
launched, launch it by calling:


        selected_index = 0

    # Verify that the value input is a number
    try:
        selected_index = int(raw_input)
    except ValueError:
        navigator.error(f'Invalid goal selection: {raw_input}')
        continue

    # Verify that the user input is within a valid range
    if (selected_index < 0) or (selected_index >= len(goal_options)):
        navigator.error(f'Goal selection out of bounds: {selected_index}')


[ Software ](/turtlebot4-user-manual/software/)


[ Electrical ](/turtlebot4-user-manual/electrical/)


Let's take a look at the main function.


if (battery_percent is not None):


The terminal will display:


v1.0.0  __


Clearpath Robotics, by Rockwell Automation. All rights reserved. Revision [
d523bec ](https://github.com/turtlebot/turtlebot4-user-
manual/commit/d523beca255aff8f224fecd6f08075cf71673416
"d523beca255aff8f224fecd6f08075cf71673416")
__ Clearpath Robotics, Inc., a Rockwell Automation Company. All rights
reserved.


#####  OpenAI Interaction


  * galactic
  * humble


  * [ __ ](/turtlebot4-user-manual/ "/")
  * [ tutorials ](/turtlebot4-user-manual/tutorials/)
  * navigation.md


##  Install Tutorial Package


waypoint_follower:
  ros__parameters:
    use_sim_time: True
    loop_rate: 20
    stop_on_failure: false
    waypoint_task_executor_plugin: "wait_at_waypoint"
    wait_at_waypoint:
      plugin: "nav2_waypoint_follower::WaitAtWaypoint"
      enabled: True
      waypoint_pause_duration: 200


For example:


    if not navigator.getDockedStatus():
        navigator.info('Docking before initialising pose')
        navigator.dock()

    initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
    navigator.clearAllCostmaps()
    navigator.setInitialPose(initial_pose)

    navigator.waitUntilNav2Active()


    # Dock
    navigator.dock()
    # Undock
    navigator.undock()
    # Go to location 0.0, 1.0, facing North
    navigator.info('Moving to 0.0, 1.0, North')
    goal = navigator.getPoseStamped([0.0, 1.0], TurtleBot4Directions.NORTH)
    navigator.startToPose(goal)
    # Move to location -1.0, 5.0, facing South East
    navigator.info('Moving to -1.0, 5.0, South East')
    goal = navigator.getPoseStamped([-1.0, 5.0], TurtleBot4Directions.SOUTH_EAST)
    navigator.startToPose(goal)
    # Navigate to shelf
    dest = destinations['metal shelf']
    navigator.info('Moving to metal shelf')
    goal = navigator.getPoseStamped(dest[0:2], dest[2])
    navigator.startToPose(goal)
    # Navigate to wooden object
    dest = destinations['wooden crate']
    navigator.info('Moving to wooden crate')
    goal = navigator.getPoseStamped(dest[0:2], dest[2])
    navigator.startToPose(goal)
    # Go to forklift
    dest = destinations['forklift']
    navigator.info('Moving to forklift')
    goal = navigator.getPoseStamped(dest[0:2], dest[2])
    navigator.startToPose(goal)


[ Changelogs ](/turtlebot4-user-manual/changelogs/)


        # Create a list of the goals for display
    options_str = 'Please enter the number corresponding to the desired robot goal position:\n'
    for i in range(len(goal_options)):
        options_str += f'    {i}. {goal_options[i]["name"]}\n'

    # Prompt the user for the goal location
    raw_input = input(f'{options_str}Selection: ')


        # Prepare goal poses
    goal_pose = []
    goal_pose.append(navigator.getPoseStamped([-5.0, 1.0], TurtleBot4Directions.EAST))
    goal_pose.append(navigator.getPoseStamped([-5.0, -23.0], TurtleBot4Directions.NORTH))
    goal_pose.append(navigator.getPoseStamped([9.0, -23.0], TurtleBot4Directions.NORTH_WEST))
    goal_pose.append(navigator.getPoseStamped([10.0, 2.0], TurtleBot4Directions.WEST))


We finish the example by docking the robot. This assumes that the last pose in
the created path is near the dock. If it is not, you can remove this action.


####  Undock the robot and go to the goal pose


ros2 launch turtlebot4_ignition_bringup turtlebot4_ignition.launch.py nav2:=true slam:=false localization:=true rviz:=true


Whenever a ` battery_state ` message is received, the battery charge
percentage is saved in a member variable.


Resources: Website Wiki


####  Create your path


If using multiple robots through the namespacing method, an additional `
namespace ` parameter must be passed. For example: ` namespace:=/robot1 ` See
[ Multiple robots ](/turtlebot4-user-manual/tutorials/multiple_robots.html)
for more details.


To launch a different supported world, see the [ simulation package
](/turtlebot4-user-manual/software/turtlebot4_simulator.html#ignition-bringup)
for a list of supported worlds. You must pass the name of the chosen world and
the path to the map file.


A thread is created to run the battery monitor thread function that was
created earlier. This thread is started.


For more information on ROS please visit www.ros.org | Find us on Google+


Answers.ros.org Recent Questions Tagged: `turtlebot4`
Browse recent questions or see the higest voted


###  Code breakdown


###  Localization


The Nav2 Goal tool allows you to set a goal pose for the robot. The Nav2 stack
will then plan a path to the goal pose and attempt to drive the robot there.
Make sure to set the initial pose of the robot before you set a goal pose.


#####  Prepare Goal Pose Loop


To run this example, start the Ignition Gazebo simulation:


###  Watch Navigation Progress in RViz


Next, we check if the robot is docked. If it is not, we send an action goal to
dock the robot. By docking the robot we guarantee that it is at the [0.0, 0.0]
coordinates on the map.


##  Follow Waypoints


####  Dock the robot


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_python_tutorials/turtlebot4_python_tutorials/follow_waypoints.py) .


Recent questions preview:
Question: Rviz doesn't show the correct tf2 tree
Asked on: Thu, 10 Aug 2023 04:24:26 -0500
I'm trying to setup rtabmap algorithm for a project I'm working on. I currently have rgb camera, depth camera, tf, tf_static and robot_description recorded in a ros2 bag file (At rate 0.5, in case it matters). I'm launching rtabmap_odom and rtabmap_slam nodes in a custom launch file. This makes the odom and map tf transforms, and connects them to base_link, which is the parent of all other transforms. Recorded with: "ros2 run tf2_tools view_frames --ros-args -r __ns:=/turtle_1 -r /tf:=tf -r /tf_static:=tf_static": ![image description](/upfiles/16916587485259604.png) *Note: However, if I record tf2 frames without remapping "/tf" to "tf", I get the same graph, without map and odom on it. Why is that?* For some reason, these transforms are not seen in Rviz2. When setting the fixed frame to "map", the rtabmap point cloud is being broadcasted, but there are a lot of errors in the "tf" tab: ![image description](/upfiles/1691658976385623.png) And, if we check the "Tree", only map and odom are seen. ![image description](/upfiles/16916593111825799.png) If I set the fixed frame from map to base_link in Rviz, there is no point cloud visible and no odom/map transform. EDIT: If I set the fixed frame to "odom" there is a transform from odom to base_link (Still no point cloud map though). But why can't it then be found from map? Thanks for your help!
Question: How to get Pointcloud data in Turtlebot 4?
Asked on: Mon, 10 Apr 2023 17:50:14 -0500
I am working with a Turtlebot 4 (that has Ubuntu 20.04 and ROS2 Galactic). I want to visualize pointcloud data in Rviz. After launching Rviz, I added pointcloud and pointcloud2 from Add option. But it shows an error "no topic to subscribe". Anyone knows in which topic pointcloud data is published? Or how do I access pointcloud data?
Question: cmd_vel being published but Turtlebot 4 is not moving. Any inputs is appreciated.
Asked on: Thu, 30 Mar 2023 22:50:42 -0500
Hi, I have set up my turtle bot 4 to my wifi. I have changed the .yaml file in the netplan and I am able to ssh into the turtle bot via my wifi. I checked and could see that the create 3 is also visible in my wifi connections. But when I try to move the robot using the keyboard tele op commands, the robot is not moving. the commands I used was: ros2 run teleop_twist_keyboard teleop_twist_keyboard. I could see that cmd_vel is being published when I list ros2 topics but the robot is not moving. Any inputs as to why it is not moving is highly appreciated.
Question: Navigation goals not working with laser, sonar and slam_toolbox
Asked on: Tue, 31 Jan 2023 14:19:31 -0600
Hi there, my platform is an "almost turtlebot4": we have a create3 platform with a lidar and an array of 7 ultrasound sensors. For navigating we use the turtlebot4 stack (Ros-Galactic). More specifically we can ***CONFIG1***. build a map with slam toolbox launching the following configuration: ros2 launch turtlebot4_navigation nav_bringup.launch.py slam:=async  base_frame:=base_link params_file:=my_robot.yaml ***CONFIG2***. correctly (and by that I mean navigating using both laser and sonar) navigate the built map (previously obtained by CONFIG1) with the following command: ros2 launch turtlebot4_navigation nav_bringup.launch.py slam:=off localization:=true  base_frame:=base_link map:=$PWD/the_map_create_at_point1.yaml params_file:=my_robot.yaml ***CONFIG3***: temporarily obtain the desired behavior until a pose estimate is issued by RVIZ2 ros2 launch turtlebot4_navigation nav_bringup.launch.py slam:=synclocalization:=true  base_frame:=base_link map:=$PWD/the_map_create_at_point1.yaml params_file:=my_robot.yaml However, when using ***CONFIG1*** (with the slam parameter either set to *async* or *sync*) I can not launch navigation goals. The controller server ĺog shows the following (notice that the tf clearly states the relation between the following frames and it is the same in all configs): ***LOG_ERROR:*** "Range sensor layer can't transform from odom to sonarX_frame", where X=[1,7] In ***CONFIG2*** there are no problems in launching navigation goals (but obviously we have the drawback of not building a map). Interestingly if I mix slam and localization (configuration ***CONFIG3***)  I can see the robot building a map and accepting navigation goals. This works until I set pose by the RVIZ2 interface (at that moment, if I get it right, amcl and slam_toolbox will concurrently update the robot position and hence the flickering..). Notice that with ***CONFIG1***, the goal navigation can be issued if I remove the sonar layer. Looking a ***LOG_ERROR*** above, is it a problem of slam toolbox not handling other sensors than laser scanner  or most likely I did not understand which configuration would give me the 3 features right below I am looking for? - ***F1.*** build a map - ***F2.*** issue navigation goals - ***F3.*** navigate taking into account scan and sonar readings (in terms of planning / obstacle avoidance) You find attached the robot configuration file where I have added the sonar layer, here below a "summary" of the config - ***CONFIG1:*** it builds the map in any case BUT navigation goals work only if I remove the "sonar_layer" from my_robot_config.yaml. - ***CONFIG2:*** it allows the robot to navigate taking into account both laser and sonar readings - ***CONFIG3:*** it gives me ***F1+F2+F3*** till I set a robot pose in RVIZ, at that point the robot position estimates start to flicker (probably due to concurrent update). Thanks File: my_robot_config.yaml ( I am reporting only the part with the sonar layer as copying the entire file does not work in terms for formatting) local_costmap: local_costmap: ros__parameters: update_frequency: 5.0 publish_frequency: 2.0 global_frame: odom robot_base_frame: base_link use_sim_time: True rolling_window: true width: 3 height: 3 resolution: 0.05 robot_radius: 0.22 plugins: ["obstacle_layer", "sonar_layer", "inflation_layer" ] inflation_layer: plugin: "nav2_costmap_2d::InflationLayer" cost_scaling_factor: 3.0 inflation_radius: 0.1 obstacle_layer: plugin: "nav2_costmap_2d::ObstacleLayer" enabled: True observation_sources: scan scan: topic: /scan max_obstacle_height: 2.0 clearing: False marking: True data_type: "LaserScan" raytrace_max_range: 3.0 raytrace_min_range: 0.0 obstacle_max_range: 2.5 obstacle_min_range: 0.0 sonar_layer: frame: sonar_frame plugin: "nav2_costmap_2d::RangeSensorLayer" topics: ["/sonar0", "/sonar1", "/sonar2", "/sonar3", "/sonar4", "/sonar5", "/sonar6"] enabled: True no_readings_timeout: 2.0 clear_on_max_reading: true clear_threshold: 0.2 mark_threshold: 0.80 static_layer: map_subscribe_transient_local: True always_send_full_costmap: True local_costmap_client: ros__parameters: use_sim_time: True local_costmap_rclcpp_node: ros__parameters: use_sim_time: True global_costmap: global_costmap: ros__parameters: update_frequency: 1.0 publish_frequency: 1.0 global_frame: map robot_base_frame: base_link use_sim_time: True robot_radius: 0.22 resolution: 0.05 track_unknown_space: true plugins: ["static_layer", "obstacle_layer", "sonar_layer", "inflation_layer"] obstacle_layer: plugin: "nav2_costmap_2d::ObstacleLayer" enabled: True observation_sources: scan scan: topic: /scan max_obstacle_height: 2.0 clearing: True marking: True data_type: "LaserScan" raytrace_max_range: 3.0 raytrace_min_range: 0.0 obstacle_max_range: 2.5 obstacle_min_range: 0.0 sonar_layer: frame: sonar_frame plugin: "nav2_costmap_2d::RangeSensorLayer" topics: ["/sonar0", "/sonar1", "/sonar2", "/sonar3", "/sonar4", "/sonar5", "/sonar6"] enabled: True no_readings_timeout: 2.0 clear_on_max_reading: true clear_threshold: 0.2 mark_threshold: 0.80 static_layer: plugin: "nav2_costmap_2d::StaticLayer" map_subscribe_transient_local: True inflation_layer: plugin: "nav2_costmap_2d::InflationLayer" cost_scaling_factor: 3.0 inflation_radius: 0.1 always_send_full_costmap: True global_costmap_client: ros__parameters: use_sim_time: True global_costmap_rclcpp_node: ros__parameters: use_sim_time: True ` `![image description](/upfiles/16752045354560875.png)
Question: [ROS2] Namespace on Navigation2 does not prefix frames
Asked on: Mon, 14 Nov 2022 10:55:57 -0600
Ubuntu 20.04 ROS2 Galactic I'm trying to have multiple Turtlebot4 in the same Gazebo(Ignition) simulation with namespaces. I'm able to spawn them correctly next to each other with basic commands working (tele-operation, docking/undocking, ..) but the navigation stack does not behave correctly. My project so far: https://github.com/sp-sophia-labs/turtlebot4_multi_sim My question is related to how namespaces work in navigation2. Based on the code, navigation2 is using a combination of `pushROSNamespace` and `GroupAction` to propagate namespaces to all nodes in the launch file and it works well for topics and node names. Frames on the other hand are not prefixed at all. The way it behaves on my side is that properly prefixed nodes and topics messages are referring to `map`, `base_link` and `odom` frames which do not exist because they are prefixed At first, I thought that it was intended and should be fixed by a correct configuration file. Although static configuration for a specific namespace seems to work, I'm not able to allow any namespace. I've tried adding wildcard namespaces to the turtlebot4 config file to force the namespaces prefixing on the frames, but they are not taken into account and the param file is not read properly. original config file: https://github.com/sp-sophia-labs/turtlebot4/blob/galactic/turtlebot4_navigation/config/nav2.yaml Am I missing something or is it a missing functionality from navigation2?
Question: [ROS2] How can I find out which host is running a node?
Asked on: Sat, 12 Nov 2022 10:54:31 -0600
ros2 node list will show all the nodes running on my network, but **how can I find out which nodes are running on which hosts, or where a particular node is running?** Application: For a TurtleBot 4 Lite running ROS2 Galactic, there are nodes running on the Create3 base, and more nodes running on the Raspberry Pi4 inside the accessory tray, and I have my desktop ROS2 environment running rviz and rqt-image-view. I would like to be able to determine what is running where.
Question: how to publish map in ros2 galactic?
Asked on: Tue, 06 Sep 2022 16:08:44 -0500
Hi I installed ros galactic on ubuntu 20.04 using this bash script (https://github.com/turtlebot/TurtleBot4Lessons/tree/main/installation), then I ran turtlebot4 simulation in depot and map its surrounding. I saved the map with ** ros2 service call /slam_toolbox/save_map slam_toolbox/srv/SaveMap "name: data: 'map_name' ** then when I want to publish the map, and use ros2 run nav2_map_server map_server $PWD/map_name.yaml I get stuck with the following log [INFO] [1662497993.651852411] [map_server]: map_server lifecycle node launched. Waiting on external lifecycle transitions to activate See https://design.ros2.org/articles/node_lifecycle.html for more information. [INFO] [1662497993.651943245] [map_server]: Creating here is the available service list: ros2 service list /map_server/change_state /map_server/describe_parameters /map_server/get_available_states /map_server/get_available_transitions /map_server/get_parameter_types /map_server/get_parameters /map_server/get_state /map_server/get_transition_graph /map_server/list_parameters /map_server/set_parameters /map_server/set_parameters_atomically and here is the result of node list ros2 node list /map_server Am I doing something wrong? should I add any other node to this?
Question: Turtlebot4 Ignition Gazebo Simulation
Asked on: Sun, 07 Aug 2022 14:51:55 -0500
Hello Guys. Clearpath Tutorials say that in order to simulate the TT4 using Gazebo Ignition, we need to have Ubuntu 20.04 and ROS2 Galactic installed. I have Humble installed on Jammy. Is there a way to get the simulation up and running, maybe using the source code, performing some tweaks, ... ? I would love to simulate the robot and learn ROS2 with it, but I wouldn't like to reinstall Ubuntu and ROS2 again. Thanks.
Question: Turtlebot4 using ROS2 Humble
Asked on: Wed, 06 Jul 2022 08:00:12 -0500
Is it possible to run Turtlebot4 using ROS2 Humble? I found that it is made for galactic and foxy, I updated Ubuntu to 22.04 and wanted to start using ROS2 Humble Hawksbill. However I found the following code made for Galactic or foxy: - https://github.com/turtlebot/turtlebot4 - https://github.com/iRobotEducation/create3_sim.git Does anyone knows if it will be in ROS2 Humble soon? Or is it any package to start testing Turtlebot4 with ROS2 Humble Thank you in advance.
Question: Run turtlebot4 simulator but got problem of lacking diffdrive_controller and joint_state_broadcaster
Asked on: Wed, 25 May 2022 04:30:11 -0500
I follow the [tutorial](https://turtlebot.github.io/turtlebot4-user-manual/software/simulation.html) to run turtlebot4 simulator but failed. There is error info. I have checked if I haved installed joint_state_broadcaster and diffdrive_controller. The result is that joint_state_broadcaster is installed already, but I am not sure diffdrive_controller package is also installed. Can you help me figure this out. If you need some more detailed info, please tell me. The cmd I run is : ```bash ros2 launch turtlebot4_ignition_bringup ignition.launch.py ``` [spawner-20] Traceback (most recent call last): [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/rosidl_generator_py/import_type_support_impl.py", line 46, in import_type_support [spawner-20] return importlib.import_module(module_name, package=pkg_name) [spawner-20] File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module [spawner-20] return _bootstrap._gcd_import(name[level:], package, level) [spawner-20] File "", line 1014, in _gcd_import [spawner-20] File "", line 991, in _find_and_load [spawner-20] File "", line 975, in _find_and_load_unlocked [spawner-20] File "", line 657, in _load_unlocked [spawner-20] File "", line 556, in module_from_spec [spawner-20] File "", line 1166, in create_module [spawner-20] File "", line 219, in _call_with_frames_removed [spawner-20] ImportError: /opt/ros/galactic/lib/libcontroller_manager_msgs__rosidl_generator_c.so: undefined symbol: builtin_interfaces__msg__Duration__are_equal [spawner-20] [spawner-20] During handling of the above exception, another exception occurred: [spawner-20] [spawner-20] Traceback (most recent call last): [spawner-20] File "/opt/ros/galactic/lib/controller_manager/spawner", line 20, in [spawner-20] ret = main() [spawner-20] File "/opt/ros/galactic/lib/controller_manager/spawner.py", line 167, in main [spawner-20] if is_controller_loaded(node, controller_manager_name, controller_name): [spawner-20] File "/opt/ros/galactic/lib/controller_manager/spawner.py", line 110, in is_controller_loaded [spawner-20] controllers = list_controllers(node, controller_manager).controller [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/controller_manager/controller_manager_services.py", line 49, in list_controllers [spawner-20] return service_caller(node, f'{controller_manager_name}/list_controllers', [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/controller_manager/controller_manager_services.py", line 23, in service_caller [spawner-20] cli = node.create_client(service_type, service_name) [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/node.py", line 1407, in create_client [spawner-20] check_is_valid_srv_type(srv_type) [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/type_support.py", line 51, in check_is_valid_srv_type [spawner-20] check_for_type_support(srv_type) [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/type_support.py", line 29, in check_for_type_support [spawner-20] msg_or_srv_type.__class__.__import_type_support__() [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/controller_manager_msgs/srv/_list_controllers.py", line 250, in __import_type_support__ [spawner-20] module = import_type_support('controller_manager_msgs') [spawner-20] File "/opt/ros/galactic/lib/python3.8/site-packages/rosidl_generator_py/import_type_support_impl.py", line 48, in import_type_support [spawner-20] raise UnsupportedTypeSupport(pkg_name) [spawner-20] rosidl_generator_py.import_type_support_impl.UnsupportedTypeSupport: Could not import 'rosidl_typesupport_c' for package 'controller_manager_msgs' [ign gazebo-1] [WARN 2022-5-25 10:42:44.975936140] [ignition_ros_control]: Desired controller update period (0.001 s) is slower than the gazebo simulation period (0 s). (PreUpdate() at /tmp/binarydeb/ros-galactic-ign-ros2-control-0.4.0/src/ign_ros2_control_plugin.cpp:445) [ERROR] [spawner-20]: process has died [pid 7532, exit code 1, cmd '/opt/ros/galactic/lib/controller_manager/spawner joint_state_broadcaster -c /controller_manager --ros-args']. [INFO] [spawner-37]: process started with pid [8086] [spawner-37] Traceback (most recent call last): [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/rosidl_generator_py/import_type_support_impl.py", line 46, in import_type_support [spawner-37] return importlib.import_module(module_name, package=pkg_name) [spawner-37] File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module [spawner-37] return _bootstrap._gcd_import(name[level:], package, level) [spawner-37] File "", line 1014, in _gcd_import [spawner-37] File "", line 991, in _find_and_load [spawner-37] File "", line 975, in _find_and_load_unlocked [spawner-37] File "", line 657, in _load_unlocked [spawner-37] File "", line 556, in module_from_spec [spawner-37] File "", line 1166, in create_module [spawner-37] File "", line 219, in _call_with_frames_removed [spawner-37] ImportError: /opt/ros/galactic/lib/libcontroller_manager_msgs__rosidl_generator_c.so: undefined symbol: builtin_interfaces__msg__Duration__are_equal [spawner-37] [spawner-37] During handling of the above exception, another exception occurred: [spawner-37] [spawner-37] Traceback (most recent call last): [spawner-37] File "/opt/ros/galactic/lib/controller_manager/spawner", line 20, in [spawner-37] ret = main() [spawner-37] File "/opt/ros/galactic/lib/controller_manager/spawner.py", line 167, in main [spawner-37] if is_controller_loaded(node, controller_manager_name, controller_name): [spawner-37] File "/opt/ros/galactic/lib/controller_manager/spawner.py", line 110, in is_controller_loaded [spawner-37] controllers = list_controllers(node, controller_manager).controller [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/controller_manager/controller_manager_services.py", line 49, in list_controllers [spawner-37] return service_caller(node, f'{controller_manager_name}/list_controllers', [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/controller_manager/controller_manager_services.py", line 23, in service_caller [spawner-37] cli = node.create_client(service_type, service_name) [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/node.py", line 1407, in create_client [spawner-37] check_is_valid_srv_type(srv_type) [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/type_support.py", line 51, in check_is_valid_srv_type [spawner-37] check_for_type_support(srv_type) [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/type_support.py", line 29, in check_for_type_support [spawner-37] msg_or_srv_type.__class__.__import_type_support__() [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/controller_manager_msgs/srv/_list_controllers.py", line 250, in __import_type_support__ [spawner-37] module = import_type_support('controller_manager_msgs') [spawner-37] File "/opt/ros/galactic/lib/python3.8/site-packages/rosidl_generator_py/import_type_support_impl.py", line 48, in import_type_support [spawner-37] raise UnsupportedTypeSupport(pkg_name) [spawner-37] rosidl_generator_py.import_type_support_impl.UnsupportedTypeSupport: Could not import 'rosidl_typesupport_c' for package 'controller_manager_msgs' [ERROR] [spawner-37]: process has died [pid 8086, exit code 1, cmd '/opt/ros/galactic/lib/controller_manager/spawner diffdrive_controller -c /controller_manager --ros-args --params-file /workspaces/turtlebot4_ws/install/share/irobot_create_control/config/control.yaml']. By the way, I wonder how to download the model which is used in the [sdf file](https://github.com/turtlebot/turtlebot4_simulator/blob/galactic/turtlebot4_ignition_bringup/worlds/depot.sdf). false 0.002 1.0 https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Depot Because the network is not good in my place. I have to download it at first. But I don't kown how to do that. Maybe you can tell me.
Share

Contribute on GitHub .


Tags: diff-drive education galactic ground hydro indoor mobile base research rolling ros2


  * [ 1\. Create® 3 ](/turtlebot4-user-manual/electrical/create3.html)
  * [ 2\. Raspberry Pi 4B ](/turtlebot4-user-manual/electrical/rpi4.html)
  * [ 3\. User Interface PCBA ](/turtlebot4-user-manual/electrical/pcba.html)
  * [ 4\. Power Budget ](/turtlebot4-user-manual/electrical/power_budget.html)


  * ![Nav through pose](media/nav_through_pose_rviz.gif) Navigate through a set of poses
  * Your browser does not support the video tag.  Navigate through a set of poses


ros2 launch turtlebot4_ignition_bringup ignition.launch.py nav2:=true slam:=off localization:=true


This example starts the same as  navigate to pose  . We initialise the node,
make sure the robot is docked, and set the initial pose. Then we wait for Nav2
to become active.


Search...
MENU
Home
All
Tags
About
Contributing
Feed
CATEGORIES
Aerial
Component
Ground
Manipulator
Marine
TurtleBot4
Robot Category: ground


Replace ` office.yaml ` with the path to your own map.


If you are using the physical robot: In a new terminal launch Rviz so that you
can view the map and interact with navigation:


#####  Multi-threading


Once the simulation has started, open another terminal and run:


ros2 launch turtlebot4_ignition_bringup ignition.launch.py nav:=true slam:=off localization:=true


     [ __ Source ](https://github.com/turtlebot/turtlebot4-user-manual "Stars: 3")
     [ __ Issues ](https://github.com/turtlebot/turtlebot4-user-manual/issues "Open issues: 2")
     [ __ Download ](https://github.com/turtlebot/turtlebot4-user-manual/zipball/gh-pages "Size: 250111 Kb")


###  Watch navigation progress in Rviz


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_python_tutorials/turtlebot4_python_tutorials/patrol_loop.py) .


  *     goal_pose = []
    goal_pose.append(navigator.getPoseStamped([-3.0, -0.0], TurtleBot4Directions.EAST))
    goal_pose.append(navigator.getPoseStamped([-3.0, -3.0], TurtleBot4Directions.NORTH))
    goal_pose.append(navigator.getPoseStamped([3.0, -3.0], TurtleBot4Directions.NORTH_WEST))
    goal_pose.append(navigator.getPoseStamped([9.0, -1.0], TurtleBot4Directions.WEST))
    goal_pose.append(navigator.getPoseStamped([9.0, 1.0], TurtleBot4Directions.SOUTH))
    goal_pose.append(navigator.getPoseStamped([-1.0, 1.0], TurtleBot4Directions.EAST))


This file reads in a set of example prompts found in a text file in a ‘ROS
2-friendly' way. Aside from the call to ` ament_index_python ` , it's quite
standard Python.


###  Code breakdown


[ User Manual ](/turtlebot4-user-manual/)


Replace ` office.yaml ` with your own map.


  1. Create an [ OpenAI account ](https://platform.openai.com/signup?launch) and [ API key ](https://platform.openai.com/account/api-keys) . Be sure to copy your API key to a safe place, it cannot be retrieved after creation!
  2. Verify that your OpenAI account has [ some credit ](https://platform.openai.com/account/usage) . A few cents are all that's required for initial testing
  3. Install the OpenAI Python library via ` pip install openai `
  4. If you do not already have a workspace, open a terminal and create one ` mkdir ~/turtlebot4_ws/src -p `
  5. Download or clone [ the code ](https://github.com/turtlebot/turtlebot4_tutorials) into your workspace.
  6. Run colcon build in your workspace ` cd ~/turtlebot4_ws/ && colcon build `


  * [ 1\. Basic Setup ](/turtlebot4-user-manual/setup/basic.html)
  * [ 2\. Networking ](/turtlebot4-user-manual/setup/networking.html)
  * [ 3\. Simple Discovery ](/turtlebot4-user-manual/setup/simple_discovery.html)
  * [ 4\. Discovery Server ](/turtlebot4-user-manual/setup/discovery_server.html)


#####  Prompt File Input


![Mail Delivery Terminal](media/mail_delivery_terminal.png) Mail Delivery
Terminal Prompt


After initialisation, the user is prompted to create their path by using the [
2D Pose Estimate ](/turtlebot4-user-manual/tutorials/navigation.html#2d-pose-
estimate) tool. You must set at least one pose. Once all of the poses have
been set, the robot will begin navigating.


The 2D Pose Estimate tool is used in localization to set the approximate
initial pose of the robot on the map. This is required for the Nav2 stack to
know where to start localizing from. Click on the tool, and then click and
drag the arrow on the map to approximate the position and orientation of the
robot.


[ __ User Manual ](/turtlebot4-user-manual/ "Turtlebot4 User Manual")


####  Set the goal pose


  * galactic
  * humble


##  Mail Delivery


##  Nav2


    def read_prompt_file(prompt_file):
        """Read in a specified file which is located in the package 'prompts' directory."""
        data_path = ament_index_python.get_package_share_directory('turtlebot4_openai_tutorials')
        prompt_path = os.path.join(data_path, 'prompts', prompt_file)

        with open(prompt_path, 'r') as file:
            return file.read()


    def query(self, base_prompt, query, stop_tokens=None, query_kwargs=None, log=True):
        new_prompt = f'{base_prompt}\n{query}'
        """ Query OpenAI API with a prompt and query """

        use_query_kwargs = {
            'model': self.model_name,
            'max_tokens': 512,
            'temperature': 0,
        }
        if query_kwargs is not None:
            use_query_kwargs.update(query_kwargs)

        messages = [
            {"role": "user", "content": new_prompt}
        ]
        response = openai.ChatCompletion.create(
            messages=messages, stop=stop_tokens, **use_query_kwargs
        )['choices'][0]['message']['content'].strip()

        if log:
            self.info(query)
            self.info(response)

        return response


**If you are using the simulator, call:**


###  Watch navigation progress in Rviz


[ Changelogs ](/turtlebot4-user-manual/changelogs/)


    def main():
        rclpy.init()

        navigator = TurtleBot4Navigator()
        gpt = GPTNode(navigator)

        gpt.prompts.append(read_prompt_file('turtlebot4_api.txt'))
        for p in gpt.prompts:
            gpt.full_prompt = gpt.full_prompt + '\n' + p

        # No need to talk to robot if we're not executing
        if not gpt.get_parameter('parking_brake').value:
            gpt.warn("Parking brake not set, robot will execute commands!")
            # Start on dock
            if not navigator.getDockedStatus():
                navigator.info('Docking before initialising pose')
                navigator.dock()

            # Set initial pose
            initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
            navigator.setInitialPose(initial_pose)

            # Wait for Nav2
            navigator.waitUntilNav2Active()

            # Undock
            navigator.undock()
        else:
            gpt.warn("Parking brake set, robot will not execute commands!")


[ Tutorials ](/turtlebot4-user-manual/tutorials/)


    initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
    navigator.setInitialPose(initial_pose)


####  Publish Point


* The source code for this example is available [ here ](https://github.com/turtlebot/turtlebot4_tutorials/blob/galactic/turtlebot4_python_tutorials/turtlebot4_python_tutorials/create_path.py) .


  * ![Nav to pose](media/nav_to_pose_rviz.gif) Navigate to a pose
  * Your browser does not support the video tag.  Navigate to a pose (3x speed)


Once the robot is undocked (or, immediately, if the ‘parking brake' is not
set), open a third terminal and run:


You can optionally also open a _fourth_ terminal to monitor if the system is
ready for new input.


####  Set goal poses


    dest = destinations['metal shelf']
    navigator.info('Moving to metal shelf')
    goal = navigator.getPoseStamped(dest[0:2], dest[2])


The TurtleBot 4 was created in a partnership between Open Robotics and Clearpath Robotics.


Source located [ here
](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_openai_tutorials/launch/natural_language_nav_launch.py)
.


[ Next __ ](/turtlebot4-user-manual/tutorials/turtlebot4_navigator.html
"TurtleBot 4 Navigator")


        def main():
        rclpy.init()

        navigator = TurtleBot4Navigator()

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Set goal poses
        goal_pose = []
        goal_pose.append(navigator.getPoseStamped([-3.0, -0.0], TurtleBot4Directions.EAST))
        goal_pose.append(navigator.getPoseStamped([-3.0, -3.0], TurtleBot4Directions.NORTH))
        goal_pose.append(navigator.getPoseStamped([3.0, -3.0], TurtleBot4Directions.NORTH_WEST))
        goal_pose.append(navigator.getPoseStamped([9.0, -1.0], TurtleBot4Directions.WEST))
        goal_pose.append(navigator.getPoseStamped([9.0, 1.0], TurtleBot4Directions.SOUTH))
        goal_pose.append(navigator.getPoseStamped([-1.0, 1.0], TurtleBot4Directions.EAST))

        # Undock
        navigator.undock()

        # Navigate through poses
        navigator.startThroughPoses(goal_pose)

        # Finished navigating, dock
        navigator.dock()

        rclpy.shutdown()


  * [ 1\. Overview ](/turtlebot4-user-manual/software/overview.html)
  * [ 2\. TurtleBot 4 Common ](/turtlebot4-user-manual/software/turtlebot4_common.html)
  * [ 3\. TurtleBot 4 Robot ](/turtlebot4-user-manual/software/turtlebot4_robot.html)
  * [ 4\. TurtleBot 4 Simulator ](/turtlebot4-user-manual/software/turtlebot4_simulator.html)
  * [ 5\. TurtleBot 4 Desktop ](/turtlebot4-user-manual/software/turtlebot4_desktop.html)
  * [ 6\. TurtleBot 4 Setup ](/turtlebot4-user-manual/software/turtlebot4_setup.html)
  * [ 7\. Create® 3 ](/turtlebot4-user-manual/software/create3.html)
  * [ 8\. Sensors ](/turtlebot4-user-manual/software/sensors.html)
  * [ 9\. Rviz2 ](/turtlebot4-user-manual/software/rviz.html)
  * [ 10\. Simulation ](/turtlebot4-user-manual/software/simulation.html)


A Global Interpreter Lock (GIL) is used to ensure that the main function and
battery monitoring functions do not access or modify that member variable at
the same time. The process will queue until the lock is available.


Let's take a look at the new node in this example, found [ here
](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_openai_tutorials/turtlebot4_openai_tutorials/natural_language_nav.py)


###  Watch navigation progress in Rviz


Let's take a look at the battery monitoring node class.


#####  Prepare Threading


__ TurtleBot 4 User Manual


[ Software ](/turtlebot4-user-manual/software/)


###  Code breakdown


#####  Subscription


GitHub


A list of goals is compiled and displayed on the terminal as a prompt and the
program will wait for input from the user.


    def main():
        rclpy.init()

        navigator = TurtleBot4Navigator()

        # Start on dock
        if not navigator.getDockedStatus():
            navigator.info('Docking before initialising pose')
            navigator.dock()

        # Set initial pose
        initial_pose = navigator.getPoseStamped([0.0, 0.0], TurtleBot4Directions.NORTH)
        navigator.setInitialPose(initial_pose)

        # Wait for Nav2
        navigator.waitUntilNav2Active()

        # Set goal poses
        goal_pose = []
        goal_pose.append(navigator.getPoseStamped([-3.3, 5.9], TurtleBot4Directions.NORTH))
        goal_pose.append(navigator.getPoseStamped([2.1, 6.3], TurtleBot4Directions.EAST))
        goal_pose.append(navigator.getPoseStamped([2.0, 1.0], TurtleBot4Directions.SOUTH))
        goal_pose.append(navigator.getPoseStamped([-1.0, 0.0], TurtleBot4Directions.NORTH))

        # Undock
        navigator.undock()

        # Follow Waypoints
        navigator.startFollowWaypoints(goal_pose)

        # Finished navigating, dock
        navigator.dock()

        rclpy.shutdown()


A prompt file or files as found [ here
](https://github.com/turtlebot/turtlebot4_tutorials/blob/humble/turtlebot4_openai_tutorials/prompts/turtlebot4_api.txt)
are also required. This file contains a handful of examples of ‘proper' API
use, where each set of API calls or commands to be executed is preceded by a
representative prompt.


The TurtleBot 4 uses the [ Nav2 ](https://navigation.ros.org/) stack for
navigation.


####  Prompt File


planner_server:
  ros__parameters:
    expected_planner_frequency: 20.0
    use_sim_time: True
    planner_plugins: ["GridBased"]
    GridBased:
      plugin: "nav2_navfn_planner/NavfnPlanner"
      tolerance: 0.5
      use_astar: false
      allow_unknown: true


Then, in another terminal, launch [ nav2
](https://github.com/turtlebot/turtlebot4/blob/humble/turtlebot4_navigation/launch/nav2.launch.py)
:


    $ ros2 component unload /ComponentManager 1 2
    Unloaded component 1 from '/ComponentManager' container
    Unloaded component 2 from '/ComponentManager' container


Sorry, something went wrong.


Options


[ ![@dirk-
thomas](https://avatars.githubusercontent.com/u/1335366?s=40&u=ec35ea6bae7c6e04a5df7482044bbc7681968435&v=4)
](/dirk-thomas) [ dirk-thomas ](/dirk-thomas) changed the title ~~rclpy
compisition API~~ rclpy composition API  Jun 16, 2020


Referring to the implementation of rclcpp_component, which introduces several
cmake macros in the CMakeList.txt, similarly, the python version just need to
make some command override in the ` setup.py ` file. I tried this:


See the [ conceptual article  ](../Concepts/About-Composition.html) .


Contributor  Author


* Background


To see all available qualifiers, see our [ documentation
](https://docs.github.com/search-github/github-code-search/understanding-
github-code-search-syntax) .


**[ crystaldust ](/crystaldust) ** commented  Jun 23, 2020


**[ dirk-thomas ](/dirk-thomas) ** commented  Jun 24, 2020


By Solution


**[ crystaldust ](/crystaldust) ** commented  Jul 1, 2020  •


  * [ Code  ](/ros2/rclpy)
  * [ Issues  ](/ros2/rclpy/issues)
  * [ Pull requests  ](/ros2/rclpy/pulls)
  * [ Actions  ](/ros2/rclpy/actions)
  * [ Security  ](/ros2/rclpy/security)
  * [ Insights  ](/ros2/rclpy/pulse)


However, if we require developers to maintain the files in ` data_files ` ,
according to [ the design of package resource indexer
](https://github.com/ament/ament_cmake/blob/master/ament_cmake_core/doc/resource_index.md#file-
system-index-layout) , and the component mechanism, we will need two files at
the locations:


To see what components are registered and available in the workspace, execute
the following in a shell:


Manually-composed components will not be reflected in the ` ros2  component
list  ` command line tool output.


Copy link


We use _composable_node_descriptions_ in a launch file to specify the
components that should be started as part of a launch. In this example, the
list includes two components: one for a component called ` CameraComponent `
and one for a component called ` DisplayComponent ` . Both of these components
are located in the ` img_pipeline_composition ` package, and they are
implemented as plugins (shared libraries that are loaded at runtime).


edited


Assignees


For information on Composable Storefront and what versions are current,
including which Commerce Cloud backends are supported, see the [ Update
Release Policy and Publication Frequency for Composable Storefront Libraries
](https://help.sap.com/docs/SAP_COMMERCE_COMPOSABLE_STOREFRONT/6c7b98dbe68f4a508cac17a207182f4c/ba62c2c708ec4751a2612a512177419b.html)
. For more information on which Composable Storefront updates work with which
versions of Node.js and Angular, see the [ Composable Storefront Dependencies
Matrix
](https://help.sap.com/docs/SAP_COMMERCE_COMPOSABLE_STOREFRONT/6c7b98dbe68f4a508cac17a207182f4c/0ec25f325c9541be86fbf85d8a45c041.html)
.


The demos use executables from [ rclcpp_components
](https://github.com/ros2/rclcpp/tree/master/rclcpp_components) , [
ros2component ](https://github.com/ros2/ros2cli/tree/master/ros2component) ,
and [ composition ](https://github.com/ros2/demos/tree/master/composition)
packages, and can be run with the following commands.


[ ![@crystaldust](https://avatars.githubusercontent.com/u/2040659?s=80&v=4)
](/crystaldust)


[ crystaldust ](/crystaldust) opened this issue  Jun 16, 2020  · 20 comments


  * [ ](../index.html) »
  * [ 教程 ](../Tutorials.html) »
  * Composing multiple nodes in a single process
  * [ 在 GitHub 上修改 ](https://github.com/ros2/ros2_documentation/blob/xin/source/Tutorials/Composition.rst)


The ros2cli component verb's types command will only try to find resource_type
'rclcpp_components' as the code shows [ here
](https://github.com/ros2/ros2cli/blob/master/ros2component/ros2component/api/__init__.py#L35)
. The rclcpp's implementation uses [ ros/class_loader
](https://github.com/ros/class_loader) to load cpp classes from the compiled
.so files. The .so files are compiled following the cmake rules described in
the application level codes(like the [ composition demo
](https://github.com/ros2/demos/tree/master/composition) ), I'm not a C++
expert, but the basic logic should be like this.


Include my email address so I can be contacted


Namespace remappings of the container do not affect loaded components.


View products (3)


###  Footer navigation


The Component Manager is a system-level component in ROS 2 that manages the
lifecycle of other components in the system. It is responsible for
_instantiating, activating, and deactivating components_ as needed.


In a second shell, components can be loaded by using the updated container
name:


**[ dirk-thomas ](/dirk-thomas) ** commented  Jun 17, 2020


* Remap component names and namespaces


Lets build a **_video pipeline_ ** using ROS2 components,
1\. First, Will set up a _camera component_ that acquires images from a
camera. This component configure to connect to the camera and to publish the
images as ROS messages.
2\. Next, We create a _display component_ that receives the images from the
camera component and displays them.
3\. To load the camera component and the display component, We need to use the
_ROS2 component manager_ . It’s tool that is responsible for managing the
_lifecycle of ROS2 components_ . It is responsible for _loading_ and
_unloading_ components at compile & runtime, connecting them to other
components, and providing a framework for coordinating their interactions.
4\. Finally, We need to start the nodelet manager and the camera and display
components. This would launch the container process, which would in turn load
the component and connect them together.


**[ dirk-thomas ](/dirk-thomas) ** commented  Jun 23, 2020  •


> And when load/unload is called, the client lib should be able to distinguish
> in which language the component is written, if the user try to load a cpp
> component into a python container, an exception should be raised.


I would propose to just use a Python API / entry point for Python components.
The component can then decide internally if it wants to use a Cython library
or not.

---

All reactions


Email Address


* [ Composable Storefront spartacus ](/t5/tag/Composable%20Storefront%20spartacus/tg-p/board-id/crm-blog-sap)


[ ![theme-lib.general.user-
avatar](https://avatars.profile.sap.com/former_member_small.jpeg)
](/t5/user/viewprofilepage/user-id/3555 "View profile") ** by  [
former_member3555  ](/t5/user/viewprofilepage/user-id/3555 "View profile") **
•  _Advisor_


#  Saved searches


Now the first shell should show repeated output for each received message.


The composition API allows developer to manage the launch of node at runtime
as described in the [ design: process-with-multiple-nodes
](http://design.ros2.org/articles/roslaunch.html#process-with-multiple-nodes)


[ Sign in
](/login?return_to=https%3A%2F%2Fgithub.com%2Fros2%2Frclpy%2Fissues%2F575)


Listen


* **Upgrade to SAP Commerce Cloud, Composable Storefront 6 (or later)** , the latest update of Commerce Cloud, and Node.js 18, **now**


$ ros2 run rclcpp_components component_container


Sorry, something went wrong.


|  1

[
![yogananda](https://avatars.profile.sap.com/5/9/id59e1da3a3dca34a1bd12f9d987d3cdb668e528e343194e20fc715b0bc28cc49b_small.jpeg)
![Product and Topic
Expert](/html/@C6690A74F301515E6881523D52BDF6AA/rank_icons/sap-logo-
small-14px.png) yogananda  ](/t5/user/viewprofilepage/user-id/75)


I now have a rough understanding of the composition, according to the design
and rclcpp implementation, the rclpy should implement:


**References:**


Password


    } // namespace img_pipeline_composition
    #endif  // IMAGE_PIPELINE_COMPOSITION__DISPLAY_HPP_

    // display_component.cpp
    #include "img_pipeline_composition/display_component.hpp"

    namespace img_pipeline_composition
    {
        int
        DisplayComponent::encoding2mat_type(const std::string & encoding)
        {
        if (encoding == "mono8") {
            return CV_8UC1;
        } else if (encoding == "bgr8") {
            return CV_8UC3;
        } else if (encoding == "mono16") {
            return CV_16SC1;
        } else if (encoding == "rgba8") {
            return CV_8UC4;
        }
        throw std::runtime_error("Unsupported mat type");
        }

        void
        DisplayComponent::callback(const sensor_msgs::msg::Image::UniquePtr msg)
        {
            cv::Mat frame(
                msg->height, msg->width,
                encoding2mat_type(msg->encoding),
                msg->data.data());
            cv::imshow("window", frame);
            cv::waitKey(1);
        }
    }

    #include "rclcpp_components/register_node_macro.hpp"

    // Register the component with class_loader.


New issue


[ ![@crystaldust](https://avatars.githubusercontent.com/u/2040659?s=80&v=4)
](/crystaldust)


|  2

[
![sophie_crepin](https://avatars.profile.sap.com/7/e/id7e32399cc58faf6ed9fe201e9df11662b444bbec8ea9e006012a5be0b612cef0_small.jpeg)
![Advisor](/html/@C6690A74F301515E6881523D52BDF6AA/rank_icons/sap-logo-
small-14px.png) sophie_crepin  ](/t5/user/viewprofilepage/user-id/276496)


[ Write
](/m/signin?operation=register&redirect=https%3A%2F%2Fmedium.com%2Fnew-
story&source=---two_column_layout_nav-----------------------
new_post_topnav-----------)


> Installing a file from the ` setup.py ` logic is sufficient to add
> information to the ament resource index: see e.g. [
> https://github.com/ament/ament_index/blob/e58791231898d575a48455f23f7980820a9356b7/ament_index_python/setup.py#L16-L17
> ](https://github.com/ament/ament_index/blob/e58791231898d575a48455f23f7980820a9356b7/ament_index_python/setup.py#L16-L17)
> which registers the package name.


Agree, to fetch component info through entry point API, just call [
importlib.metadata.entry_points
](https://docs.python.org/3/library/importlib.metadata.html#entry-points) and
pass 'rclpy_components' as group name. This should just search the python
paths and get the refs to EntryPoint objects(no loading until EntryPoint
object's load method is called):
[
https://github.com/crystaldust/ros2cli/blob/994670497f32728e971e95fd8eeb12dc3864bd16/ros2component/ros2component/api/component_loaders.py#L75
](https://github.com/crystaldust/ros2cli/blob/994670497f32728e971e95fd8eeb12dc3864bd16/ros2component/ros2component/api/component_loaders.py#L75)


Without actual PRs for the implemented code it is difficult to comment on
specifics though. E.g. the branches contain commented code, unrelated changes,
etc. which should be cleaned up before making pull requests. Also instead of
hard coding the possible extension types and their loader I would suggest to
make it extensible too, e.g. by making the component type an entry point
itself.

---

All reactions


In contrast, a nodelet is a _lightweight variant_ of a node that is designed
to be used in cases where _performance is a concern_ . Like a node, a nodelet
performs a specific task within the system, but it is implemented as a
**_shared library that is loaded at runtime by a container process_ ** rather
than being compiled into an executable file.


Assignees


Contributor  Author


    $ ros2 run composition dlopen_composition `ros2 pkg prefix composition`/lib/libtalker_component.so `ros2 pkg prefix composition`/lib/liblistener_component.so

    $ ros2 run composition dlopen_composition `ros2 pkg prefix composition`/lib/libtalker_component.dylib `ros2 pkg prefix composition`/lib/liblistener_component.dylib

    > ros2 pkg prefix composition


ROS 1 - ROS 2 communication bridge
|
[ Tutorial ](https://github.com/ros2/ros1_bridge/blob/master/README.md)
|
Available for topics and services, not yet available for actions.

Quality of service settings for handling non-ideal networks
|
[ Demo  ](../Tutorials/Demos/Quality-of-Service.html)
|

Inter- and intra-process communication using the same API
|
[ Demo  ](../Tutorials/Demos/Intra-Process-Communication.html)
|
Currently only in C++.

Composition of node components at compile, link, load, or run time
|
[ Demo  ](../Tutorials/Intermediate/Composition.html)
|
Currently only in C++.

Multiple executors (at level of callback groups) in same node
|
[ Demo
](https://github.com/ros2/examples/tree/rolling/rclcpp/executors/cbg_executor)
|
Only in C++.

Support for nodes with managed lifecycles
|
[ Demo  ](../Tutorials/Demos/Managed-Nodes.html)
|
Currently only in C++.

DDS-Security support
|
[ Demo ](https://github.com/ros2/sros2)


##  Written by  Jegathesan Shanmugam


Sorry, something went wrong.


    install(TARGETS
      camera_component
      display_component
      ARCHIVE DESTINATION lib
      LIBRARY DESTINATION lib
      RUNTIME DESTINATION bin)

      install(DIRECTORY
      launch
      DESTINATION share/${PROJECT_NAME}
    )

    ament_package()


    target_link_libraries(camera_component
      ${sensor_msgs_TARGETS}
      ${OpenCV_LIBS})
    ament_target_dependencies(camera_component
      "rclcpp"
      "rclcpp_components"
      "std_msgs"
      )
    rclcpp_components_register_nodes(camera_component "img_pipeline_composition::CameraComponent")
    set(node_plugins "${node_plugins}img_pipeline_composition::CameraComponent;$<TARGET_FILE:camera_component>\n")

    add_library(display_component SHARED
      src/display_component.cpp)

    target_compile_definitions(display_component
      PRIVATE "IMAGE_PIPELINE_COMPOSITION_BUILDING_DLL")

    target_link_libraries(display_component
      ${sensor_msgs_TARGETS}
      ${OpenCV_LIBS})

    ament_target_dependencies(display_component
      "rclcpp"
      "rclcpp_components"
      "std_msgs"
      )
    rclcpp_components_register_nodes(display_component "img_pipeline_composition::DisplayComponent")
    set(node_plugins "${node_plugins}img_pipeline_composition::DisplayComponent;$<TARGET_FILE:display_component>\n")

    if(BUILD_TESTING)
      find_package(ament_lint_auto REQUIRED)
      # the following line skips the linter which checks for copyrights
      # uncomment the line when a copyright and license is not present in all source files
      #set(ament_cmake_copyright_FOUND TRUE)
      # the following line skips cpplint (only works in a git repo)
      # uncomment the line when this package is not in a git repo
      #set(ament_cmake_cpplint_FOUND TRUE)
      ament_lint_auto_find_test_dependencies()
    endif()


Copy link


> ` register_node_macro.hpp ` and ` RCLCPP_COMPONENTS_REGISTER_NODE ` is used
> to register a ROS2 component with the component manager.

    // display_component.hpp
    #ifndef IMAGE_PIPELINE_COMPOSITION__DISPLAY_HPP_
    #define IMAGE_PIPELINE_COMPOSITION__DISPLAY_HPP_

    // ROS and OpenCV Header
    #include "img_pipeline_composition/visibility_control.h"
    #include "opencv2/highgui/highgui.hpp"
    #include "rclcpp/rclcpp.hpp"
    #include "sensor_msgs/msg/image.hpp"

    // Creation of function objects with placeholder arguments
    using std::placeholders::_1;

    namespace img_pipeline_composition
    {
        // We create a DisplayComponent class that inherits from the rclcpp::Node
        // Note: Components get built into shared libraries and as
        // such do not write their own main functions.
        class DisplayComponent final : public rclcpp::Node
        {
            public:
                explicit DisplayComponent(const rclcpp::NodeOptions & options)
                : Node("display", options)
                {
                std::string topic_name = "camera/image";
                // Create a subscriber with sensor_msgs message type and queue size is 10
                subscription_ = this->create_subscription<sensor_msgs::msg::Image>(
                topic_name, 10, std::bind(&DisplayComponent::callback, this, _1));
                }

                void callback(const sensor_msgs::msg::Image::UniquePtr msg);
                int encoding2mat_type(const std::string & encoding);
            private:
                cv::Mat frame_;
                rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_;
        };


Projects


edited


    source /opt/ros/foxy/setup.zsh # Source the ROS2 Foxy
    cd ~/ros2_ws/src/     # Move to src directory

    # Create img_pipeline_composition package
    ros2 pkg create img_pipeline_composition --build-type ament_cmake --dependencies rclcpp rclcpp_components sensor_msgs

    cd ~/ros2_ws/src/img_pipeline_composition/include/
    touch visibility_control.h


[ ![@dirk-
thomas](https://avatars.githubusercontent.com/u/1335366?s=80&u=ec35ea6bae7c6e04a5df7482044bbc7681968435&v=4)
](/dirk-thomas)


Component names and namespaces may be adjusted via arguments to the load
command.


Some examples of how to remap names and namespaces:


* [ SAP Commerce Cloud  SAP Commerce Cloud  ](/t5/c-khhcw49343/SAP+Commerce+Cloud/pd-p/73555000100800001224)


    * [ Topics ](/topics)
    * [ Trending ](/trending)
    * [ Collections ](/collections)


Verify that the container is running via ` ros2  ` command line tools:


Compile-time composition refers to the process of combining all the ROS2
Components into a single entity during the compilation process.


[ enhancement  ](/ros2/rclpy/labels/enhancement) New feature or request


Sign up for GitHub


[ Robots  ](/tag/robots?source=post_page-----209ed023d8e5---------------
robots-----------------)


Did you mean:


#  Provide feedback


Stay up-to-date on the latest developments and product news about intelligent
customer experience and CRM technologies through blog posts from SAP experts.


Run-time composition refers to the process of combining all the ROS2
Components into a single entity at runtime.


This should show repeated messages from both pairs, the talker and the
listener as well as the server and the client.


> An executor is a class responsible for scheduling the execution of these
> callback functions so that they are executed in a timely manner and the
> system as a whole functions properly. For this purpose, the
> _rclcpp::executors_ class provides a variety of executor implementations,
> including single-threaded and multi-threaded executors. In a future post,
> we’ll talk more about this topic.

    add_executable(manual_composition
      src/manual_composition.cpp)
    target_link_libraries(manual_composition
      camera_component
      display_component
      )
    ament_target_dependencies(manual_composition
      "rclcpp")

    install(TARGETS
      manual_composition
      DESTINATION lib/${PROJECT_NAME})

    cd ~/ros2_ws/
    # Compile
    ros2 run composition manual_composition

    # Run the manual_composition process
    ros2 run img_pipeline_composition manual_composition


|  1

[
![KatJankovic](https://avatars.profile.sap.com/f/2/idf2dc4c8cb583b645067a95fc21d4e57dd6b9be1a518d0e8b7f579f813a7b2b12_small.jpeg)
![Advisor](/html/@C6690A74F301515E6881523D52BDF6AA/rank_icons/sap-logo-
small-14px.png) KatJankovic  ](/t5/user/viewprofilepage/user-id/160268)


None yet


Copy link


Sorry, something went wrong.


Search or jump to...


* Run-time composition using ROS services with a publisher and subscriber


**Have a question about this project?** Sign up for a free GitHub account to
open an issue and contact its maintainers and the community.


I've made an example according to the solution above:
[ https://github.com/crystaldust/rclpy_composition_example/tree/composition-
api
](https://github.com/crystaldust/rclpy_composition_example/tree/composition-
api)


> I can't find a good way to create the file under ament resource index path.


The example with a server and a client is very similar.


    // is being loaded into a running process.
    RCLCPP_COMPONENTS_REGISTER_NODE(img_pipeline_composition::CameraComponent)


[
](https://community.sap.com/t5/blogs/v2/blogarticlepage.kudosbuttonv2.kudoentity:kudoentity/kudosable-
gid/13560202?t:ac=blog-id/crm-blog-sap/article-
id/13107&t:cp=kudos/contributions/tapletcontributionspage "Click here to give
kudos to this post.")


Labels


For


**[ crystaldust ](/crystaldust) ** commented  Jun 16, 2020


* Compile-time composition using ROS services


        * [ Creating a launch file ](../Tutorials/Intermediate/Launch/Creating-Launch-Files.html)
        * [ Integrating launch files into ROS 2 packages ](../Tutorials/Intermediate/Launch/Launch-system.html)
        * [ Using substitutions ](../Tutorials/Intermediate/Launch/Using-Substitutions.html)
        * [ Using event handlers ](../Tutorials/Intermediate/Launch/Using-Event-Handlers.html)
        * [ Managing large projects ](../Tutorials/Intermediate/Launch/Using-ROS2-Launch-For-Large-Projects.html)
      * [ ` tf2  ` ](../Tutorials/Intermediate/Tf2/Tf2-Main.html)
        * [ Introducing ` tf2  ` ](../Tutorials/Intermediate/Tf2/Introduction-To-Tf2.html)
        * [ Writing a static broadcaster (Python) ](../Tutorials/Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Py.html)
        * [ Writing a static broadcaster (C++) ](../Tutorials/Intermediate/Tf2/Writing-A-Tf2-Static-Broadcaster-Cpp.html)
        * [ Writing a broadcaster (Python) ](../Tutorials/Intermediate/Tf2/Writing-A-Tf2-Broadcaster-Py.html)
        * [ Writing a broadcaster (C++) ](../Tutorials/Intermediate/Tf2/Writing-A-Tf2-Broadcaster-Cpp.html)
        * [ Writing a listener (Python) ](../Tutorials/Intermediate/Tf2/Writing-A-Tf2-Listener-Py.html)
        * [ Writing a listener (C++) ](../Tutorials/Intermediate/Tf2/Writing-A-Tf2-Listener-Cpp.html)
        * [ Adding a frame (Python) ](../Tutorials/Intermediate/Tf2/Adding-A-Frame-Py.html)
        * [ Adding a frame (C++) ](../Tutorials/Intermediate/Tf2/Adding-A-Frame-Cpp.html)
        * [ Using time (Python) ](../Tutorials/Intermediate/Tf2/Learning-About-Tf2-And-Time-Py.html)
        * [ Using time (C++) ](../Tutorials/Intermediate/Tf2/Learning-About-Tf2-And-Time-Cpp.html)
        * [ Traveling in time (Python) ](../Tutorials/Intermediate/Tf2/Time-Travel-With-Tf2-Py.html)
        * [ Traveling in time (C++) ](../Tutorials/Intermediate/Tf2/Time-Travel-With-Tf2-Cpp.html)
        * [ Debugging ](../Tutorials/Intermediate/Tf2/Debugging-Tf2-Problems.html)
        * [ Quaternion fundamentals ](../Tutorials/Intermediate/Tf2/Quaternion-Fundamentals.html)
        * [ Using stamped datatypes with ` tf2_ros::MessageFilter  ` ](../Tutorials/Intermediate/Tf2/Using-Stamped-Datatypes-With-Tf2-Ros-MessageFilter.html)
      * [ Testing ](../Tutorials/Intermediate/Testing/Testing-Main.html)
        * [ Running Tests in ROS 2 from the Command Line ](../Tutorials/Intermediate/Testing/CLI.html)
        * [ Writing Basic Tests with C++ with GTest ](../Tutorials/Intermediate/Testing/Cpp.html)
        * [ Writing Basic Tests with Python ](../Tutorials/Intermediate/Testing/Python.html)
      * [ URDF ](../Tutorials/Intermediate/URDF/URDF-Main.html)
        * [ Building a visual robot model from scratch ](../Tutorials/Intermediate/URDF/Building-a-Visual-Robot-Model-with-URDF-from-Scratch.html)
        * [ Building a movable robot model ](../Tutorials/Intermediate/URDF/Building-a-Movable-Robot-Model-with-URDF.html)
        * [ Adding physical and collision properties ](../Tutorials/Intermediate/URDF/Adding-Physical-and-Collision-Properties-to-a-URDF-Model.html)
        * [ Using Xacro to clean up your code ](../Tutorials/Intermediate/URDF/Using-Xacro-to-Clean-Up-a-URDF-File.html)
        * [ Using URDF with ` robot_state_publisher  ` ](../Tutorials/Intermediate/URDF/Using-URDF-with-Robot-State-Publisher.html)
        * [ Generating an URDF File ](../Tutorials/Intermediate/URDF/Exporting-an-URDF-File.html)
      * [ RViz ](../Tutorials/Intermediate/RViz/RViz-Main.html)
        * [ RViz User Guide ](../Tutorials/Intermediate/RViz/RViz-User-Guide/RViz-User-Guide.html)
        * [ Building a Custom RViz Display ](../Tutorials/Intermediate/RViz/RViz-Custom-Display/RViz-Custom-Display.html)
    * [ Advanced ](../Tutorials/Advanced.html)
      * [ Enabling topic statistics (C++) ](../Tutorials/Advanced/Topic-Statistics-Tutorial/Topic-Statistics-Tutorial.html)
      * [ Using Fast DDS Discovery Server as discovery protocol [community-contributed] ](../Tutorials/Advanced/Discovery-Server/Discovery-Server.html)
      * [ Implementing a custom memory allocator ](../Tutorials/Advanced/Allocator-Template-Tutorial.html)


Run another command in the second shell to load the listener component (see [
listener
](https://github.com/ros2/demos/blob/master/composition/src/listener_component.cpp)
source code):


A package can't rely on dependencies being available when the ` setup.py `
file is being processed. Simply because Python needs to parse that file in
order to extract the declared dependencies. So you can't use any external
modules like ` from rclpy.component import rclpy_register_component ` .


|  2

[
![joris_quenee](https://avatars.profile.sap.com/4/b/id4b10e01846efcdf735c3f3a3f95992981ec64febecd0b80d2fafdd41988ca8f4_small.jpeg)
![Product and Topic
Expert](/html/@C6690A74F301515E6881523D52BDF6AA/rank_icons/sap-logo-
small-14px.png) joris_quenee  ](/t5/user/viewprofilepage/user-id/173030)


Installing a file from the ` setup.py ` logic is suffcient to add information
to the ament resource index: see e.g. [
https://github.com/ament/ament_index/blob/e58791231898d575a48455f23f7980820a9356b7/ament_index_python/setup.py#L16-L17
](https://github.com/ament/ament_index/blob/e58791231898d575a48455f23f7980820a9356b7/ament_index_python/setup.py#L16-L17)
which registers the package name.


Member


[ ![@crystaldust](https://avatars.githubusercontent.com/u/2040659?s=80&v=4)
](/crystaldust)


All reactions


The component manager name and namespace can be remapped via standard command
line arguments:


](https://speechify.com/medium?source=post_page-----
209ed023d8e5--------------------------------)


    touch ~/ros2_ws/src/img_pipeline_composition/src/manual_composition.cpp

    //manual_composition.cpp
    #include <memory>

    #include "img_pipeline_composition/camera_component.hpp"
    #include "img_pipeline_composition/display_component.hpp"

    #include "rclcpp/rclcpp.hpp"

    int main(int argc, char * argv[])
    {

      // Initialize the ROS2 communication
      rclcpp::init(argc, argv);

      // Create an executor responsible for executing callbacks
      // for a collection of nodes. This version will invoke all
      // callbacks from within this thread (the main one).
      rclcpp::executors::SingleThreadedExecutor exec;
      rclcpp::NodeOptions options;

      // Add CAMERA AND Display to the executor
      auto camera = std::make_shared<img_pipeline_composition::CameraComponent>(options);
      exec.add_node(camera);
      auto display = std::make_shared<img_pipeline_composition::DisplayComponent>(options);
      exec.add_node(display);

      // Create a default single-threaded executor and spin the specified node
      exec.spin();

      // Shutdown the ROS2 communication
      rclcpp::shutdown();

      return 0;
    }


In the second shell load the talker component (see [ talker
](https://github.com/ros2/demos/blob/master/composition/src/talker_component.cpp)
source code):


    cmake_minimum_required(VERSION 3.5)
    project(img_pipeline_composition)

    # Default to C99
    if(NOT CMAKE_C_STANDARD)
      set(CMAKE_C_STANDARD 99)
    endif()

    # Default to C++14
    if(NOT CMAKE_CXX_STANDARD)
      set(CMAKE_CXX_STANDARD 14)
    endif()

    if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
      add_compile_options(-Wall -Wextra -Wpedantic)
    endif()

    # find dependencies
    find_package(ament_cmake REQUIRED)
    find_package(rclcpp REQUIRED)
    find_package(rclcpp_components REQUIRED)
    find_package(sensor_msgs REQUIRED)
    find_package(builtin_interfaces REQUIRED)

    find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc videoio)

    include_directories(include)
    include_directories( ${OpenCV_INCLUDE_DIRS} )

    # create ament index resource which references the libraries in the binary dir
    set(node_plugins "")

    add_library(camera_component SHARED
      src/camera_component.cpp)

    target_compile_definitions(camera_component
      PRIVATE "IMAGE_PIPELINE_COMPOSITION_BUILDING_DLL")


#  rclpy composition API  #575


* [ Spartacus ](/t5/tag/Spartacus/tg-p/board-id/crm-blog-sap)


    * [ CI/CD & Automation ](/solutions/ci-cd/)
    * [ DevOps ](/solutions/devops/)
    * [ DevSecOps  ](https://resources.github.com/devops/fundamentals/devsecops/)


|

Command-line introspection tools using an extensible framework
|
[ Concept  ](../Concepts/Basic/About-Command-Line-Tools.html)
|

Launch system for coordinating multiple nodes
|
[ Tutorial  ](../Tutorials/Intermediate/Launch/Launch-system.html)
|

Namespace support for nodes and topics
|
[ Article ](https://design.ros2.org/articles/topic_and_service_names.html)
|

Static remapping of ROS names
|
[ How-to Guide  ](../How-To-Guides/Node-arguments.html)
|

Demos of an all-ROS 2 mobile robot
|
[ Demo ](https://github.com/ros2/turtlebot2_demo)
|

Preliminary support for real-time code
|
[ Demo  ](../Tutorials/Demos/Real-Time-Programming.html) , [ demo
](../Tutorials/Advanced/Allocator-Template-Tutorial.html)
|
Linux only. Not available for Fast RTPS.

Preliminary support for âbare-metalâ microcontrollers
|
[ Wiki ](https://github.com/ros2/freertps/wiki)
|

Content filtering subscription


Contributor  Author


[ ![Jegathesan
Shanmugam](https://miro.medium.com/v2/resize:fill:144:144/2*h3PRzfT7jps1zKlfhvGp6Q.jpeg)
](/@nullbyte.in?source=post_page-----
209ed023d8e5--------------------------------)


Repositories


Add the following lines to CMakeLists.txt,


[ ![](https://community.sap.com/html/assets/img_tile-default.png) ](/t5/crm-
and-cx-blogs-by-sap/sap-hybris-cloud-for-customer-all-about-integration-no-
longer-updated/ba-p/13210718 "View article")


In the first shell:


[ ![@crystaldust](https://avatars.githubusercontent.com/u/2040659?s=40&v=4)
](/crystaldust) [ crystaldust ](/crystaldust) reopened this  Jun 17, 2020


#  Search code, repositories, users, issues, pull requests...


Member


                return "mono16";
                case CV_8UC4:
                return "rgba8";
                default:
                throw std::runtime_error("Unsupported encoding type");
            }
        }

        // Camera callback
        void
        CameraComponent::callback()
        {
            while (rclcpp::ok()) {
                // Capture a frame from OpenCV.
                cap_ >> frame_;
                if (frame_.empty()) {
                    continue;
                }
                // Create a new unique_ptr to an Image message for storage.
                sensor_msgs::msg::Image::UniquePtr msg(new sensor_msgs::msg::Image());

                // Pack the OpenCV image into the ROS image.
                msg->header.frame_id = "camera_frame";
                msg->height = frame_.rows;
                msg->width = frame_.cols;
                msg->encoding = mat_type2encoding(frame_.type());
                msg->is_bigendian = false;
                msg->step = static_cast<sensor_msgs::msg::Image::_step_type>(frame_.step);
                msg->data.assign(frame_.datastart, frame_.dataend);

                // Publish the converted image
                publisher_->publish(std::move(msg));
            }
        }
    }

    #include "rclcpp_components/register_node_macro.hpp"

    // Register the component with class_loader.
    // This acts as a sort of entry point, allowing the component to be discoverable when its library


Yes, that would be fine. Storing the actual component class directly or
together with some metadata would be a design decision to figure out. Often
you want a way to determine what version of the interface contract a component
implements / supports to allow iterating it i the future.


**To stay current on Composable Storefront and avoid errors on new builds**
**, you** **must upgrade to Composable Storefront 6 (or later version)
and/or** **Node.js 18 now.**


Or, maybe it would be better to skip the command override, just provide the `
rclpy_register_component ` helper, and put it in the ` setup.py ` :


So it becomes even harder to decide, maybe we need a more thorough discussion
on this?

---

All reactions


All community  This category  Blog  Knowledge base  Users  Managed tags
cancel


Sign up


  * [ Subscribe to RSS Feed ](/khhcw49343/rss/message?board.id=crm-blog-sap&message.id=13107)
  *   * Mark as New
  * Mark as Read
  *   * Bookmark
  * Subscribe
  *   * [ Printer Friendly Page ](/t5/blogs/blogarticleprintpage/blog-id/crm-blog-sap/article-id/13107)
  * [ Report Inappropriate Content ](/t5/notifications/notifymoderatorpage/message-uid/13560202)


##  Run the demos  


[ ros2 ](/ros2) /  **[ rclpy ](/ros2/rclpy) ** Public


###  Composition using launch actions  


Dec 25, 2022


    $ ros2 component load /ComponentManager composition composition::Listener
    Loaded component 2 into '/ComponentManager' container node as '/listener'


Additional navigation options


    * [ About different ROS 2 DDS/RTPS vendors ](../Concepts/About-Different-Middleware-Vendors.html)
    * [ About logging and logger configuration ](../Concepts/About-Logging.html)
    * [ About Quality of Service settings ](../Concepts/About-Quality-of-Service-Settings.html)
    * [ About ROS 2 client libraries ](../Concepts/About-ROS-2-Client-Libraries.html)
    * [ About ROS 2 interfaces ](../Concepts/About-ROS-Interfaces.html)
    * [ About parameters in ROS 2 ](../Concepts/About-ROS-2-Parameters.html)
    * [ Executors ](../Concepts/About-Executors.html)
    * [ About topic statistics ](../Concepts/About-Topic-Statistics.html)
    * [ Introspection with command line tools ](../Concepts/About-Command-Line-Tools.html)
    * [ Overview and usage of RQt ](../Concepts/About-RQt.html)
    * [ About Composition ](../Concepts/About-Composition.html)
    * [ On the mixing of ament and catkin (catment) ](../Concepts/About-Catment.html)
    * [ About Cross-compilation ](../Concepts/About-Cross-Compilation.html)
    * [ About tf2 ](../Concepts/About-Tf2.html)
    * [ About the build system ](../Concepts/About-Build-System.html)
    * [ About internal ROS 2 interfaces ](../Concepts/About-Internal-Interfaces.html)
    * [ About ROS 2 middleware implementations ](../Concepts/About-Middleware-Implementations.html)
    * [ ROS 2 Client Interfaces (Client Libraries) ](../Concepts/About-Client-Interfaces.html)
  * [ Contributing ](../Contributing.html)
    * [ ROS 2 developer guide ](../Contributing/Developer-Guide.html)
    * [ Code style and language versions ](../Contributing/Code-Style-Language-Versions.html)
    * [ Quality guide: ensuring code quality ](../Contributing/Quality-Guide.html)
    * [ Migration guide from ROS 1 ](../Contributing/Migration-Guide.html)
      * [ Python migration guide from ROS 1 ](../Contributing/Migration-Guide-Python.html)
    * [ ROS Build Farms ](../Contributing/Build-Farms.html)
    * [ Windows Tips and Tricks ](../Contributing/Windows-Tips-and-Tricks.html)
    * [ Contributing to ROS 2 Documentation ](../Contributing/Contributing-To-ROS-2-Documentation.html)
  * [ Contact ](../Contact.html)
  * [ ROSCon Content ](../ROSCon-Content.html)
  * [ Distributions ](../Releases.html)
    * [ ROS 2 alpha releases (Aug 2015 - Oct 2016) ](../Releases/Alpha-Overview.html)
    * [ Beta 1 (codename ‘Asphalt’; December 2016) ](../Releases/Beta1-Overview.html)
    * [ Beta 2 (codename ‘r2b2’; July 2017) ](../Releases/Beta2-Overview.html)
    * [ Beta 3 (codename ‘r2b3’; September 2017) ](../Releases/Beta3-Overview.html)
    * [ ROS 2 Ardent Apalone (codename ‘ardent’; December 2017) ](../Releases/Release-Ardent-Apalone.html)
    * [ ROS 2 Bouncy Bolson (codename ‘bouncy’; June 2018) ](../Releases/Release-Bouncy-Bolson.html)
    * [ ROS 2 Crystal Clemmys (codename ‘crystal’; December 2018) ](../Releases/Release-Crystal-Clemmys.html)
    * [ ROS 2 Dashing Diademata (codename ‘dashing’; May 31st, 2019) ](../Releases/Release-Dashing-Diademata.html)
    * [ ROS 2 Eloquent Elusor (codename ‘eloquent’; November 22nd, 2019) ](../Releases/Release-Eloquent-Elusor.html)
    * [ ROS 2 Foxy Fitzroy (codename ‘foxy’; June 5th, 2020) ](../Releases/Release-Foxy-Fitzroy.html)


[ ![@crystaldust](https://avatars.githubusercontent.com/u/2040659?s=80&v=4)
](/crystaldust)


Sincerely,


    // This acts as a sort of entry point, allowing the component to be discoverable when its library
    // is being loaded into a running process.
    RCLCPP_COMPONENTS_REGISTER_NODE(img_pipeline_composition::DisplayComponent)

    # image_pipeline_launch.py
    import launch
    from launch_ros.actions import ComposableNodeContainer
    from launch_ros.descriptions import ComposableNode

    def generate_launch_description():
        """Generate launch description with multiple components."""
        container = ComposableNodeContainer(
                name='image_pipeline',
                namespace='',
                package='rclcpp_components',
                executable='component_container',
                composable_node_descriptions=[
                    ComposableNode(
                        package='img_pipeline_composition',
                        plugin='img_pipeline_composition::CameraComponent',
                        name='cameracomponent'),
                    ComposableNode(
                        package='img_pipeline_composition',
                        plugin='img_pipeline_composition::DisplayComponent',
                        name='displaycomponent'),
                ],
                output='screen',
        )

        return launch.LaunchDescription([container])


ROS2 Composition are designed to inherit many of the concepts and capabilities
of ROS1 nodelet. Like nodelet, ROS2 components are designed to be lightweight
variants of ROS2 nodes that are intended to be used in cases where performance
is a concern or where you want to add common concepts like a **_life cycle to
your code_ ** .


###  [ Tips and Tricks - Troubleshooting CRM (Interaction Center) ](/t5/crm-
and-cx-blogs-by-sap/tips-and-tricks-troubleshooting-crm-interaction-
center/ba-p/12968908)


From tooling or framework perspective, we should leave the simplicity to
developers outside and solve the complexity inside, so providing Python Entry
Point should be a preferable way. But after looking into deeper of the code,
the ros2cli component verb relies on ros2 pkg verb's APIs:


---

The text was updated successfully, but these errors were encountered:


* [ SAP Commerce Cloud Supplemental Terms and Conditions ](https://www.sap.com/about/trust-center/agreements/cloud/cloud-services.html?sort=latest_desc&search=commerce%20cloud) ,


##  Compile-time and Run-time composition:


|  1

[
![ma_c](https://avatars.profile.sap.com/f/0/idf06164cba4d48bc1874a77c716443ff8ac68b77546634238f209db539a876b24_small.jpeg)
ma_c  ](/t5/user/viewprofilepage/user-id/776176)


Member


Sign up


**[ crystaldust ](/crystaldust) ** commented  Jul 7, 2020


* **Versions of Composable Storefront that are not current** will result in build errors; you will not be able to deploy new code. For version information, refer to [ Update Release Policy and Publication Frequency for Composable Storefront Libraries ](https://help.sap.com/docs/SAP_COMMERCE_COMPOSABLE_STOREFRONT/6c7b98dbe68f4a508cac17a207182f4c/ba62c2c708ec4751a2612a512177419b.html) .


Labels:


[ ![@dirk-
thomas](https://avatars.githubusercontent.com/u/1335366?s=80&u=ec35ea6bae7c6e04a5df7482044bbc7681968435&v=4)
](/dirk-thomas)


##  Composable nodes as shared libraries  


](https://help.medium.com/hc/en-us?source=post_page-----
209ed023d8e5--------------------------------)


No milestone


No branches or pull requests


    $ ros2 component load /ComponentManager composition composition::Talker
    Loaded component 1 into '/ComponentManager' container node as '/talker'
    $ ros2 component load /ComponentManager composition composition::Listener
    Loaded component 2 into '/ComponentManager' container node as '/listener'


But for python, searching component types under the ament resource index file
is not necessary, as you mentioned, the python entry point can do the job
perfectly. Just let ` ros2 component types ` command search the `
rclpy_components ` entry points, we can refer to the actual component classes.
It will also reduce complexity. In ros2cli component verb, we just need to add
a different logic to search Python components, which is different from
searching C++ components. Does it make sense?

---

All reactions


* [ Release notes for SAP Commerce Cloud JS storefront hosting ](https://help.sap.com/whats-new/3d7190d2aab14c7d92f918cc3fa9a024?locale=en-US&Component=JavaScript%2520Storefront%253BJavaScript%2520Storefronts)


[ ](https://github.com "GitHub") © 2024 GitHub, Inc.


The composition mechanism relies on [ ament_resource_indexer
](https://github.com/ament/ament_cmake/blob/master/ament_cmake_core/doc/resource_index.md)
, basically the resources are stored in path `
<prefix>/share/ament_index/resource_index/<resource_type>/<resource_name> ` .


The rclcpp library has implemented the [ composition API
](https://github.com/ros2/rclcpp/tree/master/rclcpp_components) and has a few
samples: [ composition
](https://github.com/ros2/demos/tree/master/composition) , [
minimal_composition
](https://github.com/ros2/examples/tree/master/rclcpp/composition/minimal_composition)


Then I would prefer to ask developer to install the empty component file to `
<prefix>/share/ament_index/resource_index/packages ` , so the [ argcomplete
and get_package_names API
](https://github.com/crystaldust/ros2cli/blob/994670497f32728e971e95fd8eeb12dc3864bd16/ros2component/ros2component/verb/types.py#L20-L21)
would be supported. And when we try to instantiate the component, use the
entry point API to load the real classes.


I am not sure how this would be beneficial. In each language the logic how to
load a component is specific to that language. A container written in one
language can't load components written in a different language.


Then install the generated file and export the generated file.


$ ros2 run rclcpp_components component_container


##  Feature request


    # Remap node name
    $ ros2 component load /ComponentManager composition composition::Talker --node-name talker2
    # Remap namespace
    $ ros2 component load /ComponentManager composition composition::Talker --node-namespace /ns
    # Remap both
    $ ros2 component load /ComponentManager composition composition::Talker --node-name talker3 --node-namespace /ns2


**[ crystaldust ](/crystaldust) ** commented  Jun 20, 2020


Thank you for taking the time to read this, and I hope you found it useful! If
you have any questions or comments, please leave them in the space below.


Now with Launch file,


    ...
    setup(name='my_robot_app')
    # Pass a list like it does above
    rclpy_register_component(rclpy_components)
    # Or pass a string if the developer want to make the registration explicit
    rclpy_register_component('composition::Talker=my_robot_app.component:Talker')

---

All reactions


](/about?autoplay=1&source=post_page-----
209ed023d8e5--------------------------------)


06-15-2023  7:54 PM


###  Discover available components  


Sorry, something went wrong.


Related Content


Contributor  Author


](https://policy.medium.com/medium-privacy-
policy-f03bf92035c9?source=post_page-----
209ed023d8e5--------------------------------)


[ 245 Followers ](/@nullbyte.in/followers?source=post_page-----
209ed023d8e5--------------------------------)


Table of Contents


edited


Copy link


In this case the client sends a request to the server, the server processes
the request and replies with a response, and the client prints the received
response.


Cancel  Submit feedback


[ 上一页 ](Launch-Files/Using-Event-Handlers.html "Using event handlers in launch
files") [ 下一页  ](Colcon-Tutorial.html "使用 colcon 构建包")


  * specify the 'rclpy_components' entry points in setup.py(this is required no matter what)
  * install the empty component files to amend resource index folder, keep the file name same with entry point name


That's what I come up with for now, any ideas?

---

All reactions


|  4

[
![YannickRobin](https://avatars.profile.sap.com/2/8/id28ca5f4bcd78a866faef136971bc2822a5072d1ef47aa2e2ecaa22611f9a1d1d_small.jpeg)
![Product and Topic
Expert](/html/@C6690A74F301515E6881523D52BDF6AA/rank_icons/sap-logo-
small-14px.png) YannickRobin  ](/t5/user/viewprofilepage/user-id/144045)


Jump to bottom


    * [ Using parameters in a class (Python) ](Using-Parameters-In-A-Class-Python.html)
    * [ Getting started with ros2doctor ](Getting-Started-With-Ros2doctor.html)
    * [ Creating and Using Plugins (C++) ](Pluginlib.html)
    * [ Creating an action ](Actions/Creating-an-Action.html)
    * [ Writing an action server and client (C++) ](Actions/Writing-a-Cpp-Action-Server-Client.html)
    * [ Writing an action server and client (Python) ](Actions/Writing-a-Py-Action-Server-Client.html)
    * [ Launching/monitoring multiple nodes with Launch ](Launch-system.html)
    * [ Using ROS 2 launch for large projects ](Launch-Files/Using-ROS2-Launch-For-Large-Projects.html)
    * [ Using substitutions in launch files ](Launch-Files/Using-Substitutions.html)
    * [ Using event handlers in launch files ](Launch-Files/Using-Event-Handlers.html)
    * Composing multiple nodes in a single process
    * [ 使用 colcon 构建包 ](Colcon-Tutorial.html)
    * [ Monitoring for parameter changes (C++) ](Monitoring-For-Parameter-Changes-CPP.html)
    * [ tf2 Tutorials ](Tf2/Tf2-Main.html)
      * [ Introduction to tf2 ](Tf2/Introduction-To-Tf2.html)
      * [ Writing a tf2 static broadcaster (Python) ](Tf2/Writing-A-Tf2-Static-Broadcaster-Py.html)
      * [ Writing a tf2 static broadcaster (C++) ](Tf2/Writing-A-Tf2-Static-Broadcaster-Cpp.html)
      * [ Writing a tf2 broadcaster (Python) ](Tf2/Writing-A-Tf2-Broadcaster-Py.html)
      * [ Writing a tf2 broadcaster (C++) ](Tf2/Writing-A-Tf2-Broadcaster-Cpp.html)
      * [ Writing a tf2 listener (Python) ](Tf2/Writing-A-Tf2-Listener-Py.html)
      * [ Writing a tf2 listener (C++) ](Tf2/Writing-A-Tf2-Listener-Cpp.html)
      * [ Adding a frame (Python) ](Tf2/Adding-A-Frame-Py.html)
      * [ Adding a frame (C++) ](Tf2/Adding-A-Frame-Cpp.html)
      * [ Learning about tf2 and time (Python) ](Tf2/Learning-About-Tf2-And-Time-Py.html)
      * [ Learning about tf2 and time (C++) ](Tf2/Learning-About-Tf2-And-Time-Cpp.html)
      * [ Time travel with tf2 (Python) ](Tf2/Time-Travel-With-Tf2-Py.html)
      * [ Time travel with tf2 (C++) ](Tf2/Time-Travel-With-Tf2-Cpp.html)
      * [ Debugging tf2 problems ](Tf2/Debugging-Tf2-Problems.html)
      * [ Quaternion fundamentals ](Tf2/Quaternion-Fundamentals.html)
      * [ Using stamped datatypes with tf2_ros::MessageFilter ](Tf2/Using-Stamped-Datatypes-With-Tf2-Ros-MessageFilter.html)
    * [ URDF Tutorials ](URDF/URDF-Main.html)
      * [ Building a Visual Robot Model with URDF from Scratch ](URDF/Building-a-Visual-Robot-Model-with-URDF-from-Scratch.html)
      * [ Building a Movable Robot Model with URDF ](URDF/Building-a-Movable-Robot-Model-with-URDF.html)
      * [ Adding Physical and Collision Properties to a URDF Model ](URDF/Adding-Physical-and-Collision-Properties-to-a-URDF-Model.html)
      * [ Using Xacro to Clean Up a URDF File ](URDF/Using-Xacro-to-Clean-Up-a-URDF-File.html)
      * [ Using URDF with robot_state_publisher ](URDF/Using-URDF-with-Robot-State-Publisher.html)
    * [ ROS 2 Topic Statistics Tutorial (C++) ](Topics/Topic-Statistics-Tutorial.html)
    * [ Using Fast DDS Discovery Server as discovery protocol [community-contributed] ](Discovery-Server/Discovery-Server.html)
    * [ Implement a custom memory allocator ](Allocator-Template-Tutorial.html)
    * [ Unlock all the potential of Fast DDS as ROS 2 middleware [community-contributed] ](FastDDS-Configuration/FastDDS-Configuration.html)


> Simply because Python needs to parse that file in order to extract the
> declared dependencies.


Pick a username


Sorry, something went wrong.


Clear


[ Open in app
](https://rsci.app.link/?%24canonical_url=https%3A%2F%2Fmedium.com%2Fp%2F209ed023d8e5&%7Efeature=LoOpenInAppButton&%7Echannel=ShowPostUnderUser&source=---two_column_layout_nav----------------------------------)


> I am not sure how this would be beneficial. In each language the logic how
> to load a component is specific to that language. A container written in one
> language can't load components written in a different language.


A practical example can be seen here: [ ROS Discourse - Ament best practice
for sharing libraries ](https://discourse.ros.org/t/ament-best-practice-for-
sharing-libraries/3602)


###  Remap component names and namespaces  