README
Bridge communication between ROS and Gazebo
This package provides a network bridge which enables the exchange of messages between ROS and Gazebo Transport.
The following message types can be bridged for topics:
ROS type |
Gazebo Transport Type |
---|---|
actuator_msgs/msg/Actuators |
gz.msgs.Actuators |
builtin_interfaces/msg/Time |
gz.msgs.Time |
geometry_msgs/msg/Point |
gz.msgs.Vector3d |
geometry_msgs/msg/Pose |
gz.msgs.Pose |
geometry_msgs/msg/PoseArray |
gz.msgs.Pose_V |
geometry_msgs/msg/PoseStamped |
gz.msgs.Pose |
geometry_msgs/msg/PoseWithCovariance |
gz.msgs.PoseWithCovariance |
geometry_msgs/msg/PoseWithCovarianceStamped |
gz.msgs.PoseWithCovariance |
geometry_msgs/msg/Quaternion |
gz.msgs.Quaternion |
geometry_msgs/msg/Transform |
gz.msgs.Pose |
geometry_msgs/msg/TransformStamped |
gz.msgs.Pose |
geometry_msgs/msg/Twist |
gz.msgs.Twist |
geometry_msgs/msg/TwistStamped |
gz.msgs.Twist |
geometry_msgs/msg/TwistWithCovariance |
gz.msgs.TwistWithCovariance |
geometry_msgs/msg/TwistWithCovarianceStamped |
gz.msgs.TwistWithCovariance |
geometry_msgs/msg/Vector3 |
gz.msgs.Vector3d |
geometry_msgs/msg/Wrench |
gz.msgs.Wrench |
geometry_msgs/msg/WrenchStamped |
gz.msgs.Wrench |
gps_msgs/msg/GPSFix |
gz.msgs.NavSat |
nav_msgs/msg/Odometry |
gz.msgs.Odometry |
nav_msgs/msg/Odometry |
gz.msgs.OdometryWithCovariance |
rcl_interfaces/msg/ParameterValue |
gz.msgs.Any |
ros_gz_interfaces/msg/Altimeter |
gz.msgs.Altimeter |
ros_gz_interfaces/msg/Contact |
gz.msgs.Contact |
ros_gz_interfaces/msg/Contacts |
gz.msgs.Contacts |
ros_gz_interfaces/msg/Dataframe |
gz.msgs.Dataframe |
ros_gz_interfaces/msg/Entity |
gz.msgs.Entity |
ros_gz_interfaces/msg/EntityWrench |
gz.msgs.EntityWrench |
ros_gz_interfaces/msg/Float32Array |
gz.msgs.Float_V |
ros_gz_interfaces/msg/GuiCamera |
gz.msgs.GUICamera |
ros_gz_interfaces/msg/JointWrench |
gz.msgs.JointWrench |
ros_gz_interfaces/msg/Light |
gz.msgs.Light |
ros_gz_interfaces/msg/ParamVec |
gz.msgs.Param |
ros_gz_interfaces/msg/ParamVec |
gz.msgs.Param_V |
ros_gz_interfaces/msg/SensorNoise |
gz.msgs.SensorNoise |
ros_gz_interfaces/msg/StringVec |
gz.msgs.StringMsg_V |
ros_gz_interfaces/msg/TrackVisual |
gz.msgs.TrackVisual |
ros_gz_interfaces/msg/VideoRecord |
gz.msgs.VideoRecord |
rosgraph_msgs/msg/Clock |
gz.msgs.Clock |
sensor_msgs/msg/BatteryState |
gz.msgs.BatteryState |
sensor_msgs/msg/CameraInfo |
gz.msgs.CameraInfo |
sensor_msgs/msg/FluidPressure |
gz.msgs.FluidPressure |
sensor_msgs/msg/Image |
gz.msgs.Image |
sensor_msgs/msg/Imu |
gz.msgs.IMU |
sensor_msgs/msg/JointState |
gz.msgs.Model |
sensor_msgs/msg/Joy |
gz.msgs.Joy |
sensor_msgs/msg/LaserScan |
gz.msgs.LaserScan |
sensor_msgs/msg/MagneticField |
gz.msgs.Magnetometer |
sensor_msgs/msg/NavSatFix |
gz.msgs.NavSat |
sensor_msgs/msg/PointCloud2 |
gz.msgs.PointCloudPacked |
std_msgs/msg/Bool |
gz.msgs.Boolean |
std_msgs/msg/ColorRGBA |
gz.msgs.Color |
std_msgs/msg/Empty |
gz.msgs.Empty |
std_msgs/msg/Float32 |
gz.msgs.Float |
std_msgs/msg/Float64 |
gz.msgs.Double |
std_msgs/msg/Header |
gz.msgs.Header |
std_msgs/msg/Int32 |
gz.msgs.Int32 |
std_msgs/msg/String |
gz.msgs.StringMsg |
std_msgs/msg/UInt32 |
gz.msgs.UInt32 |
tf2_msgs/msg/TFMessage |
gz.msgs.Pose_V |
trajectory_msgs/msg/JointTrajectory |
gz.msgs.JointTrajectory |
vision_msgs/msg/Detection2D |
gz.msgs.AnnotatedAxisAligned2DBox |
vision_msgs/msg/Detection2DArray |
gz.msgs.AnnotatedAxisAligned2DBox_V |
vision_msgs/msg/Detection3D |
gz::msgs::AnnotatedOriented3DBox |
vision_msgs/msg/Detection3DArray |
gz::msgs::AnnotatedOriented3DBox_V |
And the following for services:
ROS type |
Gazebo request |
Gazebo response |
---|---|---|
ros_gz_interfaces/srv/ControlWorld |
gz.msgs.WorldControl |
gz.msgs.Boolean |
Run ros2 run ros_gz_bridge parameter_bridge -h
for instructions.
NOTE: If during startup, gazebo detects that there is another publisher on /clock
, it will only create the fully qualified /world/<worldname>/clock topic
.
Gazebo would be the only /clock
publisher, the sole source of clock information.
You should create an unidirectional /clock
bridge:
ros2 run ros_gz_bridge parameter_bridge /clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock
An alternative set-up can be using the bridge with the override_timestamps_with_wall_time
ros parameter set to true
(default=false
). In this set-up,
all header timestamps of the outgoing messages will be stamped with the wall time. This can be useful when the simulator has to communicate with an external system that requires wall times.
Example 1a: Gazebo Transport talker and ROS 2 listener
Start the parameter bridge which will watch the specified topics.
# Shell A:
. ~/bridge_ws/install/setup.bash
ros2 run ros_gz_bridge parameter_bridge /chatter@std_msgs/msg/String@gz.msgs.StringMsg
Now we start the ROS listener.
# Shell B:
. /opt/ros/rolling/setup.bash
ros2 topic echo /chatter
Now we start the Gazebo Transport talker.
# Shell C:
gz topic -t /chatter -m gz.msgs.StringMsg -p 'data:"Hello"'
Example 1b: ROS 2 talker and Gazebo Transport listener
Start the parameter bridge which will watch the specified topics.
# Shell A:
. ~/bridge_ws/install/setup.bash
ros2 run ros_gz_bridge parameter_bridge /chatter@std_msgs/msg/String@gz.msgs.StringMsg
Now we start the Gazebo Transport listener.
# Shell B:
gz topic -e -t /chatter
Now we start the ROS talker.
# Shell C:
. /opt/ros/rolling/setup.bash
ros2 topic pub /chatter std_msgs/msg/String "data: 'Hi'" --once
Example 2: Run the bridge and exchange images
In this example, we’re going to generate Gazebo Transport images using
Gazebo Sim, that will be converted into ROS images, and visualized with
rqt_image_viewer
.
First we start Gazebo Sim (don’t forget to hit play, or Gazebo Sim won’t generate any images).
# Shell A:
gz sim sensors_demo.sdf
Let’s see the topic where camera images are published.
# Shell B:
gz topic -l | grep image
/rgbd_camera/depth_image
/rgbd_camera/image
Then we start the parameter bridge with the previous topic.
# Shell B:
. ~/bridge_ws/install/setup.bash
ros2 run ros_gz_bridge parameter_bridge /rgbd_camera/image@sensor_msgs/msg/Image@gz.msgs.Image
Now we start the ROS GUI:
# Shell C:
. /opt/ros/rolling/setup.bash
ros2 run rqt_image_view rqt_image_view /rgbd_camera/image
You should see the current images in rqt_image_view
which are coming from
Gazebo (published as Gazebo Msgs over Gazebo Transport).
The screenshot shows all the shell windows and their expected content (it was taken using ROS 2 Galactic and Gazebo Fortress):
Example 3: Static bridge
In this example, we’re going to run an executable that starts a bidirectional
bridge for a specific topic and message type. We’ll use the static_bridge
executable that is installed with the bridge.
The example’s code can be found under ros_gz_bridge/src/static_bridge.cpp
.
In the code, it’s possible to see how the bridge is hardcoded to bridge string
messages published on the /chatter
topic.
Let’s give it a try, starting with Gazebo -> ROS 2.
On terminal A, start the bridge:
ros2 run ros_gz_bridge static_bridge
On terminal B, we start a ROS 2 listener:
ros2 topic echo /chatter std_msgs/msg/String
And terminal C, publish an Gazebo message:
gz topic -t /chatter -m gz.msgs.StringMsg -p 'data:"Hello"'
At this point, you should see the ROS 2 listener echoing the message.
Now let’s try the other way around, ROS 2 -> Gazebo.
On terminal D, start an Gazebo listener:
gz topic -e -t /chatter
And on terminal E, publish a ROS 2 message:
ros2 topic pub /chatter std_msgs/msg/String 'data: "Hello"' -1
You should see the Gazebo listener echoing the message.
Example 4: Service bridge
It’s possible to make ROS service requests into Gazebo. Let’s try unpausing the simulation.
On terminal A, start the service bridge:
ros2 run ros_gz_bridge parameter_bridge /world/shapes/control@ros_gz_interfaces/srv/ControlWorld
On terminal B, start Gazebo, it will be paused by default:
gz sim shapes.sdf
On terminal C, make a ROS request to unpause simulation:
ros2 service call /world/<world_name>/control ros_gz_interfaces/srv/ControlWorld "{world_control: {pause: false}}"
Example 5: Configuring the Bridge via YAML
When configuring many topics, it is easier to use a file-based configuration in a markup
language. In this case, the ros_gz
bridge supports using a YAML file to configure the
various parameters.
The configuration file must be a YAML array of maps. An example configuration for 5 bridges is below, showing the various ways that a bridge may be specified:
# Set just topic name, applies to both
- topic_name: "chatter"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "gz.msgs.StringMsg"
# Set just ROS topic name, applies to both
- ros_topic_name: "chatter_ros"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "gz.msgs.StringMsg"
# Set just GZ topic name, applies to both
- gz_topic_name: "chatter_gz"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "gz.msgs.StringMsg"
# Set each topic name explicitly
- ros_topic_name: "chatter_both_ros"
gz_topic_name: "chatter_both_gz"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "gz.msgs.StringMsg"
# Full set of configurations
- ros_topic_name: "ros_chatter"
gz_topic_name: "gz_chatter"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "gz.msgs.StringMsg"
subscriber_queue: 5 # Default 10
publisher_queue: 6 # Default 10
lazy: true # Default "false"
direction: BIDIRECTIONAL # Default "BIDIRECTIONAL" - Bridge both directions
# "GZ_TO_ROS" - Bridge Gz topic to ROS
# "ROS_TO_GZ" - Bridge ROS topic to Gz
To run the bridge node with the above configuration:
ros2 run ros_gz_bridge parameter_bridge --ros-args -p config_file:=$WORKSPACE/ros_gz/ros_gz_bridge/test/config/full.yaml
Example 6: Using ROS namespace with the Bridge
When spawning multiple robots inside the same ROS environment, it is convenient to use namespaces to avoid overlapping topic names.
There are three main types of namespaces: relative, global (/
) and private (~/
). For more information, refer to ROS documentation.
Namespaces are applied to Gazebo topic both when specified as topic_name
as well as gz_topic_name
.
By default, the Bridge will not apply ROS namespace on the Gazebo topics. To enable this feature, use parameter expand_gz_topic_names
.
Let’s test our topic with namespace:
# Shell A:
. ~/bridge_ws/install/setup.bash
ros2 run ros_gz_bridge parameter_bridge chatter@std_msgs/msg/String@ignition.msgs.StringMsg \
--ros-args -p expand_gz_topic_names:=true -r __ns:=/demo
Now we start the Gazebo Transport listener.
# Shell B:
gz topic -e -t /demo/chatter
Now we start the ROS talker.
# Shell C:
. /opt/ros/rolling/setup.bash
ros2 topic pub /demo/chatter std_msgs/msg/String "data: 'Hi from inside of a namespace'" --once
By changing chatter
to /chatter
or ~/chatter
you can obtain different results.
API
ROS 2 Parameters:
subscription_heartbeat
- Period at which the node checks for new subscribers for lazy bridges.config_file
- YAML file to be loaded as the bridge configurationexpand_gz_topic_names
- Enable or disable ROS namespace applied on GZ topics.