FireAnt / M20 SDK Deploy
This ROS 2 project runs the 8-DoF FireAnt Stage-2 policy in MuJoCo while retaining the original 16-DoF M20 path. FireAnt is the default.
FireAnt alignment
| Item | Deployment value |
|---|---|
| Robot/DDS joint order | FL knee/wheel, FR knee/wheel, HL knee/wheel, HR knee/wheel |
| Policy joint order | FL/FR/HL/HR knees, then FL/FR/HL/HR wheels |
| Actor | 63 observations, 8 actions, 50 Hz |
| Low-level loop | 200 Hz; MuJoCo step 1 kHz |
| Knee control | position action scale 0.25, kp=80, kd=2, limit 75 Nm |
| Wheel control | velocity action scale 5.0, kp=0, kd=0.6, limit 28.68 Nm |
| Wheel | radius 0.096 m, width 0.083 m, mass 1.34 kg |
| Knee module | mass 0.612 kg |
| Base | mass 15.882 kg |
The actor observation is reconstructed in the exact training order: angular velocity, projected gravity, command, relative joint position, joint velocity, last action, wheel/support contact states, wheel/support force magnitudes, wheel-slip proxy and applied torque. The simulator sends base velocity and contact data through the unused entries 8-15 of the fixed 16-slot DDS joint message. This extension is for sim2sim; sim2real requires equivalent estimators/sensors.
The MuJoCo wheel geoms have their own friction values. Contact restitution is effectively zero.
--randomize samples wheel friction, masses, inertias, base COM and control gains once from the
training-time ranges.
Policy export
The repository already contains policy/fire_ant_policy.onnx, exported from:
rl_training/logs/rsl_rl/deeprobotics_m20_support/
2026-09-12_17-52-15_stage2_multiterrain/model_39899.pt
Re-export after selecting a different checkpoint:
cd /home/ycpy/huangweifeng/hwf_workspace/rl_training_huoyi/M20_sdk_deploy
python3 scripts/export_fire_ant_policy.py \
--checkpoint /absolute/path/to/model_xxx.pt \
--output policy/fire_ant_policy.onnx
The exporter checks the ONNX graph and compares its output against PyTorch.
Build
Install the simulator dependency in the Python environment that has ROS 2 rclpy and drdds:
python3 -m pip install "numpy<2" mujoco
Then build in a ROS 2 Humble workspace. The drdds package must be built or sourced first.
cd /home/ycpy/huangweifeng/hwf_workspace/rl_training_huoyi
source /opt/ros/humble/setup.bash
source /path/to/the/workspace/containing/drdds/install/setup.bash
colcon build --packages-select m20_sdk_deploy --cmake-args -DBUILD_PLATFORM=x86
source install/setup.bash
FireAnt sim2sim
Use the same ROS domain in both terminals. Start MuJoCo first so the controller immediately receives valid joint and IMU data.
Terminal 1 — deterministic flat-ground sanity check:
export ROS_DOMAIN_ID=1
source /opt/ros/humble/setup.bash
source /path/to/the/workspace/containing/drdds/install/setup.bash
python3 /home/ycpy/huangweifeng/hwf_workspace/rl_training_huoyi/M20_sdk_deploy/interface/robot/simulation/mujoco_simulation_ros2.py \
--robot fire_ant --terrain flat
Terminal 2 — controller and Stage-2 policy:
export ROS_DOMAIN_ID=1
source /opt/ros/humble/setup.bash
source /path/to/the/workspace/containing/drdds/install/setup.bash
source /home/ycpy/huangweifeng/hwf_workspace/rl_training_huoyi/install/setup.bash
ros2 run m20_sdk_deploy rl_deploy
Keyboard sequence:
- Press
zand wait about 1.5 seconds for the default posture. - Press
cto enter RL control. - Hold
wto move forward;srequests backward motion andq/eturn. - Press
xto lower the robot orrfor joint damping.
Stage-2 was trained with zero lateral command, so a/d are intentionally disabled for FireAnt.
The policy's Stage-2 forward command range is 0.25-1.2 m/s; the keyboard uses 1.2 m/s while held.
With no movement key held, a deployment deadman override holds the default knee pose and commands
zero wheel speed, avoiding the zero-command creep caused by Stage-2's positive-only command sampling.
After the flat test, run the mixed 8/12/16 cm obstacle course:
python3 /home/ycpy/huangweifeng/hwf_workspace/rl_training_huoyi/M20_sdk_deploy/interface/robot/simulation/mujoco_simulation_ros2.py \
--robot fire_ant --terrain rough
Robustness check with one reproducible domain-randomization sample:
python3 /home/ycpy/huangweifeng/hwf_workspace/rl_training_huoyi/M20_sdk_deploy/interface/robot/simulation/mujoco_simulation_ros2.py \
--robot fire_ant --terrain rough --randomize --seed 1
Add --headless for unattended runs and --realtime-factor 0 to run as fast as possible.
Original M20 compatibility
The old model, interface and 57-to-16 ONNX policy remain available:
# Simulator
python3 interface/robot/simulation/mujoco_simulation_ros2.py --robot m20 --terrain rough
# Controller
ros2 run m20_sdk_deploy rl_deploy --robot=m20