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

#include "CameraSection.h"
#include "SimpleMissionItem.h"
12
#include "FirmwarePlugin.h"
13 14 15

QGC_LOGGING_CATEGORY(CameraSectionLog, "CameraSectionLog")

16 17 18 19 20 21
const char* CameraSection::_gimbalPitchName =                   "GimbalPitch";
const char* CameraSection::_gimbalYawName =                     "GimbalYaw";
const char* CameraSection::_cameraActionName =                  "CameraAction";
const char* CameraSection::_cameraPhotoIntervalDistanceName =   "CameraPhotoIntervalDistance";
const char* CameraSection::_cameraPhotoIntervalTimeName =       "CameraPhotoIntervalTime";
const char* CameraSection::_cameraModeName =                    "CameraMode";
22 23 24

QMap<QString, FactMetaData*> CameraSection::_metaDataMap;

25 26
CameraSection::CameraSection(Vehicle* vehicle, QObject* parent)
    : Section(vehicle, parent)
27 28 29
    , _available(false)
    , _settingsSpecified(false)
    , _specifyGimbal(false)
30
    , _specifyCameraMode(false)
31 32 33 34 35
    , _gimbalYawFact                    (0, _gimbalYawName,                     FactMetaData::valueTypeDouble)
    , _gimbalPitchFact                  (0, _gimbalPitchName,                   FactMetaData::valueTypeDouble)
    , _cameraActionFact                 (0, _cameraActionName,                  FactMetaData::valueTypeDouble)
    , _cameraPhotoIntervalDistanceFact  (0, _cameraPhotoIntervalDistanceName,   FactMetaData::valueTypeDouble)
    , _cameraPhotoIntervalTimeFact      (0, _cameraPhotoIntervalTimeName,       FactMetaData::valueTypeUint32)
36
    , _cameraModeFact                   (0, _cameraModeName,                    FactMetaData::valueTypeUint32)
37 38 39
    , _dirty(false)
{
    if (_metaDataMap.isEmpty()) {
40
        _metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSection.FactMetaData.json"), Q_NULLPTR /* metaDataParent */);
41 42 43 44 45 46 47
    }

    _gimbalPitchFact.setMetaData                    (_metaDataMap[_gimbalPitchName]);
    _gimbalYawFact.setMetaData                      (_metaDataMap[_gimbalYawName]);
    _cameraActionFact.setMetaData                   (_metaDataMap[_cameraActionName]);
    _cameraPhotoIntervalDistanceFact.setMetaData    (_metaDataMap[_cameraPhotoIntervalDistanceName]);
    _cameraPhotoIntervalTimeFact.setMetaData        (_metaDataMap[_cameraPhotoIntervalTimeName]);
48
    _cameraModeFact.setMetaData                     (_metaDataMap[_cameraModeName]);
49 50 51 52 53 54

    _gimbalPitchFact.setRawValue                    (_gimbalPitchFact.rawDefaultValue());
    _gimbalYawFact.setRawValue                      (_gimbalYawFact.rawDefaultValue());
    _cameraActionFact.setRawValue                   (_cameraActionFact.rawDefaultValue());
    _cameraPhotoIntervalDistanceFact.setRawValue    (_cameraPhotoIntervalDistanceFact.rawDefaultValue());
    _cameraPhotoIntervalTimeFact.setRawValue        (_cameraPhotoIntervalTimeFact.rawDefaultValue());
55
    _cameraModeFact.setRawValue                     (_cameraModeFact.rawDefaultValue());
56

57 58
    connect(this,                               &CameraSection::specifyGimbalChanged,       this, &CameraSection::_specifyChanged);
    connect(this,                               &CameraSection::specifyCameraModeChanged,   this, &CameraSection::_specifyChanged);
59

60
    connect(&_cameraActionFact,                 &Fact::valueChanged,                        this, &CameraSection::_cameraActionChanged);
DonLakeFlyer's avatar
DonLakeFlyer committed
61

62 63
    connect(&_gimbalPitchFact,                  &Fact::valueChanged,                        this, &CameraSection::_dirtyIfSpecified);
    connect(&_gimbalYawFact,                    &Fact::valueChanged,                        this, &CameraSection::_dirtyIfSpecified);
64 65 66 67 68 69
    connect(&_cameraPhotoIntervalDistanceFact,  &Fact::valueChanged,                        this, &CameraSection::_setDirty);
    connect(&_cameraPhotoIntervalTimeFact,      &Fact::valueChanged,                        this, &CameraSection::_setDirty);
    connect(&_cameraModeFact,                   &Fact::valueChanged,                        this, &CameraSection::_setDirty);
    connect(this,                               &CameraSection::specifyGimbalChanged,       this, &CameraSection::_setDirty);
    connect(this,                               &CameraSection::specifyCameraModeChanged,   this, &CameraSection::_setDirty);

70
    connect(this,                               &CameraSection::specifyGimbalChanged,       this, &CameraSection::_updateSpecifiedGimbalYaw);
71
    connect(this,                               &CameraSection::specifyGimbalChanged,       this, &CameraSection::_updateSpecifiedGimbalPitch);
72
    connect(&_gimbalYawFact,                    &Fact::valueChanged,                        this, &CameraSection::_updateSpecifiedGimbalYaw);
73
    connect(&_gimbalPitchFact,                  &Fact::valueChanged,                        this, &CameraSection::_updateSpecifiedGimbalPitch);
74 75 76 77 78 79 80 81 82 83
}

void CameraSection::setSpecifyGimbal(bool specifyGimbal)
{
    if (specifyGimbal != _specifyGimbal) {
        _specifyGimbal = specifyGimbal;
        emit specifyGimbalChanged(specifyGimbal);
    }
}

84 85 86 87 88 89 90 91
void CameraSection::setSpecifyCameraMode(bool specifyCameraMode)
{
    if (specifyCameraMode != _specifyCameraMode) {
        _specifyCameraMode = specifyCameraMode;
        emit specifyCameraModeChanged(specifyCameraMode);
    }
}

92
int CameraSection::itemCount(void) const
93 94 95 96 97 98
{
    int itemCount = 0;

    if (_specifyGimbal) {
        itemCount++;
    }
99 100 101
    if (_specifyCameraMode) {
        itemCount++;
    }
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    if (_cameraActionFact.rawValue().toInt() != CameraActionNone) {
        itemCount++;
    }

    return itemCount;
}

void CameraSection::setDirty(bool dirty)
{
    if (_dirty != dirty) {
        _dirty = dirty;
        emit dirtyChanged(_dirty);
    }
}

117
void CameraSection::appendSectionItems(QList<MissionItem*>& items, QObject* missionItemParent, int& nextSequenceNumber)
118
{
119
    // IMPORTANT NOTE: If anything changes here you must also change CameraSection::scanForSection
120

DonLakeFlyer's avatar
DonLakeFlyer committed
121 122 123 124
    if (_specifyCameraMode) {
        MissionItem* item = new MissionItem(nextSequenceNumber++,
                                            MAV_CMD_SET_CAMERA_MODE,
                                            MAV_FRAME_MISSION,
125
                                            0,                                              // Reserved (Set to 0)
DonLakeFlyer's avatar
DonLakeFlyer committed
126
                                            _cameraModeFact.rawValue().toDouble(),
127 128 129
                                            qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(),    // reserved
                                            true,                                           // autoContinue
                                            false,                                          // isCurrentItem
DonLakeFlyer's avatar
DonLakeFlyer committed
130 131 132 133
                                            missionItemParent);
        items.append(item);
    }

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    if (_specifyGimbal) {
        MissionItem* item = new MissionItem(nextSequenceNumber++,
                                            MAV_CMD_DO_MOUNT_CONTROL,
                                            MAV_FRAME_MISSION,
                                            _gimbalPitchFact.rawValue().toDouble(),
                                            0,                                      // Gimbal roll
                                            _gimbalYawFact.rawValue().toDouble(),
                                            0, 0, 0,                                // param 4-6 not used
                                            MAV_MOUNT_MODE_MAVLINK_TARGETING,
                                            true,                                   // autoContinue
                                            false,                                  // isCurrentItem
                                            missionItemParent);
        items.append(item);
    }

    if (_cameraActionFact.rawValue().toInt() != CameraActionNone) {
150
        MissionItem* item = nullptr;
151 152 153 154 155 156

        switch (_cameraActionFact.rawValue().toInt()) {
        case TakePhotosIntervalTime:
            item = new MissionItem(nextSequenceNumber++,
                                   MAV_CMD_IMAGE_START_CAPTURE,
                                   MAV_FRAME_MISSION,
Gus Grubba's avatar
Gus Grubba committed
157
                                   0,                                               // Reserved (Set to 0)
158 159
                                   _cameraPhotoIntervalTimeFact.rawValue().toInt(), // Interval
                                   0,                                               // Unlimited photo count
160
                                   qQNaN(), qQNaN(), qQNaN(), qQNaN(),              // reserved
161 162 163 164 165 166 167 168 169 170
                                   true,                                            // autoContinue
                                   false,                                           // isCurrentItem
                                   missionItemParent);
            break;

        case TakePhotoIntervalDistance:
            item = new MissionItem(nextSequenceNumber++,
                                   MAV_CMD_DO_SET_CAM_TRIGG_DIST,
                                   MAV_FRAME_MISSION,
                                   _cameraPhotoIntervalDistanceFact.rawValue().toDouble(),  // Trigger distance
171 172 173
                                   0,                                                       // No shutter integartion
                                   1,                                                       // Trigger immediately
                                   0, 0, 0, 0,                                              // param 4-7 not used
174 175 176 177 178 179 180 181 182
                                   true,                                                    // autoContinue
                                   false,                                                   // isCurrentItem
                                   missionItemParent);
            break;

        case TakeVideo:
            item = new MissionItem(nextSequenceNumber++,
                                   MAV_CMD_VIDEO_START_CAPTURE,
                                   MAV_FRAME_MISSION,
183 184 185 186 187
                                   0,                                               // Reserved (Set to 0)
                                   VIDEO_CAPTURE_STATUS_INTERVAL,                   // CAMERA_CAPTURE_STATUS (default to every 5 seconds)
                                   qQNaN(), qQNaN(), qQNaN(), qQNaN(),  qQNaN(),    // reserved
                                   true,                                            // autoContinue
                                   false,                                           // isCurrentItem
188 189
                                   missionItemParent);
            break;
190 191

        case StopTakingVideo:
192
            appendStopTakingVideo(items, nextSequenceNumber, missionItemParent);
193 194 195
            break;

        case StopTakingPhotos:
196
            appendStopTakingPhotos(items, nextSequenceNumber, missionItemParent);
197
            break;
DonLakeFlyer's avatar
DonLakeFlyer committed
198 199

        case TakePhoto:
200 201 202
            item = new MissionItem(nextSequenceNumber++,
                                   MAV_CMD_IMAGE_START_CAPTURE,
                                   MAV_FRAME_MISSION,
203 204 205 206 207 208
                                   0,                                   // Reserved (Set to 0)
                                   0,                                   // Interval (none)
                                   1,                                   // Take 1 photo
                                   qQNaN(), qQNaN(), qQNaN(), qQNaN(),  // reserved
                                   true,                                // autoContinue
                                   false,                               // isCurrentItem
209
                                   missionItemParent);
DonLakeFlyer's avatar
DonLakeFlyer committed
210
            break;
211 212 213 214 215 216 217
        }
        if (item) {
            items.append(item);
        }
    }
}

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
void CameraSection::appendStopTakingPhotos(QList<MissionItem*>& items, int& seqNum, QObject* missionItemParent)
{
    MissionItem* item = new MissionItem(seqNum++,
                           MAV_CMD_DO_SET_CAM_TRIGG_DIST,
                           MAV_FRAME_MISSION,
                           0,                               // Trigger distance = 0 means stop
                           0, 0, 0, 0, 0, 0,                // param 2-7 not used
                           true,                            // autoContinue
                           false,                           // isCurrentItem
                           missionItemParent);
    items.append(item);
    item = new MissionItem(seqNum++,
                           MAV_CMD_IMAGE_STOP_CAPTURE,
                           MAV_FRAME_MISSION,
                           0,                                                       // Reserved (Set to 0)
                           qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(),    // reserved
                           true,                                                    // autoContinue
                           false,                                                   // isCurrentItem
                           missionItemParent);
    items.append(item);
}

void CameraSection::appendStopTakingVideo(QList<MissionItem*>& items, int& seqNum, QObject* missionItemParent)
{
    MissionItem* item = new MissionItem(seqNum++,
                           MAV_CMD_VIDEO_STOP_CAPTURE,
                           MAV_FRAME_MISSION,
                           0,                                                       // Reserved (Set to 0)
                           qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(),    // reserved
                           true,                                                    // autoContinue
                           false,                                                   // isCurrentItem
                           missionItemParent);
    items.append(item);
}

253
bool CameraSection::_scanGimbal(QmlObjectListModel* visualItems, int scanIndex)
254
{
255 256 257
    if (scanIndex > visualItems->count() -1) {
        return false;
    }
258 259
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
260
        MissionItem& missionItem = item->missionItem();
261 262
        if ((MAV_CMD)item->command() == MAV_CMD_DO_MOUNT_CONTROL) {
            if (missionItem.param2() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == MAV_MOUNT_MODE_MAVLINK_TARGETING) {
263 264 265 266
                setSpecifyGimbal(true);
                gimbalPitch()->setRawValue(missionItem.param1());
                gimbalYaw()->setRawValue(missionItem.param3());
                visualItems->removeAt(scanIndex)->deleteLater();
267
                return true;
268
            }
269 270
        }
    }
271

272 273 274 275 276
    return false;
}

bool CameraSection::_scanTakePhoto(QmlObjectListModel* visualItems, int scanIndex)
{
277 278 279
    if (scanIndex > visualItems->count() -1) {
        return false;
    }
280 281 282 283
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_IMAGE_START_CAPTURE) {
284
            if (missionItem.param1() == 0 && missionItem.param2() == 0 && missionItem.param3() == 1) {
285
                cameraAction()->setRawValue(TakePhoto);
286
                visualItems->removeAt(scanIndex)->deleteLater();
287
                return true;
288
            }
289 290
        }
    }
291

292 293
    return false;
}
294

295 296
bool CameraSection::_scanTakePhotosIntervalTime(QmlObjectListModel* visualItems, int scanIndex)
{
297 298 299
    if (scanIndex > visualItems->count() -1) {
        return false;
    }
300 301 302 303
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_IMAGE_START_CAPTURE) {
304
            if (missionItem.param1() == 0 && missionItem.param2() >= 1 && missionItem.param3() == 0) {
305 306 307 308 309 310 311 312 313 314 315
                cameraAction()->setRawValue(TakePhotosIntervalTime);
                cameraPhotoIntervalTime()->setRawValue(missionItem.param2());
                visualItems->removeAt(scanIndex)->deleteLater();
                return true;
            }
        }
    }

    return false;
}

316
bool CameraSection::scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex, bool removeScannedItems)
317
{
318 319 320
    if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
        return false;
    }
321 322 323 324 325 326
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) {
            if (missionItem.param1() == 0 && missionItem.param2() == 0 && missionItem.param3() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
                if (scanIndex < visualItems->count() - 1) {
327 328
                    SimpleMissionItem* nextItem = visualItems->value<SimpleMissionItem*>(scanIndex + 1);
                    if (nextItem) {
329
                        MissionItem& nextMissionItem = nextItem->missionItem();
330
                        if (nextMissionItem.command() == MAV_CMD_IMAGE_STOP_CAPTURE && nextMissionItem.param1() == 0) {
331 332 333 334
                            if (removeScannedItems) {
                                visualItems->removeAt(scanIndex)->deleteLater();
                                visualItems->removeAt(scanIndex)->deleteLater();
                            }
335
                            return true;
336 337 338
                        }
                    }
                }
339 340 341
            }
        }
    }
342

343 344 345
    return false;
}

346
bool CameraSection::_scanTriggerStartDistance(QmlObjectListModel* visualItems, int scanIndex)
347
{
348 349 350
    if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
        return false;
    }
351 352 353 354
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) {
355 356 357 358 359 360 361 362 363 364 365 366 367 368
            if (missionItem.param1() > 0 && missionItem.param2() == 0 && missionItem.param3() == 1 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
                cameraAction()->setRawValue(TakePhotoIntervalDistance);
                cameraPhotoIntervalDistance()->setRawValue(missionItem.param1());
                visualItems->removeAt(scanIndex)->deleteLater();
                return true;
            }
        }
    }

    return false;
}

bool CameraSection::_scanTriggerStopDistance(QmlObjectListModel* visualItems, int scanIndex)
{
369 370 371
    if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
        return false;
    }
372 373 374 375 376
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) {
            if (missionItem.param1() == 0 && missionItem.param2() == 0 && missionItem.param3() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
377 378 379 380
                cameraAction()->setRawValue(TakePhotoIntervalDistance);
                cameraPhotoIntervalDistance()->setRawValue(missionItem.param1());
                visualItems->removeAt(scanIndex)->deleteLater();
                return true;
381
            }
382 383 384 385 386
        }
    }

    return false;
}
387

388 389
bool CameraSection::_scanTakeVideo(QmlObjectListModel* visualItems, int scanIndex)
{
390 391 392
    if (scanIndex > visualItems->count() -1) {
        return false;
    }
393 394 395 396
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_VIDEO_START_CAPTURE) {
397
            if (missionItem.param1() == 0 && missionItem.param2() == VIDEO_CAPTURE_STATUS_INTERVAL) {
398 399
                cameraAction()->setRawValue(TakeVideo);
                visualItems->removeAt(scanIndex)->deleteLater();
400
                return true;
401
            }
402 403
        }
    }
404

405 406 407
    return false;
}

408
bool CameraSection::scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex, bool removeScannedItems)
409
{
410 411 412
    if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
        return false;
    }
413 414 415 416
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_VIDEO_STOP_CAPTURE) {
417
            if (missionItem.param1() == 0) {
418 419 420
                if (removeScannedItems) {
                    visualItems->removeAt(scanIndex)->deleteLater();
                }
421
                return true;
422
            }
423 424
        }
    }
425

426 427 428 429 430
    return false;
}

bool CameraSection::_scanSetCameraMode(QmlObjectListModel* visualItems, int scanIndex)
{
431 432 433
    if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
        return false;
    }
434 435 436 437
    SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
    if (item) {
        MissionItem& missionItem = item->missionItem();
        if ((MAV_CMD)item->command() == MAV_CMD_SET_CAMERA_MODE) {
438
            // We specifically don't test param 5/6/7 since we don't have NaN persistence for those fields
439
            if (missionItem.param1() == 0 && (missionItem.param2() == CAMERA_MODE_IMAGE || missionItem.param2() == CAMERA_MODE_VIDEO || missionItem.param2() == CAMERA_MODE_IMAGE_SURVEY) && qIsNaN(missionItem.param3())) {
440 441 442
                setSpecifyCameraMode(true);
                cameraMode()->setRawValue(missionItem.param2());
                visualItems->removeAt(scanIndex)->deleteLater();
443
                return true;
444
            }
445 446
        }
    }
447

448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
    return false;
}

bool CameraSection::scanForSection(QmlObjectListModel* visualItems, int scanIndex)
{
    bool foundGimbal = false;
    bool foundCameraAction = false;
    bool foundCameraMode = false;

    qCDebug(CameraSectionLog) << "CameraSection::scanForCameraSection visualItems->count():scanIndex;" << visualItems->count() << scanIndex;

    if (!_available || scanIndex >= visualItems->count()) {
        return false;
    }

    // Scan through the initial mission items for possible mission settings

    while (visualItems->count() > scanIndex) {
        if (!foundGimbal && _scanGimbal(visualItems, scanIndex)) {
            foundGimbal = true;
            continue;
        }
        if (!foundCameraAction && _scanTakePhoto(visualItems, scanIndex)) {
            foundCameraAction = true;
            continue;
        }
        if (!foundCameraAction && _scanTakePhotosIntervalTime(visualItems, scanIndex)) {
            foundCameraAction = true;
            continue;
        }
478 479
        if (!foundCameraAction && scanStopTakingPhotos(visualItems, scanIndex, true /* removeScannedItems */)) {
            cameraAction()->setRawValue(StopTakingPhotos);
480 481 482
            foundCameraAction = true;
            continue;
        }
483 484 485 486 487
        if (!foundCameraAction && _scanTriggerStartDistance(visualItems, scanIndex)) {
            foundCameraAction = true;
            continue;
        }
        if (!foundCameraAction && _scanTriggerStopDistance(visualItems, scanIndex)) {
488 489 490 491 492 493 494
            foundCameraAction = true;
            continue;
        }
        if (!foundCameraAction && _scanTakeVideo(visualItems, scanIndex)) {
            foundCameraAction = true;
            continue;
        }
495 496
        if (!foundCameraAction && scanStopTakingVideo(visualItems, scanIndex, true /* removeScannedItems */)) {
            cameraAction()->setRawValue(StopTakingVideo);
497 498 499 500 501 502
            foundCameraAction = true;
            continue;
        }
        if (!foundCameraMode && _scanSetCameraMode(visualItems, scanIndex)) {
            foundCameraMode = true;
            continue;
503
        }
504
        break;
505 506
    }

507
    qCDebug(CameraSectionLog) << "CameraSection::scanForCameraSection foundGimbal:foundCameraAction:foundCameraMode;" << foundGimbal << foundCameraAction << foundCameraMode;
508

509
    _settingsSpecified = foundGimbal || foundCameraAction || foundCameraMode;
510 511
    emit settingsSpecifiedChanged(_settingsSpecified);

512
    return _settingsSpecified;
513 514 515 516 517 518 519
}

void CameraSection::_setDirty(void)
{
    setDirty(true);
}

520
void CameraSection::_setDirtyAndUpdateItemCount(void)
521
{
522
    emit itemCountChanged(itemCount());
523 524 525 526 527 528 529 530 531 532
    setDirty(true);
}

void CameraSection::setAvailable(bool available)
{
    if (_available != available) {
        _available = available;
        emit availableChanged(available);
    }
}
DonLakeFlyer's avatar
DonLakeFlyer committed
533 534 535 536 537 538

double CameraSection::specifiedGimbalYaw(void) const
{
    return _specifyGimbal ? _gimbalYawFact.rawValue().toDouble() : std::numeric_limits<double>::quiet_NaN();
}

539 540 541 542 543
double CameraSection::specifiedGimbalPitch(void) const
{
    return _specifyGimbal ? _gimbalPitchFact.rawValue().toDouble() : std::numeric_limits<double>::quiet_NaN();
}

DonLakeFlyer's avatar
DonLakeFlyer committed
544 545
void CameraSection::_updateSpecifiedGimbalYaw(void)
{
546 547 548 549 550 551 552 553 554 555
    if (_specifyGimbal) {
        emit specifiedGimbalYawChanged(specifiedGimbalYaw());
    }
}

void CameraSection::_updateSpecifiedGimbalPitch(void)
{
    if (_specifyGimbal) {
        emit specifiedGimbalPitchChanged(specifiedGimbalPitch());
    }
DonLakeFlyer's avatar
DonLakeFlyer committed
556
}
557 558 559

void CameraSection::_updateSettingsSpecified(void)
{
560
    bool newSettingsSpecified = _specifyGimbal || _specifyCameraMode || _cameraActionFact.rawValue().toInt() != CameraActionNone;
561 562 563 564 565 566
    if (newSettingsSpecified != _settingsSpecified) {
        _settingsSpecified = newSettingsSpecified;
        emit settingsSpecifiedChanged(newSettingsSpecified);
    }
}

567
void CameraSection::_specifyChanged(void)
568 569 570 571 572 573 574 575 576 577
{
    _setDirtyAndUpdateItemCount();
    _updateSettingsSpecified();
}

void CameraSection::_cameraActionChanged(void)
{
    _setDirtyAndUpdateItemCount();
    _updateSettingsSpecified();
}
578 579 580

bool CameraSection::cameraModeSupported(void) const
{
581
    return _specifyCameraMode || _vehicle->firmwarePlugin()->supportedMissionCommands().contains(MAV_CMD_SET_CAMERA_MODE);
582
}
583 584 585 586 587 588 589 590

void CameraSection::_dirtyIfSpecified(void)
{
    // We only set the dirty bit if specify gimbal it set. This allows us to change defaults without affecting dirty.
    if (_specifyGimbal) {
        setDirty(true);
    }
}