Moduł 06 · Sampling-based

Planowanie próbkowe

PRM, RRT, RRT-Connect, RRT*, Informed RRT*, FMT*, BIT*, ABIT*, AIT*, EIT*, EST, SBL, KPIECE. Strategie samplingu, kinodynamic.

TL;DR

Planery próbkowe nie konstruują Qfree\mathcal{Q}_{\text{free}} jawnie (niemożliwe w wysokich wymiarach — moduł 03). Zamiast tego losują punkty w Q\mathcal{Q} i sprawdzają zapytaniem collision check. Z czasem budują reprezentację łączności wolnej przestrzeni: drzewo (RRT) lub graf (PRM).

  • RRT (LaValle 1998) — drzewo rośnie ku qrandq_{\text{rand}}, naturalnie eksploruje całą Q\mathcal{Q}. Single-query, kompletny probabilistycznie. NIE jest optymalny.
  • RRT-Connect(Kuffner & LaValle 2000) — dwa drzewa rosnące ku sobie + greedy connect. ~10× szybsze niż RRT dla typowych pick&place. Domyślny planer MoveIt2.
  • RRT*(Karaman & Frazzoli 2011) — RRT + rewire + choose-parent. Asymptotycznie optymalny: cost(σn)cost\text{cost}(\sigma_n) \to \text{cost}^* gdy nn \to \infty.
  • PRM (Kavraki 1996) — multi-query: zbuduj roadmap raz, odpowiadaj na wiele zapytań start/goal.
  • BIT*, FMT*, AIT*, EIT* — druga generacja: batched sampling + heurystyka + lazy edge evaluation. Najszybsze w benchmarkach OMPL.

Wszystkie warianty łączy ich rdzeń: sample → connect → extract path. Różnią się strategią eksploracji, optymalnością, i tym czy budują drzewo vs graf.

RRT — Rapidly-exploring Random Tree

Algorytm:

T ← {q_start}
for i = 1..N:
  q_rand ← sample(Q)                  # z prob. β: goal, inaczej uniform
  q_near ← nearest(T, q_rand)
  q_new  ← steer(q_near, q_rand, ε)   # krok o ε ku q_rand
  if collision_free(q_near, q_new):
    T ← T ∪ {q_new} with parent q_near
    if dist(q_new, q_goal) < r_goal:
      return path(q_start → q_new)

Voronoi bias: drzewo „chce" eksplorować — większy region T = większe prawdopodobieństwo, że qrandq_{\text{rand}} wyląduje w jego komórce Voronoi.qnearq_{\text{near}} dla takiego sampla zwykle leży na brzegu drzewa, więc nowy węzeł rozszerza region. To klucz do dlaczego RRT zbiega do całej Qfree\mathcal{Q}_{\text{free}}.

Goal bias β[0,0.5]\beta \in [0, 0.5] — z prawdopodobieństwem β\beta samplem jest qgoalq_{\text{goal}}. Mała wartość (~5%) wystarcza by drzewo „znalazło" goal w rozsądnym czasie. Za duża β\beta (>30%) sprawia że drzewo „rozkłada się" w lokalnym minimum przed dotarciem do celu.

W demo niżej: testuj suwakami ε\varepsilon (step size — kompromis: krótki = drobny ruch ale wolny progres; długi = częste kolizje) i β\beta (goal bias — patrz scenariusz z mapą narrow-passage aby zobaczyć efekty extremalnych wartości).

RRT — iter 1 / 142

koszt: 1.558⟳ iter
SG
algorytm
mapa
seed
step size0.040
goal bias5%
start (S)goal (G)przeszkodadrzewo z Sścieżkasample

Kluczowa właściwość: probabilistic completeness

limnP{RRT znajdzie sˊciez˙kę w n iteracjach}=1\lim_{n \to \infty} \mathbb{P}\{\text{RRT znajdzie ścieżkę w } n \text{ iteracjach}\} = 1

...pod warunkiem że ścieżka istnieje. To słabsze niż zwykła kompletność (gwarancja w skończonym czasie) — nie ma algorytmu sample-based który byłby kompletny w klasycznym sensie, bo wąski korytarz może wymagać dowolnie wielu sampli.

RRT NIE jest optymalny. Ścieżka zwracana przez RRT jest jakąś ścieżką w drzewie — typowo 30-50% dłuższa od optymalnej. Optymalność wymaga RRT* (poniżej).

RRT-Connect — bidirekcyjne + greedy

Dwa drzewa: TaT_a od start, TbT_b od goal. W każdej iteracji:

  1. TaT_a rośnie ku losowemu qrandq_{\text{rand}} (EXTEND).
  2. Jeśli sukces — TbT_b wykonuje CONNECT ku nowemu węzłowi qnewq_{\text{new}} — to extend wielokrotny, dopóki nie dojdzie albo nie zderzy się z przeszkodą.
  3. Jeśli skleiły się — ścieżka znaleziona.
  4. Swap TaTbT_a \leftrightarrow T_b — drzewa na zmianę inicjują iterację.

Greedy CONNECT eliminuje większość „bezowocnych" kroków RRT. Empirycznie 5-15× szybciej niż jednostronny RRT na typowych zadaniach manipulacji. To domyślny planer w MoveIt2 i OMPL dla manipulatorów.

RRT-Connect — iter 1 / 1

koszt: 0.800✓ FOUND
SG
Drzewa się skleiły w iteracji 1, koszt 0.800
mapa
seed
step size0.040
start (S)goal (G)przeszkodadrzewo z Sdrzewo z Gścieżkasample

RRT* — asymptotyczna optymalność

Dwa dodatki do RRT:

  1. Choose parent: zamiast naivnie dodawać qnewq_{\text{new}} jako dziecko qnearq_{\text{near}}, przeszukaj wszystkich sąsiadów w r(n)r(n) i wybierz tego, który da najmniejszy koszt ścieżki qstartqnewq_{\text{start}} \to q_{\text{new}}.
  2. Rewire: dla każdego węzła qq' w r(n)r(n), sprawdź czy przejście przez qnewq_{\text{new}} daje qq' krótszą ścieżkę. Jeśli tak — przepinamy rodzica qq' na qnewq_{\text{new}}.

Promień rewire dla asymptotycznej optymalności:

r(n)=γ(lognn)1/dr(n) = \gamma \left( \frac{\log n}{n} \right)^{1/d}

gdzie dd = wymiar C-space. Dla 2D maleje logn/n\propto \sqrt{\log n / n}, więc dla n=104n = 10^4 mamy r0.03r \approx 0.03. W naszej implementacji uproszczono do stałej (suwak rewire r).

Konsekwencja: z każdym rewire ścieżka się poprawia. W demo poniżej obserwuj pomarańczowe krawędzie (świeżo rewired) — ścieżka „prostuje się" w czasie. Dla bardzo długiego biegu (n=105n = 10^5) ścieżka zbiega do optymalnej.

RRT* — iter 1 / 168

koszt: 1.271⟳ iter
SG
mapa
seed
step size0.040
goal bias5%
rewire r0.100
start (S)goal (G)przeszkodadrzewo z Sścieżkasamplerewire

Praktyczne ulepszenia RRT*

  • Informed RRT* (Gammell et al. 2014): po znalezieniu pierwszej ścieżki o koszcie cbestc_{\text{best}}, sample tylko z elipsoidy o ogniskach (start, goal) i długości cbestc_{\text{best}}. Wszelkie punkty poza tym obszarem na pewno nie polepszą ścieżki.
  • RRT-X(Otte & Frazzoli 2014): online version — odpowiada na pojawienie się/zniknięcie przeszkód bez restartu.
  • Quick-RRT* — ancestor rewire: rewire przez kilka pokoleń w górę, nie tylko bezpośrednich sąsiadów. Szybsza zbieżność.

PRM — Probabilistic Roadmap (multi-query)

Cały odrębny paradygmat: zamiast budować drzewo per zapytanie, raz konstruuj roadmap grafu w Qfree\mathcal{Q}_{\text{free}} (offline), potem odpowiadaj na wiele zapytań start/goal przez Dijkstrę (online).

Faza learning:

  1. Wylosuj NN punktów w Q\mathcal{Q}, odrzuć te w kolizji.
  2. Dla każdego: znajdź kk najbliższych (lub w promieniu rr), połącz krawędzią jeśli lokalny planer (linia prosta) jest wolny od kolizji.

Faza query: dodaj start/goal do roadmapu, połącz z najbliższymi, uruchom Dijkstrę.

Kiedy ma sens:roboty stacjonarne z fixed sceną (pick&place na linii produkcyjnej), wielokrotne zapytania. Nie ma sensu dla scen dynamicznych (każda zmiana sceny = przeliczenie roadmapu).

Warianty:

  • PRM*: promień r(n)(logn/n)1/dr(n) \propto (\log n / n)^{1/d} — asymptotyczna optymalność.
  • Lazy PRM: nie sprawdzaj kolizji krawędzi przy budowie roadmapu, tylko przy query. Tańsze gdy lista zapytań jest mała.
  • Visibility PRM: agresywne filtrowanie sampli — dodawaj tylko guardy (widzialne tylko z osobliwych regionów) lub connectory (łączące guardów). Ekstremalnie rzadki roadmap, dobry dla wąskich korytarzy.

PRM — iter 10 / 32

koszt: 1.242⟳ iter
SG
learning: sampling 10/200
mapa
seed
start (S)goal (G)przeszkodadrzewo z Sroadmapścieżkasample

Strategie samplingu

Algorytm jest tylko tak dobry jak jego źródło sampli. Pięć popularnych strategii — ta sama liczba sampli (300), ta sama mapa, różne pokrycie:

Strategie samplingu — porównanie pokrycia

seed
Uniform (300 sampli)
Halton (quasi-random) (300 sampli)
Gaussian (centered) (300 sampli)
Bridge test (4 sampli)
Obstacle-based (300 sampli)
Co zauważyć: Halton dla małej liczby sampli daje równomiernie pokrycie (lepsze niż uniform). Gaussian koncentruje się w środku — zła strategia dla eksploracji, dobra dla local refinement po znalezieniu rozwiązania. Bridge i obstacle-based znajdują „wąskie korytarze" między przeszkodami — krytyczne dla scen z narrow passage gdzie uniform sampling miałby znikomą szansę trafić.

Praktyczne reguły

  • Uniform — domyślny, sprawdza się dla większości scen.
  • Halton — preferowany dla małej liczby sampli (n<1000n < 1000) lub gdy wymagane jest deterministyczne pokrycie. Quasi-random ma niższą dyskrepancję niż pseudo-random.
  • Gaussian — gdy mamy prior na lokalizację rozwiązania (np. local refinement po global plan).
  • Bridge test — gdy scenariusz ma wąskie korytarze. Hsu et al. 2003.
  • Obstacle-based — gdy ścieżka prawdopodobnie będzie przebiegała blisko przeszkód (manipulacja, wąskie miejsca).

Druga generacja: BIT*, FMT*, AIT*, EIT*

Drugą falę otworzył FMT* (Janson et al. 2015) i BIT* (Gammell et al. 2015). Wspólne idee:

  • Batched sampling: zamiast inkrementalnie dodawać sample, generuj cały „batch" (np. 100 punktów) naraz, pracuj nad nim, dodaj kolejny.
  • Heurystyka informowana: używaj g^(v)+h^(v)\hat g(v) + \hat h(v) (jak A*) do priorytetyzacji krawędzi do ewaluacji.
  • Lazy edge evaluation: większość krawędzi roadmapu nigdy nie zostanie użyta w optymalnej ścieżce — nie wartoało ich sprawdzać. Sprawdzaj tylko gdy heurystyka mówi że krawędź jest obiecująca.

BIT* (Batch Informed Trees)

Hybryda PRM* + RRT* + A*. Per batch: sample N punktów w „informed" elipsoidzie (jak Informed RRT*); zbuduj implicit roadmap; uruchom heurystyczne przeszukiwanie (A*-like) by znaleźć nową ścieżkę niższego kosztu; dodaj kolejny batch.

Porównanie w benchmarkach (OMPL, Panda 7D)

  • RRT: szybkie znalezienie jakiejś ścieżki, brak optymalności
  • RRT*: poprawia jakość ale zbieżność wolna
  • BIT*: 2-5× szybsza zbieżność do optymalnego niż RRT*
  • AIT* / EIT*: dalsze ulepszenia, najlepsze w OMPL 2024

RRT* → Informed RRT* → BIT* — postęp asymptotycznie optymalnych planerów

SG
koszt najlepszej ścieżki vs iteracja (wszystkie algo, ten sam seed)
1.241.411.57iter 0600RRT*Informed RRT*BIT*
Co obserwować: (1) RRT* — drzewo rośnie wszędzie na mapie, większość węzłów dodanych po pierwszym rozwiązaniu nie poprawia ścieżki (są poza elipsą). (2) Informed RRT* — po pierwszym solutionie elipsa pojawia się (zielony kontur), kolejne sample tylko z jej wnętrza. Drzewo gęstnieje w obszarze potencjalnej poprawy. Koszt zbiega szybciej. (3) BIT* — batche samplowane razem; szare kreskowane = candidate edges w queue; fioletowe = tree edges; zielony flash = krawędź właśnie zaakceptowana po lazy collision-check, czerwony = odrzucona po collision-check. (4) Wykres kosztu pokazuje że Informed RRT* i BIT* zbiegają do tego samego optimum szybciej niż klasyczny RRT*.

Klucz: PHS — prolate hyperspheroid

Po znalezieniu ścieżki o koszcie cmaxc_{\max}, dalsze sample mogą poprawić rozwiązanie tylko jeśli leżą w elipsoidzie:

Xinf={x:xxs+xxgcmax}X_{\text{inf}} = \{x : \|x - x_s\| + \|x - x_g\| \le c_{\max}\}

To elipsa o ogniskach (xs,xg)(x_s, x_g), półoś główna a=cmax/2a = c_{\max}/2, półoś poprzeczna b=12cmax2cmin2b = \tfrac{1}{2}\sqrt{c_{\max}^2 - c_{\min}^2} gdzie cmin=xsxgc_{\min} = \|x_s - x_g\|. W miarę poprawy cmaxcminc_{\max} \to c_{\min} elipsa zwęża się do odcinka (xs,xg)(x_s, x_g) — sampling skupia się na coraz mniejszym obszarze.

Kinodynamic RRT — ograniczenia różniczkowe

Klasyczny RRT zakłada że pomiędzy qaq_a i qbq_b można poprowadzić linię prostą (lokalny planer geometryczny). Dla pojazdów nieholonomicznych (samochód, łódź) to nieprawda — nie da się jechać „bokiem".

Kinodynamic RRT sample'uje w przestrzeni stanu (q,q˙)TQ(q, \dot q) \in T\mathcal{Q} i propaguje przez krótki interwał dynamiką:

xnew=xnear+0Δtf(x,u)dtx_{\text{new}} = x_{\text{near}} + \int_0^{\Delta t} f(x, u) \, dt

gdzie uu losowo wybrane sterowanie. Lokalny planer jest zastąpiony przez forward simulation. Drzewo rośnie faktycznie wykonalnymi trajektoriami.

Warianty: SST (Stable Sparse RRT) — kompresuje drzewo żeby skalować się do długich horyzontów; AO-RRT — asymptotycznie optymalny kinodynamic.

Dla manipulatora Pandy: rzadko używane, bo Panda jest holonomiczna. Pojawia się gdy planujemy też dynamikę (limity przyspieszeń) — wtedy stan to (q,q˙)R14(q, \dot q) \in \mathbb{R}^{14}, sterowanie u=q¨R7u = \ddot q \in \mathbb{R}^7.

Sampling-based na Pandzie (7D C-space)

Wszystkie animacje powyżej operują na 2D — to celowe uproszczenie dla intuicji. Na realnej Pandzie:

  • QR7\mathcal{Q} \subset \mathbb{R}^7, planer próbkuje qR7q \in \mathbb{R}^7.
  • Każda iteracja: collision check Pandy w danej konfiguracji ~50 µs (FCL na mesh ogniw + scena).
  • RRT-Connect typowo znajduje ścieżkę w 0.05-0.5s na stanowisku pick&place z 2-3 przeszkodami.
  • RRT* asymptotycznie optymalny w 7D wymaga 10510610^5 - 10^6 iteracji dla zbieżności (sekundy do minut).
  • BIT* w 7D: ~1-3 sekundy dla rozwiązania bliskiego optymalnemu.

Wizualizacja drzewa 7D wymaga rzutowania (np. 2D projekcja na wybraną parę joints — najczęściej q1, q4). To zaplanowane na moduł 18 (benchmarki) gdy uruchamiamy wszystkie planery na tym samym zbiorze 50 zadań Pandy.

Ściąga

Pipeline każdego planera próbkowego

while not terminated:
  q_rand ← sample()
  q_near ← nearest(graph, q_rand)
  q_new  ← steer(q_near, q_rand, ε)
  if collision_free(q_near, q_new):
    add(graph, q_new, parent=q_near)

Gwarancje teoretyczne

  • RRT: probabilistic complete, nie-optymalny.
  • RRT*, PRM*: asymptotycznie optymalne (przy r(n) ∝ (log n/n)^(1/d)).
  • RRT-Connect: probabilistic complete, najszybszy dla single-query.
  • BIT*: asymptotycznie optymalny + szybsza zbieżność niż RRT*.

Kiedy czego użyć (Panda)

  • Pick&place w czasie rzeczywistym: RRT-Connect
  • Wymagana jakość ścieżki (transport ciężkich): RRT* lub BIT*
  • Wąskie korytarze (mocno zacieśniona scena): RRT-Connect z obstacle-based sampling lub Visibility PRM
  • Multi-query (te same przeszkody, wiele goalów): PRM*

Implementacje referencyjne

  • OMPL — wszystkie warianty + benchmarki
  • MoveIt2 — interfejs ROS2, default planer RRT-Connect
  • cuRobo — GPU batched RRT-Connect dla Pandy

Referencje

  • LaValle, „Rapidly-Exploring Random Trees: A New Tool for Path Planning" (TR 98-11, 1998) — oryginalny paper RRT.
  • Kuffner & LaValle, „RRT-Connect: An Efficient Approach to Single-Query Path Planning" (ICRA 2000).
  • Kavraki, Švestka, Latombe & Overmars, „Probabilistic Roadmaps for Path Planning in High-Dimensional Configuration Spaces" (IEEE TRA 1996) — PRM.
  • Karaman & Frazzoli, „Sampling-Based Algorithms for Optimal Motion Planning" (IJRR 2011) — RRT*, PRM*.
  • Gammell, Srinivasa & Barfoot, „Informed RRT*: Optimal Sampling-Based Path Planning Focused via Direct Sampling of an Admissible Ellipsoidal Heuristic" (IROS 2014).
  • Gammell et al., „Batch Informed Trees (BIT*)" (ICRA 2015).
  • Hsu, Jiang, Reif & Sun, „The Bridge Test for Sampling Narrow Passages with Probabilistic Roadmap Planners" (ICRA 2003).
  • OMPL docs: ompl.kavrakilab.org/planners.
  • LaValle, Planning Algorithms (CUP 2006) — rozdział 5: full sampling-based planning theory.