PX4的无人机飞控应用开发Word文件下载.docx

上传人:b****5 文档编号:20845232 上传时间:2023-01-26 格式:DOCX 页数:75 大小:104.89KB
下载 相关 举报
PX4的无人机飞控应用开发Word文件下载.docx_第1页
第1页 / 共75页
PX4的无人机飞控应用开发Word文件下载.docx_第2页
第2页 / 共75页
PX4的无人机飞控应用开发Word文件下载.docx_第3页
第3页 / 共75页
PX4的无人机飞控应用开发Word文件下载.docx_第4页
第4页 / 共75页
PX4的无人机飞控应用开发Word文件下载.docx_第5页
第5页 / 共75页
点击查看更多>>
下载资源
资源描述

PX4的无人机飞控应用开发Word文件下载.docx

《PX4的无人机飞控应用开发Word文件下载.docx》由会员分享,可在线阅读,更多相关《PX4的无人机飞控应用开发Word文件下载.docx(75页珍藏版)》请在冰豆网上搜索。

PX4的无人机飞控应用开发Word文件下载.docx

如果你想实现无人机自主飞行,那么就由你自己写的应用(运行在无人机系统上)使用Mavlink协议给无人机发送本地的控制指令就可以了。

然而,为实现飞控架构的灵活性,避免对底层实现细节的依赖,在PX4中,并不鼓励开发者在自定义飞控程序中直接使用Mavlink,而是鼓励开发者使用一种名为uORB((MicroObjectRequestBroker,微对象请求代理)的消息机制。

其实uORB在概念上等同于posix里面的命名管道(namedpipe),它本质上是一种进程间通信机制。

由于PX4实际使用的是NuttX实时ARM系统,因此uORB实际上相当于是多个进程(驱动级模块)打开同一个设备文件,多个进程(驱动级模块)通过此文件节点进行数据交互和共享。

在uORB机制中,交换的消息被称之为topic,一个topic仅包含一种message类型(即数据结构)。

每个进程(或驱动模块)均可“订阅”或“发布”多个topic,一个topic可以存在多个发布者,而且一个订阅者可也订阅多个topic。

而正因为有了uORB机制的存在,上述飞控场景变成了:

(uORBtopic)->

-(uORBtopic)<

有了以上背景基础,便可以自写飞控逻辑了,仅需在PX4源码中,添加一个自定义module,然后使用uORB订阅相关信息(如传感器消息等),并发布相关控制信息(如飞行模式控制消息等)即可。

具体的uORBAPI、uORB消息定义可参考PX4文档与源码,所有控制命令都在firmware代码的msg里面,不再敷述。

最后值得一提的是,在PX4系统中,还提供了一个名为mavlink的专用module,源码在firmware的src/modules/mavlink中,这货与linux的控制台命令工具集相当相似,其既可以作为ntt控制台下的命令使用,又可作为系统模块加载后台运行。

其所实现的功能包括:

1)uORB消息解析,将uORB消息实际翻译为具体的Mavlink底层指令,或反之。

2)通过serial/射频通信接口获取或发送Mavlink消息,既考虑到了用户自写程序的开发模式,也适用于类似linux的脚本工具链开发模式,使用起来很灵活,有兴趣的可以看看。

PX4飞控中利用EKF估计姿态角代码详解

PX4飞控中主要用EKF算法来估计飞行器三轴姿态角,具体c文件在px4\Firmware\src\modules\attitude_estimator_ekf\codegen\目录下

∙具体原理

∙程序详解

∙下一步

1.具体原理

EKF算法原理不再多讲,具体可参见上一篇blog 

这篇讲EKF算法执行过程,需要以下几个关键式子:

∙飞行器状态矩阵:

 

这里

表示三轴角速度,

表示三轴角加速度,

表示加速度在机体坐标系三轴分量,

,表示磁力计在机体坐标系三轴分量。

∙测量矩阵 

分别由三轴陀螺仪,加速度计,磁力计测得。

∙状态转移矩阵:

飞行器下一时刻状态预测矩阵如下:

其中W项均为高斯噪声,

为飞行器在姿态发生变化后,坐标系余旋变换矩阵,对该函数在

处求一阶偏导,可得到状态转移矩阵:

此时可得到飞行器状态的先验估计:

∙利用测量值修正先验估计:

这里测量矩阵H与状态矩阵X为线性关系,故无需求偏导。

卡尔曼增益:

状态后验估计:

方差后验估计:

2.程序详解

整个EKF的代码挺长的,大部分是矩阵运算,而且使用嵌套for循环来执行的,所以读起来比较费劲,但是要是移植到自己工程上的话必然离不开这一步,所以花了一个下午把各个细节理清楚,顺便记录分享。

/*Includefiles*/

#include"

rt_nonfinite.h"

attitudeKalmanfilter.h"

rdivide.h"

norm.h"

cross.h"

eye.h"

mrdivide.h"

/*

'

输入参数:

updateVect[3]:

用来记录陀螺仪,加速度计,磁力计传感器数值是否有效

z[9]:

测量矩阵

x_aposteriori_k[12]:

上一时刻状态后验估计矩阵,用来预测当前状态

P_aposteriori_k[144]:

上一时刻后验估计方差

eulerAngles[3]:

输出欧拉角

Rot_matrix[9]:

输出余弦矩阵

x_aposteriori[12]:

输出状态后验估计矩阵

P_aposteriori[144]:

输出方差后验估计矩阵'

*/

voidattitudeKalmanfilter(

constuint8_TupdateVect[3],

real32_Tdt,

constreal32_Tz[9],

constreal32_Tx_aposteriori_k[12],

constreal32_TP_aposteriori_k[144],

constreal32_Tq[12],

real32_Tr[9],

real32_TeulerAngles[3],

real32_TRot_matrix[9],

real32_Tx_aposteriori[12],

real32_TP_aposteriori[144])

{

/*以下这一堆变量用到的时候再解释*/

real32_Twak[3];

real32_TO[9];

real_Tdv0[9];

real32_Ta[9];

int32_Ti;

real32_Tb_a[9];

real32_Tx_n_b[3];

real32_Tb_x_aposteriori_k[3];

real32_Tz_n_b[3];

real32_Tc_a[3];

real32_Td_a[3];

int32_Ti0;

real32_Tx_apriori[12];

real_Tdv1[144];

real32_TA_lin[144];

staticconstint8_Tiv0[36]={0,0,0,

0,0,0,

1,0,0,

0,1,0,

0,0,1,

0,0,0};

real32_Tb_A_lin[144];

real32_Tb_q[144];

real32_Tc_A_lin[144];

real32_Td_A_lin[144];

real32_Te_A_lin[144];

int32_Ti1;

real32_TP_apriori[144];

real32_Tb_P_apriori[108];

staticconstint8_Tiv1[108]={1,0,0,0,0,0,0,0,0,0,0,0,

0,1,0,0,0,0,0,0,0,0,0,0,

0,0,1,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,1,0,0,0,0,0,

0,0,0,0,0,0,0,1,0,0,0,0,

0,0,0,0,0,0,0,0,1,0,0,0,

0,0,0,0,0,0,0,0,0,1,0,0,

0,0,0,0,0,0,0,0,0,0,1,0,

0,0,0,0,0,0,0,0,0,0,0,1};

real32_TK_k[108];

real32_Tfv0[81];

staticconstint8_Tiv2[108]={1,0,0,0,0,0,0,0,0,

0,1,0,0,0,0,0,0,0,

0,0,1,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,0,

0,0,0,1,0,0,0,0,0,

0,0,0,0,1,0,0,0,0,

0,0,0,0,0,1,0,0,0,

0,0,0,0,0,0,1,0,0,

0,0,0,0,0,0,0,1,0,

0,0,0,0,0,0,0,0,1};

real32_Tb_r[81];

real32_Tfv1[81];

real32_Tf0;

real32_Tc_P_apriori[36]=

{1,0,0,0,0,0,0,0,0,0,0,0,

0,1,0,0,0,0,0,0,0,0,0,0,

0,0,1,0,0,0,0,0,0,0,0,0};

real32_Tfv2[36];

staticconstint8_Tiv4[36]={1,0,0,

0,1,0,

0,0,1,

0,0,0,

real32_Tc_r[9];

real32_Tb_K_k[36];

real32_Td_P_apriori[72];

staticconstint8_Tiv5[72]

={1,0,0,0,0,0,0,0,0,0,0,0,

0,1,0,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,1,0,0,0,0,0,

0,0,0,0,0,0,0,0,1,0,0,0};

real32_Tc_K_k[72];

staticconstint8_Tiv6[72]={1,0,0,0,0,0,

0,1,0,0,0,0,

0,0,1,0,0,0,

0,0,0,0,0,0,

0,0,0,1,0,0,

0,0,0,0,1,0,

0,0,0,0,0,1,

0,0,0,0,0,0};

real32_Tb_z[6];

staticconstint8_Tiv7[72]

0,0,1,0,0,0,0,0,0,0,0,0,

staticconstint8_Tiv8[72]

={1,0,0,0,0,0,

0,0,0,0,0,0,

0,0,0,1,0,0,

0,0,0,0,0,1};

real32_Tfv3[6];

real32_Tc_z[6];

/*开始计算*/

/*'

wak[]为当前状态三轴角加速度'

wak[0]=x_aposteriori_k[3];

wak[1]=x_aposteriori_k[4];

wak[2]=x_aposteriori_k[5];

∙1

∙2

∙3

∙4

∙5

∙6

∙7

∙8

∙9

∙10

∙11

∙12

∙13

∙14

∙15

∙16

∙17

∙18

∙19

∙20

∙21

∙22

∙23

∙24

∙25

∙26

∙27

∙28

∙29

∙30

∙31

∙32

∙33

∙34

∙35

∙36

∙37

∙38

∙39

∙40

∙41

∙42

∙43

∙44

∙45

∙46

∙47

∙48

∙49

∙50

∙51

∙52

∙53

∙54

∙55

∙56

∙57

∙58

∙59

∙60

∙61

∙62

∙63

∙64

∙65

∙66

∙67

∙68

∙69

∙70

∙71

∙72

∙73

∙74

∙75

∙76

∙77

∙78

∙79

∙80

∙81

∙82

∙83

∙84

∙85

∙86

∙87

∙88

∙89

∙90

∙91

∙92

∙93

∙94

∙95

∙96

∙97

∙98

∙99

∙100

∙101

∙102

∙103

∙104

∙105

∙106

∙107

∙108

∙109

∙110

∙111

∙112

∙113

∙114

∙115

∙116

∙117

∙118

∙119

∙120

∙121

∙122

∙123

∙124

∙125

∙126

∙127

∙128

∙129

∙130

∙131

∙132

∙133

∙134

∙135

∙136

∙137

∙138

∙139

∙140

∙141

∙142

∙143

∙144

∙145

∙146

∙147

∙148

∙149

∙150

∙151

∙152

∙153

∙154

∙155

∙156

∙157

∙158

∙159

∙160

∙161

∙162

/*‘欧拉角旋转矩阵’ 

O=⎡⎣⎢0wzwy−wz0wxwy−wx0⎤⎦⎥

这里的O矩阵相当于A矩阵中的

的转置矩阵!

O[0]=0.0F;

O[1]=-x_aposteriori_k[2];

O[2]=x_aposteriori_k[1];

O[3]=x_aposteriori_k[2];

O[4]=0.0F;

O[5]=-x_aposteriori_k[0];

O[6]=-x_aposteriori_k[1];

O[7]=x_aposteriori_k[0];

O[8]=0.0F;

/*预测转过一个小角度之后的重力向量三轴投影*/

/*a=[1,-delta_z,delta_y;

*delta_z,1,-delta_x;

*-delta_y,delta_x,1]'

;

*/

eye(dv0);

//dv0矩阵单位化

for(i=0;

i<

9;

i++){

a[i]=(real32_T)dv0[i]+O[i]*dt;

}

/*预测转过一个小角度之后的磁力向量三轴投影*/

b_a[i]=(real32_T)dv0[i]+O[i]*dt;

/*

a=⎡⎣⎢1Δz−Δy−Δz1ΔxΔy−Δx1⎤⎦⎥

其实就是这个大家都很眼熟的的余弦矩阵的转置,用来更新机体转过一个角度之后的重力和磁力三轴投影,只不过两次计算间隔时间很短,变化角度很小,因此忽略高阶小量之后就变成了这个样子。

这里还少一个时间系数dt,下面会补上。

⎡⎣⎢cosy∗cosz−cosy∗sinzsiny(sinx∗siny∗cosz)+(cosx∗sinz)−(sinx∗siny∗sinz)+(cosx∗cosz)−sinx∗cosy−(cosx∗siny∗cosz)+(sinx∗sinz)(cosx∗siny∗sinz)+(sinx∗cosz)cosx∗cosy⎤⎦⎥

x_n_b[0]=x_aposteriori_k[0];

//角速度

x_n_b[1]=x_aposteriori_k[1];

x_n_b[2]=x_aposteriori_k[2];

b_x_aposteriori_k[0]=x_aposteriori_k[6];

//加速度

b_x_aposteriori_k[1]=x_aposteriori_k[7];

b_x_aposteriori_k[2]=x_aposteriori_k[8];

z_n_b[0]=x_aposteriori_k[9];

//磁力计

z_n_b[1]=x_aposteriori_k[10];

z_n_b[2]=x_aposteriori_k[11];

3;

c_a[i]=0.0F;

for(i0=0;

i0<

i0++){

c_a[i]+=a[i+3*i0]*b_x_aposteriori_k[i0];

d_a[i]=0.0F;

d_a[i]+=b_a[i+3*i0]*z_n_b[i0];

x_apriori[i]=x_n_b[i]+dt*wak[i];

x_apriori[i+3]=wak[i];

x_apriori[i+6]=c_a[i];

x_apriori[i+9]=d_a[i];

}//得到状态先验估计

/* 

根据上述矩阵运算

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 司法考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1