Use manipulability to diversify trajectory augmentation - #643
Open
Yuan-Xinyi wants to merge 2 commits into
Open
Yuan-Xinyi wants to merge 2 commits into
Yuan-Xinyi wants to merge 2 commits into
Conversation
Add manipulability-aware candidate generation and selection to embodichain/lab/sim/motion/expansion/, so collected expert trajectories cover a wider range of arm postures instead of clustering around the few comfortable configurations a uniform residual sampler tends to produce. New expansion/manipulability.py reuses the shared Yoshikawa helpers in embodichain.compute.kinematics: - describe_manipulability() scores caller-supplied Jacobians and reports per-sample values plus the minimum inside each trajectory phase. Scoring runs in float64 because a float32 determinant underflows to zero for small-scale Jacobians and reports a healthy posture as singular. - ManipulabilityBands groups scores into ordered ranges expressed as ratios against a per-case reference value, so one set of boundaries works across robots and tasks. - manipulability_guided_residual() draws several joint_residual proposals from one local generator and keeps the one closest to a requested range. CoverageIndex gains an optional per-range quota: once a range is full, new rollouts in it are rejected even when their geometry is new, so a single well-conditioned posture cannot consume the whole collection budget. GenerationSession classifies a rollout from the measured "manipulability" observation recorded during execution, never from a planned estimate, and reports the per-range commit counts in snapshot(). The feature is opt-in through augmentation.factors.manipulability and is disabled by default, so existing jobs behave exactly as before. Jacobians are supplied by the caller, keeping the package free of robot, solver, and simulation imports. Manipulability only ranks postures; path, dynamic, and task validation remain separate and unchanged. Fixes #634 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
matafela
reviewed
Sep 17, 2026
A reference bottleneck describes one reference trajectory, not the scene, so two initial states of the same case may carry different values. The session stored it as a shared case condition and rejected the second registration, and both the band map and `_measured_band` were keyed by scene case alone, so a second reference would have been ignored anyway. Resolve the normalizer by `(scene_case_id, initial_state_id)` and drop the reference from the cross-initial-state condition check. Re-registering one initial state with a changed reference still fails, and coverage quotas stay shared by scene case. Also make the float32 underflow regression test reject the broken implementation: a 3x3 Jacobian scaled by 1e-4 yields a determinant near 1e-24 that float32 represents fine, and `pytest.approx(1e-12)` accepted an incorrect zero through its default absolute tolerance. Score a 6x6 Jacobian instead, whose 1e-48 determinant does underflow, and compare with a purely relative tolerance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Expert trajectory collection currently samples joint residuals uniformly around one reference path, so the accepted rollouts tend to cluster around the same few comfortable arm postures. This change lets manipulability guide both how candidates are proposed and which ones are kept, so a run covers a wider range of postures, including tighter ones that still complete the task.
The work stays inside
embodichain/lab/sim/motion/expansion/and reuses the existing Yoshikawa helpers inembodichain.compute.kinematics; no new numerical algorithm is introduced.New module
expansion/manipulability.pydescribe_manipulability()scores caller-supplied Jacobians and reports the per-sample values together with the lowest value inside each trajectory phase. Scoring runs in float64: the determinant of a float32 Jacobian underflows to exactly zero at small scales and would report a healthy posture as singular.ManipulabilityBandsgroups scores into ordered ranges expressed as ratios against a per-case reference value, usually the reference trajectory's lowest score. One set of boundaries therefore transfers across robots and tasks.manipulability_guided_residual()draws severaljoint_residualproposals from one local generator, scores each, and keeps the first one that lands in the requested range, falling back to the nearest reachable range. Proposals that leave the joint limits are skipped; if every proposal fails, the last error is raised rather than swallowed.Selection side
CoverageIndexgains an optional per-range quota. Once a range is full, further rollouts in it are rejected even when their measured geometry is new, so one well-conditioned posture cannot consume the whole collection budget while tighter postures still have room.GenerationSessionclassifies each rollout from themanipulabilityobservation measured during execution, never from a planned estimate, and reports per-range commit counts insnapshot().Compatibility
Everything is opt-in through
augmentation.factors.manipulability, which is disabled by default. Existing jobs decode, validate, and run exactly as before;register_case()accepts a reference value only when the factor is enabled, andCoverageIndexkeeps its current behaviour when no quota is configured. Jacobians are supplied by the caller, so the package still imports no robot, solver, or simulation code. Manipulability only ranks postures: path, dynamic, and task validation are unchanged and remain the sole source of feasibility evidence.Not included: a coverage or downstream-training comparison. Measuring the benefit needs real scene collection plus policy training, which is outside this algorithm package; it is a reasonable follow-up once a host integration adopts the option.
No new dependencies.
Fixes #634
Type of change
Validation
python -m pytest tests/sim/motion/expansion tests/compute/test_manipulability.py— 214 passed. 29 of them are new cases intests/sim/motion/expansion/test_manipulability.py, plus added cases for the range quota intest_coverage.py, the new configuration fields intest_cfg.py, and the session's use of measured evidence intest_session.py.black .with Black 26.3.1: 1050 files unchanged.python docs/scripts/check_api_docs.py: 2085/2085 exports documented.context.py check: agent context map ok.Checklist
black .command to format the code base.python docs/scripts/check_api_docs.py).🤖 Generated with Claude Code