Skip to content

Gazebo ​

Introduction ​

Open-source Ignition Gazebo (Fortress) simulator for the RBQ quadruped robot.

Gazebo runs the full RBQ software stack (Motion / Vision / GUI) against a physics simulation, so you can develop and test robot software without any hardware. In addition, it bridges sensor data onto ROS 2, so external nodes (for example SLAM) can subscribe to the simulated IMU, LiDAR, TF, and joint states. Unlike the Isaac Gym and Isaac Lab environments, the goal here is full-stack simulation, not RL policy training.

Layout ​

PathDescription
src/Simulator sources → bin/rbq_gazebo
resources/Worlds, robot/sensor URDFs, meshes
ros2/src/sensor_bridge/colcon package: bridge launch, RViz config, DDS xml
scripts/Build / run / Docker scripts

Robot variants ​

FlagRobotModel
(none)RBQ quadruped — 12 jointsresources/models/rbq10/
--wheelWheeled RBQ — 12 joints + 4 driven wheelsresources/models/rbq10_wheel/

gazebo.bash passes the matching variant:= to the sensor bridge, so RViz loads the same URDF.

NOTE — pass the variant to the RBQ stack too

Wheel state and references ride SimInfo_.whl_joint / MotionRef_.whl_joint, so the robot-side Motion must run with the same variant — start the stack with bash scripts/sim.bash -r wheel from the repository root.

LiDAR ​

LiDAR is opt-in — nothing is spawned without a flag.

FlagDeviceMounting
(none)none—
--livoxLivox Mid-360 x2front (+35° up) / rear (−35° up)
--ousterOuster OS1 x1rear deck
bash
bash scripts/gazebo.bash --livox           # 2x Livox Mid-360
bash scripts/gazebo.bash --ouster          # 1x Ouster OS1

gazebo.bash forwards the same value to the sensor bridge as lidar:=, so one flag lines up all three:

  • Gazebo — the spawn URDF gets that LiDAR's <visual> (housing) + <sensor> (gpu_lidar) spliced in
  • TF — static base_link → lidar_front | lidar_rear | lidar_ouster
  • RViz — loads the URDF generated for the same combination (rbq10_livox.urdf, …), housings included

For the point-cloud topics, see the QoS table under External node access below.

WARNING — an empty RViz usually means the RBQ stack is not running

The bundled RViz config uses local_world as its Fixed Frame, and that frame is published by the RBQ stack (the Network daemon), not by Gazebo. Run Gazebo alone and the robot model never draws and every point cloud is dropped with Message Filter dropping message ... queue is full. Start bash scripts/sim.bash --vision --no-sim alongside it, or switch the RViz Fixed Frame to world.

Run with the full RBQ stack (Local) ​

Run the full RBQ stack (Motion / Vision / GUI) together with the Gazebo simulator:

bash
# Clone
git clone https://github.com/RainbowRobotics/RBQ.git
cd RBQ

# Install dependencies (first time only)
cd rbq_simulator/rbq_gazebo && bash scripts/debian-dep.bash

# Build rbq_gazebo
bash scripts/build.bash
cd ../../

Quadruped

bash
bash scripts/sim.bash --vision --no-sim
cd rbq_simulator/rbq_gazebo
bash scripts/gazebo.bash

Wheeled RBQ

bash
bash scripts/sim.bash --vision --no-sim -r wheel
cd rbq_simulator/rbq_gazebo
bash scripts/gazebo.bash --wheel

Run with the full RBQ stack (Docker) ​

Run the same stack with the Gazebo simulator inside Docker:

bash
# Clone
git clone https://github.com/RainbowRobotics/RBQ.git
cd RBQ

Quadruped

bash
bash scripts/sim.bash --vision --no-sim
cd rbq_simulator/rbq_gazebo
bash scripts/docker/run.bash

Wheeled RBQ

bash
bash scripts/sim.bash --vision --no-sim -r wheel
cd rbq_simulator/rbq_gazebo
bash scripts/docker/run.bash --wheel

run.bash forwards any argument it does not recognize to the simulator, so --wheel, --livox / --ouster and --world <name> all pass straight through.

NOTE — DDS networking

The simulator shares DDS domain 0 on the loopback interface (lo) with the host RBQ stack. In Docker this is provided by --network host.

External node access (SLAM / custom ROS 2 nodes) ​

The sensor_bridge publishes on ROS 2 domain 0 over loopback (lo). Run your node from rbq_simulator/rbq_gazebo with these environment variables (CycloneDDS is required to match the bridge):

bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export ROS_DOMAIN_ID=0
export CYCLONEDDS_URI=file://$(pwd)/ros2/src/sensor_bridge/config/cyclonedds_gazebo.xml

QoS is the ros_gz_bridge default (override per-topic in ros2/src/sensor_bridge/config/bridge.yaml):

ROS 2 TopicTypeQoSNote
/rbq/imu/IMU_statesensor_msgs/msg/ImuReliable · KeepLast 10500 Hz
/rbq/lidar/lidar_front/pointssensor_msgs/msg/PointCloud2Reliable · KeepLast 10--livox
/rbq/lidar/lidar_rear/pointssensor_msgs/msg/PointCloud2Reliable · KeepLast 10--livox
/rbq/lidar/lidar_ouster/pointssensor_msgs/msg/PointCloud2Reliable · KeepLast 10--ouster
/tftf2_msgs/msg/TFMessageReliable · KeepLast 10world → robot (ground truth)
/joint_statessensor_msgs/msg/JointStateReliable · KeepLast 1012 joints

/tf carries two independent chains. world → robot is the Gazebo ground truth pose, published by the rbq_gazebo bridge. local_world → base_link is the state estimator output (IMU + leg odometry, origin at boot/reset), published by RBQ SW. Ground truth is deliberately attached to robot rather than base_link so the two never compete for the same parent frame.

/rbq/odometry, /rbq/imu and /rbq/joint_states come from the RBQ stack over DDS, not the bridge. Under --sim they use the simulation clock, so use_sim_time nodes see one time base.

See also ​

This user manual is intended for RBQ users.