Motion Planning¶
Motion Planner¶
MotionPlanner(robot_name: str, config: PlannerConfig | None = None, pointcloud: np.ndarray | None = None, base_config: np.ndarray | None = None, constraints: list | None = None, costs: list | None = None)
¶
Motion planner using OMPL + VAMP C++ backend.
All internals are private. The public API accepts and returns only numpy arrays.
For subgroup planners the helper methods :meth:extract_config,
:meth:embed_config, and :meth:embed_path convert between the
reduced DOF space used by the planner and the full 11-DOF body
configuration.
Source code in fetch_planning/planning/motion_planner.py
bounds: tuple[np.ndarray, np.ndarray]
property
¶
(lower, upper) joint limits of the active DOF.
joint_limits: dict[str, tuple[float, float]]
property
¶
{joint name: (lower, upper)} the planner samples in, for every
joint of the full body. :attr:bounds gives the active joints'
ranges as arrays.
joint_names: list[str]
property
¶
Joint names controlled by this planner, in DOF order.
is_subgroup: bool
property
¶
True if this planner controls a subset of the full body.
subgroup_indices: np.ndarray | None
property
¶
Indices of this planner's joints in the full 11-DOF config.
base_config: np.ndarray
property
¶
The 11-DOF stance frozen for joints outside this subgroup.
has_pointcloud: bool
property
¶
True if a pointcloud is currently registered.
set_joint_limits(limits: Mapping[str, tuple[float, float]] | None = None) -> None
¶
Set the joint ranges the planner samples in, by joint name.
Joints left out of limits take the range compiled into the
robot model, so None restores every compiled range. The
ranges cover the full body and are kept across
:meth:set_subgroup. Collision checking does not read them.
While the base is active, base_theta_joint's range is not
used: the Dubins / Reeds-Shepp heading is periodic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
limits
|
Mapping[str, tuple[float, float]] | None
|
|
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
For an unknown joint name, or bounds that are not
finite with |
Source code in fetch_planning/planning/motion_planner.py
clear_constraints() -> None
¶
set_constraints(constraints: list) -> None
¶
Replace all constraints: clear existing, then push new ones.
clear_costs() -> None
¶
set_costs(costs: list) -> None
¶
add_pointcloud(pointcloud: np.ndarray) -> None
¶
Set the scene pointcloud, replacing any previously-registered cloud.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pointcloud
|
ndarray
|
|
required |
Source code in fetch_planning/planning/motion_planner.py
remove_pointcloud() -> bool
¶
Drop the currently-registered pointcloud.
Returns False if there was no cloud to remove.
filter_pointcloud(pointcloud: np.ndarray, min_dist: float, max_range: float, origin: np.ndarray | list[float], workspace_min: np.ndarray | list[float], workspace_max: np.ndarray | list[float], cull: bool = True) -> np.ndarray
¶
Spatially downsample a point cloud via Morton-curve sorting.
Keeps one representative point per min_dist neighbourhood and
discards points farther than max_range from origin or
outside the [workspace_min, workspace_max] bounding box.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pointcloud
|
ndarray
|
|
required |
min_dist
|
float
|
Minimum distance between two retained points. |
required |
max_range
|
float
|
Maximum distance from |
required |
origin
|
ndarray | list[float]
|
|
required |
workspace_min
|
ndarray | list[float]
|
|
required |
workspace_max
|
ndarray | list[float]
|
|
required |
cull
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
Source code in fetch_planning/planning/motion_planner.py
filter_self_from_pointcloud(pointcloud: np.ndarray, point_radius: float, config: np.ndarray) -> np.ndarray
¶
Remove points that collide with the robot body or environment.
Computes forward kinematics at config, then drops every
point whose inflated sphere (radius point_radius) overlaps
any robot collision sphere or any registered obstacle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pointcloud
|
ndarray
|
|
required |
point_radius
|
float
|
Inflation radius for each point. |
required |
config
|
ndarray
|
Active-DOF configuration (same space as |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
|
Source code in fetch_planning/planning/motion_planner.py
set_subgroup(robot_name: str, base_config: np.ndarray | None = None) -> None
¶
Switch active joints without rebuilding the collision environment.
Clears all constraints and costs. The pointcloud is preserved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
robot_name
|
str
|
Subgroup name from |
required |
base_config
|
ndarray | None
|
11-DOF frozen config for inactive joints. Defaults to the previously stored base config. |
None
|
Source code in fetch_planning/planning/motion_planner.py
extract_config(full_config: np.ndarray) -> np.ndarray
¶
Extract this planner's joints from a full 11-DOF configuration.
Source code in fetch_planning/planning/motion_planner.py
embed_config(config: np.ndarray, base_config: np.ndarray | None = None) -> np.ndarray
¶
Embed a subgroup config into a full 11-DOF configuration.
base_config defaults to the planner's stored base — the same
11-DOF values the C++ collision checker injects for inactive
joints — so the embedded config matches what was validated.
Source code in fetch_planning/planning/motion_planner.py
embed_path(path: np.ndarray, base_config: np.ndarray | None = None) -> np.ndarray
¶
Convert a subgroup path (N, sub_dof) to (N, 11).
base_config defaults to the planner's stored base — the same
11-DOF values the C++ collision checker injects for inactive
joints — so the embedded path matches what was validated.
Source code in fetch_planning/planning/motion_planner.py
plan(start: np.ndarray, goal: np.ndarray, time_limit: float | None = None) -> PlanningResult
¶
Plan a collision-free path from start to goal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
ndarray
|
Start configuration (active DOF). |
required |
goal
|
ndarray
|
Goal configuration (active DOF). |
required |
time_limit
|
float | None
|
Optional per-call override for the solver time
limit. Defaults to |
None
|
Source code in fetch_planning/planning/motion_planner.py
plan_kinodynamic(start: np.ndarray, goal: np.ndarray, start_velocity: np.ndarray | None = None, config: KinodynamicConfig | None = None) -> KinodynamicResult
¶
Plan a dynamically feasible, time-parameterised trajectory (FLASK).
Kinodynamic RRT-Connect in the differentially flat output space
(Duong et al., T-RO 2026): every tree edge is the closed-form
minimum-effort cubic between two (position, velocity) states,
validated with SIMD-batched collision checks and the joint /
base velocity and acceleration limits from
:mod:fetch_planning.fetch. For subgroups with the mobile base
the base follows unicycle kinematics — heading tangent to the
path, forward or reverse, rotate-in-place allowed while parked —
so the output can be tracked directly with feed-forward + PID;
see :meth:~fetch_planning.trajectory.KinodynamicTrajectory.base_twist.
Collision constraints and soft costs registered on this planner are not used by the kinodynamic planner.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
ndarray
|
Start configuration (active DOF). |
required |
goal
|
ndarray
|
Goal configuration (active DOF). Reached at rest. |
required |
start_velocity
|
ndarray | None
|
Optional active-DOF velocity at |
None
|
config
|
KinodynamicConfig | None
|
Kinodynamic planner parameters. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
KinodynamicResult
|
class: |
KinodynamicResult
|
|
|
KinodynamicResult
|
class: |
Source code in fetch_planning/planning/motion_planner.py
simplify_path(path: np.ndarray, time_limit: float = 1.0) -> np.ndarray
¶
Run OMPL's shortcut-based path simplifier on path.
Same pipeline plan(..., simplify=True) uses internally
(reduceVertices + collapseCloseVertices + shortcutPath
+ B-spline smoothing), but detached so you can apply it to any
path you already have — e.g. replay an old plan with a
different collision environment.
Shortcuts only consult the motion validator. Custom soft
costs (:class:Cost) are ignored; for cost-driven plans, run
:meth:plan with simplify=False and leave the path
untouched unless you've explicitly decided shortcut shaping
is acceptable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
ndarray
|
|
required |
time_limit
|
float
|
Wall-clock budget for the simplifier, seconds. |
1.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
Source code in fetch_planning/planning/motion_planner.py
interpolate_path(path: np.ndarray, count: int = 0, resolution: float = 64.0) -> np.ndarray
¶
Densify path with uniform waypoints along every edge.
Three modes (pick one; the other must be zero):
* ``count > 0`` — exactly that many total waypoints
distributed proportionally to edge length.
* ``resolution > 0.0`` — ``ceil(edge_length * resolution)``
waypoints per edge (uniform density in state-space
distance — the default).
* both ``0`` — OMPL's default longest-valid-segment
fraction.
Uses StateSpace::interpolate internally, so the inserted
states stay on the constraint manifold for projected state
spaces and on the Dubins / Reeds-Shepp curve for compound
base+arm paths. No collision check is performed — the
densification only lifts points along the existing edges.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
ndarray
|
|
required |
count
|
int
|
Exact total waypoint count if |
0
|
resolution
|
float
|
Waypoints per unit state-space distance if
|
64.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
Source code in fetch_planning/planning/motion_planner.py
validate(configuration: np.ndarray) -> bool
¶
Check if a configuration is collision-free.
validate_batch(configurations: np.ndarray) -> np.ndarray
¶
Batched collision check — one SIMD block per rake configs.
Packs rake distinct configurations into a single VAMP
ConfigurationBlock<rake> and runs one fkcc<rake> call
per block, so N queries cost ceil(N / rake) SIMD
sweeps in the common case. When a packed block fails we fall
back to per-lane single-state checks for that block only, so
the returned array is always exactly one bool per input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
configurations
|
ndarray
|
|
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
|
ndarray
|
|
Source code in fetch_planning/planning/motion_planner.py
sample_valid(max_samples: int = 100000) -> np.ndarray
¶
Sample a random collision-free configuration.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If none of |
Source code in fetch_planning/planning/motion_planner.py
Factory Function¶
create_planner(robot_name: str = 'fetch', config: PlannerConfig | None = None, pointcloud: np.ndarray | None = None, base_config: np.ndarray | None = None, constraints: list | None = None, costs: list | None = None) -> MotionPlanner
¶
Create a motion planner for any robot or subgroup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
robot_name
|
str
|
Robot or subgroup name. Use :func: |
'fetch'
|
config
|
PlannerConfig | None
|
Planner configuration (uses defaults if None). |
None
|
pointcloud
|
ndarray | None
|
|
None
|
base_config
|
ndarray | None
|
11-DOF values to inject for joints not controlled
by this planner (i.e. the frozen joints of a subgroup).
Defaults to |
None
|
constraints
|
list | None
|
Optional list of
:class: |
None
|
costs
|
list | None
|
Optional list of
:class: |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
MotionPlanner
|
class: |
Source code in fetch_planning/planning/motion_planner.py
Available Robots¶
available_robots() -> list[str]
¶
Return all available robot names for planning.
Constraint¶
Constraint(residual: ca.SX, q_sym: ca.SX, name: str = 'constraint')
dataclass
¶
A user-defined holonomic constraint, JIT-compiled via CasADi.
Constructing this class triggers (on cold cache):
1. symbolic Jacobian via ca.jacobian(residual, q_sym)
2. C code generation via CasADi
3. compilation to a .so with c++ -O3 -shared -fPIC
4. caching under ~/.cache/fetch_planning/constraints/<sha>/
On a cache hit the whole thing is a single stat + string compare.
SymbolicContext(subgroup: str, base_config: np.ndarray | None = None)
¶
CasADi-friendly view of the planner's active subgroup.
Holds the CasADi symbolic joint vector q matching the subgroup's
active dimension, plus a pinocchio.casadi model for symbolic FK.
Fetch's whole-body URDF encodes the base as three separate 1-DOF
virtual joints (prismatic x, prismatic y, revolute z) so
pinocchio.nq == 11 and the active→pinocchio mapping is a
straight copy (no trig encoding).
Source code in fetch_planning/planning/constraints.py
link_pose(link_name: str, q_active: ca.SX | None = None)
¶
Return the symbolic pinocchio SE3 of a URDF link.
Pass q_active=self.q (or omit) to get an expression that
depends on the active joints symbolically.
Source code in fetch_planning/planning/constraints.py
link_translation(link_name: str, q_active: ca.SX | None = None) -> ca.SX
¶
Symbolic 3-vector: link position in world frame.
link_rotation(link_name: str, q_active: ca.SX | None = None) -> ca.SX
¶
evaluate_link_pose(link_name: str, q_active_numeric: np.ndarray) -> np.ndarray
¶
Compute a NUMERIC 4x4 link pose (handy for building targets).
Uses the numeric pinocchio model, not the symbolic one, so it is fast and has no dependence on CasADi expressions.
Source code in fetch_planning/planning/constraints.py
project(q_init: np.ndarray, residual: ca.SX, tol: float = 1e-08, max_iters: int = 100) -> np.ndarray
¶
Project a joint configuration onto the manifold residual(q) = 0.
Runs damped Gauss-Newton on the CasADi Jacobian — the same
iteration OMPL's ProjectedStateSpace runs internally — so
the returned config will pass the planner's tolerance check
and can be used directly as a start or goal state.
Source code in fetch_planning/planning/constraints.py
Cost¶
Cost(expression: ca.SX, q_sym: ca.SX, name: str = 'cost', weight: float = 1.0)
dataclass
¶
A user-defined soft path cost, JIT-compiled via CasADi.
Pass a scalar CasADi expression in the planner's active joint vector. Construction triggers (on cold cache):
1. symbolic gradient via ``ca.gradient(expression, q_sym)``
2. C code generation via CasADi
3. compilation to a ``.so`` with ``c++ -O3 -shared -fPIC``
4. caching under ``~/.cache/fetch_planning/costs/<sha>/``
The C++ planner wraps the loaded function in an OMPL
StateCostIntegralObjective — so per-state values are
trapezoidally integrated along every motion, which is what
RRT*-family optimal planners expect.
The expression must be non-negative (OMPL objectives accumulate
with operator+ and the optimal-planner tooling assumes the
zero cost is the minimum). We don't enforce this at runtime
because that would require evaluating the symbolic expression,
but violating it produces nonsensical RRT* solutions.
Low-level C++ binding¶
OmplVampPlanner(active_indices: Sequence[int], frozen_config: Sequence[float], base_dim: int = 0, turning_radius: float = 0.2, allow_reverse: bool = False)
¶
OMPL planner with VAMP SIMD-accelerated collision checking.
Single construction mode — the Python wrapper decides which joints are active and how many form the nonholonomic base:
OmplVampPlanner(active_indices, frozen_config, base_dim, turning_radius, allow_reverse)
The C++ collision checker injects frozen_config for every slot
in the 11-DOF whole-body state that is not listed in
active_indices before running every state or motion validity
query.
Create a subgroup planner.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
active_indices
|
Sequence[int]
|
Positions in the full-body config that this planner will plan over, in DOF order. |
required |
frozen_config
|
Sequence[float]
|
Full-body stance to inject for every joint not
in |
required |
base_dim
|
int
|
How many leading active indices form the nonholonomic base (0 = arm-only, 3 = SE2 base). |
0
|
turning_radius
|
float
|
Minimum turning radius in metres (ignored
when |
0.2
|
allow_reverse
|
bool
|
Select the SE(2) base state space. |
False
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in fetch_planning/_ompl_vamp.pyi
default_joint_limits() -> tuple[list[float], list[float]]
staticmethod
¶
joint_limits() -> tuple[list[float], list[float]]
¶
set_joint_limits(lower: Sequence[float], upper: Sequence[float]) -> None
¶
Replace the range of every joint (full-body order).
Each joint needs finite bounds with lower < upper; otherwise
ValueError and nothing changes. The ranges bound the active
state space (the base x / y range the SE(2) space, whose heading
is periodic) and survive :meth:set_subgroup.
Source code in fetch_planning/_ompl_vamp.pyi
add_pointcloud(points: Sequence[Sequence[float]], r_min: float, r_max: float, point_radius: float) -> None
¶
Set the scene point cloud, replacing any registered one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Sequence[Sequence[float]]
|
|
required |
r_min
|
float
|
Minimum robot collision-sphere radius (from
:meth: |
required |
r_max
|
float
|
Maximum robot collision-sphere radius (from
:meth: |
required |
point_radius
|
float
|
Inflation radius applied to every cloud point. |
required |
Source code in fetch_planning/_ompl_vamp.pyi
remove_pointcloud() -> bool
¶
has_pointcloud() -> bool
¶
add_sphere(center: Sequence[float], radius: float) -> None
¶
clear_environment() -> None
¶
add_compiled_constraint(so_path: str, symbol_name: str, ambient_dim: int, co_dim: int) -> None
¶
Load a CasADi-generated shared library as an OMPL constraint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
so_path
|
str
|
Path to the compiled |
required |
symbol_name
|
str
|
CasADi function symbol name inside the library. |
required |
ambient_dim
|
int
|
Dimension of the joint space (must match
:meth: |
required |
co_dim
|
int
|
Number of constraint equations (rows of the residual). |
required |
Source code in fetch_planning/_ompl_vamp.pyi
clear_constraints() -> None
¶
num_constraints() -> int
¶
add_compiled_cost(so_path: str, symbol_name: str, ambient_dim: int, weight: float = 1.0) -> None
¶
Load a CasADi-generated shared library as a soft path cost.
The cost is wrapped as an ompl::StateCostIntegralObjective —
trapezoidally integrated along every motion — and drives the
search of asymptotically-optimal planners (RRT*, BIT*, AIT*,
…). Multiple costs are summed with their weight.
For whole-body / base-including subgroups the cost is combined with the Dubins / Reeds-Shepp path-length term (which lives in the state-space distance) — non-holonomic shaping is preserved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
so_path
|
str
|
Path to the compiled |
required |
symbol_name
|
str
|
CasADi function symbol name inside the library. |
required |
ambient_dim
|
int
|
Dimension of the joint space (must match
:meth: |
required |
weight
|
float
|
Non-negative scalar multiplier applied to the cost. |
1.0
|
Source code in fetch_planning/_ompl_vamp.pyi
clear_costs() -> None
¶
num_costs() -> int
¶
plan(start: Sequence[float], goal: Sequence[float], planner_name: str = 'rrtc', time_limit: float = 10.0, simplify: bool = True, interpolate: bool = True, resolution: float = 64.0) -> PlanResult
¶
Plan a collision-free path from start to goal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
Sequence[float]
|
Active-DOF start configuration (length :meth: |
required |
goal
|
Sequence[float]
|
Active-DOF goal configuration (length :meth: |
required |
planner_name
|
str
|
OMPL planner identifier (e.g. |
'rrtc'
|
time_limit
|
float
|
Solver time limit in seconds. |
10.0
|
simplify
|
bool
|
If true, run |
True
|
interpolate
|
bool
|
If true, densify the simplified path: by
|
True
|
resolution
|
float
|
Waypoints per unit of state-space distance. Each
edge of length |
64.0
|
Source code in fetch_planning/_ompl_vamp.pyi
plan_kinodynamic(start: Sequence[float], start_velocity: Sequence[float], goal: Sequence[float], time_limit: float, settings: KinodynamicSettings) -> KinodynamicResult
¶
FLASK kinodynamic planning in the flat output space.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
Sequence[float]
|
Active-DOF start configuration. |
required |
start_velocity
|
Sequence[float]
|
Active-DOF start velocity, or empty for rest.
Base entries are world-frame |
required |
goal
|
Sequence[float]
|
Active-DOF goal configuration, reached at rest. |
required |
time_limit
|
float
|
Solver time limit in seconds. |
required |
settings
|
KinodynamicSettings
|
Limits and planner parameters. |
required |
Source code in fetch_planning/_ompl_vamp.pyi
simplify_path(path: Sequence[Sequence[float]], time_limit: float = 1.0) -> list[list[float]]
¶
Run OMPL's shortcut simplifier on a waypoint list.
Reuses the current collision environment and constraints. Shortcuts only consult the motion validator, so custom soft costs are ignored. Returns the simplified path as waypoints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Sequence[Sequence[float]]
|
|
required |
time_limit
|
float
|
Simplifier wall-clock budget, seconds. |
1.0
|
Source code in fetch_planning/_ompl_vamp.pyi
interpolate_path(path: Sequence[Sequence[float]], count: int = 0, resolution: float = 64.0) -> list[list[float]]
¶
Densify a waypoint list along its existing edges.
Pass at most one of count (exact total waypoints,
distributed by edge length) or resolution (waypoints per
unit of state-space distance). Both zero falls back to OMPL's
default longest-valid-segment fraction. No collision check is
performed — densification only calls StateSpace::interpolate
on the existing edges, so the inserted waypoints stay on the
Dubins / Reeds-Shepp curve for compound base+arm paths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Sequence[Sequence[float]]
|
|
required |
count
|
int
|
Total waypoint count if > 0. |
0
|
resolution
|
float
|
Waypoints per unit distance if > 0.0. |
64.0
|
Source code in fetch_planning/_ompl_vamp.pyi
validate(config: Sequence[float]) -> bool
¶
Return True if config is collision-free.
config must have length :meth:dimension. Subgroup
planners expand it to a full 11-DOF state with the stored
frozen_config before checking.
Source code in fetch_planning/_ompl_vamp.pyi
validate_batch(configs: Sequence[Sequence[float]]) -> list[bool]
¶
Batched collision check — deep SIMD, per-config result.
Packs up to rake distinct configurations into a single
VAMP ConfigurationBlock<rake> so one Robot::fkcc<rake>
call sphere-FKs and collision-checks all of them
simultaneously — the same SIMD primitive the motion-edge
validator uses for interpolated samples, fed independent
configs per lane instead.
Returns one bool per input config in input order. In the
common case (most configs valid) costs ceil(N / rake)
SIMD calls; when a packed block fails, only that block falls
back to per-lane single-state checks.
Each configs[i] must have length :meth:dimension.
Subgroup planners expand each to a full 11-DOF state with
the stored frozen_config before packing.
Source code in fetch_planning/_ompl_vamp.pyi
dimension() -> int
¶
lower_bounds() -> list[float]
¶
upper_bounds() -> list[float]
¶
min_max_radii() -> tuple[float, float]
¶
(min_radius, max_radius) of the robot's collision spheres.
Pass these to :meth:add_pointcloud so VAMP can index its
broadphase correctly.
filter_pointcloud(points: Sequence[Sequence[float]], min_dist: float, max_range: float, origin: Sequence[float], workspace_min: Sequence[float], workspace_max: Sequence[float], cull: bool = True) -> list[list[float]]
¶
Morton-curve spatial down-sampling of a point cloud.
Keeps one representative point per min_dist neighbourhood
and discards points outside the AABB / range envelope.
Source code in fetch_planning/_ompl_vamp.pyi
filter_self_from_pointcloud(points: Sequence[Sequence[float]], point_radius: float, config: Sequence[float]) -> list[list[float]]
¶
Remove points that collide with the robot body at config
or with the registered environment.
Source code in fetch_planning/_ompl_vamp.pyi
set_subgroup(active_indices: Sequence[int], frozen_config: Sequence[float], base_dim: int = 0) -> None
¶
Switch to a different subgroup without rebuilding the environment.
Clears all constraints and costs. The pointcloud and collision geometry are preserved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
active_indices
|
Sequence[int]
|
Positions in the full-body config that this planner will plan over, in DOF order. |
required |
frozen_config
|
Sequence[float]
|
Full-body stance to inject for every joint not
in |
required |
base_dim
|
int
|
How many leading active indices form the nonholonomic base (0 = arm-only, 3 = SE2 base). |
0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |