Using planning contracts

From workflow to code

GraspPlanningWorkflow orchestrates the processing steps shown below. It does not evaluate or rank candidates itself.

Planning step

Interface or component

Request → result

Contract status

Generate grasp candidates

GraspPlanner

GraspPlanningRequestGraspPlanningResult

implemented

Check grasp collisions

GraspCollisionChecker

GraspCollisionCheckRequest → one or more GraspCollisionResult

implemented

Plan robot motion

MotionPlanner

MotionPlanningRequestMotionPlan or None

implemented

Simulate motion

PhysicsSimulator

SimulationRequestSimulationResult

planned

Evaluate, rank, and select candidates

CandidateEvaluator

candidates + available stage results → ranked selection; interface not yet defined

planned

Render grasp poses

GraspPoseVisualizer

GraspVisualizationRequesttuple[AssetRef, ...]

planned

Render simulation video

VideoRenderer

VideoRenderRequesttuple[AssetRef, ...]

planned

Here, implemented means that the interface and its data types exist in configrip-contracts; it does not describe backend completeness. The workflow may invoke the planned CandidateEvaluator after grasp generation, collision checking, and simulation. This allows it to reduce the candidate set before expensive downstream steps.

Calling a planning backend

The caller constructs a validated request and invokes any implementation of GraspPlanner. One request may contain one or several concrete gripper designs; max_candidates_per_gripper applies to each design independently. This example shows the programmatic contract implemented by the current GraspGenX adapter. Backend construction, model configuration, asset resolution, and command-line usage are documented in the grasp-pose-generation tool.

from configrip_contracts import (
    AssetRef,
    GeometryRef,
    GraspObject,
    GraspPlanner,
    GraspPlanningRequest,
    GraspPlanningResult,
    GripperRef,
)


def generate_candidates(planner: GraspPlanner) -> GraspPlanningResult:
    request = GraspPlanningRequest(
        object=GraspObject(
            geometry=GeometryRef(
                asset=AssetRef(
                    asset_id="objects/filigree_box",
                    version="1",
                ),
                frame="input_mesh",
                scale_to_metre=1.0,
            )
        ),
        grippers=(
            GripperRef(
                gripper_id="robotiq_2f_85",
                description=AssetRef(
                    asset_id="grippers/x_grippers/robotiq_2f_85",
                    version="assets-v1",
                ),
            ),
            GripperRef(
                gripper_id="franka_panda",
                description=AssetRef(
                    asset_id="grippers/x_grippers/franka_panda",
                    version="assets-v1",
                ),
            ),
        ),
        max_candidates_per_gripper=10,
        seed=0,
    )

    return planner.plan_grasps(request)

The application supplies the concrete backend without changing the calling code:

result = generate_candidates(graspgenx_adapter)

Asset identifiers and versions in this example are illustrative. The using application resolves them through its Asset Store or a local asset resolver.

Implementing a backend

Pydantic models validate requests and results. Protocols define the methods a backend must provide. Matching the method signature is sufficient; inheritance is not required.

from configrip_contracts import (
    GraspPlanner,
    GraspPlanningRequest,
    GraspPlanningResult,
)


class GraspGenXAdapter:
    def plan_grasps(
        self, request: GraspPlanningRequest
    ) -> GraspPlanningResult:
        # Call GraspGenX and map its output to GraspPlanningResult.
        ...


planner: GraspPlanner = GraspGenXAdapter()
request = GraspPlanningRequest.model_validate(input_data)
result = planner.plan_grasps(request)

Pydantic validates each model when it is created. The planner: GraspPlanner assignment lets a type checker verify the adapter interface.

Shared rules

  • AssetRef identifies versioned content instead of embedding geometry, checkpoints, or trajectories. Platform services resolve it through the Asset Store; local tools may supply a local resolver.

  • An empty GraspPlanningResult.grasps mapping means that no grasp was found; None has the same meaning for motion planning. Technical failures raise exceptions.

  • Collision checking is optional for pose generation and visualization, but required before physical validation.

  • Candidate confidence values are backend-specific and are not assumed to be comparable across grippers. Cross-gripper ranking requires common evaluation criteria. The planned CandidateEvaluator combines evidence from subsequent stages and records excluded candidates.

Provenance for motion, simulation, and validation results is not yet defined.