四旋翼无人机动力学模型及控制

2023-05-16

四旋翼无人机动力学模型及控制 I: 欧拉角与旋转矩阵

  • Overview
  • 欧拉角与旋转矩阵
  • Body Frame Angular Velocity and [ ϕ ˙ , θ ˙ , ψ ˙ ] T [\dot{\phi}, \dot{\theta}, \dot{\psi}]^T [ϕ˙,θ˙,ψ˙]T
  • 小结

Overview

我想通过这个系列的笔记,给大家分享关于四旋翼无人机的控制基础知识 (其中包括一些前沿的论文导读)。主要的思路如下:

  1. 先从robotics的基础—欧拉角与旋转矩阵开始,引入四旋翼无人机的控制动力学模型。然后通过matlab实现简单的控制算法。
  2. 介绍旋转矩阵的gimbal lock(死锁/万象锁)问题,同时介绍目前robotics旋转建模中最受欢迎的模型:quaternion(四元数)。以及对应的matlab代码(如何通过quaternion修改对四旋翼无人机的建模,并做简单控制)。
  3. 四旋翼无人机differential flatness(微分平坦)的详细推导,以及如何利用微分平坦特性进行控制。

以上的知识点在很多其它文章/百科里面都有提到,我只是想把它们系统的整理结合起来,通过我认为容易理解的方式呈现出来,同时分享如何用简单的代码实现。我会尽可能的引用我能找到的原文出处。内容估计有不严谨的地方,希望跟大家一起学习交流。

我们这一篇,就从欧拉角与旋转矩阵开始。

欧拉角与旋转矩阵

就拿无人机来说,想要表示它在 R 3 \mathbb{R}^3 R3中的旋转,我们可以首先定义三个轴(Z-Y-X)如下图Fig. 1所示。

Fig. 1

Fradi, H., Bracco, L., Canino, F. and Dugelay, J.L., 2018, September. Autonomous person detection and tracking framework using unmanned aerial vehicles (UAVs). In 2018 26th European Signal Processing Conference (EUSIPCO) (pp. 1047-1051). IEEE.

我们可以把X轴想象成鸟的躯干,Y轴是鸟的翅膀,Z轴从下往上垂直穿过鸟的身体平面。有旋转,就一定要有一个参考坐标系(第三人称视角坐标) N e x {}_N\mathbf{e}_x Nex, N e y {}_N\mathbf{e}_y Ney, N e z {}_N\mathbf{e}_z Nez。我们定义当前位置大地地面正北方为 N e x = [ 1 , 0 , 0 ] T {}_N\mathbf{e}_x=[1,0,0]^T Nex=[1,0,0]T,正东方为 N e y = [ 0 , 1 , 0 ] T {}_N\mathbf{e}_y=[0,1,0]^T Ney=[0,1,0]T,垂直地面正上方为 N e z = [ 0 , 0 , 1 ] T {}_N\mathbf{e}_z=[0,0,1]^T Nez=[0,0,1]T

定义好全局参考系(global frame)之后,我们需要定义本地参考系(body frame),也就是第一人称视角坐标。鸟躯干为 B e x = [ 1 , 0 , 0 ] T {}_B\mathbf{e}_x=[1,0,0]^T Bex=[1,0,0]T,头为正方向。鸟翅膀为 B e y = [ 0 , 1 , 0 ] T {}_B\mathbf{e}_y=[0,1,0]^T Bey=[0,1,0]T, 右手为正方向。 B e z = [ 0 , 0 , 1 ] T {}_B\mathbf{e}_z=[0,0,1]^T Bez=[0,0,1]T从下往上垂直穿过鸟身体平面。

到这里有人会问,你的 N e x {}_N\mathbf{e}_x Nex B e x {}_B\mathbf{e}_x Bex都用 [ 1 , 0 , 0 ] T [1,0,0]^T [1,0,0]T表示(另外两轴也同理),那怎么去区分呢?其实它们表示的是在各自视角下的方向,我们先不考虑位移(假设两个坐标系原点重合),那么只有当这只鸟头冲北,右翅膀朝东,身体平行地面的时候,两个坐标系才一致。我们假设这只鸟身体还是平行地面( N e z = B e z {}_N\mathbf{e}_z={}_B\mathbf{e}_z Nez=Bez),但是头逆时针旋转了 ψ = 3 0 ∘ \psi=30^{\circ} ψ=30,此时从第三人称视角看过去,鸟的头方向 B e x = [ 1 , 0 , 0 ] T {}_B\mathbf{e}_x=[1,0,0]^T Bex=[1,0,0]T变成多少呢?我们画一个从上往下的俯视图Fig. 2

Fig. 2

很明显,此时如果一个向量 m \mathbf{m} m在body frame下面写为:

  1. B m = [ B m x , 0 , 0 ] T {}_B\mathbf{m}=[{}_Bm_x,0,0]^T Bm=[Bmx,0,0]T, 那么在global frame下面就可以看做 N m = [ B m x ⋅ c o s ψ , B m x ⋅ s i n ψ , 0 ] T {}_N\mathbf{m}=[{}_Bm_x \cdot cos\psi, {}_Bm_x \cdot sin\psi, 0]^T Nm=[Bmxcosψ,Bmxsinψ,0]T
  2. B m = [ 0 , B m y , 0 ] T {}_B\mathbf{m}=[0,{}_Bm_y,0]^T Bm=[0,Bmy,0]T,那么 N m = [ B m x ⋅ − s i n ψ , B m x ⋅ c o s ψ , 0 ] T {}_N\mathbf{m}=[{}_Bm_x \cdot -sin\psi, {}_Bm_x \cdot cos\psi, 0]^T Nm=[Bmxsinψ,Bmxcosψ,0]T
  3. B m = [ 0 , 0 , B m z ] T {}_B\mathbf{m}=[0,0,{}_Bm_z]^T Bm=[0,0,Bmz]T N m = [ 0 , 0 , B m z ] T = B m {}_N\mathbf{m}=[0,0,{}_Bm_z]^T={}_B\mathbf{m} Nm=[0,0,Bmz]T=Bm

也就是说,如果我有一个向量 B m = [ B m x , B m y , B m z ] T {}_B\mathbf{m}=[{}_Bm_x,{}_Bm_y,{}_Bm_z]^T Bm=[Bmx,Bmy,Bmz]T,那么:

  1. N e x {}_N\mathbf{e}_x Nex轴上: B m x {}_Bm_x Bmx会分解 B m x ⋅ c o s ψ {}_Bm_x \cdot cos\psi Bmxcosψ N e x {}_N\mathbf{e}_x Nex轴上, B m y {}_Bm_y Bmy会分解 B m y ⋅ − s i n ψ {}_Bm_y \cdot -sin\psi Bmysinψ N e x {}_N\mathbf{e}_x Nex轴上。 B m z {}_Bm_z Bmz无分解。
  2. N e y {}_N\mathbf{e}_y Ney轴上: B m x {}_Bm_x Bmx会分解 B m x ⋅ s i n ψ {}_Bm_x \cdot sin\psi Bmxsinψ N e y {}_N\mathbf{e}_y Ney轴上, B m y {}_Bm_y Bmy会分解 B m y ⋅ c o s ψ {}_Bm_y \cdot cos\psi Bmycosψ N e y {}_N\mathbf{e}_y Ney轴上。 B m z {}_Bm_z Bmz无分解。
  3. N e z {}_N\mathbf{e}_z Nez轴上: B m x {}_Bm_x Bmx无分解, B m y {}_Bm_y Bmy无分解, B m z {}_Bm_z Bmz会分解 B m z ⋅ 1 {}_Bm_z \cdot 1 Bmz1 N e z {}_N\mathbf{e}_z Nez轴上。

我们可以用矩阵来描述 B m {}_B\mathbf{m} Bm N m {}_N\mathbf{m} Nm之间的关系:

Eq. 1
N ψ m = R z ( ψ ) ⋅ B m = [ c ( ψ ) − s ( ψ ) 0 s ( ψ ) c ( ψ ) 0 0 0 1 ] ⋅ [ B m x B m y B m z ] {}_{N\psi}\mathbf{m}=R_z(\psi)\cdot{}_B\mathbf{m}= \begin{bmatrix}c(\psi) & -s(\psi) & 0\\s(\psi) & c(\psi) &0\\0 & 0 &1\end{bmatrix} \cdot \begin{bmatrix}{}_Bm_x \\{}_Bm_y \\{}_Bm_z\end{bmatrix} Nψm=Rz(ψ)Bm= c(ψ)s(ψ)0s(ψ)c(ψ)0001 BmxBmyBmz
ps: s ( ⋅ ) = s i n ( ⋅ ) , c ( ⋅ ) = c o s ( ⋅ ) , t ( ⋅ ) = t a n ( ⋅ ) s(\cdot)=sin(\cdot), c(\cdot)=cos(\cdot), t(\cdot)=tan(\cdot) s()=sin(),c()=cos(),t()=tan()

由于此时的 m \mathbf{m} m向量只经过了一次旋转(Z), 还剩下两次旋转(Y)与(X),所以我把第一次旋转后的 N m {}_N\mathbf{m} Nm暂时写为 N ψ m {}_{N\psi}\mathbf{m} Nψm。在新的坐标系 N ψ e {}_{N\psi}\mathbf{e} Nψe下,我们继续旋转,不过此时围绕 B e y {}_B\mathbf{e}_y Bey轴,旋转角度为 θ \theta θ。用同样的方法,我们可以得到 B m {}_{B}\mathbf{m} Bm N θ ψ m {}_{N\theta\psi}\mathbf{m} ψm之间的关系:

Eq. 2
N θ ψ m = R y ( θ ) ⋅ N ψ m = R y ( θ ) ⋅ R z ( ψ ) ⋅ B m = [ c ( θ ) 0 s ( θ ) 0 1 0 − s ( θ ) 0 c ( θ ) ] ⋅ [ c ( ψ ) − s ( ψ ) 0 s ( ψ ) c ( ψ ) 0 0 0 1 ] ⋅ [ B m x B m y B m z ] {}_{N\theta\psi}\mathbf{m}=R_y(\theta)\cdot{}_{N\psi}\mathbf{m}=R_y(\theta)\cdot R_z(\psi) \cdot {}_B\mathbf{m}= \begin{bmatrix}c(\theta) & 0 & s(\theta)\\0 & 1 &0\\-s(\theta) & 0 &c(\theta)\end{bmatrix} \cdot \begin{bmatrix}c(\psi) & -s(\psi) & 0\\s(\psi) & c(\psi) &0\\0 & 0 &1\end{bmatrix} \cdot \begin{bmatrix}{}_Bm_x \\{}_Bm_y \\{}_Bm_z\end{bmatrix} ψm=Ry(θ)Nψm=Ry(θ)Rz(ψ)Bm= c(θ)0s(θ)010s(θ)0c(θ) c(ψ)s(ψ)0s(ψ)c(ψ)0001 BmxBmyBmz

最后,我们沿着 B e x {}_B\mathbf{e}_x Bex旋转 ϕ \phi ϕ。同理, B m {}_{B}\mathbf{m} Bm N ϕ θ ψ m {}_{N\phi\theta\psi}\mathbf{m} Nϕθψm之间的关系如下:

Eq. 3
N ϕ θ ψ m = R x ( ϕ ) ⋅ R y ( θ ) ⋅ R z ( ψ ) ⋅ B m = [ 1 0 0 0 c ( ϕ ) − s ( ϕ ) 0 s ( ϕ ) c ( ϕ ) ] ⋅ [ c ( θ ) 0 s ( θ ) 0 1 0 − s ( θ ) 0 c ( θ ) ] ⋅ [ c ( ψ ) − s ( ψ ) 0 s ( ψ ) c ( ψ ) 0 0 0 1 ] ⋅ [ B m x B m y B m z ] {}_{N\phi\theta\psi}\mathbf{m}=R_x(\phi)\cdot R_y(\theta)\cdot R_z(\psi) \cdot {}_B\mathbf{m}= \begin{bmatrix}1 & 0 & 0\\0 & c(\phi) &-s(\phi)\\0 & s(\phi) &c(\phi)\end{bmatrix} \cdot \begin{bmatrix}c(\theta) & 0 & s(\theta)\\0 & 1 &0\\-s(\theta) & 0 &c(\theta)\end{bmatrix} \cdot \begin{bmatrix}c(\psi) & -s(\psi) & 0\\s(\psi) & c(\psi) &0\\0 & 0 &1\end{bmatrix} \cdot \begin{bmatrix}{}_Bm_x \\{}_Bm_y \\{}_Bm_z\end{bmatrix} Nϕθψm=Rx(ϕ)Ry(θ)Rz(ψ)Bm= 1000c(ϕ)s(ϕ)0s(ϕ)c(ϕ) c(θ)0s(θ)010s(θ)0c(θ) c(ψ)s(ψ)0s(ψ)c(ψ)0001 BmxBmyBmz

最终,我们把这三个旋转矩阵乘起来,可以得到如下等式:

Eq. 4
N ϕ θ ψ m = R z y x ( ψ , θ , ϕ ) ⋅ B m = [ c ( θ ) c ( ψ ) s ( ϕ ) s ( θ ) c ( ψ ) − c ( ϕ ) s ( ψ ) c ( ϕ ) s ( θ ) c ( ψ ) + s ( ϕ ) s ( ψ ) c ( θ ) s ( ψ ) s ( ϕ ) s ( θ ) s ( ψ ) + c ( ϕ ) c ( ψ ) c ( ϕ ) s ( θ ) s ( ψ ) − s ( ϕ ) c ( ψ ) − s ( θ ) s ( ϕ ) c ( θ ) c ( ϕ ) c ( θ ) ] ⋅ [ B m x B m y B m z ] {}_{N\phi\theta\psi}\mathbf{m}=R_{zyx}(\psi,\theta,\phi)\cdot {}_B\mathbf{m}= \begin{bmatrix}c(\theta)c(\psi) & s(\phi)s(\theta)c(\psi)-c(\phi)s(\psi) & c(\phi)s(\theta)c(\psi)+s(\phi)s(\psi)\\c(\theta)s(\psi) & s(\phi)s(\theta)s(\psi)+c(\phi)c(\psi) &c(\phi)s(\theta)s(\psi)-s(\phi)c(\psi)\\-s(\theta) & s(\phi)c(\theta) &c(\phi)c(\theta)\end{bmatrix} \cdot \begin{bmatrix}{}_Bm_x \\{}_Bm_y \\{}_Bm_z\end{bmatrix} Nϕθψm=Rzyx(ψ,θ,ϕ)Bm= c(θ)c(ψ)c(θ)s(ψ)s(θ)s(ϕ)s(θ)c(ψ)c(ϕ)s(ψ)s(ϕ)s(θ)s(ψ)+c(ϕ)c(ψ)s(ϕ)c(θ)c(ϕ)s(θ)c(ψ)+s(ϕ)s(ψ)c(ϕ)s(θ)s(ψ)s(ϕ)c(ψ)c(ϕ)c(θ) BmxBmyBmz

说了这么半天,到底什么是欧拉角,什么是旋转矩阵呢?
其实欧拉角就是我们分别沿着(Z-Y-X)旋转时对应的三个角度( ψ , θ , ϕ \psi, \theta, \phi ψ,θ,ϕ)。每次旋转时,所对应的 R z ( ψ ) , R y ( θ ) , R x ( ϕ ) R_z(\psi), R_y(\theta), R_x(\phi) Rz(ψ),Ry(θ),Rx(ϕ),包括它们三个的乘积 R z y x ( ϕ , θ , ψ ) R_{zyx}(\phi,\theta,\psi) Rzyx(ϕ,θ,ψ),都可以称之为旋转矩阵。其实旋转矩阵也不止这一个形式,如果我们调整旋转的顺序(Z-X-Y, X-Z-Y…)都会得到不一样的旋转矩阵,甚至也有Z-X-Z, Z-Y-Z, X-Z-X等旋转顺序。但无论哪种旋转顺序,我们都可以从原始姿态旋转成任意一个姿态。

这里必须提一下旋转矩阵的重要性质,如果你对每一个旋转矩阵求行列式,你会发现无论旋转角度是多少,它们结果都等于1。也就说明:

  1. 一个向量旋转前后,模长保持不变
  2. 由于旋转前后可以用矩阵来描述,说明旋转是一个线性操作。那么两个向量旋转前夹角为 α \alpha α,经过同样的旋转后,夹角仍为 α \alpha α
  3. 同理可知,两个向量先叉乘再旋转,等于先各自旋转再叉乘。说明旋转前后相对姿态保持不变。

以上三个性质,大家有兴趣可以去验证一下。

至此,我们在已知欧拉角的情况下,能够把body frame下的向量转换为global frame下。这对于无人机的动力学建模至关重要,因为无人机里面的IMU传感器,只能给我们提供欧拉角,body frame下的加速度 [ B a x , B a y , B a z ] T [{}_Ba_x, {}_Ba_y, {}_Ba_z]^T [Bax,Bay,Baz]T和角速度 [ B ω x , B ω y , B ω z ] T [{}_B\omega_x, {}_B\omega_y, {}_B\omega_z]^T [Bωx,Bωy,Bωz]T。但是我们控制的时候,需要global frame下面的位置以及速度等状态信息,方便我们控制无人机的飞行轨迹。比如我们想控制无人机从 [ 0 , 0 , 0 ] T [0,0,0]^T [0,0,0]T点飞往 [ 10 , 10 , 5 ] T [10,10,5]^T [10,10,5]T点,这些坐标都是global frame下的。我们都知道,无人机四个螺旋桨转起来,会提供一个 B e z {}_B\mathbf{e}_z Bez方向向上的力 f t ⋅ B e z f_t\cdot{}_B\mathbf{e}_z ftBez. 此时,我们就可以通过旋转矩阵,将其转换到global frame下,,与重力 m ⋅ g = m ⋅ [ 0 , 0 , − 9.81 ] T m\cdot\mathbf{g}=m\cdot[0,0,-9.81]^T mg=m[0,0,9.81]T求向量和,得到合力方向, 进而通过ODE解出global frame下的速度与位置。

这一篇的最后,我想再补充一个内容:欧拉角的导数 [ ϕ ˙ , θ ˙ , ψ ˙ ] T [\dot{\phi}, \dot{\theta}, \dot{\psi}]^ T [ϕ˙,θ˙,ψ˙]T与body frame angular velocity [ B ω x , B ω y , B ω z ] T [{}_B\omega_x, {}_B\omega_y, {}_B\omega_z]^T [Bωx,Bωy,Bωz]T之间的关系。这样,我们下一篇就能直接开始对四旋翼无人机进行建模。

Body Frame Angular Velocity and [ ϕ ˙ , θ ˙ , ψ ˙ ] T [\dot{\phi}, \dot{\theta}, \dot{\psi}]^T [ϕ˙,θ˙,ψ˙]T

回顾一下初中的知识:角速度不光有大小,也有方向,我们可以根据下图,用右手定则,来判断角速度的方向。

Fig. 3

这个时候,有很多人就会说:那这个关系多简单,不是跟上面一样吗? B ω x {}_B\omega_x Bωx就是绕着body frame x 轴转动的,右手一握,方向就是 B e x {}_B\mathbf{e}_x Bex的正方向。同理, B ω y {}_B\omega_y Bωy方向是 B e y {}_B\mathbf{e}_y Bey, B ω z {}_B\omega_z Bωz方向是 B e z {}_B\mathbf{e}_z Bez。我们想把它们转换成global frame下面的 [ ϕ ˙ , θ ˙ , ψ ˙ ] T [\dot{\phi}, \dot{\theta}, \dot{\psi}]^T [ϕ˙,θ˙,ψ˙]T,就直接用我们前面推出来的 R z y x ( ϕ , θ , ϕ ) R_{zyx}(\phi,\theta,\phi) Rzyx(ϕ,θ,ϕ)矩阵乘以 [ B ω x , B ω y , B ω z ] T [{}_B\omega_x, {}_B\omega_y, {}_B\omega_z]^T [Bωx,Bωy,Bωz]T不就好了?

答案肯定是不对的。因为这里的欧拉角 [ ϕ , θ , ψ ] T [\phi, \theta, \psi]^T [ϕ,θ,ψ]T可不是像速度、位置那样的向量。它们本身就有一个旋转顺序。比如我们上面一直用的Z-Y-X顺序, 在沿着最后一个轴(body frame x轴)旋转 ϕ \phi ϕ角度之后,完成整个旋转。那么你想,假设我们现在完成了前面两次(Z-Y)旋转,目前正沿着 B e x {}_B\mathbf{e}_x Bex 2.5 r a d / s 2.5rad/s 2.5rad/s的速度完成最后一次角度为 ϕ \phi ϕ的旋转,那是不是意味着, ϕ ˙ = 2.5 r a d / s \dot{\phi}=2.5rad/s ϕ˙=2.5rad/s. 同时,这个 2.5 r a d / s 2.5rad/s 2.5rad/s是沿着 B e x {}_B\mathbf{e}_x Bex方向的,那么它就是 B ω x {}_B\omega_x Bωx! 换句话说,如果我的测得现在的 B ω x {}_B\omega_x Bωx,那么它会完完全全投射到 ϕ ˙ \dot{\phi} ϕ˙上面,在 θ ˙ , ψ ˙ \dot{\theta}, \dot{\psi} θ˙,ψ˙上的投影为0.

那么其它两个角度呢?其实很容易发现,这个转换其实有点类似于Z-Y-X的逆过程。 B ω z {}_B\omega_z Bωz直接对应最后一个旋转角 ϕ \phi ϕ B ω y {}_B\omega_y Bωy需要经过最后一次旋转 R ϕ R_{\phi} Rϕ,而 B ω z {}_B\omega_z Bωz需要经过两次旋转 R ϕ ⋅ R θ R_{\phi} \cdot R_{\theta} RϕRθ。这里的公式我就不再一一推导,根据旋转顺序,把对应的旋转矩阵逆过来,就可以解出如下关系:

Eq. 5
[ ϕ ˙ θ ˙ ψ ˙ ] = T ⋅ [ B ω x B ω y B ω z ] = [ 1 s ( ϕ ) t ( θ ) c ( ϕ ) t ( θ ) 0 c ( ϕ ) − s ( ϕ ) 0 s ( ϕ ) c ( θ ) c ( ϕ ) s ( θ ) ] ⋅ [ B ω x B ω y B ω z ] \begin{bmatrix} \dot{\phi} \\ \dot{\theta} \\ \dot{\psi} \end{bmatrix} = T\cdot \begin{bmatrix} {}_B\omega_x \\ {}_B\omega_y \\ {}_B\omega_z \end{bmatrix} = \begin{bmatrix} 1 & s(\phi)t(\theta) & c(\phi)t(\theta)\\ 0 & c(\phi) & -s(\phi) \\ 0 & \frac{s(\phi)}{c(\theta)} & \frac{c(\phi)}{s(\theta)} \end{bmatrix} \cdot \begin{bmatrix} {}_B\omega_x \\ {}_B\omega_y \\ {}_B\omega_z \end{bmatrix} ϕ˙θ˙ψ˙ =T BωxBωyBωz = 100s(ϕ)t(θ)c(ϕ)c(θ)s(ϕ)c(ϕ)t(θ)s(ϕ)s(θ)c(ϕ) BωxBωyBωz
对这个公式不是很理解的,可以去看一下这个链接:https://physics.stackexchange.com/questions/429081/rotational-kinematics-and-angular-velocity-vector-transformation

小结

至此,我们大致介绍了欧拉角,以及如何用欧拉角推出旋转矩阵,从而使旋转矩阵乘上body frame下面的任意一个向量,可以转换为global frame对应的向量。也简单介绍了body frame angular velocity与欧拉角导数之间的关系。

下一节,我们将以global frame position ( N p x , N p y , N p z {}_Np_x, {}_Np_y, {}_Np_z Npx,Npy,Npz), global frame velocity ( N v x , N v y , N v z {}_Nv_x, {}_Nv_y, {}_Nv_z Nvx,Nvy,Nvz), Euler angles ( ϕ , θ , ψ \phi, \theta, \psi ϕ,θ,ψ), 以及body frame angular velocity ( B ω x , B ω y , B ω z {}_B\omega_x, {}_B\omega_y, {}_B\omega_z Bωx,Bωy,Bωz)这12个参数作为我们四旋翼无人机系统状态,进行动力学建模,并介绍小角度近似线性模型,以及通过简单的MATLAB代码对小角度近似线性模型进行LQR控制。

之后,我们会介绍旋转矩阵的死锁问题,并讲解新的旋转建模方式:四元数(quaternion)。

最后,我们会详细了解并推导四旋翼无人机系统的微分平坦(differential flatness)特性,以及如何利用微分平坦特性直接对非线性系统进行控制,并对比它与小角度近似LQR, 以及非线性模型预测控制(NLMPC)的控制效果。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

四旋翼无人机动力学模型及控制 的相关文章

  • 发现三本不错的讲解数据存储的书

    研究数据存储 xff0c 没有很多现成的东西 xff0c 但是可以参考数据库系统的存储实现的内容 xff0c 发现三本书 xff0c 觉得值得一读 数据库系统全书 http www china pub com computers commo
  • Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, 4

    处理Failed to get convolution algorithm This is probably because cuDNN failed to initialize so try looking to see if a war
  • 字符型设备驱动程序--gpio 驱动实例

    概述 xff1a 字符设备驱动程序 xff1a 是按照字符设备要求完成的由操作系统调用的代码 重点理解以下内容 1 驱动是写给操作系统的代码 xff0c 它不是直接给用户层程序调用的 xff0c 而是给系统调用的 2 所以驱动要向系统注册
  • 协议栈

    协议栈 协议栈是指网络中各层协议的总和 xff0c 其形象的反映了一个网络中数据传输的过程 xff1a 由上层协议到底层协议 xff0c 再由底层协议到上层协议 使用最广泛的是英特网协议栈 xff0c 由上到下的协议分别是 xff1a 应用
  • 再见2011,你好,2012。

    不会写文章 xff0c 这个算是对自己的一个总结吧 xff0c 毕业一年半了 xff0c 从事嵌入式也有一年半了 xff0c 总觉得自己连入门都谈不上 xff0c 整天都看上去很忙 xff0c 有时候确实有一大堆的事情要做 xff0c 但是
  • matlab读取realsense bag文件数据

    代码参考 xff1a https dev intelrealsense com docs matlab wrapper 本示例的功能 xff1a matlab代码 xff1a 给出bag文件路径 xff0c 显示realsense相机型号
  • vncserver:command not found

    Question Solution 1 使用root用户登录 xff0c 运行 yum install tigervnc server 2 使用其他用户 eg opuser 登录 xff0c 启动vncserver xff0c 设置pass
  • CKF MCSCKF UKF EKF滤波性能对比

    CKF MCSCKF UKF EKF滤波性能对比 在非线性滤波中 比较了CKF MCSCKF UKF EKF 几种非线性滤波的性能 用MATLAB进行仿真 八维非线性滤波中 CKF MCSCKF 比较稳定 EKF UKF 表现不好 MATL
  • 自制串口调试助手

    span class token keyword using span span class token namespace System span span class token punctuation span span class
  • 文件描述符和套接字

    文件描述符 xff1a 文件描述符在形式上是一个非负整数 实际上 xff0c 它是一个索引值 xff0c 指向内核为每一个进程所维护的该进程打开文件的记录表 当程序打开一个现有文件或者创建一个新文件时 xff0c 内核向进程返回一个文件描述
  • Papers with Code 2020 全年回顾(顶流论文+顶流代码+Benchmarks)

    点击上方 CVer xff0c 选择加 34 星标 34 置顶 重磅干货 xff0c 第一时间送达 本文转载自 xff1a AI公园 作者 xff1a Ross Taylor 编译 xff1a ronghuaiyang 导读 2020年Pa
  • Nginx 多进程模型是如何实现高并发的?

    进程数与并发数不存在很直接的关系 这取决取server采用的工作方式 如果一个server采用一个进程负责一个request的方式 xff0c 那么进程数就是并发数 那么显而易见的 xff0c 就是会有很多进程在等待中 等什么 xff1f
  • 剑指offer 矩阵中的路径

    题目描述 请设计一个函数 xff0c 用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径 路径可以从矩阵中的任意一个格子开始 xff0c 每一步可以在矩阵中向左 xff0c 向右 xff0c 向上 xff0c 向下移动一个格子 如果
  • QGC二次开发---自定义MAVLink消息

    MAVLink库下载 下载网站https github com mavlink mavlink 可以通过git工具 xff0c 在存放文件夹下打开git工具 xff0c 输入命令 xff1a git clone https github c
  • 视差图(Disparity)三维重投影得到特征点的三维空间坐标的2种方法

    文章目录 前提方法1 perspectiveTransform 方法2 reprojectimageto3d PS参考 前提 1 使用BM或者SGBM算法计算得到了双目图像的合适左右视差图 xff1b 2 使用立体校正函数stereoRec
  • ubuntu查看内存使用情况

    ubuntu下单独查看内存使用情况 free m free默认输出的单位是kb xff0c m表示以M为单位 查看CPU内存使用情况 top 查看GPU内存使用情况 nvidia smi
  • QT 如何调节Windows系统音量大小

    在平时日常工作中 xff0c 我们切换输入法的方式一般会通过键盘组合按键来进行切换的 xff0c 那么作为程序员 xff0c 当然可以通过发送键盘消息事件来实现输入法的切换 同样的道理 xff0c 我们也可以通过发送键盘事件实现麦克风音量或
  • QT 九宫格绘图(QSS方式)

    什么是九宫格方式绘图 xff1f 顾名思义 xff0c 就是把一个方块分割成 9 个部分 xff0c 如图所示 xff1a 九宫格绘图的原理就是把背景图分割成 9 个部分 xff0c 绘制时 xff1a 四个角 xff08 1 3 7 9
  • QT QTimeLine 用法小结

    QTimeLine简述 它最常用于通过周期性调用槽来动画化GUI控件 您可以通过将时间线的持续时间 xff08 以毫秒为单位 xff09 传递给QTimeLine的构造函数来构造时间线 时间线的持续时间描述动画将运行多长时间 然后通过调用s
  • QT 秒/毫秒 转 时分秒

    在日常开发时 xff0c 经常会遇到计算剩余进度或者剩余时间的问题 xff0c 比如计算剩余下载时间等等 本篇文章旨在提供几个常用的转换方式供各位参考 1 秒转时分秒 xff08 方法壹 xff09 QString span class t

随机推荐

  • QT 如何实现 半透明的 圆角 矩形 窗口

    在日常使用的软件里面 xff0c 有些软件提示用户时 xff0c 经常会发现有些提示窗口是半透明的 那么如何实现一个可拖动的 半透明 圆角矩形窗口呢 xff1f 整体思路 xff1a 将窗口本身设置为透明 xff0c 然后通过qss或者绘图
  • 小哥质疑谷歌顶会CV论文有错!并且拿出了复现代码来证明

    点击上方 CVer xff0c 选择加 34 星标 34 置顶 重磅干货 xff0c 第一时间送达 萧箫 发自 凹非寺 来源 xff1a 量子位 xff08 QbitAI xff09 景色很好看 xff0c 可是手机相机分辨率太低 xff0
  • QT 如何只允许打开一个 chm 文档

    chm文档 xff0c 大家都不会陌生 xff0c 很多软件的帮助文档就是chm格式的 我们自己在开发程序的时候 xff0c 也需要对外提供帮助文档 xff0c 为了方便用户 xff0c 经常在软件中就可以打开帮助文档 xff0c 那么如何
  • QT 如何把外部程序嵌入到QT界面

    一个奇怪但又合乎现实需要的需求 xff0c 就是把外部程序嵌入到本窗口内 xff0c 实现外部程序在本窗口的显示 可能外部程序是由其他人开发的 xff0c 但是想 拿来 作为内部使用 xff0c 于是乎想把外部程序嵌入到本程序窗口内 xff
  • QT 如何去除QListView选中item后的虚线框

    在使用QListView或者QListWidget时 xff0c 如果选中其item xff0c 会发现边框会出现虚线框 xff0c 这并不美观 xff01 所以 xff0c 我们需要去掉选中后的虚线框 在查阅各路大神的实现方式后 xff0
  • QT QCompleter 用法小结

    1 有何用处 QCompleter类提供基于项模型的补全功能 您可以使用QCompleter在任何Qt小部件 xff08 如QLineEdit和QComboBox xff09 中提供自动补全 当用户开始键入单词时 xff0c QComple
  • QT 关于全屏 与 退出全屏

    在某些场景 xff08 比如说 xff1a 车机系统 医疗仪器等 xff09 可能需要确保软件的全屏显示 xff0c 本次探讨的是如何实现全屏与退出全屏 实现全屏的几种方式 span class token operator lt span
  • QT 如何设置 QCompleter 样式

    在使用QCompleter xff0c 一般都会面临两个问题 xff1a 1 如何设置Completer的行高 xff1b 2 如何设置Completer的样式 本文将一次为你解答 xff0c 顺便讲讲ComboBox设置Completer
  • QT 如何知道用户点击 QTextBrowser 中的具体链接地址

    在通过鼠标点击 QTextBrowser 中的链接地址时 xff0c 如果是希望使用外部浏览器打开链接地址 xff0c 只需要添加一行代码 ui gt textBrowser gt setOpenExternalLinks true 但如果
  • QT 常用控件类型命名参考

    规范的定义 规范 xff0c 有名词 动词 代词等词性 意指符合逻辑 xff0c 客观 真实 全面 完整 准确 及时 xff0c 达标 明文规定或约定俗成的标准 如 xff1a 道德规范 技术规范等 或是指按照既定标准 规范的要求进行操作
  • C++ 如何让代码在main()函数之前或者之后执行

    程序最早执行的函数其实并不是main xff0c 在main函数之前会有一系列初始化的操作 xff08 通常是由链接器等完成的 xff09 比如在windows中 xff0c 这个函数是mainCRTStartup xff0c 这个函数是链
  • QT 如何提高 Qt Creator 的编译速度

    如何提高编译速度 xff0c 貌似是一个老生常谈的话题 对于Qter而言 xff0c 如何提高QT Creator 的编辑速度是一直都是大家所期盼的 本文也是查阅了各路大神的方法后整理出来的 xff0c 希望对各位有所帮助 1 在 pro文
  • 卧槽!出了一个Python实时目标跟踪系统神器!

    在当下自动驾驶 智慧城市 安防等领域对车辆 行人 飞行器等快速移动的物体进行实时跟踪及分析的需求可谓比比皆是 xff0c 但单纯的目标检测算法只能输出目标的定位 43 分类 xff0c 无法对移动的目标具体的运动行为及特征进行分析 xff0
  • C++ 什么是BCC校验

    BCC Block Check Character xff0c 俗称异或校验 BCC的实现方法 xff1a 将所有数据都和一个指定的初始值 通常是0 异或一次 xff0c 所得结果为校验值 BCC一般只是用来排错的 xff0c 并不是加密算
  • QT 如何让QLineEdit的文字从最左边开始显示

    当QLineEdit的文字长度超过了控件宽度 xff0c 一般而言 xff08 控件文字设为靠左对齐 xff09 xff0c 用户只能看到这一长串文字的后半段部分 但是如果想让QLineEdit从最左边开始显示字符串内容呢 xff1f 举个
  • QT setBuddy 用法小结

    将此标签的好友 xff08 窗口其他小部件 xff09 设置为好友 当用户按下此标签指示的快捷键时 xff0c 键盘焦点将转移到标签的好友小部件 好友机制仅适用于包含一个字符前缀为 amp 的文本的QLabels 此字符被设置为快捷键 设置
  • QT stackUnder 用法小结

    stackUnder是什么意思 xff1f 根据官方的解析 xff0c 简而言之一句话 xff1a 把窗口的小部件放置于父窗口的堆栈窗口中 本文将通过一则简单的示例 xff0c 来具体解析stackUnder该如何使用 官方解析 void
  • QT 线程安全的单例模式(使用Q_GLOBAL_STATIC实现)

    Qt提供了宏 Q GLOBAL STATIC xff08 官方说明文档 xff1a https doc qt io qt 5 qglobalstatic html xff09 xff0c 用于创建全局静态对象 鉴于此 xff0c 我们可以通
  • git push提示“fatal: the remote end hung up unexpectedly”的解决方法

    问题描述 在执行push命令时 xff0c 命令行提示 xff1a span class token function git span push origin master Enumerating objects 4968 done Co
  • 四旋翼无人机动力学模型及控制

    四旋翼无人机动力学模型及控制 I 欧拉角与旋转矩阵 Overview欧拉角与旋转矩阵Body Frame Angular Velocity and