Unified Planner Architecture¶
The Unified Planner is the central node of curobo_ros. It exposes a single ROS 2 node (unified_planner) that supports multiple planning algorithms, kinematics services, and obstacle management through a unified interface.
Overview¶
The unified planner uses the Strategy Pattern to encapsulate different trajectory planning algorithms, making it easy to switch between planning methods at runtime without modifying client code.
Available Planners¶
Planner |
Enum ID |
Mode |
Description |
Use Case |
|---|---|---|---|---|
Classic |
0 |
Open-loop |
Single-shot trajectory generation |
Static environments, pre-computed paths |
MPC |
1 |
Closed-loop |
Real-time replanning at each step |
Dynamic environments, moving obstacles |
Multi-Point |
4 |
Open-loop |
Waypoint-based trajectory generation |
Pick-and-place, inspection paths |
Joint Space |
5 |
Open-loop |
Planning in joint space |
Direct joint configuration targets |
Note: Constrained planning (hold orientation, lock axes) is available in Classic and Multi-Point planners via the
trajectory_constraintsfield — it does not require a separate planner type.
Architecture¶
Node Structure¶
UnifiedPlannerNode (/unified_planner)
│
├── Trajectory Planners (Strategy Pattern)
│ ├── ClassicPlanner — MotionGen, open-loop
│ ├── MPCPlanner — MpcSolver, closed-loop
│ ├── MultiPointPlanner — MotionGen, waypoints
│ └── JointSpacePlanner — MotionGen, joint targets
│
├── Kinematics Services (lazy warmup)
│ ├── IKServices — IkSolver, shares obstacles
│ └── FKServices — CudaRobotModel, geometry only
│
└── Shared Infrastructure
├── ObstacleManager — single source of truth for world
├── RobotContext — robot strategy (real/emulator/ghost)
└── ConfigWrapperMotion — robot config, camera, parameters
Planner Class Hierarchy¶
TrajectoryPlanner (abstract)
│
├── SinglePlanner (shared MotionGen instance)
│ ├── ClassicPlanner
│ ├── MultiPointPlanner
│ └── JointSpacePlanner
│
└── MPCPlanner (independent MpcSolver)
SinglePlanner is an intermediate abstract class for all planners that use cuRobo’s MotionGen. All SinglePlanner children share a single MotionGen instance — warmup is performed only once, and switching between them is instantaneous with no re-warmup cost.
MPCPlanner uses a separate MpcSolver instance. It can optionally share the world collision checker with MotionGen to avoid duplicating obstacle data in VRAM.
Planner Details¶
Classic Planner¶
Generates a complete collision-free trajectory from start to goal in one shot, then executes it open-loop.
Strengths: Predictable, reproducible, low GPU overhead during execution. Limitations: No reaction to environment changes mid-execution. Best for: Static, well-defined environments.
Supports optional trajectory constraints (hold orientation, lock axes) via the trajectory_constraints field.
MPC Planner¶
Continuously replans in a closed-loop at high frequency using cuRobo’s Model Predictive Control solver.
Strengths: Reactive to perturbations and dynamic obstacles, high-precision tracking. Limitations: Sustained GPU usage, less predictable completion time. Best for: Dynamic environments, moving targets, disturbance rejection.
Convergence is declared when the end-effector reaches within convergence_threshold (default 0.01m) of the target.
Multi-Point Planner¶
Plans a trajectory through a sequence of Cartesian waypoints in a single optimized pass.
Strengths: Efficient multi-waypoint tasks without chaining multiple service calls. Limitations: All waypoints must be reachable; failure at one invalidates the whole plan. Best for: Pick-and-place sequences, inspection paths, structured workflows.
Joint Space Planner¶
Plans a trajectory to a target joint configuration instead of a Cartesian pose.
Strengths: Precise joint-level control, avoids IK ambiguity. Best for: Moving to a known home configuration, calibration poses.
IK and FK Services¶
IK and FK are services on the same node as the trajectory planner. They are not initialized at startup — each solver is created only when the corresponding warmup service is called (lazy initialization).
Design Rationale¶
IKServices |
FKServices |
|
|---|---|---|
Solver |
|
|
Obstacle dependency |
Yes — shares |
No — geometry only |
World updates |
Receives obstacle changes automatically |
Not needed |
Warmup service |
|
|
Because IK uses collision avoidance, it shares the same obstacle world as the trajectory planners. When obstacles are added or removed, the IK solver is updated automatically — no manual synchronization needed.
FK is purely geometric (forward kinematics has no collision component), so it depends only on the robot’s kinematic model.
Warmup and Batch Size¶
The IK solver pre-allocates GPU memory for a fixed batch size. If you call ik_batch with a different number of poses than the warmup batch size, the solver reinitializes automatically (the first call will be slower). For best performance, warmup with the batch size you intend to use.
FK warmup primes the CUDA kernels with the expected batch size but does not require reinitialization when the batch size changes.
See ROS Interfaces — Kinematics Services for full service specifications and CLI examples.
Runtime Planner Switching¶
Planners can be switched at runtime without restarting the node:
# Switch to MPC
ros2 service call /unified_planner/set_planner curobo_msgs/srv/SetPlanner "{planner_type: 1}"
# Switch back to Classic
ros2 service call /unified_planner/set_planner curobo_msgs/srv/SetPlanner "{planner_type: 0}"
# Query available planners and their enum IDs
ros2 service call /unified_planner/get_planners curobo_msgs/srv/GetPlanners
Switching between Classic / Multi-Point / Joint Space is instantaneous (shared MotionGen). Switching to or from MPC requires its solver to be initialized (lazy warmup on first switch, ~5–15s).
Execution Modes¶
Open-loop (Classic, Multi-Point, Joint Space):
Full trajectory computed during
generate_trajectory, then sent to robot viaexecute_trajectoryPredictable and reproducible
Requires replanning if environment changes mid-execution
Closed-loop (MPC):
No pre-computed trajectory — the solver computes the next command at each control cycle
Reactive to real-time changes
Execution continues until convergence or cancellation via the
execute_trajectoryaction
Services and Actions Summary¶
Service / Action |
Type |
Description |
|---|---|---|
|
|
Plan with current planner |
|
|
Execute planned trajectory |
|
|
Switch active planner |
|
|
List available planners with enum IDs |
|
|
Initialize IK solver |
|
|
Initialize FK model |
|
|
Single IK query |
|
|
Batch IK query |
|
|
Batch FK query |
File Structure¶
curobo_ros/
├── core/
│ ├── unified_planner_node.py # Main node
│ ├── ik_services.py # IK lazy services
│ ├── fk_services.py # FK lazy services
│ ├── config_wrapper_motion.py # MotionGen config
│ └── obstacle_manager.py # World state
│
└── planners/
├── trajectory_planner.py # Abstract base class
├── single_planner.py # Shared MotionGen base
├── classic_planner.py
├── mpc_planner.py
├── multi_point_planner.py
├── joint_space_planner.py
└── planner_factory.py # Factory and Manager
Performance¶
Planner |
Planning time |
GPU during execution |
Notes |
|---|---|---|---|
Classic |
10–100ms |
Idle |
Best for static environments |
Multi-Point |
20–200ms |
Idle |
Scales with number of waypoints |
Joint Space |
10–100ms |
Idle |
Fastest when goal is in joint space |
MPC |
1–10ms/iter |
Sustained |
Continuous replanning loop |
Design Patterns¶
Strategy Pattern — planning algorithms are interchangeable at runtime
Factory Pattern —
PlannerFactorycentralizes planner creation and registrationTemplate Method —
SinglePlannerdefines the execution skeleton; children implement only the planning logicLazy Initialization — IK, FK, and MPC solvers are created only when first needed