Overview
The live (production) Nav2 stack runs on the robot, and does its own autonomous driving with no server in the loop. The sim Nav2 stack runs on the server and drives Gazebo. The two use different topic naming, bare names for the live and sim_*//gazebo/* for the sim, so the sim never mixes with live driving. In short: drive is on the robot, the sim is on the server.
Stack: map_server, amcl, ekf_localization, navsat_transform, planner_server, controller_server, behavior_server, bt_navigator, smoother_server, velocity_smoother, costmaps, lifecycle_manager.
Locomotion: CHAMP (gait + IK, 200 Hz) runs on the robot and drives the real hardware (12× GIM6010-8 CAN-bus motors, 12 DOF); the sim instance runs in Gazebo on the server under the sim_* topic convention. Operator teleop: Limit Dash keyboard drive, W/S fwd·back, Q/E strafe, A/D turn.
Stack dataflow
IMU source: /imu_corrected is the stamp-shifted ZED 2i IMU (/zed2i_front/zed_node/imu/data), the EKF IMU source. /ouster/imu is not published. Ouster supplies /ouster/scan and /ouster/points only.
EKF chain: odom0 = /zed_odom_corrected (stamp-shifted ZED VIO odometry), imu0 = /imu_corrected, odom1 = /odometry/gps (navsat_transform) → /odom + TF odom→base_link.
Locomotion contract (CHAMP reference):
- In: live, CHAMP (robot) consumes the velocity command over DDS (Twist, via the
cmd_vel_stamped_to_twistadapter) and drives the GIM6010-8 motors on CAN. Sim, the same adapter feeds the Gazebo CHAMP on the server. - Out:
joint_states(live, encoder feedback),foot_contacts; sim publishes thesim_*variants. - Odometry: live, the robot EKF consuming the ZED odom (see above); sim, state_estimation → EKF on the server →
/odom+ TFodom→base_link.
/cmd_vel chain
All commanded motion arrives on a single bus. The live chain runs on the robot with bare topic names; the sim chain runs on the server under the sim_* names. Both are the same stock Nav2 chain, just on different machines.
Live (robot, drive)
- Autonomous:
controller_server(FollowPath) →/cmd_vel_raw→velocity_smoother→/cmd_vel→ the live CHAMP. Runs entirely on the robot, no server. - Recovery:
behavior_serverSpin/BackUp publish straight to/cmd_vel, bypassing the smoother (standard stock Nav2). - Teleop (drive): Limit Dash keyboard drive publishes straight to
/cmd_vel(W/S fwd·back, Q/E strafe, A/D turn).
Sim (server, autonomous)
- Autonomous: the same chain on the server under
sim_*names,sim controller_server→/sim_cmd_vel_raw→velocity_smoother→/sim_cmd_vel→ the sim CHAMP → Gazebo. - Autonomous only. Teleop does not drive the sim; it only ever works with the live chain on the robot.
Lyrical velocity_smoother uses array-based velocity/accel limits and takes its topic names from remaps: cmd_vel input remapped to /cmd_vel_raw, output remapped to /cmd_vel:
use_sim_time: false
max_velocity: [1.0, 0.0, 1.5] # x m/s, y LOCKED TO ZERO, θ rad/s
min_velocity: [-1.0, 0.0, -1.5]
max_accel: [1.5, 0.0, 3.0]
max_decel: [-1.5, 0.0, -3.0]
smoothing_frequency: 20.0
feedback: "OPEN_LOOP"
enable_stamped_cmd_vel: true
Locomotion
CHAMP (quadruped_controller) runs the gait at 200 Hz over 12 DOF (trot) on the robot and drives the 12× GIM6010-8 motors (CAN, 1 Mbps, frame = (node_id<<5)|cmd_id) in position mode. CHAMP additionally publishes /joint_states (encoder feedback) and /foot_contacts.
In the Gazebo path, cmd_vel_stamped_to_twist adapts /cmd_vel (TwistStamped) to /cmd_vel/smooth (Twist) for the controller.
Gazebo simulation
The sim stack runs the CHAMP Gazebo workspace on the same domain, under the sim_* topic convention:
ROS_DOMAIN_ID=0 ros2 launch limitx_limit_sim limit_limit_launch.py \
rviz:=false gazebo_relay:=true gui:=false
Command path: /cmd_vel → cmd_vel_stamped_to_twist → /cmd_vel/smooth → quadruped_controller → Gazebo legs. State returns live: /sim_joint_states (~230 Hz), /odom, /gazebo/imu_corrected (~93 Hz), /gazebo/foot_contacts (~100 Hz), and the 15 /gazebo/* relay routes. gt_pose_bridge publishes /sim_amcl_pose (ground truth + constant (5,5) offset).
CHAMP stack packages, including champ, champ_base, champ_msgs, limitx_application, limitx_limit_description, and limitx_limit_sim, live in production-limit-baremetal-2604-nav2/src/.