5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 3320|回复: 23
打印 上一主题 下一主题

我还是来开个源吧,有兴趣的就来看看

[复制链接]
跳转到指定楼层
楼主
发表于 2011-6-25 01:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
别的啰啰嗦嗦的代码就不贴了,对于会做OSD的来说都是小菜
贴核心点的,姿态解算的微分方程
我这个是自己推导的简化方程,属于有误差的公式
而四元数则不存在理论误差的
我这个的计算精度跟姿态计算频率有关,频率越高,误差越小
跟其他的算法相比,特点是计算量小得多、便于和加速度计融合
实际试验表明,只要精确校准了传感器,全姿态误差是在可接受的范围内(测试视频见我另外一个贴,里面就是用这个方程做的,那个视频融合参数没调好,受加速度影响较大)

这两天在对比和四元数算法的差异
我这个方程的特点是,只要运动角度不太大(接近90度或连续滚转),它的往复累计误差是相当小的,不加修正都可以归零
而四元数则不然,虽然每次运动角度都不大,但反复运动若干次后,不可避免的计算误差就出来了(估计是三角函数和双精度数的误差反复乘积造成的,因为每次姿态解算,它的乘除次数太多了)
但四元数的特点是,经过校准传感器后,在全姿态或连续滚转情况下误差并不大
可以说各有千秋吧
有兴趣的可以看看,说不定会有所启发

=================================================================
double dd,xa,ya,za;
double gxx,gyy,gzz;
double w,dw1,dw2,th; //ω,dω1,dω2,θ
double cw,sw,sth;  //cos(ω),sin(ω),sin(θ)
double sa;

//gxx,gyy,gzz:从上次计算到这次计算之间陀螺积分出来的角度值
//za:Z轴角度,z轴垂直时为90度,水平时为0度,-90~+90
//xa:横滚轴和水平面夹角,-90~90度
//ya:俯仰轴和水平面夹角,-90~90度
//absd()双精度数的取绝对值
//--------------------计算x角-----------------------------
//计算ωx引起的x角变化量
if( za<0 ) w=-gxx;  
else w=gxx;
th=ya+PI2;
sw=sin(w);cw=cos(w);sth=sin(th);sa=sin(xa);
if( absd(sth)<=absd(sa) ) //sth=sa;
  dw1=asin( sa*cw )-xa;
else dw1=asin( sw*sqrt(sth*sth-sa*sa)+sa*cw )-xa;

//计算ωz引起的x角变化量
if( ya<0 ) w=-gzz;
else w=gzz;
th=za+PI2;
sw=sin(w);cw=cos(w);sth=sin(th);
if( absd(sth)<=absd(sa) ) //sth=sa;
  dw2=asin( sa*cw)-xa;
else dw2=asin( sw*sqrt(sth*sth-sa*sa)+sa*cw)-xa;
//计算x角的陀螺计算值
xa+=dw1+dw2;
//--------------------计算y角-----------------------------
//计算ωy引起的y角变化量
if( za<0 ) w=-gyy;
else w=gyy;
th=xa+PI2;
sw=sin(w);cw=cos(w);sth=sin(th);sa=sin(ya);
if( absd(sth)<absd(sa) ) //sth=sa;
  dw1=asin( sa*cw)-ya;
else dw1=asin( sw*sqrt(sth*sth-sa*sa)+sa*cw)-ya;
//------------计算ωz引起的y角变化量--------------
if( xa<0 ) w=gzz;
else w=-gzz;
th=za+PI2;
sw=sin(w);cw=cos(w);sth=sin(th);
if( absd(sth)<absd(sa) ) //sth=sa;
  dw2=asin( sa*cw)-ya;
else dw2=asin( sw*sqrt(sth*sth-sa*sa)+sa*cw)-ya;
//计算y角的陀螺计算值
ya+=dw1+dw2;

//--------------------计算z角-----------------------------
sw=sin(x_angle);sw*=sw;
cw=sin(y_angle);cw*=cw;
sth=sqrt(sw+cw); //sth=sqrt(sinx*sinx+siny*siny)
dd=asin(sth)+PI2;
if( dd>PI2 ) dd=PI-dd;
if( z_acc<0 ) dd*=-1;
za=dd;

和加速度融合是自己搞的一种正交滤波器
滤波器参数还在调整中,要不断试飞寻找合适参数,麻烦得很
估计近期会出测试视频

欢迎继续阅读楼主其他信息

沙发
 楼主| 发表于 2011-6-25 01:23 | 只看该作者
上面忘了说明,PI2=PI/2
3
发表于 2011-6-25 02:00 | 只看该作者
:em17: 书读得少看不懂
帮顶:em15:
4
发表于 2011-6-25 02:09 | 只看该作者
:em20:
5
发表于 2011-6-25 03:39 | 只看该作者
:em26: 我也搞过,放弃了,觉得过于复杂。
6
发表于 2011-6-25 06:44 | 只看该作者
:em20:
7
发表于 2011-6-27 06:14 | 只看该作者
很喜欢开源的东西,谢了
8
发表于 2011-6-29 20:41 | 只看该作者
谢谢LZ分享,数学原理有些深奥,等会儿弄到arduino上试一试。
9
发表于 2011-6-29 22:09 | 只看该作者
楼主,以下三个变量无定义:
x_angle
y_angle
z_acc

我假设他们为xa,ya,za了。

还有,你的输入gxx,gyy,gzz是弧度值吧,我用传感器的值放进去,最后的结果看不懂。

我发现我的AVR片子,跟不上你的算法速度。代码表面上看,运算量可能比四元数还要大。
10
 楼主| 发表于 2011-6-29 22:53 | 只看该作者
原帖由 dongfang 于 2011-6-29 22:09 发表
楼主,以下三个变量无定义:
x_angle
y_angle
z_acc

我假设他们为xa,ya,za了。

还有,你的输入gxx,gyy,gzz是弧度值吧,我用传感器的值放进去,最后的结果看不懂。

我发现我的AVR片子,跟不上你的算法速度 ...

对的,x_angle就是xa
所有角度都是弧度值,gxx,gyy,gzz是陀螺上次到这次间隔的角速率积分值哦,不是陀螺的角速率
AVR没玩过,不了解性能
不过运算量不可能比四元数大吧:em17:
你看看四元数需要多少次计算三角函数,其结果全是double的,还要乘除
实再不行你用float试试,可能AVR算双精度太慢

[ 本帖最后由 dstdx72 于 2011-6-29 22:56 编辑 ]
11
 楼主| 发表于 2011-6-29 22:56 | 只看该作者
:em16: 你不会是用的8位的AVR吧
12
发表于 2011-6-30 01:07 | 只看该作者
看不懂
13
发表于 2011-6-30 07:57 | 只看该作者
是8位的AVR,12M的ATMEGA328。而且编译器早就把double等同于float了。我回头算一下计算量的负载。

我不是每次更新四元数姿态时都获取新的欧拉角,因此工作量不是很大。
14
 楼主| 发表于 2011-6-30 17:57 | 只看该作者
原帖由 dongfang 于 2011-6-30 07:57 发表
是8位的AVR,12M的ATMEGA328。而且编译器早就把double等同于float了。我回头算一下计算量的负载。

我不是每次更新四元数姿态时都获取新的欧拉角,因此工作量不是很大。

那你最好还是上STM32,8位机搞这个基本没实用价值的,运算量要求摆在那里
要实用的话必须每次都要换成欧拉角的,不然无法使用滤波器和加速度计融合
要是滤波器融合也用四元数的话,那运算量就会更大了(因为相当于两个欧拉角相加的运算,换成四元数是相乘的,而四元数相乘得有4组方程才行)
15
发表于 2011-7-1 14:39 | 只看该作者
四元数相乘的运算量不大的,就下面那几句,乘法在AVR里是一个周期完成的指令。

        c.w=w*b.w        -x*b.x        -y*b.y        -z*b.z;
        c.x=w*b.x        +x*b.w        +y*b.z        -z*b.y;
        c.y=w*b.y        -x*b.z        +y*b.w        +z*b.x;
        c.z=w*b.z        +x*b.y        -y*b.x        +z*b.w;

加速度传感器不能产生偏航角,我又不想用磁感应器。估计得先从四元数中解出一个偏航角,再叠加加速度数据,构成一个加速度4元数。这个加速度4元数和角速度4元数的融合,暂时没想清楚怎么做。
16
发表于 2011-7-2 18:09 | 只看该作者
四元数计算量又不算大,涉及三角函数就是三个反三角函数调用,比起欧拉角的好处是越过奇点不会飘。
我用M3的STM32,没跑满72M,整个循环也就是2ms,相对20ms的循环间隔那是毛毛雨。。。。
17
发表于 2011-7-2 18:15 | 只看该作者
偏航角不用算,我也在这个问题上纠结过,不过后来想通了,偏航角完全由GPS来定好了。
比如有风的情况下,你觉得飞机头朝家回航好,还是整个飞机的实际飞行方向朝家好呢?
不过如果风大到比飞机空速还快,这时用GPS的方向就对导航有误导作用了。
不过即使你做到没问题,飞机还能回来吗?
18
 楼主| 发表于 2011-7-2 21:29 | 只看该作者
原帖由 heuyck 于 2011-7-2 18:09 发表
四元数计算量又不算大,涉及三角函数就是三个反三角函数调用,比起欧拉角的好处是越过奇点不会飘。
我用M3的STM32,没跑满72M,整个循环也就是2ms,相对20ms的循环间隔那是毛毛雨。。。。

等你继续下去,到把整个系统全部完,成你就晓得2ms不是毛毛雨了
实际上对于有效的姿态系统,绝大部分运算时间还是花在信号调理上的,也就是传感器数据的预处理
不管是数字陀螺还是模拟的,还有加速度计,原始信号不加以处理就拿来用是不可靠的
另外另外还有PPM采样、控制的开销
还有通讯上花的时间也相当惊人(除非你搞的是简单系统,不传送姿态和接受命令)
还要为系统可靠性留出相当程度的富余
这时你再看看时间还够用不
再说了,你的测算可能不很准,一次四元数姿态运算下来应该不止2ms的,反三角函数运算花的时间是最多的,其次是三角函数,乘除法对于stm32来说虽然都是单周期的
但像4元素那样的方程,一组方程里面包含若干加减乘除,那就不是几个周期能完成的
你可以编译后运行,然后断点,然后切换到反汇编,你就晓得一组只包含乘除加减的公式,汇编后要多少指令和寄存器数据转移才能完成了
用stm32f103测耗时很方便的,用systick里面的计时器可以准确测量每个循环花了多少时间
不晓得你的系统构成,反正在我的系统上用4元数法的话,必须把姿态计算频率降低到25~30Hz才能保证可靠
19
发表于 2011-7-2 21:40 | 只看该作者
:em26:
20
 楼主| 发表于 2011-7-2 21:45 | 只看该作者
原帖由 heuyck 于 2011-7-2 18:15 发表
偏航角不用算,我也在这个问题上纠结过,不过后来想通了,偏航角完全由GPS来定好了。
比如有风的情况下,你觉得飞机头朝家回航好,还是整个飞机的实际飞行方向朝家好呢?
不过如果风大到比飞机空速还快,这时用GPS ...

恭喜,答对了
这类AHRS系统中的H,也就是heading,是靠GPS来完成的
所以此类系统不能算是惯性导航,只能说是惯性平衡
飞行中,航向永远是处于不停调整中的,如果想靠机头固定一个指向来作为回家依据,那么飞机十有八九是回不了家的
因为高空中,只有风大风小的区别,没有风,是不可能的,因为我们的飞机飞不出对流层
如果风太大,超过了飞机的空速,这种算法就会出大问题,飞机就会南辕北辙地飞
所以必须引入抗风算法,依靠GPS速度值、油门输出、加速度数据,和平时飞行时积累的数据,来判断是否逆风飞行,并在地速降低到0以前加大油门
这就是抗风智能
我的OSD里面就用了这个,但效果如何还没经过检验
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /2 下一条

快速回复 返回顶部 返回列表