AnyLearn
All lessons
Roboticsadvanced

Sampling-Based Planning: RRT and PRM

When grids fail in high dimensions, random sampling saves you. Understand why PRM builds reusable roadmaps, how RRT grows a tree toward the goal, what probabilistic completeness really means, and how RRT* achieves asymptotic optimality.

Not signed in β€” your progress and quiz score won't be saved.
Lesson progress1 / 8

Why sampling beats grids in high dimensions

A uniform grid in dd-dimensional C-space requires (1/Ο΅)d(1/\epsilon)^d cells. At d=7d = 7 (a Franka Panda arm) and Ο΅=5Β°\epsilon = 5Β° resolution, that is roughly 727β‰ˆ101372^7 \approx 10^{13} cells β€” impossible to store, let alone search. Grids pay for every cell regardless of whether it is reachable or interesting.

Sampling-based planners take the opposite approach: draw configurations qq uniformly at random from C\mathcal{C}, discard those in Cobs\mathcal{C}_{\text{obs}}, and connect neighbours. No grid is stored. Memory grows with the number of useful nodes, not with resolution. The key insight is that you do not need to cover Cfree\mathcal{C}_{\text{free}} β€” you only need to find one valid path (or the optimal one). Random samples achieve dense coverage of Cfree\mathcal{C}_{\text{free}} as their count grows, enabling probabilistic completeness.

Two dominant families emerged in the 1990s: PRM (multi-query roadmaps) and RRT (single-query trees). Both are standard tools in every serious motion planning stack.

Full lesson text

All 8 steps on one page β€” for reading, reference, and search.

Show

1. Why sampling beats grids in high dimensions

A uniform grid in dd-dimensional C-space requires (1/Ο΅)d(1/\epsilon)^d cells. At d=7d = 7 (a Franka Panda arm) and Ο΅=5Β°\epsilon = 5Β° resolution, that is roughly 727β‰ˆ101372^7 \approx 10^{13} cells β€” impossible to store, let alone search. Grids pay for every cell regardless of whether it is reachable or interesting.

Sampling-based planners take the opposite approach: draw configurations qq uniformly at random from C\mathcal{C}, discard those in Cobs\mathcal{C}_{\text{obs}}, and connect neighbours. No grid is stored. Memory grows with the number of useful nodes, not with resolution. The key insight is that you do not need to cover Cfree\mathcal{C}_{\text{free}} β€” you only need to find one valid path (or the optimal one). Random samples achieve dense coverage of Cfree\mathcal{C}_{\text{free}} as their count grows, enabling probabilistic completeness.

Two dominant families emerged in the 1990s: PRM (multi-query roadmaps) and RRT (single-query trees). Both are standard tools in every serious motion planning stack.

2. Probabilistic Roadmap (PRM)

PRM (Kavraki et al., 1996) has two phases:

Learning phase: sample NN configurations uniformly from C\mathcal{C}. Keep those in Cfree\mathcal{C}_{\text{free}}. For each valid sample, attempt to connect it to its kk nearest neighbours with a local planner (typically straight-line in C-space + collision check). Successful connections become graph edges.

Query phase: connect qsq_s and qgq_g to the nearest roadmap nodes, then run Dijkstra/A* on the resulting graph.

PRM is a multi-query method: once built, the roadmap answers many (qs,qg)(q_s, q_g) pairs sharing the same environment β€” ideal for robot arms that repeatedly replan in a fixed workspace. The cost is upfront: O(Nk)O(N k) collision checks during construction.

Weakness: narrow passages. A doorway thinner than the typical nearest-neighbour distance is rarely bridged by straight-line connections. Fixes include bridge sampling (sample near obstacle boundaries) and visibility-based PRM, but narrow passages remain the canonical hard case.

3. Rapidly-exploring Random Tree (RRT)

RRT (LaValle, 1998) grows a tree rooted at qsq_s using a simple loop:

  1. Sample a random configuration qrandq_{\text{rand}} (with probability pgoalp_{\text{goal}}, sample the goal instead).
  2. Find the tree node qnearq_{\text{near}} nearest to qrandq_{\text{rand}}.
  3. Extend from qnearq_{\text{near}} toward qrandq_{\text{rand}} by a step of size Ξ΄\delta: qnew=qnear+Ξ΄β‹…qrandβˆ’qnearβˆ₯qrandβˆ’qnearβˆ₯q_{\text{new}} = q_{\text{near}} + \delta \cdot \frac{q_{\text{rand}} - q_{\text{near}}}{\|q_{\text{rand}} - q_{\text{near}}\|}.
  4. If the segment [qnear,qnew][q_{\text{near}}, q_{\text{new}}] is collision-free, add qnewq_{\text{new}} to the tree.
  5. If qnewq_{\text{new}} is within Ξ΄\delta of the goal, the path is found.

RRT is single-query: the tree does not persist across planning problems. It excels in high-DOF spaces and kinodynamic problems because the extend step can respect dynamics. The tree's Voronoi bias ensures uniform exploration: large Voronoi regions attract more samples, driving the tree outward.

4. RRT extend in Python

A self-contained RRT for a 2-D point robot illustrates the core loop:

import random, math

class RRT:
    def __init__(self, q_start, q_goal, checker,
                 step=0.05, goal_bias=0.1, max_iter=5000):
        self.tree = [q_start]      # list of nodes
        self.parent = {q_start: None}
        self.q_goal = q_goal
        self.checker = checker     # callable: q -> bool (True = free)
        self.step = step
        self.goal_bias = goal_bias
        self.max_iter = max_iter

    def _nearest(self, q):
        return min(self.tree, key=lambda n: math.dist(n, q))

    def _extend(self, q_near, q_rand):
        d = math.dist(q_near, q_rand)
        if d < 1e-9:
            return None
        alpha = min(self.step / d, 1.0)
        q_new = tuple(a + alpha*(b-a) for a,b in zip(q_near, q_rand))
        if self.checker(q_new):    # collision check at endpoint
            return q_new
        return None

    def plan(self):
        for _ in range(self.max_iter):
            q_rand = (self.q_goal if random.random() < self.goal_bias
                      else (random.uniform(0,1), random.uniform(0,1)))
            q_near = self._nearest(q_rand)
            q_new  = self._extend(q_near, q_rand)
            if q_new is None:
                continue
            self.tree.append(q_new)
            self.parent[q_new] = q_near
            if math.dist(q_new, self.q_goal) < self.step:
                return self._extract_path(q_new)
        return None  # timeout

    def _extract_path(self, q):
        path = []
        while q is not None:
            path.append(q); q = self.parent[q]
        return path[::-1]

Note: this extend checks only the endpoint, not the full segment. Production planners call segment_free(q_near, q_new) for safety.

5. Probabilistic completeness β€” not completeness

RRT and PRM are probabilistically complete: the probability that they fail to find a path (when one exists) converges to zero as the number of samples Nβ†’βˆžN \to \infty. Formally, for RRT:

P(failureΒ afterΒ NΒ iters)≀(1βˆ’pconnect)Nβ†’0P(\text{failure after } N \text{ iters}) \leq (1 - p_{\text{connect}})^N \to 0

where pconnect>0p_{\text{connect}} > 0 is a lower bound on the probability that a single iteration makes progress toward the goal.

This is not the same as completeness. A complete planner terminates in finite time and either finds a path or proves none exists. RRT does neither: it can run forever without finding a path (though probability decays), and it cannot certify infeasibility.

Practical implication: if RRT times out, you do not know whether no path exists or you just need more samples. For safety-critical applications (surgical robots, aerospace), probabilistic completeness is often not sufficient β€” exact methods or certified planners are required despite their higher cost.

6. RRT* and asymptotic optimality

Plain RRT finds a path but has no quality guarantee. The path typically has redundant detours and jerky turns. RRT* (Karaman & Frazzoli, 2011) adds two operations after each extend:

  1. Rewire near-nodes: within a ball of radius rn=γ(log⁑n/n)1/dr_n = \gamma (\log n / n)^{1/d} around qnewq_{\text{new}}, check whether routing through qnewq_{\text{new}} reduces each near-node's cost. If so, redirect the parent.
  2. Choose the best parent: when inserting qnewq_{\text{new}}, connect it to the near-node with the lowest gg-cost, not the nearest node.

The radius rnr_n shrinks as the tree grows (ensuring finite vertex degree) but shrinks slowly enough that the tree remains connected. The result is asymptotic optimality: the path cost returned by RRT* converges to the optimal path cost cβˆ—c^* almost surely as Nβ†’βˆžN \to \infty:

lim⁑Nβ†’βˆžcRRTβˆ—(N)=cβˆ—(a.s.)\lim_{N\to\infty} c_{\text{RRT}^*}(N) = c^* \quad \text{(a.s.)}

In contrast, RRT's path cost converges to a suboptimal value and stays there β€” it is not asymptotically optimal.

7. Comparing planners: A* vs PRM vs RRT vs RRT*

No single algorithm dominates all scenarios. Here is an honest comparison:

PropertyA* (grid)PRMRRTRRT*
CompleteYes (finite grid)ProbabilisticProbabilisticProbabilistic
OptimalYesNoNoAsymptotically
Multi-queryYes (rebuild graph)YesNoNo
High DOF (d>6d>6)No (grid explodes)YesYesYes
KinodynamicHardHardNaturalNatural
Narrow passagesGood (fine grid)PoorModerateModerate
AnytimeWith ARA*NoYes (first path fast)Yes (improves)
MemoryO((1/Ο΅)d)O((1/\epsilon)^d)O(N)O(N)O(N)O(N)O(N)O(N)

Rule of thumb: use A* for 2-D navigation (well-understood, fast, reliable); PRM for high-DOF arms in fixed environments; RRT for single-query high-DOF or kinodynamic problems; RRT* when path quality matters and planning time is available.

8. Practical considerations and variants

Vanilla RRT and PRM have well-known failure modes that production planners address:

BiRRT (bidirectional RRT): grow two trees β€” one from qsq_s, one from qgq_g β€” and attempt to connect them. Halves the effective search depth, giving order-of-magnitude speedups in cluttered environments.

Goal biasing: set pgoal=0.05p_{\text{goal}} = 0.05–0.100.10. Without it, RRT explores uniformly and rarely reaches the goal in practice. Too high (p>0.3p > 0.3) and the tree gets stuck on local obstacles.

Informed RRT:* once any path of cost cbestc_{\text{best}} is found, restrict future samples to the prolate hyperspheroid {q:βˆ₯qβˆ’qsβˆ₯+βˆ₯qβˆ’qgβˆ₯≀cbest}\{q : \|q - q_s\| + \|q - q_g\| \leq c_{\text{best}}\}. This focuses effort where improvements are still possible.

CHOMP / STOMP / TrajOpt: optimise a trajectory in continuous space using gradient descent or stochastic perturbation. Often used to smooth an RRT* path post-planning rather than plan from scratch.

For real robots, always add a post-processing step: shortcut the path (try direct connections between non-adjacent waypoints), then smooth with a spline or elastic band.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. RRT is probabilistically complete but NOT complete. What is the practical consequence?
    • RRT always finds the optimal path if given enough iterations.
    • If RRT times out, you cannot tell whether no path exists or you simply need more samples.
    • RRT is complete for robots with fewer than 6 DOF.
    • Probabilistic completeness implies the path cost converges to optimal.
  2. PRM is called a multi-query method because:
    • It can plan for multiple robots simultaneously.
    • The roadmap is built once for a fixed environment and reused across many start-goal pairs.
    • It queries the collision checker multiple times per node.
    • It runs multiple RRTs in parallel and merges the results.
  3. RRT* achieves asymptotic optimality over plain RRT through:
    • Using a finer grid resolution as the tree grows.
    • Rewiring near-nodes through the new node when it reduces their path cost, and choosing the best parent within a shrinking radius ball.
    • Running multiple RRT trees and selecting the shortest resulting path.
    • Replacing the random sampling with deterministic Halton sequences.
  4. Why does plain PRM struggle with narrow passages in C-space?
    • PRM's local planner cannot handle curved C-space obstacles.
    • The probability that a uniform random sample falls inside a narrow passage is proportional to its volume, which is very small.
    • PRM's nearest-neighbour query is inaccurate near obstacle boundaries.
    • Narrow passages only exist for robots with more than 6 DOF.
  5. Which claim about goal biasing in RRT is correct?
    • Setting goal bias $p_{\text{goal}} = 1.0$ makes RRT find the shortest possible path.
    • Goal biasing replaces random sampling entirely for faster convergence.
    • A small goal bias ($p \approx 0.05$–$0.10$) accelerates convergence without compromising exploration; too high and the tree gets stuck on local obstacles.
    • Goal biasing makes RRT asymptotically optimal, matching RRT*.

Related lessons