agentsclimarketplace

Grasping with planner

Skill graph-robots/open-robot-skills/skills/grasping-with-planner

Top-down grasping via a fast axis-locked linear descend with a collision-aware cuRobo fallback. A single `grasp_descend_linear` node rises, translates over the target, and descends straight down (Z-locked, orientation held) onto the object; if the straight-line solve is infeasible (far-edge reach, no IK for the fixed wrist) it falls back to the cuRobo planner over the candidate fan. Use when the curobo tool bundle is installed and a perceived object (OBB) must be grasped — the default grasping skill whenever cuRobo is deployed, in clean and cluttered scenes alike.From its SKILL.md

Install
npx -y skills add graph-robots/open-robot-skills --skill grasping-with-planner

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • runs commandsInstructs the agent to run 2 commands, including `export CUDA_HOME=/usr/local/cuda` and 1 more.

SKILL.md

10.7 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it

grasping-with-planner

Top-down grasping with a fast axis-locked linear descend and a collision-aware cuRobo fallback. The primary path rises to a hover height, translates over the target while rotating to the grasp yaw, and descends straight down (Z-only, orientation locked) onto the object — which, unlike a goalset planner, happily grips a flat object by simply lowering onto it. If the straight-line solve is infeasible, the same node hands off to the cuRobo planner, which builds a per-observation collision world and searches the whole candidate fan for a reachable, collision-free wrist. This is the grocery_packing grasp motion, distilled to the general single-object case.

Install

This skill depends on the curobo tool bundle (curobo.plan_directed_linear, curobo.plan_to_grasp_poses). cuRobo JIT-compiles CUDA extensions at install time — build isolation must be off and CUDA_HOME must point at a toolkit matching your torch build:

export CUDA_HOME=/usr/local/cuda
uv sync --extra curobo   # (pip: pip install -e "open-robot-skills[curobo]" --no-build-isolation)

See tools/curobo/SKILL.md for the full recipe and gotchas.

When to use

  • Default grasping skill whenever curobo is deployed — clean or cluttered.
  • Flat / low-profile objects (a butter box, cream cheese) where a goalset planner struggles but a straight lower-on-top succeeds.

When NOT to use

  • curobo not deployed. Use grasping-direct-ik instead.
  • The graspable region is NOT the OBB centroid — bowl rim, mug / moka-pot / frying-pan handle, or any off-center grasp. The OBB top-down candidates from geometry.top_down_grasp_candidates are centered on the OBB XY, so they slip on hollow centers and miss handles. Use grasping-short-axis for elongated handles, where the centroid is graspable but orientation is what matters.

Recommended subgraph state flow

6 states, in order:

open → compute_grasp → goto_grasp → observe → close → grasped

(grasped is the success-marker noop from sg.add_exit("grasped"), with an edge to END.)

State details:

  1. opentype: tool, tool: "robot.open_gripper", inputs: { settle_steps: 40 }.

  2. compute_grasptype: tool, tool: "geometry.top_down_grasp_candidates", inputs: { obb: Ref("in.target_obb") }. Returns candidates: {poses: list[Se3Pose]} — a yaw fan of top-down grasps.

  3. goto_grasptype: script, file scripts/<sg>/grasp_descend_linear.py from this bundle's canonical_scripts. Inputs: grasp_pose = Ref("compute_grasp.candidates.poses.0"), candidate_poses = Ref("compute_grasp.candidates.poses"), target_obb = Ref("in.target_obb"), hover_z = 0.2. Rises to hover_z, translates over the target at the grasp yaw, then Z-locked linear-descends onto it (shallow grip near the perceived top, floored a hair above the object base so the fingers never ram the table). On an infeasible cartesian solve it falls back to curobo.plan_to_grasp_poses over candidate_poses.

  4. observetype: tool, tool: "robot.get_observation", inputs: {}. Captures the arm state AT the grasp (post-descend, pre-close) so ee_pose_at_grasp reflects the real TCP pose the object was gripped at.

  5. closetype: tool, tool: "robot.close_gripper", inputs: { settle_steps: 60 }. Edge directly from close to the grasped success marker; the subgraph's on_error: "failed" catches any raise from goto_grasp (both paths failed). Whether the gripper actually closed on the object is checked by the target_held postcondition checkpoint (see ## Checkpoints), NOT by a re-check-and-raise node (none such exists).

    The subgraph publishes two cross-subgraph outputs:

    • ee_pose_at_grasp — the live TCP pose captured at the observe step (which sits between the descend and close). Downstream transporting-objects uses it to compute a drop height that accounts for the panda hand-to-tcp offset and the held object's geometry.
    • grasp_pose — the computed grasp pose emitted by compute_grasp, i.e. what the descend is targeting. Distinct from ee_pose_at_grasp (the actual EE pose at grasp time). Exposing grasp_pose lets the checkpoint author write an output-anchored verifier like predicate=lambda w, o: o["grasp_pose"]["position"]["z"] > 0.01 to catch sub-table grasp poses before they cascade into a target_held=False failure.

    Hard rule on the output binding: the robot.get_observation response is an Observation { cameras: list[CameraFrame]; arms: list[ArmState] }. There is no flat ee_pose field — the EE pose lives at arms[0].ee_pose. The binding must therefore be exactly:

    sg.set_outputs(
        ee_pose_at_grasp=Ref("observe.arms.0.ee_pose"),
        grasp_pose=Ref("compute_grasp.candidates.poses.0"),
    )
    

    Do not write Ref("observe.ee_pose") — that path does not exist and the cross-subgraph binding will silently resolve to None, sending the downstream compute_drop_pose.py into its inferior no-ee_pose_at_grasp fallback (drop height too high, placement misses).

    Cross-subgraph data flow is by name, so any downstream subgraph that declares ee_pose_at_grasp as an input automatically receives it.

    "edges": [ ..., ["close", "grasped"], ["grasped", "END"] ],
    "conditional_edges": {},
    "exit": { "router_field": null, "success_values": ["grasped"] },
    "on_error": "failed"
    

    The lift onto a safe carry height is handled by the next transporting-objects subgraph (its waypoint_move script lifts before lateral motion); do NOT add a lift step here.

Optional candidate-reordering state

For a thin/elongated target (frypan handle, screwdriver, spoon, rod) insert ONE type: script state select_short_axis (scripts/<sg>/select_short_axis.py) between compute_grasp and goto_grasp. Inputs: target_obb = Ref("in.target_obb"), candidate_poses = Ref("compute_grasp.candidates.poses"). It reorders the candidate fan so poses whose finger-opening axis aligns with the OBB's short horizontal axis come first (count and pose values preserved — only the ordering changes), then wire goto_grasp's grasp_pose/candidate_poses against Ref("select_short_axis.poses...") instead. For a deterministic, geometry-locked single short-axis pose use the dedicated grasping-short-axis skill instead.

Required end states

End stateMeaning
graspedGripper has closed on the object after the descend. Route to next subgraph (typically transporting-objects).
failedGrasp-attempt failure: the cartesian descend AND the cuRobo planner fallback both failed (a raise to on_error). Coordinator routes to abort. Lives only in on_error — never declare a failed node.

See also

  • references/design_grasp_curobo.md — the Z-locked (fingertip-frame, orientation-LOCK) linear descend and why it beats a blended rotate+descend.
  • references/gripper_settle_constants.md — settle-step tunings.
  • scripts/{grasp_descend_linear,select_short_axis}.py — canonical scripts.

What ships with it: 9 files

35.8 KB alongside SKILL.md, 6 of them executable

Gives 0 of the 12 instructions most plan spec skills give in ~1.9k tokens

Counted across 1,360 of the 2,617 authors here whose files we hold, read 2026-09-06

  • Ask one question at a timein 73 of 1360
  • Write the spec using the templatein 22 of 1360
  • Ask clarifying questions if neededin 19 of 1360, across 18 files
  • Wait for user confirmation before proceedingin 19 of 1360
  • Save plans to the plans directoryin 17 of 1360, across 13 files
  • Check for product marketing context firstin 16 of 1360, across 5 files
  • Read the plan file completelyin 16 of 1360
  • Order tasks by dependencyin 16 of 1360
  • Gather context from the conversationin 15 of 1360, across 9 files
  • Explore the codebase instead of askingin 15 of 1360, across 13 files
  • Wait for explicit user approvalin 14 of 1360, across 13 files
  • Quiz the user on the breakdownin 13 of 1360, across 7 files

Said here and by no other author read

  • Use curobo tool bundle when deployed
  • Open gripper before computing grasp
  • Compute top down grasp candidates from object obb
  • Execute linear descend onto target
  • Capture arm observation at grasp
  • Close gripper after descend

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.