SensorsComponentController.cc 17 KB
Newer Older
1 2 3 4 5 6 7 8 9
/****************************************************************************
 *
 *   (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.
 *
 ****************************************************************************/

Don Gagne's avatar
Don Gagne committed
10 11 12 13 14 15

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "SensorsComponentController.h"
#include "QGCMAVLink.h"
16
#include "UAS.h"
17
#include "QGCApplication.h"
Don Gagne's avatar
Don Gagne committed
18 19 20 21

#include <QVariant>
#include <QQmlProperty>

22 23
QGC_LOGGING_CATEGORY(SensorsComponentControllerLog, "SensorsComponentControllerLog")

Don Gagne's avatar
Don Gagne committed
24
SensorsComponentController::SensorsComponentController(void) :
25 26
    _statusLog(NULL),
    _progressBar(NULL),
Don Gagne's avatar
Don Gagne committed
27 28 29 30
    _compassButton(NULL),
    _gyroButton(NULL),
    _accelButton(NULL),
    _airspeedButton(NULL),
31
    _levelButton(NULL),
Don Gagne's avatar
Don Gagne committed
32
    _cancelButton(NULL),
Don Gagne's avatar
Don Gagne committed
33
    _setOrientationsButton(NULL),
Don Gagne's avatar
Don Gagne committed
34
    _showOrientationCalArea(false),
35
    _gyroCalInProgress(false),
Don Gagne's avatar
Don Gagne committed
36 37 38 39 40 41 42 43
    _magCalInProgress(false),
    _accelCalInProgress(false),
    _orientationCalDownSideDone(false),
    _orientationCalUpsideDownSideDone(false),
    _orientationCalLeftSideDone(false),
    _orientationCalRightSideDone(false),
    _orientationCalNoseDownSideDone(false),
    _orientationCalTailDownSideDone(false),
Don Gagne's avatar
Don Gagne committed
44 45 46 47 48 49
    _orientationCalDownSideVisible(false),
    _orientationCalUpsideDownSideVisible(false),
    _orientationCalLeftSideVisible(false),
    _orientationCalRightSideVisible(false),
    _orientationCalNoseDownSideVisible(false),
    _orientationCalTailDownSideVisible(false),
Don Gagne's avatar
Don Gagne committed
50 51 52 53 54 55
    _orientationCalDownSideInProgress(false),
    _orientationCalUpsideDownSideInProgress(false),
    _orientationCalLeftSideInProgress(false),
    _orientationCalRightSideInProgress(false),
    _orientationCalNoseDownSideInProgress(false),
    _orientationCalTailDownSideInProgress(false),
Don Gagne's avatar
Don Gagne committed
56
    _orientationCalDownSideRotate(false),
57
    _orientationCalUpsideDownSideRotate(false),
Don Gagne's avatar
Don Gagne committed
58
    _orientationCalLeftSideRotate(false),
59
    _orientationCalRightSideRotate(false),
Don Gagne's avatar
Don Gagne committed
60
    _orientationCalNoseDownSideRotate(false),
61
    _orientationCalTailDownSideRotate(false),
Don Gagne's avatar
Don Gagne committed
62
    _unknownFirmwareVersion(false),
Don Gagne's avatar
Don Gagne committed
63
    _waitingForCancel(false)
Don Gagne's avatar
Don Gagne committed
64
{
65
}
Don Gagne's avatar
Don Gagne committed
66

67 68 69
bool SensorsComponentController::usingUDPLink(void)
{
    return _vehicle->priorityLink()->getLinkConfiguration()->type() == LinkConfiguration::TypeUdp;
Don Gagne's avatar
Don Gagne committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
}

/// Appends the specified text to the status log area in the ui
void SensorsComponentController::_appendStatusLog(const QString& text)
{
    Q_ASSERT(_statusLog);
    
    QVariant returnedValue;
    QVariant varText = text;
    QMetaObject::invokeMethod(_statusLog,
                              "append",
                              Q_RETURN_ARG(QVariant, returnedValue),
                              Q_ARG(QVariant, varText));
}

Don Gagne's avatar
Don Gagne committed
85
void SensorsComponentController::_startLogCalibration(void)
Don Gagne's avatar
Don Gagne committed
86
{
Don Gagne's avatar
Don Gagne committed
87
    _unknownFirmwareVersion = false;
88 89
    _hideAllCalAreas();
    
Don Gagne's avatar
Don Gagne committed
90 91 92 93 94 95 96
    connect(_uas, &UASInterface::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
    
    _cancelButton->setEnabled(false);
}

void SensorsComponentController::_startVisualCalibration(void)
{
97 98 99 100
    _compassButton->setEnabled(false);
    _gyroButton->setEnabled(false);
    _accelButton->setEnabled(false);
    _airspeedButton->setEnabled(false);
101
    _levelButton->setEnabled(false);
Don Gagne's avatar
Don Gagne committed
102
    _setOrientationsButton->setEnabled(false);
Don Gagne's avatar
Don Gagne committed
103
    _cancelButton->setEnabled(true);
104 105

    _resetInternalState();
Don Gagne's avatar
Don Gagne committed
106 107
    
    _progressBar->setProperty("value", 0);
108 109
}

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
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();
}

Don Gagne's avatar
Don Gagne committed
136
void SensorsComponentController::_stopCalibration(SensorsComponentController::StopCalibrationCode code)
137
{
Don Gagne's avatar
Don Gagne committed
138
    disconnect(_uas, &UASInterface::textMessageReceived, this, &SensorsComponentController::_handleUASTextMessage);
Don Gagne's avatar
Don Gagne committed
139
    
140 141 142 143
    _compassButton->setEnabled(true);
    _gyroButton->setEnabled(true);
    _accelButton->setEnabled(true);
    _airspeedButton->setEnabled(true);
144
    _levelButton->setEnabled(true);
Don Gagne's avatar
Don Gagne committed
145
    _setOrientationsButton->setEnabled(true);
Don Gagne's avatar
Don Gagne committed
146 147 148
    _cancelButton->setEnabled(false);
    
    if (code == StopCalibrationSuccess) {
149
        _resetInternalState();
Don Gagne's avatar
Don Gagne committed
150 151 152 153 154
        
        _progressBar->setProperty("value", 1);
    } else {
        _progressBar->setProperty("value", 0);
    }
155
    
Don Gagne's avatar
Don Gagne committed
156 157 158
    _waitingForCancel = false;
    emit waitingForCancelChanged();

159 160
    _refreshParams();
    
Don Gagne's avatar
Don Gagne committed
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
    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();
178
            qgcApp()->showMessage("Calibration failed. Calibration log will be displayed.");
Don Gagne's avatar
Don Gagne committed
179
            break;
180
    }
Don Gagne's avatar
Don Gagne committed
181 182 183 184
    
    _magCalInProgress = false;
    _accelCalInProgress = false;
    _gyroCalInProgress = false;
185 186 187 188
}

void SensorsComponentController::calibrateGyro(void)
{
Don Gagne's avatar
Don Gagne committed
189 190
    _startLogCalibration();
    _uas->startCalibration(UASInterface::StartCalibrationGyro);
Don Gagne's avatar
Don Gagne committed
191 192 193 194
}

void SensorsComponentController::calibrateCompass(void)
{
Don Gagne's avatar
Don Gagne committed
195 196
    _startLogCalibration();
    _uas->startCalibration(UASInterface::StartCalibrationMag);
Don Gagne's avatar
Don Gagne committed
197 198 199 200
}

void SensorsComponentController::calibrateAccel(void)
{
Don Gagne's avatar
Don Gagne committed
201 202
    _startLogCalibration();
    _uas->startCalibration(UASInterface::StartCalibrationAccel);
Don Gagne's avatar
Don Gagne committed
203 204
}

205 206 207 208 209 210
void SensorsComponentController::calibrateLevel(void)
{
    _startLogCalibration();
    _uas->startCalibration(UASInterface::StartCalibrationLevel);
}

Don Gagne's avatar
Don Gagne committed
211 212
void SensorsComponentController::calibrateAirspeed(void)
{
Don Gagne's avatar
Don Gagne committed
213 214
    _startLogCalibration();
    _uas->startCalibration(UASInterface::StartCalibrationAirspeed);
Don Gagne's avatar
Don Gagne committed
215 216 217 218 219 220 221
}

void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text)
{
    Q_UNUSED(compId);
    Q_UNUSED(severity);
    
222
    UASInterface* uas = _autopilot->vehicle()->uas();
Don Gagne's avatar
Don Gagne committed
223 224 225 226 227
    Q_ASSERT(uas);
    if (uasId != uas->getUASID()) {
        return;
    }
    
228 229 230 231 232 233 234 235 236 237 238
    if (text.contains("progress <")) {
        QString percent = text.split("<").last().split(">").first();
        bool ok;
        int p = percent.toInt(&ok);
        if (ok) {
            Q_ASSERT(_progressBar);
            _progressBar->setProperty("value", (float)(p / 100.0));
        }
        return;
    }

Don Gagne's avatar
Don Gagne committed
239
    _appendStatusLog(text);
240
    qCDebug(SensorsComponentControllerLog) << text;
Don Gagne's avatar
Don Gagne committed
241 242 243 244 245 246 247 248 249 250 251 252
    
    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());
253

Don Gagne's avatar
Don Gagne committed
254 255 256 257 258 259
    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(" ");
260
        if (parts.count() != 2 && parts[0].toInt() != _supportedFirmwareCalVersion) {
Don Gagne's avatar
Don Gagne committed
261
            _unknownFirmwareVersion = true;
262 263 264
            QString msg = "Unsupported calibration firmware version, using log";
            _appendStatusLog(msg);
            qDebug() << msg;
Don Gagne's avatar
Don Gagne committed
265
            return;
Don Gagne's avatar
Don Gagne committed
266
        }
Don Gagne's avatar
Don Gagne committed
267 268 269 270 271 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
        
        _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") {
305 306 307 308

                // Work out what the autopilot is configured to
                int sides = 0;

309
                if (_vehicle->parameterExists(FactSystem::defaultComponentId, "CAL_MAG_SIDES")) {
310
                    // Read the requested calibration directions off the system
311
                    sides = _vehicle->getParameterFact(FactSystem::defaultComponentId, "CAL_MAG_SIDES")->rawValue().toFloat();
312 313 314 315 316
                } else {
                    // There is no valid setting, default to all six sides
                    sides = (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
                }

Don Gagne's avatar
Don Gagne committed
317
                _magCalInProgress = true;
318 319 320 321 322 323
                _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);
Don Gagne's avatar
Don Gagne committed
324 325 326 327 328 329 330 331 332 333
            } else if (text == "gyro") {
                _gyroCalInProgress = true;
                _orientationCalDownSideVisible = true;
            } else {
                Q_ASSERT(false);
            }
            emit orientationCalSidesDoneChanged();
            emit orientationCalSidesVisibleChanged();
            emit orientationCalSidesInProgressChanged();
            _updateAndEmitShowOrientationCalArea(true);
Don Gagne's avatar
Don Gagne committed
334
        }
Don Gagne's avatar
Don Gagne committed
335 336 337 338
        return;
    }
    
    if (text.endsWith("orientation detected")) {
Don Gagne's avatar
Don Gagne committed
339 340
        QString side = text.section(" ", 0, 0);
        qDebug() << "Side started" << side;
Don Gagne's avatar
Don Gagne committed
341
        
Don Gagne's avatar
Don Gagne committed
342 343
        if (side == "down") {
            _orientationCalDownSideInProgress = true;
Don Gagne's avatar
Don Gagne committed
344 345 346
            if (_magCalInProgress) {
                _orientationCalDownSideRotate = true;
            }
347
        } else if (side == "up") {
Don Gagne's avatar
Don Gagne committed
348
            _orientationCalUpsideDownSideInProgress = true;
349 350 351
            if (_magCalInProgress) {
                _orientationCalUpsideDownSideRotate = true;
            }
352
        } else if (side == "left") {
Don Gagne's avatar
Don Gagne committed
353
            _orientationCalLeftSideInProgress = true;
Don Gagne's avatar
Don Gagne committed
354 355 356
            if (_magCalInProgress) {
                _orientationCalLeftSideRotate = true;
            }
357
        } else if (side == "right") {
Don Gagne's avatar
Don Gagne committed
358
            _orientationCalRightSideInProgress = true;
359 360 361
            if (_magCalInProgress) {
                _orientationCalRightSideRotate = true;
            }
362
        } else if (side == "front") {
Don Gagne's avatar
Don Gagne committed
363
            _orientationCalNoseDownSideInProgress = true;
Don Gagne's avatar
Don Gagne committed
364 365 366
            if (_magCalInProgress) {
                _orientationCalNoseDownSideRotate = true;
            }
367
        } else if (side == "back") {
Don Gagne's avatar
Don Gagne committed
368
            _orientationCalTailDownSideInProgress = true;
369 370 371
            if (_magCalInProgress) {
                _orientationCalTailDownSideRotate = true;
            }
372
        }
Don Gagne's avatar
Don Gagne committed
373 374 375 376 377 378 379
        
        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");
        }
        
Don Gagne's avatar
Don Gagne committed
380
        emit orientationCalSidesInProgressChanged();
Don Gagne's avatar
Don Gagne committed
381 382 383 384 385
        emit orientationCalSidesRotateChanged();
        return;
    }
    
    if (text.endsWith("side done, rotate to a different side")) {
386 387
        QString side = text.section(" ", 0, 0);
        qDebug() << "Side finished" << side;
Don Gagne's avatar
Don Gagne committed
388
        
389
        if (side == "down") {
Don Gagne's avatar
Don Gagne committed
390 391
            _orientationCalDownSideInProgress = false;
            _orientationCalDownSideDone = true;
Don Gagne's avatar
Don Gagne committed
392
            _orientationCalDownSideRotate = false;
393
        } else if (side == "up") {
Don Gagne's avatar
Don Gagne committed
394 395
            _orientationCalUpsideDownSideInProgress = false;
            _orientationCalUpsideDownSideDone = true;
396
            _orientationCalUpsideDownSideRotate = false;
397
        } else if (side == "left") {
Don Gagne's avatar
Don Gagne committed
398 399
            _orientationCalLeftSideInProgress = false;
            _orientationCalLeftSideDone = true;
Don Gagne's avatar
Don Gagne committed
400
            _orientationCalLeftSideRotate = false;
401
        } else if (side == "right") {
Don Gagne's avatar
Don Gagne committed
402 403
            _orientationCalRightSideInProgress = false;
            _orientationCalRightSideDone = true;
404
            _orientationCalRightSideRotate = false;
405
        } else if (side == "front") {
Don Gagne's avatar
Don Gagne committed
406 407
            _orientationCalNoseDownSideInProgress = false;
            _orientationCalNoseDownSideDone = true;
Don Gagne's avatar
Don Gagne committed
408
            _orientationCalNoseDownSideRotate = false;
409
        } else if (side == "back") {
Don Gagne's avatar
Don Gagne committed
410 411
            _orientationCalTailDownSideInProgress = false;
            _orientationCalTailDownSideDone = true;
412
            _orientationCalTailDownSideRotate = false;
413
        }
Don Gagne's avatar
Don Gagne committed
414 415 416
        
        _orientationCalAreaHelpText->setProperty("text", "Place you vehicle into one of the orientations shown below and hold it still");

Don Gagne's avatar
Don Gagne committed
417 418
        emit orientationCalSidesInProgressChanged();
        emit orientationCalSidesDoneChanged();
Don Gagne's avatar
Don Gagne committed
419 420
        emit orientationCalSidesRotateChanged();
        return;
421
    }
422 423 424 425 426

    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;
    }
Don Gagne's avatar
Don Gagne committed
427
    
Don Gagne's avatar
Don Gagne committed
428 429 430 431
    QString calCompletePrefix("calibration done:");
    if (text.startsWith(calCompletePrefix)) {
        _stopCalibration(StopCalibrationSuccess);
        return;
432
    }
Don Gagne's avatar
Don Gagne committed
433 434 435 436
    
    if (text.startsWith("calibration cancelled")) {
        _stopCalibration(_waitingForCancel ? StopCalibrationCancelled : StopCalibrationFailed);
        return;
437 438
    }
    
Don Gagne's avatar
Don Gagne committed
439 440 441 442 443 444 445 446
    if (text.startsWith("calibration failed")) {
        _stopCalibration(StopCalibrationFailed);
        return;
    }
}

void SensorsComponentController::_refreshParams(void)
{
Don Gagne's avatar
Don Gagne committed
447 448 449 450
    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";
451
    foreach (const QString &paramName, fastRefreshList) {
Don Gagne's avatar
Don Gagne committed
452 453 454 455
        _autopilot->refreshParameter(FactSystem::defaultComponentId, paramName);
    }
    
    // Now ask for all to refresh
456 457
    _autopilot->refreshParametersPrefix(FactSystem::defaultComponentId, "CAL_");
    _autopilot->refreshParametersPrefix(FactSystem::defaultComponentId, "SENS_");
Don Gagne's avatar
Don Gagne committed
458 459
}

Don Gagne's avatar
Don Gagne committed
460
void SensorsComponentController::_updateAndEmitShowOrientationCalArea(bool show)
461
{
Don Gagne's avatar
Don Gagne committed
462 463
    _showOrientationCalArea = show;
    emit showOrientationCalAreaChanged();
464 465 466 467
}

void SensorsComponentController::_hideAllCalAreas(void)
{
Don Gagne's avatar
Don Gagne committed
468 469 470
    _updateAndEmitShowOrientationCalArea(false);
}

Don Gagne's avatar
Don Gagne committed
471
void SensorsComponentController::cancelCalibration(void)
Don Gagne's avatar
Don Gagne committed
472
{
Don Gagne's avatar
Don Gagne committed
473 474 475 476 477 478
    // 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();
479
}