我目前在我的 Arduino 项目中使用 MPU9150Lib 从我的 IMU(当然是 MPU9150)中读取数据。到目前为止效果很好。但我有时会注意到一些小故障。我认为这是一个云台锁定问题。当我查看库时,似乎它们融合了数据,然后简单地将生成的欧拉角转换为四元数。这会导致万向节锁定吗?如果是这样,你们能帮我重写代码吗?我不太了解数据融合背后的数学原理。所以我不知道如何更正图书馆。
你可以在这里找到它: https ://github.com/zarthcode/MPU9150Lib/tree/master/libraries/MPU9150Lib
该库包含以下功能。我不确定问题是否出在函数内,但对我来说它看起来很奇怪,因为最终它将欧拉坐标转换为四元数。
void MPU9150Lib::dataFusion()
{
float qMag[4];
float deltaDMPYaw, deltaMagYaw;
float newMagYaw, newYaw;
float temp1[4], unFused[4];
float unFusedConjugate[4];
// *** NOTE *** pitch direction swapped here
m_fusedEulerPose[VEC3_X] = m_dmpEulerPose[VEC3_X];
m_fusedEulerPose[VEC3_Y] = -m_dmpEulerPose[VEC3_Y];
m_fusedEulerPose[VEC3_Z] = 0;
MPUQuaternionEulerToQuaternion(m_fusedEulerPose, unFused); // create a new quaternion
deltaDMPYaw = -m_dmpEulerPose[VEC3_Z] + m_lastDMPYaw; // calculate change in yaw from dmp
m_lastDMPYaw = m_dmpEulerPose[VEC3_Z]; // update that
qMag[QUAT_W] = 0;
qMag[QUAT_X] = m_calMag[VEC3_X];
qMag[QUAT_Y] = m_calMag[VEC3_Y];
qMag[QUAT_Z] = m_calMag[VEC3_Z];
// Tilt compensate mag with the unfused data (i.e. just roll and pitch with yaw 0)
MPUQuaternionConjugate(unFused, unFusedConjugate);
MPUQuaternionMultiply(qMag, unFusedConjugate, temp1);
MPUQuaternionMultiply(unFused, temp1, qMag);
// Now fuse this with the dmp yaw gyro information
newMagYaw = -atan2(qMag[QUAT_Y], qMag[QUAT_X]);
if (newMagYaw != newMagYaw) { // check for nAn
#ifdef MPULIB_DEBUG
Serial.println("***nAn\n");
#endif
return; // just ignore in this case
}
if (newMagYaw < 0)
newMagYaw = 2.0f * (float)M_PI + newMagYaw; // need 0 <= newMagYaw <= 2*PI
newYaw = m_lastYaw + deltaDMPYaw; // compute new yaw from change
if (newYaw > (2.0f * (float)M_PI)) // need 0 <= newYaw <= 2*PI
newYaw -= 2.0f * (float)M_PI;
if (newYaw < 0)
newYaw += 2.0f * (float)M_PI;
deltaMagYaw = newMagYaw - newYaw; // compute difference
if (deltaMagYaw >= (float)M_PI)
deltaMagYaw = deltaMagYaw - 2.0f * (float)M_PI;
if (deltaMagYaw <= -(float)M_PI)
deltaMagYaw = (2.0f * (float)M_PI + deltaMagYaw);
newYaw += deltaMagYaw/4; // apply some of the correction
if (newYaw > (2.0f * (float)M_PI)) // need 0 <= newYaw <= 2*PI
newYaw -= 2.0f * (float)M_PI;
if (newYaw < 0)
newYaw += 2.0f * (float)M_PI;
m_lastYaw = newYaw;
if (newYaw > (float)M_PI)
newYaw -= 2.0f * (float)M_PI;
m_fusedEulerPose[VEC3_Z] = newYaw; // fill in output yaw value
MPUQuaternionEulerToQuaternion(m_fusedEulerPose, m_fusedQuaternion);
}