Skip to content

Add an optional build-time, sim-free gate to keep only the object layouts a robot can actually reach, using cuRobo IK (Part 2/3)#914

Merged
xyao-nv merged 24 commits into
mainfrom
xyao/feature/curobo_buildtime_simfree_validation
Jul 24, 2026
Merged

Add an optional build-time, sim-free gate to keep only the object layouts a robot can actually reach, using cuRobo IK (Part 2/3)#914
xyao-nv merged 24 commits into
mainfrom
xyao/feature/curobo_buildtime_simfree_validation

Conversation

@xyao-nv

@xyao-nv xyao-nv commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Today the solver only checks that objects fit geometrically, before placement event. This MR adds a second, optional check: a layout is stored only when it passes geometry and the robot can reach a top-down grasp at every movable object. The placement loop keeps re-sampling until every env has enough reachable layouts.

Detailed description

  • IK_reachability is registered to the validator registry and loaded if curobo deps exist when requested by enable_checks/required_checks by the env.yaml
  • A new SimApp-free IK solver that can be used to reconstruct each object's world pose from a layout, build one collision box per object, and batch-check top-down grasp IK feasibility. This validator only runs on geometry-valid candidates so the expensive IK check never wastes time on layouts that already failed.
  • Consolidated the cuRobo IK helpers. Added supportive utils funcs.

How to

Run in curobo image (-c). Include ik_reachability in enabled_checks

python isaaclab_arena/evaluation/policy_runner.py       --viz kit       --policy_type zero_action       --enable_cameras       --num_steps 100  --env_graph_spec_yaml isaaclab_arena_environments/robolab/tasks/butter_above_rasin.yaml

Logs will show how many layouts are rejected after validation upon each refill

[placement] Validated 50 candidate layout(s); passed per check: on_relation=48/50, next_to=50/50, not_next_to=50/50, face_to=50/50, no_overlap=41/50, ik_reachable=1/40
image
image

(Green dots: reachable voxels, red bbox: objects unreachable by eef)

Note

  • Different than Add Curobo-IK reachability post-validation check (Part 1/3) #837 where it's an isolated, post-validation, sim-live, env-coupled process. Here it refactors previous Curobo machinery and uses Curobo in a sim-free manner.
  • Instead of using live USD mesh for all its compute, it approximates the world by using cuboid with object's AABB. It's a simpler machinery compared with a throwaway env to avoid conflict from calling env.reset() terms.

TODO

  1. Apply reachability only among task-centric objects.
  2. Disable hand joint to check collision between world <> arms (Curobo.success)

Comment thread isaaclab_arena/environments/arena_env_builder.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder_cfg.py Outdated
Comment thread isaaclab_arena_curobo/curobo_ik_utils.py Outdated
@xyao-nv
xyao-nv force-pushed the xyao/feature/curobo_buildtime_simfree_validation branch from 3134be9 to 314de34 Compare July 15, 2026 22:14
@xyao-nv xyao-nv changed the title Xyao/feature/curobo buildtime simfree validation Add an optional build-time, sim-free gate to keep only the object layouts a robot can actually reach, using cuRobo IK (Part 2/3) Jul 15, 2026

@zhx06 zhx06 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Focused pass on the reachability-solver interface — i.e. how the IK gate validates the geometry-valid layouts. The plumbing (registry indirection, geometry-first short-circuit, reject-&-refill) is clean and keeps core vendor-agnostic. My main concern is that the current IK check is pose-residual only and does not yet enforce the collision world it goes to some trouble to build, so "IK reachable" doesn't actually validate the geometric/collision feasibility a grasp needs. Inline notes below.

Comment thread isaaclab_arena_curobo/curobo_frame_utils.py Outdated
Comment thread isaaclab_arena_curobo/curobo_frame_utils.py Outdated
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
Comment thread isaaclab_arena_curobo/curobo_ik_utils.py Outdated

@zhx06 zhx06 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up focused on the relation-solver side of the interface — where the gate actually plugs into PooledObjectPlacer. The predicate hook itself is a clean seam, but the placement of the call inside the refill loop has a real efficiency cost, and the Callable[..., bool] contract hides a mutation. Notes inline.

Comment thread isaaclab_arena/relations/pooled_object_placer.py Outdated
Comment thread isaaclab_arena/relations/pooled_object_placer.py
Comment thread isaaclab_arena/relations/object_placer_params.py Outdated
Comment thread isaaclab_arena/relations/pooled_object_placer.py Outdated

@zhx06 zhx06 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more fixable items on the core relation-solver side (the geometry path that feeds the gate), independent of cuRobo.

Comment thread isaaclab_arena/embodiments/embodiment_base.py Outdated
Comment thread isaaclab_arena/relations/reachability_validator_registry.py Outdated
Comment thread isaaclab_arena/relations/reachability_validator_registry.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder.py Outdated
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated

@alexmillane alexmillane left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this together. Great that it's working!

I've left a few comments. I think we need to investigate the class heirachy and see how we can build this into the solver such that's not passed in from the top level.

Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
Comment thread isaaclab_arena/cli/isaaclab_arena_cli.py Outdated
Comment thread isaaclab_arena/embodiments/embodiment_base.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder_cfg.py Outdated
Comment thread isaaclab_arena_curobo/curobo_frame_utils.py Outdated
Comment thread isaaclab_arena_curobo/curobo_ik_utils.py Outdated
Comment thread isaaclab_arena_curobo/curobo_ik_utils.py Outdated
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
Comment thread isaaclab_arena_curobo/curobo_ik_utils.py Outdated
@xyao-nv
xyao-nv force-pushed the xyao/feature/curobo_buildtime_simfree_validation branch from a4d6455 to 102eaa0 Compare July 21, 2026 00:53
@xyao-nv
xyao-nv changed the base branch from main to xyao/feature/build_time_validator July 21, 2026 00:54
@xyao-nv
xyao-nv force-pushed the xyao/feature/build_time_validator branch from 6abe142 to 79a991d Compare July 21, 2026 01:55
@xyao-nv
xyao-nv force-pushed the xyao/feature/curobo_buildtime_simfree_validation branch from 102eaa0 to efb689e Compare July 21, 2026 05:27
@xyao-nv
xyao-nv force-pushed the xyao/feature/build_time_validator branch from e4ef360 to 9794812 Compare July 21, 2026 14:37
@xyao-nv
xyao-nv changed the base branch from xyao/feature/build_time_validator to main July 21, 2026 15:48
@xyao-nv
xyao-nv force-pushed the xyao/feature/curobo_buildtime_simfree_validation branch from efb689e to c7a5fde Compare July 21, 2026 16:06
Comment thread isaaclab_arena/relations/object_placer_params.py
Comment thread isaaclab_arena/relations/object_placer_params.py Outdated
Comment thread isaaclab_arena_environments/robolab/scenes/butter_raisin_box.yaml
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
@xyao-nv
xyao-nv marked this pull request as ready for review July 22, 2026 04:44
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an optional build-time IK-reachability gate to the placement pool: before storing a candidate layout, a SimFreeIKSolver (cuRobo, no SimApp) checks that the robot can reach a top-down grasp at every movable object. Rejected candidates trigger a refill loop until every env accumulates enough reachable layouts.

  • Core validator path: ReachabilityValidator (gated, runs only on geometry-passing candidates) is injected via ObjectPlacerParams.extra_validators; object_placer.py gains a two-pass loop that runs non-gated checks first, then gated checks only on the surviving subset.
  • Refactored cuRobo helpers: frame-math utilities consolidated into curobo_frame_utils.py; SimFreeIKSolver and AABB-cuboid world-building extracted into curobo_ik_utils.py; ik_utils.py deleted.
  • Activation gap: arena_env_builder.py calls configure_reachability_validator unconditionally, causing the solver to be built and the check to run even for environments that never set ik_reachable in enabled_checks.

Confidence Score: 3/5

The gated-validator mechanics and sim-free IK solver are well-implemented, but the activation path wires the check for all environments with a cuRobo-registered embodiment rather than only those that request it.

configure_reachability_validator builds the GPU solver and installs the validator regardless of enabled_checks. Since build_validators includes all extra_validators when enabled_checks is None, this silently enables IK reachability for environments that never opted in — potentially causing refill loops or very slow pool fills as a behavioral regression.

isaaclab_arena_curobo/ik_reachability_validator.py and isaaclab_arena/environments/arena_env_builder.py need the enabled_checks guard before the solver is built.

Important Files Changed

Filename Overview
isaaclab_arena_curobo/ik_reachability_validator.py New build-time IK reachability validator; configure_reachability_validator installs the solver without checking enabled_checks and catches AssertionError too broadly.
isaaclab_arena/environments/arena_env_builder.py Calls configure_reachability_validator unconditionally; comment omits that enabled_checks is not checked, causing the solver to build for all cuRobo-registered embodiments.
isaaclab_arena_curobo/curobo_frame_utils.py New shared frame/IK helpers; assert used as guard for require_collision_free instead of raise NotImplementedError, making dead code reachable under Python -O.
isaaclab_arena_curobo/curobo_ik_utils.py New SimFreeIKSolver and collision-cuboid helpers; clean implementation, solver construction and world-update logic look correct.
isaaclab_arena/relations/object_placer.py Added gated-validator two-pass logic; non-gated checks run first, then gated validators only process candidates that pass required non-gated checks. Logic is correct.
isaaclab_arena/relations/placement_validators.py Added gated ClassVar and enabled_by_default hook; extra_validators bypass enabled_by_default in the default case, contributing to the P1 opt-in issue.
isaaclab_arena/relations/object_placer_params.py Added ReachabilityConfig dataclass and extra_validators/reachability_config fields to ObjectPlacerParams; clean addition.
isaaclab_arena_curobo/curobo_planner_utils.py Refactored to use shared curobo_frame_utils; minor per-iteration recomputation of R_R_W in sync loop, but logic is correct.
isaaclab_arena/embodiments/embodiment_base.py Added get_base_pose() with clear priority chain (initial_pose to init_state to identity); straightforward and well-guarded.
isaaclab_arena/relations/pooled_object_placer.py Simplified pool-fill logic by removing a redundant total_valid counter; no algorithmic change.
isaaclab_arena/tests/test_placement_events.py Added integration tests for gated validator refill behavior and reject-all-raises path; good coverage.
isaaclab_arena_curobo/tests/test_ik_reachability_validator.py New unit tests for make_ik_reachability_validator with cuRobo mocked out; covers accept and reject paths.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[ArenaEnvBuilder._make_placement_params] --> B[configure_reachability_validator]
    B -->|cuRobo unavailable| C[no-op return False]
    B -->|cuRobo available + embodiment has config| D[build_reachability_validator]
    D --> E[SimFreeIKSolver created on GPU]
    E --> F[ReachabilityValidator wraps predicate]
    F --> G[appended to extra_validators]
    G --> H[build_validators]
    H -->|enabled_checks=None| I[ALL extra_validators included]
    H -->|enabled_checks set without ik_reachable| J[filtered out but solver already built]
    H -->|enabled_checks includes ik_reachable| K[validator included]
    I --> L[ObjectPlacer._validate_candidates]
    K --> L
    L --> M[Pass 1 non-gated validators]
    M --> N[Pass 2 gated ReachabilityValidator on geometry-passing subset]
    N -->|all pass| O[layout stored]
    N -->|any fail| P[layout rejected refill loop]
Loading

Comments Outside Diff (1)

  1. isaaclab_arena_curobo/ik_reachability_validator.py, line 1287-1305 (link)

    P1 IK reachability validator installed regardless of enabled_checks

    configure_reachability_validator never checks placer_params.enabled_checks, so it builds SimFreeIKSolver (CUDA memory, URDF loading, cuRobo warmup) and appends the validator to extra_validators unconditionally. In build_validators, the default case (enabled_checks=None) runs all extra_validators, so any environment whose embodiment has a registered cuRobo config silently gets IK reachability enabled — a breaking change for environments that never opted in. The PR description says the check is "loaded if curobo deps exist when requested by enable_checks/required_checks by the env.yaml", but the implementation is opt-out rather than opt-in. Add an early return before build_reachability_validator is called.

Reviews (1): Last reviewed commit: "remove print" | Re-trigger Greptile

Comment thread isaaclab_arena_curobo/curobo_frame_utils.py Outdated
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder.py Outdated
Comment thread isaaclab_arena_environments/robolab/scenes/butter_raisin_box.yaml
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
Comment thread isaaclab_arena/relations/object_placer.py
Comment thread isaaclab_arena/embodiments/embodiment_base.py Outdated

@alexmillane alexmillane left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review round 2.

Looking good. I have quite a few comments and questions.

Happy to have another look when you're ready.

Comment thread isaaclab_arena/embodiments/embodiment_base.py Outdated
Comment thread isaaclab_arena/embodiments/embodiment_base.py Outdated
Comment thread isaaclab_arena/embodiments/embodiment_base.py Outdated
Comment thread isaaclab_arena/embodiments/embodiment_base.py Outdated
Comment thread isaaclab_arena/environments/arena_env_builder.py Outdated
Comment thread isaaclab_arena_curobo/curobo_frame_utils.py Outdated
Comment thread isaaclab_arena_curobo/curobo_frame_utils.py Outdated
Comment thread isaaclab_arena_curobo/curobo_frame_utils.py Outdated
Comment thread isaaclab_arena_curobo/curobo_ik_utils.py Outdated
Comment thread isaaclab_arena_curobo/curobo_ik_utils.py Outdated

@alexmillane alexmillane left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for cleaning this all up. it's looking much better. clean!

I had a couple of questions around the structure of the validator, but you're clear to merge.

Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated
Comment thread isaaclab_arena_curobo/ik_reachability_validator.py Outdated

@qianl-nv qianl-nv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for multi rounds of updates. LGTM!

xyao-nv added 23 commits July 23, 2026 17:06
- Add curobo_frame_utils/curobo_ik_utils and standalone_ik_layout_validator: a
  build-time, SimApp-free top-down-grasp IK reachability check over pooled layouts.
- Replace ik_utils with the standalone/live IK split; refresh curobo_planner_utils
  and placement_pool_ik_validation accordingly.
- Add EmbodimentBase.get_base_pose, utils/device.resolve_cuda_device, the
  --validate_reachability CLI flag, and ArenaEnvBuilderCfg fields.
- Add reachability_validator_registry.resolve_reachability_validator to discover an
  extension's make_reachability_validator entry point, keeping cuRobo out of core.

Signed-off-by: Xinjie Yao <xyao@nvidia.com>
- Add ReachabilityValidator (check IK_REACHABLE) wrapping the extension-supplied
  per-layout predicate on ObjectPlacerParams.reachability_validator, so reachability
  flows through the same registry, check-name, and required_checks machinery as the
  geometry validators instead of a bespoke pool-level gate.
- Make the validator opt-in (enabled_by_default only once a predicate is provisioned)
  and gated: object_placer runs gated validators only on candidates that already pass
  the required non-gated checks, so cuRobo IK never runs on geometry-rejected layouts.
- Because IK_REACHABLE is a required check, PlacementResult.success reflects
  reachability and the existing pool reject-and-refill needs no special-casing.
- Wire --validate_reachability through ArenaEnvBuilder to provision the predicate and
  enable/require the check; port the reachability pool tests to the new contract.

Signed-off-by: Xinjie Yao <xyao@nvidia.com>
Declare a task_constraint (pick_object + optional place_destination) in the
env graph YAML and thread its target object ids through ObjectPlacerParams so
the build-time IK reachability gate checks only the task-relevant objects
instead of every movable object.

- New TaskConstraintSpec with target_object_ids() extractor (pick always;
  place destination only when it names an object)
- ArenaEnvGraphSpec validates the constraint's ids against known assets
- ReachabilityValidator focuses on target_object_ids, falling back to all
  movable objects when unset
- Example task_constraint added to banana_on_plate.yaml

Signed-off-by: Xinjie Yao <xyao@nvidia.com>
@xyao-nv
xyao-nv force-pushed the xyao/feature/curobo_buildtime_simfree_validation branch from fa1ec61 to a03d53f Compare July 24, 2026 00:07
@xyao-nv
xyao-nv merged commit 525ca4f into main Jul 24, 2026
10 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.

5 participants