🤖AI-generated documentation☐ curatedAI Generated
About content generation types
(e.g., docs generated from codebase analysis)
(e.g., livestream → blog post, meeting notes → docs)
(e.g., hand-written tutorial)
Implementation Plan
Progress tracker
High-level status — checked off as we go. Granular task checkboxes live in each phase below.
- Phase 0 — Center of mass + XCoM (pre-existing)
- Phase 1 — Module scaffold + point-mass ellipsoid + ground references — backend ✅ tested (plan) + frontend ✅ typechecked (plan); live visual smoke pending hardware
- Phase 2 — Real segment inertia + orbital angular momentum
- Phase 3 — Per-segment orientation + spin term (full RMP)
- Phase 4 — Posthoc path + validation
Phasing at a glance
Phase 0 — Center of mass + XCoM (done)
Already in the realtime pipeline: per-frame whole-body and per-segment CoM
(center_of_mass.py) and the XCoM (Hof 2008). This proposal builds directly on the data
these already produce (segment_coms, mass fractions, the prev_com velocity history).
- Whole-body + per-segment center of mass (per frame)
- XCoM / instantaneous capture point (per frame)
Phase 1 — Module scaffold + point-mass ellipsoid + ground references
Goal: stand up freemocap/core/kinematics/ and get a meaningful reaction-mass ellipsoid
and the ground-reference overlay on screen — with no new data required.
- Scaffold the
freemocap/core/kinematics/package (withinertial/andonline/). - Add
inertial/composite_inertia.py: point-massI_Gfrom masses + segment CoMs,eigh→ principal axes/moments, and equimomental display semi-axes. - Add
inertial/ground_reference.py: CoP (CoM ground projection), XCoM (move/centralize the existing computation here), CMP. - Add
body_kinematics_state.py(BodyKinematicsState) andonline/streaming_kinematics.py(per-frame wrapper using the rolling-history pattern). - Wire into
RealtimeAggregatorNodeafter the CoM step; addbody_kinematicstoAggregationNodeOutputMessageandFrontendPayload. (serialization verified through the real websocket encoder; live camera-session smoke still pending hardware.) - Frontend: render the reaction-mass ellipsoid + CMP / CoP→CMP overlay
(
BodyKinematicsRenderer), default-on. tsc clean; live visual smoke pending hardware.
Resequenced (2026-06-21): the bs ontology port (ReferenceGeometry / RigidBodyKinematics / quaternion / derivatives) moved to Phase 3 — the point-mass ellipsoid and ground references need no orientation, so the port is not on the Phase 1 critical path.
Acceptance: ellipsoid stretches/tumbles with body mass distribution; CoP, XCoM, CMP draw on the ground plane; CMP ≈ CoP when the subject is still, separating during dynamic motion. Hot-loop cost stays negligible (target well under 0.1 ms/frame for the math).
Phase 2 — Real segment inertia + orbital angular momentum
Goal: make the ellipsoid anatomically correct and add (most of) the angular momentum.
- Add
inertial/anthropometry.py: de Leva 1996 Table 4 radii of gyration (+ mass & CoM), female + male tables with the mean as default. Single source of truth; mass fractions sum to 1.0 (verified by test). - Add
inertial/segment_inertia.py:Jᵢ = mᵢ · diag((r·L)²)about each segment CoM. - Feed
Jᵢintocomposite_inertia(drop the point-mass assumption). - Add
inertial/centroidal_momentum.pywith the orbital term only:H_G ≈ Σ mᵢ dᵢ × (vᵢ − v_G)(needs segment-CoM velocities — extend the rolling history). - Add
H_G(andω = I_G⁻¹ H_G) toBodyKinematicsState; render theH_Garrow.
Acceptance: ellipsoid matches expected human segment-inertia proportions; H_G responds
sensibly to arm swing / trunk rotation; values are in a plausible range vs literature.
Phase 3 — Per-segment orientation + spin term (full RMP)
Goal: complete H_G and the inertia model with rotational detail.
- Port the bs
kinematics_coreontology intofreemocap/core/kinematics/(reference_geometry,rigid_body_state,rigid_body_kinematics,quaternion,derivatives; imports →freemocap.core.kinematics.*; port the bs tests). Moved here from Phase 1 — first needed for per-segment orientation. - Per-segment orientation: bone-vector frames for limbs;
ReferenceGeometryframes for trunk / pelvis / head (shoulders + hips). Deriveωᵢvia the ported angular-velocity machinery, per-frame. - Add the spin term
Σ Jᵢ ωᵢtocentroidal_momentum. - Rotate segment inertia tensors into world frame in
composite_inertia(R Jᵢ Rᵀ) for full fidelity.
Acceptance: full H_G (orbital + spin) and ω; spin term is a sensible secondary
contribution; ellipsoid orientation tracks trunk/limb configuration.
Phase 4 — Posthoc path + validation
Goal: offline parity and trustworthiness.
- Consume the same
inertial/*core from the posthoc pipeline usingRigidBodyKinematicstrajectories (clean whole-array derivatives → less-noisyH_G). - Persist per-frame
BodyKinematicsStatefields into the recording data store. - Validate against literature benchmarks: spin angular momentum magnitude in gait (Herr &
Popovic), CMP-within-support-base behavior (Popovic/Goswami/Herr), and the point-mass
limit (zero
H_G→ CMP = CoP, XCoM = capture point).
Acceptance: offline and realtime agree within filtering differences; benchmarks fall in published human ranges.
Cross-cutting principles
- Estimation only. No controllers, no actuators (see Overview scope).
- Pure functions at the core. All physics lives in pure, unit-tested functions called by both pipelines.
- Honesty flags. The CoP is estimated (no force plate); outputs carry a flag and the docs/UI say so.
- Fail loudly. No silent fallbacks; unexpected states raise. (Phase boundaries are the valid place to gate on data availability, e.g. needing ≥2 frames for velocities.)
- Single source of truth. Anthropometry, the XCoM formula, and the inertia math each have
exactly one definition point in
freemocap/core/kinematics/.
Open questions to resolve during build
- Final field set + serialization for
BodyKinematicsState(and binary vs JSON if it grows). - de Leva vs Dumas as the default anthropometric source (diagonal radii vs full tensors).
- Whether trunk-frame definition reuses the FABRIK canonical landmarks or defines its own
ReferenceGeometry. - Ellipsoid scaling convention for display (
√λvs radii of gyration vs a tuned visual gain).