RRT* (Rapidly-exploring Random Tree, optimal variant) grows a tree of collision-free motions from the start by repeatedly sampling a random point, steering the nearest tree node toward it by a fixed step, and — if the new edge clears every obstacle — adding it as a node. Each addition also rewires nearby nodes through it when that lowers their path cost, which is what makes the tree converge toward a near-shortest route instead of just any route. It always re-samples against the obstacles as they exist right now, so it is correct in any layout, at the cost of visibly working for it.
loop:
q_rand = sample(bias → goal)
q_near = nearest(tree, q_rand)
q_new = steer(q_near, q_rand, step)
if collisionFree(q_near, q_new):
parent = chooseBestParent(q_new, radius)
tree.add(q_new, parent)
rewireNeighbors(q_new, radius)
Learned policy stands in for a network trained on many planning episodes in this environment: instead of searching, it was fit — once, offline — to a frozen value field over the trained obstacle layout. At run time it just walks downhill along that frozen field from start to goal, a single forward pass with no search at all, which is why it answers almost instantly ("amortized" planning). The trade-off is generalization: the field only knows the obstacle positions it was trained on. Drag an obstacle and the field doesn't know — the trajectory it outputs can walk straight through the obstacle's new spot, while RRT* re-plans from scratch and is never fooled.
- Start Planning Race — runs both planners on the current obstacle layout at the same time.
- Drag obstacles — click and drag any pillar to move it; this is how you take the environment "out of distribution" for the learned policy.
- Shuffle Obstacles — quickly randomizes every pillar at once for a bigger mismatch.
- Reset — restores the original trained layout and clears both trajectories.