Skip to content

feat: open forward model (physical imagination) for the 85 mm body - #7

Open
xebastian153 wants to merge 1 commit into
britcruise9:mainfrom
xebastian153:feature/forward-model
Open

feat: open forward model (physical imagination) for the 85 mm body#7
xebastian153 wants to merge 1 commit into
britcruise9:mainfrom
xebastian153:feature/forward-model

Conversation

@xebastian153

Copy link
Copy Markdown

Closes the proposal in #6, in the shape you asked for: standalone runner + weights first, planner split into its own file, at policy/forward/ beside the walk policy.

What this adds

policy/forward/

  • growbot_forward.js — the runner. Pure JS, no deps, browser or Node. History ring, one-tick step(), imagine(plan) open-loop rollout. 82 lines.
  • forward_85mm.json — the weights. 24,841 params (128×2, swish), same size class as policy_85mm.json.
  • growbot_planner.js — optional planToMatch(fwd, targetTrace): a small CEM over an action chunk, the mimic game. Separate so ports and the harness can take the runner alone.
  • test_forward.mjs — verifies the JS against the trained PyTorch net: single step 7.5e-6, 25-tick rollout 5.0e-6; and that the planner beats hold-still on a reachable target. node test_forward.mjs → PASS.
  • README.md — contract, usage, measurements, caveats. Same layout as policy/README.md.

Contract

Mirrors the walk policy's so they share one calibration: last 5 (imu6, [aRight, aLeft]) pairs newest first, same IMU frame and signs you feed GrowBotPolicy, actions in radians of leg swing. Output is the IMU change over one 20 ms tick; angles are (sin, cos) internally so yaw wrap and a roll through ±π never jump.

Measured in the twin (policy/Harsh_policies/DR_RMA_EXPORT)

Imagined roll/pitch within 0.2 rad of truth, held-out episodes:

horizon nothing-changes linear this model
100 ms 85.9 % 93.5 % 95.9 %
500 ms 59.0 % 75.0 % 83.6 %

Gains concentrate where the video locates the gap: fast motion 41 → 86 %, tipping/fallen 58 → 89 %.

Mimic game, 40 held-out 2 s traces, plan through imagination and execute in the twin: hold-still 0.210 rad RMSE, planning without a forward model 0.220 (worse than doing nothing), with this model 0.095, beating hold-still on 39/40. Replanning every 100 ms is the optimum.

What it isn't

Sim-only — it has learned MuJoCo. The on-device error-driven update (the learning half) is the follow-up, and I'll take that to #world-model. Nothing here touches firmware, protocol or the harness.

Source, data generation, evaluation: https://github.com/xebastian153/growbot-cerebellum

Checklist

  • One change, one folder, 251 lines + weights JSON
  • No secrets, keys or env files
  • Test runs green from inside the fork
  • License: PolyForm NC, same as the walk policy, weights included

A 24,841-param net that predicts the change in the phone IMU over one
20 ms tick from the last 5 (imu, action) pairs, packaged like the walk
policy: pure-JS runner, weights JSON, and a Node test that verifies the
runner against the trained PyTorch net (single step 7.5e-6, 25-tick
rollout 5.0e-6). imagine() rolls a plan forward open-loop.

The mimic planner (planToMatch, a small CEM over an action chunk) lives in
its own file, growbot_planner.js, so ports and the harness can take the
runner alone.

Trained on the MuJoCo twin in policy/Harsh_policies/DR_RMA_EXPORT.
Measured in the twin, imagined roll/pitch within 0.2 rad of truth at
100 ms: nothing-changes 85.9 %, linear 93.5 %, this model 95.9 %; gains
concentrate under fast motion (41 -> 86 %) and while fallen (58 -> 89 %).
Mimic game over 40 held-out traces: 0.095 rad RMSE vs 0.210 holding still,
beating hold-still on 39/40.

Sim-only; sim-to-real and the on-device error-driven update are the
follow-ups. Discussed in britcruise9#6.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant