URDF Real Robot Project Part II

Hello, @duckfrost2 @girishkumar.kannan

I am trying to add Gazebo Plug-ins for the second part of the URDF Project. I have added the plugs ins but whenever I try to spawn the robot, the sim shuts down.
Following is the terminal output when I spawn the robot:

ros2 launch small_city_lab_gzsim simulation.launch.py
[INFO] [launch]: All log files can be found below /home/user/.ros/log/2026-05-07-14-40-07-502220-4_xterm-21747
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [DISPLAY=:2 ruby $(which gz) sim-1]: process started with pid [21750]
[DISPLAY=:2 ruby $(which gz) sim-1] QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-user'
[DISPLAY=:2 ruby $(which gz) sim-1] MESA: error: ZINK: vkCreateInstance failed (VK_ERROR_INCOMPATIBLE_DRIVER)
[DISPLAY=:2 ruby $(which gz) sim-1] glx: failed to create drisw screen
[DISPLAY=:2 ruby $(which gz) sim-1] Warning [Utils.cc:132] [/sdf/model[@name="fastbot"]/link[@name="laser_spinner"]/sensor[@name="gpu_lidar"]/gz_frame_id:<urdf-string>:L0]: XML Element[gz_frame_id], child of element[sensor], not defined in SDF. Copying[gz_frame_id] as children of [sensor].
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.019080403] [gz_ros_control]: Loading controller_manager
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.038667933] [controller_manager]: Using ROS clock for triggering controller manager cycles.
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.044467760] [controller_manager]: Subscribing to '/robot_description' topic for robot description.
[DISPLAY=:2 ruby $(which gz) sim-1] [WARN] [1778164826.047800600] [gz_ros_control]: Waiting RM to load and initialize hardware...
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.088853498] [controller_manager]: Received robot description from topic.
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.088936736] [controller_manager]: Enforcing command limits is disabled. Command limits from URDF will be ignored.
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.105184462] [gz_ros_control]: The position_proportional_gain has been set to: 0.1
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.105335091] [gz_ros_control]: Loading joint: laser_spinner_joint
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.105357303] [gz_ros_control]:     State:
.
.
.
[DISPLAY=:2 ruby $(which gz) sim-1] [INFO] [1778164826.106228333] [resource_manager]: Successful 'activate' of hardware 'GazeboSimSystem'
[DISPLAY=:2 ruby $(which gz) sim-1] gz sim server: symbol lookup error: /opt/ros/jazzy/lib/libcontroller_manager_msgs__rosidl_typesupport_fastrtps_cpp.so:undefined symbol: _ZN8eprosima7fastcdr3Cdr9serializeEj
[INFO] [DISPLAY=:2 ruby $(which gz) sim-1]: process has finished cleanly [pid 21750]
[INFO] [launch]: process[DISPLAY=:2 ruby $(which gz) sim-1] was required: shutting down launched system

I checked my environment variables, and only ROS2 Jazzy is sourced (ROS_DISTRO=jazzy ).
I also checked installed package versions and noticed that most ROS Jazzy packages are from 2024 builds, while ros-jazzy-gz-ros2-control appears to be from a much newer 2026 build.

When I remove the ros2control part, I don’t face this issue and the robot gets spawned normally.
Could this be a package/version mismatch issue between gz_ros2_control , FastDDS/FastCDR, or Gazebo packages in the lab environment?
Also, is the project officially tested on ROS2 Jazzy, or primarily on Humble?

Any guidance would be appreciated. Thank you.

Best,
Ninad Mehta

Hi! Did anyone get a chance to take a look at this?
The only urdf code I have added is the following:

  <!--Gazebo Plug-ins-->
  
  <!--Laser Rotate Model -->
  <!--Keeping the Lidar exactly as we have it, spinner will sit at the top of the lidar body -->
  <link name="laser_spinner">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder radius="0.017" length="0.012"/>
      </geometry>
      <material name="red"/>
    </visual>
    <collision>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder radius="0.017" length="0.012"/>
      </geometry>
    </collision>
    <inertial>  
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <mass value="0.020"/>
      <inertia ixx="1.63e-06" ixy="0" ixz="0"
               iyy="1.63e-06" iyz="0"
               izz="2.89e-06"/>
    </inertial>      
  </link>
  <joint name="laser_spinner_joint" type="revolute">
    <parent link="Lidar"/>
    <child link="laser_spinner"/>
    <!--
    Place at top of lidar base = 0.023m (base height) + half spinner height
    = 0.023 + 0.006 = 0.029m from Lidar origin
    -->
    <origin xyz="0 0 0.029" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-3.14159" upper="3.14159"
         effort="1.0" velocity="10.0"/>
  </joint>

  <!-- Laser Scan Frame — virtual, no geometry -->
  <link name="laser_scan_frame">
  </link>

  <joint name="laser_scan_frame_joint" type="fixed">
    <origin rpy="0 0 0" xyz="0 0 0.006"/>
    <parent link="laser_spinner"/>
    <child link="laser_scan_frame"/>
    <axis xyz="0 0 0"/>
  </joint>  
 <!-- PLUGINS -->
 <!--Joint State Publisher Plugin--> 
  <gazebo>
    <!-- Inside your model or <world> -->
    <plugin filename="gz-sim-joint-state-publisher-system"
            name="gz::sim::systems::JointStatePublisher">
      <topic>/joint_states</topic>
      <update_rate>30</update_rate>
      <!-- Publish the state of these joints -->
      <joint_name>joint_left_wheel</joint_name>
      <joint_name>joint_right_wheel</joint_name>
      <!-- <joint_name>joint_caster_wheel</joint_name> -->
    </plugin>
  </gazebo>

  <!-- Differential Drive Plugin -->
  <gazebo>
    <plugin
        filename="gz-sim-diff-drive-system"
        name="gz::sim::systems::DiffDrive">
        <left_joint>joint_left_wheel</left_joint>
        <right_joint>joint_right_wheel</right_joint>
        <wheel_separation>0.134</wheel_separation> <!--Separation = |0.067| + |-0.067| = 0.134 wheel axle Separation-->
        <wheel_radius>0.0325</wheel_radius>
        <topic>cmd_vel</topic>
        <publish_odom>true</publish_odom>
        <publish_odom_tf>true</publish_odom_tf>
        <publish_wheel_tf>true</publish_wheel_tf>
        <odom_topic>odom</odom_topic>
        <tf_topic>tf</tf_topic>
        <frame_id>odom</frame_id>
        <child_frame_id>base_link</child_frame_id>
    </plugin>
  </gazebo>

  
    <!-- ros2_control config -->
  <!--This is where you register a joint with ROS2 control system -->
  <ros2_control name="GazeboSimSystem" type="system">
    <hardware>
        <!-- Gazebo Sim integration plugin -->
        <plugin>gz_ros2_control/GazeboSimSystem</plugin>
    </hardware>

    <joint name="laser_spinner_joint">
        <command_interface name="velocity"> <!--Command interface is the input-->
          <param name="min">0.0</param>
          <param name="max">2.0</param>
        </command_interface>
        <state_interface name="position"/> <!--State interfaces are Outputs (what the state returns to you)-->
        <state_interface name="velocity"/>
        <state_interface name="effort"/>
    </joint>

  </ros2_control>

  <!-- Gazebo Sim system plugin that boots the controller manager and parses the ros2_control tags -->
  <gazebo>
    <plugin filename="gz_ros2_control-system"
        name="gz_ros2_control::GazeboSimROS2ControlPlugin">

     <!-- Controller configuration YAML files -->
     <parameters>$(find ros2_urdf_project)/config/controllers.yaml</parameters>
    </plugin>
  </gazebo>

  <!--Enable Sensors in Gazebo Sim-->
  <gazebo>
    <plugin filename="gz-sim-sensors-system" name="gz::sim::systems::Sensors">
        <!--use ogre2 if ogre v2.x is installed, otherwise use ogre-->
        <render_engine>ogre2</render_engine>
    </plugin>
  </gazebo>
  <!--Laser Scanner Plugin-->
  <gazebo reference="laser_scan_frame">
    <sensor type="gpu_lidar" name="gpu_lidar">
        <pose relative_to='laser_scan_frame'>0 0 0 0 0 0</pose>
        <gz_frame_id>laser_scan_frame</gz_frame_id> <!--all data published by this sensor 
        belongs to the laser_scan_frame coordinate frame-->
        <always_on>1</always_on>
        <visualize>true</visualize>
        <update_rate>100</update_rate> <!--frequency of update. lower it based on you GPU-->
        <topic>laser_scan</topic>
        <ray>
            <scan>
                <horizontal>
                    <samples>200</samples> <!--creates 200 beams across the horizontal field of view-->
                    <resolution>1</resolution> <!--one measurement per beam-->
                    <min_angle>-3.14</min_angle>
                    <max_angle>3.14</max_angle>
                </horizontal>
            </scan>
            <range>
                <min>0.1</min>
                <max>5.0</max>
                <resolution>0.01</resolution> <!--smallest difference the sensor can detect-->
                <!--in this case, sensor can distinguish between object that are 1 cm apart-->
            </range>
        </ray>
    </sensor>
  </gazebo>

I checked and I have the necessary launch files. But I am unable to figure out what to change.

Hi, Dificult to see without the project, but I would reccomend to try this:

  1. Change the yaml file to : $(find-pkg-share ros2_urdf_project)/config/controllers.yaml, because it might not be finding it and fail silently. Or put the absolute path just for testing.

  2. check the controller.yaml so it has something like this : ""controller_manager:
    ros__parameters:
    update_rate: 50

    joint_state_broadcaster:
    type: joint_state_broadcaster/JointStateBroadcaster

    laser_spinner_controller:
    type: velocity_controllers/JointGroupVelocityController

laser_spinner_controller:
ros__parameters:
joints:
- laser_spinner_joint
interface_name: velocity""

  1. Also a lydar should be continuous: “”





    “”

  2. Try this ```<ros2_control name=“GazeboSimSystem” type=“system”>

    gz_ros2_control/GazeboSimSystem

```

And <gazebo> <plugin filename="gz_ros2_control-system" name="gz_ros2_control::GazeboSimROS2ControlPlugin"> <parameters>$(find-pkg-share ros2_urdf_project)/config/controllers.yaml</parameters> </plugin> </gazebo>.

Keep us posted for the results

Hi @ninadmehta34 ,

The fastrtps related error that you get seems to be related to some missing dependencies in the rosject environment.

I did a quick Google search to find out that installing the eProsima FastCDR library for ROS2 Jazzy would be a potential fix.

So run the following code in your environment and see if this solves your problem:

sudo apt update
sudo apt install ros-jazzy-fastcdr

Execute the above two commands and recompile your work from scratch by deleting build, install, and log folders.

But this error is not related to your URDF file for sure.

Also try re-installing gz_ros2_control package for ROS2 Jazzy:

sudo apt remove ros-jazzy-gz-ros2-control
sudo apt update
sudo apt install ros-jazzy-gz-ros2-control

If things still don’t work after these fixes, let us know.

Regards,
Girish

Hi. Thank you for the suggestions.
@duckfrost2 I have re-checked the .yaml, the urdf and the code setup is exactly as you mentioned.

@girishkumar.kannan
I tried sudo update and sudo install ros-jazzy-fastcdr followed by reinstalling gz_ros_control.
It didn’t resolve the issue. When running the urdf launch file state_publisher.launch.pyafter those steps, I received the following error:

user:~/ros2_ws$ ros2 launch ros2_urdf_project state_publisher.launch.py

[INFO] [launch]: All log files can be found below /home/user/.ros/log/2026-05-12-14-10-27-977000-4_xterm-8523

[INFO] [launch]: Default logging verbosity is set to INFO

Fetching URDF ==>

[INFO] [robot_state_publisher-1]: process started with pid [8542]

[robot_state_publisher-1] terminate called after throwing an instance of 'eprosima::fastcdr::exception::BadParamException'

[robot_state_publisher-1]   what():  This member is not been selected

[ERROR] [robot_state_publisher-1]: process has died [pid 8542, exit code -6, cmd '/opt/ros/jazzy/lib/robot_state_publisher/robot_state_publisher --ros-args -r __node:=robot_state_publisher_node --params-file /tmp/launch_params_0l4xow0j'].

On digging a bit, I found that the error was most likely caused because of version mismatch again between a newer version of FastCDR and an older version of the robot_state_publisher.

Later, on AI suggestion, I ran the following commands:

sudo apt update
sudo apt install ros-jazzy-rmw-cyclonedds-cpp
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp

That successfully stopped the state_publisher from crashing. However, when I tried to actually spawn the robot (ros2 launch ros2_urdf_project spawn.launch.py), I hit a new error

user:~$ cd ros2_wsuser:~/ros2_ws$ source install/setup.bash

user:~/ros2_ws$ export RMW_IMPLEMENTATION=rmw_cyclonedds_cppuser:~/ros2_ws$ source install/setup.bash

user:~/ros2_ws$ ros2 launch ros2_urdf_project spawn.launch.py

[INFO] [launch]: All log files can be found below /home/user/.ros/log/2026-05-12-14-44-32-274761-4_xterm-24048

[INFO] [launch]: Default logging verbosity is set to INFO

[INFO] [create-1]: process started with pid [24051]

[create-1]

[create-1] >>> [rcutils|error_handling.c:108] rcutils_set_error_state()

[create-1] This error state is being overwritten:

[create-1]

[create-1]   'failed to resolve symbol 'rmw_event_type_is_supported' in shared library '/home/simulations/ros2_sims_ws/install/rmw_cyclonedds_cpp/lib/librmw_cyclonedds_cpp.so', at ./src/functions.cpp:152'

[create-1]

[create-1] with this new error message:

[create-1]

[create-1]   'Handle's typesupport identifier (rosidl_typesupport_cpp) is not supported by this library, at ./src/type_support_dispatch.hpp:114'

[create-1]

[create-1] rcutils_reset_error() should be called after error handling to avoid this.

[create-1] <<<

[create-1] [INFO] [1778597072.685598600] [my_robot_spawn]: Requesting list of world names.

[create-1] [INFO] [1778597072.957736030] [my_robot_spawn]: Waiting messages on topic [robot_description].

[create-1] [INFO] [1778597072.980842665] [my_robot_spawn]: Entity creation successful.

[INFO] [create-1]: process has finished cleanly [pid 24051]

The suggested solution to this was a full system upgrade with sudo apt upgrade, but I haven’t done that as this is on a managed platform.

What would you suggest I do next? Is it safe for me to run a full apt upgrade in this rosject?

Best,
Ninad Mehta

Hi @ninadmehta34,

Now that you mentioned upgrade, I saw that the Jazzy version associated to your rosject was generated on 2024-06-19.

So, I just set your rosject to use a Jazzy Docker Image generated on 2026-04-28 (2 weeks ago).

So, if you launch your rosject now, it should have the updated packages.

You may still need to install your specific requirements, but the base Docker Image associated to your rosject now has the latest packages.

Please let us know how your tests go.

Hi @ralves
Thank you. The new Jazzy Docker image probably set things right for me, as I am able to spawn the robot in Gazebo and the simulation part of the rosject is working as expected now. Thank you for the help!

1 Like

I’m glad it worked.

You’re Welcome.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.