BetaFlight深入传感设计之六:四元数计算方法

2023-05-16

BetaFlight深入传感设计之六:四元数计算方法

  • 1. 四元数理论
    • 1.1 定义
    • 1.2 基本运算
      • 1.2.1 矢量加减
      • 1.2.2 标量乘法
    • 1.3 矢量点叉乘
      • 1.3.1 矢量点乘
      • 1.3.2 矢量叉乘
    • 1.4 除法求逆
  • 2. 程序四元素
    • 2.1 四元数定义
    • 2.2 四元数初始化
      • 2.2.1 单位标量初始化
      • 2.2.2 矢量初始化
    • 2.3 表达转换
      • 2.3.1 复数式转三角式
      • 2.3.2 三角式转复数式
    • 2.4 基本运算
      • 2.4.1 矢量加法
      • 2.4.2 标量乘法
    • 2.5 矢量点叉乘
      • 2.5.1 矢量点乘
      • 2.5.2 矢量叉乘
    • 2.6 零标量四元数旋转
      • 2.6.1 CW方向旋转
      • 2.6.2 CCW方向旋转
    • 2.7 其他运算
      • 2.7.1 四元素模平方
      • 2.7.2 四元素求厄
      • 2.7.3 四元素归一化
  • 3. 机体坐标系和地球坐标系转换
    • 3.1 机体坐标系向地球坐标系旋转
    • 3.2 地球坐标系向机体坐标系旋转
  • 4. 总结
  • 5. 补充资料
    • 5.1 ENU Coordinates
    • 5.2 NED Coordinates
    • 5.3 Earth-Centered Earth-Fixed Coordinates
    • 5.4 Azimuth-Elevation-Range Coordinates
  • 6. 参考资料

BetaFlight和iNavFlight都是出自CleanFlight分支,两者的侧重点不太一样。从四元数应用的角度来看,iNav不仅代码比较完整,且对四元数操作进行了相应的数学逻辑封装。

我们这里针对四元数的应用,结合代码进行一次整理和理解。

1. 四元数理论

1.1 定义

  1. 矢量式

Q → = q 0 + q → \overrightarrow{Q} = q_0 + \overrightarrow{q} Q =q0+q

  1. 复数式

Q → = q 0 + q 1 ⋅ i + q 2 ⋅ j + q 3 ⋅ k \overrightarrow{Q} = q_0 + q_1 \cdot i + q_2 \cdot j + q_3 \cdot k Q =q0+q1i+q2j+q3k

注:高中课本的复数就是超复数的一种特殊情况,其中 q 2 = q 3 = 0 q_2 = q_3 = 0 q2=q3=0

  1. 三角式

Q → = c o s θ 2 + u → s i n θ 2 \overrightarrow{Q} = cos \cfrac{\theta}{2} + \overrightarrow{u} sin \cfrac{\theta}{2} Q =cos2θ+u sin2θ

1.2 基本运算

1.2.1 矢量加减

P → ± Q → = ( p 0 + p 1 ⋅ i + p 2 ⋅ j + p 3 ⋅ k ) ± ( q 0 + q 1 ⋅ i + q 2 ⋅ j + q 3 ⋅ k ) = ( p 0 ± q 0 ) + ( p 1 ± q 1 ) ⋅ i + ( p 2 ± q 2 ) ⋅ j + ( p 3 ± q 3 ) ⋅ k \overrightarrow{P} \pm \overrightarrow{Q} = (p_0 + p_1 \cdot i + p_2 \cdot j + p_3 \cdot k) \pm (q_0 + q_1 \cdot i + q_2 \cdot j + q_3 \cdot k) = (p_0 \pm q_0) + (p_1 \pm q_1) \cdot i + (p_2 \pm q_2) \cdot j + (p_3 \pm q_3) \cdot k P ±Q =(p0+p1i+p2j+p3k)±(q0+q1i+q2j+q3k)=(p0±q0)+(p1±q1)i+(p2±q2)j+(p3±q3)k

1.2.2 标量乘法

a ⋅ Q → = a ⋅ q 0 + a ⋅ q 1 ⋅ i + a ⋅ q 2 ⋅ j + a ⋅ q 3 ⋅ k a \cdot \overrightarrow{Q} = a \cdot q_0 + a \cdot q_1 \cdot i + a \cdot q_2 \cdot j + a \cdot q_3 \cdot k aQ =aq0+aq1i+aq2j+aq3k

1.3 矢量点叉乘

1.3.1 矢量点乘

P → ⋅ Q → = ∣ P ∣ ∣ Q ∣ c o s θ P Q \overrightarrow{P} \cdot \overrightarrow{Q} = \rvert P \rvert \rvert Q \rvert cos \theta_{PQ} P Q =P∣∣QcosθPQ

P → ⋅ Q → = ( p 0 + p 1 ⋅ i + p 2 ⋅ j + p 3 ⋅ k ) ⋅ ( q 0 + q 1 ⋅ i + q 2 ⋅ j + q 3 ⋅ k ) = p 0 q 0 + p 1 q 1 + p 2 q 2 + p 3 q 3 \overrightarrow{P} \cdot \overrightarrow{Q} = (p_0 + p_1 \cdot i + p_2 \cdot j + p_3 \cdot k) \cdot (q_0 + q_1 \cdot i + q_2 \cdot j + q_3 \cdot k) = p_0 q_0 + p_1 q_1 + p_2 q_2 + p_3 q_3 P Q =(p0+p1i+p2j+p3k)(q0+q1i+q2j+q3k)=p0q0+p1q1+p2q2+p3q3

1.3.2 矢量叉乘

P → × Q → = − Q → × P → \overrightarrow{P} \times \overrightarrow{Q} = -\overrightarrow{Q} \times \overrightarrow{P} P ×Q =Q ×P

∣ P → × Q → ∣ = ∣ P ∣ ∣ Q ∣ s i n θ P Q \rvert \overrightarrow{P} \times \overrightarrow{Q} \rvert =\rvert P \rvert \rvert Q \rvert sin \theta_{PQ} P ×Q =P∣∣QsinθPQ

P → × Q → = ( P → × Q → ) x + ( P → × Q → ) y + ( P → × Q → ) z \overrightarrow{P} \times \overrightarrow{Q} = (\overrightarrow{P} \times \overrightarrow{Q} )_x + (\overrightarrow{P} \times \overrightarrow{Q} )_y + (\overrightarrow{P} \times \overrightarrow{Q} )_z P ×Q =(P ×Q )x+(P ×Q )y+(P ×Q )z

( P → × Q → ) x = P y Q z − P z Q y (\overrightarrow{P} \times \overrightarrow{Q} )_x = P_yQ_z - P_zQ_y (P ×Q )x=PyQzPzQy
( P → × Q → ) y = P z Q x − P x Q z (\overrightarrow{P} \times \overrightarrow{Q} )_y = P_zQ_x - P_xQ_z (P ×Q )y=PzQxPxQz
( P → × Q → ) z = P x Q y − P y Q x (\overrightarrow{P} \times \overrightarrow{Q} )_z = P_xQ_y - P_yQ_x (P ×Q )z=PxQyPyQx

P → × Q → = ( p 0 + p 1 ⋅ i + p 2 ⋅ j + p 3 ⋅ k ) × ( q 0 + q 1 ⋅ i + q 2 ⋅ j + q 3 ⋅ k ) = ( p 0 q 0 − p 1 q 1 − p 2 q 2 − p 3 q 3 ) + ( p 0 q 1 + p 1 q 0 + p 2 q 3 − p 3 q 2 ) ⋅ i + ( p 0 q 2 + p 2 q 0 + p 3 q 1 − p 1 q 3 ) ⋅ j + ( p 0 q 3 + p 3 q 0 + p 1 q 2 − p 2 q 1 ) ⋅ k = r 0 + r 1 ⋅ i + r 2 ⋅ j + r 3 ⋅ k \overrightarrow{P} \times \overrightarrow{Q} = (p_0 + p_1 \cdot i + p_2 \cdot j + p_3 \cdot k) \times (q_0 + q_1 \cdot i + q_2 \cdot j + q_3 \cdot k) = (p_0q_0 - p_1q_1 - p_2q_2 - p_3q_3) + (p_0q_1 + p_1q_0 + p_2q_3 - p_3q_2) \cdot i + (p_0q_2 + p_2q_0 + p_3q_1 -p_1q_3) \cdot j +(p_0q_3 + p_3q_0 +p_1q_2 - p_2q_1) \cdot k = r_0 + r_1 \cdot i + r_2 \cdot j + r_3 \cdot k P ×Q =(p0+p1i+p2j+p3k)×(q0+q1i+q2j+q3k)=(p0q0p1q1p2q2p3q3)+(p0q1+p1q0+p2q3p3q2)i+(p0q2+p2q0+p3q1p1q3)j+(p0q3+p3q0+p1q2p2q1)k=r0+r1i+r2j+r3k

换成矩阵表达式(便于后续计算机计算):

R = M ( P ) Q = M ′ ( Q ) P R = M(P)Q = M\rq(Q)P R=M(P)Q=M(Q)P

[ r 0 r 1 r 2 r 3 ] = M ( P ) Q = [ p 0 − p 1 − p 2 − p 3 p 1 p 0 − p 3 p 2 p 2 p 3 p 0 − p 1 p 3 − p 2 p 1 p 0 ] [ q 0 q 1 q 2 q 3 ] \begin{bmatrix} r_0 \\ r_1 \\ r_2 \\ r_3 \end{bmatrix} = M(P)Q =\begin{bmatrix} p_0 & -p_1 & -p_2 & -p_3\\ p_1& p_0 & -p_3 & p_2 \\ p_2 & p_3 & p_0 & -p_1\\ p_3 & -p_2 & p_1 & p_0 \end{bmatrix}\begin{bmatrix} q_0 \\ q_1 \\ q_2 \\ q_3 \end{bmatrix} r0r1r2r3 =M(P)Q= p0p1p2p3p1p0p3p2p2p3p0p1p3p2p1p0 q0q1q2q3

[ r 0 r 1 r 2 r 3 ] = M ′ ( Q ) P = [ q 0 − q 1 − q 2 − q 3 q 1 q 0 q 3 − q 2 q 2 − q 3 q 0 q 1 q 3 q 2 − q 1 q 0 ] [ p 0 p 1 p 2 p 3 ] \begin{bmatrix} r_0 \\ r_1 \\ r_2 \\ r_3 \end{bmatrix} = M\rq(Q)P = \begin{bmatrix} q_0 & -q_1 & -q_2 & -q_3\\ q_1& q_0 & q_3 & -q_2 \\ q_2 & -q_3 & q_0 & q_1\\ q_3 & q_2 & -q_1 & q_0 \end{bmatrix}\begin{bmatrix} p_0 \\ p_1 \\ p_2 \\ p_3 \end{bmatrix} r0r1r2r3 =M(Q)P= q0q1q2q3q1q0q3q2q2q3q0q1q3q2q1q0 p0p1p2p3

1.4 除法求逆

P → ⊗ R → = 1 \overrightarrow{P} \otimes \overrightarrow{R} = 1 P R =1

将记作: R → = P − 1 → = P ∗ → \overrightarrow{R} = \overrightarrow{P^{-1}}=\overrightarrow{P^*} R =P1 =P

P → ⊗ P ∗ → = ( p 0 + p 1 ⋅ i + p 2 ⋅ j + p 3 ⋅ k ) ⊗ ( p 0 − p 1 ⋅ i − p 2 ⋅ j − p 3 ⋅ k ) = q 0 2 + q 1 2 + q 2 2 + q 3 2 = ∥ P ∥ \overrightarrow{P} \otimes \overrightarrow{P^*} = (p_0 + p_1 \cdot i + p_2 \cdot j + p_3 \cdot k) \otimes (p_0 - p_1 \cdot i - p_2 \cdot j - p_3 \cdot k)= q_0^2 + q_1^2 + q_2^2 + q_3^2 = \rVert P \rVert P P =p0+p1i+p2j+p3kp0p1ip2jp3k=q02+q12+q22+q32=P

所以: P − 1 → = P ∗ → ∥ P ∥ \overrightarrow{P^{-1}} =\cfrac{\overrightarrow{P^*}}{ \rVert P \rVert} P1 =PP

2. 程序四元素

2.1 四元数定义

typedef struct {
    float q0, q1, q2, q3;
} fpQuaternion_t;

2.2 四元数初始化

2.2.1 单位标量初始化

static inline fpQuaternion_t * quaternionInitUnit(fpQuaternion_t * result)
{
    result->q0 = 1.0f;
    result->q1 = 0.0f;
    result->q2 = 0.0f;
    result->q3 = 0.0f;
    return result;
}

2.2.2 矢量初始化

static inline fpQuaternion_t * quaternionInitFromVector(fpQuaternion_t * result, const fpVector3_t * v)
{
    result->q0 = 0.0f;
    result->q1 = v->x;
    result->q2 = v->y;
    result->q3 = v->z;
    return result;
}

2.3 表达转换

注:进行转换的输入参数必须归一化。

2.3.1 复数式转三角式

static inline void quaternionToAxisAngle(fpAxisAngle_t * result, const fpQuaternion_t * q)
{
    fpAxisAngle_t a = {.axis = {{1.0f, 0.0f, 0.0f}}, .angle = 0};

    a.angle = 2.0f * acos_approx(constrainf(q->q0, -1.0f, 1.0f));

    if (a.angle > M_PIf) {
        a.angle -= 2.0f * M_PIf;
    }

    const float sinVal = sqrt(1.0f - q->q0 * q->q0);

    // Axis is only valid when rotation is large enough sin(0.0057 deg) = 0.0001
    if (sinVal > 1e-4f) {
        a.axis.x = q->q1 / sinVal;
        a.axis.y = q->q2 / sinVal;
        a.axis.z = q->q3 / sinVal;
    } else {
        a.angle = 0;
    }

    *result = a;
}

2.3.2 三角式转复数式

static inline fpQuaternion_t * axisAngleToQuaternion(fpQuaternion_t * result, const fpAxisAngle_t * a)
{
  fpQuaternion_t q;
  const float s = sin_approx(a->angle / 2.0f);

  q.q0 = cos_approx(a->angle / 2.0f);
  q.q1 = -a->axis.x * s;
  q.q2 = -a->axis.y * s;
  q.q3 = -a->axis.z * s;

  *result = q;
  return result;
}

问题1:为什么 q 1 q 2 q 3 q_1 q_2 q_3 q1q2q3是负值??? 按照定义的角度看应该是正的呀,有知道的朋友请评论批注,谢谢!

2.4 基本运算

2.4.1 矢量加法

static inline fpQuaternion_t * quaternionAdd(fpQuaternion_t * result, const fpQuaternion_t * a, const fpQuaternion_t * b)
{
    fpQuaternion_t p;

    p.q0 = a->q0 + b->q0;
    p.q1 = a->q1 + b->q1;
    p.q2 = a->q2 + b->q2;
    p.q3 = a->q3 + b->q3;

    *result = p;
    return result;
}

2.4.2 标量乘法

static inline fpQuaternion_t * quaternionScale(fpQuaternion_t * result, const fpQuaternion_t * a, const float b)
{
    fpQuaternion_t p;

    p.q0 = a->q0 * b;
    p.q1 = a->q1 * b;
    p.q2 = a->q2 * b;
    p.q3 = a->q3 * b;

    *result = p;
    return result;
}

2.5 矢量点叉乘

2.5.1 矢量点乘

略.

注:貌似点乘在实际飞控应用中用的不多,代码中未见定义。

2.5.2 矢量叉乘

根据叉乘定义和右手螺旋法则,我们知道叉乘结果是两个矢量模与 s i n θ sin \theta sinθ乘积,方向垂直于两个叉乘矢量。

  • θ = 0 \theta = 0 θ=0的时候, 叉乘结果为零;
  • θ = 90 \theta = 90 θ=90的时候,叉乘结果为两个矢量模,并垂直于两个叉乘矢量;

所以,在实际应用中,归一化的矢量叉乘结果往往用于表达两个矢量的相关性。当两个物理量表达的是同一个物理特性时,叉乘结果的值越趋于零,表示误差越小。

static inline fpQuaternion_t * quaternionMultiply(fpQuaternion_t * result, const fpQuaternion_t * a, const fpQuaternion_t * b)
{
  fpQuaternion_t p;

  p.q0 = a->q0 * b->q0 - a->q1 * b->q1 - a->q2 * b->q2 - a->q3 * b->q3;
  p.q1 = a->q0 * b->q1 + a->q1 * b->q0 + a->q2 * b->q3 - a->q3 * b->q2;
  p.q2 = a->q0 * b->q2 - a->q1 * b->q3 + a->q2 * b->q0 + a->q3 * b->q1;
  p.q3 = a->q0 * b->q3 + a->q1 * b->q2 - a->q2 * b->q1 + a->q3 * b->q0;

  *result = p;
  return result;
}

2.6 零标量四元数旋转

2.6.1 CW方向旋转

static inline fpVector3_t * quaternionRotateVector(fpVector3_t * result, const fpVector3_t * vect, const fpQuaternion_t * ref)
{
    fpQuaternion_t vectQuat, refConj;

    vectQuat.q0 = 0;
    vectQuat.q1 = vect->x;
    vectQuat.q2 = vect->y;
    vectQuat.q3 = vect->z;

    quaternionConjugate(&refConj, ref);
    quaternionMultiply(&vectQuat, &refConj, &vectQuat);
    quaternionMultiply(&vectQuat, &vectQuat, ref);

    result->x = vectQuat.q1;
    result->y = vectQuat.q2;
    result->z = vectQuat.q3;
    return result;
}

2.6.2 CCW方向旋转

static inline fpVector3_t * quaternionRotateVectorInv(fpVector3_t * result, const fpVector3_t * vect, const fpQuaternion_t * ref)
{
    fpQuaternion_t vectQuat, refConj;

    vectQuat.q0 = 0;
    vectQuat.q1 = vect->x;
    vectQuat.q2 = vect->y;
    vectQuat.q3 = vect->z;

    quaternionConjugate(&refConj, ref);
    quaternionMultiply(&vectQuat, ref, &vectQuat);
    quaternionMultiply(&vectQuat, &vectQuat, &refConj);

    result->x = vectQuat.q1;
    result->y = vectQuat.q2;
    result->z = vectQuat.q3;
    return result;
}

2.7 其他运算

2.7.1 四元素模平方

static inline float quaternionNormSqared(const fpQuaternion_t * q)
{
    return sq(q->q0) + sq(q->q1) + sq(q->q2) + sq(q->q3);
}

2.7.2 四元素求厄

static inline fpQuaternion_t * quaternionConjugate(fpQuaternion_t * result, const fpQuaternion_t * q)
{
    result->q0 =  q->q0;
    result->q1 = -q->q1;
    result->q2 = -q->q2;
    result->q3 = -q->q3;

    return result;
}

2.7.3 四元素归一化

static inline fpQuaternion_t * quaternionNormalize(fpQuaternion_t * result, const fpQuaternion_t * q)
{
    float mod = fast_fsqrtf(quaternionNormSqared(q));
    if (mod < 1e-6f) {
        // Length is too small - re-initialize to zero rotation
        result->q0 = 1;
        result->q1 = 0;
        result->q2 = 0;
        result->q3 = 0;
    }
    else {
        result->q0 = q->q0 / mod;
        result->q1 = q->q1 / mod;
        result->q2 = q->q2 / mod;
        result->q3 = q->q3 / mod;
    }

    return result;
}

3. 机体坐标系和地球坐标系转换

问题2:这里为什么NED (sensor frame) 和 NEU (navigation)是这个关系,逻辑在哪里???

3.1 机体坐标系向地球坐标系旋转

void imuTransformVectorBodyToEarth(fpVector3_t * v)
{
    // From body frame to earth frame
    quaternionRotateVectorInv(v, v, &orientation);

    // HACK: This is needed to correctly transform from NED (sensor frame) to NEU (navigation)
    v->y = -v->y;
}

3.2 地球坐标系向机体坐标系旋转

void imuTransformVectorEarthToBody(fpVector3_t * v)
{
    // HACK: This is needed to correctly transform from NED (sensor frame) to NEU (navigation)
    v->y = -v->y;

    // From earth frame to body frame
    quaternionRotateVector(v, v, &orientation);
}

4. 总结

四元数在四轴飞控方面关于姿态和导航方面的应用具有举足轻重的意义。尤其对PID的的误差计算带来了便捷,但是这个在物理概念上需要明确的符号推导和现实意义,才能在后续传感融合上得到长远的发展。

为此,整理了上述基本概念,但是截止目前为止,还存在以下两个问题:

【1】三角式转复数式的时候,什么 q 1 q 2 q 3 q_1 q_2 q_3 q1q2q3是负值??? 按照定义的角度看应该是正的,如何理解???
==》这里搜索了iNav的代码,没有看到axisAngleToQuaternion函数在代码中使用。因此即使有问题,也没有太多关系。

【2】NED (sensor frame) 和 NEU (navigation)的指向是如何定义的?
==》请参考补充资料

如果有同学知道原因,也请多多指点,谢谢先!

5. 补充资料

5.1 ENU Coordinates

ENU Coordinates

5.2 NED Coordinates

NED Coordinates

5.3 Earth-Centered Earth-Fixed Coordinates

Earth-Centered Earth-Fixed Coordinates

5.4 Azimuth-Elevation-Range Coordinates

Azimuth-Elevation-Range Coordinates

6. 参考资料

【1】Comparison of 3-D Coordinate Systems
【2】About Aerospace Coordinate Systems
【3】Flight controller is different from the airframe coordinate system? #11903

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

BetaFlight深入传感设计之六:四元数计算方法 的相关文章

  • PX4模块设计之二十三:自定义FlightTask

    PX4模块设计之二十三 xff1a 自定义FlightTask Step1 创建飞行模式文件夹Step2 创建飞行模式源代码和CMakeLists txt文件Step3 更新CMakeLists txt文件Step4 更新FlightTas
  • PX4模块设计之二十四:内部ADC模块

    PX4模块设计之二十四 xff1a 内部ADC模块 1 内部ADC模块简介2 模块入口函数2 1 主入口board adc main2 2 自定义子命令custom command 3 内部ADC模块重要函数3 1 task spawn3
  • PX4模块设计之二十五:DShot模块

    PX4模块设计之二十五 xff1a DShot模块 1 DShot模块简介2 DShot类继承关系3 模块入口函数3 1 主入口dshot main3 2 自定义子命令custom command 4 DShot模块重要函数4 1 task
  • PX4模块设计之二十六:BatteryStatus模块

    PX4模块设计之二十六 xff1a BatteryStatus模块 1 BatteryStatus模块简介2 模块入口函数2 1 主入口battery status main2 2 自定义子命令custom command 3 Batter
  • PX4模块设计之二十七:LandDetector模块

    PX4模块设计之二十七 xff1a LandDetector模块 1 LandDetector模块简介2 模块入口函数2 1 主入口land detector main2 2 自定义子命令custom command 3 LandDetec
  • CentOS-7 中安装VS Code 并启动

    VSCode安装 安装平台 xff1a CentOS7 安装方法 xff1a 1 在官网上下载64位 xff08 或者32位 xff09 的rpm包 xff08 官网地址 xff1a https code visualstudio com
  • PX4模块设计之二十八:RCInput模块

    PX4模块设计之二十八 xff1a RCInput模块 1 RCInput模块简介2 模块入口函数2 1 主入口rc input main2 2 自定义子命令custom command2 3 模块状态print status 重载 3 R
  • PX4模块设计之二十九:RCUpdate模块

    PX4模块设计之二十九 xff1a RCUpdate模块 1 RCUpdate模块简介2 模块入口函数2 1 主入口rc update main2 2 自定义子命令custom command2 3 模块状态print status 重载
  • PX4模块设计之三十:Hysteresis类

    PX4模块设计之三十 xff1a Hysteresis类 1 Hysteresis类简介2 Hysteresis类成员变量介绍3 Hysteresis类迟滞逻辑4 Hysteresis类重要方法4 1 Hysteresis bool ini
  • PX4模块设计之三十一:ManualControl模块

    PX4模块设计之三十一 xff1a ManualControl模块 1 ManualControl模块简介2 模块入口函数2 1 主入口manual control main2 2 自定义子命令custom command 3 Manual
  • PX4模块设计之三十二:AttitudeEstimatorQ模块

    PX4模块设计之三十二 xff1a AttitudeEstimatorQ模块 1 AttitudeEstimatorQ模块简介2 模块入口函数2 1 主入口attitude estimator q main2 2 自定义子命令custom
  • PX4模块设计之三十三:Sensors模块

    PX4模块设计之三十三 xff1a Sensors模块 1 Sensors模块简介2 模块入口函数2 1 主入口sensors main2 2 自定义子命令custom command2 3 模块状态print status 重载 3 Se
  • 树莓派(Raspberry Pi)miniDLNA服务搭建

    树莓派 Raspberry Pi miniDLNA服务搭建 1 MiniDLNA简介2 安装前提3 安装步骤4 服务配置5 进程配置6 参考资料7 补充资料7 1 配置外置硬盘 xff08 媒体库 xff09 7 2 配置samba符号链接
  • PX4模块设计之三十四:ControlAllocator模块

    PX4模块设计之三十四 xff1a ControlAllocator模块 1 ControlAllocator模块简介2 模块入口函数2 1 主入口control allocator main2 2 自定义子命令custom command
  • PX4模块设计之三十五:MulticopterAttitudeControl模块

    PX4模块设计之三十五 xff1a MulticopterAttitudeControl模块 1 MulticopterAttitudeControl模块简介2 模块入口函数2 1 主入口mc att control main2 2 自定义
  • 穿越机用途和机架尺寸

    穿越机用途和机架尺寸 1 穿越机的用途2 穿越机的机架3 机架的类型3 1 正X型机架3 2 宽X型机架3 3 长X型机架3 4 Hybrid机架3 5 涵道机架 4 总结 1 穿越机的用途 穿越机按功能分 xff0c 主要分为竞速Race
  • HC05和电脑蓝牙通讯

    通常情况下都是将HC05和HC04进行主从配对 xff0c 然后进行通讯 如果手边没有HC04其实可以使用笔记本自带的蓝牙和HC05进行通讯 配置方法如下 xff1a 将HC05配置为主机模式将电脑和HC05的保存连接删除 单击下方更多蓝牙
  • PX4模块设计之三十六:MulticopterPositionControl模块

    PX4模块设计之三十六 xff1a MulticopterPositionControl模块 1 MulticopterPositionControl模块简介2 模块入口函数2 1 主入口mc pos control main2 2 自定义
  • PX4模块设计之三十七:MulticopterRateControl模块

    PX4模块设计之三十七 xff1a MulticopterRateControl模块 1 MulticopterRateControl模块简介2 模块入口函数2 1 主入口mc rate control main2 2 自定义子命令cust
  • PX4模块设计之三十八:Navigator模块

    PX4模块设计之三十八 xff1a Navigator模块 1 Navigator模块简介2 模块入口函数2 1 主入口navigator main2 2 自定义子命令custom command 3 Navigator模块重要函数3 1

随机推荐