The Create 3 / TurtleBot 4 stack¶
roqsim_create3_toolbox runs the iRobot Create 3’s own software stack – and the TurtleBot 4’s
node on top of it – over roqsim’s turtlebot4 model, so a stack, a scenario or an evaluator
that talks to a TurtleBot 4 finds the same ROS 2 interface it finds on the robot and in the
robot’s Gazebo simulator: wheel_vels, hazard_detection, dock_status, kidnap_status,
the safety_override parameter, the e_stop service, the dock/undock actions.
None of that is reimplemented here. The Create 3 API is the released irobot_create_nodes, the
adapters that turn a simulator’s raw streams into Create 3 events are the released
irobot_create_gz_toolbox (Gazebo-named, but every adapter in it except the bumper consumes plain
ROS types), and the TurtleBot 4’s node is the released turtlebot4_node. What this package adds is
the one adapter that could not be reused, the launch files, and the world; what the model adds is
the raw streams on the names those adapters’ shipped parameter files expect.
Run it¶
source /opt/ros/jazzy/setup.bash
source ros2_ws/install/setup.bash
python -m roqsim_ros_bridge.run_bridge --world ros2_ws/src/roqsim_create3_toolbox/worlds/turtlebot4_create3.yaml --headless
ros2 launch roqsim_create3_toolbox turtlebot4_nodes.launch.py # or create3_nodes.launch.py
Then, as on the robot:
ros2 topic hz /wheel_vels # ~62 Hz
ros2 param get /motion_control max_speed # 0.306; 0.46 after ...
ros2 param set /motion_control safety_override full
ros2 service call /e_stop irobot_create_msgs/srv/EStop "{e_stop_on: true}"
ros2 action send_goal /dock irobot_create_msgs/action/Dock {}
Nav2 runs beside it exactly as in nav2 example, publishing cmd_vel: motion_control
owns that topic, applies the safety features, and hands the clamped command to the base on
diffdrive_controller/cmd_vel, which is where the world points the base’s diff_drive.
How it is layered¶
The same three layers the robot’s Gazebo simulator has, so the stack’s behaviour is the stack’s and only the physics is roqsim’s:
What the stack consumes |
The Gazebo TurtleBot 4 supplies it as |
roqsim supplies it as |
|---|---|---|
|
|
|
|
|
|
Bumper events on |
a contact sensor on the bumper link; the toolbox zones each contact by its bearing |
the |
Cliff ×4 and IR ×7 as |
one ray and 5×5 ray sensors in the URDF |
|
Wheel drop from |
the URDF’s suspension joints; Gazebo’s |
the model’s suspension joints; |
|
|
the same binaries, launched by this package with their shipped parameter files |
What is the same, and what is not¶
Interfaces are identical to the Gazebo TurtleBot 4 and to the real robot’s republished surface –
the nodes that define them are the same binaries. Every topic the robot’s republisher.yaml lists,
commented out or not, exists.
Behaviour is identical for the stack layer: the speed clamp, the backup limit, e_stop, the
hazard vector, kidnap estimation, the IR intensity formula, the cliff threshold, the wheel-drop
hysteresis, the docking geometry and behaviours are the same code. It differs for the physics
layer: contact forces, ray hits, wheel slip and suspension travel come from MuJoCo, so a bumper
zone or a cliff fires on the same geometric condition, not at the same millisecond.
Neither simulator is the robot. Inherited knowingly from the reference simulator: reflexes are a
stub there (enabling one throws); slip_status, interface_buttons, stop_status and the
battery are mocks or models; motion_control is iRobot’s re-implementation of firmware
behaviour, not the firmware; the real republisher forwards only what its configuration lists,
whereas in simulation everything is always on; the HMI display and LEDs have no physical
counterpart without the Gazebo GUI plugin; and kidnap_status never turns true, because the
simulator adapters stamp a wheel-drop event with its joint’s name and a cliff event with
base_link while the kidnap estimator counts events framed wheel_drop_left and
cliff_<sensor> – the hazards themselves (four CLIFF, two WHEEL_DROP) are on
hazard_detection when the robot is lifted, in both simulators. The firmware’s
wheel_accel_limit is not a parameter of the simulated motion_control: the ramp is the base’s
diff_drive: {wheel_accel_limit}.
On the real robot¶
A topic that is missing on the robot is usually commented out in the republisher’s parameter
file: turtlebot4_bringup/config/republisher.yaml is what create3_republisher (started by
turtlebot4_bringup’s robot.launch.py, argument create3_param_file) forwards from the
Create 3’s own DDS domain to the compute board’s, and it has nothing to do with nav2_params.yaml.
Uncomment wheel_vels there (the installed copy, or your own file passed as
create3_param_file:=) and restart the turtlebot4 service. The safety parameters are
parameters of the Create 3’s motion_control node; which node name is reachable from the compute
board depends on the discovery-server and namespace setup, so check ros2 node list there.
Varying it in a campaign¶
config/create3_params.yaml holds the motion_control parameters as one file, so a campaign
tool that rewrites a parameter file per configuration addresses
motion_control.ros__parameters.safety_override and nothing else; the base’s and the sensors’
keys are world keys (components.robot.diff_drive.wheel_accel_limit,
components.robot.cliff_front_left.max_range) and are varied as any world key is; and the
Create 3 topics are recorded and converted like any other, given irobot_create_msgs wherever
the bags are read.