无人机姿态融合——EKF

5 篇文章 0 订阅
5 篇文章 4 订阅

联系方式:860122112@qq.com

一、实验目的

使用惯性测量单元IMU和磁场传感器(磁力计)的信息,通过EKF对四旋翼无人机进行姿态融合。

二、实验环境

ROS机器人操作系统

三、实验步骤

1. 安装hector quadrotor
hector quadrotor 是德国老牌理工学校Technische Universität Darmstadt大学开发的ros包,整合了ros和gazebo,可以进行uav相关的很多仿真实验,例如飞行动力学,机载传感器例如imu、gps、camera,复杂环境仿真,姿态融合,SLAM等等。

首先下载和编译hector quadrotor的ros包(注意自己安装的ros版本,这里用的是kinetic版)

~$ mkdir catkin_ws/src/hector_quadrotor_tutorial
~$ cd catkin_ws/src/hector_quadrotor_tutorial
$ wstool init src https://raw.github.com/tu-darmstadt-ros-pkg/hector_quadrotor/kinetic-devel/tutorials.rosinstall
$ cd ../..
~/catkin_ws$ catkin_make
~/catkin_ws$ source devel/setup.bash

然后可以启动launch文件(共有两个,一个是outdoor,一个是indoor)测试无人机了。

~/catkin_ws$ roslaunch hector_quadrotor_demo outdoor_flight_gazebo.launch

或者

~/catkin_ws$ roslaunch hector_quadrotor_demo indoor_slam_gazebo.launch

想要用键盘控制无人机首先要启动无人机的电机

$ rosservice call /enable_motors true

再启动键盘控制节点

$ rosrun teleop_twist_keyboard teleop_twist_keyboard.py

测试效果图
outdoor
这里写图片描述
这里写图片描述

indoor
这里写图片描述
这里写图片描述

参考教程

2. EKF姿态融合

这里使用了两种EKF方法进行姿态融合
第一种的参考文献在此
第二种的参考文献在此
其中第二种基于四元数实现。

算法实现及使用:
首先下载和编译算法代码ros包

~$ cd catkin_ws/src/
~/catkin_ws/src$ git clone https://github.com/DajunZhou/uav_att_EKF.git
~/catkin_ws/src$ cd ..
~/catkin_ws$ catkin_make
~/catkin_ws$ source devel/setup.bash

启动测试环境(可以自己写一个empty world的测试环境):

~/catkin_ws$ roslaunch hector_quadrotor_demo outdoor_flight_gazebo.launch
~/catkin_ws$ roslaunch uav_att_EKF uav_att_est.launch

(上面使用了两个终端)

启动算法节点(因为是使用python实现,包含了自己实现的类,所以用python启动)
第一种算法

~/catkin_ws$ cd src/uav_att_EKF/scripts/
$ python uav_att_node.py

启动键盘控制

$ rosservice call /enable_motors true
$ rosrun teleop_twist_keyboard teleop_twist_keyboard.py

姿态融合效果
src="http://player.youku.com/embed/XMjgxNDc1MzMzNg==" width="800" height="500">

第二种算法

~/catkin_ws$ cd src/uav_att_EKF/scripts/
$ python uav_att_2stageEKF_node.py

启动键盘控制

$ rosservice call /enable_motors true
$ rosrun teleop_twist_keyboard teleop_twist_keyboard.py

姿态融合效果
src="http://player.youku.com/embed/XMjgxNTYzMDU5Mg==" width="800" height="500">

四、结果分析

从视频上看,在旋转时,对于无人机的偏航角第一种方法比第二种方法响应更快,估计更准。分析原因:第一种算法使用加速度/磁力计矫正时,可同时对俯仰角、滚动角和偏航角进行矫正,且状态矩阵共12维,包含信息更多;第二种方法状态使用的是四元数,加速度计不矫正偏航角,磁力计只矫正偏航角,由于实验环境中IMU的频率是100Hz,磁力计是10Hz,所以无人机偏航角的估计会比较慢。但从计算量和计算时间的角度来说,第二种方法应该会优于第一种方法。

参考文献
Comprehensive Simulation of Quadrotor UAVs Using ROS and Gazebo
A Double-Stage Kalman Filter for Orientation Tracking With an Integrated Processor in 9-D IMU


  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,EKF C语言六轴姿态融合算法是一种使用扩展卡尔曼滤波器(EKF)进行六轴姿态融合的算法。该算法使用加速度计和磁力计来估计姿态,并使用EKF融合两个感器的数据。在加速度计为0的条件下,该算法可以准确地估计姿态。在后续的融合算法中,加速度计和磁力计只起到修正的作用,影响不大。 以下是一个简单的EKF C语言六轴姿态融合算法的示例: ```c #include <stdio.h> #include <math.h> #define PI 3.14159265358979323846 // 定义加速度计和磁力计的数据结构 typedef struct { double x; double y; double z; } Vector3; // 定义姿态的数据结构 typedef struct { double roll; double pitch; double yaw; } Attitude; // 定义EKF的数据结构 typedef struct { double q0; double q1; double q2; double q3; double p[3]; double k[4]; double h[4]; double f[16]; double q[16]; double r[4]; double x[4]; double z[4]; double y[4]; double s[4]; double t[16]; } EKF; // 初始化EKF void EKF_Init(EKF *ekf) { ekf->q0 = 1.0; ekf->q1 = 0.0; ekf->q2 = 0.0; ekf->q3 = 0.0; ekf->p[0] = 0.0; ekf->p[1] = 0.0; ekf->p[2] = 0.0; ekf->k[0] = 0.0; ekf->k[1] = 0.0; ekf->k[2] = 0.0; ekf->k[3] = 0.0; ekf->h[0] = 0.0; ekf->h[1] = 0.0; ekf->h[2] = 0.0; ekf->h[3] = 0.0; ekf->f[0] = 1.0; ekf->f[1] = 0.0; ekf->f[2] = 0.0; ekf->f[3] = 0.0; ekf->f[4] = 0.0; ekf->f[5] = 1.0; ekf->f[6] = 0.0; ekf->f[7] = 0.0; ekf->f[8] = 0.0; ekf->f[9] = 0.0; ekf->f[10] = 1.0; ekf->f[11] = 0.0; ekf->f[12] = 0.0; ekf->f[13] = 0.0; ekf->f[14] = 0.0; ekf->f[15] = 1.0; ekf->q[0] = 0.01; ekf->q[1] = 0.0; ekf->q[2] = 0.0; ekf->q[3] = 0.0; ekf->q[4] = 0.0; ekf->q[5] = 0.01; ekf->q[6] = 0.0; ekf->q[7] = 0.0; ekf->q[8] = 0.0; ekf->q[9] = 0.0; ekf->q[10] = 0.01; ekf->q[11] = 0.0; ekf->q[12] = 0.0; ekf->q[13] = 0.0; ekf->q[14] = 0.0; ekf->q[15] = 0.01; ekf->r[0] = 0.1; ekf->r[1] = 0.0; ekf->r[2] = 0.0; ekf->r[3] = 0.1; ekf->x[0] = 1.0; ekf->x[1] = 0.0; ekf->x[2] = 0.0; ekf->x[3] = 0.0; } // 更新EKF void EKF_Update(EKF *ekf, Vector3 acc, Vector3 mag, double dt) { double ax = acc.x; double ay = acc.y; double az = acc.z; double mx = mag.x; double my = mag.y; double mz = mag.z; double q0 = ekf->q0; double q1 = ekf->q1; double q2 = ekf->q2; double q3 = ekf->q3; double p0 = ekf->p[0]; double p1 = ekf->p[1]; double p2 = ekf->p[2]; double k0 = ekf->k[0]; double k1 = ekf->k[1]; double k2 = ekf->k[2]; double k3 = ekf->k[3]; double h0 = ekf->h[0]; double h1 = ekf->h[1]; double h2 = ekf->h[2]; double h3 = ekf->h[3]; double f0 = ekf->f[0]; double f1 = ekf->f[1]; double f2 = ekf->f[2]; double f3 = ekf->f[3]; double f4 = ekf->f[4]; double f5 = ekf->f[5]; double f6 = ekf->f[6]; double f7 = ekf->f[7]; double f8 = ekf->f[8]; double f9 = ekf->f[9]; double f10 = ekf->f[10]; double f11 = ekf->f[11]; double f12 = ekf->f[12]; double f13 = ekf->f[13]; double f14 = ekf->f[14]; double f15 = ekf->f[15]; double q0q0 = q0 * q0; double q0q1 = q0 * q1; double q0q2 = q0 * q2; double q0q3 = q0 * q3; double q1q1 = q1 * q1; double q1q2 = q1 * q2; double q1q3 = q1 * q3; double q2q2 = q2 * q2; double q2q3 = q2 * q3; double q3q3 = q3 * q3; double norm; double hx; double hy; double hz; double bx; double bz; double vx; double vy; double vz; double wx; double wy; double wz; double ex; double ey; double ez; double qa; double qb; double qc; double qd; double s0; double s1; double s2; double s3; double s4; double s5; double s6; double s7; double s8; double s9; double s10; double s11; double s12; double s13; double s14; double s15; double t0; double t1; double t2; double t3; double t4; double t5; double t6; double t7; double t8; double t9; double t10; double t11; double t12; double t13; double t14; double t15; // 计算加速度计和磁力计的模 norm = sqrt(ax * ax + ay * ay + az * az); ax /= norm; ay /= norm; az /= norm; norm = sqrt(mx * mx + my * my + mz * mz); mx /= norm; my /= norm; mz /= norm; // 计算磁力计的方向 hx = mx * q0q0 - 2.0 * q0 * my * q3 + 2.0 * q0 * mz * q2 + mx * q1q1 + 2.0 * q1 * my * q2 + 2.0 * q1 * mz * q3 - mx * q2q2 - my * q1q1 + 2.0 * q2 * mz * q3 - mz * q0q0 - mz * q1q1; hy = 2.0 * q0 * mx * q3 + my * q0q0 - 2.0 * q0 * mz * q1 + 2.0 * q1 * mx * q2 - my * q2q2 + my * q3q3 + 2.0 * q2 * mz * q3 - mz * q1q1 - mz * q2q2; hz = 2.0 * q0 * my * q1 + 2.0 * q0 * mz * q0 + mz * q1q1 - my * q2q2 + 2.0 * q1 * mx * q3 - mz * q3q3 + 2.0 * q2 * my * q3 - mx * q1q1 - mx * q2q2; bx = sqrt((hx * hx) + (hy * hy)); bz = hz; // 计算预测状态 vx = 2.0 * (q1q3 - q0q2); vy = 2.0 * (q0q1 + q2q3); vz = q0q0 - q1q1 - q2q2 + q3q3; wx = 2.0 * bx * (0.5 - q2q2 - q3q3) + 2.0 * bz * (q1q3 - q0q2); wy = 2.0 * bx * (q1q2 - q0q3) + 2.0 * bz * (q0q1 + q2q3); wz = 2.0 * bx * (q0q2 + q1q3) + 2.0 * bz * (0.5 - q1q1 - q2q2); ex = (ay * vz - az * vy) + (my * wz - mz * wy); ey = (az * vx - ax * vz) + (mz * wx - mx * wz); ez = (ax * vy - ay * vx) + (mx * wy - my * wx); ekf->x[0] += dt * (q1 * ex + q2 * ey + q3 * ez); ekf->x[1] += dt * (q0 * ex + q2 * ez - q3 * ey); ekf->x[2] += dt * (q0 * ey - q1 * ez + q3 * ex); ekf->x[3] += dt * (q0 * ez + q1 * ey - q2 * ex); // 计算雅可比矩阵 s0 = q0q0 + q1q1 - q2q2 - q3q3; s1 = 2.0 * (q1 * q2 + q0 * q3); s2 = 2.0 * (q1 * q3 - q0 * q2); s3 = 2.0 * (q1 * q2 - q0 * q3); s4 = q0q0 - q1q1 + q2q2 - q3q3; s5 = 2.0 * (q2 * q3 + q0 * q1); s6 = 2.0 * (q1 * q3 + q0 * q2); s7 = 2.0 * (q2 * q3 - q0 * q1); s8 = q0q0 - q1q1 - q2q2 + q3q3; t0 = 2.0 * (-q2q2 - q3q3); t1 = 2.0 * (q1q2 - q0q3); t2 = 2.0 * (q1q3 + q0q2); t3 = 2.0 * (q1q2 + q0q3); t4 = 2.0 * (-q1q1 - q3q3); t5 = 2.0 * (q
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值