Newer
Older
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "SensorsComponentController.h"
#include "QGCMAVLink.h"
#include "QGCApplication.h"
#include "ParameterManager.h"
#include <QVariant>
#include <QQmlProperty>
QGC_LOGGING_CATEGORY(SensorsComponentControllerLog, "SensorsComponentControllerLog")
_statusLog(NULL),
_progressBar(NULL),
_compassButton(NULL),
_gyroButton(NULL),
_accelButton(NULL),
_airspeedButton(NULL),
_magCalInProgress(false),
_accelCalInProgress(false),
_orientationCalDownSideDone(false),
_orientationCalUpsideDownSideDone(false),
_orientationCalLeftSideDone(false),
_orientationCalRightSideDone(false),
_orientationCalNoseDownSideDone(false),
_orientationCalTailDownSideDone(false),
_orientationCalDownSideVisible(false),
_orientationCalUpsideDownSideVisible(false),
_orientationCalLeftSideVisible(false),
_orientationCalRightSideVisible(false),
_orientationCalNoseDownSideVisible(false),
_orientationCalTailDownSideVisible(false),
_orientationCalDownSideInProgress(false),
_orientationCalUpsideDownSideInProgress(false),
_orientationCalLeftSideInProgress(false),
_orientationCalRightSideInProgress(false),
_orientationCalNoseDownSideInProgress(false),
_orientationCalTailDownSideInProgress(false),
bool SensorsComponentController::usingUDPLink(void)
{
return _vehicle->priorityLink()->getLinkConfiguration()->type() == LinkConfiguration::TypeUdp;
}
/// Appends the specified text to the status log area in the ui
void SensorsComponentController::_appendStatusLog(const QString& text)
{
if (!_statusLog) {
qWarning() << "Internal error";
return;
}
QVariant returnedValue;
QVariant varText = text;
QMetaObject::invokeMethod(_statusLog,
"append",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, varText));
}
void SensorsComponentController::_startLogCalibration(void)
connect(_uas, &UASInterface::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
_cancelButton->setEnabled(false);
}
void SensorsComponentController::_startVisualCalibration(void)
{
_compassButton->setEnabled(false);
_gyroButton->setEnabled(false);
_accelButton->setEnabled(false);
_airspeedButton->setEnabled(false);
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
void SensorsComponentController::_resetInternalState(void)
{
_orientationCalDownSideDone = true;
_orientationCalUpsideDownSideDone = true;
_orientationCalLeftSideDone = true;
_orientationCalRightSideDone = true;
_orientationCalTailDownSideDone = true;
_orientationCalNoseDownSideDone = true;
_orientationCalDownSideInProgress = false;
_orientationCalUpsideDownSideInProgress = false;
_orientationCalLeftSideInProgress = false;
_orientationCalRightSideInProgress = false;
_orientationCalNoseDownSideInProgress = false;
_orientationCalTailDownSideInProgress = false;
_orientationCalDownSideRotate = false;
_orientationCalUpsideDownSideRotate = false;
_orientationCalLeftSideRotate = false;
_orientationCalRightSideRotate = false;
_orientationCalNoseDownSideRotate = false;
_orientationCalTailDownSideRotate = false;
emit orientationCalSidesRotateChanged();
emit orientationCalSidesDoneChanged();
emit orientationCalSidesInProgressChanged();
}
void SensorsComponentController::_stopCalibration(SensorsComponentController::StopCalibrationCode code)
disconnect(_uas, &UASInterface::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
_compassButton->setEnabled(true);
_gyroButton->setEnabled(true);
_accelButton->setEnabled(true);
_airspeedButton->setEnabled(true);
_cancelButton->setEnabled(false);
if (code == StopCalibrationSuccess) {
_progressBar->setProperty("value", 1);
} else {
_progressBar->setProperty("value", 0);
}
_waitingForCancel = false;
emit waitingForCancelChanged();
switch (code) {
case StopCalibrationSuccess:
_orientationCalAreaHelpText->setProperty("text", "Calibration complete");
emit resetStatusTextArea();
if (_magCalInProgress) {
emit setCompassRotations();
}
break;
case StopCalibrationCancelled:
emit resetStatusTextArea();
_hideAllCalAreas();
break;
default:
// Assume failed
_hideAllCalAreas();
qgcApp()->showMessage("Calibration failed. Calibration log will be displayed.");
_magCalInProgress = false;
_accelCalInProgress = false;
_gyroCalInProgress = false;
}
void SensorsComponentController::calibrateGyro(void)
{
_startLogCalibration();
_uas->startCalibration(UASInterface::StartCalibrationGyro);
}
void SensorsComponentController::calibrateCompass(void)
{
_startLogCalibration();
_uas->startCalibration(UASInterface::StartCalibrationMag);
}
void SensorsComponentController::calibrateAccel(void)
{
_startLogCalibration();
_uas->startCalibration(UASInterface::StartCalibrationAccel);
void SensorsComponentController::calibrateLevel(void)
{
_startLogCalibration();
_uas->startCalibration(UASInterface::StartCalibrationLevel);
}
void SensorsComponentController::calibrateAirspeed(void)
{
_startLogCalibration();
_uas->startCalibration(UASInterface::StartCalibrationAirspeed);
}
void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text)
{
Q_UNUSED(compId);
Q_UNUSED(severity);
if (uasId != _vehicle->id()) {
if (text.contains("progress <")) {
QString percent = text.split("<").last().split(">").first();
bool ok;
int p = percent.toInt(&ok);
if (ok) {
if (_progressBar) {
_progressBar->setProperty("value", (float)(p / 100.0));
} else {
qWarning() << "Internal error";
}
qCDebug(SensorsComponentControllerLog) << text;
if (_unknownFirmwareVersion) {
// We don't know how to do visual cal with the version of firwmare
return;
}
// All calibration messages start with [cal]
QString calPrefix("[cal] ");
if (!text.startsWith(calPrefix)) {
return;
}
text = text.right(text.length() - calPrefix.length());
QString calStartPrefix("calibration started: ");
if (text.startsWith(calStartPrefix)) {
text = text.right(text.length() - calStartPrefix.length());
// Split version number and cal type
QStringList parts = text.split(" ");
if (parts.count() != 2 && parts[0].toInt() != _supportedFirmwareCalVersion) {
QString msg = "Unsupported calibration firmware version, using log";
_appendStatusLog(msg);
qDebug() << msg;
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
_startVisualCalibration();
text = parts[1];
if (text == "accel" || text == "mag" || text == "gyro") {
// Reset all progress indication
_orientationCalDownSideDone = false;
_orientationCalUpsideDownSideDone = false;
_orientationCalLeftSideDone = false;
_orientationCalRightSideDone = false;
_orientationCalTailDownSideDone = false;
_orientationCalNoseDownSideDone = false;
_orientationCalDownSideInProgress = false;
_orientationCalUpsideDownSideInProgress = false;
_orientationCalLeftSideInProgress = false;
_orientationCalRightSideInProgress = false;
_orientationCalNoseDownSideInProgress = false;
_orientationCalTailDownSideInProgress = false;
// Reset all visibility
_orientationCalDownSideVisible = false;
_orientationCalUpsideDownSideVisible = false;
_orientationCalLeftSideVisible = false;
_orientationCalRightSideVisible = false;
_orientationCalTailDownSideVisible = false;
_orientationCalNoseDownSideVisible = false;
_orientationCalAreaHelpText->setProperty("text", "Place your vehicle into one of the Incomplete orientations shown below and hold it still");
if (text == "accel") {
_accelCalInProgress = true;
_orientationCalDownSideVisible = true;
_orientationCalUpsideDownSideVisible = true;
_orientationCalLeftSideVisible = true;
_orientationCalRightSideVisible = true;
_orientationCalTailDownSideVisible = true;
_orientationCalNoseDownSideVisible = true;
} else if (text == "mag") {
// Work out what the autopilot is configured to
int sides = 0;
if (_vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, "CAL_MAG_SIDES")) {
// Read the requested calibration directions off the system
sides = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, "CAL_MAG_SIDES")->rawValue().toFloat();
} else {
// There is no valid setting, default to all six sides
sides = (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
}
_orientationCalTailDownSideVisible = ((sides & (1 << 0)) > 0);
_orientationCalNoseDownSideVisible = ((sides & (1 << 1)) > 0);
_orientationCalLeftSideVisible = ((sides & (1 << 2)) > 0);
_orientationCalRightSideVisible = ((sides & (1 << 3)) > 0);
_orientationCalUpsideDownSideVisible = ((sides & (1 << 4)) > 0);
_orientationCalDownSideVisible = ((sides & (1 << 5)) > 0);
} else if (text == "gyro") {
_gyroCalInProgress = true;
_orientationCalDownSideVisible = true;
} else {
qWarning() << "Unknown calibration message type" << text;
}
emit orientationCalSidesDoneChanged();
emit orientationCalSidesVisibleChanged();
emit orientationCalSidesInProgressChanged();
_updateAndEmitShowOrientationCalArea(true);
return;
}
if (text.endsWith("orientation detected")) {
QString side = text.section(" ", 0, 0);
qDebug() << "Side started" << side;
if (side == "down") {
_orientationCalDownSideInProgress = true;
if (_magCalInProgress) {
_orientationCalDownSideRotate = true;
}
if (_magCalInProgress) {
_orientationCalUpsideDownSideRotate = true;
}
if (_magCalInProgress) {
_orientationCalLeftSideRotate = true;
}
if (_magCalInProgress) {
_orientationCalRightSideRotate = true;
}
if (_magCalInProgress) {
_orientationCalNoseDownSideRotate = true;
}
if (_magCalInProgress) {
_orientationCalTailDownSideRotate = true;
}
if (_magCalInProgress) {
_orientationCalAreaHelpText->setProperty("text", "Rotate the vehicle continuously as shown in the diagram until marked as Completed");
} else {
_orientationCalAreaHelpText->setProperty("text", "Hold still in the current orientation");
}
emit orientationCalSidesRotateChanged();
return;
}
if (text.endsWith("side done, rotate to a different side")) {
QString side = text.section(" ", 0, 0);
qDebug() << "Side finished" << side;
_orientationCalDownSideInProgress = false;
_orientationCalDownSideDone = true;
_orientationCalUpsideDownSideInProgress = false;
_orientationCalUpsideDownSideDone = true;
_orientationCalUpsideDownSideRotate = false;
_orientationCalLeftSideInProgress = false;
_orientationCalLeftSideDone = true;
_orientationCalRightSideInProgress = false;
_orientationCalRightSideDone = true;
_orientationCalRightSideRotate = false;
_orientationCalNoseDownSideInProgress = false;
_orientationCalNoseDownSideDone = true;
_orientationCalTailDownSideInProgress = false;
_orientationCalTailDownSideDone = true;
_orientationCalTailDownSideRotate = false;
_orientationCalAreaHelpText->setProperty("text", "Place you vehicle into one of the orientations shown below and hold it still");
emit orientationCalSidesInProgressChanged();
emit orientationCalSidesDoneChanged();
if (text.endsWith("side already completed")) {
_orientationCalAreaHelpText->setProperty("text", "Orientation already completed, place you vehicle into one of the incomplete orientations shown below and hold it still");
return;
}
QString calCompletePrefix("calibration done:");
if (text.startsWith(calCompletePrefix)) {
_stopCalibration(StopCalibrationSuccess);
return;
if (text.startsWith("calibration cancelled")) {
_stopCalibration(_waitingForCancel ? StopCalibrationCancelled : StopCalibrationFailed);
return;
if (text.startsWith("calibration failed")) {
_stopCalibration(StopCalibrationFailed);
return;
}
}
void SensorsComponentController::_refreshParams(void)
{
QStringList fastRefreshList;
// We ask for a refresh on these first so that the rotation combo show up as fast as possible
fastRefreshList << "CAL_MAG0_ID" << "CAL_MAG1_ID" << "CAL_MAG2_ID" << "CAL_MAG0_ROT" << "CAL_MAG1_ROT" << "CAL_MAG2_ROT";
foreach (const QString ¶mName, fastRefreshList) {
_vehicle->parameterManager()->refreshParameter(FactSystem::defaultComponentId, paramName);
_vehicle->parameterManager()->refreshParametersPrefix(FactSystem::defaultComponentId, "CAL_");
_vehicle->parameterManager()->refreshParametersPrefix(FactSystem::defaultComponentId, "SENS_");
void SensorsComponentController::_updateAndEmitShowOrientationCalArea(bool show)
_showOrientationCalArea = show;
emit showOrientationCalAreaChanged();
}
void SensorsComponentController::_hideAllCalAreas(void)
{
// The firmware doesn't allow us to cancel calibration. The best we can do is wait
// for it to timeout.
_waitingForCancel = true;
emit waitingForCancelChanged();
_cancelButton->setEnabled(false);
_uas->stopCalibration();