You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We use A* Search, a hallmark graph algorithm in robotics, which builds upon Dijkstra's Algorithm by expanding nodes prioritized by the sum of their "cost-to-come" ($g(v): V \rightarrow \mathbb{R}$) and an estimated "cost-to-go" ($h(v): V \rightarrow \mathbb{R}$), $f(v) = g(v) + h(v)$. We take as input a graph $G(V, E)$, a source node $v_s \in V$, and a sink node $v_g \in V$.
The "cost-to-come" term $g(v)$ defines the cost of following the optimal sub-path from $v_s$ to $v \in V$. The "cost-to-go" term, also known as a heuristic $h(v)$, is an estimate of the cost to follow the optimal path from $v \in V$ to $v_g$. We ensure that A* Search is optimal and complete by using a heuristic $h(v)$ that is both admissible and consistent.
We consider $h(v)$ admissible if $\forall v \in V$, $h(v) \leq c^\star(v, v_g)$, where $c^*(v)$ is the true cost of the optimal path from $v$ to $v_g$. We consider $h(v)$ consistent if $\forall u, v \in V$ such that $e(u, v) \in E$, $h(u) \leq c(u, v) + h(v)$.
We choose $h$ as the Euclidean ($L_2$) distance. Other candidates include the Manhattan ($L_1$) distance and Diagonal or Chebyshev ($L_{\infty}$) distance.
By using A* Search with these heuristics, we will return a path $p^* = (v_s, ..., v_g)$ which minimizes the Euclidean distance traversing $e \in E$ from $v_s$ to $v_g$.
We can apply this algorithm from the source node to the sink node and from the sink node to the source node at the same time. When the two paths meet, the algorithm converges to the shortest path. With a good heuristic choice, this will improve convergence time.
Waypoint pruning
Assuming we have performed bidirectional A* and obtained a list of waypoints, we can use the Ramer–Douglas–Peucker (RDP) algorithm to reduce the number of waypoints before feeding them into a trajectory generator. The RDP algorithm simplifies a path by removing points that do not significantly contribute to the overall shape, thus reducing complexity while maintaining the path's essential form.
The RDP algorithm works as follows:
Initial Step: Given a set of waypoints $P = {p_1, p_2, \ldots, p_n}$, the algorithm starts with the first point $p_1$ and the last point $p_n$ as the initial endpoints of the simplified path.
Finding the Point of Maximum Distance: For each point $p_i$ in the set $P$, the perpendicular distance $d_i$ from the point to the line segment $p_1p_n$ is calculated. This distance is given by:
$\quad \quad$ where $\times$ denotes the cross product and $| \cdot |$ denotes the Euclidean norm.
Recursive Subdivision: Find the point $p_k$ with the maximum distance $d_k$ from the line segment $p_1p_n$. If $d_k$ is greater than a predefined threshold $\epsilon$, the algorithm keeps $p_k$ and recursively applies the same process to the segments $p_1p_k$ and $p_kp_n$. If $d_k \leq \epsilon$, all points between $p_1$ and $p_n$ are discarded.
Constructing the Simplified Path: The process is repeated recursively for each sub-segment until all points are processed. The remaining points form the simplified path.
Minimum-Snap Trajectory Generation
To generate minimum-snap trajectories, we use a $7\text{th}$ order polynomial to represent the position (in one dimension) of the quadrotor:
where $\symbf{A}_{corr}$ and $\symbf{b}_{corr}$ are the matrices associated with additional corridor constraints.
Control
Nonlinear Geometric Control
To control the robot's motion three-dimensional space, a nonlinear geometric controller is designed, with feedback coming in the form of position ($\textbf{r}$), velocity ($\dot{\textbf{r}}$), orientation $\left({}^WR_B\right)$ and angular velocity ($\symbf\omega$). The desired force necessary to command the robot's movement in $\mathbb{R}^3$, $\textbf{F}_{des}$, is given by the expression
with units of $s^{-2}$ and $s^{-1}$, respectively. The acceleration from the trajectory acts as a feedforward term, where corrections are made via the proportional controllers on position and velocity. Using equations (\ref{eqn:F_des}) and (\ref{eqn:r_ddot_des}), the thrust input $u_1$ to the quadrotor is calculated via
$$
u_1 = \textbf{b}^T_3\textbf{F}_{des}
$$
where $\textbf{b}_3 = {}^WR_B\begin{bmatrix}
0 & 0 & 1
\end{bmatrix}^T$ is the quadrotor's body z-axis expressed in the inertial frame. The input $u_1$ only provides the input necessary to keep the robot in the air, therefore a second input $u_2$ is used to change the robot's attitude. To calculate this input, a desired rotation based on a desired trajectory and input thrust is established. The input moments ($\textbf{u}_2$) drive the robot's current orientation to this desired orientation given by the expression
The body y-axis should be perpendicular to both the body x-axis and a vector which defines the yaw direction in the plane made up by the world x and y axes. The following yields an expression for the body y-axis, which ensures that the plane formed by the body z-axis and body x-axis contains the the vector defining yaw direction:
where $\psi_T$ is the yaw given by a generated trajectory. The body x-axis is computed by taking the cross product between the body y-axis and body z-axis, i.e.,
Equations (\ref{eqn:b_1_des}), (\ref{eqn:b_2_des}) and (\ref{eqn:b_3_des}) are plugged into equation \ref{eqn:R_des} to generate the desired attitude for the quadrotor. For the sake of simplicity, the superscripts and subscripts are dropped from both ${}^WR_B$ and $\left({}^WR_B\right)_{des}$. The orientation error is given by
where $\vee$ is used to vectorize a skew-symmetric matrix. Moreover, the error in angular velocity $\textbf{e}_\omega = \symbf\omega -\symbf\omega_{des}$ is computed with the desired angular velocity being set to zero (though a trajectory-based desired angular velocity can be computed by exploiting differential flatness).
with units of $s^{-2}$ and $s^{-1}$, respectively.
The gain matrix $K_p$ provides a proportional constant on the position error of the robot in $\mathbb{R}^3$, which produces large accelerations with high error and less acceleration with low error. The gain matrix $K_d$ provides a proportional constant on the velocity error of the robot $\mathbb{R}^3$, which produces a damping effect on the system's acceleration. This helps to minimize the overshoot the quadrotor experiences when following trajectories or flying towards a point.
Estimation
Unscented Kalman Filter
To estimate the quadrotor's orientation and angular velocity, we will use an unscented Kalman filter. Our filter's state is
$$
x = \begin{bmatrix}q\ \omega \end{bmatrix} \in \mathbb{R}^7
$$
where $q$ is our quaternion orientation and $\omega$ is our angular velocity. Let's define our estimate at each time-step as the mean of our distribution
$$
\mu_{k|k}\in \mathbb{R}^7
$$
Since our quaternions will always be normalized to unit length, our covariance matrix is actually
$$
\Sigma_{k|k} \in \mathbb{R}^{6\times6}
$$
In our prediction step, we start by generating sigma points via an unscented transform. We generate $2n + 1$ sigma points, where $n$ corresponds to the dimension of our covariance matrix. Due to the difference in dimension between our covariance and our mean, we update the orientation and angular rate portions of our sigma points independently.
We use Cholesky decomposition to get the matrix sqaure root for the the upper left $3\times3$ portion of the covariance, associated with the orientation and do the same for the bottom right $3\times3$ portion, associated with the angular rate. Let's call these matrices $\sqrt{\Sigma_{q}}$ and $\sqrt{\Sigma_{\omega}}$, respectively.
Since the sigma points associated with the orientation are quaternions, we must convert our representation to quaternion form. Let's define $\psi_s$ as an axis-angle representation given by
where $\sqrt{\Sigma_{q, k|k}}_{(i)}$ is the $i\text{th}$ row of the matrix $\sqrt{\Sigma_{q, k|k}}$. We then convert $\psi_s$ into the quaternion $q_{s, i}$. For the orientation portion, the first sigma points are therefore given by:
where $\Delta q_k$ is the quaternion equivalent of the axis-angle representation of $\omega_k \Delta t$. Due to part of our state being a quaternion, we use the algorithm described in this paper to compute the "quaternion mean" and "quaternion covariance". In this case, this corresponds to finding $\mu_{q, k+1|k}$ and $\Sigma_{q, k+1|k}$, respectively. For angular velocity, We simply take find the propagated mean and covariance with:
For the update step, we start by taking the propagated sigma points and propagating them through the measurement model (though generating new sigma points should also work). The measurement function is represented by:
where $q_g$ is the quaternion representation of the acceleration due to gravity vector and $\text{vec}$ represents the conversion of a quaternion object to Euclidean space. This means that $y_k \in \mathbb{R}^6$. Since no portion of our output is in quaternion space, we find
where $Q$ is the tune-able measurement covariance and the quaternion portion of $s_i - \mu_{k+1|k}$ is calculated using elements from the quaternion covariance algorithm.
Now, we compute the Kalman gain
$$
K = \Sigma_{xy} \Sigma_{yy}^{-1}
$$
and the innovation vector
$$
\text{innovation} = y_k - \hat{y}
$$
We compute the quaternion portion of $\mu_{k+1|k+1}$ by converting the upper three elements of the Kalman gain multiplied by the innovation vector to a quaternion and doing matrix multiplication. The angular velocity portion of $\mu_{k+1|k+1}$ is computed using