Skip to content

feat(manipulation): support unbounded planar-base motion - #3844

Open
TomCC7 wants to merge 9 commits into
feat/r1pro-mobile-manipfrom
cc/feat/unbounded-planar-base
Open

feat(manipulation): support unbounded planar-base motion#3844
TomCC7 wants to merge 9 commits into
feat/r1pro-mobile-manipfrom
cc/feat/unbounded-planar-base

Conversation

@TomCC7

@TomCC7 TomCC7 commented Aug 31, 2026

Copy link
Copy Markdown
Member

Contribution path

Problem

R1 Pro planning previously treated planar-base coordinates as bounded scalar joints. That imposed an artificial workspace, made yaw discontinuous at ±π, and spread joint-type policy across backend adapters.

Viser could also rebuild joint controls concurrently when planning groups were toggled quickly, causing duplicate handle removal and dictionary changed size during iteration.

Design

Canonical joint space

prepare_robot_model() now compiles the final materialized URDF once into a PreparedRobotModel. Its ordered JointSpace assigns one topology to every controlled coordinate:

URDF coordinate Canonical topology Planning behavior
Bounded revolute or prismatic INTERVAL Uses physical lower and upper limits
Unbounded prismatic LINE Uses a finite request-local sampling domain
Continuous revolute CIRCLE Uses shortest-angle deltas and wrapped sampling

Worlds, IK, planners, trajectory generation, and Viser consume this prepared model. RobotModelConfig no longer duplicates joint-limit arrays or fallback velocity and acceleration values. Robot assets must supply positive finite velocity and acceleration limits before preparation.

JointCoordinate is a frozen Pydantic dataclass that validates its mechanism, topology, bounds, and motion limits once during model preparation. Planner-hot-path configurations and tangents remain lightweight standard dataclasses.

Planning and backend adaptation

  • Selected-joint RRT builds finite domains from the request. Unbounded dimensions retry with 1, 2, 4, 8, then 16 metre margins while sharing one deadline and node budget.
  • Distance, interpolation, collision subdivision, simplification, and path length use velocity-scaled shortest circular deltas.
  • Circular paths are lifted before trajectory generation, so crossing ±π produces a short continuous trajectory.
  • Pink translates canonical LINE and CIRCLE coordinates to Pinocchio's native representation and preserves locked joints.
  • Drake keeps native scalar coordinates but reads limits and planning domains from the prepared joint space.
  • RoboPlan uses its native planner for interval-only selections. Selections containing LINE or CIRCLE coordinates use the shared dimOS RRT against RoboPlan collision and kinematics queries.
  • RoboPlan TOPP-RA expands each continuous scalar to its cosine/sine representation, then collapses and lifts the generated positions back into the canonical scalar path. Unbounded prismatic coordinates pass through unchanged.

Whole-body IK chooses the endpoint across the selected arm, torso, and base joints. Path simplification only removes collision-free intermediate waypoints; it does not redistribute endpoint motion between the arm and base. Selecting only an arm locks the unselected torso, other arm, and base.

R1 Pro and Viser

  • R1 Pro exposes base/x and base/y as unbounded translations and base/yaw as a continuous angle.
  • R1 Pro uses the shared planner and the normal RoboPlan TOPP-RA default.
  • Viser renders line coordinates as unbounded number inputs and circle coordinates as wrapped sliders.
  • Group-selection and joint-control rebuilds are serialized. The handle registry is cleared before handles are removed, making concurrent rebuilds idempotent.

Base execution remains disabled until R1 Pro has a feedback-controlled base trajectory executor. Preview and planning work, but execution rejects trajectories that require the missing base-controller capability. Cartesian waypoint planning remains interval-only.

Verification

.venv/bin/pytest dimos/manipulation -m 'not (self_hosted or mujoco or self_hosted_large)'

Result: 465 passed, 25 deselected.

Additional checks completed:

  • RoboPlan TOPP-RA adapter tests: 11 passed, including a real unbounded planar-base trajectory.
  • RoboPlan self-hosted Cartesian integration tests: 2 passed.
  • R1 Pro self-hosted model and IK tests: 2 passed.
  • Actual R1 Pro TOPP-RA smoke test: 652 trajectory points from (0, 0, 3.04) to (6, -6, 3.24) across the short yaw boundary.
  • Ruff, targeted mypy, affected pre-commit hooks, and documentation links passed.

Manual R1 Pro/Viser validation has not been run in this environment.

Manual R1 Pro test

uv sync --extra all
dimos run r1pro-planner-coordinator

In the Viser URL printed by the blueprint:

  1. Select moving_base; plan to base/x = 6.0 and base/y = -6.0.
  2. Plan from yaw near 3.04 to -3.04; confirm the preview takes the short crossing.
  3. Select left_arm, torso, and moving_base; move the left TCP target and plan a whole-body path.
  4. Repeat with only left_arm; confirm the torso, right arm, and base remain fixed.
  5. Add an obstacle and confirm RRT expands its request-local domain to find a detour.
  6. Rapidly toggle planning groups; confirm no duplicate-removal warning or dictionary mutation exception occurs.
  7. Preview a base plan, then execute it; confirm execution reports the missing base-controller capability.

The detailed design and manual procedure are in docs/capabilities/manipulation/unbounded-planar-base.md.

AI assistance

OpenAI Codex implemented and tested the change under human direction.

Checklist

  • I have read and approved the CLA.

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.88388% with 161 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
dimos/manipulation/visualization/viser/gui.py 42.10% 50 Missing and 5 partials ⚠️
dimos/manipulation/planning/spec/joint_space.py 82.28% 17 Missing and 14 partials ⚠️
...planning/world/test_drake_world_planning_groups.py 11.11% 16 Missing ⚠️
...manipulation/planning/planners/roboplan_planner.py 45.00% 6 Missing and 5 partials ⚠️
...imos/manipulation/planning/planners/rrt_planner.py 81.66% 7 Missing and 4 partials ⚠️
dimos/manipulation/planning/world/drake_world.py 50.00% 6 Missing ⚠️
...os/manipulation/planning/kinematics/jacobian_ik.py 16.66% 5 Missing ⚠️
dimos/manipulation/planning/spec/validation.py 89.47% 2 Missing and 2 partials ⚠️
dimos/robot/assets/model.py 86.20% 2 Missing and 2 partials ⚠️
...mos/manipulation/planning/monitor/world_monitor.py 75.00% 1 Missing and 2 partials ⚠️
... and 8 more
@@                     Coverage Diff                     @@
##           feat/r1pro-mobile-manip    #3844      +/-   ##
===========================================================
+ Coverage                    77.93%   78.01%   +0.08%     
===========================================================
  Files                         1332     1334       +2     
  Lines                       127227   127828     +601     
  Branches                     11050    11106      +56     
===========================================================
+ Hits                         99151    99724     +573     
+ Misses                       24980    24920      -60     
- Partials                      3096     3184      +88     
Flag Coverage Δ
OS-ubuntu-24.04-arm 74.64% <74.57%> (+0.04%) ⬆️
OS-ubuntu-latest 75.23% <79.53%> (+0.10%) ⬆️
Py-3.10 75.22% <79.53%> (?)
Py-3.11 75.22% <79.53%> (+0.09%) ⬆️
Py-3.12 75.22% <79.53%> (+0.10%) ⬆️
Py-3.13 75.22% <79.53%> (+0.10%) ⬆️
Py-3.14 75.22% <79.53%> (+0.63%) ⬆️
Py-3.14t 75.22% <79.53%> (?)
SelfHosted-Large 30.21% <27.82%> (+0.01%) ⬆️
SelfHosted-Linux 34.84% <43.14%> (+0.19%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
dimos/manipulation/manipulation_module.py 68.42% <ø> (-1.92%) ⬇️
dimos/manipulation/planning/factory.py 74.00% <100.00%> (+5.31%) ⬆️
...kinematics/test_drake_optimization_ik_selection.py 98.54% <100.00%> (+0.01%) ⬆️
.../planning/kinematics/test_jacobian_ik_selection.py 94.82% <100.00%> (+0.09%) ⬆️
...s/manipulation/planning/kinematics/test_pink_ik.py 99.86% <100.00%> (-0.14%) ⬇️
dimos/manipulation/planning/kinematics/utils.py 74.64% <100.00%> (ø)
...anipulation/planning/monitor/test_world_monitor.py 94.00% <100.00%> (+0.20%) ⬆️
dimos/manipulation/planning/spec/config.py 86.20% <ø> (-2.03%) ⬇️
dimos/manipulation/planning/spec/models.py 100.00% <100.00%> (ø)
dimos/manipulation/planning/spec/protocols.py 100.00% <100.00%> (ø)
... and 49 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread dimos/robot/manipulators/r1pro/blueprints/basic.py Outdated
Comment thread dimos/manipulation/planning/spec/joint_space.py Outdated
@TomCC7
TomCC7 force-pushed the cc/feat/unbounded-planar-base branch from c73b412 to cf1fd29 Compare September 1, 2026 16:53
@TomCC7
TomCC7 marked this pull request as ready for review September 1, 2026 18:40
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This change extends joint-space planning and related adapters to support unbounded planar translation and continuous yaw. Validation reproduced an RRT accounting error in which LINE-coordinate connection expansions are omitted from the shared iteration count, allowing failed searches to perform substantially more collision checking than requested. This should be corrected before merge.

Confidence Score: 4/5

Not safe to merge until LINE-coordinate connection expansions are charged to the planner's shared iteration accounting.

A deterministic runtime reproduction exercised the affected retry path, observed the excess planning work, and confirmed that accounting for connection expansions constrains the same scenario.

Files Needing Attention: dimos/manipulation/planning/planners/rrt_planner.py

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a finding-comment proof for a posted P1 finding.
  • T-Rex produced a second finding-comment proof for another posted P1 finding.
  • T-Rex ran the budget harness in original and comparison modes and found that the remaining-iterations calculation does not reflect the true budget, effectively allowing about 2.5 times the intended maximum.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (1)

  1. General comment

    P1 LINE-domain RRT retries do not charge connection expansions against max_iterations

    • Bug
      • With a LINE coordinate, each expanding-domain attempt is capped locally at 1,000 nodes. The connection phase can consume up to 997 nodes per attempt, but five forced nonconnecting attempts performed 4,990 extensions under max_iterations=2000 and the result claimed only 5 iterations.
    • Cause
      • At dimos/manipulation/planning/planners/rrt_planner.py:296-304, connected_nodes is added to local nodes but not global iterations; only the preceding selected-tree extension increments global accounting at line 293.
    • Fix
      • After nodes += connected_nodes at line 304, add iterations += connected_nodes (or otherwise use one shared budget counter for both extend and connect operations). Add a focused regression test that forces nonconnecting LINE-domain attempts and asserts total extensions/collision checks do not exceed the global iteration budget.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "fix(manipulation): adapt TOPP-RA continu..." | Re-trigger Greptile

Comment thread dimos/manipulation/planning/planners/rrt_planner.py
@TomCC7
TomCC7 force-pushed the cc/feat/unbounded-planar-base branch from c11007f to 2f8b373 Compare September 1, 2026 22:51
TomCC7 and others added 9 commits September 1, 2026 16:12
Represent mobile-base x/y as unbounded coordinates and yaw as periodic throughout model validation, Pink IK, world backends, selected-joint RRT, path lifting, and trajectory parameterization.

Use request-local expanding sampling domains for obstacle detours, wire the behavior into the R1 Pro blueprint and Viser controls, and serialize Viser joint-control rebuilds to prevent concurrent handle removal failures.

Tests: .venv/bin/pytest -q -p no:rerunfailures dimos/manipulation/planning/kinematics/test_pink_ik.py dimos/manipulation/planning/planners/test_rrt_planner_selection.py dimos/manipulation/planning/spec/test_model_validation.py dimos/manipulation/planning/world/test_drake_world_planning_groups.py dimos/manipulation/test_plan_execution.py dimos/manipulation/visualization/viser/test_gui.py dimos/robot/assets/test_model.py dimos/robot/manipulators/r1pro/test_config.py
Count connect-phase node expansions alongside extend attempts so LINE-domain retries cannot exceed max_iterations. Update RoboPlan integration tests to prepare models before loading them.
@TomCC7
TomCC7 force-pushed the cc/feat/unbounded-planar-base branch from 2f8b373 to 26c7cdd Compare September 1, 2026 23:12
@github-actions github-actions Bot added the ready-to-merge Required CI checks have passed on this PR label Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Required CI checks have passed on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant