I looked at the specific locations in the code within both tools and maybe I found the little difference which is responsible here.
(Please keep in mind that I’m not an expert here and I’m doing just a little guessing by trying to understand what the code should do
)
Here’s a snipped of the Mission Planner code:
// disable learning
MainV2.comPort.setParam("COMPASS_LEARN", 0);
if (!MainV2.comPort.SetSensorOffsets(MAVLinkInterface.sensoroffsetsenum.magnetometer, (float)ofs[0], (float)ofs[1], (float)ofs[2]))
{
// set values
MainV2.comPort.setParam("COMPASS_OFS_X", (float)ofs[0]);
MainV2.comPort.setParam("COMPASS_OFS_Y", (float)ofs[1]);
MainV2.comPort.setParam("COMPASS_OFS_Z", (float)ofs[2]);
}
// disable learning
MainV2.comPort.setParam("COMPASS_LEARN", 0);
if (!MainV2.comPort.SetSensorOffsets(MAVLinkInterface.sensoroffsetsenum.second_magnetometer, (float)ofs[0], (float)ofs[1], (float)ofs[2]))
{
// set values
MainV2.comPort.setParam("COMPASS_OFS2_X", (float)ofs[0]);
MainV2.comPort.setParam("COMPASS_OFS2_Y", (float)ofs[1]);
MainV2.comPort.setParam("COMPASS_OFS2_Z", (float)ofs[2]);
}
As you can see it sets the params which the APM Planner also does in CompassConfig.cc:417:
void CompassConfig::saveOffsets(alglib::real_1d_array* offset, alglib::real_1d_array* offset2)
{
alglib::real_1d_array& ofs = *offset;
float xOffset = static_cast<float>(ofs[0]);
float yOffset = static_cast<float>(ofs[1]);
float zOffset = static_cast<float>(ofs[2]);
QLOG_INFO() << "New Compass Offset to be set are: " << xOffset
<< ", " << yOffset
<< ", " << zOffset;
QGCUASParamManager* paramMgr = m_uas->getParamManager();
paramMgr->setParameter(1, "COMPASS_LEARN", 0);
// set values
paramMgr->setParameter(1, "COMPASS_OFS_X", xOffset);
paramMgr->setParameter(1, "COMPASS_OFS_Y", yOffset);
paramMgr->setParameter(1, "COMPASS_OFS_Z", zOffset);
QString message = tr("New offsets (Compass 1) are \n\nx:") + QString::number(xOffset,'f',3)
+ " y:" + QString::number(yOffset,'f',3) + " z:" + QString::number(zOffset,'f',3);
if (m_haveSecondCompass) {
alglib::real_1d_array& ofs2 = *offset2;
float xOffset2 = static_cast<float>(ofs2[0]);
float yOffset2 = static_cast<float>(ofs2[1]);
float zOffset2 = static_cast<float>(ofs2[2]);
QLOG_INFO() << "New Compass 2 Offset to be set are: " << xOffset2
<< ", " << yOffset2
<< ", " << zOffset2;
paramMgr->setParameter(1, "COMPASS_OFS2_X", xOffset2);
paramMgr->setParameter(1, "COMPASS_OFS2_Y", yOffset2);
paramMgr->setParameter(1, "COMPASS_OFS2_Z", zOffset2);
message.append(tr("\n\nNew offsets (Compass 2) are \n\nx:") + QString::number(xOffset2,'f',3)
+ " y:" + QString::number(yOffset2,'f',3) + " z:" + QString::number(zOffset2,'f',3));
}
cleanup();
QMessageBox::information(this, tr("New Compass Offsets"), message + tr("\n\nThese have been saved for you."));
}
But when you look close again to the way Mission Planner does it, you’ll find that it does something else:
if (!MainV2.comPort.SetSensorOffsets(MAVLinkInterface.sensoroffsetsenum.magnetometer, (float)ofs[0], (float)ofs[1], (float)ofs[2]))
And this seems to be it. It sets the sensor offsets using a mavlink command instead of just setting the params through the com port interface:
public bool SetSensorOffsets(sensoroffsetsenum sensor, float x, float y, float z)
{
return doCommand(MAV_CMD.PREFLIGHT_SET_SENSOR_OFFSETS,(int)sensor,x,y,z,0,0,0);
}
This “doCommand()” essentially generates a mavlink packet and sends it to the pixhawk which I think treats the whole sensor setup a little different, which is finally the reason why the calibration worked only by using Mission Planner.
So this seems to be a little “issue” in both, the tool and the copter firmware?!