Skip to content

fix(mechanism): rest-pose collision/contact gate; seat the SO-100 arm and gripper - #935

Merged
w1ne merged 17 commits into
developfrom
fix/rest-pose-collision-gate
Oct 13, 2026
Merged

w1ne merged 17 commits into
developfrom
fix/rest-pose-collision-gate

Conversation

@w1ne

@w1ne w1ne commented Oct 12, 2026

Copy link
Copy Markdown
Owner

Problem

The SO-100 arm painted with links through each other and still came back ok from evaluate_script. Nothing failed when parts penetrated at rest, and once the pose sweep went over budget the verdict dropped to unverified, which still passes.

Gate (criterion 9, src/modeling/runtime/restPoseContact.ts)

This runs on every assembly that has mates, using the rest scene that is already lowered. It runs whether or not the sweep fits the budget.

  • mechanism.rest-interpenetration (error) checks every part pair whose AABBs overlap. The shared volume is integrated on the analysis meshes (getMesh()) with a voxel grid of at most 96³ cells and a minimum cell of 0.25 mm. A grid point counts as inside a mesh when at least 2 of the 3 axis-ray parity tests say so. The cap is the existing uniform 20 mm³ contact-noise cap (JOINT_CONTACT_NOISE_MM3). The message names the pair, the volume, the location and the voxel size. solvedModel({ ignore }) does not silence this check.
    • Why mesh-based: OCCT BRepAlgoAPI_Common on solids sewn from STL is badly wrong. For SO-100 Base vs Base_Motor it reports 10,857 mm³, while point sampling gives 21 mm³ and an exact manifold boolean gives 23.8 mm³.
  • mechanism.mate-gap (error) requires the two parts of every mate to be within 1 mm of each other at rest (BRep extrema distance). The message names the mate, the pair and the gap.
  • Coincident faces, a pin in a clearance bore, and pocketed or fastened parts all share about 0 volume and pass. Mate-less multi-part scenes are not mechanisms and are skipped.
  • This also carries PR Fail disconnected links at rest, and seat the SO-100 elbow, wrist, and claw #884's rest-pose joint-mesh gap check, which runs when the sweep is skipped.

SO-100

  • parts/seat_meshes.py uses exact manifold booleans to cut the servo pockets, and grooves of revolution around the joint axis that cover each joint's full URDF travel, into the printed links. Output goes to parts/sim-seated/. The servos are not changed. Lower_Arm has non-manifold vendor seams and ships unchanged; its leftover contact with its servo is about 6–14 mm³ by sampling, which is under the cap.
  • so100.kcad.ts is now the real SO-ARM100 gripper: Fixed_Jaw, its STS3215, and Moving_Jaw on a revolute joint on the servo output. It replaces the bracket-and-floating-jaw layout. Verdict: real.
  • so100-arm.kcad.ts loads the seated links. It passes the gate. The verdict is unverified because the sweep is still over budget (work 455 vs budget 300).

Tests

  • tests/unit/assemblies/restPoseContactGate.test.ts: checks the volume integral; a colliding elbow fails with the pair named; ignore is not honored; a floating bracket fails with its gap; a pin in a bore plus a cap on top passes.
  • tests/integration/examples/so100Gripper.test.ts and so100ArmRestContact.test.ts: the fixed examples pass, and the unseated vendor base/servo pair fails with the pair named.

cursoragent and others added 17 commits October 12, 2026 18:48
SO-100's elbow and wrist shells stop short of the joint, and a fastened
servo box was enough for joint-mesh continuity to call that connected.
The check also never ran once the arm exceeded the BREP sweep budget,
so evaluate stayed ok. Rest-pose body continuity now runs anyway, only
the two mated bodies count, and contact far from the axis does not.
Printed axle bosses carry the elbow and wrist so those shells meet.

Signed-off-by: Cursor Agent <[email protected]>
Co-authored-by: Andrii Shylenko <[email protected]>
Signed-off-by: Andrii Shylenko <[email protected]>
…ce-borne carrier; rest gate falls back to BREP on open meshes

Signed-off-by: Andrii Shylenko <[email protected]>
…re, snout drillings); spool turns in the front bearing

Signed-off-by: Andrii Shylenko <[email protected]>
…accepts any param default

Signed-off-by: Andrii Shylenko <[email protected]>
…y ratchet; host the SO-100 arm loop check in its own file

Signed-off-by: Andrii Shylenko <[email protected]>
…-bored tilt axle, servo on its plate, tube socket)

Signed-off-by: Andrii Shylenko <[email protected]>
…; SO-100 negative fixture in its own process

Signed-off-by: Andrii Shylenko <[email protected]>
@w1ne
w1ne merged commit aa9e00a into develop Oct 13, 2026
16 checks passed
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.

2 participants