使用橢圓擬合做電子羅盤校正
本帖最后由 john800422 于 2013-4-8 00:27 编辑自己做的, 分享下
主要是參考
"橢圓直接擬合算法研究"
以Mathematica做實現
附有C及推導
流程:
最小二乘法→解方程組→代推導結果→校正電子羅盤數據→使用atan2求解航向角
=========== 推導 =======================================
=========== Mathematica實現 ===============================
=========== C語言實現 ===================================
void EllipseFitting( float* Ans, short* MegDataX, short* MegDataY, unsigned char Num )
{
char i, j, k;
float temp, temp1, temp2;
float tempArrX = {0}, tempArrY = {0};
float MEG_X1Y0 = 0.0f;
float MEG_X2Y0 = 0.0f;
float MEG_X3Y0 = 0.0f;
float MEG_X0Y1 = 0.0f;
float MEG_X0Y2 = 0.0f;
float MEG_X0Y3 = 0.0f;
float MEG_X0Y4 = 0.0f;
float MEG_X1Y1 = 0.0f;
float MEG_X2Y1 = 0.0f;
float MEG_X1Y2 = 0.0f;
float MEG_X1Y3 = 0.0f;
float MEG_X2Y2 = 0.0f;
float MEG_X3Y1 = 0.0f;
float MegArr = {0};
/* 因為累加數值會太大, 故除1000 */
for(i=0; i<Num; i++) {
tempArrX = (float)MegDataX/1000.0f;
tempArrY = (float)MegDataY/1000.0f;
}
for(i=0; i<Num; i++) {
MEG_X1Y0 += tempArrX;
MEG_X2Y0 += tempArrX*tempArrX;
MEG_X3Y0 += tempArrX*tempArrX*tempArrX;
MEG_X0Y1 += tempArrY;
MEG_X0Y2 += tempArrY*tempArrY;
MEG_X0Y3 += tempArrY*tempArrY*tempArrY;
MEG_X0Y4 += tempArrY*tempArrY*tempArrY*tempArrY;
MEG_X1Y1 += tempArrX*tempArrY;
MEG_X2Y1 += tempArrX*tempArrX*tempArrY;
MEG_X1Y2 += tempArrX*tempArrY*tempArrY;
MEG_X1Y3 += tempArrX*tempArrY*tempArrY*tempArrY;
MEG_X2Y2 += tempArrX*tempArrX*tempArrY*tempArrY;
MEG_X3Y1 += tempArrX*tempArrX*tempArrX*tempArrY;
}
MegArr = MEG_X2Y2;
MegArr = MEG_X1Y3;
MegArr = MEG_X2Y1;
MegArr = MEG_X1Y2;
MegArr = MEG_X1Y1;
MegArr = -MEG_X3Y1;
MegArr = MEG_X1Y3;
MegArr = MEG_X0Y4;
MegArr = MEG_X1Y2;
MegArr = MEG_X0Y3;
MegArr = MEG_X0Y2;
MegArr = -MEG_X2Y2;
MegArr = MEG_X2Y1;
MegArr = MEG_X1Y2;
MegArr = MEG_X2Y0;
MegArr = MEG_X1Y1;
MegArr = MEG_X1Y0;
MegArr = -MEG_X3Y0;
MegArr = MEG_X1Y2;
MegArr = MEG_X0Y3;
MegArr = MEG_X1Y1;
MegArr = MEG_X0Y2;
MegArr = MEG_X0Y1;
MegArr = -MEG_X2Y1;
MegArr = MEG_X1Y1;
MegArr = MEG_X0Y2;
MegArr = MEG_X1Y0;
MegArr = MEG_X0Y1;
MegArr = Num;
MegArr = -MEG_X2Y0;
/* 解方程組 */
for(i=0; i<5; i++)
for(j=i+1; j<6; j++)
for(k=5; k>i-1; k--)
MegArr = MegArr - MegArr/MegArr*MegArr;
for(i=0; i<5; i++) {
temp = MegArr;
for(j=i; j<6; j++)
MegArr = MegArr/temp;
}
for(j=4; j>0; j--)
for(i=0; i<j; i++)
MegArr = MegArr - MegArr*MegArr;
/* 解算橢圓參數 */
temp = (1-MegArr)/MegArr;
temp1 = temp + sqrtf(temp*temp+1.0f);
Ans = atanf(temp1); /* Theta */
temp = MegArr*MegArr-4*MegArr;
Ans = (2.0f*MegArr*MegArr-MegArr*MegArr)/temp; /* X0 */
Ans = (2.0f*MegArr-MegArr*MegArr)/temp; /* Y0 */
temp= (Ans*Ans+MegArr*Ans*Ans+MegArr*Ans*Ans-MegArr)*(temp1*temp1*temp1*temp1-1.0f);
temp2 = cosf(Ans);
Ans = temp2/sqrtf((MegArr*temp1*temp1-1)/temp); /* a */
Ans = temp2/sqrtf((temp1*temp1-MegArr)/temp); /* b */
/* 將之前除的1000補回來 */
Ans = Ans*1000.0f;
Ans = Ans*1000.0f;
Ans = Ans*1000.0f;
Ans = Ans*1000.0f;
} 顶一个,论坛上之前有用matlab拟合的,我是用那个matlab拟合校正的,效果很好。 zywei_09 发表于 2013-4-8 09:44 static/image/common/back.gif
顶一个,论坛上之前有用matlab拟合的,我是用那个matlab拟合校正的,效果很好。 ...
不知可貼個連結不?
最近也在學Matlab
想說用Matlab寫個接收STM32的示波器看看
john800422 发表于 2013-4-8 10:41 static/image/common/back.gif
不知可貼個連結不?
最近也在學Matlab
http://www.amobbs.com/forum.php?mod=viewthread&tid=5488742&highlight=5883
《分享一种校准HMC5883的方法,此法也可以校验其他双轴... 》
我是把5883的数据读回来输入到Matlab里拟合的。 记号一下, zywei_09 发表于 2013-4-9 08:30 static/image/common/back.gif
http://www.amobbs.com/forum.php?mod=viewthread&tid=5488742&highlight=5883
《分享一种校准HMC5883的 ...
感謝提供連結
又學到了一些~
不過因為這需要用在四軸上的
送回Matlab的方法貌似不方便 john800422 发表于 2013-4-9 12:19 static/image/common/back.gif
感謝提供連結
又學到了一些~
还好,因为不是每次都要校准,校准一次基本就可以了。除非环境变化比较大。其实真正的校准是应该是把一般椭球体校准成球体。。。。 指南针是轴三的数据,楼主只要稍微改一下变成椭球拟合就可以修正三轴罗盘了 zywei_09 发表于 2013-4-9 18:00 static/image/common/back.gif
还好,因为不是每次都要校准,校准一次基本就可以了。除非环境变化比较大。其实真正的校准是应该是把一般 ...
每次換環境
圓心似乎都會偏移
所以才每次啟動都先校正
等有空再來測試環境對航向角的誤差影響
__@ 发表于 2013-4-10 12:10 static/image/common/back.gif
指南针是轴三的数据,楼主只要稍微改一下变成椭球拟合就可以修正三轴罗盘了 ...
似乎會複雜許多
尤其是推導橢圓參數的部分 这个是椭圆到圆的平面矫正,只要倾角大了还是不行,用椭球到圆球的约束矫正会得到更好的效果。 楼主,台湾教的是mathematica吗?
国内学校教的是matlab。 kmani 发表于 2013-10-8 09:58 static/image/common/back.gif
楼主,台湾教的是mathematica吗?
国内学校教的是matlab。
工程科系幾乎都是教 matlab
mathematica 是自學的 之前因为考试一直没有往下做,这两天来看,台湾兄都进展这么深入了 谢谢分享。。。。。。。 这个必须顶起 楼主大人,我想问下求出椭圆的五个参数之后怎样把它校准为圆啊? 支持了 不错哦 silence2455 发表于 2014-4-4 19:20
楼主大人,我想问下求出椭圆的五个参数之后怎样把它校准为圆啊?
長軸除以長軸,短軸除以短軸,就會變成單位圓了 楼主大哥,请问一下,你这里面得到的a和b应该是长短半轴吧?那么进行缩放的时候怎么知道是X方向的轴更长还是Y方向的轴更长呢? silence2455 发表于 2014-4-10 14:56
楼主大哥,请问一下,你这里面得到的a和b应该是长短半轴吧?那么进行缩放的时候怎么知道是X方向的轴更长还 ...
可以通過角度或是取樣數據得知。 大神膜拜,留个记号以后肯定要用到 这个必须mark,谢谢LZ的分享。{:handshake:} 膜拜大神,学到很多 我想问5883的程序流程图是怎样的? 楼主大人,我用你的这个函数EllipseFitting进行程序校准,发现一加上这个函数就会导致程序复位,是不是因为太费时了?请问你有没有遇到这个问题啊? 楼主我问一下采集数据时旋转罗盘时一定要在水平面内吗 孤单片机器人 发表于 2014-8-21 13:55
楼主我问一下采集数据时旋转罗盘时一定要在水平面内吗
目前橢圓擬合僅校正旋轉的平面,
無法校正三維空間
mark LZ,去年我也用过椭圆拟合的方法校正磁场,发现软磁(Theta )有问题,用此方法校正之后有可能会出现角度的静差,请问你有什么办法解决么?拜谢~ yang9769 发表于 2014-8-22 17:08
LZ,去年我也用过椭圆拟合的方法校正磁场,发现软磁(Theta )有问题,用此方法校正之后有可能会出现角度的 ...
橢圓擬合僅是將已知數據擬合出橢圓形,並假設之後讀取到的數據依然會分布在該橢圓上,
所以若是環境磁場變化,讀到的數據就不一定會分布在橢圓上,轉換出來的角度就會不準確。
假設環境磁場變化不大的話,可以使用陀螺儀作為主要測量方位的裝置,定期透過電子羅盤來校正陀螺儀。 john800422 发表于 2014-8-22 22:32
橢圓擬合僅是將已知數據擬合出橢圓形,並假設之後讀取到的數據依然會分布在該橢圓上,
所以若是環境磁場 ...
计算这个对单片机的要求挺高吧 其实原理很简单的,最小二乘问题求解在微积分和线性代数都有提到,各位可以多看看书 这个收藏一下{:lol:} 感谢分享{:smile:} 不错,谢谢分享 这个用来校准软磁可能还不错,关键看运算效率 谢谢楼主~最近在搞四轴~ 随影 发表于 2015-1-26 07:18
谢谢楼主~最近在搞四轴~
回答你的問題 http://www.amobbs.com/forum.php?mod=redirect&goto=findpost&ptid=5605744&pid=8384377
switch((u16)(Correction_Time/600)) {
case n:
MagDataX = (s16)MoveAve_WMA(Mag.X, MAG_FIFO, MagCorrectionAve);
MagDataY = (s16)MoveAve_WMA(Mag.Y, MAG_FIFO, MagCorrectionAve);
break;
...
default:
Correction_Time = 0;
EllipseFitting(Ellipse, MagDataX, MagDataY, 8);
Mag.OffsetX = Ellipse;
Mag.OffsetY = Ellipse;
SensorMode = Mode_Algorithm;// 切換至運算模式
break;
}
(Correction_Time/600) 決定每一個 case 會執行的時間與次數。
case 的 n = 0 ~ 7,表示 360 度取樣 8 個點,分別為 0(360), 45, 90, 135, 180, 225, 270, 315
每一個取樣點裡面紀錄 X, Y 軸的磁力大小,MoveAve_WMA 只是求多筆資料的平均值。
所以跑完 case0 ~ case7 會有 8*2 筆磁力計資料(取完平均值的),將這些資料放入橢圓擬合計算橢圓參數。
本帖最后由 随影 于 2015-1-28 15:28 编辑
john800422 发表于 2015-1-26 17:29
回答你的問題 http://www.amobbs.com/forum.php?mod=redirect&goto=findpost&ptid=5605744&pid=8384377
...
恩恩,谢谢楼主大神,我都懂你的思路了。我的还有一个疑问在于。。这两个数组为什么要这样子用呢? 我个人的思维想法会做两个不同的数组。而楼主的处理在于用了一个数组。仅仅是头部相差1?这中间有什么精妙的算法吗? 本帖最后由 john800422 于 2015-1-30 13:20 编辑
随影 发表于 2015-1-28 15:27
恩恩,谢谢楼主大神,我都懂你的思路了。我的还有一个疑问在于。。这两个数组为什么要这样子用呢? 我 ...
只是指針與數組的用法而已 mark Mathematica 好东西 真心有帮助 mark 先标记一下 请问椭圆拟合后解算出来的角度Θ怎么利用 PANGKUN 发表于 2015-5-4 12:04
请问椭圆拟合后解算出来的角度Θ怎么利用
旋轉回水平 xj=cos(-thetarad)/a*(X-x0)-sin(-thetarad)/a*(Y-y0);
yj=sin(-thetarad)/b*(X-x0)+cos(-thetarad)/b*(Y-y0);是这样吗 高手啊,这个方程算起来挺复杂的。
for(i=0; i<5; i++)
for(j=i+1; j<6; j++)
for(k=5; k>i-1; k--)
MegArr = MegArr - MegArr/MegArr*MegArr;
for(i=0; i<5; i++) {
temp = MegArr;
for(j=i; j<6; j++)
MegArr = MegArr/temp;
}
for(j=4; j>0; j--)
for(i=0; i<j; i++)
MegArr = MegArr - MegArr*MegArr;
看起来就很牛逼的样子,实际上更牛逼! 好贴必须顶起!!!! mark下,,学习了~~ curve fitting 思路是正确的,但是用的时候依然会有问题,不是数学上的问题,而是工程上的问题。
来自国内外的朋友,我很想和你继续讨论这个问题。 westloveohyeah 发表于 2015-10-28 22:23
curve fitting 思路是正确的,但是用的时候依然会有问题,不是数学上的问题,而是工程上的问题。
来自国内 ...
有問題可以直接在這裡提出,或許其他人有會有類似問題。
實際的四軸磁力計校正實現可以參考下面,使用 MPU9150,一圈取 8 的點做採樣
https://github.com/QCopter/QCopterFlightControl/blob/d79ff6a8ab07dd373d9e41f98af74c1594ed61a0/Software/QCopterFC_FlightControl/Program_System/QCopterFC_it.c
john800422 发表于 2015-10-28 23:04
有問題可以直接在這裡提出,或許其他人有會有類似問題。
實際的四軸磁力計校正實現可以參考下面,使用 M ...
等我的论文发表出来,投稿在IEEE trans 罗盘校准mark一下下 这个我也做出来了,不过现在需要实时修正,不知有没有思路?
页:
[1]