✨ Selectable motion-planning backend (OMPL / cuRobo) - #11
Open
correll wants to merge 5 commits into
Open
Conversation
Add a backend factory behind PlannerClient so the joint-space planner can be OMPL (CPU, default) or cuRobo (CUDA GPU), selected by planner.backend in the controller config. 'auto' prefers cuRobo when a GPU is present and falls back to OMPL otherwise, so the headless CPU sim (Mac/Colima) keeps working with no config changes. - planner_types.py: ompl-free PlannerConfig / PlanResult (adds backend + curobo fields), re-exported from reduced_joint_planner for backward compatibility - backend.py: create_joint_planner() + curobo_available(); explicit 'curobo' fails loudly without a GPU, 'auto' degrades to OMPL and never breaks planning - curobo_planner.py: CuroboJointPlanner matching the plan() -> PlanResult contract; endpoint validation, active-mask projection and final revalidation mirror the OMPL backend, and all CUDA imports are lazy so the module stays importable on CPU-only hosts (cuRobo API paths still need GPU validation) - wire the factory into the planner subprocess and thread backend/curobo config through _load_planner_config + debug.yaml - test_planner_backend.py: selection/fallback logic and the GPU-free cuRobo contract Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Draft the cuRobo robot_cfg the CuroboJointPlanner needs, derived from the existing collision assets so both planning backends share identical geometry. - config/curobo/h1_2_handless_curobo.yml: 24 collision spheres over 16 links (exact centers/radii from h1_2_handless_sphere.urdf), 39 self-collision ignore pairs from the SRDF, legs+torso locked, cspace = the 14 arm joints with home (zeros) as the retract config - config/curobo/gen_curobo_cfg.py: reproducible generator (pure stdlib) so the config can be regenerated when the sphere URDF/SRDF change - curobo_planner: inject an absolute urdf_path / asset_root_path from planner.curobo so the committed YAML stays host-agnostic - debug.yaml: point the commented curobo example at the generated file Not yet validated on a GPU (no CUDA here); the cspace-vs-lock_joints convention is the most likely first-load adjustment (noted inline). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Standalone script that loads h1_2_handless_curobo.yml into cuRobo MotionGen and plans one joint-space motion (home -> small arm pose). Run on a GPU host before wiring the backend in, to isolate config-schema issues (cspace/lock convention, sphere format, URDF resolution). Exits 0/1/2 for pass/plan-fail/no-cuRobo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TonyZYT2000
force-pushed
the
feature/curobo
branch
from
July 15, 2026 22:24
eeab994 to
a2201f0
Compare
TonyZYT2000
force-pushed
the
feature/curobo
branch
from
July 16, 2026 01:27
cdf38aa to
1ebc7ff
Compare
github-actions
Bot
force-pushed
the
main
branch
from
August 14, 2026 03:57
493b533 to
3508df0
Compare
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.
Summary
Makes the arm joint-space motion planner swappable between OMPL (current, CPU) and cuRobo (CUDA GPU), selected by one config key. Adds a cuRobo backend, a robot config generated from the existing collision assets, and a GPU smoke test — without changing anything downstream of the planner.
Motivation: cuRobo gives GPU-accelerated, collision-aware planning (and a path to environment-aware reaching), but it requires a CUDA GPU and so cannot run in the headless CPU sim (Mac/Colima). This PR keeps OMPL as the default with automatic fallback, so the sim keeps working untouched while cuRobo becomes available on GPU hosts.
The seam
Everything downstream consumes one contract —
PlannerClient.plan_configuration(...) → PlanResult(anN×14reduced-joint waypoint array streamed byexecute_path). A new factory picks the backend behind that contract, soframe_task_server,dual_arm_server, andexecute_pathare unchanged.Changes
Backend seam
core/planner/planner_types.py(new) — ompl-freePlannerConfig/PlanResult(addsbackend+curobofields), re-exported fromreduced_joint_plannerfor backward compat. Lets the cuRobo backend be imported/tested with neither ompl nor CUDA present.core/planner/backend.py(new) —create_joint_planner()+curobo_available(); the selection/fallback logic above.core/planner/curobo_planner.py(new) —CuroboJointPlanner, matchingplan(start, goal, active_mask) → PlanResultexactly. Endpoint validation, active-mask projection (pin the untasked arm), and final revalidation mirror OMPL's guarantees (soexecute_path's re-checks always pass). All cuRobo/CUDA imports are lazy; supports injecting an absoluteurdf_pathso the committed YAML stays host-agnostic.planner_process.py); threadedbackend/curoboconfig through_load_planner_config+debug.yaml.cuRobo robot config —
config/curobo/h1_2_handless_curobo.yml(new), generated fromh1_2_handless_sphere.urdf+ its SRDF so both backends share identical self-collision geometry:collision_spheresself_collision_ignoredisable_collisions(sphere-bearing links) + kinematic-ancestor closurelock_jointsBODY_JOINTS − ENABLED_JOINTScspaceretract_config=home(zeros)ENABLED_JOINTS,NAMED_CONFIGS['home']base_link/ee_linkpelvis/left_wrist_yaw_link, both wrists + grasp frames trackedconfig/curobo/gen_curobo_cfg.py(new) — pure-stdlib, reproducible generator; re-run when the sphere URDF/SRDF change.config/curobo/smoke_test_curobo.py(new) — loads the YAML into cuRoboMotionGenand plans one motion; run first on a GPU host to shake out schema issues. Exits 0/1/2 for pass / plan-fail / no-cuRobo.Tests —
test/test_planner_backend.py(new): selection/fallback branches + the GPU-free cuRobo contract.Key design decisions
base_link = pelvis(nottorso_link) so pelvis/torso spheres stay in the tree for arm-vs-body avoidance; this pullstorso_jointinto the chain, hence it's inlock_joints.lock_jointsare static at load, so if the torso is rotated at runtime the collision model drifts. Flagged inline; the clean fix later is syncing the locked value per-plan or adding torso tocspace.cspace= 14 movable joints, rest locked — the convention most likely to need a first-GPU-load tweak (some cuRobo versions want all 27 joints enumerated withlock_jointssubtracting). Noted inline; regenerating for that layout is trivial.Verified
__init__s): 13/13 checks pass (every backend branch + cuRobo endpoint-validation, missing-robot_cfg, active-mask projection, column reorder).h1_2_handless_curobo.ymlparses as valid YAML; shapes cross-checked (14/14 cspace,collision_sphereskeys ==collision_link_names, 13 locked joints).NOT verified (needs a GPU)
No CUDA in this environment. The sphere geometry, ignore pairs, and joint mapping are exact, but cuRobo schema acceptance and the
MotionGenplanning path are unvalidated.curobo_planner.pyandsmoke_test_curobo.pyfollow cuRobo's documentedMotionGenAPI and usegetattrfallbacks where accessor names vary by version.Enabling cuRobo on a GPU host
python3 config/curobo/smoke_test_curobo.py --urdf /abs/path/h1_2_handless_sphere.urdf→ expect[smoke] PASSandactive DOF = 14. Fix any schema mismatch here.autokeeps OMPL as the fallback, so the same config is safe on the CPU sim.Test plan
pytest test/test_planner_backend.py(+ existingtest_reduced_joint_planner.pyunaffected).backend: autoon Mac/Colima still uses OMPL;rob_poseplanning unchanged.backend: curoboplans a named-config move end-to-end.🤖 Generated with Claude Code