SensorsComponentController.cc 17.1 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"
18
#include "ParameterManager.h"
Don Gagne's avatar
Don Gagne committed
19 20 21 22

#include <QVariant>
#include <QQmlProperty>

23 24
QGC_LOGGING_CATEGORY(SensorsComponentControllerLog, "SensorsComponentControllerLog")

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

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

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

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

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

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

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

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

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

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

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

void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, int severity, QString text)
{
    Q_UNUSED(compId);
    Q_UNUSED(severity);
    
223
    if (uasId != _vehicle->id()) {
Don Gagne's avatar
Don Gagne committed
224 225 226
        return;
    }
    
227 228 229 230 231 232 233 234 235 236 237
    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
238
    _appendStatusLog(text);
239
    qCDebug(SensorsComponentControllerLog) << text;
Don Gagne's avatar
Don Gagne committed
240 241 242 243 244 245 246 247 248 249 250 251
    
    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());
252

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

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

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

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

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

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

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

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

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