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.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# 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 ablation** — `HERDING_LIDAR=360` works in all four diff cells.
|
||||
- **Dual-dog axis-split** — `HERDING_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".
|
||||
Reference in New Issue
Block a user