[ROS2 Q&A] 222 – How to use hidden /cmd_vel topic with ros1_bridge

Written by Ruben Alves

07/01/2022

What we are going to learn

  1. How to launch ros1_bridge
  2. How to use available topics that don’t show up
  3. How to connect to The Construct’s Real Robot Lab RoBoX

List of resources used in this post

  1. The Construct: https://app.theconstructsim.com/
  2. RoBoX Real Robot Lab: https://app.theconstructsim.com/#/RealRobot
  3. Repositories:
    1. https://github.com/ROBOTIS-GIT/turtlebot3
    2. https://github.com/ROBOTIS-GIT/turtlebot3_msgs
    3. https://github.com/ROBOTIS-GIT/turtlebot3_simulations
  4. This post answers the following question asked on ROS Answers: https://answers.ros.org/question/359969/ros2-foxy-ros1_bridge-topics-missing/

Creating a rosject

In order to learn how to use hidden topics with ros1_bridge, let’s start by creating a rosject (ROS project). We are going to use The Construct (https://www.theconstructsim.com/) for this tutorial, but if you have ROS2 installed on your own computer, you should be able to do ~everything on your own computer, except this creating a rosject part.

Let’s start by opening The Construct (https://www.theconstructsim.com/) and logging in. You can easily create a free account if you still don’t have one.

Once inside, let’s create My Rosjects and then, Create a new rosject:

My Rosjects

My Rosjects

 

Create a new rosject

Create a new rosject

For the rosject, let’s select ROS2 Foxy for the ROS Distro, let’s name the rosject as Turtlebot3 hidden topics. You can leave the rosject public.

If you mouse over the recently created rosject, you should see a Run button. Just click that button to launch the rosject.

Turtlebot3 hidden topics in ROS2

Turtlebot3 hidden topics in ROS2

Cloning the required repositories with the simulations

After we have created our rosject and opened it, let’s now open a web shell as we can see in the image below:

Open a new Web Shell/Terminal

Open a new Web Shell/Terminal

After that, let’s enter into the ~/simulation_ws/src directory and clone three repositories there with the following commands:

cd ~/simulation_ws/src/
git clone https://github.com/ROBOTIS-GIT/turtlebot3

git clone https://github.com/ROBOTIS-GIT/turtlebot3_msgs

git clone https://github.com/ROBOTIS-GIT/turtlebot3_simulations

Starting the simulation

Once we have correctly cloned the repositories that contain the simulation and ROS messages needed to simulate Turtlebot with ROS, we now need to start the simulation.

The rosject that we created comes by default with ROS2 Noetic and ROS2 Foxy installed.

In order to test the simulation in ROS2, let’s first launch it with ROS1 to make sure the simulation is working properly at least in ROS1. We will then use ROS1 Bridge to be able to see the topics in ROS2.

Let’s start by sourcing ros1 noetic with, and sourcing our simulation_ws/devel folder as follows:

cd ~/simulation_ws

source /opt/ros/noetic/setup.bash

source devel/setup.bash

After having sourced the workspace that contains the simulation, we should now be able to launch it with the following commands:

export TURTLEBOT3_MODEL=burger

roslaunch turtlebot3_gazebo turtlebot3_empty_world.launch

 

Now that the simulation has been launched, we can open gazebo in order to see it. For that, hover your mouse over the button that has the icon of gazebo and click Open Gazebo. After that, you should be able to see the turthebot3 simulation in ROS1, which means the simulation is well defined, and the meshes are correct.

Open Gazebo by clicking Open Gazebo

Open Gazebo by clicking Open Gazebo

Launching ROS1 Bridge

Let’s start by sourcing the ros workspaces in order. Let’s start by sourcing ROS1, then ROS2, and finally, run the bridge. For that, open a second web shell and type the following:

source /opt/ros/noetic/setup.bash

source /opt/ros/foxy/setup.bash

ros2 run ros1_bridge dynamic_bridge --bridge-all-topics

If everything went well, you should have seen some logs like the following:

created 1to2 bridge for topic '/clock' with ROS 1 type 'rosgraph_msgs/Clock' and ROS 2 type 'rosgraph_msgs/msg/Clock'
created 1to2 bridge for topic '/gazebo/link_states' with ROS 1 type 'gazebo_msgs/LinkStates' and ROS 2 type 'gazebo_msgs/msg/LinkStates'
created 1to2 bridge for topic '/gazebo/model_states' with ROS 1 type 'gazebo_msgs/ModelStates' and ROS 2 type 'gazebo_msgs/msg/ModelStates'
created 1to2 bridge for topic '/imu' with ROS 1 type 'sensor_msgs/Imu' and ROS 2 type 'sensor_msgs/msg/Imu'
created 1to2 bridge for topic '/joint_states' with ROS 1 type 'sensor_msgs/JointState' and ROS 2 type 'sensor_msgs/msg/JointState'
created 1to2 bridge for topic '/odom' with ROS 1 type 'nav_msgs/Odometry' and ROS 2 type 'nav_msgs/msg/Odometry'
created 1to2 bridge for topic '/rosout' with ROS 1 type 'rosgraph_msgs/Log' and ROS 2 type 'rcl_interfaces/msg/Log'
created 1to2 bridge for topic '/rosout_agg' with ROS 1 type 'rosgraph_msgs/Log' and ROS 2 type 'rcl_interfaces/msg/Log'
created 1to2 bridge for topic '/scan' with ROS 1 type 'sensor_msgs/LaserScan' and ROS 2 type 'sensor_msgs/msg/LaserScan'
created 1to2 bridge for topic '/tf' with ROS 1 type 'tf2_msgs/TFMessage' and ROS 2 type 'tf2_msgs/msg/TFMessage'
Created 2 to 1 bridge for service /gazebo/clear_body_wrenches
Created 2 to 1 bridge for service /gazebo/clear_joint_forces
Created 2 to 1 bridge for service /gazebo/delete_light
Created 2 to 1 bridge for service /gazebo/delete_model
Created 2 to 1 bridge for service /gazebo/get_joint_properties
Created 2 to 1 bridge for service /gazebo/get_light_properties
Created 2 to 1 bridge for service /gazebo/get_link_properties
Created 2 to 1 bridge for service /gazebo/get_link_state
Created 2 to 1 bridge for service /gazebo/get_model_properties
Created 2 to 1 bridge for service /gazebo/get_model_state
Created 2 to 1 bridge for service /gazebo/get_physics_properties
Created 2 to 1 bridge for service /gazebo/get_world_properties
Created 2 to 1 bridge for service /gazebo/pause_physics
Created 2 to 1 bridge for service /gazebo/reset_simulation
Created 2 to 1 bridge for service /gazebo/reset_world
Created 2 to 1 bridge for service /gazebo/set_joint_properties
Created 2 to 1 bridge for service /gazebo/set_link_properties
Created 2 to 1 bridge for service /gazebo/set_link_state
Created 2 to 1 bridge for service /gazebo/set_model_configuration
Created 2 to 1 bridge for service /gazebo/set_model_state
Created 2 to 1 bridge for service /gazebo/set_physics_properties
Created 2 to 1 bridge for service /gazebo/spawn_sdf_model
Created 2 to 1 bridge for service /gazebo/spawn_urdf_model
Created 2 to 1 bridge for service /gazebo/unpause_physics
Created 2 to 1 bridge for service /imu_service
[INFO] [1641212256.136511189] [ros_bridge]: Passing message from ROS 1 rosgraph_msgs/Clock to ROS 2 rosgraph_msgs/msg/Clock (showing msg only once per type)
[INFO] [1641212256.138899978] [ros_bridge]: Passing message from ROS 1 gazebo_msgs/LinkStates to ROS 2 gazebo_msgs/msg/LinkStates (showing msg only once per type)
created 2to1 bridge for topic '/gazebo/link_states' with ROS 2 type 'gazebo_msgs/msg/LinkStates' and ROS 1 type 'gazebo_msgs/LinkStates'
[INFO] [1641212256.140508214] [ros_bridge]: Passing message from ROS 1 gazebo_msgs/ModelStates to ROS 2 gazebo_msgs/msg/ModelStates (showing msg only once per type)
created 2to1 bridge for topic '/rosout' with ROS 2 type 'rcl_interfaces/msg/Log' and ROS 1 type'rosgraph_msgs/Log'
[INFO] [1641212256.141466301] [ros_bridge]: Passing message from ROS 1 sensor_msgs/Imu to ROS 2sensor_msgs/msg/Imu (showing msg only once per type)
[INFO] [1641212256.142755982] [ros_bridge]: Passing message from ROS 1 sensor_msgs/JointState to ROS 2 sensor_msgs/msg/JointState (showing msg only once per type)
removed 2to1 bridge for topic '/gazebo/link_states'
[INFO] [1641212256.144608098] [ros_bridge]: Passing message from ROS 1 nav_msgs/Odometry to ROS2 nav_msgs/msg/Odometry (showing msg only once per type)
[INFO] [1641212256.146602236] [ros_bridge]: Passing message from ROS 1 tf2_msgs/TFMessage to ROS 2 tf2_msgs/msg/TFMessage (showing msg only once per type)
[INFO] [1641212256.160265245] [ros_bridge]: Passing message from ROS 2 rcl_interfaces/msg/Log to ROS 1 rosgraph_msgs/Log (showing msg only once per type)
[INFO] [1641212256.466793392] [ros_bridge]: Passing message from ROS 1 sensor_msgs/LaserScan toROS 2 sensor_msgs/msg/LaserScan (showing msg only once per type)
[INFO] [1641212256.469177152] [ros_bridge]: Passing message from ROS 1 rosgraph_msgs/Log to ROS2 rcl_interfaces/msg/Log (showing msg only once per type)

 

Checking the /cmd_vel topic

Now that ros1_bridge is up and running, let’s open a third terminal and list the ros2 topics with:

ros2 topic list

You should have seen at least the following topics:

/clock
/gazebo/link_states
/gazebo/model_states
/imu
/joint_states
/odom
/parameter_events
/rosout
/rosout_agg
/scan
/tf

If we look carefully at the list of topics above, we cannot see any /cmd_vel topic. But the topic exists in ROS1. To ensure the topic exists in ROS1, let’s open a fourth terminal and list the topics with:

source /opt/ros/noetic/setup.bash

rostopic list

The list should contain something like the output below, showing that indeed we have a topic called /cmd_vel (the second one in the list below).

/clock
/cmd_vel
/gazebo/link_states
/gazebo/model_states
/gazebo/parameter_descriptions
/gazebo/parameter_updates
/gazebo/performance_metrics
/gazebo/set_link_state
/gazebo/set_model_state
/imu
/joint_states
/odom
/rosout
/rosout_agg
/scan
/tf

And this is what confuses some users. How is that /cmd_vel is available in ros1 but it is not available on ros2? Well, we still do not have a definite answer on why this happens, but we know that if in ROS2 we start publishing in that topic, it will be received by ROS1 and the robot will move accordingly, even though we are not able to see the topic with ros2 topic list. Let’s try that.

First, if we were to publish messages in the /cmd_vel topic using ROS1, the command would be as follows (you do not need to run the command below):

rostopic pub /cmd_vel geometry_msgs/Twist "linear:
  x: 0.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.0"

For ros2, the message instead of geometry_msgs/Twist would be geometry_msgs/msg/Twist. Since ros2 does not auto-complete because it does not know the /cmd_vel topic, we can copy the auto-completed values for geometry_msgs/Twist in ROS1 and pass it to ros2.

Let’s go back to the third terminal where ROS2 Foxy is sourced by default and run the following command:

ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "linear:
  x: 0.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.3"

You should have seen something like what we have below:

publisher: beginning loop
publishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.3))
publishing #2: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.3))
publishing #3: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.3))
publishing #4: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.3))
publishing #5: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.3))

And the robot should now be rotating.

As you can see, with ROS2 we are able to move the robot that is running with ROS1, even if we cannot list the topic with ros2.

By looking at the logs of the second web shell, where ros1_bridge was launched, we can also confirm that the message is being correctly interchanged from the ROS2 to the ROS1 /cmd_vel topic:

created 2to1 bridge for topic '/cmd_vel' with ROS 2 type 'geometry_msgs/msg/Twist' and ROS 1 type ''
[INFO] [1641214498.129565691] [ros_bridge]: Passing message from ROS 2 geometry_msgs/msg/Twistto ROS 1 geometry_msgs/Twist (showing msg only once per type)
removed 2to1 bridge for topic '/cmd_vel'
created 2to1 bridge for topic '/cmd_vel' with ROS 2 type 'geometry_msgs/msg/Twist' and ROS 1 type ''

So, that is it. We just learned that even when some topics are not visible in ROS2 through ros1_bridge, we can still publish messages on them using ROS2.

Youtube video

So this is the post for today. Remember that we have the live version of this post on YouTube. If you liked the content, please consider subscribing to our youtube channel. We are publishing new content ~every day.

Keep pushing your ROS Learning.

Topics:

Check Out These Related Posts

0 Comments

Pin It on Pinterest

Share This