Question:
behaviortree-cpp not installing using apt

I tried to install behaviortree using sudo apt install ros-noetic-behaviortree-cpp* and got the following error while the system installing it:

Preparing to unpack .../ros-noetic-behaviortree-cpp-v3_3.8.5-1focal.20230814.151
459_amd64.deb ...
Unpacking ros-noetic-behaviortree-cpp-v3 (3.8.5-1focal.20230814.151459) ...
dpkg: error processing archive /var/cache/apt/archives/ros-noetic-behaviortree-c
pp-v3_3.8.5-1focal.20230814.151459_amd64.deb (--unpack):
 trying to overwrite '/opt/ros/noetic/bin/bt3_log_cat', which is also in package
 ros-noetic-behaviortree-cpp 4.4.2-1focal.20231128.201059
dpkg-deb: error: paste subprocess was killed by signal (Broken pipe)
Errors were encountered while processing:
 /var/cache/apt/archives/ros-noetic-behaviortree-cpp-v3_3.8.5-1focal.20230814.15
1459_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
I tried multiple ways to install it but was unsuccessful.

Explanation:
Internally, the dpkg command is called on the archived file path /var/cache/apt/archives/ros-noetic-behaviortree-c pp-v3_3.8.5-1focal.20230814.151459_amd64.deb. It has an error because it's unable to overwrite /opt/ros/noetic/bin/bt3_log_cat as you install the ros-noetic packages.

It seems that you have a conflicting existing package, i.e. ros-noetic-behaviortree-cpp, and that needs to be purged prior to installing the new packages. Based on your command to install all other packages, my best guess is that it's an older package, hence the conflict. We can purge/remove the older package and reinstall it.

$\begingroup$

Acc'd to your output:

    dpkg: error processing archive /var/cache/apt/archives/ros-noetic-behaviortree-c
    pp-v3_3.8.5-1focal.20230814.151459_amd64.deb (--unpack):
     trying to overwrite '/opt/ros/noetic/bin/bt3_log_cat', which is also in package
     ros-noetic-behaviortree-cpp 4.4.2-1focal.20231128.201059

Internally, the ` dpkg ` command is called on the archived file path `
/var/cache/apt/archives/ros-noetic-behaviortree-c
pp-v3_3.8.5-1focal.20230814.151459_amd64.deb ` . It has an error because it's
unable to overwrite ` /opt/ros/noetic/bin/bt3_log_cat ` as you install the
ros-noetic packages.

It seems that you have a conflicting existing package, i.e. ros-noetic-
behaviortree-cpp, and that needs to be purged prior to installing the new
packages. Based on your command to install all other packages, my best guess
is that it's an older package, hence the conflict.

See [ man dpkg
](https://manpages.ubuntu.com/manpages/noble/en/man1/dpkg.1.html)

Try the following:

    # Remove the existing package, -P or --purge
    sudo dpkg -P ros-noetic-behaviortree-cpp

Another way to fix this (not recommend), is to simply force the overwrite when
installing with ` dpkg ` .

    # Force overwrite
    sudo dpkg -i --force-overwrite /var/cache/apt/archives/ros-noetic-behaviortree-c
    pp-v3_3.8.5-1focal.20230814.151459_amd64.deb

In either case, follow up with ` sudo apt -f install ` to fix broken pipes (as
your output mentions in the following line for ` dpkg-deb ` ). Then try
running your command again.

    # Fix broken pipes
    sudo apt -f install

    # Your command
    sudo apt install ros-noetic-behaviortree-cpp*

Hope this helps.


Question:
How to get started using the C++ API for Gazebo Harmonic?

I'm completely new to gazebo and did some of the well explained tutorials to learn how the basic functionality of gazebo is working. So this is my setup:

I'm using Windows 10 and installed gazebo with WSL2 on a Ubuntu distribution. From here I did some of the tutorials and was able to interact with the simulation with the gui and also via messages from the powershell (using wsl). So from the powershell I'm able to start the simulation and also can send and receive commands to move the robot or read out some sensor data.

My plan is, to use this functionality inside of a C++ or C# application without using the powershell. So I like to use the C++ API given by gazebo.

My idea is, to write some code in Visual Studio on my Windows machine and execute this code via cross compilation on my wsl2 instance, where my actual gazebo instance is running.

My key question is, how to integrate the gazebo library into Visual Studio and to be able to interact with my gazebo instance? For the beginning i would just start a scene "my_world.sdf" and read out some sensor data.

Currently I am struggeling with the integration into Visual Studio 2022.

I would be really grateful for any advice given to this topic.

Explanation: We need to find tutorials/guidance to add ROS2 to vscode.

$\begingroup$

Gazebo Sim uses the ` gz-transport ` library as its communication layer, so if
you want to interact with a running simulation from a separate application,
you will need to use that library. See the tutorials [ here
](https://github.com/gazebosim/gz-transport/tree/gz-transport13/tutorials) and
[ here ](https://gazebosim.org/api/transport/13/tutorials.html) .

Simulation functionality in Gazebo Sim is provided by plugins (system plugins,
sensor plugins, gui plugins, physics plugin, etc). Depending on your needs,
you can use the existing plugins, or you will have to write your own plugins.
For more info on plugins, see this [ previous RSE answer
](https://robotics.stackexchange.com/a/103884/35117) .

I am not sure about Visual Studio; I use VSCode with ROS 2 per [ these
instructions ](https://www.allisonthackston.com/articles/vscode-docker-ros2)
and apart from that I just had to add the include path to the Gazebo headers.


Question:
Using standalone gazebo 11, and no gui will spawn

I am trying to use gazebo through c++ (without calling from command line). I have a main.cpp file something like following

#include <gazebo/gazebo.hh>
#include <gazebo/common/common.hh>
#include <gazebo/physics/physics.hh>

int main(int _argc, char **_argv)
{
  // Initialize gazebo.
  gazebo::setupServer(_argc, _argv);

  // Load a world
  gazebo::physics::WorldPtr world = gazebo::loadWorld("simple_world.world");

  gazebo::physics::ModelPtr robot = world->ModelByName("robot");

  while (true)
  {
    gazebo::runWorld(world, 1);
  }

  // Close everything.
  gazebo::shutdown();
}
However no gui will spawn by running this but the robot will move around if I set velocity to the robot. I can spawn gazebo gui if I use command line tools gazebo simple_world.world.

Does anyone know if I missed anything here? I would really appreciate any help here. Thank you

Explanation: We can check the developer's main file and see what they did.

$\begingroup$

The gazebo-classic simulator is implemented using two applications which work
together: gzserver and gzclient. The gui part is handled by gzclient.

The job of /usr/bin/gazebo is to launch gzserver and gzclient. All of this
code is open source, so you can easily see what the developers did to perform
this task. IIRC, the src file is ` gazebo/gazebo_main.cc ` .

[ https://github.com/gazebosim/gazebo-classic
](https://github.com/gazebosim/gazebo-classic)


Question:
Gazebo Garden: How to publish the transform of elements in a simulation

I need the depth ground truth of a camera view in gazebo and decided to go with an rgbd camera which produces a pointcloud. In order to visualize this I need to somehow publish the transform of the rgbd camera. How can I publish such a transform in gazebo? I can transfer gazebo topics to ros topics with my setup but I don't know how to publish the transforms from the simulation in the first place. Any ideas?

I am working with a gazebo garden setup where I use a gz-ros2 and ros2-ros1 bridge in order to work with ros as well (I know this is not a good setup and the endeavor is to only use ros2 at some point.)

Explanation: We can check the PosePublisher for details.

$\begingroup$

You should be able to get the rgbd camera pose through the [ pose publisher
plugin ](https://github.com/gazebosim/gz-
sim/blob/8b40b546e050ad1e8a3e08897e8146a4869d6d3e/src/systems/pose_publisher/PosePublisher.hh#L35)
.

See also the [ pose_publisher.sdf ](https://github.com/gazebosim/gz-
sim/blob/gz-sim8/examples/worlds/pose_publisher.sdf) demo world.


Question:
How to use Planner Selector in the Nav2 BT's xml file

I want to use the PlannerSelector action in Nav2 in order to use multiple planners and choose which one to use in the runtime. I modified the default behavior tree xml a little bit in order to do this, and I added a PlannerSelector BT node in my xml file as you can see in the xml file below.

The main issue is that the robot always uses the default planner. I tried to change the planner by publishing the string message "GridBased1" in the topic /planner_selector (ros2 topic pub /planner_selector std_msgs/msg/String "data: GridBased1") but the robot was still using the default planner. If I change the default planner before starting the robot and execute the process again then the planner normally changes.

To sum up, it seems that the different planners work normally when assigning them as default_planner in the PlannerSelector but the system always uses the default planner and it cannot be changed by publishing in the /planner_selector topic.

Below you can see the parameters related to planner_server:

planner_server:
 ros__parameters:
  expected_planner_frequency: 20.0
  use_sim_time: True
  planner_plugins: ["GridBased", "GridBased1"]
  GridBased:
    plugin: "nav2_navfn_planner/NavfnPlanner"
    tolerance: 0.5
    use_astar: false
    allow_unknown: true
  GridBased1:
    plugin: "nav2_straightline_planner/StraightLine"
    interpolation_resolution: 0.1
Below you can see the BT's xml file that I use:

<root main_tree_to_execute="MainTree">
 <BehaviorTree ID="MainTree">
  <RecoveryNode number_of_retries="6" name="NavigateRecovery">
   <PipelineSequence name="NavigateWithReplanning">
    <RateController hz="1.0">
      <PipelineSequence name="SelectPlanner">
        <PlannerSelector selected_planner="{selected_planner}" default_planner="GridBased" topic_name="planner_selector"/>
        <RecoveryNode number_of_retries="1" name="ComputePathToPose">
          <ComputePathToPose goal="{goal}" path="{path}" planner_id="{selected_planner}"/>
          <ReactiveFallback name="ComputePathToPoseRecoveryFallback">
            <GoalUpdated/>
            <ClearEntireCostmap name="ClearGlobalCostmap-Context" service_name="global_costmap/clear_entirely_global_costmap"/>
          </ReactiveFallback>
        </RecoveryNode>
      </PipelineSequence>
    </RateController>
    <RecoveryNode number_of_retries="1" name="FollowPath">
      <FollowPath path="{path}" controller_id="FollowPath"/>
      <ReactiveFallback name="FollowPathRecoveryFallback">
        <GoalUpdated/>
        <ClearEntireCostmap name="ClearLocalCostmap-Context" service_name="local_costmap/clear_entirely_local_costmap"/>
      </ReactiveFallback>
    </RecoveryNode>
  </PipelineSequence>
  <ReactiveFallback name="RecoveryFallback">
    <GoalUpdated/>
    <RoundRobin name="RecoveryActions">
      <Sequence name="ClearingActions">
        <ClearEntireCostmap name="ClearLocalCostmap-Subtree" service_name="local_costmap/clear_entirely_local_costmap"/>
        <ClearEntireCostmap name="ClearGlobalCostmap-Subtree" service_name="global_costmap/clear_entirely_global_costmap"/>
      </Sequence>
      <Spin spin_dist="1.57"/>
      <Wait wait_duration="5"/>
      <BackUp backup_dist="0.15" backup_speed="0.025"/>
    </RoundRobin>
  </ReactiveFallback>
 </RecoveryNode>
I am using:

turtlebot3 package for the simulation with the default launchers for the gazebo and navigation packages
ROS2 galactic
Ubuntu 20.04
If you have any workable BT xml file with a PlannerSelector feel free to share. It's not necessary to correct my specific implementation. I generally try to figure out how the PlannerSelector node is used inside the behavior tree.

Thanks

Explanation: The issue may lie in the incorrect use of QoS so that the message isn't being received due to incompatibility in the middleware. We may check an example and make some tests.

$\begingroup$

I believe your issue is not using the right QoS [1] so that the message isn't
being received due to incompatibility in the middleware. You can mess with the
QoS on the commandline, but you may be better served testing with a Python3
script to make your life easier.

[1] [ https://github.com/ros-
planning/navigation2/blob/7872bfae096ac548a4af72c12a72c025648050fa/nav2_behavior_tree/plugins/action/planner_selector_node.cpp#L44
](https://github.com/ros-
planning/navigation2/blob/7872bfae096ac548a4af72c12a72c025648050fa/nav2_behavior_tree/plugins/action/planner_selector_node.cpp#L44)


Question:
How to access URDF info inside a transmission interface?

I'm trying to write a custom transmission interface for ros2 control for the robotiq 3f, and I need access to the joint limits defined by the urdf, but the Joint handle does seem to contain that info, and I can't see any way to access the URDF. Any suggestions or good workarounds?

Explanation: We can check whether urdf information is exposed or stored in some component.

$\begingroup$

_I already had the same problem as you are describing: But this is not yet
possible directly from ros2_control side. I'll bring that up on the roadmap
for the next LTS version Jazzy. (We recently added this for controllers in the
rolling version.) In the meantime, the only workaround is to add a node to
your hardware_component and parse the URDF from a parameter or add a
subscriber to the /robot_description topic._

Edit: I was wrong, this should be possible already since [ this PR
](https://github.com/ros-controls/ros2_control/pull/709/files) : The full URDF
is inside ` hardware_info.original_xml ` .


Question:
Implementing a prismatic joint within a joint trajectory controller

I'm wondering if someone has some ideas about how to make a prismatic axis work with ros2 controllers.

I am using a UR10e which is mountd on an igus drylin ZLW 7th Axis controlled by Dryve D1. I have an API for it to communicate with the Axis to initialize, run and control it. It has an encoder so after homing I can extrapolate the exact position, velocity and other info.

I send the move command using the function xAxis.profilePositionAbs_Async(pos, setvel, acc, dec);

I have written a hardware interface with the following functions:

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

    state_interfaces.emplace_back(hardware_interface::StateInterface(
    axisName, hardware_interface::HW_IF_POSITION, &pos));

  return state_interfaces;
}

std::vector<hardware_interface::CommandInterface>
RRBotSystemPositionOnlyHardware::export_command_interfaces()
{
  std::vector<hardware_interface::CommandInterface> command_interfaces;
    command_interfaces.emplace_back(hardware_interface::CommandInterface(
    axisName, hardware_interface::HW_IF_POSITION, &pos));

  return command_interfaces;
}

hardware_interface::CallbackReturn RRBotSystemPositionOnlyHardware::on_deactivate(
  const rclcpp_lifecycle::State & /*previous_state*/)
{
    xAxis.waitForReady();
    xAxis.setShutdown();

    // Gracefully close everything down

    close(xAxis.sock);
  return hardware_interface::CallbackReturn::SUCCESS;
}

hardware_interface::return_type RRBotSystemPositionOnlyHardware::read(
  const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/)
{

  pos=xAxis.getCurrentPosInMM()/1000;
  std::cout << "position in meters" << pos << std::endl;

  return hardware_interface::return_type::OK;
}

hardware_interface::return_type RRBotSystemPositionOnlyHardware::write(
  const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/)
{

  xAxis.profilePositionAbs_Async(pos*1000, setvel, acc, dec);

  return hardware_interface::return_type::OK;
}
Now the problem is, as the profilePositionAbs_Async function is within the write function it gets called every loop, meaning the movement gets rerun continuously leading to a continuous accel- and deceleration.

Also I seem to get issues due to the position parameter being used in both the state and command interface.

So i was wondering, what is the best way to incorporate such an axis in a joint trajectory controller and handle the state/command interference

EDIT: in order to elaborate on @ChristophFroehlich's reply i have added the description of the possible functions to interact with the driver:

        void profilePositionAbs(float position, float velo, float accel, float decel=0); // Function "Profile Position Mode"; Move to an absolute position with given velocity, acceleration and deceleration
        void profilePositionRel(float position, float velo, float accel, float decel=0); // Function "Profile Position Mode"; Move to an relative position with given velocity, acceleration and deceleration
        void profileVelocity(float velo, float accel, float decel=0); // Function "Profile Position Mode"; Move with a set target velocity, acceleration and deceleration; Movement starts directly when the target velocity is not 0```

Explanation: We can use the velocity interface of your drive, and use the joint_trajectory_controller with position control and velocity command interface.

$\begingroup$

Without knowing details of the underlying implementation of your drive, I can
only guess:

  * If the drive takes new position commands without stopping the old target, you can use position command and regularily send a new setpoint, sampled by JTC. Then the drive might have safe software-end stops implemented etc.
  * use the velocity interface of your drive, and use the joint_trajectory_controller with position control and velocity command interface. Unclear if end-stops work then?

If you use the latter one: (More information [ in the docs
](https://control.ros.org/humble/doc/ros2_controllers/joint_trajectory_controller/doc/userdoc.html)
)

    command_interfaces:
      - velocity

    state_interfaces:
      - position
      - velocity

In the write method of the hardware component, you send the velocity to the
hardware coming from the command interfaces. In the read method you get the
data from your encoders, calculate the velocity from the signal, and update
the state interfaces.


Question:
Issues with Sending ROS2 Action from roslib.js to rosbridge_suite: Unable to Import Message Classes

I'm encountering difficulties sending a ROS2 action from roslib.js to rosbridge_suite. The action is supposed to be handled by rosbridge_suite, but I'm encountering issues related to the import of message classes, such as "Unable to import msg class FollowJointTrajectoryGoal from package control_msgs."

My setup:

Ubuntu 22.04.2 LTS (Jammy) running on Windows 11 wsl
ROS2 @ rolling distribution
roslib.js @ ros2 branch ( commit 6a63a03 )
rosbridge_suite @ ros2-actions branch ( commit 692f41a )
ROS_PYTHON_VERSION=3
This is the example action I'm trying to send from roslib.js to rosbridge:

ros2 action send_goal /ur5e/ur_joint_trajectory_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory "{
  trajectory: {
    joint_names: [shoulder_pan_joint, shoulder_lift_joint, elbow_joint, wrist_1_joint, wrist_2_joint, wrist_3_joint],
    points: [
      { positions: [3.02, -1.63, -1.88, 1.01, 1.51, 1.13], time_from_start: { sec: 5, nanosec: 500 } },
      { positions: [-1.01, 0.38, -0.63, -0.88, 0.25, -1.63], time_from_start: { sec: 6, nanosec: 500 } },
      { positions: [-1.01, 0.38, -0.63, -0.88, 0.25, 6.2], time_from_start: { sec: 50, nanosec: 500 } }
    ]
  },
  goal_tolerance: [
    { name: shoulder_pan_joint, position: 0.01 },
    { name: shoulder_lift_joint, position: 0.01 },
    { name: elbow_joint, position: 0.01 },
    { name: wrist_1_joint, position: 0.01 },
    { name: wrist_2_joint, position: 0.01 },
    { name: wrist_3_joint, position: 0.01 }
  ]
}"
I use the latest roslib.js build from ros2-actions branch and I built and ran rosbridge_websocket (ros2 branch) with the following terminal commands. I could only find ROS1 rosbridge building steps. I modified the steps after some research.

source /opt/ros/rolling/setup.bash
mkdir ~/ws
mkdir ~/ws/src
cd ~/ws/src
git clone https://github.com/RobotWebTools/rosbridge_suite.git -b ros2
cd ~/ws
sudo apt install python3-colcon-common-extensions
colcon build --symlink-install
colcon test
source install/setup.bash
ros2 run rosbridge_server rosbridge_websocket
Here's my javascript code for sending the action using roslib.js:

/* eslint-disable no-undef */

import "./roslib.js"; // https://github.com/RobotWebTools/roslibjs/blob/ros2-actions/build/roslib.js

class RosController {
    constructor() {
        this.ros = new ROSLIB.Ros({
            url: "ws://localhost:9090",
        });

        this.ros.on('error', (error) => {
            console.error('Error connecting to ROS:', error);
        });

        // Create an action client
        this.actionClient = new ROSLIB.ActionClient({
            ros: this.ros,
            serverName: '/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory',
            actionName: 'control_msgs/action/FollowJointTrajectory'
        });

        // Create a goal
        this.goal = new ROSLIB.Goal({
            actionClient: this.actionClient,
            goalMessage: {
                trajectory: {
                    joint_names: ['shoulder_pan_joint', 'shoulder_lift_joint', 'elbow_joint', 'wrist_1_joint', 'wrist_2_joint', 'wrist_3_joint'],
                    points: [
                        { positions: [3.02, -1.63, -1.88, 1.01, 1.51, 1.13], time_from_start: { sec: 5, nanosec: 500 } },
                        { positions: [-1.01, 0.38, -0.63, -0.88, 0.25, -1.63], time_from_start: { sec: 6, nanosec: 500 } },
                        { positions: [-1.01, 0.38, -0.63, -0.88, 0.25, 6.2], time_from_start: { sec: 50, nanosec: 500 } }
                    ]
                },
                goal_tolerance: [
                    { name: 'shoulder_pan_joint', position: 0.01 },
                    { name: 'shoulder_lift_joint', position: 0.01 },
                    { name: 'elbow_joint', position: 0.01 },
                    { name: 'wrist_1_joint', position: 0.01 },
                    { name: 'wrist_2_joint', position: 0.01 },
                    { name: 'wrist_3_joint', position: 0.01 }
                ]
            }
        });

        // Check the status of the goal
        this.goal.on('status', (status) => {
            console.log('Goal status: ' + status.status);
            if (status.status === 5) { // 5 is the status code for REJECTED
                console.error('Goal was rejected');
            }
        });

        this.ros.on('error', (error) => {
            console.error('Error connecting to ROS:', error);
        });

        this.ros.on('connection', () => {
            console.log('Connected to websocket server.');
            // ROS is connected, now you can send the goal
            this.moveUR5eRobot();
        });

        this.ros.on('close', function () {
            console.log('Connection to websocket server closed.');
        });

        // Optional: Listen for result or feedback
        this.goal.on('result', (result) => {
            console.log('Action completed successfully:', result);
        });

        this.goal.on('feedback', (feedback) => {
            console.log('Received feedback:', feedback);
        });

        // Optional: Handle errors
        this.goal.on('timeout', () => {
            console.error('Action did not complete before timeout');
        });
    }

    getRos() {
        return this.ros;
    }

    /*
    https://docs.ros.org/en/iron/Tutorials/Advanced/Simulators/Webots/Installation-Windows.html#launch-the-webots-ros2-universal-robot-example
    https://index.ros.org/p/webots_ros2_universal_robot/#humble-overview
    https://github.com/cyberbotics/webots_ros2/wiki/Example-Universal-Robots
    */
    moveUR5eRobot() {
        console.log("moveUR5eRobot");
        // Send the goal
        this.goal.send();
    }

}

export { RosController };
The rosbridge_suite prints errors indicating problems with importing message classes. I've tried both the rolling and iron distributions, and the issue persists. Am I missing something in my setup, or could the problem be in rosbridge or roslib.js?

tapani@Desktop:~/ws$ ros2 run rosbridge_server rosbridge_websocket
registered capabilities (classes):
 - <class 'rosbridge_library.capabilities.advertise.Advertise'>
 - <class 'rosbridge_library.capabilities.publish.Publish'>
 - <class 'rosbridge_library.capabilities.subscribe.Subscribe'>
 - <class 'rosbridge_library.capabilities.defragmentation.Defragment'>
 - <class 'rosbridge_library.capabilities.advertise_service.AdvertiseService'>
 - <class 'rosbridge_library.capabilities.call_service.CallService'>
 - <class 'rosbridge_library.capabilities.service_response.ServiceResponse'>
 - <class 'rosbridge_library.capabilities.unadvertise_service.UnadvertiseService'>
 - <class 'rosbridge_library.capabilities.advertise_action.AdvertiseAction'>
 - <class 'rosbridge_library.capabilities.action_feedback.ActionFeedback'>
 - <class 'rosbridge_library.capabilities.action_result.ActionResult'>
 - <class 'rosbridge_library.capabilities.send_action_goal.SendActionGoal'>
 - <class 'rosbridge_library.capabilities.unadvertise_action.UnadvertiseAction'>
[INFO] [1702467864.667909416] [rosbridge_websocket]: Rosbridge WebSocket server started on port 9090
[INFO] [1702467884.421195988] [rosbridge_websocket]: Calling services in existing thread
[INFO] [1702467884.421448867] [rosbridge_websocket]: Sending action goals in existing thread
[INFO] [1702467884.421979997] [rosbridge_websocket]: Client connected. 1 clients total.
[ERROR] [1702467885.354114994] [rosbridge_websocket]: [Client 27351158-07e8-47e7-9dba-7d897476db2e] [id: advertise:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal:1] advertise: Unable to import msg class FollowJointTrajectoryGoal from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryGoal'
[INFO] [1702467885.359658954] [rosbridge_websocket]: [Client 27351158-07e8-47e7-9dba-7d897476db2e] Subscribed to /ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/status
[ERROR] [1702467885.359900905] [rosbridge_websocket]: [Client 27351158-07e8-47e7-9dba-7d897476db2e] [id: subscribe:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/feedback:4] subscribe: Unable to import msg class FollowJointTrajectoryFeedback from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryFeedback'
[ERROR] [1702467885.360110707] [rosbridge_websocket]: [Client 27351158-07e8-47e7-9dba-7d897476db2e] [id: subscribe:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/result:5] subscribe: Unable to import msg class FollowJointTrajectoryResult from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryResult'
[ERROR] [1702467885.360289265] [rosbridge_websocket]: [Client 27351158-07e8-47e7-9dba-7d897476db2e] [id: publish:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal:7] publish: Cannot infer topic type for topic /ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal as it is not yet advertised
[ERROR] [1702467885.360480628] [rosbridge_websocket]: [Client 27351158-07e8-47e7-9dba-7d897476db2e] [id: subscribe:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/result:6] subscribe: Unable to import msg class FollowJointTrajectoryResult from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryResult'
[INFO] [1702467885.491837270] [rosbridge_websocket]: Calling services in existing thread
[INFO] [1702467885.492038974] [rosbridge_websocket]: Sending action goals in existing thread
[INFO] [1702467885.492506295] [rosbridge_websocket]: Client connected. 2 clients total.
[ERROR] [1702467886.352260753] [rosbridge_websocket]: [Client 01c40dd7-4ffc-4c64-abb8-bd477e5c49a0] [id: advertise:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal:1] advertise: Unable to import msg class FollowJointTrajectoryGoal from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryGoal'
[INFO] [1702467886.397142045] [rosbridge_websocket]: [Client 01c40dd7-4ffc-4c64-abb8-bd477e5c49a0] Subscribed to /ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/status
[ERROR] [1702467886.397518737] [rosbridge_websocket]: [Client 01c40dd7-4ffc-4c64-abb8-bd477e5c49a0] [id: subscribe:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/feedback:4] subscribe: Unable to import msg class FollowJointTrajectoryFeedback from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryFeedback'
[ERROR] [1702467886.398005589] [rosbridge_websocket]: [Client 01c40dd7-4ffc-4c64-abb8-bd477e5c49a0] [id: subscribe:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/result:5] subscribe: Unable to import msg class FollowJointTrajectoryResult from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryResult'
[ERROR] [1702467886.398194954] [rosbridge_websocket]: [Client 01c40dd7-4ffc-4c64-abb8-bd477e5c49a0] [id: publish:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal:7] publish: Cannot infer topic type for topic /ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal as it is not yet advertised
[ERROR] [1702467886.398401323] [rosbridge_websocket]: [Client 01c40dd7-4ffc-4c64-abb8-bd477e5c49a0] [id: subscribe:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/result:6] subscribe: Unable to import msg class FollowJointTrajectoryResult from package control_msgs. Caused by module 'control_msgs.msg' has no attribute 'FollowJointTrajectoryResult'
[ERROR] [1702467887.947030067] [rosbridge_websocket]: [Client 01c40dd7-4ffc-4c64-abb8-bd477e5c49a0] [id: publish:/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal:8] publish: Cannot infer topic type for topic /ur5e/ur_joint_trajectory_controller/follow_joint_trajectory/goal as it is not yet advertised
Related roslib.js github issue: https://github.com/RobotWebTools/roslibjs/issues/646

$\begingroup$

The solution was to use ROS2 roslib.js classes for action client and action
goal: [
https://github.com/RobotWebTools/roslibjs/issues/646#issuecomment-1855739957
](https://github.com/RobotWebTools/roslibjs/issues/646#issuecomment-1855739957)

Fixed to use ROS2 classes:

    // Create an action client.
    this.actionClient = new ROSLIB.Action({
        ros: this.ros,
        name: '/ur5e/ur_joint_trajectory_controller/follow_joint_trajectory',
        actionType: 'control_msgs/FollowJointTrajectory'
    });

    // Create a goal
    this.goal = new ROSLIB.ActionGoal({
        trajectory: {
            joint_names: ['shoulder_pan_joint', 'shoulder_lift_joint', 'elbow_joint', 'wrist_1_joint', 'wrist_2_joint', 'wrist_3_joint'],
            points: [
                { positions: [3.02, -1.63, -1.88, 1.01, 1.51, 1.13], time_from_start: { sec: 5, nanosec: 500 } },
                { positions: [-1.01, 0.38, -0.63, -0.88, 0.25, -1.63], time_from_start: { sec: 6, nanosec: 500 } },
                { positions: [-1.01, 0.38, -0.63, -0.88, 0.25, 6.2], time_from_start: { sec: 50, nanosec: 500 } }
            ]
        },
        goal_tolerance: [
            { name: 'shoulder_pan_joint', position: 0.01 },
            { name: 'shoulder_lift_joint', position: 0.01 },
            { name: 'elbow_joint', position: 0.01 },
            { name: 'wrist_1_joint', position: 0.01 },
            { name: 'wrist_2_joint', position: 0.01 },
            { name: 'wrist_3_joint', position: 0.01 }
        ]
    });

    // Send the goal , following the example from https://github.com/RobotWebTools/roslibjs/blob/ros2-actions/examples/ros2_action_client.html
    var goal_id = this.actionClient.sendGoal(this.goal,
        (result) => {
            console.log('Result for action goal on ' + this.actionClient.name + ': ' + result.result.sequence);
        },
        (feedback) => {
            console.log('Feedback for action on ' + this.actionClient.name + ': ' + feedback.partial_sequence);
        },
    );


Question:
ROS2: Adding parameters to YAML launch file

How do I use a YAML launch file to pass parameters to a node? The tutorial covers passing parameters using a python launch file but not YAML.

Explanation: We can check the sample yaml file about how to launch file using yaml parameters.

$\begingroup$

I made a working example [ here
](https://github.com/danzimmerman/dz_launch_examples/blob/rolling/launch/yaml_param_passing.launch.yaml)
.

In ` dz_launch_examples/launch/yaml_param_passing.launch.yaml ` I have launch
file contents:

    launch:
    - node:
        pkg: "turtlesim"
        exec: "turtlesim_node"
        name: "sim"
        namespace: "turtlesim_dz"
        param:
          -
            from: $(find-pkg-share dz_launch_examples)/config/turtlesim_custom_params.yaml

and I have a parameter file `
dz_launch_examples/config/turtlesim_custom_params.yaml ` with the contents:

    /turtlesim_dz/sim:
      ros__parameters:
        background_b: 0
        background_g: 204
        background_r: 255
        use_sim_time: false

This runs a turtlesim node with an orange background color.

I've found that the [ migration guide from ROS 1 to ROS 2
](https://docs.ros.org/en/rolling/How-To-Guides/Migrating-from-ROS1/Migrating-
Launch-Files.html) can be helpful in discovering how to do things in ROS 2
launch.

In working out some of the launch examples [ here
](https://github.com/danzimmerman/dz_launch_examples/) , I've observed that
YAML syntax closely mirrors XML examples, even if that results in (in my
opinion) a non-obvious syntax for the YAML.

In XML, passing parameters from file in ROS 2 is described [ here
](https://docs.ros.org/en/rolling/How-To-Guides/Migrating-from-ROS1/Migrating-
Launch-Files.html#rosparam) . It uses the ` from ` attribute in a ` <param> `
tag:

    <node pkg="my_package" exec="my_executable" name="my_node" ns="/an_absolute_ns">
       <param from="/path/to/file"/>
    </node>

In YAML this becomes:

    - node:
        pkg: "my_package"
        exec: "my_executable"
        name: "my_node"
        namespace: "/an_absolute_ns"
        param:
          -
            from: "/path/to/file"


Question:
URDF surface tags are not propagated to gazebo

I am struggling to set friction to my model in gazebo. Issue is it is frictionless. It is walking in place and cannot move. I set my tags according to this document SDFormat but they are not visible in link inspection in Gazebo. Looks like surface tag is not propagated at all. I got gazebo 11.10.2 .

Explanation: We need to check the tag/element for gazebo, link and robot.

$\begingroup$

I figured it out. You need to insert all tags inside < gazebo
reference="link_name"> tag under < robot> tag and not under < link> tag. Here
is document [ GazeboURDF
](http://classic.gazebosim.org/tutorials?tut=ros_urdf&cat=connect_ros#%3Ccollision%3Eand%3Cvisual%3Eelements)
. Like this works for me:

    <robot xmlns:xacro="http://www.ros.org/wiki/xacro">
    <gazebo reference="link_name">
        <minDepth>0.01</minDepth>
        <material>Gazebo/Orange</material>
        <mu2>0.23</mu2>
    </gazebo>
    <link name="link_name">
    (other tags ...)
    </link>
    </robot>


Question:
Create message which is array of submessages?

Let's say I created a custom message in ROS2. How would I create a second meta message consisting of an array of those messages?

The documentation tutorial is very poor on creating anything but trivial messages.

Explanation: To figure out how to implement, we can check the available message types.

$\begingroup$

Typically messages contain a timestamp and a reference frame. If one needs an
array of data, that array is typically created inside the custom message. If
one is looking to use a custom message type for multiple sensors or actuators,
the ROS convention is to publish each sensor or actuator separately rather
than aggregating them into a single publisher.

There examples of building messages consisting of other message types in the `
geometry_msgs ` library: [
https://docs.ros.org/en/noetic/api/geometry_msgs/html/index-msg.html
](https://docs.ros.org/en/noetic/api/geometry_msgs/html/index-msg.html) . In
particular "Polygon", "PolygonStamped", and "PoseWithCovariance" might be good
examples.


Question:
How can i show on my browser what i see on Rviz?

Im on ROS2-Humble and i want to see my robot's location and movement on the map, the way i see it on Rviz, on my browser. For example, I want from Rviz to get the Grid, RobotModel, TF, and Map, send it on my browser and show it there, kinda like streaming it or rendering it via a .js file and .html. Im new with ROS2 and i cant seem to find any sources to help me. Most of the things i find are for ROS1 and Chat GPT doesnt help at all. Basically something like this: https://answers.ros.org/question/319626/real-time-map-generate-on-web-like-a-rviz/

Any tips/help would be greatly appreciated, thanks in advance!

Explanation: An alternative is to use rosbridge, which provides a JSON API to ROS functionality for non-ROS programs.

$\begingroup$

I assume it is not your intention to use third party tools but these worth
giving a try:

  * [ Foxglove ](https://foxglove.dev/ros)
  * [ webviz ](https://webviz.io/)

If you don't want to deal with these, then by using **rosbridge_suite** you
can do so: [ rosbridge_suite wiki ](https://wiki.ros.org/rosbridge_suite)


Question:
Simple takeoff then do yaw rotation

Arming and takeoff work fine but i don't know how to do yaw rotation:

class controller:
    def __init__(self):

        rospy.Subscriber('mavros/state', State, self.state_cb)

        self.state = State()

    def state_cb(self, msg):
        self.state = msg

    def move(self,x,y,z):
        pub_posisi = rospy.Publisher("/mavros/setpoint_velocity/cmd_vel",TwistStamped,queue_size=1)
        pub_data = TwistStamped()

        pub_data.twist.linear.x = x
        pub_data.twist.linear.y = y
        pub_data.twist.linear.z = z

        pub_posisi.publish(pub_data)

        time.sleep(5)

    def position(self,x,y,z):
        pub_posisi = rospy.Publisher("/mavros/setpoint_position/local",PoseStamped,queue_size=10)
        posisi = PoseStamped()

        posisi.pose.position.x = x
        posisi.pose.position.y = y
        posisi.pose.position.z = z

        q = quaternion_from_euler(0.0,0.0,3.0)

        posisi.pose.orientation.x = q[0]
        posisi.pose.orientation.y = q[1]
        posisi.pose.orientation.z = q[2]
        posisi.pose.orientation.w = q[3]

        pub_posisi.publish(posisi)

        rospy.loginfo(f"go to point {x,y,z}")

        time.sleep(15)

Explanation: To do this with the existing functions we can modify the position function to take a yaw value. For example, quaternion_from_euler(ai, aj, ak, axes='sxyz') takes a yaw value in radians for the ak parameter.

$\begingroup$

To do this with your existing functions you can modify the position function
to take a yaw value. quaternion_from_euler(ai, aj, ak, axes='sxyz') takes a
yaw value in radians for the ak parameter. You can find this in the [
tf.transformations docs
](http://docs.ros.org/en/jade/api/tf/html/python/transformations.html) .

    def position(self,x,y,z,yaw):
            pub_posisi = rospy.Publisher("/mavros/setpoint_position/local",PoseStamped,queue_size=10)
            posisi = PoseStamped()

            posisi.pose.position.x = x
            posisi.pose.position.y = y
            posisi.pose.position.z = z

            q = quaternion_from_euler(0.0,0.0,yaw)

            posisi.pose.orientation.x = q[0]
            posisi.pose.orientation.y = q[1]
            posisi.pose.orientation.z = q[2]
            posisi.pose.orientation.w = q[3]

            pub_posisi.publish(posisi)

            rospy.loginfo(f"go to point {x,y,z} with yaw {yaw}")

            time.sleep(15)

Hope this helps! :)


Question:
irobot create3 topics not found after setup in macos multipass vm

I have a Mac OS 14.1 and I'm seting up irobot Create3 for the first time. I've confirmed the robot works using the python web playground.

I've installed Multipass 1.12.2+mac and created an Ubuntu 22.04 instance and installed ROS2 per the robot humble setup guide. I created the multipass instance with this command:

multipass launch --name=create3 --cpus=2 --disk=20GiB
When listing the topics, I don't see any of the expected irobot topics

ros2 topic list
Actual:

/parameter_events
/rosout
Expected:

/battery_state
/cliff_intensity
/cmd_audio ...
The VM info multipass info create3:

Name:           create3
State:          Running
IPv4:           10.211.67.3
                172.17.0.1
Release:        Ubuntu 22.04.3 LTS
Image hash:     054db2d88c45 (Ubuntu 22.04 LTS)
CPU(s):         2
Load:           0.00 0.14 0.12
Disk usage:     8.8GiB out of 19.3GiB
Memory usage:   248.8MiB out of 3.8GiB
Mounts:         --

Explanation: We need to check possible ways to communicate over a network between a virtual machine (VM) and the Create® 3 robot using ROS 2.

$\begingroup$

Per the [ Network Reccommendations
](https://iroboteducation.github.io/create3_docs/setup/network-config/) ,
Bridged Network is required:

> While many virtualization applications default to a "shared" or "NAT"
> network connection, this type of connection will not allow ROS 2 to
> communicate with the Create® 3 robot. Instead, a bridged network connection
> should be used for the virtual machine.

Creating a multipass instance with ` --bridged ` fixes:

    multipass launch --name=create3-bridged --bridged --cpus=2 --disk=20GiB

VM Infor ` multipass info create3-bridged ` :

    Name:           create3-bridged
    State:          Running
    IPv4:           10.211.67.5
                    192.168.0.153
    Release:        Ubuntu 22.04.3 LTS
    Image hash:     054db2d88c45 (Ubuntu 22.04 LTS)
    CPU(s):         2
    Load:           1.38 0.90 0.47
    Disk usage:     2.5GiB out of 19.3GiB
    Memory usage:   204.5MiB out of 951.1MiB

Notice previously, the IP was ` 172.17.0.1 ` but now is ` 192.168.0.153 `
which matches my home network.

` ros2 topic list ` now produces:

    /battery_state
    /cliff_intensity
    /cmd_audio
    /cmd_lightring
    /cmd_vel
    /dock
    /hazard_detection
    /imu
    /interface_buttons
    /ir_intensity
    /ir_opcode
    /kidnap_status
    /mobility_monitor/transition_event
    /mouse
    /odom
    /parameter_events
    /robot_state/transition_event
    /rosout
    /slip_status
    /static_transform/transition_event
    /stop_status
    /tf
    /tf_static
    /wheel_status
    /wheel_ticks
    /wheel_vels


Question:
executable '[<launch.substitutions.text_substitution.TextSubstitution>]' not found on the PATH

I am trying to launch the first example from the ros2 control demo package: https://github.com/ros-controls/ros2_control_demos/tree/humble. I am using ROS2 humble on ubuntu 22.04. First I built every package successfully, then sourced the install/setup.bash and started the launchfile with:

ros2 launch ros2_control_demo_example_1 view_robot.launch.py
But I received the following Error.

[ERROR] [launch]: Caught exception in launch (see debug for traceback): executable '[<launch.substitutions.text_substitution.TextSubstitution object at 0x7f6a81793cd0>]' not found on the PATH
I did not change any code from the example. It would be nice if somebody could help me or tell me what the problem is?

Here is my Traceback:

[DEBUG] [launch.launch_context]: emitting event synchronously: 'launch.events.IncludeLaunchDescription'
[INFO] [launch]: All log files can be found below /home/user/.ros/log/date
[INFO] [launch]: Default logging verbosity is set to DEBUG
[DEBUG] [launch]: processing event: '<launch.events.include_launch_description.IncludeLaunchDescription object at 0x7f6a8632e3e0>'
[DEBUG] [launch]: processing event: '<launch.events.include_launch_description.IncludeLaunchDescription object at 0x7f6a8232e3e0>' ✓ '<launch.event_handlers.on_include_launch_description.OnIncludeLaunchDescription object at 0x7f6a8236d8a0>'
Executing <Task finished name='Task-2' coro=<LaunchService._process_one_event() done, defined at /opt/ros/humble/lib/python3.10/site-packages/launch/launch_service.py:228> exception=SubstitutionFailure("executable '[<launch.substitutions.text_substitution.TextSubstitution object at 0x7f6a81793cd0>]' not found on the PATH") created at /opt/ros/humble/lib/python3.10/site-packages/launch/launch_service.py:318> took 0.133 seconds
[DEBUG] [launch]: An exception was raised in an async action/event
[DEBUG] [launch]: Traceback (most recent call last):
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/launch_service.py", line 336, in run_async
    raise completed_tasks_exceptions[0]
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/launch_service.py", line 230, in _process_one_event
    await self.__process_event(next_event)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/launch_service.py", line 250, in __process_event
    visit_all_entities_and_collect_futures(entity, self.__context))
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
    futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
    futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 45, in visit_all_entities_and_collect_futures
    futures_to_return += visit_all_entities_and_collect_futures(sub_entity, context)
  [Previous line repeated 1 more time]
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 38, in visit_all_entities_and_collect_futures
    sub_entities = entity.visit(context)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/action.py", line 108, in visit
    return self.execute(context)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch_ros/actions/node.py", line 490, in execute
    self._perform_substitutions(context)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch_ros/actions/node.py", line 445, in _perform_substitutions
    evaluated_parameters = evaluate_parameters(context, self.__parameters)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch_ros/utilities/evaluate_parameters.py", line 164, in evaluate_parameters
    output_params.append(evaluate_parameter_dict(context, param))
  File "/opt/ros/humble/lib/python3.10/site-packages/launch_ros/utilities/evaluate_parameters.py", line 72, in evaluate_parameter_dict
    evaluated_value = perform_substitutions(context, list(value))
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/perform_substitutions_impl.py", line 26, in perform_substitutions
    return ''.join([context.perform_substitution(sub) for sub in subs])
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/perform_substitutions_impl.py", line 26, in <listcomp>
    return ''.join([context.perform_substitution(sub) for sub in subs])
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/launch_context.py", line 240, in perform_substitution
    return substitution.perform(self)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/substitutions/command.py", line 94, in perform
    command_str = perform_substitutions(context, self.command)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/perform_substitutions_impl.py", line 26, in perform_substitutions
    return ''.join([context.perform_substitution(sub) for sub in subs])
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/utilities/perform_substitutions_impl.py", line 26, in <listcomp>
    return ''.join([context.perform_substitution(sub) for sub in subs])
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/launch_context.py", line 240, in perform_substitution
    return substitution.perform(self)
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/substitutions/path_join_substitution.py", line 45, in perform
    performed_substitutions = [sub.perform(context) for sub in self.__substitutions]
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/substitutions/path_join_substitution.py", line 45, in <listcomp>
    performed_substitutions = [sub.perform(context) for sub in self.__substitutions]
  File "/opt/ros/humble/lib/python3.10/site-packages/launch/substitutions/find_executable.py", line 66, in perform
    raise SubstitutionFailure("executable '{}' not found on the PATH".format(self.name))
launch.substitutions.substitution_failure.SubstitutionFailure: executable '[<launch.substitutions.text_substitution.TextSubstitution object at 0x7f6a81793cd0>]' not found on the PATH

[ERROR] [launch]: Caught exception in launch (see debug for traceback): executable '[<launch.substitutions.text_substitution.TextSubstitution object at 0x7f6a81793cd0>]' not found on the PATH
[DEBUG] [launch.launch_context]: emitting event: 'launch.events.Shutdown'
[DEBUG] [launch]: processing event: '<launch.events.shutdown.Shutdown object at 0x7f6a8232e140>'
[DEBUG] [launch]: processing event: '<launch.events.shutdown.Shutdown object at 0x7f6a8232e140>' ✓ '<launch.event_handlers.on_shutdown.OnShutdown object at 0x7f6a8171cbb0>'
[DEBUG] [launch]: processing event: '<launch.events.shutdown.Shutdown object at 0x7f6a8232e140>' ✓ '<launch.event_handlers.on_shutdown.OnShutdown object at 0x7f6a8232c9a0>'

Explanation: This is related to the missing dependency. We need to check steps to build packages.

$\begingroup$

The solution was that I had to install all the dependencies with rosdep. I
forgot this step. Thank you @ChristophFroehlich

Follow the [ tutorial
](https://control.ros.org/master/doc/ros2_control_demos/doc/index.html#build-
from-debian-packages) on how to build the ros2 control demos:


Question:
octomap_msgs/conversions.h: No such file or directory

Using 64-bit Ubuntu 22.04.3 LTS On "colcon build" I'm recieving the following error:

/home/ajifoster3/dev_ws/src/octomap_publisher/src/octomap_publisher_node.cpp:2:10: fatal error: octomap_msgs/conversions.h: No such file or directory
    2 | #include <octomap_msgs/conversions.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
gmake[2]: *** [CMakeFiles/octomap_publisher_node.dir/build.make:76: CMakeFiles/octomap_publisher_node.dir/src/octomap_publisher_node.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:137: CMakeFiles/octomap_publisher_node.dir/all] Error 2
gmake: *** [Makefile:146: all] Error 2
---
Failed   <<< octomap_publisher [0.17s, exited with code 2]
opt/ros/humble/include/octomap_msgs has a file called conversions.h

My ros node:

#include <octomap/OcTree.h>
#include <octomap_msgs/conversions.h>
#include <rclcpp/rclcpp.hpp>

class OctomapPublisher : public rclcpp::Node {
public:
    OctomapPublisher() : Node("octomap_publisher") {
        this->declare_parameter<std::string>("octomap_file", "/home/ajifoster3/occupancy_map_full.txt");
        std::string octomap_file;
        this->get_parameter("octomap_file", octomap_file);

        auto tree = std::make_shared<octomap::OcTree>(octomap_file);
        octomap_msgs::msg::Octomap octomap_msg;
        octomap_msgs::binaryMapToMsg(*tree, octomap_msg);

        publisher_ = this->create_publisher<octomap_msgs::msg::Octomap>("octomap", 1);
        timer_ = this->create_wall_timer(
            std::chrono::milliseconds(1000),
            [this, octomap_msg]() {
                publisher_->publish(octomap_msg);
            });
    }

private:
    rclcpp::Publisher<octomap_msgs::msg::Octomap>::SharedPtr publisher_;
    rclcpp::TimerBase::SharedPtr timer_;
};

int main(int argc, char** argv) {
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<OctomapPublisher>());
    rclcpp::shutdown();
    return 0;
}
my CMakeLists.txt is the following

cmake_minimum_required(VERSION 3.8)
project(octomap_publisher)

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

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(octomap_msgs REQUIRED)

add_executable(octomap_publisher_node src/octomap_publisher_node.cpp)

ament_target_dependencies(octomap_publisher_node rclcpp octomap_msgs)

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

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()
package.xml:

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>octomap_publisher</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="ajifoster3@gmail.com">ajifoster3</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>rclcpp</depend>
  <depend>octomap_msgs</depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

Explanation: The CMakeLists.txt file needs to specify the version of c++ standard. We can check example CMakeLists.txt file.

$\begingroup$

I'm not exactly sure of the solution to my problem, but I resolved it. The
following is my current source code, CMakeList.txt and package.xml.

octomap_publisher_node.cpp

    #include <rclcpp/rclcpp.hpp>
    #include <octomap/octomap.h>
    #include <octomap_msgs/conversions.h>
    #include <octomap_msgs/msg/octomap.hpp>
    #include <iostream>

    class OctomapPublisher : public rclcpp::Node
    {
    public:
        OctomapPublisher(const std::string& octree_file)
            : Node("octomap_publisher"), octree_file_(octree_file)
        {
            publisher_ = this->create_publisher<octomap_msgs::msg::Octomap>("octomap", 10);
            timer_ = this->create_wall_timer(
                std::chrono::milliseconds(500),
                std::bind(&OctomapPublisher::publishOctomap, this));
        }

    private:
        void publishOctomap()
        {
            octomap::OcTree* tree = nullptr;

            // Load the octree from the OT file
            tree = dynamic_cast<octomap::OcTree*>(octomap::AbstractOcTree::read(octree_file_));
            if (!tree) {
                RCLCPP_ERROR(this->get_logger(), "Failed to read octree from file");
                return;
            }

            // Convert the octree to a message
            octomap_msgs::msg::Octomap msg;
            octomap_msgs::binaryMapToMsg(*tree, msg);
            msg.header.frame_id = "map";
            msg.header.stamp = this->now();

            // Publish the message
            publisher_->publish(msg);

            delete tree; // Clean up
        }

        std::string octree_file_;
        rclcpp::Publisher<octomap_msgs::msg::Octomap>::SharedPtr publisher_;
        rclcpp::TimerBase::SharedPtr timer_;
    };

    int main(int argc, char **argv)
    {
        rclcpp::init(argc, argv);

        if (argc < 2) {
            std::cerr << "Usage: octomap_publisher <octree_file.ot>" << std::endl;
            return 1;
        }

        auto octomap_publisher = std::make_shared<OctomapPublisher>(argv[1]);
        rclcpp::spin(octomap_publisher);

        rclcpp::shutdown();
        return 0;
    }

CMakeList.txt

    cmake_minimum_required(VERSION 3.5)
    project(octomap_publisher)

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

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

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

    # Find dependencies
    find_package(ament_cmake REQUIRED)
    find_package(rclcpp REQUIRED)
    find_package(octomap REQUIRED)
    find_package(octomap_msgs REQUIRED)
    find_package(octomap_server REQUIRED)

    # Include C++ libraries
    include_directories(
      include
    )

    # Declare a C++ executable
    add_executable(octomap_publisher_node src/octomap_publisher_node.cpp)

    ament_target_dependencies(octomap_publisher_node
      rclcpp
      octomap
      octomap_msgs
      octomap_server
      )

    # Specify libraries to link a library or executable target against
    target_link_libraries(octomap_publisher_node
      ${OCTOMAP_LIBRARIES}
    )

    # Specify libraries to link a

    # Install targets
    install(TARGETS
      octomap_publisher_node
      DESTINATION lib/${PROJECT_NAME}
    )
    ament_package()

package.xml

    <?xml version="1.0"?>
    <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
    <package format="3">
      <name>octomap_publisher</name>
      <version>0.0.0</version>
      <description>TODO: Package description</description>
      <maintainer email="[[email protected]](/cdn-cgi/l/email-protection)">ajifoster3</maintainer>
      <license>TODO: License declaration</license>

      <buildtool_depend>ament_cmake_auto</buildtool_depend>

      <depend>octomap_msgs</depend>
      <depend>octomap</depend>
      <depend>rclcpp</depend>
      <depend>octomap_server</depend>

      <test_depend>ament_lint_auto</test_depend>
      <test_depend>ament_lint_common</test_depend>

      <export>
        <build_type>ament_cmake</build_type>
      </export>
    </package>


Question:
Error fetching dependencies from Git repo

I have cloned this repo:https://github.com/ClemensElflein/open_mower_ros

however when fetching the dependencies with:

rosdep install --from-paths src --ignore-src --default-yes
I get the following error:

ERROR: the following packages/stacks could not have their rosdep keys resolved  to system dependencies:
mower_utils: Cannot locate rosdep definition for [xbot_msgs]
mower_msgs: Cannot locate rosdep definition for [xesc_msgs]
mower_simulation: Cannot locate rosdep definition for [xbot_positioning]
mower_comms: Cannot locate rosdep definition for [xesc_msgs]
mower_map: Cannot locate rosdep definition for [xbot_msgs]
open_mower: Cannot locate rosdep definition for [ftc_local_planner]
mower_logic: Cannot locate rosdep definition for [xbot_positioning]
I have tried many things, but nothing works. I am working on ros-noetic. Any tip?

Explanation: We need to check the missing submodules.

$\begingroup$

It looks like you didn't get the [ openmower submodules
](https://github.com/ClemensElflein/open_mower_ros/blob/main/.gitmodules) (the
[ readme
](https://github.com/ClemensElflein/open_mower_ros/blob/main/README.md) should
be changed to mention those prominently)

    cd open_mower_ros
    git submodule update --init --recursive

There may be some other packages to git clone manually that aren't in the
submodules and can't be installed through rosdep (like the above comment
suggests).


Question:
depth aligned capture doesn't yield same number of rgb and depth frames -- cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is

Steps for reproducing the problem with an Intel RealSense D435 camera using ROS Noetic inside a docker.

In the first terminal:

(base) mona@ada:~$ sudo docker run -it --privileged -v /dev:/dev -v /home/mona:/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY --device /dev/bus/usb ros_noetic

root@7a805700666e:/workspace# cd catkin_ws

(base) mona@ada:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7a805700666e ros_noetic "/ros_entrypoint.sh …" 4 seconds ago Up 3 seconds clever_feynman

roslaunch realsense2_camera rs_camera.launch align_depth:=true

After capture is done,

5.

root@7a805700666e:/workspace/catkin_ws# catkin_make
Base path: /workspace/catkin_ws
Source space: /workspace/catkin_ws/src
Build space: /workspace/catkin_ws/build
Devel space: /workspace/catkin_ws/devel
Install space: /workspace/catkin_ws/install
####
#### Running command: "make cmake_check_build_system" in "/workspace/catkin_ws/build"
####
####
#### Running command: "make -j32 -l32" in "/workspace/catkin_ws/build"
####
 root@ce71bcbb2d89:/workspace/catkin_ws# source devel/setup.bash
 root@ce71bcbb2d89:/workspace/catkin_ws# rosrun bag_converter convert.py
other terminal

$ xhost +local:docker

docker exec -it -e DISPLAY=$DISPLAY  clever_feynman  bash run step 3 in this terminal after starting step 4 in the first terminal.

root@7a805700666e:/workspace# rosbag record -a -O mona_noetic

Here's the conversion script:

(base) mona@ada:~$ cat catkin_ws/src/bag_converter/scripts/convert.py
#!/usr/bin/python3

import os
import sys
import yaml
from rosbag.bag import Bag
import cv2

import roslib;   #roslib.load_manifest(PKG)
import rosbag
import rospy
import cv2
import numpy as np
import argparse
import os

from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from cv_bridge import CvBridgeError

class ImageCreator():
    def __init__(self, bagfile, rgbpath, depthpath, rgbstamp, depthstamp):
        self.bridge = CvBridge()
        with rosbag.Bag(bagfile, 'r') as bag:
            for topic,msg,t in bag.read_messages():
                print(topic)
                if topic == "/camera/color/image_raw":
                    cv_image = self.bridge.imgmsg_to_cv2(msg,"bgr8")
                    timestr = "%.6f" %  msg.header.stamp.to_sec()
                    image_name = timestr+ ".png"
                    cv2.waitKey(1);
                    cv2.imwrite(rgbpath + image_name, cv_image)

                elif topic == "/camera/aligned_depth_to_color/image_raw":
                    cv_image = self.bridge.imgmsg_to_cv2(msg,"16UC1")
                    timestr = "%.6f" %  msg.header.stamp.to_sec()
                    image_name = timestr+ ".png"

                    cv2.imwrite(depthpath + image_name, (cv_image).astype(np.uint16))

if __name__ == '__main__':
    ImageCreator('/workspace/mona_noetic.bag', '/workspace/mona_noetic/rgb/', '/workspace/mona_noetic/depth/', 1, 1)

However, from the capture, we see this unaligned number of depth aligned frames for rgb and depth:

root@7a805700666e:/workspace# rosbag info mona_noetic.bag
path:        mona_noetic.bag
version:     2.0
duration:    18.2s
start:       Nov 15 2023 16:04:52.73 (1700064292.73)
end:         Nov 15 2023 16:05:10.93 (1700064310.93)
size:        30.5 MB
messages:    462
compression: none [41/41 chunks]
types:       bond/Status                           [eacc84bf5d65b6777d4c50f463dfb9c8]
             diagnostic_msgs/DiagnosticArray       [60810da900de1dd6ddd437c3503511da]
             dynamic_reconfigure/Config            [958f16a05573709014982821e6822580]
             dynamic_reconfigure/ConfigDescription [757ce9d44ba8ddd801bb30bc456f946f]
             realsense2_camera/Extrinsics          [3627b43073f4cd5dd6dc179a49eda2ad]
             realsense2_camera/Metadata            [4966ca002be16ee67fe4dbfb2f354787]
             rosgraph_msgs/Log                     [acffd30cd6b6de30f120938c17c593fb]
             sensor_msgs/CameraInfo                [c9a58c1b0b154e0e6da7578cb991d214]
             sensor_msgs/CompressedImage           [8f7a12909da2c9d3332d540a0977563f]
             sensor_msgs/Image                     [060021388200f6f0f447d0fcd9c64743]
             tf2_msgs/TFMessage                    [94810edda583a504dfda3829e70d7eec]
             theora_image_transport/Packet         [33ac4e14a7cff32e7e0d65f18bb410f3]
topics:      /camera/align_to_color/parameter_descriptions                                      1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/align_to_color/parameter_updates                                           1 msg     : dynamic_reconfigure/Config
             /camera/aligned_depth_to_color/image_raw                                           2 msgs    : sensor_msgs/Image
             /camera/aligned_depth_to_color/image_raw/compressed/parameter_descriptions         1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/aligned_depth_to_color/image_raw/compressed/parameter_updates              1 msg     : dynamic_reconfigure/Config
             /camera/aligned_depth_to_color/image_raw/compressedDepth/parameter_descriptions    1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/aligned_depth_to_color/image_raw/compressedDepth/parameter_updates         1 msg     : dynamic_reconfigure/Config
             /camera/aligned_depth_to_color/image_raw/theora/parameter_descriptions             1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/aligned_depth_to_color/image_raw/theora/parameter_updates                  1 msg     : dynamic_reconfigure/Config
             /camera/color/camera_info                                                          2 msgs    : sensor_msgs/CameraInfo
             /camera/color/image_raw/compressed                                                 2 msgs    : sensor_msgs/CompressedImage
             /camera/color/image_raw/compressed/parameter_descriptions                          1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/color/image_raw/compressed/parameter_updates                               1 msg     : dynamic_reconfigure/Config
             /camera/color/image_raw/compressedDepth/parameter_descriptions                     1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/color/image_raw/compressedDepth/parameter_updates                          1 msg     : dynamic_reconfigure/Config
             /camera/color/image_raw/theora/parameter_descriptions                              1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/color/image_raw/theora/parameter_updates                                   1 msg     : dynamic_reconfigure/Config
             /camera/depth/camera_info                                                         39 msgs    : sensor_msgs/CameraInfo
             /camera/depth/image_rect_raw                                                      38 msgs    : sensor_msgs/Image
             /camera/depth/image_rect_raw/compressed                                           38 msgs    : sensor_msgs/CompressedImage
             /camera/depth/image_rect_raw/compressed/parameter_descriptions                     1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/depth/image_rect_raw/compressed/parameter_updates                          1 msg     : dynamic_reconfigure/Config
             /camera/depth/image_rect_raw/compressedDepth                                      40 msgs    : sensor_msgs/CompressedImage
             /camera/depth/image_rect_raw/compressedDepth/parameter_descriptions                1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/depth/image_rect_raw/compressedDepth/parameter_updates                     1 msg     : dynamic_reconfigure/Config
             /camera/depth/image_rect_raw/theora                                                3 msgs    : theora_image_transport/Packet
             /camera/depth/image_rect_raw/theora/parameter_descriptions                         1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/depth/image_rect_raw/theora/parameter_updates                              1 msg     : dynamic_reconfigure/Config
             /camera/depth/metadata                                                            37 msgs    : realsense2_camera/Metadata
             /camera/extrinsics/depth_to_color                                                  1 msg     : realsense2_camera/Extrinsics
             /camera/realsense2_camera_manager/bond                                            37 msgs    : bond/Status                           (2 connections)
             /camera/rgb_camera/auto_exposure_roi/parameter_descriptions                        1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/rgb_camera/auto_exposure_roi/parameter_updates                             1 msg     : dynamic_reconfigure/Config
             /camera/rgb_camera/parameter_descriptions                                          1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/rgb_camera/parameter_updates                                               1 msg     : dynamic_reconfigure/Config
             /camera/stereo_module/auto_exposure_roi/parameter_descriptions                     1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/stereo_module/auto_exposure_roi/parameter_updates                          1 msg     : dynamic_reconfigure/Config
             /camera/stereo_module/parameter_descriptions                                       1 msg     : dynamic_reconfigure/ConfigDescription
             /camera/stereo_module/parameter_updates                                            1 msg     : dynamic_reconfigure/Config
             /diagnostics                                                                      68 msgs    : diagnostic_msgs/DiagnosticArray
             /rosout                                                                           88 msgs    : rosgraph_msgs/Log                     (2 connections)
             /rosout_agg                                                                       38 msgs    : rosgraph_msgs/Log
             /tf_static                                                                         1 msg     : tf2_msgs/TFMessage
Further, I see this error when starting the depth align capture:

[ INFO] [1700064224.344956163]: SELECTED BASE:Depth, 0
[ INFO] [1700064224.355172954]: RealSense Node Is Up!
 15/11 16:03:44,482 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 300, error: Resource temporarily unavailable, number: b
[ WARN] [1700064224.531686247]:
 15/11 16:03:44,873 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:44,924 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,179 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,230 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,381 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,432 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,584 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,635 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,786 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,837 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:45,988 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:46,039 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:46,191 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
 15/11 16:03:46,243 WARNING [140201123149568] (messenger-libusb.cpp:42) control_transfer returned error, index: 768, error: Resource temporarily unavailable, number: 11
[ERROR] [1700064294.457665710]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
 15/11 16:04:54,800 ERROR [140200416114432] (uvc-streamer.cpp:106) uvc streamer watchdog triggered on endpoint: 132
[ERROR] [1700064294.983499621]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064295.496846075]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064296.010771429]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064296.478652416]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064296.895753832]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064297.321010419]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064297.747054477]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064298.173193296]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064298.601070803]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064299.022315621]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064299.448716345]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064299.868316530]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064300.287427109]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064300.702281242]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064301.118212082]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064301.540673572]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064301.961749822]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064302.381357661]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064302.799640022]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064303.226624059]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064303.655973210]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064304.081943511]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064304.509441908]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064304.939367902]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064305.369842480]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064305.800837626]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064306.233901531]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064306.662224030]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064307.088729246]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064307.503594745]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064307.920114882]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064308.346923624]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064308.779323394]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064309.224245296]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064309.664677204]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064310.094353804]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064310.524822175]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
[ERROR] [1700064310.940728063]: cv_bridge exception: '[16UC1] is not a color format. but [bgr8] is. The conversion does not make sense'
^C[camera/realsense2_camera-3] killing on exit
[camera/realsense2_camera_manager-2] killing on exit
[rosout-1] killing on exit
[master] killing on exit
shutting down processing monitor...
... shutting down processing monitor complete
done

Explanation: The regex format of rosbag record may not be correct. We need to check for the one that fixes the problem.

$\begingroup$

Using

` rosbag record -O mona_noetic.bag -a -x "(.*)theora(.*)|(.*)compressed(.*)" `

instead of

` rosbag record -a -O mona_noetic `

fixed the problem.

Also, if you exactly know what you want to capture, you can use a command like
the following:

    root@77c9b6999e4b:/workspace# rosbag record -O mona_noetic.bag /camera/aligned_depth_to_color/image_raw /camera/color/image_raw /camera/depth/camera_info /camera/color/camera_info /camera/extrinsics/depth_to_color
    [ INFO] [1700147750.161300211]: Subscribing to /camera/aligned_depth_to_color/image_raw
    [ INFO] [1700147750.164502682]: Subscribing to /camera/color/camera_info
    [ INFO] [1700147750.166064340]: Subscribing to /camera/color/image_raw
    [ INFO] [1700147750.166996966]: Subscribing to /camera/depth/camera_info
    [ INFO] [1700147750.167893184]: Subscribing to /camera/extrinsics/depth_to_color
    [ INFO] [1700147750.170980936]: Recording to 'mona_noetic.bag'.

Please note, despite having depth aligned captures, it happens that we have 1-3 more depth images than color. And you can find and omit them by using ` ls *.png | sort > ../depth.txt ` and ` ls *.png | sort > ../rgb.txt ` and then ` vimdiff depth.txt rgb.txt ` .

    (base) mona@ada:~/mona_noetic$ ls rgb/*.png | wc -l
    538
    (base) mona@ada:~/mona_noetic$ ls depth/*.png | wc -l
    539

Reference [ https://github.com/IntelRealSense/realsense-
ros/issues/315#issuecomment-699030884
](https://github.com/IntelRealSense/realsense-
ros/issues/315#issuecomment-699030884)


Question:
What is the difference between RCL_STEADY_TIME, RCL_SYSTEM_TIME and RCL_ROS_TIME?

I wrote the following code to check the difference myself, but I could not find any considerable difference.

#include <rclcpp/rclcpp.hpp>

auto main(int argc, char **argv) -> int
{
        rclcpp::init(argc, argv);

        auto node = std::make_shared<rclcpp::Node>("time_converter");

        rclcpp::Time steady_time(node->now(),RCL_STEADY_TIME);
        RCLCPP_INFO(node->get_logger(), "RCL_STEADY_TIME = %f",steady_time.seconds());

        rclcpp::Time sys_time(node->now(),RCL_SYSTEM_TIME);
        RCLCPP_INFO(node->get_logger(), "RCL_SYSTEM_TIME = %f",sys_time.seconds());

        rclcpp::Time ros_time(node->now(),RCL_ROS_TIME);
        RCLCPP_INFO(node->get_logger(), "RCL_ROS_TIME = %f",ros_time.seconds());

        return EXIT_SUCCESS;
}
Output:

[INFO] [1699543136.456027415] [time_converter]: steady node time = 1699543136.456026
[INFO] [1699543136.456121797] [time_converter]: sys node time = 1699543136.456121
[INFO] [1699543136.456138399] [time_converter]: sys node time = 1699543136.456138
Actual question is, How do I get steady time from node->now()? Because that is the answer I am looking for.

Explanation: We need to check the documentation on the different time sources.

$\begingroup$

The documentation on the different time sources is [ here
](https://design.ros2.org/articles/clock_and_time.html) :

> There will be at least three versions of these abstractions with the
> following types, ` SystemTime ` , ` SteadyTime ` and ` ROSTime ` . These
> choices are designed to parallel the ` std::chrono ` ` system_clock ` and `
> steady_clock ` .
>
> [...]
>
> The ` ROSTime ` will report the same as ` SystemTime ` when a ROS Time
> Source is not active. When the ROS time source is active ` ROSTime ` will
> return the latest value reported by the Time Source. ` ROSTime ` is
> considered active when the parameter ` use_sim_time ` is set on the node.

For the difference between ` std::chrono::system_clock ` and `
std::chrono::steady_clock ` , see [ this stackverflow answer
](https://stackoverflow.com/a/31553641/20622761) :

> If you're holding a ` system_clock ` in your hand, you would call it a
> watch, and it would tell you what time it is.
>
> If you're holding a ` steady_clock ` in your hand, you would call it a
> stopwatch, and it would tell you how fast someone ran a lap, but it would
> not tell you what time it is.
>
> If you had to, you could time someone running a lap with your watch. But if
> your watch (like mine) periodically talked to another machine (such as the
> atomic clock in Boulder CO) to correct itself to the current time, it might
> make minor mistakes in timing that lap. The stopwatch won't make that
> mistake, but it also can't tell you what the correct current time is.

Re. your second question:

> Actual question is, How do I get steady time from node->now()? Because that
> is the answer I am looking for.

~~I think ROS node clocks always use ` RCL_ROS_TIME ` which either is `
SystemTime ` or the time that is published to topic ` /clock ` in case of `
use_sim_time ` true.~~

**EDIT:** Seems above is wrong, see [ the source code
](https://github.com/ros2/rclcpp/blob/9c098e544ecf191b7c61f63f7f4fac6f6449cedd/rclcpp/src/rclcpp/node.cpp#L197)
: the Node constructor takes the clock type from the NodeOptions. So it seems
it is possible to choose the clock type by instantiatin a NodeOptions, set its
clock type and pass it to your node constructor. See [ here
](https://github.com/ros2/rclcpp/blob/9c098e544ecf191b7c61f63f7f4fac6f6449cedd/rclcpp/include/rclcpp/node_options.hpp#L38-L61)
for the options in the NodeOptions. **/EDIT**

What is your exact use case to want to set the node clock to steady time?

If you actually want a steady timer:

You can create use ` Node::create_wall_timer() ` instead of `
Node::create_timer() ` , e.g.:

    timer_ = this->create_wall_timer(
          500ms, std::bind(&MinimalPublisher::timer_callback, this));

A wall timer uses RCL_STEADY_TIME:

[
https://github.com/ros2/rclcpp/blob/0f331f90a99da40f7b7a69b4f55b30b7245d294f/rclcpp/include/rclcpp/timer.hpp#L347
](https://github.com/ros2/rclcpp/blob/0f331f90a99da40f7b7a69b4f55b30b7245d294f/rclcpp/include/rclcpp/timer.hpp#L347)

Do realize that if you use a wall_timer in a node that is also used with `
use_sim_time == true ` , its timer will run and the timer callback will be
triggered irrespective of the simulation time (e.g. also when the simulation
is paused).


Question:
Parameter substitution within rosparam list inside launch file

I am trying to change the parameter map_frame within the rosparam list as shown below, but the substitution does not work.

I am actually passing the "tf_pre" argument from another launch file.

This line <rosparam param="map_frame" subst_value="True">$(arg tf_pre)/map </rosparam> # prefix the tf name for the map is used to pass the value of tf_pre to the value of map_frame inside the <rosparam> list.

This does not seem to have any effect because when I run rosparam get /h1/slam_gmapping/map_frame I get the wrong value.

Anyone has an idea what could be wrong?

This runs in ROS Noetic and I am trying to slam a multi robot Gazebo simulation.

 <launch>

      <arg name="tf_pre" default="robot1" />

      <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping">

        <rosparam param="map_frame" subst_value="True">$(arg tf_pre)/map </rosparam> # prefix the tf name for the map

        <rosparam>
          odom_frame: odom
          base_frame: base_link
          map_frame: map
          ...

        </rosparam>

      </node>
    </launch>

Explanation:
It looks like you're setting that parameter twice and the one that you're trying to parameterize is lower in precedence.

We need to check the parameter evaluation order.

$\begingroup$

You haven't provided a fully reproducible example to show what is actually
going wrong. But based on your description it looks like you're setting that
parameter twice and the one that you're trying to parameterize is lower in
precedence.

The last instance of the parameter is the one used. [
http://wiki.ros.org/roslaunch/XML#Evaluation_order
](http://wiki.ros.org/roslaunch/XML#Evaluation_order)


Question:
Crazyflie: Connecting, logging and parameters-->Add logging config

I would like to define stateEstimate.vx, stateEstimate.vy, and stateEstimate.vz variables to access those data. I used the following code parts.

def _connected(self, link_uri):

        self.get_logger().info('Connected!')
        self._lg_stab = LogConfig(name='Stabilizer', period_in_ms=100)
        self._lg_stab.add_variable('stateEstimate.x', 'float')
        self._lg_stab.add_variable('stateEstimate.y', 'float')
        self._lg_stab.add_variable('stateEstimate.z', 'float')
        self._lg_stab.add_variable('stateEstimate.vx', 'float')
        self._lg_stab.add_variable('stateEstimate.vy', 'float')
        self._lg_stab.add_variable('stateEstimate.vz', 'float')
        self._lg_stab.add_variable('stateEstimate.roll', 'float')
        self._lg_stab.add_variable('stateEstimate.pitch', 'float')
        self._lg_stab.add_variable('stateEstimate.yaw', 'float')

        self._lg_range = LogConfig(name='Range', period_in_ms=100)
        self._lg_range.add_variable('range.zrange', 'uint16_t')
        self._lg_range.add_variable('range.front', 'uint16_t')
        self._lg_range.add_variable('range.right', 'uint16_t')
        self._lg_range.add_variable('range.left', 'uint16_t')
        self._lg_range.add_variable('range.back', 'uint16_t')
        try:
            self._cf.log.add_config(self._lg_stab)
            self._lg_stab.data_received_cb.add_callback(self._stab_log_data)
            self._lg_stab.error_cb.add_callback(self._stab_log_error)
            self._lg_stab.start()
            self._cf.log.add_config(self._lg_range)
            self._lg_range.data_received_cb.add_callback(self._range_log_data)
            self._lg_range.error_cb.add_callback(self._range_log_error)
            self._lg_range.start()

        except KeyError as e:
            print('Could not start log configuration,'
                  '{} not found in TOC'.format(str(e)))
        except AttributeError:
            print('Could not add Stabilizer log config, bad configuration.')
When I run my python file via ROS2, I saw the following part on the terminal (Could not add Stabilizer log config, bad configuration). I could not get why it happens. However, whenver I use the above code part without stateEstimate.vx, stateEstimate.vy, and stateEstimate.vz, it works pretty well. Could you help us to fix it, thanks.

ntukenmez3@ae-icps-407120:~/Documents/2023-crazy-flie-1/crazyflie_ros2_experimental_2/crazyflie_ros2$ ros2 run crazyflie_ros2 crazyflie_publisher
[INFO] [1698871075.735318053] [crazyflie_publisher]: Connected!
Could not add Stabilizer log config, bad configuration.

Explanation: This is related to the messages in the logblocks. We may check its maximum data size.

$\begingroup$

The error itself comes from your own (or the copied) script

            except AttributeError:
                print('Could not add Stabilizer log config, bad configuration.')`

This is an error but it is not clear why it fails. Here is the API
documentation of the crazyflie python library logging functionality:

[ https://www.bitcraze.io/documentation/repository/crazyflie-lib-
python/master/user-guides/python_api/#logging
](https://www.bitcraze.io/documentation/repository/crazyflie-lib-
python/master/user-guides/python_api/#logging)

Here it says that you can only create logblocks for messages that are no
larger than 30 bytes. the logblock 'Stabilizer' contains 36 bytes (9 x float
which is 4 bytes each). So therefore it fails.

If you look in the documentation, you can see that there is a possibility of
declaring a 16 - bit (2 byte) float. In the logblock declaration, you can
replace ` 'float' ` with ` 'FP16' ` , and reduce the total message size. This
should fix it.


Question:
Transform failed during publishing of map_odom transform

i am trying publish tf and odom. my problem is that i always get this error:

[ERROR] [1698638471.209513778]: Transform failed during publishing of map_odom transform: Lookup would require extrapolation 0.567969187s into the future.  Requested time 1698638469.812094927 but the latest data is at time 1698638469.244125605, when looking up transform from frame [base_link] to frame [odom]
And when i look at my tf tree, odom is not publish to base_link as i expected enter image description here

Here's the odom publisher node:

#include "ros/ros.h"
#include "std_msgs/Int16.h"
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/PoseStamped.h>
#include <tf2/LinearMath/Quaternion.h>
#include <tf2_ros/transform_broadcaster.h>
#include <cmath>

// Create odometry data publishers
ros::Publisher odom_data_pub;
ros::Publisher odom_data_pub_quat;
nav_msgs::Odometry odomNew;
nav_msgs::Odometry odomOld;

// Initial pose
const double initialX = 0.0;
const double initialY = 0.0;
const double initialTheta = 0.00000000001;
const double PI = 3.141592;

// Robot physical constants
const double TICKS_PER_REVOLUTION = 535; // For reference purposes.
const double WHEEL_RADIUS = 0.033; // Wheel radius in meters
const double WHEEL_BASE = 0.17; // Center of left tire to center of right tire
const double TICKS_PER_METER = 3100; // Original was 2800

// Distance both wheels have traveled
double distanceLeft = 0;
double distanceRight = 0;

// Flag to see if initial pose has been received
bool initialPoseRecieved = false;

using namespace std;

// Get initial_2d message from either Rviz clicks or a manual pose publisher
void set_initial_2d(const geometry_msgs::PoseStamped &rvizClick) {

  odomOld.pose.pose.position.x = rvizClick.pose.position.x;
  odomOld.pose.pose.position.y = rvizClick.pose.position.y;
  odomOld.pose.pose.orientation.z = rvizClick.pose.orientation.z;
  initialPoseRecieved = true;
}

// Calculate the distance the left wheel has traveled since the last cycle
void Calc_Left(const std_msgs::Int16& leftCount) {

  static int lastCountL = 0;
  if(leftCount.data != 0 && lastCountL != 0) {

    int leftTicks = (leftCount.data - lastCountL);

    if (leftTicks > 10000) {
      leftTicks = 0 - (65535 - leftTicks);
    }
    else if (leftTicks < -10000) {
      leftTicks = 65535-leftTicks;
    }
    else{}
    distanceLeft = leftTicks/TICKS_PER_METER;
  }
  lastCountL = leftCount.data;
}

// Calculate the distance the right wheel has traveled since the last cycle
void Calc_Right(const std_msgs::Int16& rightCount) {

  static int lastCountR = 0;
  if(rightCount.data != 0 && lastCountR != 0) {

    int rightTicks = rightCount.data - lastCountR;

    if (rightTicks > 10000) {
      distanceRight = (0 - (65535 - distanceRight))/TICKS_PER_METER;
    }
    else if (rightTicks < -10000) {
      rightTicks = 65535 - rightTicks;
    }
    else{}
    distanceRight = rightTicks/TICKS_PER_METER;
  }
  lastCountR = rightCount.data;
}

// Publish a nav_msgs::Odometry message in quaternion format
void publish_quat() {

  tf2::Quaternion q;

  q.setRPY(0, 0, odomNew.pose.pose.orientation.z);

  nav_msgs::Odometry quatOdom;
  quatOdom.header.stamp = odomNew.header.stamp;
  quatOdom.header.frame_id = "odom";
  quatOdom.child_frame_id = "base_link";
  quatOdom.pose.pose.position.x = odomNew.pose.pose.position.x;
  quatOdom.pose.pose.position.y = odomNew.pose.pose.position.y;
  quatOdom.pose.pose.position.z = odomNew.pose.pose.position.z;
  quatOdom.pose.pose.orientation.x = q.x();
  quatOdom.pose.pose.orientation.y = q.y();
  quatOdom.pose.pose.orientation.z = q.z();
  quatOdom.pose.pose.orientation.w = q.w();
  quatOdom.twist.twist.linear.x = odomNew.twist.twist.linear.x;
  quatOdom.twist.twist.linear.y = odomNew.twist.twist.linear.y;
  quatOdom.twist.twist.linear.z = odomNew.twist.twist.linear.z;
  quatOdom.twist.twist.angular.x = odomNew.twist.twist.angular.x;
  quatOdom.twist.twist.angular.y = odomNew.twist.twist.angular.y;
  quatOdom.twist.twist.angular.z = odomNew.twist.twist.angular.z;

  for(int i = 0; i<36; i++) {
    if(i == 0 || i == 7 || i == 14) {
      quatOdom.pose.covariance[i] = .01;
     }
     else if (i == 21 || i == 28 || i== 35) {
       quatOdom.pose.covariance[i] += 0.1;
     }
     else {
       quatOdom.pose.covariance[i] = 0;
     }
  }

  odom_data_pub_quat.publish(quatOdom);
}

// Update odometry information
void update_odom() {

  // Calculate the average distance
  double cycleDistance = (distanceRight + distanceLeft) / 2;

  // Calculate the number of radians the robot has turned since the last cycle
  double cycleAngle = asin((distanceRight-distanceLeft)/WHEEL_BASE);

  // Average angle during the last cycle
  double avgAngle = cycleAngle/2 + odomOld.pose.pose.orientation.z;

  if (avgAngle > PI) {
    avgAngle -= 2*PI;
  }
  else if (avgAngle < -PI) {
    avgAngle += 2*PI;
  }
  else{}

  // Calculate the new pose (x, y, and theta)
  odomNew.pose.pose.position.x = odomOld.pose.pose.position.x + cos(avgAngle)*cycleDistance;
  odomNew.pose.pose.position.y = odomOld.pose.pose.position.y + sin(avgAngle)*cycleDistance;
  odomNew.pose.pose.orientation.z = cycleAngle + odomOld.pose.pose.orientation.z;

  // Prevent lockup from a single bad cycle
  if (isnan(odomNew.pose.pose.position.x) || isnan(odomNew.pose.pose.position.y)
     || isnan(odomNew.pose.pose.position.z)) {
    odomNew.pose.pose.position.x = odomOld.pose.pose.position.x;
    odomNew.pose.pose.position.y = odomOld.pose.pose.position.y;
    odomNew.pose.pose.orientation.z = odomOld.pose.pose.orientation.z;
  }

  // Make sure theta stays in the correct range
  if (odomNew.pose.pose.orientation.z > PI) {
    odomNew.pose.pose.orientation.z -= 2 * PI;
  }
  else if (odomNew.pose.pose.orientation.z < -PI) {
    odomNew.pose.pose.orientation.z += 2 * PI;
  }
  else{}

  // Compute the velocity
  odomNew.header.stamp = ros::Time::now();
  odomNew.twist.twist.linear.x = cycleDistance/(odomNew.header.stamp.toSec() - odomOld.header.stamp.toSec());
  odomNew.twist.twist.angular.z = cycleAngle/(odomNew.header.stamp.toSec() - odomOld.header.stamp.toSec());

  // Save the pose data for the next cycle
  odomOld.pose.pose.position.x = odomNew.pose.pose.position.x;
  odomOld.pose.pose.position.y = odomNew.pose.pose.position.y;
  odomOld.pose.pose.orientation.z = odomNew.pose.pose.orientation.z;
  odomOld.header.stamp = odomNew.header.stamp;

  // Publish the odometry message
  odom_data_pub.publish(odomNew);
}

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

  // Set the data fields of the odometry message
  odomNew.header.frame_id = "odom";
  odomNew.pose.pose.position.z = 0;
  odomNew.pose.pose.orientation.x = 0;
  odomNew.pose.pose.orientation.y = 0;
  odomNew.twist.twist.linear.x = 0;
  odomNew.twist.twist.linear.y = 0;
  odomNew.twist.twist.linear.z = 0;
  odomNew.twist.twist.angular.x = 0;
  odomNew.twist.twist.angular.y = 0;
  odomNew.twist.twist.angular.z = 0;
  odomOld.pose.pose.position.x = initialX;
  odomOld.pose.pose.position.y = initialY;
  odomOld.pose.pose.orientation.z = initialTheta;

  // Launch ROS and create a node
  ros::init(argc, argv, "ekf_odom_pub");
  ros::NodeHandle node;

  // Subscribe to ROS topics
  ros::Subscriber subForRightCounts = node.subscribe("right_ticks", 100, Calc_Right, ros::TransportHints().tcpNoDelay());
  ros::Subscriber subForLeftCounts = node.subscribe("left_ticks", 100, Calc_Left, ros::TransportHints().tcpNoDelay());
  ros::Subscriber subInitialPose = node.subscribe("slam_out_pose", 1, set_initial_2d);

  // Publisher of simple odom message where orientation.z is an euler angle
  odom_data_pub = node.advertise<nav_msgs::Odometry>("odom_data_euler", 100);

  // Publisher of full odom message where orientation is quaternion
  odom_data_pub_quat = node.advertise<nav_msgs::Odometry>("odom_data_quat", 100);

  ros::Rate loop_rate(30);

  while(ros::ok()) {

    if(initialPoseRecieved) {
      update_odom();
      publish_quat();
    }
    ros::spinOnce();
    loop_rate.sleep();
  }

  return 0;
}
Can anyone please tell me where did i do wrong. Thank you!

$\begingroup$

It seems you are only publishing the odometry message to topics
"odom_data_euler" and odom_data_quat ", but not actually broadcasting it.

You will typically use TransformStamped to achieve this. It is almost the same
code-wise, but check this link out:

[ https://docs.ros.org/en/humble/Tutorials/Intermediate/Tf2/Writing-A-
Tf2-Broadcaster-Cpp.html
](https://docs.ros.org/en/humble/Tutorials/Intermediate/Tf2/Writing-A-
Tf2-Broadcaster-Cpp.html)