ECE 276B Β· Robotics Β· Project 2

3D Motion Planning

Comparing Bidirectional RRT and Weighted A* for collision-free path planning across seven challenging 3D obstacle environments.

Overview

Motion planning is the problem of finding a collision-free path from a start configuration to a goal in a space cluttered with obstacles. This project implements and compares two fundamentally different strategies β€” sampling-based (Bi-RRT) and graph-search (Weighted A*) β€” across seven 3D environments of varying complexity: a single cube, a maze, flappy-bird-style corridors, pillars, a window gap, a tower, and a room.

Collision detection uses vectorized axis-aligned bounding box (AABB) segment tests via the slab method. The improved Bi-RRT with a greedy-connect extension now successfully solves all seven environments, including topologically complex ones. However, a key trade-off remains: Bi-RRT finds significantly longer paths on narrow-passage maps (maze: 135.3 vs. A*'s 91.9), while Weighted A* reliably produces near-optimal paths at the cost of higher computation time on complex environments.

Method

🌳

Bi-directional RRT

Grows two random trees simultaneously β€” one from the start, one from the goal β€” using goal-biased sampling (pgoal = 0.05). After each extension step, a greedy-connect phase steps the opposite tree toward the new node until blocked or connected (gap < step/2). Trees swap roles each iteration for balanced growth. Fast on open spaces; finds longer paths on narrow passages.

xnew = steer(xrand, xnear, step=0.5)
⭐

Weighted A*

Searches a voxelized grid with resolution 0.5 m and 26-neighbor connectivity (±1 in each axis). The weight parameter w ∈ {1.0, 1.2, 1.5} scales the heuristic: w = 1.0 is optimal A*, higher weights trade path quality for speed. Guarantees a solution in all tested environments; slower on mazes due to exhaustive grid expansion.

f(n) = g(n) + w Β· β€–n βˆ’ goalβ€–
3D Map
AABB blocks
β†’
Sample / Grid
RRT / A*
β†’
Collision AABB
slab method
β†’
Path Graph
nodes / edges
β†’
Backtrack
goal β†’ start
β†’
Final Path
3D waypoints

Algorithm Flowcharts

Step-by-step logic for both planners, including the greedy-connect extension in Bi-RRT.

🌳 Bi-directional RRT

flowchart TD S([Start]) --> I["Init: Va ← {start}, Vb ← {goal}"] I --> L{"iter < max_iter?"} L -- No --> N([Return None]) L -- Yes --> SA["Sample q_rand\n(p=0.05 toward Vb root)"] SA --> NA["q_near_a = nearest(Va, q_rand)"] NA --> ST["q_new = steer(q_near_a, q_rand)\nstep = 0.5 m"] ST --> CF{"Inside boundary &\ncollision-free?"} CF -- "No β†’ Swap" --> L CF -- Yes --> ADD["Add q_new to Va"] ADD --> GC["Greedy-connect: step Vb β†’ q_new\nuntil blocked or gap < step/2"] GC --> CO{"Trees\nconnected?"} CO -- Yes --> P([Return Path βœ“]) CO -- No --> SW["Swap Va ↔ Vb"] SW --> L style S fill:#eff6ff,stroke:#2563eb,color:#1d4ed8 style N fill:#fef2f2,stroke:#dc2626,color:#b91c1c style P fill:#f0fdf4,stroke:#16a34a,color:#15803d style CF fill:#fffbeb,stroke:#d97706,color:#92400e style CO fill:#fffbeb,stroke:#d97706,color:#92400e style L fill:#fffbeb,stroke:#d97706,color:#92400e style ADD fill:#f0fdf4,stroke:#86efac,color:#15803d

⭐ Weighted A*

flowchart TD S([Start]) --> I["Init heap: push (wΒ·h(start), start)\ng(start) = 0"] I --> HE{"Heap\nempty?"} HE -- Yes --> N([Return None]) HE -- No --> PO["Pop cur with min f-score"] PO --> GE{"cur == goal?"} GE -- Yes --> P([Return Path βœ“]) GE -- No --> EX["For each of 26 neighbors nbr\n(Β±1 in x, y, z) Γ— res"] EX --> CF{"Collision-free?\n(AABB slab test)"} CF -- No --> MORE{"More\nneighbors?"} CF -- Yes --> TG["tentative_g = g(cur) + res"] TG --> BT{"tentative_g < g(nbr)?"} BT -- No --> MORE BT -- Yes --> UP["Update came_from(nbr), g(nbr)\nf = tentative_g + wΒ·β€–nbrβˆ’goalβ€–\nPush (f, nbr) to heap"] UP --> MORE MORE -- Yes --> EX MORE -- No --> HE style S fill:#eff6ff,stroke:#2563eb,color:#1d4ed8 style N fill:#fef2f2,stroke:#dc2626,color:#b91c1c style P fill:#f0fdf4,stroke:#16a34a,color:#15803d style HE fill:#fffbeb,stroke:#d97706,color:#92400e style GE fill:#fffbeb,stroke:#d97706,color:#92400e style CF fill:#fffbeb,stroke:#d97706,color:#92400e style BT fill:#fffbeb,stroke:#d97706,color:#92400e style MORE fill:#fffbeb,stroke:#d97706,color:#92400e style UP fill:#f0fdf4,stroke:#86efac,color:#15803d

Results

Bi-RRT vs. Weighted A* (w = 1.0) across all seven test environments. All runs successful.

Environment Bi-RRT RRT Time (s) RRT Length Weighted A* A* Time (s) A* Length
Single Cube βœ“ 0.008 8.39 βœ“ 0.010 7.98
Maze βœ“ 8.566 135.31 βœ“ 8.918 91.99
Flappy Bird βœ“ 0.074 42.69 βœ“ 2.500 28.80
Pillars βœ“ 0.010 36.23 βœ“ 0.170 32.49
Window βœ“ 0.012 28.11 βœ“ 4.183 29.72
Tower βœ“ 0.213 44.86 βœ“ 2.116 32.85
Room βœ“ 0.037 19.75 βœ“ 0.242 13.68

Weighted A* β€” effect of weight parameter on planning time and path length.

Environment w = 1.0 Time w = 1.0 Length w = 1.2 Time w = 1.2 Length w = 1.5 Time w = 1.5 Length
Single Cube0.010 s7.980.011 s7.980.010 s7.98
Maze8.918 s91.9911.086 s91.9912.757 s91.99
Flappy Bird2.500 s28.802.144 s28.801.232 s29.41
Pillars0.170 s32.490.073 s32.080.060 s31.89
Window4.183 s29.720.138 s28.680.093 s28.63
Tower2.116 s32.852.583 s32.851.149 s33.43
Room0.242 s13.680.186 s13.680.164 s13.68

Tech Stack

Python 3.10
Runtime
NumPy
Spatial computations
Matplotlib
Path visualization
Custom AABB
Vectorized collision detection

Configuration

ParameterValueDescription
max_iter500,000Bi-RRT max iterations
step_size0.5 mRRT steer & greedy-connect step
p_goal0.05Goal-bias sampling probability
connect_thrstep / 2Tree connection gap threshold
grid_res0.5 mA* voxel grid resolution
Connectivity26-neighborΒ±1 in x, y, z axes
weight w1.0 / 1.2 / 1.5A* heuristic inflation factor