Question:
Can’t see debug messages using RCLCPP_DEBUG

I can’t see messages using RCLCPP_DEBUG by terminal and rqt, but I can using other levels of verbosity( INFO, ERROR, FATAL…).Selecting debug in rqt to see those messages doesn’t work either.

I’m using rolling, working in C++ in a plugin of a controller and launching tb3_simulation_launch.py from nav2_bringup.

I also saw a post here where they recommended to set the environment variable:

RCLCPP_LOG_MIN_SEVERITY=RCLCPP_LOG_MIN_SEVERITY_DEBUG

but that didn’t work either. It must be something silly that I’m missing. Has this ever happened to you?

Thank you

Explanation: showing debug messages is usually related to log-level. We can check whether there is some argument that can adjust this.

$\begingroup$

You can try adding ` arguments=["--ros-args", "--log-level", "debug"], ` to
the Node which you are interested in at the launch file.

Or in the case where you seem to be using the nav2_bringup straight, you can
change it at [ https://github.com/ros-
planning/navigation2/blob/ab9b1010d7a126c0c407cd09228d97068646ee4c/nav2_bringup/launch/navigation_launch.py#L134
](https://github.com/ros-
planning/navigation2/blob/ab9b1010d7a126c0c407cd09228d97068646ee4c/nav2_bringup/launch/navigation_launch.py#L134)

You should also be able to give argument ` log_level:=debug ` when launching
the launch file since that is being handled in [ the launch file
](https://github.com/ros-
planning/navigation2/blob/ab9b1010d7a126c0c407cd09228d97068646ee4c/nav2_bringup/launch/navigation_launch.py#L119)
. Downside is that then all nodes will have debug level and there will be lots
of extras

Example of launch file addition

        controller_server = Node(
            package="nav2_controller",
            executable="controller_server",
            output={"both": {"screen", "log", "own_log"}},
            emulate_tty=True,
            parameters=[],
            arguments=["--ros-args", "--log-level", "debug"],
         )


Question:
sensor fusion of lidar and camera detection

I am trying to achieve sensor fusion between two sensors(camera and lidar). I have two separate node(one is publishing detection results using camera, and other is using lidar and they both are operating on a seperate deep learning based object detection methods) which are publishing detection results in the form of vision_msgs detection array.

Now I want to fuse these detection results. How can I go further? I am using ros2 humble with gazebo fortress and I am trying this experiments in the simulated environment only. (no real sensors)

Explanation: This is related to Kalman Filter, which uses a series of measurements observed over time to produce estimates of unknown variables.

$\begingroup$

If you're looking to fuse the sensor readings together into one better
measurement, the right tool for the job is generally a Kalman Filter. It's not
ROS specific, but OpenCV has a [ Kalman Filter Implementation
](https://vovkos.github.io/doxyrest-
showcase/opencv/sphinx_rtd_theme/class_cv_KalmanFilter.html) . The OpenCV
kalman filter is available in python and C++. It's well documented and there
are plenty of [ online tutorials ](https://pieriantraining.com/kalman-filter-
opencv-python-example/) available for it that may apply directly to your use.


Question:
Does gazebo_ros2_control need to be sourced/built/linked after installation via apt?

Anywhere I search I can see that gazebo_ros2_control can be installed in the Humble distribution with Ubuntu 22 with just an apt command. My problem is that ros2 seems to not be finding the plugin.

[gazebo-3] [Err] [Model.cc:1160] Exception occured in the Load function of plugin with name[gazebo_ros2_control] and filename[libgazebo_ros2_control.so]. This plugin will not run.
For example in here it is mentioned:

A Gazebo plugin is added with this lines in the URDF:

  <plugin filename="plugin_name.so" name="some_name" >
    plugin args...
  </plugin>
However you will need to export the plugins path to advertise Gazebo where to find custom plugins. Take a look at this tutorial, you whould be able to follow it until the end, where you will find how to export and launch the plugin.

I am wondering, maybe I need to source /usr/share/gazebo/ or gazebo-11 for that matter. I tried with some repositories that are instantly triable. Same error. I actually thought of using the universal robots repo, which installs in the workspace the different ros2-control, gazebo-ros2-control.

ls ../workspaces/ur_gazebo/src/
gazebo_ros2_control       moveit_msgs
learm_ros2                ros2_control
learm_ros2_description    ros2_controllers
learm_ros2_moveit_config  Universal_Robots_ROS2_Gazebo_Simulation
moveit2                   ur_description
But I am getting the same. I got at some point a message to "override" paths.

My main question is: After installing gazebo_ros2_control, does ANYTHING ELSE need to be done? Adding to a CMakesList.txt, or to package.xml, setup.py? I read in here that it might be related to GAZEBO_MODEL_PATH. Something related to rosdep maybe?

Code:

import os
from launch_ros.actions import Node
from launch import LaunchDescription
from launch.substitutions import Command
from launch.actions import ExecuteProcess
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():

    #robot_model = 'm1013'

    xacro_file = get_package_share_directory('learm_ros2') + '/urdf/learm-gazebo.urdf.xacro'

    # Robot State Publisher
    robot_state_publisher = Node(package    ='robot_state_publisher',
                                 executable ='robot_state_publisher',
                                 name       ='robot_state_publisher',
                                 output     ='both',
                                 parameters =[{'robot_description': Command(['xacro', ' ', xacro_file])
                                }])

    # Spawn the robot in Gazebo
    spawn_entity_robot = Node(package     ='gazebo_ros',
                              executable  ='spawn_entity.py',
                              arguments   = ['-entity', 'learm_ros2', '-topic', 'robot_description'],
                              output      ='screen')

    # Gazebo
    world_file_name = 'table_world.world'
    world = os.path.join(get_package_share_directory('learm_ros2'), 'worlds', world_file_name)
    gazebo_node = ExecuteProcess(cmd=['gazebo', '--verbose', world,'-s', 'libgazebo_ros_factory.so'], output='screen')

    # These are not working....

    # load_joint_state_broadcaster = ExecuteProcess(
    #                                   cmd=['ros2', 'control', 'load_controller', '--set-state', 'start','joint_state_broadcaster'],
    #                                   output='screen')

    # load_joint_trajectory_controller = ExecuteProcess(
    #                                   cmd=['ros2', 'control', 'load_controller', '--set-state', 'start', 'joint_trajectory_controller'],
    #                                   output='screen')

    return LaunchDescription([robot_state_publisher, spawn_entity_robot, gazebo_node,   ])
Complete log:

ros2 launch learm_ros2 my_gazebo_controller.launch.py
[INFO] [launch]: All log files can be found below /home/mk/.ros/log/2024-04-11-09-15-23-807156-mk-5577
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [robot_state_publisher-1]: process started with pid [5579]
[INFO] [spawn_entity.py-2]: process started with pid [5581]
[INFO] [gazebo-3]: process started with pid [5583]
[robot_state_publisher-1] [INFO] [1712819724.075684381] [robot_state_publisher]: got segment base_link
[robot_state_publisher-1] [INFO] [1712819724.075815637] [robot_state_publisher]: got segment finger_left_link
[robot_state_publisher-1] [INFO] [1712819724.075825642] [robot_state_publisher]: got segment finger_right_link
[robot_state_publisher-1] [INFO] [1712819724.075831179] [robot_state_publisher]: got segment forearm_link
[robot_state_publisher-1] [INFO] [1712819724.075835984] [robot_state_publisher]: got segment grip_left_link
[robot_state_publisher-1] [INFO] [1712819724.075840953] [robot_state_publisher]: got segment grip_right_link
[robot_state_publisher-1] [INFO] [1712819724.075845599] [robot_state_publisher]: got segment hand_link
[robot_state_publisher-1] [INFO] [1712819724.075850323] [robot_state_publisher]: got segment humerus_link
[robot_state_publisher-1] [INFO] [1712819724.075855091] [robot_state_publisher]: got segment shoulder_link
[robot_state_publisher-1] [INFO] [1712819724.075859804] [robot_state_publisher]: got segment tendon_left_link
[robot_state_publisher-1] [INFO] [1712819724.075864539] [robot_state_publisher]: got segment tendon_right_link
[robot_state_publisher-1] [INFO] [1712819724.075869254] [robot_state_publisher]: got segment world
[robot_state_publisher-1] [INFO] [1712819724.075873869] [robot_state_publisher]: got segment wrist_link
[gazebo-3] Gazebo multi-robot simulator, version 11.10.2
[gazebo-3] Copyright (C) 2012 Open Source Robotics Foundation.
[gazebo-3] Released under the Apache 2 License.
[gazebo-3] http://gazebosim.org
[gazebo-3]
[spawn_entity.py-2] [INFO] [1712819724.364785269] [spawn_entity]: Spawn Entity started
[spawn_entity.py-2] [INFO] [1712819724.365130349] [spawn_entity]: Loading entity published on topic robot_description
[spawn_entity.py-2] /opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/qos.py:307: UserWarning: DurabilityPolicy.RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL is deprecated. Use DurabilityPolicy.TRANSIENT_LOCAL instead.
[spawn_entity.py-2]   warnings.warn(
[spawn_entity.py-2] [INFO] [1712819724.366856777] [spawn_entity]: Waiting for entity xml on robot_description
[gazebo-3] Gazebo multi-robot simulator, version 11.10.2
[gazebo-3] Copyright (C) 2012 Open Source Robotics Foundation.
[gazebo-3] Released under the Apache 2 License.
[gazebo-3] http://gazebosim.org
[gazebo-3]
[spawn_entity.py-2] [INFO] [1712819724.472695945] [spawn_entity]: Waiting for service /spawn_entity, timeout = 30
[spawn_entity.py-2] [INFO] [1712819724.473441392] [spawn_entity]: Waiting for service /spawn_entity
[gazebo-3] [INFO] [1712819724.887534290] [gazebo_ros_node]: ROS was initialized without arguments.
[spawn_entity.py-2] [INFO] [1712819725.229984757] [spawn_entity]: Calling service /spawn_entity
[spawn_entity.py-2] [INFO] [1712819725.546704340] [spawn_entity]: Spawn status: SpawnEntity: Successfully spawned entity [learm_ros2]
[INFO] [spawn_entity.py-2]: process has finished cleanly [pid 5581]
[gazebo-3] [Msg] Waiting for master.
[gazebo-3] [Msg] Connected to gazebo master @ http://127.0.0.1:11345
[gazebo-3] [Msg] Publicized address: 192.168.1.49
[gazebo-3] [Msg] Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
[gazebo-3] [Wrn] [Event.cc:61] Warning: Deleting a connection right after creation. Make sure to save the ConnectionPtr from a Connect call
[gazebo-3] [INFO] [1712819726.206974140] [gazebo_ros2_control]: Loading gazebo_ros2_control plugin
[gazebo-3] [INFO] [1712819726.208899511] [gazebo_ros2_control]: Starting gazebo_ros2_control plugin in namespace: /
[gazebo-3] [INFO] [1712819726.209095469] [gazebo_ros2_control]: Starting gazebo_ros2_control plugin in ros 2 node: gazebo_ros2_control
[gazebo-3] [INFO] [1712819726.210755756] [gazebo_ros2_control]: connected to service!! robot_state_publisher
[gazebo-3] [INFO] [1712819726.211154584] [gazebo_ros2_control]: Received urdf from param server, parsing...
[gazebo-3] [INFO] [1712819726.211194783] [gazebo_ros2_control]: Loading parameter files /home/mk/ros2_ws/install/learm_ros2_description/share/learm_ros2_description/config/combined_controllers.yaml
[gazebo-3] [INFO] [1712819726.219434473] [gazebo_ros2_control]: Loading joint: shoulder_pan...(#hiding other joints for log)
[gazebo-3] [INFO] [1712819726.221340144] [resource_manager]: Initialize hardware 'GazeboSystem'
[gazebo-3] [INFO] [1712819726.221351965] [resource_manager]: Successful initialization of hardware 'GazeboSystem'
[gazebo-3] [INFO] [1712819726.221431741] [gazebo_ros2_control]: Loading controller_manager
[gazebo-3] [Msg] Waiting for master.
[gazebo-3] [Msg] Connected to gazebo master @ http://127.0.0.1:11345
[gazebo-3] [Msg] Publicized address: 192.168.1.49
[gazebo-3] [Msg] Loading world file [/home/mk/ros2_ws/install/learm_ros2/share/learm_ros2/worlds/table_world.world]
[gazebo-3] [Err] [Model.cc:1160] Exception occured in the Load function of plugin with name[gazebo_ros2_control] and filename[libgazebo_ros2_control.so]. This plugin will not run.
[gazebo-3] [Err] [Connection.cc:547] Connection[16] Closed during Read
[gazebo-3] [Err] [TransportIface.cc:385] Unable to read from master
[ERROR] [gazebo-3]: process has died [pid 5583, exit code 255, cmd 'gazebo --verbose /home/mk/ros2_ws/install/learm_ros2/share/learm_ros2/worlds/table_world.world -s libgazebo_ros_factory.so'].
[gazebo-3]
[gazebo-3]
^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)
[robot_state_publisher-1] [INFO] [1712819751.927358582] [rclcpp]: signal_handler(signum=2)
[INFO] [robot_state_publisher-1]: process has finished cleanly [pid 5579]
controller.yaml:

controller_manager:
  ros__parameters:
    update_rate: 30.0
    use_sim_time: true

    joint_state_controller:
      type: joint_state_controller/JointStateController
      publish_rate: 50.0
    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster
    arm_controller:
      type: joint_trajectory_controller/JointTrajectoryController

arm_controller:
  ros__parameters:
    publish_rate: 50.0
    base_frame_id: base_link
    command_interfaces:
      - position
    state_interfaces:
      - position
      - velocity
    joints:
      - shoulder_pan
      - shoulder_lift
      - elbow
      - wrist_flex
      - wrist_roll
      - grip_left
And finally my urdf.xacro file that has included <xacro:include filename = "ros2_control.xacro" /> and my ros2_control.xacro: has

<?xml version="1.0" ?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">

<ros2_control name="GazeboSystem" type="system">
  <hardware>
    <plugin>gazebo_ros2_control/GazeboSystem</plugin>
  </hardware>
<joint name="shoulder_pan">
<command_interface name="position">
  <param name="min">-1.57</param>
  <param name="max">1.57</param>
</command_interface>
<command_interface name="velocity">
  <param name="min">-0.5</param>
  <param name="max">0.5</param>
</command_interface>
<command_interface name="effort">
  <param name="min">-1000</param>
  <param name="max">1000</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
and all the info relevant to the joints, and at the end:
<plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">

  <parameters>$(find learm_ros2_description)/config/combined_controllers.yaml</parameters>

</plugin>
EDIT:

I used the same launch.py file as in [cart_example_position.launch.py]4.

Running ros2 launch gazebo_ros2_control_demos cart_example_position.launch.py and ros2 run gazebo_ros2_control_demos example_position works perfectly fine. copying all the contents, creating a new.run.launch.py file and editing

gazebo_ros2_control_demos_path = os.path.join(
        get_package_share_directory('learm_ros2'))

    xacro_file = os.path.join(gazebo_ros2_control_demos_path,
                              'urdf',
                              'learm-gazebo-xacroTurdf.urdf')
Still gives me errors.

[gazebo_ros2_control]: Loading controller_manager
    [ERROR] [gzserver-1]: process has died [pid 23581, exit code -11, cmd 'gzserver -slibgazebo_ros_init.so -slibgazebo_ros_factory.so -slibgazebo_ros_force_system.so'].
    [ros2-5] Could not contact service /controller_manager/load_controller
    [ERROR] [ros2-5]: process has died [pid 23669, exit code 1, cmd 'ros2 control load_controller --set-state active joint_state_broadcaster'].
    [INFO] [ros2-6]: process started with pid [23794]
    [ros2-6] Could not contact service /controller_manager/load_controller
    [ERROR] [ros2-6]: process has died [pid 23794, exit code 1, cmd 'ros2 control load_controller --set-state active joint_trajectory_controller'].
    ^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)
    [robot_state_publisher-3] [INFO] [1712843686.506268158] [rclcpp]: signal_handler(signum=2)
    [INFO] [robot_state_publisher-3]: process has finished cleanly [pid 23585]
    [INFO] [gzclient-2]: process has finished cleanly [pid 23583]
So I am currently lost. Editing my controllers.yaml to the yaml file they use, gives me different errors, but as if it managed to connect! So my errors are probably in the controller.yaml or urdf.

Explanation: With apt, we need to check steps that install ROS 2 package. It may also provide a Gazebo plugin which instantiates a ros2_control controller manager and connects it to a Gazebo model.

$\begingroup$

If you install gazebo_ros2_control via apt, this should be fine and all
dependencies should be installed. Can you follow the steps described
https://control.ros.org/humble/doc/ros2_control_demos/example_9/doc/userdoc.html
or [ here
](https://control.ros.org/humble/doc/gazebo_ros2_control/doc/index.html) ?

Note that you have to source ` source /usr/share/gazebo/setup.sh ` , but from
your console output it seems that gazebo itself is loading fine.


Question:
Running ros1 packages with ros2 data

I'm trying to run different lidar based SLAM methods in order to produce a map of an environment. I've recorded my data in both .db3 and .mcap formats, but a lot of SLAM methods (an example being Interactive SLAM by SMRT-AIST) are only implemented on ROS1 with the .bag format. Is there any way to either change the modern formats to .bag or is there another way to use these older packages with ROS2 datatypes?

Explanation: One option is to find code that can convert between rosbag1 and rosbag2.

$\begingroup$

As discussed in this link: [
https://answers.ros.org/question/352466/converting-ros2-bag-to-ros1-bag/
](https://answers.ros.org/question/352466/converting-ros2-bag-to-ros1-bag/) it
seems that you can use ternaris/rosbags to convert ROS2 bag to ROS1. You can
also take a look in this discussion. [
https://answers.ros.org/question/388484/how-to-read-ros2-bag-file-in-ros1/
](https://answers.ros.org/question/388484/how-to-read-ros2-bag-file-in-ros1/)

In case of slam method for ROS2 with 3D lidar, [ LIO-slam
](https://github.com/TixiaoShan/LIO-SAM) have support for ROS2. There is
another option like using ROSbridge which I'm not sure about the changes in
data rate but you can look into.


Question:
ldlidar ros 2, colcon build error, pthread mutex init/lock/unlock not declared

So i am trying to use the LD19 Lidar from ldrobot with ros2_iron. I am following this tutorial: https://github.com/ldrobotSensorTeam/ldlidar_stl_ros2. When i enter colcon build in the console it runs to 87% and then fails. I am using Rasbian OS on Raspberry Pi 5. The console shows this:

Starting >>> ldlidar_stl_ros2
--- stderr: ldlidar_stl_ros2
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp: In member function 'void LogModule::InitLock()':
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp:172:3: error: 'pthread_mutex_init' was not declared in this scope; did you mean 'pthread_mutex_t'?
  172 |   pthread_mutex_init(&mutex_lock_,NULL);
      |   ^~~~~~~~~~~~~~~~~~
      |   pthread_mutex_t
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp: In member function 'void LogModule::RealseLock()':
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp:180:9: error: 'pthread_mutex_unlock' was not declared in this scope; did you mean 'pthread_mutex_t'?
  180 |         pthread_mutex_unlock(&mutex_lock_);
      |         ^~~~~~~~~~~~~~~~~~~~
      |         pthread_mutex_t
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp: In member function 'void LogModule::Lock()':
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp:188:9: error: 'pthread_mutex_lock' was not declared in this scope; did you mean 'pthread_mutex_t'?
  188 |         pthread_mutex_lock(&mutex_lock_);
      |         ^~~~~~~~~~~~~~~~~~
      |         pthread_mutex_t
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp: In member function 'void LogModule::UnLock()':
/home/pi/ldlidar_ros2_ws/src/ldlidar_stl_ros2/ldlidar_driver/src/logger/log_module.cpp:196:9: error: 'pthread_mutex_unlock' was not declared in this scope; did you mean 'pthread_mutex_t'?
  196 |         pthread_mutex_unlock(&mutex_lock_);
      |         ^~~~~~~~~~~~~~~~~~~~
      |         pthread_mutex_t
gmake[2]: *** [CMakeFiles/ldlidar_stl_ros2_node.dir/build.make:132: CMakeFiles/ldlidar_stl_ros2_node.dir/ldlidar_driver/src/logger/log_module.cpp.o] Fehler 1
gmake[2]: *** Es wird auf noch nicht beendete Prozesse gewartet....
gmake[1]: *** [CMakeFiles/Makefile2:137: CMakeFiles/ldlidar_stl_ros2_node.dir/all] Fehler 2
gmake: *** [Makefile:146: all] Fehler 2
---
Failed   <<< ldlidar_stl_ros2 [12.7s, exited with code 2]

Summary: 0 packages finished [13.0s]
  1 package failed: ldlidar_stl_ros2
  1 package had stderr output: ldlidar_stl_ros2
```

Explanation: The problem is related to a missing include of the required header file for the functions mentioned in the compiler output. We can check pthread_mutex_init for the required #include.

$\begingroup$

The problem is a missing include of the required header file for the functions
mentioned in the compiler output. See e.g. [ ` pthread_mutex_init `
](https://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_mutex_init.html)
for the required ` #include ` .

This can be traced back to [ log_module.h
](https://github.com/ldrobotSensorTeam/ldlidar_stl_ros2/blob/master/ldlidar_driver/include/logger/log_module.h#L37C1-L44C33)
from the ` #include "log_module.h" ` in [ log_module.cpp
](https://github.com/ldrobotSensorTeam/ldlidar_stl_ros2/blob/master/ldlidar_driver/src/logger/log_module.cpp#L18)
of the ` ldlidar_stl_ros2 ` project:

    #ifndef LINUX
    #include <windows.h>
    #else
    //#include <pthread.h> <-- uncomment this line
    #include <stdarg.h>
    #define printf_s(fileptr,str)  (fprintf(fileptr,"%s",str))
    #define __in
    #endif // ??????????????????????


Question:
Nav2 Custom Costmap plugin subscription [closed]

Closed 5 days ago.

I am trying to write a costmap plugin for nav2 and i need to get a specific data from a topic but i couldnt create and spin the subscription inside the plugin. (I need coordinate points to create an obstacle at those points)

Explanation: To add a subscription, we can use node->create_subscription in static layer.

$\begingroup$

Could you elaborate the issue further with any relevant logs? As far as I know
if you're running this with the layers of the global costmap, you should be
able to add a subscription using ` node->create_subscription ` . This is how
it's done in the ` static_layer ` plugin for ROS 2 Humble. You can find it
here: [ https://github.com/ros-
planning/navigation2/blob/humble/nav2_costmap_2d%2Fplugins%2Fstatic_layer.cpp
](https://github.com/ros-
planning/navigation2/blob/humble/nav2_costmap_2d%2Fplugins%2Fstatic_layer.cpp)


Question:
Trouble launching moveit2 configurations

Hi I am using ROS2 humble with moveit2. I created a configuration with setup_assistant of moveit2. However, when I try to launch the demo launch file created by it. It gaves me the error:

[ERROR] [launch]: Caught exception in launch (see debug for traceback): 'capabilities'

I could not find anything related to capabilities. What does it mean? May someone please help me?

Explanation: It is related to capabilities in default launch argument of moveit2.

$\begingroup$

From what it looks like, this is a known issue for Humble. You will find more
discussion on [ this
](https://robotics.stackexchange.com/questions/109885/ros2-error-launch-
capabilities) thread.

**UPDATE**

I don't know if this is going to solve your issue, but I'm taking a shot in
the dark regardless. I checked the recent pull requests for MoveIt2, and
someone has sent in a PR which might correspond to what you want. [ Here
](https://github.com/ros-
planning/moveit2/pull/2697/commits/b634e96c2f080ab38780668e85e974351978106d)
is the PR in question.

From what I suspect, there is some misdefinition of the default value of the
"capabilities" launch argument, which the PR aims to fix by declaring proper
default argument. You may try this out to see if that fixes your issue.


Question:
Is it possible to modify or extend pre-existing Gazebo Sim plugins?

Question
Is it possible to modify or extend a pre-existing Gazebo Sim (Garden) plugin, such as the gz-sim-multicopter-control-system plugin to publish the quadcopter rotor velocities as Gazebo topics? How can this be done?

Summary
I am using Gazebo Garden (gz-sim7) to simulate a quadcopter. I have implemented two of Gazebo's pre-existing plugins for the quadcopter model flight. The plugins are gz-sim-multicopter-motor-model-system and gz-sim-multicopter-control-system, and their use in the model.sdf file is shown below. You can also find a more detailed version of the plugin implementation at multicopter_velocity_control.sdf.

<?xml version="1.0"?>
<sdf version="1.8">
    <model name="quadcopter">
        <!-- The links of the quadcopter model -->
        <!-- The links of the quadcopter model -->

        <!-- Multicopter Motor Model plugin for each rotor -->
        <!-- Rotor 0 -->
        <plugin
            filename="gz-sim-multicopter-motor-model-system"
            name="gz::sim::systems::MulticopterMotorModel">
            <robotNamespace>quadcopter</robotNamespace>
            <jointName>rotor_0_joint</jointName>
            <linkName>rotor_0</linkName>

            <!-- More Multicopter Motor Model plugin components -->

            <commandSubTopic>gazebo/command/motor_speed</commandSubTopic>
            <actuator_number>0</actuator_number>
            <motorSpeedPubTopic>motor_speed/0</motorSpeedPubTopic>
            <motorType>velocity</motorType>
        </plugin>

        <!-- Similarly define Rotor 1, Rotor 2 and Rotor 3 -->

        <!-- Multicopter Control plugin -->
        <plugin
            filename="gz-sim-multicopter-control-system"
            name="gz::sim::systems::MulticopterVelocityControl">
            <robotNamespace>quadcopter</robotNamespace>
            <comLinkName>base_link</comLinkName>
            <commandSubTopic>gazebo/command/twist</commandSubTopic>
            <enableSubTopic>enable</enableSubTopic>

            <!-- More Multicopter Control plugin components -->

            <rotorConfiguration>
                <rotor>
                    <jointName>rotor_0_joint</jointName>

                    <!-- More Multicopter Control plugin rotor configuration components -->

                </rotor>

                <!-- Similarly configure Rotor 1, Rotor 2 and Rotor 3 -->

            </rotorConfiguration>
        </plugin>
    </model>
</sdf>
Is it possible to publish the rotor velocities using Gazebo topics? If not, is it possible to modify or extend the functionalities of the pre-existing plugins to publish the rotor velocities to topics after calculating them?

Further Info
I am using Gazebo Garden and ROS 2 Humble for this project. I have used the Gazebo's ros_gz_project_template as a starting framework for my project. There are four main packages in the workspace (my_package_application, my_package_bringup, my_package_description and my_package_gazebo), and the src directory looks something like this.

src
├── ros_gz
├── sdformat_urdf
├── my_package_application
├── my_package_bringup
├── my_package_description
│   ├── CMakeLists.txt
│   ├── hooks
│   ├── include
│   │   └── my_package_description
│   │       └── MotorVelocityPublisher.hh
│   ├── models
│   │   └──quadcopter
│   │       ├── model.config
│   │       └── model.sdf
│   ├── package.xml
│   └── src
│       └── MotorVelocityPublisher.cc
└── my_package_gazebo
    ├── CMakeLists.txt
    ├── hooks
    ├── include
    ├── package.xml
    ├── src
    └── worlds
        └── quadcopter.sdf
My initial idea was to create a custom plugin called MotorVelocityPublisher which would access the rotor velocity data from the gz-sim-multicopter-control-system but the plugin doesn't make the rotor velocity data easily accessible.

I have also thought about modifying or extending the existing gz-sim-multicopter-control-system plugin to publish the rotor velocity data. More specifically, creating a new RotorVelocitiesComponent.hh component to store the rotor velocity values.

// RotorVelocitiesComponent.hh

#ifndef ROTOR_VELOCITIES_COMPONENT_HH_
#define ROTOR_VELOCITIES_COMPONENT_HH_

#include <gz/sim/components/Component.hh>

namespace multicopter_control
{
    // Define a new Gazebo component to store rotor velocities
    GZ_SIM_DEFINE_COMPONENT(RotorVelocities, std::vector<double>)
}

#endif  // ROTOR_VELOCITIES_COMPONENT_HH_
Extending the PreUpdate method in the MulticopterVelocityControl.cc library to save the rotor velocity values into the component.

// Add the component header in MulticopterVelocityControl.cc
#include "RotorVelocitiesComponent.hh"

// Existing Multicopter Velocity Control methods

void MulticopterVelocityControl::PreUpdate(
    const UpdateInfo &_info,
    EntityComponentManager &_ecm)
{
    GZ_PROFILE("MulticopterVelocityControl::PreUpdate");

    // Existing code for the Multicopter Velocity Control Pre-Update

    this->velocityController->CalculateRotorVelocities(*frameData, cmdVel,
                                                       this->rotorVelocities);

    // New code to store the rotor velocities in the component
    auto rotorVelocitiesComp = _ecm.Component<multicopter_control::RotorVelocities>(this->model.Entity());
    if (!rotorVelocitiesComp)
    {
        _ecm.CreateComponent(this->model.Entity(), multicopter_control::RotorVelocities(this->rotorVelocities));
    }
    else
    {
        rotorVelocitiesComp->Data() = this->rotorVelocities;
    }   // New code ends here

    this->PublishRotorVelocities(_ecm, this->rotorVelocities);
}
The problem with this solution is that I don't know how to correctly save the extended gz-sim-multicopter-control-system plugin, build it, link it, etc. I'm not sure if this method will work or not.

Explanation: We need to modify the MulticopterVelocityControl.hh and MulticopterVelocityControl.cc files to advertise the rotor velocity data through a Gazebo topic.

$\begingroup$

My solution to this question is slightly different to the solutions I proposed
in my question. Instead of creating a new ` RotorVelocitiesComponent.hh `
component to store the rotor velocity values, I modified the [ `
MulticopterVelocityControl.hh ` ](https://github.com/gazebosim/gz-sim/blob/gz-
sim7/src/systems/multicopter_control/MulticopterVelocityControl.hh) and [ `
MulticopterVelocityControl.cc ` ](https://github.com/gazebosim/gz-sim/blob/gz-
sim7/src/systems/multicopter_control/MulticopterVelocityControl.cc) files to
advertise the rotor velocity data through a Gazebo topic.

##  Method

I copied the plugin source files into my package, similar to how it is done in
Gazebo's [ ` ros_gz_project_template `
](https://github.com/gazebosim/ros_gz_project_template) . My ` src ` directory
now looks something like this.

    src
    ├── ros_gz
    ├── sdformat_urdf
    ├── my_package_application
    ├── my_package_bringup
    ├── my_package_description
    │   ├── CMakeLists.txt
    │   ├── hooks
    │   ├── include
    │   │   └── my_package_description
    │   │       ├── Common.hh
    │   │       ├── LeeVelocityController.hh
    │   │       ├── MulticopterVelocityControl.hh
    │   │       └── Parameters.hh
    │   ├── models
    │   │   └──quadcopter
    │   │       ├── model.config
    │   │       └── model.sdf
    │   ├── package.xml
    │   └── src
    │       ├── Common.cc
    │       ├── LeeVelocityController.cc
    │       └── MulticopterVelocityControl.cc
    └── my_package_gazebo

The next step is to change the package ` CMakeLists.txt ` file to build the
plugin correctly.

    cmake_minimum_required(VERSION 3.8)
    project(my_package_description)

    # other ROS 2 CMakeLists.txt template code

    # find dependencies
    find_package(ament_cmake REQUIRED)
    find_package(Eigen3 REQUIRED)

    # find the needed plugin dependencies
    find_package(gz-cmake3 REQUIRED)
    find_package(gz-plugin2 REQUIRED COMPONENTS register)
    set(GZ_PLUGIN_VER ${gz-plugin2_VERSION_MAJOR})
    find_package(gz-common5 REQUIRED COMPONENTS profiler)
    set(GZ_COMMON_VER ${gz-common5_VERSION_MAJOR})
    find_package(gz-transport12 REQUIRED)
    set(GZ_TRANSPORT_VER ${gz-transport12_VERSION_MAJOR})
    find_package(gz-msgs9 REQUIRED)
    set(GZ_MSGS_VER ${gz-msgs9_VERSION_MAJOR})

    # set the right variables for gazebo garden
    find_package(gz-sim7 REQUIRED)
    set(GZ_SIM_VER ${gz-sim7_VERSION_MAJOR})
    message(STATUS "Compiling against Gazebo Garden")

    # define a library target named 'MyModifiedPlugin'.
    add_library(MyModifiedPlugin
      SHARED
      src/MulticopterVelocityControl.cc
      src/Common.cc
      src/LeeVelocityController.cc
    )

    # specify 'include' as the include directory for compiling
    # the 'MyModifiedPlugin' target.
    target_include_directories(
      MyModifiedPlugin PRIVATE include
    )

    # specify the gazebo libraries needed when linking the 'MyModifiedPlugin' target.
    target_link_libraries(MyModifiedPlugin PRIVATE
      gz-transport${GZ_TRANSPORT_VER}::gz-transport${GZ_TRANSPORT_VER}
      gz-msgs${GZ_MSGS_VER}::gz-msgs${GZ_MSGS_VER}
      gz-plugin${GZ_PLUGIN_VER}::gz-plugin${GZ_PLUGIN_VER}
      gz-common${GZ_COMMON_VER}::gz-common${GZ_COMMON_VER}
      gz-sim${GZ_SIM_VER}::gz-sim${GZ_SIM_VER}
      Eigen3::Eigen
    )

    # copy the compiled libraries of 'MyModifiedPlugin' targets to the
    # subfolder 'lib/my_package_description' of the install directory.
    install(TARGETS MyModifiedPlugin
      DESTINATION lib/${PROJECT_NAME}
    )

    # other ROS 2 CMakeLists.txt template code
    # any other custom CMakeLists.txt code

    # I also use hooks to guide gazebo concerning where to look
    # for resources and plugins

    ament_package()

Now it's just a matter of correctly modifying the pre-existing plugin source
files and correctly using the plugin in the ` model.sdf ` file.

Make sure to change any file inclusion directives to specify the correct
locations of the header files. An example for this case would be changing the
following inclusion directives

    #include "Common.hh"
    #include "LeeVelocityController.hh"
    #include "MulticopterVelocityControl.hh"
    #include "Parameters.hh"

to the following inclusion directives.

    #include "my_package_description/Common.hh"
    #include "my_package_description/LeeVelocityController.hh"
    #include "my_package_description/MulticopterVelocityControl.hh"
    #include "my_package_description/Parameters.hh"

The majority of plugin modifications were done in the [ `
MulticopterVelocityControl.hh ` ](https://github.com/gazebosim/gz-sim/blob/gz-
sim7/src/systems/multicopter_control/MulticopterVelocityControl.hh) and [ `
MulticopterVelocityControl.cc ` ](https://github.com/gazebosim/gz-sim/blob/gz-
sim7/src/systems/multicopter_control/MulticopterVelocityControl.cc) files.
Useful inclusion directives were added to the [ `
MulticopterVelocityControl.hh ` ](https://github.com/gazebosim/gz-sim/blob/gz-
sim7/src/systems/multicopter_control/MulticopterVelocityControl.hh) .

    // Pre-existing `MulticopterVelocityControl.hh` inclusion directives

    #include <string>

    // New msg header for rotor velocity variables
    #include <gz/msgs/float_v.pb.h>

    #include <gz/msgs/actuators.pb.h>

    // Remaining pre-existing `MulticopterVelocityControl.hh` inclusion directives

Additional variables were added for the plugin modification.

    namespace gz
    {
    namespace sim
    {
    inline namespace GZ_SIM_VERSION_NAMESPACE
    {
    namespace systems
    {
        class MulticopterVelocityControl
            :   public System,
                public ISystemConfigure,
                public ISystemPreUpdate
        {

            // Pre-existing `MulticopterVelocityControl.hh` declarations

            /// \brief Gazebo communication node.
            private: transport::Node node;

            /// \brief New topic for rotor velocities.
            private: std::string rotorVelocityPubTopic{"rotor_velocities"};

            /// \brief New rotor velocities publisher.
            private: transport::Node::Publisher rotorVelocityPub;

            /// \brief New variable that holds rotor velocities
            /// computed by the controller to later be published.
            private: gz::msgs::Float_V rotorVelocityPubMsg;

            // Remaining pre-existing `MulticopterVelocityControl.hh` declarations

        };
    }
    }
    }
    }

    #endif

The rest of the changes were made in [ ` MulticopterVelocityControl.cc `
](https://github.com/gazebosim/gz-sim/blob/gz-
sim7/src/systems/multicopter_control/MulticopterVelocityControl.cc) . First,
add new logic to the ` MulticopterVelocityControl::Configure ` method to
initialise the topic advertiser.

    void MulticopterVelocityControl::Configure(const Entity &_entity,
                                               const std::shared_ptr<const sdf::Element> &_sdf,
                                               EntityComponentManager &_ecm,
                                               EventManager & /*_eventMgr*/)
    {

        // Pre-existing Configure method logic

        sdfClone->Get<std::string>("enableSubTopic",
                                    this->enableSubTopic, this->enableSubTopic);
        this->enableSubTopic = transport::TopicUtils::AsValidTopic(
            this->enableSubTopic);
        if (this->enableSubTopic.empty())
        {
            gzerr << "Invalid enable sub-topic." << std::endl;
            return;
        }

        // New code for rotor velocity publisher topic name
        sdfClone->Get<std::string>("rotorVelocityPubTopic",
                                    this->rotorVelocityPubTopic, this->rotorVelocityPubTopic);
        this->rotorVelocityPubTopic = transport::TopicUtils::AsValidTopic(
            this->rotorVelocityPubTopic);
        if (this->rotorVelocityPubTopic.empty())
        {
            gzerr << "Invalid rotor velocity pub-topic." << std::endl;
            return;
        }   // New code ends here

        // Pre-existing code to subscribe to actuator command messages

        // New initialise the publisher for rotor velocities
        std::string rotorVelocityTopic{this->robotNamespace + "/" + this->rotorVelocityPubTopic};
        this->rotorVelocityPub = this->node.Advertise<gz::msgs::Float_V>(rotorVelocityTopic);
        gzmsg << "MulticopterVelocityControl publishing Double messages on ["
                << rotorVelocityTopic << "]" << std::endl;  // New code ends here

        // Remaining pre-existing Configure method logic

        this->initialized = true;
    }

Finally, add additional logic to [ ` MulticopterVelocityControl.cc `
](https://github.com/gazebosim/gz-sim/blob/gz-
sim7/src/systems/multicopter_control/MulticopterVelocityControl.cc) to publish
the rotor velocities. I chose to do this in the `
MulticopterVelocityControl::PublishRotorVelocities ` function to prevent the
simulation from breaking as much as possible.

    void MulticopterVelocityControl::PublishRotorVelocities(
        EntityComponentManager &_ecm,
        const Eigen::VectorXd &_vels)
    {

        // Pre-existing PublishRotorVelocities method logic

        // New code to clear previous data in the message
        // to prepare for new rotor velocities
        this->rotorVelocityPubMsg.clear_data();

        for (int i = 0; i < this->rotorVelocities.size(); ++i)
        {

            // Pre-existing logic to set rotorVelocitiesMsg velocities

            // New code to add each velocity value to the rotorVelocityPubMsg
            this->rotorVelocityPubMsg.add_data(_vels(i));
        }

        // New code to publish rotor velocities using rotorVelocityPub publisher
        this->rotorVelocityPub.Publish(this->rotorVelocityPubMsg);

        // Remaining pre-existing PublishRotorVelocities method logic

    }

The new plugin implementation can be done by directly specifying the plugin `
.so ` file location, similarly as described in one of the [ answers
](https://robotics.stackexchange.com/a/110132/40013) to this question.

    <plugin
        filename="libMyModifiedPlugin"
        name="gz::sim::v7::systems::MulticopterVelocityControl">

    </plugin>

Gazebo can also easily find the plugin in the ` lib/my_package_description `
folder if you use hook files to widen Gazebo's search. The hook files will
need to be specified in ` CMakeLists.txt ` . You can also expand Gazebo's
search by setting the GZ_SIM_SYSTEM_PLUGIN_PATH environment variable using the
command.

    export GZ_SIM_SYSTEM_PLUGIN_PATH=${GZ_SIM_SYSTEM_PLUGIN_PATH}:<path-to-your-plugin-library>

So far the simulation has been running well, without breaking.


Question:
How to executing a callback function with multiple threads in ROS2

I have a camera_node publishing image to processer_node, images are published faster than they are processed.

When a new image appears in my image queue but the previous image is still processing, split a thread to bind a callback function to process the new image.

Is there any way to this?

Explanation: We can process multiple msgs coming on the same topic in multiple threads, which can be done using callback group and executor functionalities of ros2

$\begingroup$

Yes you can process multiple msgs coming on the same topic in multiple threads
and you do not need to handle thread spinning, it can be done using ` callback
group ` and ` executor ` functionalities of ros2. To achieve this you can
follow these steps

  * Define a [ multithreaded executor ](https://docs.ros.org/en/foxy/Concepts/About-Executors.html#callback-groups:%7E:text=The-,Multi%2DThreaded%20Executor,-creates%20a%20configurable) in your main function

> ` rclcpp::executors::MultiThreadedExecutor executor; `

  * Add your node to this executor

> ` executor->add_node(node); `

  * Now inside your node define a reentrant callback group (this allows parallel execution) and give this callback group in your topic subscription
    * ` my_callback_group = create_callback_group(rclcpp::CallbackGroupType::Reentrant); `
    * ` rclcpp::SubscriptionOptions options; `
    * ` options.callback_group = my_callback_group; `
    * ` my_subscription = create_subscription<type>("/topic",rclcpp::SensorDataQoS(),callback, options); `

This should work for your use case. For further understanding check out the [
executor ](https://docs.ros.org/en/foxy/Concepts/About-
Executors.html#callback-groups) concept on ros 2 wiki.


Question:
What is the alternative to a <ros2arduino.h>

I am using Arduino Mega.

I wanted to configure it to create a ros2 topic using the ros2arduino header.

However, I found out that the header cannot be used because it can only be supported from 32bit or higher

In this case, what idea can you recommend?

Currently, the board is connected to I2C communication, and it seems that the main board will also be connected to Arduino through I2C communication. (Currently, I am connecting from Ubuntu installed on my PC for testing purposes.)

Thank you so much for reading.

Explanation: One option is to try Serial. We can check examples of interfaces about how to communicate serially with Ros2.

$\begingroup$

If you don't have to use I2C, why don't you try Serial? Here seems to be an
example of an interface that can communicate serially with Ros2.

[ https://github.com/AnrdyShmrdy/ros2_serial_interface
](https://github.com/AnrdyShmrdy/ros2_serial_interface)


Question:
How do I post-process rviz images? [closed]

I've made a gazebo envirnment and successfully visualized the cam image with rviz. However I wanted to do some post process to make it simulate the result of image segmentation and send it back to rviz. Is there any similiar methods or tutorials for this? Maybe a way to import the node to python?

Explanation: We may find packages to process images in ros.

$\begingroup$

There are so many nice tutorials that you could follow. I am listing down some
of them below:

[ http://wiki.ros.org/image_proc ](http://wiki.ros.org/image_proc)

[ https://roboticsbackend.com/ros-import-python-module-from-another-package/
](https://roboticsbackend.com/ros-import-python-module-from-another-package/)

And for the last part of your question, see this.

[ https://gist.github.com/zkytony/fb7616b745d77025f6abe919c41f8ea4
](https://gist.github.com/zkytony/fb7616b745d77025f6abe919c41f8ea4)


Question:
How to add an additional argument in a ROS2 cpp callback

I want to add an additional argument in a callback function for rclcpp, e.g. callback(msg, additional_argument).

I can do it in python. There the solution would be:

import rclpy
from std_msgs.msg import String

def callback(data, source):
    rospy.loginfo(f"I heard '{data.data}' from {source}")

def listener():
    rclpy.init()
    node = rclpy.create_node('listener')

    node.create_subscription(String, 'chatter_1', lambda msg: callback(msg, 1), 10)
    node.create_subscription(String, 'chatter_2', lambda msg: callback(msg, 2), 10)

    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    listener()
I also did it in ROS1 with boost::bind. I tried to do it in ROS2 with std::bind, but it did not work.

Does someone know the exact syntax?

Explanation: We can check examples of callback implemented in ros2.

$\begingroup$

You can find a specific example in the ros2 examples repo: [
https://github.com/ros2/examples/blob/rolling/rclcpp/topics/minimal_subscriber/lambda.cpp
](https://github.com/ros2/examples/blob/rolling/rclcpp/topics/minimal_subscriber/lambda.cpp)

It can be done even shorter:

    #include <memory>

    #include "rclcpp/rclcpp.hpp"
    #include "std_msgs/msg/string.hpp"

    class MinimalSubscriber : public rclcpp::Node {
    public:
      MinimalSubscriber()
          : Node("minimal_subscriber"),
            subscription_1_(this->create_subscription<std_msgs::msg::String>(
                "chatter_1", 10,
                [this](const std_msgs::msg::String &msg) -> void {
                  callback(msg, 1);
                })),
            subscription_2_(this->create_subscription<std_msgs::msg::String>(
                "chatter_2", 10, [this](const std_msgs::msg::String &msg) -> void {
                  callback(msg, 2);
                })) {}

    private:
      void callback(const std_msgs::msg::String &msg, int source) {
        RCLCPP_INFO(this->get_logger(), "I heard: '%s' from %d", msg.data.c_str(),
                    source);
      }

      rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_1_;
      rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_2_;
    };

    int main(int argc, char *argv[]) {
      rclcpp::init(argc, argv);
      rclcpp::spin(std::make_shared<MinimalSubscriber>());
      rclcpp::shutdown();
      return 0;
    }
    ```


Question:
ros2_control - Hardware Interface - Write() & Moveit2 Joint Trajectory

By using ROS Humble, Moveit2, and ros2_control, I am trying to accomplish manipulation tasks with the CRX-10iA/L Fanuc robot. Currently, I am implementing ros2_control hardware_interface part. Inside the default write function I am sending motion commands to robot.

I have two motion command options from the provided robot interface. One of them should be sent except the last write command and the other one must be sent lastly. Otherwise, communication can't go further.

I was wondering whether I can access to the total number of write commands that will be sent by hardware_interface? Then I can set a simple if-else logic.

I thought about accessing total number of joint trajectory commands but I realized that when moveit generated a joint trajectory point with 22 positions, write() function was called 5 times in hardware_interface. Less than ideal as expected due to real hardware constraints.

Any suggestion is appreciated. Thank you for your time.

Explanation: The number of times write() method is called is related to the update rate of controller manager. We can check implrmentation of Hardware Components with different update rates.

$\begingroup$

the write() method will be called with the update rate of your controller
manager, if you need a different rate we added some [ docs here
](https://control.ros.org/master/doc/ros2_control/hardware_interface/doc/different_update_rates_userdoc.html)
. Which sampling time has your joint_trajectory, and which one the
controller_manager? It sounds strange that it would be called 5 times only.

You cannot access the trajectory from your hardware_component, because the
joint_trajectory_controller is sampling the trajectory at the current time
instance and sends only the current command to the hardware component.

I'm not sure if I understand your problem right, but you simply can add a
buffer to save the old commands for the next call to write()?


Question:
ROS2 - modify py launchfile without rebuilding package

In ROS1 we could modify XML launchfile and roslaunch them directly without catkin_make rebuilding, in ROS2 it seems if I modify python launchfile, I need to rebuild the package otherwise

ros2 launch <package_name> <launchfile_name>
runs the old launchfile. Do I need to rebuild the package after each modification or am I missing something?

Explanation: We may use some symbol link, which create symlinks pointing to actual source files. In this case, the change in source files will automatically be reflected.

$\begingroup$

You can use the ` --symlink-install ` flag while building your code. This will
create symlinks in the install directory which points to actual source files
rather then creating copies. So whenever you make change in your source files
it will automatically be reflected in install and you won't be required to
build again. You can also check this link, [ what is the use of --symlink-
install in ROS2 colcon build? ](https://answers.ros.org/question/371822/what-
is-the-use-of-symlink-install-in-ros2-colcon-build/) , for further help.


Question:
Comparison of trajectories from odometries

Is there a way in ROS2 to compare trajectories from odometry data? I'm using robot_localization to calculate various odometry outputs by incorporating GPS and IMU data. I have a bag file where I recorded odometry topics, and I would like to compare the paths taken in the following configurations:

/odom_local (odometry + IMU)
/odom_global (odometry + IMU + GPS)
/odom_ackermann (only my odometry data)
I can visualize the trajectories in rviz2, but I also want to compare them in terms of distance error, etc.

If someone has already done this, I hope they can assist me.

Thanks in advance.

Explanation: We may use Plotjuggler, a tool for plotting and investigating data. We can plot X-Y plots in case of plotting odometry data.

$\begingroup$

You should try [ Plotjuggler ](https://github.com/facontidavide/PlotJuggler) .
Its a nice tool for plotting and investigating data. You can directly import
rosbags into it. Another good thing about plotjuggler is that you can plot X-Y
plots which really helps in case of plotting odometry data. I have been using
it for years now, It might take some time to setup and get started but it will
be worth it.

Tip: you can plot goal (X-Y position) and over it your odometry(X-Y position)
for each case and you'll see how deviated each one of them is from reference
path (goal path).

Check out [ this ](https://vimeo.com/351160225) video by the author of
plotjuggler and you'll understand more.

Hope this helps


Question:
Gazebo ignition spawn_entity equivalent

When designing simulations in Gazebo Classic it was possible to spawn robots in the simulation with the launch file spawn_entity from the gazebo_ros pkg. Is there any equivalent in to that in Gazebo Ignition?

Explanation: We may try to change the file of spawn_entity, and migrate the project from Gazebo Classic to Gazebo Ignition.

$\begingroup$

In Gazebo Ignition, they have moved from ` gazebo_ros ` to ` ros_gz ` . Inside
this ` ros_gz ` metapackage, you'd find the ` ros_gz_sim ` package, which
provides the functionality that you want.

I'll point you to the source of the [ package
](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_sim) , you can use this
to check what types of inputs the launch file expects, and also to read more
about the package. In case you are looking to use it in the ROS 2 CLI, it's

    ros2 launch ros_gz_sim gz_sim.launch.py gz_args:="shapes.sdf"

I'd also point you to [ this
](https://gazebosim.org/docs/harmonic/migrating_gazebo_classic_ros2_packages)
Migration Guide, where you have a a very nicely written document on how to
migrate your project from Gazebo Classic to Gazebo Ignition. The section of
interest for you would be the [ spawn model
](https://gazebosim.org/docs/harmonic/migrating_gazebo_classic_ros2_packages#spawn-
model) section.


Question:
Comparing navigation algorithms

I am new to Nav2 stack and currently there are a bunch of navigation plugins to choose from (https://navigation.ros.org/plugins/index.html). I am interested in how to choose available algorithms from those in "Planners" and "Controllers" sections. For example, how to know pros & cons of NavFn planner compared with SmacPlanner. How to know pros & cons of DWB controller against TEB controller. Is there any site clarify something like this?

Thank you,

Peera

Explanation: We can check overview/comparison between planners.

$\begingroup$

There's a paper for that: [ https://arxiv.org/pdf/2307.15236.pdf
](https://arxiv.org/pdf/2307.15236.pdf)

> S. Macenski, T. Moore, DV Lu, A. Merzlyakov, M. Ferguson, From the desks of
> ROS maintainers: A survey of modern & capable mobile robotics algorithms in
> the robot operating system 2, Robotics and Autonomous Systems, 2023


Question:
Trouble Installing ROS 2 Humble on Ubuntu 20.04 with arm64/x86_64 Architecture

I've been encountering an issue while attempting to install ROS 2 Humble on my Ubuntu 20.04 system. My machine supports both arm64 and x86_64 architectures. Despite following the official installation instructions closely, I run into the "unable to locate package ros-humble-desktop" error every time I try to execute the installation command.

Here are the steps I've followed based on the instructions from the ROS.org page for Humble:

1. Added the ROS 2 repository and keyring as follows:

sudo apt update && sudo apt install curl -y

sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
2. Updated and upgraded my package lists:

   sudo apt update
   sudo apt upgrade
3. Attempted to install ROS 2 Humble packages:

   sudo apt install ros-humble-desktop
However, this results in the "unable to locate package ros-humble-desktop" error.

Interestingly, I came across a similar issue on ROS Answers where a user encountered package location errors due to their system running on an ARMhf platform. However, after checking my system using dpkg --print-architecture and lscpu, I confirmed that my system is on arm64 and x86_64, which should be compatible with ROS 2 Humble according to REP 2000.

I'm reaching out to see if anyone has faced a similar issue or could offer guidance on resolving this error. Could this problem be related to my prior attempts to uninstall ROS 2 Foxy and clean my system? Or is there something else I'm missing in the setup process for ROS 2 Humble on Ubuntu 20.04?

Any advice or suggestions would be greatly appreciated. Thank you in advance for your help!

Explanation: One option is to try source install.

$\begingroup$

In normal case, ROS2 Humble binary installation is available in Ubuntu 22.04
version, unless you have built a separate container environment.

[ ![enter image description here](https://i.sstatic.net/YMaN6.png)
](https://i.sstatic.net/YMaN6.png)

    **Installation**
    Options for installing ROS 2 Humble Hawksbill:

    Binary packages
    Binaries are only created for the Tier 1 operating systems listed in REP-2000. Given the nature of Rolling, this list may be updated at any time. If you are not running any of the following operating systems you may need to build from source or use a container solution to run ROS 2 on your platform.

    We provide ROS 2 binary packages for the following platforms:

    Ubuntu Linux - Jammy Jellyfish (22.04)

    Debian packages (recommended)

    “fat” archive

    RHEL 8

    RPM packages (recommended)

    “fat” archive

    Windows (VS 2019)

Or you could try Source Install [
https://docs.ros.org/en/humble/Installation/Alternatives/Ubuntu-Development-
Setup.html ](https://docs.ros.org/en/humble/Installation/Alternatives/Ubuntu-
Development-Setup.html) [ ![enter image description
here](https://i.sstatic.net/11U0I.png) ](https://i.sstatic.net/11U0I.png)

    Ubuntu (source)
    Table of Contents

    System requirements

    System setup

    Set locale

    Add the ROS 2 apt repository

    Install development tools and ROS tools

    Get ROS 2 code

    Install dependencies using rosdep

    Install additional DDS implementations (optional)

    Build the code in the workspace

    Environment setup

    Source the setup script

    Try some examples

    Next steps after installing

    Using the ROS 1 bridge

    Additional RMW implementations (optional)

    Alternate compilers

    Clang

    Stay up to date

    Troubleshooting

    Uninstall

    System requirements
    The current Debian-based target platforms for Humble Hawksbill are:

    Tier 1: Ubuntu Linux - Jammy (22.04) 64-bit

    Tier 3: Ubuntu Linux - Focal (20.04) 64-bit

    Tier 3: Debian Linux - Bullseye (11) 64-bit


Question:
How to use ros2_control with actual hardware communicating via etherCAT?

I am learning ros2_control with the real hardware. I need some help writing hardware interface for the current setup. I do not have experience writing on the communication side of the real hardware.

setup: I have Jetson nano, drives, motors, and sensors communicating via EtherCAT and using ros2 foxy and SOEM_ROS2 package. these were installed and running without ros2 control, simply via publisher and subscriber. The whole system controls the x,y,z axis with prismatic joint. It is not a robot. so no end effector. Now, I want to integrate ros2 control with the whole system. I don't know how to get the values from the hardware for the read and write methods of the hardware interface. I appreciate any help you can provide.

Explanation: We need a driver with generic ways to parametrise and assemble Hardware Interfaces based on EtherCAT modules.

$\begingroup$

Have you seen this [ EtherCAT driver ](https://github.com/ICube-
Robotics/ethercat_driver_ros2) ?


Question:
Reading a ros2_control xacro file in a regular node

I have a xacro file that I used for a specific piece of hardware. I figured out how to store custom data structures within the gpio framework within ros2_control

example:

    <gpio name="motion_command_output">
        <param name="byteIndex">0</param>
        <param name="bitMask">0x01</param>
    </gpio>
This would get automatically loading into the associated plugin and the data was available in the hardwareinfo structure/map.

I want to use the same xacro file but in a regular lifecycle node. It seems that I can read and parse the file in the launch file with

    device_config = xacro.process_file(io_config_file_path)
    device_config_parsed = device_config.toprettyxml(indent='  ')
But there isn't really a way to load that into the parameters.

I have tried a bunch of different options and it blows up or nothing happens. Another option would be just to parse the file in the node with tinyxml2.

Any ideas?

Thanks

Explanation: We need a component parser to be incorporated into the code.

$\begingroup$

Have a look at the [ component parser ](https://github.com/ros-
controls/ros2_control/blob/master/hardware_interface/include/hardware_interface/component_parser.hpp)
used within the controller_manager of ros2_control. It should be possible to
use that in your node.


Question:
Custom hardware interface type

I would like to write a controller that needs all joint states to update a single joint.

My idea was to create a class MyStateInterface which inherits from hardware_interface::StateInterface and stores all information for each joint. Then, I would like to export this class inside the hardware interface to pass the joint information to the controller.

To make it clear, I modify this example:

std::vector<double> hw_states_;

CallbackReturn MyRobotHardware::on_init(const hardware_interface::HardwareInfo & info) {
  // set some default values when starting the first time
  hw_states_.resize(info_.joints.size(), 0.0);
  return CallbackReturn::SUCCESS;
}

std::vector<hardware_interface::StateInterface>
MyRobotHardware::export_state_interfaces()
{
  std::vector<hardware_interface::StateInterface> state_interfaces;

  for (uint i = 0; i < info_.joints.size(); i++)
  {
    state_interfaces.emplace_back(hardware_interface::StateInterface(
      info_.joints[i].name,                  // joint name from controller.yaml
      hardware_interface::HW_IF_POSITION,    // "position"
      &hw_states_[i]                         // the joint value
    ));
  }

  return state_interfaces;
}
To something like this:

std::vector<MyStateHandle> hw_states_;

CallbackReturn MyRobotHardware::on_init(const hardware_interface::HardwareInfo & info) {
  // set some default object when starting the first time
  hw_states_.resize(info_.joints.size(), MyStateHandle());
  return CallbackReturn::SUCCESS;
}

std::vector<hardware_interface::StateInterface>
MyRobotHardware::export_state_interfaces()
{
  std::vector<hardware_interface::StateInterface> state_interfaces;

  for (uint i = 0; i < info_.joints.size(); i++)
  {
    state_interfaces.emplace_back(hardware_interface::StateInterface(
      info_.joints[i].name,      // joint name from controller.yaml
      "my_state_handle",         // a made up name
      &hw_states_[i]             // information for controlling the joint
    ));
  }

  return states_interfaces;
}
This didn't work because there is no matching function for the call hardware_interface::StateInterface(const std::string &name, const std::string &interface_name, MyStateHandle *value_ptr=nullptr) because there is only the function hardware_interface::StateInterface(const std::string &name, const std::string &interface_name, double *value_ptr=nullptr)

I want to know if there is a way to pass a class full of control data from the hardware interface to the controller, or am I on a completely wrong track?

Explanation: We can check post/issues related to HW interface creation change.

$\begingroup$

No this is not possible yet. But we are working on that feature, see [ this PR
here ](https://github.com/ros-controls/ros2_control/pull/1240) . This feature
might come with Jazzy.


Question:
Octomap and Projected Octomap not lining up

I am trying to use a projected Octomap as an occupancy grid to pass onto the ROS navigation stack, but when I create one using the octomap_server package, it creates an occupancy grid which is rotated 90 degrees from the top down view (i.e., It projects from the side when it should be projecting downwards). The Octomap and the projected Octomap are shown below.

Is there any way to change the direction from which Octomap creates the projection?

Explanation: We can use dynamic configure to modify the parameters dynamically and check if it fixes the orientation

$\begingroup$

It seems you can use dynamic configure to modify the parameters dynamically
and check if fix your orientation [ Octomap Params
](https://github.com/OctoMap/octomap_mapping/blob/kinetic-
devel/octomap_server/cfg/OctomapServer.cfg)

    rosrun rqt_reconfigure rqt_reconfigure

Or add in your launch file a static transform Publisher between your robot
base_link and map frames with desired orientation

    <node pkg="tf" type="static_transform_publisher" name="octomap_to_base_link" args="0 0 0 0 0 0 1 map base_link 100" />


Question:
Controlling power input for different currents and voltages connected to the same power source

I am new to robotics and am struggling with the electronics a bit. I am using two 9 V batteries in series to provide 18 V. I need to power 2 x 12 W DC motors and an Arduino Uno. I need to divide the input power of 18 volts into 3 streams: 2 x (12 V, 1 A) streams for the motors + 1 x (6 V, 0.2 A) for the Arduino.

I thought of using a 1 Ω resistor and a 2 Ω resistor in parallel to get two streams: 12 volts and 6 volts respectively, but I am not sure if that will ensure the right current values will be drawn. I tried looking online but couldn't find a method. How can I go about carrying this out? Any help will be greatly appreciated!

Explanation: An alternative is to use a converter and set the output voltage.

$\begingroup$

In addition to the above comment, you will never be able to source that much
power from a pair of 9 Volt batteries. If you do use a battery eliminator
circuit keep in mind that they operate in the linear regime and are therefor
not very efficient. You would be better off using switch mode DC to DC
converters and a LiPo battery. There are lots of options, look at spark fun
and find the ratings you need. Here is a [ link
](https://www.sparkfun.com/products/9370) to a converter and [ here
](https://www.sparkfun.com/categories/tags/power) are some batteries. If you
need to increase the voltage use a [ boost
](https://www.sparkfun.com/search/results?term=boost+converter) converter, you
dont need to stack these in series.


Question:
Subscriber in Hardware Interface (ros2_control)

Is there any example for adding subscriber to hardware interface ? Publisher works fine. My code is below, I dont know where its going wrong but unable to get values after publishing using CLI.

.hpp file '''

namespace diffdrive_ctre { class HardwareCommandPub : public rclcpp::Node { public:

HardwareCommandPub();
void publishData();
void pincmdcheck();
private: rclcpp::Publisher<amr_v4_msgs_srvs::msg::Motor>::SharedPtr pub_; rclcpp::Publisher<std_msgs::msg::Bool>::SharedPtr estop_pub_; rclcpp::Subscription<amr_v4_msgs_srvs::msg::Pin>::SharedPtr pin_sub_; rclcpp::TimerBase::SharedPtr timer_; amr_v4_msgs_srvs::msg::Pin latest_pin_cmd; };

class DiffDriveCTREHardware : public hardware_interface::SystemInterface {

''' .cpp file

HardwareCommandPub::HardwareCommandPub() : Node("Motor_Status") {

pub_ = this->create_publisher<amr_v4_msgs_srvs::msg::Motor>("talonFX_right/status", 10); estop_pub_ = this->create_publisher<std_msgs::msg::Bool>("/e_stop", 10); pin_sub_ = this->create_subscription<amr_v4_msgs_srvs::msg::Pin>("/amr/pin_cmd", 10, [this](const amr_v4_msgs_srvs::msg::Pin::SharedPtr pin_cmd) { latest_pin_cmd = *pin_cmd; });

}

void HardwareCommandPub::publishData() { // //motor1 auto message = amr_v4_msgs_srvs::msg::Motor(); message.temperature_right = motor_right.GetDeviceTemp().ToString(); message.bus_voltage_right = motor_right.GetSupplyVoltage().ToString();
message.output_current_right = motor_right.GetStatorCurrent().ToString(); message.error_right = motor_right.GetStickyFault_Hardware().ToString();

// //motor2 message.temperature_left = motor_left.GetDeviceTemp().ToString(); message.bus_voltage_left = motor_left.GetSupplyVoltage().ToString();
message.output_current_left = motor_left.GetStatorCurrent().ToString(); message.error_left = motor_left.GetStickyFault_Hardware().ToString();

// //motor pin   message.temperature_pin = pin_motor.GetDeviceTemp().ToString();   message.bus_voltage_pin =
pin_motor.GetSupplyVoltage().ToString(); message.output_current_pin = pin_motor.GetStatorCurrent().ToString(); message.error_pin = pin_motor.GetStickyFault_Hardware().ToString();

//estop auto message_estop = std_msgs::msg::Bool();
message_estop.data = estop_temp; if (rclcpp::ok()) { estop_pub_->publish(message_estop); pub_->publish(message); pincmdcheck(); } }

void HardwareCommandPub::pincmdcheck() { pin_temp = latest_pin_cmd.pin_command; RCLCPP_INFO( rclcpp::get_logger("Pin test"), "Got pin cmd '%i'and '%i' and '%s'!",pin_temp,latest_pin_cmd.pin_command); }

Explanation: We can check how subscription is created in the node of topic-based subscriber.

$\begingroup$

Have a look at [ this implementation of topic_based_ros2_control
](https://github.com/PickNikRobotics/topic_based_ros2_control/blob/37a98e652818ac4b884786558a2f3c0373415c16/src/topic_based_system.cpp#L149)
here.

Note that in general, it is not recommended to use a node inside the hardware
interface if you have realtime requirements. Write your custom controller with
realtime-safe implementations instead.


Question:
Make the robot stop if it finds an obstacle in front

I am using the navigation stack (nav2) without problems, but I would like to understand how I can make the robot stop from its path if it finds a dynamic obstacle in front of it (at a minimum distance of n metres)?

Is there a demo or tutorial to take inspiration from?

many thanks in advance

Explanation: We can use the CollisionMonitor package inside the Nav2 Stack.

$\begingroup$

You can use the CollisionMonitor package inside the Nav2 Stack.

Here is a tutorial: [ Using Collision Monitor
](https://navigation.ros.org/tutorials/docs/using_collision_monitor.html#using-
collision-monitor) and here are the sources [ Github ](https://github.com/ros-
planning/navigation2/tree/main/nav2_collision_monitor)


Question:
What determines a robots euler rotation order?

I know Fanuc robots use the XYZ rotation order, ABB uses ZYX and some robots use the ZYZ rotation order. What actually determines this order? is it the way the frames are setup on the DH table? Or is it just the order they chose to solve the IK, and any order could be used? Can anyone help me understand this? TY.

Explanation: Any euler angles triplet can be used to represent the orientation of a rigid body (and so of the link a robot).

$\begingroup$

Any [ euler angles triplet ](https://en.wikipedia.org/wiki/Euler_angles) can
be used to represent the orientation of a rigid body (and so of the link a
robot). I cannot answer for the particular robots you mentioned, but usually
one choose a representation for ease of visualization or to simplify some
computation (e.g. if a link rotate around a revolute joint, it simplify the
equation of motion to have one the rotation axis aligned with the joint axis).


Question:
How to make 4 wheeled robot work with DiffDrive plugin and ROS2 Control?

I have a 4 wheeled robot with mecanum wheels (in real life), I have been able to simulate it and get it to work with the ROS2 DiffDrive plugin (replicating the skid steer plugin from ROS1) but now that I want to implement ROS2 Control with it I cannot get it to work. I have been following the Articubot tutorials but his robot only has 2 wheels. I can't find anything online regarding a 4 wheeled robot that would make use of the DiffDrive plugin on ROS2 while using ROS2 Control. At the moment My aim is to only simulate the robot in gazebo so that I can better understand how ROS2 control works but I am stuck.

GitHub Repo

I hope the question is clear.

Some guidance on how to make ROS2 Control work with this robot with be very much appreciated. Thanks

Explanation: We may use DiffBot, a simple mobile base with differential drive. We may also check parameters of diff_drive_controller.

$\begingroup$

There is currently no ros2_controller supporting omniwheels. If it has
standard wheels, use the diff_drive controller as in [ this demo
](https://control.ros.org/humble/doc/ros2_control_demos/example_2/doc/userdoc.html)
. Consider the wheels_per_side [ parameter ](https://github.com/ros-
controls/ros2_controllers/blob/humble/diff_drive_controller/src/diff_drive_controller_parameter.yaml)
.


Question:
Underwater Property Simulation with ROS2 e.g Particle Plume

I want to develop and test adaptive path planning algorithms for AUVs or also USVs.

So far I did this in ROS1 with the UUV Simulator and especially the uuv_plume_simulator.

Now I am looking for ways to do this in ROS2.

I managed to get a simulation of an AUV working with ROS2 Humble and Gazebo Ignition but I couldn't find a solution comparable to the UUV Plume Simulator.

Are there Gazebo (Ignition/Garden/Harmonic) Plugins or Projects that already deal with the simulation of the distribution of water properties like salinity/turbidity/temperature or the simulation of freshwater/hotwater/oil/particle spill or plumes? Ideally these properties would be also influenced by currents.

So far i only came across the EnvironmentPreload Plugin for Gazebo Harmonic but it seems to only offer the a static distribution of values.

Any recommendations are highly appreciated.

Explanation: We can use the ROS2 Port of the uuv_plume_simulator package.

$\begingroup$

We did a port of the UUV Plume Simulator Package to Ros2 and it is available
here:

[ https://github.com/tiko5000/uuv_plume_simulator_ros2
](https://github.com/tiko5000/uuv_plume_simulator_ros2)


Question:
ros_gz_bridge does not publish on ros2 topic

I am running ros_gz_bridge to read some data from Gazebo, in particular I have run:

ros2 run ros_gz_bridge parameter_bridge /model/x500_vision_0/odometry@nav_msgs/msg/Odometry[gz.msgs.Odometry

[INFO] [1706113773.667589591] [ros_gz_bridge]: Creating GZ->ROS Bridge: [/model/x500_vision_0/odometry (gz.msgs.Odometry) -> /model/x500_vision_0/odometry (nav_msgs/msg/Odometry)] (Lazy 0)
The problem is that when I run

ros2 topic echo /model/x500_vision_0/odometry
I do not see any message published on the topic.

I have already checked that the name of the topic is correct, and when I run

gz topic -et /model/x500_vision_0/odometry
I can see the messages exchanged within Gazebo.

So why is the bridge not publishing the messages on the ROS2 network?

Explanation: We can try to install from the source. This can be related to different versions Gazebo Garden and Gazebo Fortress.

$\begingroup$

I solved the issue. I thought I was working with Gazebo Fortress, but a
software I was working with installed Gazebo Garden instead.

When I installed the ` ros-gz-bridge ` from the apt repository, it installed
only the supported package that is officially supported by ROS Humble, which
is the Gazebo Fortress one.

I installed the ros-gz-bridge from [ sources
](https://github.com/gazebosim/ros_gz/tree/humble) and now the bridge is
working as expected.


Question:
Compilation error when subscription callback's input is of certain type

I did an experiment where I tried all combinations of const, &, and SharedPtr as the input to the subscription callback. The message type is nav_msgs::msg::Odometry and the results are at the bottom of the code snippet.

#include "rclcpp/rclcpp.hpp"
#include "nav_msgs/msg/odometry.hpp"

class SubToSharedPtr : public rclcpp::Node
{
public:
    SubToSharedPtr()
    : Node("sub_to_shared_ptr_node")
    {
        odom_sub_ = this->create_subscription<nav_msgs::msg::Odometry>(
            "odom", rclcpp::SystemDefaultsQoS(),
            std::bind(&SubToSharedPtr::odomCb, this, std::placeholders::_1)
        );
    }

private:
    rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_;

    void odomCb(const nav_msgs::msg::Odometry& msg)
    {

    }
};

int main(int argc, char** argv)
{
    rclcpp::init(argc, argv);
    auto node = std::make_shared<SubToSharedPtr>();
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

// const SharedPtr& - doesn't work
// const SharedPtr - works
// SharedPtr - works
// SharedPtr& - doesn't work
// const & - works
// const - works
// & - doesn't work
// nothing - works
It seems like there is an important implication to this pattern (maybe something to do with ownership?). For example, all the ones with & doesn't work except for const & maybe because even though you are getting the actual variable (not a copy) you are promising not to change it, which is why it's acceptable.

Does anyone have an explanation for why this pattern exists?

Explanation: This is related to the pass of the smart pointer as a function parameter. We need to check the correct way to implement it.

$\begingroup$

You are correct that the implication to the pattern does have to do with
ownership. I'll summarize here, but there is a much more thorough explanation
of the guidelines in [ Herb Sutter's GoTW #91: Smart Pointer Parameters
](https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-
parameters/)

The relevant section that the ROS 2 callbacks are enforcing are:

> Guideline: Don’t pass a smart pointer as a function parameter unless you
> want to use or manipulate the smart pointer itself, such as to share or
> transfer ownership.

> Guideline: Prefer passing objects by value, *, or &, not by smart pointer.

The new set of signatures are trying to be much more explicit about ownership.
While the ownership may not be important in a single-producer, single-consumer
situation, there are more complex applications. This is especially important
in the case of _intraprocess communications_ where the messages are held in an
internal buffer and only distributed based on the signatures of the
subscriptions. For more information on the implications on _intraprocess
comms_ , consult the [ Intraprocess Communications Design Doc
](https://design.ros2.org/articles/intraprocess_communications.html) . The
most relevant section is _Number of message copies_ , which has a table
comparing various signatures.

Generally the signatures should be thought of as follows:

  * ` const Msg & ` \- immutable, no ownership
  * ` unique_ptr<Msg> ` \- mutable and takes ownership
  * ` shared_ptr<const Msg> ` \- immutable, but allows subscription to share ownership (by copying into member)
  * ` const shared_ptr<const Msg> & ` \- immutable, but allows subscription to share ownership (by copying into member)
  * ` shared_ptr<Msg> ` \- deprecated. It's potentially unsafe if multiple subscriptions take the same message.

Finally, for a full enumeration of all of the available subscription types,
it's best to consult the ` AnySubscriptionCallbackPossibleTypes ` structure in
` rclcpp ` : [
https://github.com/ros2/rclcpp/blob/rolling/rclcpp/include/rclcpp/any_subscription_callback.hpp#L57
](https://github.com/ros2/rclcpp/blob/rolling/rclcpp/include/rclcpp/any_subscription_callback.hpp#L57)


Question:
Where can i find the code about move_group_interface.plan method?

I'm studying moveit. A trajectory was created through a method called plan, but I couldn't find the process, so I asked a question. thank you

Explanation: We can find move_group_interface file in moveit repo, and search functions related to motion plan construction.

$\begingroup$

This should be in the MoveIt GitHub repository. More specifically, you can
find it [ here ](https://github.com/ros-
planning/moveit2/blob/4c024bc49ef20369f01d363c5884556932bf86da/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp#L636)
in the ` move_group_interface.cpp ` file. In simple terms, this method
prepares the action goal, sends the goal, and handles the result.

The function takes only a reference to the ` Plan ` object, and the process
does not really tell you what is happening under the hood. For a deeper
understanding of how the motion planning request is constructed, look into the
` constructMotionPlanRequest ` function too. You can find it [ here
](https://github.com/ros-
planning/moveit2/blob/4c024bc49ef20369f01d363c5884556932bf86da/moveit_ros/planning_interface/move_group_interface/src/move_group_interface.cpp#L1012)
.


Question:
Are hardware components in ros2_control designed to include a ROS 2 node as a member?

I need to transmit high-level status updates strings about my hardware to another node using a publisher. Recognizing that blocking calls are not welcome within the read/write methods, I intend to employ a Node in conjunction with RealtimePublisher from the realtime_tools package. However, I'm uncertain whether it is possible to instantiate a node within the implementation of the SystemInterface.

Explanation: We can find a system that integrates ros2_control and can command the robot and publish its state.

$\begingroup$

It is possible but not recommended if you need to satisfy real-time
requirements. See e.g. [ this package
](https://github.com/PickNikRobotics/topic_based_ros2_control) (be aware, that
was written for simulation).


Question:
Oriented Bounding Box in RVIZ

I want to visualize an OrientedBoundingBox from Open3D on RVIZ, I have seen the :

RvizVisualTools::publishWireframeRectangle
RVIZ Line Segments
publishWireframeRectangle has two dimensions width, and height, while I still have length, and for RVIZ Line Segment I have to develop the function myself, I wonder if there is a ready to use function to publish RVIZ Marker for OrientedBoundingBox which is ready to use, can you please tell me if there is any? thanks in advance.

Explanation: It is related to the extension of rviz visualization tools that focused on MoveIt-related debugging and visualization.

$\begingroup$

The tool that builds on [ Rviz Visual Tools
](https://github.com/PickNikRobotics/rviz_visual_tools) is [ Moveit Visual
Tools ](https://github.com/ros-planning/moveit_visual_tools) . MoveIt Visual
Tools is more high-level and focused on MoveIt-related debugging and
visualization. That being said, MVT extends RVT with inheritance, which makes
all the functionality you need available in both.

**Here are the available shapes from (Rviz Visual Tools):**

[ ![enter image description here](https://i.sstatic.net/REpVZ.png)
](https://i.sstatic.net/REpVZ.png)

To start, you can use the method ` RvizVisualTools::publishWireframeRectangle
` and see if this satisfies what you need. If you want to customize the
bounding box edge shapes, you can use the ` publishLine ` or ` publishCylinder
` methods to draw edges. This is doable in the same way that `
publishWireframeRectangle ` works, given the center and dimensions of the
bounding box.

Try to familiarize yourself first with publishing shapes and markers before
building your own. You need a Markers display in Rviz that visualizes shapes
published on a specific topic. You set the topic name when defining the `
rviz_visual_tools::RvizVisualTools ` object.

Regarding the orientation, you would do some basic trigonometry to determine
the starting and ending of edges. Start with implementing something simple,
then figure out the formula that robustly works for the orientation.


Question:
turtlebot4 nav2: how to call action navigateToPose from node in cpp

I am migrating a node that send goals to nav2 (originally move_base) thru an action since I need to know if it has been reached or cancelled by the planner.

It will work with the Turtlebot4. I've been reading the nav2 documentation and launching the nav2 launch of Turtlebot4 and I guess that I need to call the action /navigate_to_pose of the node bt_navigator. However showing the interface, I see that the result is a std_msgs/Empty.

How can I easily send goals to Turtlebot4 from a cpp node and know the status of the navigation (i.e. goal reached/cancelled/travelling)?

Explanation: We can check whether there is avaialable attribute that can show the result succeeded or cancelled.

$\begingroup$

I found this [ example
](https://github.com/ros2/examples/blob/humble/rclcpp/actions/minimal_action_client/member_functions.cpp)
and I realized that the class `
rclcpp_action::ClientGoalHandle<T>::WrappedResult ` already has the attribute
` code ` (that can be either ` rclcpp_action::ResultCode::SUCCEEDED ` , `
rclcpp_action::ResultCode::ABORTED ` or ` rclcpp_action::ResultCode::CANCELLED
` ) so there is no need of putting this information in the action interface.


Question:
iRobot Roomba compatible with ROS2 other than the Create?

I plan to buy an iRobot to test ROS2, but the Create 3 not available in my country, import tax and shipping cost may very high, also sometime custom will reject the import. But many other model from iRobot available like 627, I7, J7 ..., So what model compatible with ROS? Or I should by the Create 3.

Explanation: We can consider build our own robots. We need to find related content/tutorials.

$\begingroup$

The iRobot models 627, i7, and j7 are consumer-grade robotic vacuum cleaners
and are not natively compatible with ROS. Do not expect the same level of
programmability or integration capabilities as the Create 3.

The Create series is designed for robotic development and is compatible with
ROS 2. Create 3 is actually the base for Turtlebot 4. My answer is that it
should be Create 3 or a custom robot you make.

If getting it is hard, and there are no alternatives in your region, why don't
you try making your own mobile robot? This will help you much more than just
trying ROS 2. This [ series ](https://articulatedrobotics.xyz/mobile-robot-
full-list/) is a good resource for that.


Question:
Ros2 Dictionary srv/msg type

I would like to be able to return a dictionary as a Response in my interface, Is it possible to return a python dictionary or should I write code similar to this:

uint8 action

---

item1Class dict
-- other msg types below ---

where item1Class is a struct

This is probably not possible, essentially I want:

    observation = {
        "lidar": lidar_data,
        "pose": {
            "positionX": X,
            "positionY": Y,
            "orientation": yaw,
        },
    }
as a srv message where lidar is float32[] and all pose variable are floats.

Whats the best practice using Ros2 to achieve this. Or is this not what srv/msg was intended for?

Explanation: We may define a .srv file to contain these along these lines. We can find example files as reference.

$\begingroup$

Dictionaries are not a natively supported type. And we actually encourage
things to be strongly typed, where a dictionary is not because it can contain
approximately arbitrary data. When you receive a ROS datatype it will be a
fully defined datatype with it's own structure.

The best practice is to define a ` .srv ` file to contain these along these
lines to cover your description above.

    uint8 action

    ---

    sensor_msgs/LaserScan lidar_data
    geometry_msgs/Pose pose

Messages to consider:

  * [ LaserScan ](https://github.com/ros2/common_interfaces/blob/rolling/sensor_msgs/msg/LaserScan.msg)
  * [ Pose ](https://github.com/ros2/common_interfaces/blob/rolling/geometry_msgs/msg/Pose.msg)


Question:
How to send and receive CAN messages on Ubuntu 18.04 using ROS Melodic

I am trying to use a PCAN-USB device (from Peak-System) to be able to send and receive CAN messages which I would like to use to control a robot using ROS at some point for work.From the research I have done, I have found out that there are different drivers and python libraries and different APIs to achieve what I am looking for. The problem is there is no guides or clear instructions on how to get started.

I go to a page and then it tells me to look at something else and this keeps happening. I would like to use the PEAK-System API and drivers, installed both already but I don't know how to make it work with python but and I am not sure if what I have downloaded is even the right thing.

Essentially what I am looking for is some guidance on how to check if the drivers and API is installed correctly and how to get a simple python script going, and then I'll have something to build on.

I have tried to give as much detail as possible and not make the question too broad sorry if it's still not specific enough.

Thanks.

Explanation: We need to find packages/examples that can connect to a CAN bus, creat and send messages.

$\begingroup$

You can use [ python-can ](https://python-
can.readthedocs.io/en/stable/index.html) . I find the documentation on [
https://python-can.readthedocs.io/en/stable/index.html ](https://python-
can.readthedocs.io/en/stable/index.html) very well written, it should be easy
to follow.
I have used this library with ROS 2 without any problem. You can also use it
in your ROS 1 package. Note that, drivers are already included in the linux
kernel for PCAN.

Don't forget to enable your existing can interface. See [ https://python-
can.readthedocs.io/en/stable/interfaces/socketcan.html ](https://python-
can.readthedocs.io/en/stable/interfaces/socketcan.html)

    sudo ip link set can0 up type can bitrate 250000

Here is a sample python script to send a message;

    import can

    bus = can.interface.Bus(interface='socketcan', channel='can0')
    msg = can.Message(
        arbitration_id=0xC0FFEE,
        data=[0, 25, 0, 1, 3, 1, 4, 1],
        is_extended_id=True
    )
    bus.send(msg)

For receiving can messages, I recommend using the [ Notifier ](https://python-
can.readthedocs.io/en/stable/listeners.html#notifier) object. It creates a
thread to read messages from the bus and distributes them to listeners, i.e.,
your callback function to process incoming can messages.


Question:
Nav2 - How to create a custom behavior tree (BT) plugin/node in a separate ros2 package?

I'm trying to create a my own custom bt plugin. In the official tutorial https://navigation.ros.org/plugin_tutorials/docs/writing_new_bt_plugin.html, I can't see an instruction or an example on how to create a behavior tree plugin in a separate ros2 package just like in this nav2 repo tutorial https://github.com/ros-planning/navigation2_tutorials/tree/master where the custom plugins (custom costmap, behavior, controller and planner) are created in a separate package.

So I'm wondering, is it possible to create the bt plugin/node in a separate package? or I need to install nav2 from source and try to create the bt plugin on the /navigation2/nav2_behavior_tree/plugins folder?

Explanation: We can check implementation examples about behavior tree nodes.

$\begingroup$

Yes, it is possible. There's nothing special about the ` nav2_behavior_tree `
package. Here's one such recent example: [ https://github.com/open-
navigation/opennav_coverage/tree/main/opennav_coverage_bt
](https://github.com/open-
navigation/opennav_coverage/tree/main/opennav_coverage_bt)


Question:
How to use Gazebo Ignition NavSat plugin

I'm trying to use the Navsat plugin but I can't get it working. I'm using ros-humble

I've been following the link below, but I am unable to see any navsat topic in gazebo https://answers.gazebosim.org//question/28643/gps-sensor-plugin-in-ignition/

In my robot urdf, I have the following code

    <link name="chassis">
            ....
      <plugin filename="ignition-gazebo-navsat-system" name="ignition::gazebo::systems::NavSat"/>
      <gazebo>
        <sensor name="navsat_sensor" type="navsat">
          <always_on>1</always_on>
          <update_rate>1</update_rate>
          <topic>navsat</topic>
        </sensor>
     </gazebo>
    </link>
On my world sdf, I also included

    <world name="field">
        ...
      <spherical_coordinates>
        <surface_model>EARTH_WGS84</surface_model>
        <world_frame_orientation>ENU</world_frame_orientation>
        <latitude_deg>-22.986687</latitude_deg>
        <longitude_deg>-43.202501</longitude_deg>
        <elevation>0</elevation>
        <heading_deg>0</heading_deg>
      </spherical_coordinates>
    </world>

Explanation: We need to check examples about how the tag gazebo and plugin are used.

$\begingroup$

  1. The ` <plugin> ` should be in the world SDF file (see [ example ](https://github.com/gazebosim/gz-sim/blob/ign-gazebo6/examples/worlds/spherical_coordinates.sdf) ).
  2. The ` <gazebo> ` tag should be directly under ` <robot> ` in a URDF file and should reference the link it's modifying. In your case, it should be ` <gazebo reference="chassis"> ` . You can refer to [ this ](http://sdformat.org/tutorials?tut=sdformat_urdf_extensions&cat=specification&) documentation for more details on the ` <gazebo> ` tag.


Question:
Sensors in ROS2 without driver

I got a new LiDAR from a seller who unfortunately does not provide any ROS2 support. Rather there is only a Point Cloud Visualiser .exe in Windows. I would like to use the LiDAR in my project of developing Autonomous Farming Vehicle but dont know how I can use this in ROS2 without any Package or Driver. Is it possible to use it somehow or develop a ROS2 supported package of the LiDAR??

Explanation: We need to find the driver with ROS wrapper to make the sensor data available over ROS topics/services.

$\begingroup$

If there is an API or a device protocol specification available, then it would
be possible to develop your own driver for the hardware. This is how all
existing drivers for ROS 2 have started.

Typically, people write a library that is independent of ROS, and then provide
a ROS wrapper to make the sensor data available over ROS topics/services.

Example drivers that you may want to reference:

  * [ https://github.com/ros-drivers/velodyne/tree/humble-devel/velodyne_driver ](https://github.com/ros-drivers/velodyne/tree/humble-devel/velodyne_driver) \- Velodyne LIDAR driver, the lidar connects over ethernet and the driver uses PCAP to receive packets and expand them into ` sensor_msgs/LaserScan `
  * [ https://github.com/ros-drivers/ros2_ouster_drivers ](https://github.com/ros-drivers/ros2_ouster_drivers) \- Ouster lidar drivers
  * [ https://github.com/ros-drivers/urg_node ](https://github.com/ros-drivers/urg_node) \- Hokuyo lidar driver, wraps the official ` urg_c ` library

In the case that a manufacturer does not provide an API, then you will have to
write the lower-level hardware driver yourself. An example of this in the
above list is the Velodyne driver, where the manufacturer provides a datasheet
describing the packet format and the driver interprets the packets
accordingly.


Question:
Transform between odom and base_link not made. ros2_controller Ackermann Steering Controller

I cannot set odom as a fixed frame inside RViz. It doesn't show up at all. My robot is fully functional and visible in both Gazebo. I don't get any warnings, errors or exceptions in the log. I'm using ROS2 Humble and Gazebo Fortress. I follow the code of the tricycle_drive_example from ign_ros2_control_demos (which publishes odom correctly if I run it on my laptop).

As intended by the controller, the topic /ackermann_steering_cotroller/odometry is published. Whenerver I try to visualize that topic with RViz, I get the following message:

[INFO] [1704543459.237610775] [rviz]: Message Filter dropping message: frame 'odom' at time 214,560 for reason 'discarding message because the queue is full'
Running ros2 run tf2_ros tf2_echo odom base_link, gives this:

[INFO] [1704543792.043830485] [tf2_echo]: Waiting for transform odom ->  base_link: Invalid frame ID "odom" passed to canTransform argument target_frame - frame does not exist
Also, my tf_tree looks like this: enter image description here

The ros2_control tag inside my urdf:

<ros2_control name="IgnitionSystem" type="system">
    <hardware>
        <plugin>ign_ros2_control/IgnitionSystem</plugin>
    </hardware>
    <joint name="LEFT_HINGE_JOINT">
        <command_interface name="position"/>
        <state_interface name="position"/>
    </joint>
    <joint name="RIGHT_HINGE_JOINT">
        <command_interface name="position"/>
        <state_interface name="position"/>
    </joint>
    <joint name="LEFT_REAR_WHEEL_JOINT">
        <command_interface name="velocity"/>
        <state_interface name="velocity"/>
        <state_interface name="position"/>
    </joint>
    <joint name="RIGHT_REAR_WHEEL_JOINT">
        <command_interface name="velocity"/>
        <state_interface name="velocity"/>
        <state_interface name="position"/>
    </joint>
</ros2_control>
The configuration file for the controllers:

controller_manager:
  ros__parameters:
    update_rate: 50

    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster

    ackermann_steering_controller:
      type: ackermann_steering_controller/AckermannSteeringController

joint_state_broadcaster:
  ros__parameters:
  extra_joints: ["RIGHT_FRONT_WHEEL_JOINT", "LEFT_FRONT_WHEEL_JOINT"]

ackermann_steering_controller:
  ros__parameters:

    reference_timeout: 2.0
    front_steering: true
    open_loop: false
    velocity_rolling_window_size: 10
    use_stamped_vel: false
    rear_wheels_names: [RIGHT_REAR_WHEEL_JOINT, LEFT_REAR_WHEEL_JOINT]
    front_wheels_names: [RIGHT_HINGE_JOINT, LEFT_HINGE_JOINT]
    odom_frame_id: odom
    base_frame_id: base_link
    enable_odom_tf: true
    odom_only_twist: false

    wheelbase: 0.324
    front_wheel_track: 0.387
    rear_wheel_track: 0.387
    front_wheels_radius: 0.055
    rear_wheels_radius: 0.055
In addition, here is what's on the log:

[ruby $(which ign) gazebo-2] [INFO] [1704582360.211746217] [controller_manager]: Loading controller 'ackermann_steering_controller'
[ruby $(which ign) gazebo-2] [INFO] [1704582360.222413325] [controller_manager]: Setting use_sim_time=True for ackermann_steering_controller to match controller manager (see ros2_control#325 for details)
[spawner-7] [INFO] [1704582360.288968173] [spawner_ackermann_steering_controller]: Loaded ackermann_steering_controller
[ruby $(which ign) gazebo-2] [INFO] [1704582360.290052009] [controller_manager]: Configuring controller 'ackermann_steering_controller'
[ruby $(which ign) gazebo-2] [INFO] [1704582360.290166991] [ackermann_steering_controller]: ackermann odom configure successful
[ruby $(which ign) gazebo-2] [INFO] [1704582360.295780665] [ackermann_steering_controller]: configure successful
[spawner-7] [INFO] [1704582360.569778822] [spawner_ackermann_steering_controller]: Configured and activated ackermann_steering_controller
[INFO] [spawner-7]: process has finished cleanly [pid 51038]

Explanation: We need to check the implementation of tricycle_controller and ackermann_steering_controller to see whether their configurations are compatible.

$\begingroup$

Be aware that tricycle_controller has a totally different codebase then the
ackermann_steering_controller (which uses the same base as
bicycle_steering_controller and tricycle_steering_controller, see [
steering_controller_library
](https://control.ros.org/master/doc/ros2_controllers/steering_controllers_library/doc/userdoc.html)
): You cannot use the configuration directly.

Does [ this note ](https://github.com/ros-
controls/ros2_controllers/issues/937#issuecomment-1875040977) here maybe fix
your problem?