基于Linux微计算机BBB的飞控开发之IMU姿态解算
1. 介绍
最近在做Linux平台的飞控开发,过程中还是遇到了不少的问题,当然也学到很多东西。在我博客的四旋翼无人机开发专栏里我会分享我制作的每一个过程,希望能够帮到同样在制作飞控的小伙伴。硬件平台是Beaglebone Blue(BBB)。在看本章之前或之后,读者也可以看一看我写的另外一篇文章《基于Linux微计算机BBB的飞控开发之IMU数据获取与预处理》,看如何获取mpu9250的数据。
2. 坐标变换
2.1 坐标系
在研究无人机姿态时我们需要考虑两个坐标系,一个是地理坐标系(E系),一个是物体坐标系(b系),E系是固定不变的,而b系是随着无人机的姿态变化的。
2.1.1 E系
首先我们先定义E系,x指向北方,y指向西方,z指向天空,如图1。当然也有其它定义方式,这是为了与物体坐标系的定义相统一,减少不必要的坐标转换。
图1
2.1.2 b系
接着我们定义b系,如图2。这里x与y轴的位置与我们熟知的并不一样,看起来有点难受。我也尝试过交换x轴与y轴,但是最终还是以失败告终,至于为什么我也不太清楚,实在吃不消了,再不学课程就要挂科了`(>﹏<)′。
图2
2.1.3 IMU坐标系
最后我们再看一下mpu9250的坐标系,如图3。可以看到加速度计与陀螺仪的坐标系我们定义的b系一致,而对磁力计只需将x数据与y数据互换,z数据乘-1,就可以将mpu9250的坐标系转换到b系。
图3
2.2 坐标转换
我们知道E系是静止的,而b系是相对于E系进行旋转的。那么E系中的一个向量如何使用b系的坐标基来表示呢,比如重力加速度向量 G ⃗ \vec G G ,在E系中为(0,0,-1),在b系中是什么呢?也就是E系如何变换b系的问题。下面从两个角度来给出解决方法。
2.2.1 四元数求解变换矩阵
四元数是什么呢?四元数就是对三维旋转问题的一个数学描述。定义为
Q
⃗
\vec Q
Q =
q
0
q_0
q0 +
q
1
i
⃗
q_1\vec i
q1i +
q
2
j
⃗
q_2\vec j
q2j +
q
3
k
⃗
q_3\vec k
q3k,这里
i
⃗
\vec i
i、
j
⃗
\vec j
j、
k
⃗
\vec k
k分别为x、y、z轴上的单位向量。不过我们还是先来看看它的三角式
Q
⃗
\vec Q
Q =
c
o
s
θ
2
cos\frac{\theta} {2}
cos2θ +
u
⃗
∗
s
i
n
\vec u * sin
u∗sin
θ
2
\frac{\theta} {2}
2θ,这里
u
⃗
\vec u
u(
u
⃗
\vec u
u =
l
i
⃗
l\vec i
li +
m
j
⃗
m\vec j
mj +
n
k
⃗
n\vec k
nk)表示的旋转轴方向上的向量(一般是单位向量),表示绕
u
⃗
\vec u
u向量顺时针旋转
θ
\theta
θ角。把
u
⃗
\vec u
u带入
Q
⃗
\vec Q
Q,可以得到
Q
⃗
\vec Q
Q =
c
o
s
θ
2
cos\frac{\theta} {2}
cos2θ +
(
l
i
⃗
+
m
j
⃗
+
n
k
⃗
)
∗
s
i
n
θ
2
( l\vec i + m\vec j + n\vec k) * sin\frac{\theta} {2}
(li+mj+nk)∗sin2θ = cos
θ
2
\frac{\theta} {2}
2θ +
l
i
⃗
∗
s
i
n
θ
2
l\vec i * sin\frac{\theta} {2}
li∗sin2θ +
m
j
⃗
∗
s
i
n
θ
2
m\vec j * sin\frac{\theta} {2}
mj∗sin2θ +
n
k
⃗
∗
s
i
n
θ
2
n\vec k * sin\frac{\theta} {2}
nk∗sin2θ,令
q
0
q_0
q0 =
c
o
s
θ
2
cos\frac{\theta} {2}
cos2θ,
q
1
q_1
q1 =
l
s
i
n
θ
2
lsin\frac{\theta} {2}
lsin2θ,
q
2
q_2
q2 =
m
s
i
n
θ
2
msin\frac{\theta} {2}
msin2θ,
q
3
q_3
q3 =
n
s
i
n
θ
2
nsin\frac{\theta} {2}
nsin2θ,也就是最上面那个定义式。
了解四元数了,那么它跟变换矩阵有什么关系呢?可以证明E系到b系的变换矩阵
C
E
b
C_E^b
CEb =
(
1
−
2
(
q
2
2
+
q
3
2
)
2
(
q
0
∗
q
3
+
q
1
∗
q
2
)
2
(
q
1
∗
q
3
−
q
0
∗
q
2
)
2
(
q
1
∗
q
2
−
q
0
∗
q
3
)
1
−
2
(
q
2
2
+
q
3
2
)
2
(
q
0
∗
q
1
+
q
2
∗
q
3
)
2
(
q
0
∗
q
2
+
q
1
∗
q
3
)
2
(
q
2
∗
q
3
−
q
0
∗
q
1
)
1
−
2
(
q
2
2
+
q
1
2
)
)
\begin{pmatrix} 1 - 2(q_2^2 + q_3^2)&2(q_0 * q_3 + q_1 * q_2)&2(q_1 * q_3 - q_0 * q_2)&\\ 2(q_1 * q_2 - q_0 * q_3)&1 - 2(q_2^2 + q_3^2)&2(q_0 * q_1 + q_2 * q_3)&\\ 2(q_0 * q_2 + q_1 * q_3)&2(q_2 * q_3 - q_0 * q_1)&1 - 2(q_2^2 + q_1^2)&\end{pmatrix}
⎝⎛1−2(q22+q32)2(q1∗q2−q0∗q3)2(q0∗q2+q1∗q3)2(q0∗q3+q1∗q2)1−2(q22+q32)2(q2∗q3−q0∗q1)2(q1∗q3−q0∗q2)2(q0∗q1+q2∗q3)1−2(q22+q12)⎠⎞
注意这里的四元数是规范四元数,即
q
0
2
q_0^2
q02 +
q
1
2
q_1^2
q12 +
q
2
2
q_2^2
q22 +
q
3
2
q_3^2
q32 = 1,一般可以使用
Q
⃗
q
0
2
+
q
1
2
+
q
2
2
+
q
3
2
\frac {\vec Q} {\sqrt {q_0^2 + q_1^2 + q_2^2 + q_3^2}}
q02+q12+q22+q32Q来规范化四元数。
同样可以得到b系到E系的逆变换矩阵
C
b
E
C_b^E
CbE =
(
C
E
b
)
T
(C_E^b)^T
(CEb)T =
(
1
−
2
(
q
2
2
+
q
3
2
)
2
(
q
1
∗
q
2
−
q
0
∗
q
3
)
2
(
q
0
∗
q
2
+
q
1
∗
q
3
)
2
(
q
0
∗
q
3
+
q
1
∗
q
2
)
1
−
2
(
q
2
2
+
q
3
2
)
2
(
q
2
∗
q
3
−
q
0
∗
q
1
)
2
(
q
1
∗
q
3
−
q
0
∗
q
2
)
2
(
q
0
∗
q
1
+
q
2
∗
q
3
)
1
−
2
(
q
2
2
+
q
1
2
)
)
\begin{pmatrix} 1 - 2(q_2^2 + q_3^2)&2(q_1 * q_2 - q_0 * q_3)&2(q_0 * q_2 + q_1 * q_3)&\\ 2(q_0 * q_3 + q_1 * q_2)&1 - 2(q_2^2 + q_3^2)&2(q_2 * q_3 - q_0 * q_1)&\\ 2(q_1 * q_3 - q_0 * q_2)&2(q_0 * q_1 + q_2 * q_3)&1 - 2(q_2^2 + q_1^2)&\end{pmatrix}
⎝⎛1−2(q22+q32)2(q0∗q3+q1∗q2)2(q1∗q3−q0∗q2)2(q1∗q2−q0∗q3)1−2(q22+q32)2(q0∗q1+q2∗q3)2(q0∗q2+q1∗q3)2(q2∗q3−q0∗q1)1−2(q22+q12)⎠⎞
在回去看看我们在第二部分开头提出的问题,是不是就可以解决了,只要我们知道四元数我们就可以使用这个公式计算b系中的重力向量
Q
⃗
‘
\vec Q`
Q‘ =
C
E
b
Q
⃗
C_E^b \vec Q
CEbQ
2.2.2 欧拉角求解变换矩阵
三维坐标系中的旋转问题也可以使用欧拉角来描述,旋转可以等效成先绕z轴旋转
ψ
\psi
ψ(yaw)角度,然后绕y轴旋转
γ
\gamma
γ(pitch)角度,最后绕x轴旋转
ϕ
\phi
ϕ(roll)角度。
绕z旋转的变换矩阵
C
z
C_z
Cz =
(
c
o
s
ψ
s
i
n
ψ
0
−
s
i
n
ψ
c
o
s
ψ
0
0
0
1
)
\begin{pmatrix} cos\psi&sin\psi&0\\ -sin\psi&cos\psi&0\\ 0&0&1& \end{pmatrix}
⎝⎛cosψ−sinψ0sinψcosψ0001⎠⎞
绕y旋转的变换矩阵
C
y
C_y
Cy =
(
c
o
s
γ
0
−
s
i
n
γ
0
1
0
s
i
n
γ
0
c
o
s
γ
)
\begin{pmatrix} cos\gamma&0&-sin\gamma&\\ 0&1&0&\\ sin\gamma&0&cos\gamma& \end{pmatrix}
⎝⎛cosγ0sinγ010−sinγ0cosγ⎠⎞
绕x旋转的变换矩阵
C
x
C_x
Cx =
(
1
0
0
0
c
o
s
ϕ
s
i
n
ϕ
0
−
s
i
n
ϕ
c
o
s
ϕ
)
\begin{pmatrix} 1&0&0&\\ 0&cos\phi&sin\phi&\\ 0&-sin\phi&cos\phi& \end{pmatrix}
⎝⎛1000cosϕ−sinϕ0sinϕcosϕ⎠⎞
那么可以计算E系到b系的变换矩阵
C
E
b
C_E^b
CEb =
C
x
C
y
C
z
C_xC_yC_z
CxCyCz =
(
c
o
s
γ
c
o
s
ψ
c
o
s
γ
s
i
n
ψ
−
s
i
n
γ
−
c
o
s
ϕ
s
i
n
ψ
+
s
i
n
ϕ
s
i
n
γ
s
i
n
ψ
c
o
s
ϕ
c
o
s
ψ
+
s
i
n
ϕ
s
i
n
γ
s
i
n
ψ
s
i
n
ϕ
c
o
s
γ
s
i
n
ϕ
s
i
n
ψ
+
c
o
s
ϕ
s
i
n
γ
c
o
s
ψ
−
s
i
n
ϕ
c
o
s
ψ
+
c
o
s
ϕ
s
i
n
γ
s
i
n
ψ
c
o
s
ϕ
c
o
s
γ
)
\begin{pmatrix} cos\gamma cos\psi&cos\gamma sin\psi&-sin\gamma&\\ -cos\phi sin\psi + sin\phi sin\gamma sin\psi&cos\phi cos\psi + sin\phi sin\gamma sin\psi&sin\phi cos\gamma&\\ sin\phi sin\psi + cos\phi sin\gamma cos\psi&-sin\phi cos\psi + cos\phi sin\gamma sin\psi&cos\phi cos\gamma& \end{pmatrix}
⎝⎛cosγcosψ−cosϕsinψ+sinϕsinγsinψsinϕsinψ+cosϕsinγcosψcosγsinψcosϕcosψ+sinϕsinγsinψ−sinϕcosψ+cosϕsinγsinψ−sinγsinϕcosγcosϕcosγ⎠⎞
而b系到E系的变换矩阵
C
b
E
C_b^E
CbE =
(
C
E
b
)
T
(C_E^b)^T
(CEb)T =
(
c
o
s
γ
c
o
s
ψ
−
c
o
s
ϕ
s
i
n
ψ
+
s
i
n
ϕ
s
i
n
γ
s
i
n
ψ
s
i
n
ϕ
s
i
n
ψ
+
c
o
s
ϕ
s
i
n
γ
c
o
s
ψ
c
o
s
γ
s
i
n
ψ
c
o
s
ϕ
c
o
s
ψ
+
s
i
n
ϕ
s
i
n
γ
s
i
n
ψ
−
s
i
n
ϕ
c
o
s
ψ
+
c
o
s
ϕ
s
i
n
γ
s
i
n
ψ
−
s
i
n
γ
s
i
n
ϕ
c
o
s
γ
c
o
s
ϕ
c
o
s
γ
)
\begin{pmatrix} cos\gamma cos\psi&-cos\phi sin\psi + sin\phi sin\gamma sin\psi&sin\phi sin\psi + cos\phi sin\gamma cos\psi&\\ cos\gamma sin\psi&cos\phi cos\psi + sin\phi sin\gamma sin\psi&-sin\phi cos\psi + cos\phi sin\gamma sin\psi&\\ -sin\gamma&sin\phi cos\gamma&cos\phi cos\gamma& \end{pmatrix}
⎝⎛cosγcosψcosγsinψ−sinγ−cosϕsinψ+sinϕsinγsinψcosϕcosψ+sinϕsinγsinψsinϕcosγsinϕsinψ+cosϕsinγcosψ−sinϕcosψ+cosϕsinγsinψcosϕcosγ⎠⎞
到这里,开头提出的问题我们也可以使用这里的矩阵来计算,但是显然
s
i
n
sin
sin与
c
o
s
cos
cos的计算复杂度与简单乘法完全不是层次,所以在进行坐标转换时还是使用2.2.1提出的矩阵来计算比较简单。
3. Mahony算法解算姿态
前面我们说欧拉角和四元数都可以用来描述三维旋转,并且提出了两种方式对应的变换矩阵。其实我们只要能够求出欧拉角和四元数中的一个就可以完成姿态解算。实际上下面我们是直接求解四元数,最终会用四元数计算欧拉角。四元数便于解算姿态,而欧拉角看起来更明白,在控制上使用起来更简单。下面介绍的就是Mahony算法,当然还有其它算法,但是在大部分飞控软件都是使用的这种Mahony算法,可能是比较简单吧。Ardupoilot就是用的这个算法,另外在使用了Mahony算法之后他还用了卡尔曼滤波(EKF),但我已经无力再学了。实际上,我把Ardopoilt的EKF关掉之后,发现姿态解算的效果并没有显著的差别。
3.1 使用四元数计算欧拉角
我们到过来说吧,假如我们已经计算出了四元数,那怎么用四元数计算欧拉角呢?
第二部分我们已经给出了两种计算变换矩阵的方法。如
C
b
E
C_b^E
CbE =
(
1
−
2
(
q
2
2
+
q
3
2
)
2
(
q
1
∗
q
2
−
q
0
∗
q
3
)
2
(
q
0
∗
q
2
+
q
1
∗
q
3
)
2
(
q
0
∗
q
3
+
q
1
∗
q
2
)
1
−
2
(
q
2
2
+
q
3
2
)
2
(
q
2
∗
q
3
−
q
0
∗
q
1
)
2
(
q
1
∗
q
3
−
q
0
∗
q
2
)
2
(
q
0
∗
q
1
+
q
2
∗
q
3
)
1
−
2
(
q
2
2
+
q
1
2
)
)
\begin{pmatrix} 1 - 2(q_2^2 + q_3^2)&2(q_1 * q_2 - q_0 * q_3)&2(q_0 * q_2 + q_1 * q_3)&\\ 2(q_0 * q_3 + q_1 * q_2)&1 - 2(q_2^2 + q_3^2)&2(q_2 * q_3 - q_0 * q_1)&\\ 2(q_1 * q_3 - q_0 * q_2)&2(q_0 * q_1 + q_2 * q_3)&1 - 2(q_2^2 + q_1^2)&\end{pmatrix}
⎝⎛1−2(q22+q32)2(q0∗q3+q1∗q2)2(q1∗q3−q0∗q2)2(q1∗q2−q0∗q3)1−2(q22+q32)2(q0∗q1+q2∗q3)2(q0∗q2+q1∗q3)2(q2∗q3−q0∗q1)1−2(q22+q12)⎠⎞ =
(
c
o
s
γ
c
o
s
ψ
−
c
o
s
ϕ
s
i
n
ψ
+
s
i
n
ϕ
s
i
n
γ
s
i
n
ψ
s
i
n
ϕ
s
i
n
ψ
+
c
o
s
ϕ
s
i
n
γ
c
o
s
ψ
c
o
s
γ
s
i
n
ψ
c
o
s
ϕ
c
o
s
ψ
+
s
i
n
ϕ
s
i
n
γ
s
i
n
ψ
−
s
i
n
ϕ
c
o
s
ψ
+
c
o
s
ϕ
s
i
n
γ
s
i
n
ψ
−
s
i
n
γ
s
i
n
ϕ
c
o
s
γ
c
o
s
ϕ
c
o
s
γ
)
\begin{pmatrix} cos\gamma cos\psi&-cos\phi sin\psi + sin\phi sin\gamma sin\psi&sin\phi sin\psi + cos\phi sin\gamma cos\psi&\\ cos\gamma sin\psi&cos\phi cos\psi + sin\phi sin\gamma sin\psi&-sin\phi cos\psi + cos\phi sin\gamma sin\psi&\\ -sin\gamma&sin\phi cos\gamma&cos\phi cos\gamma& \end{pmatrix}
⎝⎛cosγcosψcosγsinψ−sinγ−cosϕsinψ+sinϕsinγsinψcosϕcosψ+sinϕsinγsinψsinϕcosγsinϕsinψ+cosϕsinγcosψ−sinϕcosψ+cosϕsinγsinψcosϕcosγ⎠⎞
上面的矩阵应该各项相等,即:
−
s
i
n
γ
-sin\gamma
−sinγ =
2
(
q
1
∗
q
3
−
q
0
∗
q
2
)
2(q_1 * q_3 - q_0 * q_2)
2(q1∗q3−q0∗q2)
c
o
s
γ
c
o
s
ψ
cos\gamma cos\psi
cosγcosψ =
1
−
2
(
q
2
2
+
q
3
2
)
1 - 2(q_2^2 + q_3^2)
1−2(q22+q32)
c
o
s
γ
s
i
n
ψ
cos\gamma sin\psi
cosγsinψ =
2
(
q
0
∗
q
3
+
q
1
∗
q
2
)
2(q_0 * q_3 + q_1 * q_2)
2(q0∗q3+q1∗q2)
s
i
n
ϕ
c
o
s
γ
sin\phi cos\gamma
sinϕcosγ =
2
(
q
0
∗
q
1
+
q
2
∗
q
3
)
2(q_0 * q_1 + q_2 * q_3)
2(q0∗q1+q2∗q3)
c
o
s
ϕ
c
o
s
γ
cos\phi cos\gamma
cosϕcosγ =
1
−
2
(
q
2
2
+
q
1
2
)
1 - 2(q_2^2 + q_1^2)
1−2(q22+q12)
就可以解得欧拉角
γ
(
p
i
t
c
h
)
、
ϕ
(
r
o
l
l
)
、
ψ
(
y
a
w
)
\gamma(pitch)、\phi(roll)、\psi(yaw)
γ(pitch)、ϕ(roll)、ψ(yaw):
γ
\gamma
γ =
−
a
r
c
s
i
n
(
2
(
q
1
∗
q
3
−
q
0
∗
q
2
)
)
-arcsin(2(q_1 * q_3 - q_0 * q_2))
−arcsin(2(q1∗q3−q0∗q2))
ϕ
\phi
ϕ =
a
r
c
t
a
n
(
2
(
q
0
∗
q
1
+
q
2
∗
q
3
)
1
−
2
(
q
2
2
+
q
1
2
)
)
arctan(\frac {2(q_0 * q_1 + q_2 * q_3)} {1 - 2(q_2^2 + q_1^2)})
arctan(1−2(q22+q12)2(q0∗q1+q2∗q3))
ψ
\psi
ψ =
a
r
c
t
a
n
(
2
(
q
0
∗
q
3
+
q
1
∗
q
2
)
1
−
2
(
q
2
2
+
q
3
2
)
)
arctan(\frac {2(q_0 * q_3 + q_1 * q_2)} {1 - 2(q_2^2 + q_3^2)})
arctan(1−2(q22+q32)2(q0∗q3+q1∗q2))
3.2 计算四元数
上面的计算都是在四元数已知的条件下,那么如何求解四元数呢?
这时候mpu9250就派上用场了。
3.2.1 四元数微分
我们对四元数
Q
⃗
\vec Q
Q =
c
o
s
θ
2
+
u
⃗
∗
s
i
n
θ
2
cos\frac{\theta} {2} + \vec u * sin\frac{\theta} {2}
cos2θ+u∗sin2θ求微分:
d
Q
⃗
d
t
=
−
d
θ
2
d
t
∗
s
i
n
θ
2
+
d
u
⃗
d
t
∗
s
i
n
θ
2
+
u
⃗
∗
d
θ
2
d
t
∗
c
o
s
θ
2
\frac {d\vec Q} {dt} = -\frac {d\theta} {2dt} * sin\frac {\theta} {2} + \frac {d\vec u} {dt} * sin\frac {\theta} {2} + \vec u * \frac {d\theta} {2dt} * cos\frac {\theta} {2}
dtdQ=−2dtdθ∗sin2θ+dtdu∗sin2θ+u∗2dtdθ∗cos2θ
因为
u
⃗
∗
u
⃗
\vec u* \vec u
u∗u = -1,所以上式可以继续化为:
d
Q
⃗
d
t
=
u
⃗
∗
u
⃗
∗
d
θ
2
d
t
∗
s
i
n
θ
2
+
d
u
⃗
d
t
∗
s
i
n
θ
2
+
u
⃗
∗
d
θ
2
d
t
∗
c
o
s
θ
2
\frac {d\vec Q} {dt} = \vec u * \vec u * \frac {d\theta} {2dt} * sin\frac {\theta} {2} + \frac {d\vec u} {dt} * sin\frac {\theta} {2} + \vec u * \frac {d\theta} {2dt} * cos\frac {\theta} {2}
dtdQ=u∗u∗2dtdθ∗sin2θ+dtdu∗sin2θ+u∗2dtdθ∗cos2θ
=
u
⃗
∗
d
θ
2
d
t
∗
(
c
o
s
θ
2
+
u
⃗
∗
s
i
n
θ
2
)
+
d
u
⃗
d
t
∗
s
i
n
θ
2
\vec u * \frac {d\theta} {2dt} * (cos\frac{\theta} {2} + \vec u * sin\frac{\theta} {2}) + \frac {d\vec u} {dt} * sin\frac {\theta} {2}
u∗2dtdθ∗(cos2θ+u∗sin2θ)+dtdu∗sin2θ
=
u
⃗
∗
d
θ
2
d
t
∗
Q
⃗
+
d
u
⃗
d
t
∗
s
i
n
θ
2
\vec u * \frac {d\theta} {2dt} * \vec Q + \frac {d\vec u} {dt} * sin\frac {\theta} {2}
u∗2dtdθ∗Q+dtdu∗sin2θ
我们知道飞机在某一段很短的时刻是绕着同一个轴在旋转的,也就是说在某一一段时间内
u
⃗
\vec u
u是一个常量,导数为0。转轴发生的变化是阶跃式的变化,可以忽略不计,所以
d
u
⃗
d
t
\frac {d\vec u} {dt}
dtdu = 0。
另外
u
⃗
∗
d
θ
d
t
\vec u * \frac {d\theta} {dt}
u∗dtdθ的实际意义就是将绕
u
⃗
\vec u
u旋转的角速度分解为E系中的x、y、z轴的角速度,我们记
ω
⃗
E
\vec \omega_E
ωE =
u
⃗
∗
d
θ
d
t
\vec u * \frac {d\theta} {dt}
u∗dtdθ
则上式可以改写为:
d
Q
⃗
d
t
=
1
2
ω
⃗
E
∗
Q
⃗
\frac {d\vec Q} {dt} = \frac {1} {2}\vec \omega^E * \vec Q
dtdQ=21ωE∗Q
可以证明
ω
⃗
b
=
Q
⃗
∗
∗
ω
⃗
E
∗
Q
⃗
\vec \omega^b = \vec Q^* * \vec \omega^E * \vec Q
ωb=Q∗∗ωE∗Q,且
ω
⃗
b
=
ω
x
b
∗
i
⃗
+
ω
y
b
∗
j
⃗
+
ω
z
b
∗
z
⃗
\vec \omega^b = \omega_x^b * \vec i + \omega_y^b * \vec j + \omega_z^b * \vec z
ωb=ωxb∗i+ωyb∗j+ωzb∗z
所以上式可以继续改写为:
d
Q
⃗
d
t
=
1
2
Q
⃗
∗
ω
⃗
b
=
1
2
(
0
−
ω
x
b
−
ω
y
b
−
ω
z
b
ω
x
b
0
ω
z
b
−
ω
y
b
ω
y
b
−
ω
z
b
0
ω
x
b
ω
z
b
ω
y
b
−
ω
x
b
0
)
(
q
0
q
1
q
2
q
3
)
\frac {d\vec Q} {dt} = \frac {1} {2} \vec Q * \vec \omega^b = \frac {1} {2} \begin{pmatrix} 0&-\omega_x^b &-\omega_y^b &-\omega_z^b \\ \omega_x^b &0&\omega_z^b &-\omega_y^b \\ \omega_y^b &-\omega_z^b &0&\omega_x^b \\ \omega_z^b &\omega_y^b &-\omega_x^b &0\end{pmatrix} \begin{pmatrix} q_0\\ q_1\\ q_2\\ q_3 \end{pmatrix}
dtdQ=21Q∗ωb=21⎝⎜⎜⎛0ωxbωybωzb−ωxb0−ωzbωyb−ωybωzb0−ωxb−ωzb−ωybωxb0⎠⎟⎟⎞⎝⎜⎜⎛q0q1q2q3⎠⎟⎟⎞
好了,到这里我们已经求出四元数微分了,下面我们积分一下就可以成功的求解出四元数了。
3.2.2 由四元数微分求解四元数
这里就很简单了,我们只需要把上面的微分方程两边积分一下就好了,得到下面的公式:
Q
⃗
t
+
Δ
t
=
Q
⃗
t
+
1
2
∗
(
0
−
ω
x
b
−
ω
y
b
−
ω
z
b
ω
x
b
0
ω
z
b
−
ω
y
b
ω
y
b
−
ω
z
b
0
ω
x
b
ω
z
b
ω
y
b
−
ω
x
b
0
)
∗
(
q
0
q
1
q
2
q
3
)
t
\vec Q_{t + \Delta t} = \vec Q_t + \frac {1} {2} * \begin{pmatrix} 0&-\omega_x^b &-\omega_y^b &-\omega_z^b \\ \omega_x^b &0&\omega_z^b &-\omega_y^b \\ \omega_y^b &-\omega_z^b &0&\omega_x^b \\ \omega_z^b &\omega_y^b &-\omega_x^b &0\end{pmatrix} * \begin{pmatrix} q_0\\ q_1\\ q_2\\ q_3 \end{pmatrix}_t
Qt+Δt=Qt+21∗⎝⎜⎜⎛0ωxbωybωzb−ωxb0−ωzbωyb−ωybωzb0−ωxb−ωzb−ωybωxb0⎠⎟⎟⎞∗⎝⎜⎜⎛q0q1q2q3⎠⎟⎟⎞t
即:
(
q
0
q
1
q
2
q
3
)
t
+
Δ
t
=
(
q
0
q
1
q
2
q
3
)
t
+
1
2
(
0
−
ω
x
b
−
ω
y
b
−
ω
z
b
ω
x
b
0
ω
z
b
−
ω
y
b
ω
y
b
−
ω
z
b
0
ω
x
b
ω
z
b
ω
y
b
−
ω
x
b
0
)
(
q
0
q
1
q
2
q
3
)
t
∗
Δ
t
\begin{pmatrix} q_0\\ q_1\\ q_2\\ q_3 \end{pmatrix}_{t + \Delta t} = \begin{pmatrix} q_0\\ q_1\\ q_2\\ q_3 \end{pmatrix}_t + \frac {1} {2} \begin{pmatrix} 0&-\omega_x^b &-\omega_y^b &-\omega_z^b \\ \omega_x^b &0&\omega_z^b &-\omega_y^b \\ \omega_y^b &-\omega_z^b &0&\omega_x^b \\ \omega_z^b &\omega_y^b &-\omega_x^b &0\end{pmatrix} \begin{pmatrix} q_0\\ q_1\\ q_2\\ q_3 \end{pmatrix}_t * \Delta t
⎝⎜⎜⎛q0q1q2q3⎠⎟⎟⎞t+Δt=⎝⎜⎜⎛q0q1q2q3⎠⎟⎟⎞t+21⎝⎜⎜⎛0ωxbωybωzb−ωxb0−ωzbωyb−ωybωzb0−ωxb−ωzb−ωybωxb0⎠⎟⎟⎞⎝⎜⎜⎛q0q1q2q3⎠⎟⎟⎞t∗Δt
这里的
ω
x
b
、
ω
y
b
、
ω
z
b
\omega_x^b、\omega_y^b、\omega_z^b
ωxb、ωyb、ωzb就是b系下各轴的角速度(弧度制)。
一开始我们假设四元数的初始值
Q
⃗
0
=
(
1
0
0
0
)
\vec Q_0 = \begin{pmatrix} 1\\ 0 \\ 0 \\ 0\end{pmatrix}
Q0=⎝⎜⎜⎛1000⎠⎟⎟⎞,然后用上面的公式一直迭代下去就可以获得每个时刻的四元数。当然求解完,一定要记得规范化一下。由于误差的存在可能会导致四元数不再是规范四元数。
ok,到这里我们已经完成了几乎所有的工作。回想一下,我们由mpu9250的陀螺仪的角速度计算出四元数之后,我们就可以计算出欧拉角,也可以用变换矩阵计算b系中的重力向量。
4. 陀螺仪的修正
我们虽然已经求出了四元数,但是其实我们在实际求解的过程中不是准确无误的。首先陀螺仪由于自身特性和噪声影响会产生一定的误差;其次积分的时候
Δ
t
\Delta t
Δt并不可能无穷小,实际上会取0.002s或者0.0025这些数值,在
Δ
t
\Delta t
Δt内角速度只能测量一次或至少有限次,所以这样就会产生一定的误差。这些误差短时间内不会有什么影响,但是由于积分效应,误差会越来越大。因而我们要去对这些误差进行一些修正。这里我们其实是使用PI控制器进行修正。如下图。陀螺仪属于正反馈,而磁力计与加速度计属于负反馈,我们对负反馈的误差进行比例放大和积分,修正陀螺仪的输出数据,进而修正四元数。下面提供了两种修正方式。
图4(该图来自于_Summer__的博客)
4.1 加速度计补偿
在我的另外一篇文章《基于Linux微计算机BBB的飞控开发之IMU数据获取与预处理》里面我们已经获取了加速度计的数据。我们假设加速度计数据向量
A
⃗
r
a
w
=
(
a
x
a
y
a
z
)
\vec A_{raw} = \begin{pmatrix} a_x\\ a_y\\ a_z\end{pmatrix}
Araw=⎝⎛axayaz⎠⎞,我们把它规范化一下,即:
A
⃗
=
A
⃗
r
a
w
a
x
2
+
a
y
2
+
A
z
2
\vec A = \frac {\vec A_{raw}} {\sqrt {a_x^2 + a_y^2 + A_z^2}}
A=ax2+ay2+Az2Araw。在静止或匀速直线运动状态下,
A
⃗
\vec A
A向量就是b系下的重力向量(这里的重力向量实际上是竖直指向天空的,而不是竖直指向地下的,这跟我们的理解不一样,读者要特别注意)。可以说加速度计算出的重力向量是比较精确的,我们把它作为一个实际值看待。
前面说到由变换矩阵可以将E系中的重力向量
G
⃗
(
0
,
0
,
1
)
\vec G(0,0,1)
G(0,0,1)(为什么是1不是-1的原因在上一段提到了)变换b系中,即
G
⃗
‘
=
C
E
b
G
⃗
\vec G` = C_E^b \vec G
G‘=CEbG,
G
⃗
‘
\vec G`
G‘就是b系下的重力向量,只不过这是一个理论值,是由四元数求解出来的,是有一定误差的。
那么现在,我们用理论值与实际值作比较,求解出误差向量
E
⃗
\vec E
E,求解方法就是叉乘。即:
E
⃗
=
G
⃗
‘
∗
A
⃗
\vec E = \vec G` * \vec A
E=G‘∗A
读者有没有疑问,为什么叉乘可以计算出误差?实际上,我们想一下,
E
⃗
\vec E
E是不是就是垂直于
A
⃗
、
G
⃗
‘
\vec A 、\vec G`
A、G‘,而
E
⃗
\vec E
E的模是不是就是
A
⃗
、
G
⃗
‘
\vec A 、\vec G`
A、G‘两个向量围成的平行四边形面积。两个单位向量形成的面积一定程度上可以描述两个向量之间的差距,这个最终体现在
E
⃗
\vec E
E的模上。再想一想,既然
E
⃗
\vec E
E垂直于这两个向量,那么我是不是只要让
G
⃗
‘
\vec G`
G‘绕着这个
E
⃗
\vec E
E旋转一个与
E
⃗
\vec E
E的模相关的角度就可以使得
G
⃗
‘
\vec G`
G‘与
A
⃗
\vec A
A重合。那么绕着
E
⃗
\vec E
E旋转一个与
E
⃗
\vec E
E的模相关的角度如何实现呢?实际上
E
⃗
\vec E
E在b系各个坐标轴的投影长度就对应了各个轴角速度应该减去的修正值。绕单位向量
n
⃗
\vec n
n旋转
θ
\theta
θ可以使用这个公式分解为各个轴的角速度:
ω
x
b
∗
i
⃗
+
ω
y
b
∗
j
⃗
+
ω
z
b
∗
k
⃗
=
n
⃗
∗
θ
\omega_x^b * \vec i + \omega_y^b * \vec j + \omega_z^b * \vec k = \vec n * \theta
ωxb∗i+ωyb∗j+ωzb∗k=n∗θ。
描述修正过程的公式如下:
G
⃗
=
(
0
0
1
)
\vec G = \begin{pmatrix} 0\\ 0\\ 1\end{pmatrix}
G=⎝⎛001⎠⎞
A
⃗
r
a
w
=
(
a
x
b
a
y
b
a
z
b
)
\vec A_{raw} = \begin{pmatrix} a_x^b\\ a_y^b\\ a_z^b\end{pmatrix}
Araw=⎝⎛axbaybazb⎠⎞
ω
⃗
r
a
w
b
=
(
ω
x
b
ω
y
b
ω
z
b
)
\vec \omega_{raw}^b = \begin{pmatrix} \omega_x^b\\ \omega_y^b\\ \omega_z^b\end{pmatrix}
ωrawb=⎝⎛ωxbωybωzb⎠⎞
A
⃗
=
A
⃗
r
a
w
a
x
2
+
a
y
2
+
A
z
2
\vec A = \frac {\vec A_{raw}} {\sqrt {a_x^2 + a_y^2 + A_z^2}}
A=ax2+ay2+Az2Araw
G
⃗
‘
=
C
E
b
G
⃗
\vec G` = C_E^b \vec G
G‘=CEbG
E
⃗
=
G
⃗
‘
∗
A
⃗
\vec E = \vec G` * \vec A
E=G‘∗A
ω
⃗
c
o
r
r
e
c
t
i
o
n
b
=
ω
⃗
r
a
w
b
−
k
p
∗
E
⃗
−
k
i
∗
∑
i
=
0
n
E
⃗
\vec \omega_{correction}^b = \vec \omega_{raw}^b - kp * \vec E - ki * \sum_{i=0} ^{n} \vec E
ωcorrectionb=ωrawb−kp∗E−ki∗∑i=0nE
最终
ω
⃗
c
o
r
r
e
c
t
i
o
n
b
\vec \omega_{correction}^b
ωcorrectionb作为四元数积分的输入值。就可以达到修正的目的。当然,
k
p
与
k
i
kp 与ki
kp与ki的取值对修正的效果是有一定影响的。注意只有在静止或匀速直线运动下才可以修正,加速和圆周运动下,加速度计中混入了其它加速度,加速度计数据向量并不是垂直指向地下的,也就是
4000
<
∣
A
⃗
r
a
w
∣
<
4150
4000< |\vec A_{raw}| < 4150
4000<∣Araw∣<4150,因为加速度计在静止状态测出的重力向量的模为4096,所以笔者设置了这样一个范围,读者可以根据需要调整范围。
4.2 磁力计补偿
加速度只能修补
p
i
t
c
h
和
r
o
l
l
pitch 和roll
pitch和roll,至于为什么读者可以将IMU绕着E系的z轴旋转,看加速度计数据向量是否有明显变化,加速度计是无法反应yaw的。所以还需要磁力计来专门修正yaw。磁力计补偿的原理与加速度补偿类似,仅有一点点区别,下面直接以公式说明修正方法。
因为磁场是从北指向南,而我们定义的E系的x轴是指向北,所以磁力在E系xoy上的投影向量:
M
⃗
=
(
−
1
0
)
\vec M = \begin{pmatrix} -1\\ 0\end{pmatrix}
M=(−10)
磁力计数据向量:
m
⃗
b
=
(
m
x
b
m
y
b
m
z
b
)
\vec m^b = \begin{pmatrix} m_x^b\\ m_y^b\\ m_z^b\end{pmatrix}
mb=⎝⎛mxbmybmzb⎠⎞
我们把
m
⃗
b
\vec m^b
mb转换到E系:
m
⃗
E
=
C
b
E
(
m
x
E
m
x
E
m
x
E
)
\vec m^E = C_b^E\begin{pmatrix} m_x^E\\ m_x^E\\ m_x^E\end{pmatrix}
mE=CbE⎝⎛mxEmxEmxE⎠⎞
取投影值:
m
⃗
x
y
E
=
(
m
x
E
m
x
E
)
\vec m_{xy}^E = \begin{pmatrix} m_x^E\\ m_x^E\end{pmatrix}
mxyE=(mxEmxE)
与实际值
M
⃗
\vec M
M做叉乘:
e
r
r
o
r
=
m
⃗
x
y
E
∗
M
⃗
=
s
i
n
<
m
⃗
x
y
E
,
M
⃗
>
=
s
i
n
(
y
a
w
e
r
r
o
r
)
error = \vec m_{xy}^E * \vec M = sin<\vec m_{xy}^E,\vec M> = sin(yaw_{error})
error=mxyE∗M=sin<mxyE,M>=sin(yawerror)
则:
y
a
w
e
r
r
o
r
=
a
r
c
s
i
n
(
m
⃗
x
y
E
∗
M
⃗
)
yaw_{error} = arcsin(\vec m_{xy}^E * \vec M)
yawerror=arcsin(mxyE∗M)
这里得到的是实际的yaw与四元数计算出来的yaw得偏差,要修正这个偏差,实际上就是要绕重力向量旋转
y
a
w
e
r
r
o
r
yaw_{error}
yawerror这样一个角度,在加速度修正的基础上继续做出如下修正:
ω
⃗
c
o
r
r
e
c
t
i
o
n
b
=
ω
⃗
c
o
r
r
e
c
t
i
o
n
b
−
k
p
∗
G
⃗
‘
∗
y
a
w
e
r
r
o
r
\vec \omega_{correction}^b = \vec \omega_{correction}^b - kp * \vec G`* yaw_{error}
ωcorrectionb=ωcorrectionb−kp∗G‘∗yawerror
这里
k
p
kp
kp与加速度计的
k
p
kp
kp并不一样,具体还需要实际的测试调整。
哇,终于写到最后了,最后我们只需要用这个修正的角速度去计算四元数就可以达到修正陀螺仪误差的作用。
上面的计算过程我经过实测。理论上我并不是很懂,最近才接触飞控的,所以有什么错的地方还望读者指正。