Planning Groups

August 27, 2026 ยท View on GitHub

Planning groups are named, selectable kinematic chains used by manipulation planning. They let APIs target a specific part of a robot, such as an arm or torso, without confusing that group with the robot's hardware identity.

Concepts

ConceptMeaning
ModelThe single configured RobotModelConfig.
Planning groupA named subset of the model's controllable joints.
Planning group IDStable declared group name, such as left_arm.
Canonical joint nameJoint name used unchanged by the model, planner, coordinator, and visualization.
Generated planPlanning artifact containing selected group IDs, geometric waypoints, and one synchronized canonical trajectory.
Auxiliary groupA selected group that contributes free DOFs to a pose plan without receiving its own pose target.

The configured model owns one canonical joint namespace. Planning groups select subsets of that namespace; they do not rename or prefix joints.

Discovering planning groups

Robot configs can provide planning groups explicitly with RobotModelConfig.planning_groups. Direct RobotModelConfig(...) construction does not run discovery or synthesize groups in model_post_init; callers must pass explicit planning_groups there.

When code uses the discovery helper instead of explicit config, dimOS discovers groups in this order:

  1. Explicit srdf_path provided to the helper.
  2. Conservative SRDF auto-discovery near the model path, with a warning.
  3. Fallback generation of one manipulator group when the configured controllable joints form exactly one unambiguous serial chain.
  4. Error if no SRDF or fallback chain can provide a single valid group.

Supported SRDF group forms:

<group name="arm">
  <chain base_link="base_link" tip_link="tool0" />
</group>
<group name="arm">
  <joint name="joint1" />
  <joint name="joint2" />
  <joint name="joint3" />
</group>

Unsupported SRDF forms are skipped with warnings: link groups, nested group references, mixed group declarations, branching or non-serial groups, and SRDF <end_effector> metadata. A chain group's tip_link is its pose target frame. An ordered joint-list group can be pose-targeted only when dimOS can validate a unique serial target frame.

Fallback behavior

When discovery runs without an SRDF, fallback uses RobotModelConfig.joint_names as the candidate controllable set. This field is the model's ordered canonical joint set, not an implicit planning group.

Fallback removes terminal prismatic leaves first, including branched finger joints, and then requires the remaining joints to form one unambiguous serial chain. Internal prismatic axes remain part of the arm. The generated group name is always manipulator.

Current APIs

Use list_planning_groups() to discover group IDs and capabilities before planning:

groups = manip.list_planning_groups()
pose_groups = [group for group in groups if group.has_pose_target]
group_id = pose_groups[0].id

Joint-space planning targets group IDs. Each target JointState may be unnamed in the group's joint order or named with the group's canonical joints.

ok = manip.plan_to_joint_targets(
    {
        "left_arm": JointState(
            name=["left/joint1", "left/joint2", "left/joint3"],
            position=[0.0, -0.4, 0.2],
        )
    }
)

Pose planning targets pose-capable group IDs. Add auxiliary groups when another chain should participate as free DOFs but does not have its own pose target. Pose targets are Pose values keyed by planning group ID:

ok = manip.plan_to_pose_targets(
    {"left_arm": target_pose},
    auxiliary_groups=["torso"],
)

After a successful planning call, preview and execution use the module's current stored plan:

manip.preview_plan()
manip.execute_plan()

Callers that already hold a GeneratedPlan may pass it explicitly:

manip.preview_plan(plan)
manip.execute_plan(plan)

A generated plan is the execution boundary. The canonical trajectory is sent unchanged to the coordinator. To execute a subset, first plan only that subset's planning group.

Generated plans and execution

A GeneratedPlan stores:

  • selected planning group IDs;
  • a geometric path of JointState waypoints keyed by canonical joint names;
  • one materialized synchronized JointTrajectory over the same selected canonical joint names;
  • status, timing, path length, iteration count, and message metadata.

Preview and execution consume the stored trajectory; they do not lazily parameterize the geometric path. Preview and execution forward the canonical trajectory without renaming, splitting, or merging it. The coordinator's trajectory task remains planning-group agnostic and holds omitted joints while executing the selected subset.

Robot placement config

RobotModelConfig.base_pose and RobotModelConfig.base_link describe robot placement: base_pose places base_link in the world and current backends use that link for weld/placement and optional model-authored world-joint stripping. This is model placement metadata, not planning-chain metadata.

Planning-group base_link and tip_link values are the source for chain bases and pose target frames. Convenience pose APIs require an explicit group when the model has multiple pose-targetable groups.

Robot placement can be encoded either in model assets or in base_pose, depending on the blueprint. joint_names describes the ordered controllable canonical model joint set.