地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
15 KiB

/****************************************************************************
*
* (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 "SimpleMissionItemTest.h"
#include "QGCApplication.h"
#include "QGroundControlQmlGlobal.h"
#include "SettingsManager.h"
const SimpleMissionItemTest::ItemInfo_t SimpleMissionItemTest::_rgItemInfo[] = {
{ MAV_CMD_NAV_WAYPOINT, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_LOITER_UNLIM, MAV_FRAME_GLOBAL },
{ MAV_CMD_NAV_LOITER_TURNS, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_LOITER_TIME, MAV_FRAME_GLOBAL },
{ MAV_CMD_NAV_LAND, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_TAKEOFF, MAV_FRAME_GLOBAL },
{ MAV_CMD_DO_JUMP, MAV_FRAME_MISSION },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesWaypoint[] = {
{ "Hold", 10.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLoiterUnlim[] = {
{ "Radius", 30.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLoiterTurns[] = {
{ "Radius", 30.1234567 },
{ "Turns", 10.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLoiterTime[] = {
{ "Radius", 30.1234567 },
{ "Hold", 10.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLand[] = {
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesTakeoff[] = {
{ "Pitch", 10.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesDoJump[] = {
{ "Item #", 10.1234567 },
{ "Repeat", 20.1234567 },
};
const SimpleMissionItemTest::ItemExpected_t SimpleMissionItemTest::_rgItemExpected[] = {
// Text field facts count Fact Values Altitude Altitude Mode
{ sizeof(SimpleMissionItemTest::_rgFactValuesWaypoint)/sizeof(SimpleMissionItemTest::_rgFactValuesWaypoint[0]), SimpleMissionItemTest::_rgFactValuesWaypoint, 70.1234567, SimpleMissionItem::AltitudeRelative },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterUnlim)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterUnlim[0]), SimpleMissionItemTest::_rgFactValuesLoiterUnlim, 70.1234567, SimpleMissionItem::AltitudeAMSL },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTurns)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTurns[0]), SimpleMissionItemTest::_rgFactValuesLoiterTurns, 70.1234567, SimpleMissionItem::AltitudeRelative },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTime)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTime[0]), SimpleMissionItemTest::_rgFactValuesLoiterTime, 70.1234567, SimpleMissionItem::AltitudeAMSL },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLand)/sizeof(SimpleMissionItemTest::_rgFactValuesLand[0]), SimpleMissionItemTest::_rgFactValuesLand, 70.1234567, SimpleMissionItem::AltitudeRelative },
{ sizeof(SimpleMissionItemTest::_rgFactValuesTakeoff)/sizeof(SimpleMissionItemTest::_rgFactValuesTakeoff[0]), SimpleMissionItemTest::_rgFactValuesTakeoff, 70.1234567, SimpleMissionItem::AltitudeAMSL },
{ sizeof(SimpleMissionItemTest::_rgFactValuesDoJump)/sizeof(SimpleMissionItemTest::_rgFactValuesDoJump[0]), SimpleMissionItemTest::_rgFactValuesDoJump, qQNaN(), SimpleMissionItem::AltitudeRelative },
};
SimpleMissionItemTest::SimpleMissionItemTest(void)
: _simpleItem(NULL)
{
}
void SimpleMissionItemTest::init(void)
{
VisualMissionItemTest::init();
rgSimpleItemSignals[commandChangedIndex] = SIGNAL(commandChanged(int));
rgSimpleItemSignals[altitudeModeChangedIndex] = SIGNAL(altitudeModeChanged());
rgSimpleItemSignals[friendlyEditAllowedChangedIndex] = SIGNAL(friendlyEditAllowedChanged(bool));
rgSimpleItemSignals[headingDegreesChangedIndex] = SIGNAL(headingDegreesChanged(double));
rgSimpleItemSignals[rawEditChangedIndex] = SIGNAL(rawEditChanged(bool));
rgSimpleItemSignals[cameraSectionChangedIndex] = SIGNAL(cameraSectionChanged(QObject*));
rgSimpleItemSignals[speedSectionChangedIndex] = SIGNAL(speedSectionChanged(QObject*));
rgSimpleItemSignals[coordinateHasRelativeAltitudeChangedIndex] = SIGNAL(coordinateHasRelativeAltitudeChanged(bool));
MissionItem missionItem(1, // sequence number
MAV_CMD_NAV_WAYPOINT,
MAV_FRAME_GLOBAL_RELATIVE_ALT,
10.1234567, // param 1-7
20.1234567,
30.1234567,
40.1234567,
50.1234567,
60.1234567,
70.1234567,
true, // autoContinue
false); // isCurrentItem
_simpleItem = new SimpleMissionItem(_offlineVehicle, true /* editMode */, missionItem);
// It's important top check that the right signals are emitted at the right time since that drives ui change.
// It's also important to check that things are not being over-signalled when they should not be, since that can lead
// to incorrect ui or perf impact of uneeded signals propogating ui change.
_spySimpleItem = new MultiSignalSpy();
QCOMPARE(_spySimpleItem->init(_simpleItem, rgSimpleItemSignals, cSimpleItemSignals), true);
VisualMissionItemTest::_createSpy(_simpleItem, &_spyVisualItem);
}
void SimpleMissionItemTest::cleanup(void)
{
delete _simpleItem;
VisualMissionItemTest::cleanup();
}
void SimpleMissionItemTest::_testEditorFacts(void)
{
Vehicle* vehicle = new Vehicle(MAV_AUTOPILOT_PX4, MAV_TYPE_FIXED_WING, qgcApp()->toolbox()->firmwarePluginManager());
for (size_t i=0; i<sizeof(_rgItemInfo)/sizeof(_rgItemInfo[0]); i++) {
const ItemInfo_t* info = &_rgItemInfo[i];
const ItemExpected_t* expected = &_rgItemExpected[i];
qDebug() << "Command" << info->command;
MissionItem missionItem(1, // sequence number
info->command,
info->frame,
10.1234567, // param 1-7
20.1234567,
30.1234567,
40.1234567,
50.1234567,
60.1234567,
70.1234567,
true, // autoContinue
false); // isCurrentItem
SimpleMissionItem simpleMissionItem(vehicle, true /* editMode */, missionItem);
// Validate that the fact values are correctly returned
size_t factCount = 0;
for (int i=0; i<simpleMissionItem.textFieldFacts()->count(); i++) {
Fact* fact = qobject_cast<Fact*>(simpleMissionItem.textFieldFacts()->get(i));
bool found = false;
for (size_t j=0; j<expected->cFactValues; j++) {
const FactValue_t* factValue = &expected->rgFactValues[j];
if (factValue->name == fact->name()) {
QCOMPARE(fact->rawValue().toDouble(), factValue->value);
factCount ++;
found = true;
break;
}
}
qDebug() << "textFieldFact" << fact->name();
QVERIFY(found);
}
QCOMPARE(factCount, expected->cFactValues);
if (!qIsNaN(expected->altValue)) {
QCOMPARE(simpleMissionItem.altitudeMode(), expected->altMode);
QCOMPARE(simpleMissionItem.altitude()->rawValue().toDouble(), expected->altValue);
}
}
delete vehicle;
}
void SimpleMissionItemTest::_testDefaultValues(void)
{
SimpleMissionItem item(_offlineVehicle);
item.missionItem().setCommand(MAV_CMD_NAV_WAYPOINT);
item.missionItem().setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
QCOMPARE(item.missionItem().param7(), qgcApp()->toolbox()->settingsManager()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble());
}
void SimpleMissionItemTest::_testSignals(void)
{
MissionItem& missionItem = _simpleItem->missionItem();
// Check that changing to the same coordinate does not signal
_simpleItem->setCoordinate(QGeoCoordinate(missionItem.param5(), missionItem.param6(), missionItem.param7()));
QVERIFY(_spyVisualItem->checkNoSignals());
QVERIFY(_spySimpleItem->checkNoSignals());
// Check coordinateChanged signalling. Calling setCoordinate should trigger:
// coordinateChanged
// dirtyChanged
// Check that actually changing coordinate signals correctly
_simpleItem->setCoordinate(QGeoCoordinate(missionItem.param5() + 1, missionItem.param6(), missionItem.param7()));
QVERIFY(_spyVisualItem->checkOnlySignalByMask(coordinateChangedMask | dirtyChangedMask));
_spyVisualItem->clearAllSignals();
_simpleItem->setCoordinate(QGeoCoordinate(missionItem.param5(), missionItem.param6() + 1, missionItem.param7()));
QVERIFY(_spyVisualItem->checkOnlySignalByMask(coordinateChangedMask | dirtyChangedMask));
_spyVisualItem->clearAllSignals();
_simpleItem->setCoordinate(QGeoCoordinate(missionItem.param5(), missionItem.param6(), missionItem.param7() + 1));
QVERIFY(_spyVisualItem->checkOnlySignalByMask(coordinateChangedMask | dirtyChangedMask));
_spyVisualItem->clearAllSignals();
// Check dirtyChanged signalling
missionItem.setParam1(missionItem.param1());
QVERIFY(_spyVisualItem->checkNoSignals());
missionItem.setParam2(missionItem.param2());
QVERIFY(_spyVisualItem->checkNoSignals());
missionItem.setParam3(missionItem.param3());
QVERIFY(_spyVisualItem->checkNoSignals());
missionItem.setParam4(missionItem.param4());
QVERIFY(_spyVisualItem->checkNoSignals());
missionItem.setParam1(missionItem.param1() + 1);
QVERIFY(_spyVisualItem->checkOnlySignalByMask(dirtyChangedMask));
_spyVisualItem->clearAllSignals();
missionItem.setParam1(missionItem.param2() + 1);
QVERIFY(_spyVisualItem->checkOnlySignalByMask(dirtyChangedMask));
_spyVisualItem->clearAllSignals();
missionItem.setParam1(missionItem.param3() + 1);
QVERIFY(_spyVisualItem->checkOnlySignalByMask(dirtyChangedMask));
_spyVisualItem->clearAllSignals();
missionItem.setParam1(missionItem.param4() + 1);
QVERIFY(_spyVisualItem->checkOnlySignalByMask(dirtyChangedMask));
_spyVisualItem->clearAllSignals();
_simpleItem->setAltitudeMode(_simpleItem->altitudeMode() == SimpleMissionItem::AltitudeRelative ? SimpleMissionItem::AltitudeAMSL : SimpleMissionItem::AltitudeRelative);
QVERIFY(_spySimpleItem->checkOnlySignalByMask(dirtyChangedMask | friendlyEditAllowedChangedMask | altitudeModeChangedMask | coordinateHasRelativeAltitudeChangedMask));
_spySimpleItem->clearAllSignals();
_spyVisualItem->clearAllSignals();
// Check commandChanged signalling. Call setCommand should trigger:
// commandChanged
// commandNameChanged
// dirtyChanged
// coordinateChanged - since altitude will be set back to default
_simpleItem->setCommand(MAV_CMD_NAV_WAYPOINT);
QVERIFY(_spyVisualItem->checkNoSignals());
QVERIFY(_spySimpleItem->checkNoSignals());
_simpleItem->setCommand(MAV_CMD_NAV_LOITER_TIME);
QVERIFY(_spySimpleItem->checkSignalsByMask(commandChangedMask));
QVERIFY(_spyVisualItem->checkSignalsByMask(commandNameChangedMask | dirtyChangedMask | coordinateChangedMask));
}
void SimpleMissionItemTest::_testCameraSectionDirty(void)
{
CameraSection* cameraSection = _simpleItem->cameraSection();
QVERIFY(!cameraSection->dirty());
QVERIFY(!_simpleItem->dirty());
// Dirtying the camera section should also dirty the item
cameraSection->setDirty(true);
QVERIFY(_simpleItem->dirty());
// Clearing the dirty bit from the item should also clear the dirty bit on the camera section
_simpleItem->setDirty(false);
QVERIFY(!cameraSection->dirty());
}
void SimpleMissionItemTest::_testSpeedSectionDirty(void)
{
SpeedSection* speedSection = _simpleItem->speedSection();
QVERIFY(!speedSection->dirty());
QVERIFY(!_simpleItem->dirty());
// Dirtying the speed section should also dirty the item
speedSection->setDirty(true);
QVERIFY(_simpleItem->dirty());
// Clearing the dirty bit from the item should also clear the dirty bit on the camera section
_simpleItem->setDirty(false);
QVERIFY(!speedSection->dirty());
}
void SimpleMissionItemTest::_testCameraSection(void)
{
// No gimbal yaw to start with
QVERIFY(qIsNaN(_simpleItem->specifiedGimbalYaw()));
QVERIFY(qIsNaN(_simpleItem->missionGimbalYaw()));
QCOMPARE(_simpleItem->dirty(), false);
double gimbalYaw = 10.1234;
_simpleItem->cameraSection()->setSpecifyGimbal(true);
_simpleItem->cameraSection()->gimbalYaw()->setRawValue(gimbalYaw);
QCOMPARE(_simpleItem->specifiedGimbalYaw(), gimbalYaw);
QVERIFY(qIsNaN(_simpleItem->missionGimbalYaw()));
QCOMPARE(_spyVisualItem->checkSignalsByMask(specifiedGimbalYawChangedMask), true);
QCOMPARE(_simpleItem->dirty(), true);
}
void SimpleMissionItemTest::_testSpeedSection(void)
{
// No flight speed
QVERIFY(qIsNaN(_simpleItem->specifiedFlightSpeed()));
QCOMPARE(_simpleItem->dirty(), false);
double flightSpeed = 10.1234;
_simpleItem->speedSection()->setSpecifyFlightSpeed(true);
_simpleItem->speedSection()->flightSpeed()->setRawValue(flightSpeed);
QCOMPARE(_simpleItem->specifiedFlightSpeed(), flightSpeed);
QCOMPARE(_spyVisualItem->checkSignalsByMask(specifiedFlightSpeedChangedMask), true);
QCOMPARE(_simpleItem->dirty(), true);
}
void SimpleMissionItemTest::_testAltitudePropogation(void)
{
// Make sure that changes to altitude propogate to param 7 of the mission item
_simpleItem->setAltitudeMode(SimpleMissionItem::AltitudeRelative);
_simpleItem->altitude()->setRawValue(_simpleItem->altitude()->rawValue().toDouble() + 1);
QCOMPARE(_simpleItem->altitude()->rawValue().toDouble(), _simpleItem->missionItem().param7());
QCOMPARE(_simpleItem->missionItem().frame(), MAV_FRAME_GLOBAL_RELATIVE_ALT);
_simpleItem->setAltitudeMode(SimpleMissionItem::AltitudeAMSL);
_simpleItem->altitude()->setRawValue(_simpleItem->altitude()->rawValue().toDouble() + 1);
QCOMPARE(_simpleItem->altitude()->rawValue().toDouble(), _simpleItem->missionItem().param7());
QCOMPARE(_simpleItem->missionItem().frame(), MAV_FRAME_GLOBAL);
}