Week #4: Discrete Planning in Known Environments
A plan is usually “open-loop,” in the sense that it is assumed that once computed you can execute it perfectly
This is not realistic because: wind, drag, external forces, friction, unknown factors make the system diverge from the planned trajectory.
He means: why bother
estimating state and planning?
It’s too much work and could be
error-prone. Why not only have
a hierarchy of reactive
behaviors/controllers?
One possibility:
instead of u(state)=…
use u(sensory observation)=…
Graph nodes represent discrete states
Edges represent transitions/actions
Edges have weights
Potential queries:
\[ D(v) = \min_{u \in N(v)} [d(v, u) + D(u)] \]
\[ D(v_{\text{dest}}) = 0 \]
\[ D(v) = \min_{u \in N(v)} [d(v, u) + D(u)] \]
\[ D(v_{\text{dest}}) = 0 \]
Note: this should remind you
of the LQR cost-to-go update
\[ \begin{align} J_{t+1}(\mathbf{x}) &= \min_{\mathbf{u}} [g(\mathbf{x}_t, \mathbf{u}_t) + J_t(A\mathbf{x} + B\mathbf{u})] \\ J_0(\mathbf{x}) &= \mathbf{x}^T Q\mathbf{x} \end{align} \]
\[ D(v) = \min_{u \in N(v)} [d(v, u) + D(u)] \]
\[ D(v_{\text{dest}}) = 0 \]
Worst-Case
Complexity:
\(O(|V|^2)\)
In 2D grid world
\(O(|V|)\)
Let \(D(v)\) denote the length of the optimal path from the source node to node \(v\) (i.e. cost-to-come, not cost-to-go like before)
Set \(D(v) = \infty\) for all nodes except the source: \(D(v_{\text{src}}) = 0\)
Add all nodes to priority queue Q with cost-to-come as priority
While Q is not empty:
For Fibonacci heaps
\(O(|E|T_{\text{update priority}} + |V|T_{\text{remove min}}) = O(|E| + |V|\log|V|)\)
Many nodes are explored
unnecessarily. We are sure that
they are not going to be part of
the solution.
Modifies Dijkstra’s algorithm to be more efficient
Expands fewer nodes than Dijkstra’s by using a heuristic
While Dijkstra prioritizes nodes based on cost-to-come
A* prioritizes them based on:
cost-to-come to \(v\) + lower bound on cost-to-go from \(v\) to \(v_{\text{dest}}\)
Optimistic search: explore node with smallest f(v) next
Lower bound on
cost of path from
source to destination
that passes through \(v\)
Modifies Dijkstra’s algorithm to be more efficient
Expands fewer nodes than Dijkstra’s by using a heuristic
While Dijkstra prioritizes nodes based on cost-to-come
A* prioritizes them based on:
cost-to-come to \(v\) + lower bound on cost-to-go from \(v\) to \(v_{\text{dest}}\)
h() is called a heuristic. h() must be admissible, i.e. underestimate the cost-to-go from v to destination. h() must also be monotonic, i.e. satisfy the triangle inequality.
Lower bound on
cost of path from
source to destination
that passes through \(v\)
Idea: dilate obstacles to account for the ways the robot can collide with them.
Why? Instead of planning in the work space and checking whether the robot’s body collides with obstacles, plan in configuration space where you can treat the robot as a point because the obstacles are dilated.
This idea is typically not used for robots with high-dimensional states.
How do we dilate obstacles?
Minkowski Sum
\(P \oplus Q = \{p + q \mid p \in P, q \in Q\}\)
Grid-based planning works well for grids of up to 3-4 dimensions
State-space discretization suffers from combinatorial explosion:
If the state is \(x = [x_1, ... , x_D]\) and we split each dimension into N bins then we will have \(N^D\) nodes in the graph.
This is not practical for planning paths for robot arms with multiple joints, or other high-dimensional systems.
Need to find ways to reduce the continuous domain into a sparse representation: graphs, trees etc.
Today:
Rapidly-exploring Random Tree (RRT),
Probabilistic RoadMap (PRM)
Visibility Planning
Smoothing Planned Paths
Main idea: maintain a tree of reachable configurations from the root
Main steps:
Things to pay attention to:
SampleFree() needs to sample
a random state from the
uniform distribution. How do
you sample rotations uniformly?
Things to pay attention to:
Nearest() searches for the nearest
neighbor of a given vector. Brute
force search examines |V| nodes
(increasing). Is there a more
efficient method?
Things to pay attention to:
Steer() finds the controls that take the nearest state
to the new state. Easy for omnidirectional robots. What
about non-holonomic systems?
Things to pay attention to:
ObstacleFree() checks the path from the
nearest state to the new state for collisions.
How do you do collision checks?
Things to pay attention to:
Upside of using ObstacleFree(): you don’t need to model
obstacles in Steer(). For example, if Steer() computes LQR
controllers you don’t need to model obstacles in the control
computation.
Only tricky case is when the state contains rotation components
For example: \(x = [_B^Wq ^Wp_{W B}]\)
State involving both rotation and translation components is often called the pose of the system.
Idea #1: Uniformly sample 3 Euler angles (roll, pitch, yaw)
3D rotation visualization:
rotation axis is a point on a sphere,
rotation angle is the direction
of the red arrow
Idea #1
Not uniform after all
Correct, uniform
Only tricky case is when the state contains rotation components
For example: \(x = [_B^Wq ^Wp_{W B}]\)
State involving both rotation and translation components is often called the pose of the system.
Idea #1: Uniformly sample 3 Euler angles (roll, pitch, yaw)
Nonuniformity at the north pole
caused by Gimbal Lock: same rotation
parameterized by different Euler angles
Idea #1
Not uniform after all
Correct, uniform
\[ \mathbf{q} = [\sqrt{1 - u_1}\sin(2\pi u_2), \sqrt{1 - u_1}\cos(2\pi u_2), \sqrt{u_1}\sin(2\pi u_3), \sqrt{u_1}\cos(2\pi u_3)] \]
Each split is done along the median of the
points on that region
Balanced kd-tree:
Can query in O(logn)
This is an optimal control problem, but without a specified time constraint
For omnidirectional systems we can connect states by a straight line.
For more complicated systems you could use LQR.
You could also use a large set of predefined controls, one of which could be able to take the system close to the given state
Source: https://www.toptal.com/game/video-game-physics-part-ii-collision-detection-for-solid-objects
#1: The RRT will eventually cover the space, i.e. it is a space-filling tree
Source: Planning Algorithms, Lavalle
#1: The RRT will eventually cover the space, i.e. it is a space-filling tree
#2: The RRT will NOT compute the optimal path asymptotically
Source: Karaman, Frazzoli, 2010
This problem has been addressed in recent years by RRT*, BIT*, Fast-Marching Trees
#1: The RRT will eventually cover the space, i.e. it is a space-filling tree
#2: The RRT will NOT compute the optimal path asymptotically
#3: The RRT will exhibit “Voronoi bias,” i.e. new nodes will fall in free regions of Voronoi diagram (cells consist of points that are closest to a node)
#1: The RRT will eventually cover the space, i.e. it is a space-filling tree
#2: The RRT will NOT compute the optimal path asymptotically
#3: The RRT will exhibit “Voronoi bias,” i.e. new nodes will fall in free regions of Voronoi diagram
#4: The probability of RRT finding a path increases exponentially in the number of iterations
#5: The distribution of RRT’s nodes is the same as the distribution used in SampleFree()
RRTs were good for single-query path planning
You need to re-plan from scratch for every query A -> B
PRM addresses this problem
It is good for multi-query path planning
In the offline PRM
construction phase we
maintain a matrix
D[i, j] which contains the
total distance of the
shortest path from node i
to node j.
We can do this with an
all pairs shortest paths
algorithm and then
incrementally update D
as new nodes are added.
In the online PRM
query phase we
are given two endpoints
(not vertices of the graph)
and we want to find the
shortest path between them,
by making use of the matrix
D[i, j] that was precomputed
in the offline phase.
We can incorporate the
endpoints in the graph and
add 1 row and 1 column
to D
To perform a query (A->B) we need to connect A and B to the PRM.
We can do this by nearest neighbor search (kd-trees, hashing etc.)
Visibility graph
Can use graph search on visibility graph to find shortest path
Potential problem:
shortest path touches
obstacle corners. Need
to dilate obstacles.
Plans obtained from any of these planners are not going to be smooth
A plan is a sequence of states: \(\pi = (\mathbf{x}_{\text{src}}, \mathbf{x}_1, \mathbf{x}_2, \ldots, \mathbf{x}_N, \mathbf{x}_{\text{dest}})\)
We can get a smoother path \(\text{smooth}(\pi) = (\mathbf{x}_{\text{src}}, \mathbf{y}_1, \mathbf{y}_2, \ldots, \mathbf{y}_N, \mathbf{x}_{\text{dest}})\) by minimizing the following cost function
\[ f(\mathbf{y}_1, \ldots, \mathbf{y}_N) = \sum_{t=1}^{N} ||\mathbf{y}_t - \mathbf{x}_t||^2 + \alpha \sum_{t=1}^{N} ||\mathbf{y}_t - \mathbf{y}_{t-1}||^2 \]