|
楼主 |
发表于 2013-3-21 09:56:31
|
显示全部楼层
本帖最后由 seanwood 于 2013-3-21 10:00 编辑
有人问加电子罗盘的融合是怎么回事,我再献丑一回,开课讲解喽,来鼓掌来顶
我嚓,顶楼不能编辑的,只好放在楼中间了。这也好,给肯挨页翻帖子的朋友一个惊喜。- //=====================================================================================================
- // AHRS.c
- // S.O.H. Madgwick
- // 25th August 2010
- //=====================================================================================================
- // Description:
- //
- // Quaternion implementation of the 'DCM filter' [Mayhony et al]. Incorporates the magnetic distortion
- // compensation algorithms from my filter [Madgwick] which eliminates the need for a reference
- // direction of flux (bx bz) to be predefined and limits the effect of magnetic distortions to yaw
- // axis only.
- //
- // User must define 'halfT' as the (sample period / 2), and the filter gains 'Kp' and 'Ki'.
- //
- // Global variables 'q0', 'q1', 'q2', 'q3' are the quaternion elements representing the estimated
- // orientation. See my report for an overview of the use of quaternions in this application.
- //
- // User must call 'AHRSupdate()' every sample period and parse calibrated gyroscope ('gx', 'gy', 'gz'),
- // accelerometer ('ax', 'ay', 'ay') and magnetometer ('mx', 'my', 'mz') data. Gyroscope units are
- // radians/second, accelerometer and magnetometer units are irrelevant as the vector is normalised.
- //
- //=====================================================================================================
- //----------------------------------------------------------------------------------------------------
- // Header files
- #include "AHRS.h"
- #include <math.h>
- //----------------------------------------------------------------------------------------------------
- // Definitions
- #define Kp 2.0f // proportional gain governs rate of convergence to accelerometer/magnetometer
- #define Ki 0.005f // integral gain governs rate of convergence of gyroscope biases
- #define halfT 0.5f // half the sample period
- //---------------------------------------------------------------------------------------------------
- // Variable definitions
- float q0 = 1, q1 = 0, q2 = 0, q3 = 0; // quaternion elements representing the estimated orientation
- float exInt = 0, eyInt = 0, ezInt = 0; // scaled integral error
- //====================================================================================================
- // Function
- //====================================================================================================
- void AHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
- float norm;
- float hx, hy, hz, bx, bz;
- float vx, vy, vz, wx, wy, wz;
- float ex, ey, ez;
- // auxiliary variables to reduce number of repeated operations
- float q0q0 = q0*q0;
- float q0q1 = q0*q1;
- float q0q2 = q0*q2;
- float q0q3 = q0*q3;
- float q1q1 = q1*q1;
- float q1q2 = q1*q2;
- float q1q3 = q1*q3;
- float q2q2 = q2*q2;
- float q2q3 = q2*q3;
- float q3q3 = q3*q3;
-
- // normalise the measurements
- norm = sqrt(ax*ax + ay*ay + az*az);
- ax = ax / norm;
- ay = ay / norm;
- az = az / norm;
- norm = sqrt(mx*mx + my*my + mz*mz);
- mx = mx / norm;
- my = my / norm;
- mz = mz / norm;
-
- 从机体坐标系的电子罗盘测到的矢量转成地理坐标系下的磁场矢量hxyz(测量值)
- // compute reference direction of flux
- hx = 2*mx*(0.5 - q2q2 - q3q3) + 2*my*(q1q2 - q0q3) + 2*mz*(q1q3 + q0q2);
- hy = 2*mx*(q1q2 + q0q3) + 2*my*(0.5 - q1q1 - q3q3) + 2*mz*(q2q3 - q0q1);
- hz = 2*mx*(q1q3 - q0q2) + 2*my*(q2q3 + q0q1) + 2*mz*(0.5 - q1q1 - q2q2);
- 计算地理坐标系下的磁场矢量bxyz(参考值)。
- 因为地理地磁水平夹角,我们已知是0度(抛去磁偏角的因素,固定向北),所以by=0,bx=某值
- 但地理参考地磁矢量在垂直面上也有分量bz,地球上每个地方都是不一样的。
- 我们无法得知,也就无法用来融合(有更适合做垂直方向修正融合的加速度计),所以直接从测量值hz上复制过来,bz=hz。
- 磁场水平分量,参考值和测量值的大小应该是一致的(bx*bx) + (by*by)) = ((hx*hx) + (hy*hy))。
- 因为by=0,所以就简化成(bx*bx) = ((hx*hx) + (hy*hy))。可算出bx。
- bx = sqrt((hx*hx) + (hy*hy));
- bz = hz;
-
- // estimated direction of gravity and flux (v and w)
- vx = 2*(q1q3 - q0q2);
- vy = 2*(q0q1 + q2q3);
- vz = q0q0 - q1q1 - q2q2 + q3q3;
- 我们把地理坐标系上的磁场矢量bxyz,转到机体上来wxyz。
- 因为by=0,所以所有涉及到by的部分都被省略了。
- 类似上面重力vxyz的推算,因为重力g的gz=1,gx=gy=0,所以上面涉及到gxgy的部分也被省略了
- 你可以看看两个公式:wxyz的公式,把bx换成gx(0),把bz换成gz(1),就变成了vxyz的公式了(其中q0q0+q1q1+q2q2+q3q3=1)。
- wx = 2*bx*(0.5 - q2q2 - q3q3) + 2*bz*(q1q3 - q0q2);
- wy = 2*bx*(q1q2 - q0q3) + 2*bz*(q0q1 + q2q3);
- wz = 2*bx*(q0q2 + q1q3) + 2*bz*(0.5 - q1q1 - q2q2);
-
- 现在把加速度的测量矢量和参考矢量做叉积,把磁场的测量矢量和参考矢量也做叉积。都拿来来修正陀螺。
- // error is sum of cross product between reference direction of fields and direction measured by sensors
- 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);
-
- // integral error scaled integral gain
- exInt = exInt + ex*Ki;
- eyInt = eyInt + ey*Ki;
- ezInt = ezInt + ez*Ki;
-
- // adjusted gyroscope measurements
- gx = gx + Kp*ex + exInt;
- gy = gy + Kp*ey + eyInt;
- gz = gz + Kp*ez + ezInt;
-
- // integrate quaternion rate and normalise
- q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
- q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
- q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
- q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;
-
- // normalise quaternion
- norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
- q0 = q0 / norm;
- q1 = q1 / norm;
- q2 = q2 / norm;
- q3 = q3 / norm;
- }
- //====================================================================================================
- // END OF CODE
- //====================================================================================================
复制代码 |
|