互补滤波姿态估计程序

/**
 * 6DOF 互补滤波姿态估计(via Mahony)
 * @param[in] halfT:状态估计周期的一半
 */
const float Kp = 3.5, Ki = 0.05;
float exInt, eyInt, ezInt;
float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; // roll,pitch,yaw 都为 0 时对应的四元数值。
void imuEstimatedAttitude(float gx, float gy, float gz, float ax, float ay, float az, float halfT) 
{
    float norm;
	float vx, vy, vz;  // v-陀螺仪积分后推算出的重力向量
	float ex, ey, ez;  // e-两重力向量的叉积(向量间的误差 a与v之间)   
	
	// 加速度原始数据归一化,得到单位化的加速度。
	norm = sqrt(ax*ax + ay*ay + az*az);
	ax = ax/norm;
	ay = ay/norm;
	az = az/norm;
	 
	// 坐标系变换,将地理坐标系“R系”的重力向量转换到机体坐标系“b系”的v_xyz
	vx = 2*(q1*q3 - q0*q2);
	vy = 2*(q0*q1 + q2*q3);
	vz = q0*q0 - q1*q1 - q2*q2 + q3*q3;
	
	// a_xyz是测量得到的重力向量,v_xyz是陀螺积分后的姿态来推算出的重力向量,它们都是机体坐标参照系上的重力向量。
	// 那它们之间的误差向量,就是陀螺积分后的姿态和加计测出来的姿态之间的误差。
    // 这个叉积向量仍旧是位于机体坐标系上的,而陀螺积分误差也是在机体坐标系,
	// 而且叉积的大小与陀螺积分误差成正比,正好拿来纠正陀螺仪积分误差。
	ex = (ay*vz - az*vy);
	ey = (az*vx - ax*vz);
	ez = (ax*vy - ay*vx);
	
	// 误差作PI修正
	exInt = exInt + ex*Ki;
	eyInt = eyInt + ey*Ki;
	ezInt = ezInt + ez*Ki;

	gx = gx + Kp*ex +exInt;
	gy = gy + Kp*ey +eyInt;
	gz = gz + Kp*ez +ezInt;
	
	// 四元数微分方程求解
	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;

	norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
	q0 = q0/norm;
	q1 = q1/norm;
	q2 = q2/norm;
	q3 = q3/norm;

	roll =  atan2f(2*q2*q3 + 2*q0*q1, -2*q1*q1 - 2*q2*q2 + 1)*57.3;    	
	pitch =  asinf(2*q1*q3 - 2*q0*q2)*57.3;                                                          
	yaw  =  -atan2f(2*q1*q2 + 2*q0*q3, -2*q2*q2 -2*q3*q3 + 1)*57.3; 
}

### 使用低通互补滤波进行姿态解算 #### 姿态解算中的传感器融合需求 在姿态解算过程中,加速度计和陀螺仪各自具有不同的优缺点。陀螺仪能够提供快速变化的姿态角度测量,但由于其固有的偏置漂移问题,在长时间内会产生累积误差。相比之下,加速度计虽然不会产生累积误差,但在动态环境中容易受到振动和其他干扰的影响,导致读数不准确。 因此,为了获得更精确的姿态估计,通常会将这两种类型的传感器结合起来使用。这可以通过应用一种称为互补滤波的技术来实现[^4]。 #### 互补滤波的工作机制 互补滤波是一种简单的线性组合方式,它利用了不同传感器频率响应特性的差异来进行有效的数据融合。具体来说: - **低通部分**:来自加速度计的角度信息被送入一个低通滤波器(Low Pass Filter),该滤波器允许较低频率分量通过并衰减较高频率成分。这样做的目的是保留重力矢量的方向信息,从而消除短期内的噪声影响。 - **高通部分**:另一方面,来自陀螺仪的速度增量则经过一个隐含的高通处理过程(实际上是对角速度做积分),即只考虑高于某个截止频率的变化率,忽略缓慢变动的部分。这部分主要用来捕捉快速转动事件而不受长期趋势的影响。 最终输出是由上述两者的适当比例相加以形成当前时刻的最佳姿态估计值。 #### 数学表达式 假设 `θ_acc` 表示由加速度计得出的角度,`ω_gyro` 是从陀螺仪测得的角速率,则有如下关系: \[ \theta_{comp} = (1-\alpha)\cdot\theta_{acc}(t)+\alpha(\theta(t-1)+T_s\omega_{gyro}) \] 其中 \( T_s \) 是采样周期时间间隔;\( \alpha \in [0,1] \) 控制着两种输入源之间权衡的比例因子——当接近于零时更多依赖于加速计的结果;反之亦然。这个参数的选择取决于实际应用场景的具体要求以及所使用的硬件性能特点[^3]。 #### Python 实现案例 下面给出一段Python代码片段作为例子展示如何构建这样一个基本框架下的姿态更新逻辑: ```python import numpy as np class ComplementaryFilter: def __init__(self, alpha=0.98): self.alpha = alpha self.angle = None def update(self, gyro_rate, acc_angle, dt): if self.angle is None: # Initialize with accelerometer angle on first call self.angle = acc_angle predicted_angle = self.angle + gyro_rate * dt corrected_angle = (1 - self.alpha)*acc_angle + self.alpha*predicted_angle self.angle = corrected_angle return corrected_angle # Example usage of the filter class if __name__ == "__main__": cf = ComplementaryFilter(alpha=0.98) # Simulated data points for demonstration purposes only. gyroscope_data = ... # Replace with actual sensor readings or simulated values accelerometer_angles = ... # Similarly replace these placeholders. time_step = 0.01 # Time step between measurements in seconds angles_over_time = [] for i in range(len(gyroscope_data)): current_angle = cf.update(gyroscope_data[i], accelerometer_angles[i], time_step) angles_over_time.append(current_angle) ``` 这段程序展示了如何创建一个名为 `ComplementaryFilter` 的类,并在其内部实现了基于给定公式的状态预测与校正循环。每次调用 `update()` 方法都会接收新的传感数据点及其对应的时间戳差值 (`dt`) 来调整最新的姿态评估结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值