我正在开发一个小型室内导航应用程序,我在其中使用陀螺仪和指南针进行设备定位。我使用陀螺仪来平滑罗盘数据。我的传感器融合如下所示。这是我的motionHandler,一切都发生在这里。
// Listen to events from the motionManager
motionHandler = ^ (CMDeviceMotion *motion, NSError *error) {
__block float heading;
heading = mHeading;
CMAttitude *currentAttitude = motion.attitude;
//Initial heading setting
if (lastHeading == 0 && heading != 0) {
updatedHeading = heading;
}
lastHeading = heading;
if (oldQuaternion.w != 0 || oldQuaternion.x != 0 || oldQuaternion.y != 0 || oldQuaternion.z != 0){
diffQuaternion = [self multiplyQuaternions:[self inverseQuaternion:oldQuaternion] :currentAttitude.quaternion];
diffQuaternion = [self normalizeQuaternion:diffQuaternion];
}
oldQuaternion = currentAttitude.quaternion;
diffYaw = RADIANS_TO_DEGREES([self yawFromQuaternion:diffQuaternion]);
quaternion = currentAttitude.quaternion;
//Get Pitch
rpy.pitch = -[self pitchFromQuaternion:quaternion];
rpy.pitch += M_PI/2;
//Use Yaw-Difference for Heading
updatedHeading = updatedHeading - diffYaw;
//Heading has to be between 0 and 360 degrees
if (updatedHeading < 0) {
updatedHeading = 360 + updatedHeading;
}
else if (updatedHeading > 360) {
updatedHeading -= 360;
}
//fusionate gyro estimated heading with new magneticHeading
updatedHeading = (19.0*updatedHeading + 1.0*heading)/20.0;
//generate queternion
rotation = [self createFromAxisAngle:0 :rpy.pitch :DEGREES_TO_RADIANS(updatedHeading)];
};
实际的传感器融合公式是这一行:updatedHeading = (19.0*updatedHeading + 1.0*heading)/20.0;
。这是我的 didUpdateHeading 函数,它接收最新的标题信息:
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
// Get new heading
mHeading = newHeading.magneticHeading;
mHeading += 90;
if (mHeading > 360) {
mHeading -= 360;
}
}
diffYaw
是陀螺仪计算的航向变化。rotation
是最后一个四元数。这很完美,除了一种特殊情况:在 0 到 360 度之间的过渡。
如果updatedHeading
接近但小于 360 并且mHeading
刚好高于 0,则结果会移动一个圆圈。例如如果updatedHeading
= 355 和mHeading
= 5,正确的结果应该在 360 和 5 之间。但是我的公式计算的是 337.5 度,这显然是完全错误的!
我认为必须有任何常见的解决方法来解决这个问题……</p>