Skip to content

Role-table version 2: bind the upper chest by the model's chain (MOT-O12) - #25

Merged
snkmcb merged 1 commit into
mainfrom
phase9/role-table-v2
Sep 25, 2026
Merged

snkmcb merged 1 commit into
mainfrom
phase9/role-table-v2

Conversation

@snkmcb

@snkmcb snkmcb commented Sep 25, 2026

Copy link
Copy Markdown
Member

Stacked on #24. It opens against that branch, so this diff shows only role-table version 2. Merge #24 first.

Summary

This PR resolves MOT-O12. In both local models that have 上半身3, the chain is 上半身 → 上半身3 → 上半身2 → 首. Role-table version 1 bound 上半身2 as chest and 上半身3 as upperChest, which is the opposite order.

Ordering the two bones by the chain is not enough. The shared retarget drops a joint the target does not bind, rather than folding it into its child (usd-motion-plugins RETARGETING_POLICY §4.1, case 6). On a target without 上半身3, both orders leave the arms up to 25° off:

  • under version 1, the neck carries 上半身2's key twice;
  • with only the order changed, 上半身2's key is dropped.

Version 2 (kRoleTableVersion = 2) binds the two bones differently on each side:

  • As a target: 上半身2 and 上半身3 bind chest and upperChest in the model's own chain order. Where 上半身3 is off the neck's chain, it binds nothing.
  • As a source: upperChest is never emitted. chest is the bone the neck hangs from, and its evaluated world rotation already holds every torso rotation below it. This is the second role, after hips, that a source and a target bind differently.

Measured over 17 local characters (motion C, PMX onto PMX, identity rests; median / largest p95 / max):

Segment Version 1 Version 2
neck 2.73° / 19.37° / 22.37° 2.66° / 11.89° / 11.89°
upper arm 2.63° / 18.49° / 25.20° 2.45° / 5.26° / 5.26°
lower arm 2.04° / 18.94° / 25.68° 1.82° / 5.62° / 5.62°

Motion C's figures now equal motion A's.

Changes

  • mmdSkeletonAdapter: OrderUpperBody sets the target order and SourceUpperBody builds the source roles; the version is bumped. Unit tests cover the conventional order, the inserted order and the off-chain case.
  • check_installed_consumer.py: now expects roleTable=2.
  • MOTION_CONTRACT:
    • §12.2 has new rows and an "upper chest" paragraph. Its heading drops "version 1", so the links to its anchor are updated.
    • §12.5 now states version 2.
    • MOT-O12 moves to the resolved questions.
  • Docs:
    • a new report, docs/reports/2026-09-25-phase9-upper-chest.md;
    • a CHANGELOG entry under "Changed";
    • updates to the roadmap, CAPABILITY_MATRIX and WORKSPACE.

Test plan

  • ctest --preset windows-release: 32 of 32 pass, including workspace_installed_consumer with roleTable=2.
  • python scripts/check_docs.py passes.
  • The before/after figures above come from local runs with the installed build.

🤖 Generated with Claude Code

…O12)

Both local models that have 上半身3 chain 上半身 -> 上半身3 -> 上半身2 ->
首. Version 1 bound 上半身2 as chest and 上半身3 as upperChest.

The shared retarget drops a joint a target does not bind. It does not
fold that joint into its child (RETARGETING_POLICY 4.1, case 6).
Reordering the two bones therefore does not help on a target without an
upper chest. Under version 1 the neck carried 上半身2's key twice; the
reordered table drops that key instead. Both leave the arms up to 25
degrees off.

Version 2 binds the two bones differently on each side.

- As a target, they bind in the model's own chain order. Where 上半身3
  is off the neck's chain, it binds nothing.
- As a source, upperChest is never emitted. chest is the bone the neck
  hangs from, and its world rotation already holds the torso below it.

Over the local corpus, arms from those models now stay within 2.5
degrees of the ground truth on every target, as every other pair does.

The MOTION_CONTRACT section 12.2 heading drops "version 1", so the links
to its anchor are updated. MOT-O12 moves to the resolved questions,
backed by a new dated report.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@snkmcb
snkmcb changed the base branch from docs/mot-o10-rest-comparison to main September 25, 2026 03:43
@snkmcb
snkmcb merged commit d95b329 into main Sep 25, 2026
8 checks passed
@snkmcb
snkmcb deleted the phase9/role-table-v2 branch September 25, 2026 03:43
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