Commit 92e7bf38 authored by Don Gagne's avatar Don Gagne

parent 4d0fd52a
......@@ -12,6 +12,7 @@ Note: This file only contains high level features or important fixes.
* Make Distance to GCS available for display from instrument panel.
* Make Heading to Home available for display from instrument panel.
* Edit Position dialog available on polygon vertices.
* Fixed Wing Landing Pattern: Add stop photo/video support. Defaults to on such that doing an RTL will stop camera.
## 3.4
......
......@@ -434,6 +434,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/CameraCalcTest.h \
src/MissionManager/CameraSectionTest.h \
src/MissionManager/CorridorScanComplexItemTest.h \
src/MissionManager/FWLandingPatternTest.h \
src/MissionManager/MissionCommandTreeTest.h \
src/MissionManager/MissionControllerManagerTest.h \
src/MissionManager/MissionControllerTest.h \
......@@ -475,6 +476,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/CameraCalcTest.cc \
src/MissionManager/CameraSectionTest.cc \
src/MissionManager/CorridorScanComplexItemTest.cc \
src/MissionManager/FWLandingPatternTest.cc \
src/MissionManager/MissionCommandTreeTest.cc \
src/MissionManager/MissionControllerManagerTest.cc \
src/MissionManager/MissionControllerTest.cc \
......
......@@ -37,7 +37,7 @@ CameraSection::CameraSection(Vehicle* vehicle, QObject* parent)
, _dirty(false)
{
if (_metaDataMap.isEmpty()) {
_metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSection.FactMetaData.json"), NULL /* metaDataParent */);
_metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSection.FactMetaData.json"), Q_NULLPTR /* metaDataParent */);
}
_gimbalPitchFact.setMetaData (_metaDataMap[_gimbalPitchName]);
......@@ -122,11 +122,11 @@ void CameraSection::appendSectionItems(QList<MissionItem*>& items, QObject* miss
MissionItem* item = new MissionItem(nextSequenceNumber++,
MAV_CMD_SET_CAMERA_MODE,
MAV_FRAME_MISSION,
0, // Reserved (Set to 0)
0, // Reserved (Set to 0)
_cameraModeFact.rawValue().toDouble(),
NAN, NAN, NAN, NAN, NAN, // param 3-7 reserved
true, // autoContinue
false, // isCurrentItem
qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), // reserved
true, // autoContinue
false, // isCurrentItem
missionItemParent);
items.append(item);
}
......@@ -157,7 +157,7 @@ void CameraSection::appendSectionItems(QList<MissionItem*>& items, QObject* miss
0, // Reserved (Set to 0)
_cameraPhotoIntervalTimeFact.rawValue().toInt(), // Interval
0, // Unlimited photo count
NAN, NAN, NAN, NAN, // param 4-7 reserved
qQNaN(), qQNaN(), qQNaN(), qQNaN(), // reserved
true, // autoContinue
false, // isCurrentItem
missionItemParent);
......@@ -180,55 +180,32 @@ void CameraSection::appendSectionItems(QList<MissionItem*>& items, QObject* miss
item = new MissionItem(nextSequenceNumber++,
MAV_CMD_VIDEO_START_CAPTURE,
MAV_FRAME_MISSION,
0, // Reserved (Set to 0)
VIDEO_CAPTURE_STATUS_INTERVAL, // CAMERA_CAPTURE_STATUS (default to every 5 seconds)
NAN, NAN, NAN, NAN, NAN, // param 3-7 reserved
true, // autoContinue
false, // isCurrentItem
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
missionItemParent);
break;
case StopTakingVideo:
item = new MissionItem(nextSequenceNumber++,
MAV_CMD_VIDEO_STOP_CAPTURE,
MAV_FRAME_MISSION,
0, // Reserved (Set to 0)
NAN, NAN, NAN, NAN, NAN, NAN, // param 2-7 reserved
true, // autoContinue
false, // isCurrentItem
missionItemParent);
appendStopTakingVideo(items, nextSequenceNumber, missionItemParent);
break;
case StopTakingPhotos:
item = new MissionItem(nextSequenceNumber++,
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(nextSequenceNumber++,
MAV_CMD_IMAGE_STOP_CAPTURE,
MAV_FRAME_MISSION,
0, // Reserved (Set to 0)
NAN, NAN, NAN, NAN, NAN, NAN, // param 2-7 reserved
true, // autoContinue
false, // isCurrentItem
missionItemParent);
appendStopTakingPhotos(items, nextSequenceNumber, missionItemParent);
break;
case TakePhoto:
item = new MissionItem(nextSequenceNumber++,
MAV_CMD_IMAGE_START_CAPTURE,
MAV_FRAME_MISSION,
0, // Reserved (Set to 0)
0, // Interval (none)
1, // Take 1 photo
NAN, NAN, NAN, NAN, // param 4-7 reserved
true, // autoContinue
false, // isCurrentItem
0, // Reserved (Set to 0)
0, // Interval (none)
1, // Take 1 photo
qQNaN(), qQNaN(), qQNaN(), qQNaN(), // reserved
true, // autoContinue
false, // isCurrentItem
missionItemParent);
break;
}
......@@ -238,8 +215,46 @@ void CameraSection::appendSectionItems(QList<MissionItem*>& items, QObject* miss
}
}
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);
}
bool CameraSection::_scanGimbal(QmlObjectListModel* visualItems, int scanIndex)
{
if (scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -259,6 +274,9 @@ bool CameraSection::_scanGimbal(QmlObjectListModel* visualItems, int scanIndex)
bool CameraSection::_scanTakePhoto(QmlObjectListModel* visualItems, int scanIndex)
{
if (scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -276,6 +294,9 @@ bool CameraSection::_scanTakePhoto(QmlObjectListModel* visualItems, int scanInde
bool CameraSection::_scanTakePhotosIntervalTime(QmlObjectListModel* visualItems, int scanIndex)
{
if (scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -292,8 +313,11 @@ bool CameraSection::_scanTakePhotosIntervalTime(QmlObjectListModel* visualItems,
return false;
}
bool CameraSection::_scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex)
bool CameraSection::scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex, bool removeScannedItems)
{
if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -304,9 +328,10 @@ bool CameraSection::_scanStopTakingPhotos(QmlObjectListModel* visualItems, int s
if (nextItem) {
MissionItem& nextMissionItem = nextItem->missionItem();
if (nextMissionItem.command() == MAV_CMD_IMAGE_STOP_CAPTURE && nextMissionItem.param1() == 0) {
cameraAction()->setRawValue(StopTakingPhotos);
visualItems->removeAt(scanIndex)->deleteLater();
visualItems->removeAt(scanIndex)->deleteLater();
if (removeScannedItems) {
visualItems->removeAt(scanIndex)->deleteLater();
visualItems->removeAt(scanIndex)->deleteLater();
}
return true;
}
}
......@@ -320,6 +345,9 @@ bool CameraSection::_scanStopTakingPhotos(QmlObjectListModel* visualItems, int s
bool CameraSection::_scanTriggerStartDistance(QmlObjectListModel* visualItems, int scanIndex)
{
if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -338,6 +366,9 @@ bool CameraSection::_scanTriggerStartDistance(QmlObjectListModel* visualItems, i
bool CameraSection::_scanTriggerStopDistance(QmlObjectListModel* visualItems, int scanIndex)
{
if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -356,6 +387,9 @@ bool CameraSection::_scanTriggerStopDistance(QmlObjectListModel* visualItems, in
bool CameraSection::_scanTakeVideo(QmlObjectListModel* visualItems, int scanIndex)
{
if (scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -371,15 +405,19 @@ bool CameraSection::_scanTakeVideo(QmlObjectListModel* visualItems, int scanInde
return false;
}
bool CameraSection::_scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex)
bool CameraSection::scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex, bool removeScannedItems)
{
if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
if ((MAV_CMD)item->command() == MAV_CMD_VIDEO_STOP_CAPTURE) {
if (missionItem.param1() == 0) {
cameraAction()->setRawValue(StopTakingVideo);
visualItems->removeAt(scanIndex)->deleteLater();
if (removeScannedItems) {
visualItems->removeAt(scanIndex)->deleteLater();
}
return true;
}
}
......@@ -390,6 +428,9 @@ bool CameraSection::_scanStopTakingVideo(QmlObjectListModel* visualItems, int sc
bool CameraSection::_scanSetCameraMode(QmlObjectListModel* visualItems, int scanIndex)
{
if (scanIndex < 0 || scanIndex > visualItems->count() -1) {
return false;
}
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
......@@ -434,7 +475,8 @@ bool CameraSection::scanForSection(QmlObjectListModel* visualItems, int scanInde
foundCameraAction = true;
continue;
}
if (!foundCameraAction && _scanStopTakingPhotos(visualItems, scanIndex)) {
if (!foundCameraAction && scanStopTakingPhotos(visualItems, scanIndex, true /* removeScannedItems */)) {
cameraAction()->setRawValue(StopTakingPhotos);
foundCameraAction = true;
continue;
}
......@@ -450,7 +492,8 @@ bool CameraSection::scanForSection(QmlObjectListModel* visualItems, int scanInde
foundCameraAction = true;
continue;
}
if (!foundCameraAction && _scanStopTakingVideo(visualItems, scanIndex)) {
if (!foundCameraAction && scanStopTakingVideo(visualItems, scanIndex, true /* removeScannedItems */)) {
cameraAction()->setRawValue(StopTakingVideo);
foundCameraAction = true;
continue;
}
......
......@@ -67,6 +67,13 @@ public:
///< @return The gimbal pitch specified by this item, NaN if not specified
double specifiedGimbalPitch(void) const;
static bool scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex, bool removeScannedItems);
static bool scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex, bool removeScannedItems);
static void appendStopTakingPhotos(QList<MissionItem*>& items, int& seqNum, QObject* missionItemParent);
static void appendStopTakingVideo(QList<MissionItem*>& items, int& seqNum, QObject* missionItemParent);
static int stopTakingPhotosCommandCount(void) { return 2; }
static int stopTakingVideoCommandCount(void) { return 1; }
// Overrides from Section
bool available (void) const override { return _available; }
bool dirty (void) const override { return _dirty; }
......@@ -97,11 +104,9 @@ private:
bool _scanGimbal(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTakePhoto(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTakePhotosIntervalTime(QmlObjectListModel* visualItems, int scanIndex);
bool _scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTriggerStartDistance(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTriggerStopDistance(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTakeVideo(QmlObjectListModel* visualItems, int scanIndex);
bool _scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex);
bool _scanSetCameraMode(QmlObjectListModel* visualItems, int scanIndex);
bool _available;
......
......@@ -20,9 +20,6 @@ CameraSectionTest::CameraSectionTest(void)
, _validDistanceItem (NULL)
, _validTimeItem (NULL)
, _validStartVideoItem (NULL)
, _validStopVideoItem (NULL)
, _validStopDistanceItem (NULL)
, _validStopTimeItem (NULL)
, _validCameraPhotoModeItem (NULL)
, _validCameraVideoModeItem (NULL)
, _validCameraSurveyPhotoModeItem (NULL)
......@@ -75,18 +72,6 @@ void CameraSectionTest::init(void)
true, // autocontinue
false), // isCurrentItem
this);
_validStopVideoItem = new SimpleMissionItem(_offlineVehicle,
false, // flyView
MissionItem(0, MAV_CMD_VIDEO_STOP_CAPTURE, MAV_FRAME_MISSION, 0, NAN, NAN, NAN, NAN, NAN, NAN, true, false),
this);
_validStopDistanceItem = new SimpleMissionItem(_offlineVehicle,
false, // flyView
MissionItem(0, MAV_CMD_DO_SET_CAM_TRIGG_DIST, MAV_FRAME_MISSION, 0, 0, 0, 0, 0, 0, 0, true, false),
this);
_validStopTimeItem = new SimpleMissionItem(_offlineVehicle,
false, // flyView
MissionItem(1, MAV_CMD_IMAGE_STOP_CAPTURE, MAV_FRAME_MISSION, 0, NAN, NAN, NAN, NAN, NAN, NAN, true, false),
this);
_validCameraPhotoModeItem = new SimpleMissionItem(_offlineVehicle,
false, // flyView
MissionItem(0, // sequence number
......@@ -132,6 +117,10 @@ void CameraSectionTest::init(void)
true, // autoContinue
false), // isCurrentItem
this);
_validStopVideoItem = createValidStopVideoItem(_offlineVehicle, this);
_validStopDistanceItem = createValidStopDistanceItem(_offlineVehicle, this);
_validStopTimeItem = createValidStopTimeItem(_offlineVehicle, this);
}
void CameraSectionTest::cleanup(void)
......@@ -471,8 +460,6 @@ void CameraSectionTest::_testAppendSectionItems(void)
QCOMPARE(seqNum, 0);
rgMissionItems.clear();
// Test specifyGimbal
_cameraSection->setSpecifyGimbal(true);
_cameraSection->gimbalPitch()->setRawValue(_validGimbalItem->missionItem().param1());
_cameraSection->gimbalYaw()->setRawValue(_validGimbalItem->missionItem().param3());
......@@ -484,8 +471,6 @@ void CameraSectionTest::_testAppendSectionItems(void)
rgMissionItems.clear();
seqNum = 0;
// Test specifyCameraMode
_cameraSection->setSpecifyCameraMode(true);
_cameraSection->cameraMode()->setRawValue(CAMERA_MODE_IMAGE);
_cameraSection->appendSectionItems(rgMissionItems, this, seqNum);
......@@ -910,7 +895,7 @@ void CameraSectionTest::_testScanForStopVideoSection(void)
/*
MAV_CMD_VIDEO_STOP_CAPTURE Stop the current video capture (recording)
Mission Param #1 Reserved (Set to 0)
*/
*/
SimpleMissionItem* newValidStopVideoItem = new SimpleMissionItem(_offlineVehicle, false /* flyView */, this);
newValidStopVideoItem->missionItem() = _validStopVideoItem->missionItem();
......@@ -941,7 +926,7 @@ void CameraSectionTest::_testScanForStopVideoSection(void)
visualItems.clear();
}
void CameraSectionTest::_testScanForStopImageSection(void)
void CameraSectionTest::_testScanForStopPhotoSection(void)
{
QCOMPARE(_cameraSection->available(), true);
......@@ -1124,3 +1109,28 @@ void CameraSectionTest::_testSpecifiedGimbalValuesChanged(void)
_cameraSection->gimbalPitch()->setRawValue(_cameraSection->gimbalPitch()->rawValue().toDouble() + 1);
QVERIFY(_spyCamera->checkSignalByMask(specifiedGimbalPitchChangedMask));
}
SimpleMissionItem* CameraSectionTest::createValidStopVideoItem(Vehicle* vehicle, QObject* parent)
{
return new SimpleMissionItem(vehicle,
false, // flyView
MissionItem(0, MAV_CMD_VIDEO_STOP_CAPTURE, MAV_FRAME_MISSION, 0, qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), true, false),
parent);
}
SimpleMissionItem* CameraSectionTest::createValidStopDistanceItem(Vehicle* vehicle, QObject* parent)
{
return new SimpleMissionItem(vehicle,
false, // flyView
MissionItem(0, MAV_CMD_DO_SET_CAM_TRIGG_DIST, MAV_FRAME_MISSION, 0, 0, 0, 0, 0, 0, 0, true, false),
parent);
}
SimpleMissionItem* CameraSectionTest::createValidStopTimeItem(Vehicle* vehicle, QObject* parent)
{
return new SimpleMissionItem(vehicle,
false, // flyView
MissionItem(1, MAV_CMD_IMAGE_STOP_CAPTURE, MAV_FRAME_MISSION, 0, qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), true, false),
parent);
}
......@@ -23,6 +23,10 @@ public:
void init(void) override;
void cleanup(void) override;
static SimpleMissionItem* createValidStopVideoItem (Vehicle* vehicle, QObject* parent);
static SimpleMissionItem* createValidStopDistanceItem(Vehicle* vehicle, QObject* parent);
static SimpleMissionItem* createValidStopTimeItem (Vehicle* vehicle, QObject* parent);
private slots:
void _testDirty (void);
void _testSettingsAvailable (void);
......@@ -34,7 +38,7 @@ private slots:
void _testScanForPhotoIntervalDistanceSection (void);
void _testScanForStartVideoSection (void);
void _testScanForStopVideoSection (void);
void _testScanForStopImageSection (void);
void _testScanForStopPhotoSection (void);
void _testScanForCameraModeSection (void);
void _testScanForTakePhotoSection (void);
void _testScanForMultipleItems (void);
......
......@@ -52,5 +52,17 @@
"max": 90,
"decimalPlaces": 1,
"defaultValue": 12.0
},
{
"name": "StopTakingPhotos",
"shortDescription": "Stop taking photos",
"type": "bool",
"defaultValue": true
},
{
"name": "StopTakingVideo",
"shortDescription": "Stop taking video",
"type": "bool",
"defaultValue": true
}
]
/****************************************************************************
*
* (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 "FWLandingPatternTest.h"
#include "QGCApplication.h"
#include "MissionCommandTree.h"
#include "MissionCommandUIInfo.h"
#include "CameraSectionTest.h"
FWLandingPatternTest::FWLandingPatternTest(void)
: _offlineVehicle (Q_NULLPTR)
, _fwItem (Q_NULLPTR)
, _multiSpy (Q_NULLPTR)
, _validStopVideoItem (Q_NULLPTR)
, _validStopDistanceItem (Q_NULLPTR)
, _validStopTimeItem (Q_NULLPTR)
{
}
void FWLandingPatternTest::init(void)
{
UnitTest::init();
rgSignals[dirtyChangedIndex] = SIGNAL(dirtyChanged(bool));
_offlineVehicle = new Vehicle(MAV_AUTOPILOT_PX4, MAV_TYPE_QUADROTOR, qgcApp()->toolbox()->firmwarePluginManager(), this);
_fwItem = new FixedWingLandingComplexItem(_offlineVehicle, false /* flyView */, this);
_multiSpy = new MultiSignalSpy();
QCOMPARE(_multiSpy->init(_fwItem, rgSignals, cSignals), true);
// Start in a clean state
QVERIFY(!_fwItem->dirty());
_fwItem->setLandingCoordinate(QGeoCoordinate(47, -122));
_fwItem->setDirty(false);
QVERIFY(!_fwItem->dirty());
_multiSpy->clearAllSignals();
_validStopVideoItem = CameraSectionTest::createValidStopTimeItem(_offlineVehicle, this);
_validStopDistanceItem = CameraSectionTest::createValidStopTimeItem(_offlineVehicle, this);
_validStopTimeItem = CameraSectionTest::createValidStopTimeItem(_offlineVehicle, this);
}
void FWLandingPatternTest::cleanup(void)
{
delete _fwItem;
delete _offlineVehicle;
delete _multiSpy;
delete _validStopVideoItem;
delete _validStopDistanceItem;
delete _validStopTimeItem;
UnitTest::cleanup();
}
void FWLandingPatternTest::_testDefaults(void)
{
QCOMPARE(_fwItem->stopTakingPhotos()->rawValue().toBool(), true);
QCOMPARE(_fwItem->stopTakingVideo()->rawValue().toBool(), true);
}
void FWLandingPatternTest::_testItemCount(void)
{
QList<MissionItem*> items;
_fwItem->stopTakingPhotos()->setRawValue(true);
_fwItem->stopTakingVideo()->setRawValue(true);
_fwItem->appendMissionItems(items, this);
QCOMPARE(items.count(), 3 + CameraSection::stopTakingPhotosCommandCount() + CameraSection::stopTakingVideoCommandCount());
QCOMPARE(items.count() - 1, _fwItem->lastSequenceNumber());
items.clear();
_fwItem->stopTakingPhotos()->setRawValue(false);
_fwItem->stopTakingVideo()->setRawValue(false);
_fwItem->appendMissionItems(items, this);
QCOMPARE(items.count(), 3);
QCOMPARE(items.count() - 1, _fwItem->lastSequenceNumber());
items.clear();
}
void FWLandingPatternTest::_testAppendSectionItems(void)
{
QList<MissionItem*> rgMissionItems;
// Create the set of appended mission items
_fwItem->stopTakingPhotos()->setRawValue(true);
_fwItem->stopTakingVideo()->setRawValue(true);
_fwItem->appendMissionItems(rgMissionItems, this);
// Convert to visual items
QmlObjectListModel* simpleItems = new QmlObjectListModel(this);
for (MissionItem* item: rgMissionItems) {
SimpleMissionItem* simpleItem = new SimpleMissionItem(_offlineVehicle, false /* flyView */, simpleItems);
simpleItem->missionItem() = *item;
simpleItems->append(simpleItem);
}
// Scan the items back in to verify the same values come back
// Note that the compares does the best it can with doubles going to floats and back causing inaccuracies beyond a fuzzy compare.
QVERIFY(FixedWingLandingComplexItem::scanForItem(simpleItems, false /* flyView */, _offlineVehicle));
QCOMPARE(simpleItems->count(), 1);
_validateItem(simpleItems->value<FixedWingLandingComplexItem*>(0));
// Reset
simpleItems->deleteLater();
rgMissionItems.clear();
// Check for no stop camera actions
_fwItem->stopTakingPhotos()->setRawValue(false);
_fwItem->stopTakingVideo()->setRawValue(false);
_fwItem->appendMissionItems(rgMissionItems, this);
simpleItems = new QmlObjectListModel(this);
for (MissionItem* item: rgMissionItems) {
SimpleMissionItem* simpleItem = new SimpleMissionItem(_offlineVehicle, false /* flyView */, simpleItems);
simpleItem->missionItem() = *item;
simpleItems->append(simpleItem);
}
QVERIFY(FixedWingLandingComplexItem::scanForItem(simpleItems, false /* flyView */, _offlineVehicle));
QCOMPARE(simpleItems->count(), 1);
_validateItem(simpleItems->value<FixedWingLandingComplexItem*>(0));
// Reset
simpleItems->deleteLater();
rgMissionItems.clear();
}
void FWLandingPatternTest::_testDirty(void)
{
_fwItem->setDirty(true);
QVERIFY(_fwItem->dirty());
QVERIFY(_multiSpy->checkOnlySignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_fwItem->setDirty(false);
_multiSpy->clearAllSignals();
// These facts should set dirty when changed
QList<Fact*> rgFacts;
rgFacts << _fwItem->loiterAltitude()
<< _fwItem->landingHeading()
<< _fwItem->loiterRadius()
<< _fwItem->landingAltitude()
<< _fwItem->landingDistance()
<< _fwItem->glideSlope()
<< _fwItem->stopTakingPhotos()
<< _fwItem->stopTakingVideo();
for(Fact* fact: rgFacts) {
qDebug() << fact->name();
QVERIFY(!_fwItem->dirty());
if (fact->typeIsBool()) {
fact->setRawValue(!fact->rawValue().toBool());
} else {
fact->setRawValue(fact->rawValue().toDouble() + 1);
}
QVERIFY(_multiSpy->checkSignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_fwItem->setDirty(false);
_multiSpy->clearAllSignals();
}
rgFacts.clear();
// These bool properties should set dirty when changed
QList<const char*> rgBoolNames;
rgBoolNames << "valueSetIsDistance"
<< "loiterClockwise"
<< "altitudesAreRelative";
const QMetaObject* metaObject = _fwItem->metaObject();
for(const char* boolName: rgBoolNames) {
qDebug() << boolName;
QVERIFY(!_fwItem->dirty());
QMetaProperty boolProp = metaObject->property(metaObject->indexOfProperty(boolName));
QVERIFY(boolProp.write(_fwItem, !boolProp.read(_fwItem).toBool()));
QVERIFY(_multiSpy->checkSignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_fwItem->setDirty(false);
_multiSpy->clearAllSignals();
}
rgFacts.clear();
// These coordinates should set dirty when changed
QVERIFY(!_fwItem->dirty());
_fwItem->setLoiterCoordinate(_fwItem->loiterCoordinate().atDistanceAndAzimuth(1, 0));
QVERIFY(_multiSpy->checkSignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_fwItem->setDirty(false);
_multiSpy->clearAllSignals();
QVERIFY(!_fwItem->dirty());
_fwItem->setLoiterCoordinate(_fwItem->landingCoordinate().atDistanceAndAzimuth(1, 0));
QVERIFY(_multiSpy->checkSignalByMask(dirtyChangedMask));
QVERIFY(_multiSpy->pullBoolFromSignalIndex(dirtyChangedIndex));
_fwItem->setDirty(false);
_multiSpy->clearAllSignals();
}
void FWLandingPatternTest::_testSaveLoad(void)
{
QJsonArray items;
_fwItem->save(items);
QString errorString;
FixedWingLandingComplexItem* newItem = new FixedWingLandingComplexItem(_offlineVehicle, false /* flyView */, this /* parent */);
bool success =newItem->load(items[0].toObject(), 10, errorString);
if (!success) {
qDebug() << errorString;
}
QVERIFY(success);
QVERIFY(errorString.isEmpty());
_validateItem(newItem);
newItem->deleteLater();
}
void FWLandingPatternTest::_validateItem(FixedWingLandingComplexItem* newItem)
{
QVERIFY(newItem);
QVERIFY(fuzzyCompareLatLon(newItem->loiterCoordinate(), _fwItem->loiterCoordinate()));
QVERIFY(fuzzyCompareLatLon(newItem->loiterTangentCoordinate(), _fwItem->loiterTangentCoordinate()));
QVERIFY(fuzzyCompareLatLon(newItem->landingCoordinate(), _fwItem->landingCoordinate()));
QCOMPARE(newItem->stopTakingPhotos()->rawValue().toBool(), _fwItem->stopTakingPhotos()->rawValue().toBool());
QCOMPARE(newItem->stopTakingVideo()->rawValue().toBool(), _fwItem->stopTakingVideo()->rawValue().toBool());
QCOMPARE(newItem->loiterAltitude()->rawValue().toInt(), _fwItem->loiterAltitude()->rawValue().toInt());
QCOMPARE(newItem->loiterRadius()->rawValue().toInt(), _fwItem->loiterRadius()->rawValue().toInt());
QCOMPARE(newItem->landingAltitude()->rawValue().toInt(), _fwItem->landingAltitude()->rawValue().toInt());