Motion planning · repose-motion-planning
Choosing a planner
The planners differ in how they explore and what they guarantee. The short version: start with RRT-Connect, use RRT* or PRM when path length matters, and try Direct first when the space is usually open.
At a glance
| Planner (RON name) | Family · behaviour |
RRT-Connect (rrt_connect) | Sampling. Fast first path, no optimisation. Converges at the first connection. |
RRT* (rrt_star) | Sampling. Asymptotically optimal: keeps shortening the path with more budget. |
PRM (prm) | Sampling. Roadmap that densifies; shortest roadmap path improves over time. |
A* (a_star) | Search. Deterministic, resolution-complete on a joint lattice. Good for few joints or coarse grids. |
STOMP (stomp) | Optimisation. Seeded stochastic rollouts; copes with flat or discontinuous costs. Smooth paths with clearance. |
Path optimizer (path_optimizer) | Optimisation. CHOMP-style deterministic gradient descent. Smooth paths that push away from obstacles. |
Direct (direct) | One shot. The straight joint line, collision-checked. Cheapest possible; fails if anything is in the way. |
Shared parameters
Every planner has collision_check_step (a CuJointResolution, default 0.08 rad / 1 cm) and metric (a CuJointMetric, default 1 rad = 1 m). Distances like step_size are in the metric's normalised units. See Joint values.
RRT-Connect
Two trees grow, one from the start and one from the goal. Each iteration extends one tree a step toward a random sample, then greedily tries to connect the other tree to the new node, and the trees swap roles. The first connection is shortcut by line of sight and the job converges. Fast and robust in clutter; the path is feasible, not short.
step_size = 0.3 | Maximum extension per step. |
max_nodes = 256 | Capacity per tree (2–256). Running out → Exhausted. |
RRT*
A single tree from the start. Each new node picks the cheapest parent in its neighbourhood and then rewires neighbours through itself when that shortens their path, so the tree converges toward shortest paths. Sampling is informed: once a solution exists, samples that can't improve it are pruned. A goal bias pulls the tree toward the goal. If the straight line is free, it's found immediately.
step_size = 0.35 | Maximum extension per step. |
goal_bias = 0.15 | Probability of sampling the goal exactly. |
goal_threshold = 0.40 | Distance within which a node may connect straight to the goal. |
rewire_radius = 0.75 | Neighbourhood for choosing parents and rewiring. |
max_nodes = 256 | Tree capacity (≥ 2, ≤ 256). |
PRM
The roadmap starts with start and goal. Each work unit adds one random sample; a free sample connects to its nearest neighbours within connection_radius through free segments. After every quantum that changed the roadmap, Dijkstra finds the shortest roadmap path, which is shortcut. The path improves as the roadmap densifies, and the job converges when the roadmap is full. The roadmap is rebuilt per job from the seed.
connection_radius = 2.0 | Maximum edge length. |
neighbors = 8 | Neighbours tried per node (1–10). |
max_nodes = 1024 | Roadmap capacity (3–1024). |
A*
Configurations live on a grid anchored at the start, spaced resolution apart. Each expansion moves one joint one grid step through a free segment; the heuristic is the straight-line distance to the goal (admissible and consistent). When a node is within one grid diagonal of the goal and sees it, the path is shortcut and the job converges. No randomness. The grid grows exponentially with joint count, so on a 6-axis arm A* suits short moves or coarse resolutions.
resolution = 0.25 | Grid spacing. |
max_nodes = 2048 | Lattice capacity (2–2048). |
STOMP
The path is a fixed number of waypoints seeded on the straight line. Each iteration draws noisy, smooth copies (rollouts), scores each waypoint by obstacle penalty plus smoothness cost, weights the noise by exp(−sensitivity · normalised cost), and adds the smoothed weighted noise to the path. No gradients needed. The shortest collision-free path seen is the result.
waypoints = 12 | Including start and goal (3–32). |
rollouts = 8 | Noisy copies per iteration (2–16). |
noise = 0.15 | Exploration noise standard deviation. |
sensitivity = 10.0 | How strongly low-cost rollouts dominate. |
clearance = 0.05 m | Distance below which the obstacle cost applies. |
obstacle_weight = 40, smoothness_weight = 1 | Cost weights. |
max_iterations = 200 | Iterations after which the job ends. |
Path optimizer
CHOMP-style. The same straight-line seed, then one gradient step per iteration on
cost = w_smooth · ½ Σ |x[i+1] − x[i]|² + w_obstacle · Σ max(0, ε − c(x[i]))² / εwhere c is the clearance against the scene and ε the target clearance. The clearance gradient is a finite difference, so any scene works. After each step the path is checked segment by segment and the shortest free one is kept. Fully deterministic. It can get stuck when the straight line passes through an obstacle's middle, where pushing in any direction looks equally bad; RRT-Connect handles that case better.
waypoints = 12 | Including start and goal (3–32). |
learning_rate = 0.05 | Step per unit gradient. |
clearance = 0.05 m | Target clearance ε. |
obstacle_weight = 40, smoothness_weight = 1 | Cost weights. |
gradient_step = 1e-3 | Finite-difference step. |
max_iterations = 300 | Iterations after which the job ends. |
Direct
Checks the straight joint-space line: Converged if free, Exhausted if not. No parameters besides the shared ones. Use it as a cheap first attempt, falling back to a real planner when it fails.
Tuning checklist
Exhaustedquickly: raisemax_nodes(sampling) or the budgets, or increasestep_sizeso trees reach further.- Paths look wasteful: switch from RRT-Connect to RRT* or PRM and give
refinetime, or post-process with the optimizer. - Paths too close to obstacles: raise the collision model's
safety_margin, or use STOMP/optimizer with a largerclearance. - Narrow passages missed: finer
collision_check_step(so edges aren't wrongly accepted) and smallerstep_size(so trees can thread through).