Files
TIR_PROJ/docs/status.md
T
Johnny Fernandes 27c0f65722 Mecanum Webots via Supervisor kinematic injection
Replace the failing ODE-rolled mecanum chassis dynamics with a
Supervisor.setVelocity call that uses the gym mecanum forward
kinematics formula directly. Wheel motors still spin (visual);
chassis motion comes from the gym model so training and deployment
match by construction.

Results (seed=42, n=10 sheep): BC + RL mecanum pen 10/10 in both
field and field_round. n=5 mecanum cells still 0/5 due to tracker
phantoms anchored to wall corners under the 360° LiDAR — documented
in docs/status.md as the remaining gap.

Cleanup: drop deploy-time hacks (HERDING_HEADING_*, HERDING_OMEGA_CLAMP,
HERDING_TRACKER_*) that were workarounds for the old ODE chaos;
revert the proto inertiaMatrix, roller dampingConstant, and reduced
motor torque since they no longer carry load; refresh comments
around the mecanum config presets.
2026-05-18 22:46:37 +00:00

5.0 KiB
Raw Blame History

Status — 2026-05-18

Current snapshot of what works in Webots, and what design choices got us here.

Results matrix (Webots, seed=42)

Differential drive — bash tools/run_webots.sh N MODE differential WORLD:

controller field n=5 field n=10 field_round n=5 field_round n=10
BC 5/5 10/10 5/5 10/10
RL 5/5 10/10 5/5 10/10
Strömbom 5/5 10/10 5/5 10/10
Sequential 5/5 10/10 5/5 10/10

Mecanum drive — bash tools/run_webots.sh N MODE mecanum WORLD HERDING_LIDAR=360:

controller field n=5 field n=10 field_round n=5 field_round n=10
BC 0/5 10/10 0/5 10/10
RL 0/5 10/10 0/5 10/10

Extra-merit:

  • 360° LiDAR ablationHERDING_LIDAR=360 works in all four diff cells.
  • Dual-dog axis-splitHERDING_NDOGS=2 HERDING_AXIS_LEAK=0.3 pens 5/5 on diff.

Architecture decisions and why

Differential drive — full ODE simulation

Standard Webots physics with two wheel motors and a caster. No special handling needed; the chassis is dynamically stable, and the trained policies transfer directly to Webots.

Mecanum drive — kinematic Supervisor injection

The mecanum proto uses physical 8-roller wheels for visual fidelity, but the chassis is moved by Supervisor.setVelocity() using the gym mecanum forward-kinematics formula (see controllers/shepherd_dog/shepherd_dog.py::drive_mecanum).

We explored two other paths before settling here:

  1. Plain cylinder wheels + anisotropic ContactProperties. Tried frictionRotation ±0.7854 on the wheel contact frame. Strafe motion came out the wrong direction and diagonals zeroed out. Discarded.
  2. Full ODE simulation on 32 physical roller hinges. The free-spinning rollers coupled chaotically through the body, producing ±150° yaw drift over 200 control steps. Even with inertiaMatrix overrides, dampingConstant on every roller, and a 6× cut to motor torque, dynamic policy commands kept producing tumbling. Discarded.
  3. Kinematic Supervisor injection (current). ODE physics on the wheels is kept for visuals only; the chassis velocity is set directly each step from the gym forward-kinematics formula. Gym training and Webots deployment produce identical body motion. Yaw drift is zero by construction.

This is not a hack — it matches how most academic mecanum sims work (e.g., Gazebo's mecanum plugins use kinematic models by default; ODE's contact solver does not handle the rolling-without-slipping constraint cleanly for 32 free hinges).

Why n=5 mecanum fails (and n=10 passes)

The 360° LiDAR scans the full perimeter every step. Wall corners, gate posts, and pen rails occasionally produce sheep-shaped blobs that pass the wall_reject and static_reject filters. The tracker promotes a candidate to "active" after consensus_k=3 consistent hits within 20 steps — phantoms anchored to fixed world features satisfy this trivially.

With n=10 real sheep, the tracker's active slots fill with real sheep and phantoms can't compete. With n=5 there are ~5 free slots that wall phantoms occupy; the policy then chases ghosts.

Tightening the consensus filter (consensus_k=5) and wall_reject=0.9 were tried; both kept ~70% of frames at 10 active tracks. The proper fix is parallax-aware tracking — record each track's world position across multiple dog vantage points; real sheep move, static phantoms don't. Out of scope for the 2026-06-04 deadline.

File map (what changed in this push)

herding/config.py                      mecanum presets keep matched
                                       strafe scaling (strafe_eff=0.26,
                                       bleed=-0.40) for kinematic injection
controllers/shepherd_dog/shepherd_dog.py
                                       Supervisor() + drive_mecanum kinematic
                                       injection via _self_node.setVelocity
protos/ShepherdDogMecanum.proto        supervisor TRUE; physics tuning
protos/ShepherdDogMecanum360.proto     reverted (ODE no longer load-bearing)
tools/gen_mecanum_wheels.py            wheels regen-script (clean)
tools/run_webots.sh                    contact-properties comment cleaned
training/{bc/collect,rl/train}.py      comment cleanup; preset selection unchanged

Options for the remaining cleanup

  1. Keep matched preset (0.26, -0.40). Policies trained against these values; controller applies them at deploy; no retrain. Current state.
  2. Switch preset to textbook (1.0, 0.0) and retrain mecanum BC+RL (~6h). Cleaner story (textbook mecanum throughout); same kinematic-injection mechanism.

Either is defensible. (1) ships faster; (2) is more "pure".