Rollout Classes¶
A rollout in optimal control refers to the computation of costs and constraints from given
optimization variables; these optimization variables are often a sequence of actions that a robot
will take from a given initial state at fixed timesteps dt. The length of the sequence is the
rollout horizon. In some cases, the horizon of the action will be different from the rollout.
For example, if the robot needs to be static at the final timestep, we execute the last action
for a few more timesteps to ensure the robot is static.
Rollout Flow¶
In cuRobo, evaluation of action sequences is often done for a batch of action sequences as cuRobo
optimizes over different seeds/variations in parallel to find the best action sequence. For e.g.,
when using sampling based methods like MPPI,
evaluations are done across multiple particles to find the best action sequence. When using
gradient-based methods like LBFGSOpt, evaluations
are done across step sizes (parallel line search). In addition to the batching due to optimization
solvers, we also need to batch across multiple seeds and also across different optimization
targets.
The Rollout Protocol¶
cuRobo rollouts are defined structurally rather than through inheritance. Any class whose public
surface matches the Rollout
Protocol can be passed wherever the solvers expect a rollout – no base class is
required, and there is no RolloutBase to subclass.
A rollout must expose the following properties (all read-only):
action_dim– dimensionality of a single action.action_horizon– number of timesteps in an action sequence.action_bound_lows/action_bound_highs– per-dimension action limits, shape(action_dim,).dt– integration timestep (seconds).sum_horizon– whether costs are summed across the horizon before being returned.
and the following methods:
evaluate_action(act_seq)– the core forward pass used every optimizer iteration; returns aRolloutResult.compute_metrics_from_state(state)/compute_metrics_from_action(act_seq)– compute fullRolloutMetrics(costs, constraints, convergence) after optimization finishes.update_params/update_batch_size/update_dt– lifecycle hooks the solver calls between solves to retarget, resize internal buffers, or change the timestep.reset/reset_shape/reset_seed– clear per-problem state, cached goal shapes, and the Halton sampler respectively.
Separating evaluate_action from compute_metrics_from_* lets the optimizer hot-loop stay
tight while post-optimization analysis can afford to compute extra information. For inverse
kinematics, for example, compute_metrics_from_state reports position and rotation error
separately even though the optimizer only needed their weighted sum.
Two reference implementations ship with cuRobo:
RosenbrockRollout– a minimal implementation over the Rosenbrock function, intended as a pedagogical example and as a test rollout for the solvers. See Writing Optimization Problems.RobotRollout– the realistic rollout used throughout cuRobo, composing a transition model, aRobotCostManager, and a scene collision checker.
CUDA Graph Acceleration¶
cuRobo supports CUDA graphs to reduce the overhead of kernel launches during the hot loop. CUDA graphs require the shape of inputs and outputs to be constant across replays.
CUDA-graph acceleration is a constructor parameter, not a subclass or mixin. Pass
use_cuda_graph=True when constructing the rollout:
from curobo._src.rollout.rollout_rosenbrock import RosenbrockCfg, RosenbrockRollout
rollout = RosenbrockRollout(config, use_cuda_graph=True)
Internally the rollout wraps the post-optimization hooks
(compute_metrics_from_state and compute_metrics_from_action) in
GraphExecutor instances. The graph is recorded
lazily on the first call and replayed on every subsequent call. When
use_cuda_graph=False (the default), GraphExecutor transparently falls back to a direct
function call, so the same rollout class runs with or without graphs.
Two CUDA graphs are captured per rollout when use_cuda_graph=True:
One for
compute_metrics_from_state.One for
compute_metrics_from_action.
A separate CUDA graph for the inner evaluate_action loop is captured inside the optimizer
(see Optimization Solvers), since the optimizer’s batch size typically differs from
the post-optimization batch size. Because it is also a constructor parameter
(LBFGSOpt(config, rollout_list, use_cuda_graph=True)), user rollout code does not need to
opt in; simply satisfying the Rollout
Protocol is enough. See Accelerating with CUDA Graphs for a worked example.
Cost Managers¶
When a rollout has many cost and constraint terms, listing all of them inline in evaluate_action
becomes unwieldy. cuRobo provides a single flat class,
RobotCostManager, that owns every
cost term used by RobotRollout. There is no cost
manager hierarchy – RobotCostManager is not abstract and has no subclasses.
The manager is config-driven:
RobotCostManagerCfg has one
optional field per cost kind:
self_collision_cfgscene_collision_cfgcspace_cfgstart_cspace_dist_cfgtarget_cspace_dist_cfgtool_pose_cfg
Setting any of these to None disables that cost for the rollout. At construction time the
manager instantiates the corresponding BaseCost objects,
registers them via register_cost(name, component), and allocates a dedicated CUDA
stream/event pair for each via
cuda_stream_util so the enabled costs can be evaluated in parallel.
A single compute_costs
call evaluates every enabled cost component inline (no super() chain) and returns a
CostCollection. Individual terms can still be toggled at
runtime through enable_cost_component(name) / disable_cost_component(name).
Cost Manager Architecture¶
For a step-by-step guide showing how RobotCostManager is wired into a rollout, see
Writing Motion Optimization Problems.
Available Rollout Classes¶
cuRobo ships two rollout classes, both of which satisfy the
Rollout Protocol.
Rollout Class |
Description |
|---|---|
Minimal pedagogical rollout over the Rosenbrock function. Useful for testing optimization algorithms and as a starting point for custom rollouts. |
|
|
Realistic rollout used across cuRobo’s IK, trajectory optimization, and MPC pipelines.
Composes a
|
To create your own rollout class and optimize it using cuRobo, see Writing Optimization Problems.