This is a package created on the basis of ros_gz_bridge. It has been modified to include a mapping between the NavSat Gazebo Sim plugin velocities and ROS2 Humble.
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/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.
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@ignition.msgs.StringMsg
Now we start the ROS listener.
# Shell B:
. /opt/ros/humble/setup.bash
ros2 topic echo /chatter
Now we start the Gazebo Transport talker.
# Shell C:
ign topic -t /chatter -m ignition.msgs.StringMsg -p 'data:"Hello"'
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@ignition.msgs.StringMsg
Now we start the Gazebo Transport listener.
# Shell B:
ign topic -e -t /chatter
Now we start the ROS talker.
# Shell C:
. /opt/ros/humble/setup.bash
ros2 topic pub /chatter std_msgs/msg/String "data: 'Hi'" --once
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:
ign gazebo sensors_demo.sdf
Let's see the topic where camera images are published.
# Shell B:
ign 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@ignition.msgs.Image
Now we start the ROS GUI:
# Shell C:
. /opt/ros/humble/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):
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:
ign topic -t /chatter -m ignition.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 Igntion listener:
ign 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.
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:
ign gazebo 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}}"
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: "ignition.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: "ignition.msgs.StringMsg"
# Set just GZ topic name, applies to both
- gz_topic_name: "chatter_ign"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "ignition.msgs.StringMsg"
# Set each topic name explicitly
- ros_topic_name: "chatter_both_ros"
gz_topic_name: "chatter_both_ign"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "ignition.msgs.StringMsg"
# Full set of configurations
- ros_topic_name: "ros_chatter"
gz_topic_name: "ign_chatter"
ros_type_name: "std_msgs/msg/String"
gz_type_name: "ignition.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 Ignition topic to ROS
# "ROS_TO_GZ" - Bridge ROS topic to Ignition
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
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:
ign topic -e -t /demo/chatter
Now we start the ROS talker.
# Shell C:
. /opt/ros/humble/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.
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.