Commit 4a36f9d5 authored by Don Gagne's avatar Don Gagne

New V3 format for mission items

Moves all params into param array instead of using GeoCoordinate for
param 5/6/7
parent 6dae1e7e
......@@ -162,12 +162,8 @@ void MissionItem::save(QJsonObject& json) const
json[_jsonAutoContinueKey] = autoContinue();
json[_jsonDoJumpIdKey] = _sequenceNumber;
QJsonArray rgParams = { param1(), param2(), param3(), param4() };
QJsonArray rgParams = { param1(), param2(), param3(), param4(), param5(), param6(), param7() };
json[_jsonParamsKey] = rgParams;
QJsonValue coordinateValue;
JsonHelper::saveGeoCoordinate(QGeoCoordinate(param5(), param6(), param7()), true /* writeAltitude */, coordinateValue);
json[_jsonCoordinateKey] = coordinateValue;
}
bool MissionItem::load(QTextStream &loadStream)
......@@ -229,10 +225,46 @@ bool MissionItem::_convertJsonV1ToV2(const QJsonObject& json, QJsonObject& v2Jso
return true;
}
bool MissionItem::_convertJsonV2ToV3(QJsonObject& json, QString& errorString)
{
// V2 format: param 5/6/7 stored in GeoCoordinate
// V3 format: param 5/6/7 stored in params array
if (!json.contains(_jsonCoordinateKey)) {
// Already V3 format
return true;
}
QList<JsonHelper::KeyValidateInfo> keyInfoList = {
{ _jsonCoordinateKey, QJsonValue::Array, true },
};
if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) {
return false;
}
QGeoCoordinate coordinate;
if (!JsonHelper::loadGeoCoordinate(json[_jsonCoordinateKey], true /* altitudeRequired */, coordinate, errorString)) {
return false;
}
QJsonArray rgParam = json[_jsonParamsKey].toArray();
rgParam.append(coordinate.latitude());
rgParam.append(coordinate.longitude());
rgParam.append(coordinate.altitude());
json[_jsonParamsKey] = rgParam;
json.remove(_jsonCoordinateKey);
return true;
}
bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& errorString)
{
QJsonObject v2Json;
if (!_convertJsonV1ToV2(json, v2Json, errorString)) {
QJsonObject convertedJson;
if (!_convertJsonV1ToV2(json, convertedJson, errorString)) {
return false;
}
if (!_convertJsonV2ToV3(convertedJson, errorString)) {
return false;
}
......@@ -242,21 +274,20 @@ bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& err
{ _jsonCommandKey, QJsonValue::Double, true },
{ _jsonParamsKey, QJsonValue::Array, true },
{ _jsonAutoContinueKey, QJsonValue::Bool, true },
{ _jsonCoordinateKey, QJsonValue::Array, true },
{ _jsonDoJumpIdKey, QJsonValue::Double, false },
};
if (!JsonHelper::validateKeys(v2Json, keyInfoList, errorString)) {
if (!JsonHelper::validateKeys(convertedJson, keyInfoList, errorString)) {
return false;
}
if (v2Json[VisualMissionItem::jsonTypeKey] != VisualMissionItem::jsonTypeSimpleItemValue) {
errorString = tr("Type found: %1 must be: %2").arg(v2Json[VisualMissionItem::jsonTypeKey].toString()).arg(VisualMissionItem::jsonTypeSimpleItemValue);
if (convertedJson[VisualMissionItem::jsonTypeKey] != VisualMissionItem::jsonTypeSimpleItemValue) {
errorString = tr("Type found: %1 must be: %2").arg(convertedJson[VisualMissionItem::jsonTypeKey].toString()).arg(VisualMissionItem::jsonTypeSimpleItemValue);
return false;
}
QJsonArray rgParams = v2Json[_jsonParamsKey].toArray();
if (rgParams.count() != 4) {
errorString = tr("%1 key must contains 4 values").arg(_jsonParamsKey);
QJsonArray rgParams = convertedJson[_jsonParamsKey].toArray();
if (rgParams.count() != 7) {
errorString = tr("%1 key must contains 7 values").arg(_jsonParamsKey);
return false;
}
......@@ -268,29 +299,24 @@ bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& err
}
// Make sure to set these first since they can signal other changes
setFrame((MAV_FRAME)v2Json[_jsonFrameKey].toInt());
setCommand((MAV_CMD)v2Json[_jsonCommandKey].toInt());
QGeoCoordinate coordinate;
if (!JsonHelper::loadGeoCoordinate(v2Json[_jsonCoordinateKey], true /* altitudeRequired */, coordinate, errorString)) {
return false;
}
setParam5(coordinate.latitude());
setParam6(coordinate.longitude());
setParam7(coordinate.altitude());
setFrame((MAV_FRAME)convertedJson[_jsonFrameKey].toInt());
setCommand((MAV_CMD)convertedJson[_jsonCommandKey].toInt());
_doJumpId = -1;
if (v2Json.contains(_jsonDoJumpIdKey)) {
_doJumpId = v2Json[_jsonDoJumpIdKey].toInt();
if (convertedJson.contains(_jsonDoJumpIdKey)) {
_doJumpId = convertedJson[_jsonDoJumpIdKey].toInt();
}
setIsCurrentItem(false);
setSequenceNumber(sequenceNumber);
setAutoContinue(v2Json[_jsonAutoContinueKey].toBool());
setAutoContinue(convertedJson[_jsonAutoContinueKey].toBool());
setParam1(JsonHelper::possibleNaNJsonValue(rgParams[0]));
setParam2(JsonHelper::possibleNaNJsonValue(rgParams[1]));
setParam3(JsonHelper::possibleNaNJsonValue(rgParams[2]));
setParam4(JsonHelper::possibleNaNJsonValue(rgParams[3]));
setParam5(JsonHelper::possibleNaNJsonValue(rgParams[4]));
setParam6(JsonHelper::possibleNaNJsonValue(rgParams[5]));
setParam7(JsonHelper::possibleNaNJsonValue(rgParams[6]));
return true;
}
......
......@@ -114,6 +114,7 @@ private slots:
private:
bool _convertJsonV1ToV2(const QJsonObject& json, QJsonObject& v2Json, QString& errorString);
bool _convertJsonV2ToV3(QJsonObject& json, QString& errorString);
int _sequenceNumber;
int _doJumpId;
......@@ -134,10 +135,12 @@ private:
static const char* _jsonFrameKey;
static const char* _jsonCommandKey;
static const char* _jsonAutoContinueKey;
static const char* _jsonCoordinateKey;
static const char* _jsonParamsKey;
static const char* _jsonDoJumpIdKey;
// Deprecated V2 format keys
static const char* _jsonCoordinateKey;
// Deprecated V1 format keys
static const char* _jsonParam1Key;
static const char* _jsonParam2Key;
......
......@@ -241,20 +241,30 @@ void MissionItemTest::_testFactSignals(void)
QCOMPARE(arguments.at(0).toDouble(), 8.0);
}
void MissionItemTest::_checkExpectedMissionItem(const MissionItem& missionItem)
void MissionItemTest::_checkExpectedMissionItem(const MissionItem& missionItem, bool allNaNs)
{
QCOMPARE(missionItem.sequenceNumber(), _seq);
QCOMPARE(missionItem.isCurrentItem(), false);
QCOMPARE(missionItem.frame(), (MAV_FRAME)3);
QCOMPARE(missionItem.command(), (MAV_CMD)80);
QCOMPARE(missionItem.param1(), 10.0);
QCOMPARE(missionItem.param2(), 20.0);
QCOMPARE(missionItem.param3(), 30.0);
QCOMPARE(missionItem.param4(), 40.0);
QCOMPARE(missionItem.param5(), -10.0);
QCOMPARE(missionItem.param6(), -20.0);
QCOMPARE(missionItem.param7(), -30.0);
QCOMPARE(missionItem.autoContinue(), true);
if (allNaNs) {
QVERIFY(qIsNaN(missionItem.param1()));
QVERIFY(qIsNaN(missionItem.param2()));
QVERIFY(qIsNaN(missionItem.param3()));
QVERIFY(qIsNaN(missionItem.param4()));
QVERIFY(qIsNaN(missionItem.param5()));
QVERIFY(qIsNaN(missionItem.param6()));
QVERIFY(qIsNaN(missionItem.param7()));
} else {
QCOMPARE(missionItem.param1(), 10.0);
QCOMPARE(missionItem.param2(), 20.0);
QCOMPARE(missionItem.param3(), 30.0);
QCOMPARE(missionItem.param4(), 40.0);
QCOMPARE(missionItem.param5(), -10.0);
QCOMPARE(missionItem.param6(), -20.0);
QCOMPARE(missionItem.param7(), -30.0);
}
}
void MissionItemTest::_testLoadFromStream(void)
......@@ -285,21 +295,9 @@ void MissionItemTest::_testLoadFromJsonV1(void)
{
MissionItem missionItem;
QString errorString;
QJsonArray coordinateArray;
coordinateArray << -10.0 << -20.0 <<-30.0;
QJsonObject jsonObject;
jsonObject.insert(MissionItem::_jsonAutoContinueKey, true);
jsonObject.insert(MissionItem::_jsonCommandKey, 80);
jsonObject.insert(MissionItem::_jsonFrameKey, 3);
jsonObject.insert(MissionItem::_jsonParam1Key, 10);
jsonObject.insert(MissionItem::_jsonParam2Key, 20);
jsonObject.insert(MissionItem::_jsonParam3Key, 30);
jsonObject.insert(MissionItem::_jsonParam4Key, 40);
jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue);
jsonObject.insert(MissionItem::_jsonCoordinateKey, coordinateArray);
QJsonObject jsonObject = _createV1Json();
// We only need to test the differences between V1 and V2
// V1 format has param 1-4 in seperate items instead of in params array
QStringList removeKeys;
removeKeys << MissionItem::_jsonParam1Key << MissionItem::_jsonParam2Key << MissionItem::_jsonParam3Key << MissionItem::_jsonParam4Key;
......@@ -313,7 +311,11 @@ void MissionItemTest::_testLoadFromJsonV1(void)
// Test good load
QVERIFY(missionItem.load(jsonObject, _seq, errorString));
bool success = missionItem.load(jsonObject, _seq, errorString);
if (!success) {
qDebug() << errorString;
}
QVERIFY(success);
_checkExpectedMissionItem(missionItem);
}
......@@ -321,27 +323,12 @@ void MissionItemTest::_testLoadFromJsonV2(void)
{
MissionItem missionItem;
QString errorString;
QJsonArray coordinateArray;
coordinateArray << -10.0 << -20.0 <<-30.0;
QJsonObject jsonObject;
jsonObject.insert(MissionItem::_jsonAutoContinueKey, true);
jsonObject.insert(MissionItem::_jsonCommandKey, 80);
jsonObject.insert(MissionItem::_jsonFrameKey, 3);
jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue);
jsonObject.insert(MissionItem::_jsonCoordinateKey, coordinateArray);
QJsonArray rgParams = { 10, 20, 30, 40 };
jsonObject.insert(MissionItem::_jsonParamsKey, rgParams);
QJsonObject jsonObject = _createV2Json();
// Test missing key detection
QStringList removeKeys;
removeKeys << MissionItem::_jsonAutoContinueKey <<
MissionItem::_jsonCommandKey <<
MissionItem::_jsonFrameKey <<
MissionItem::_jsonParamsKey <<
VisualMissionItem::jsonTypeKey <<
MissionItem::_jsonCoordinateKey;
removeKeys << MissionItem::_jsonCoordinateKey;
foreach(const QString& removeKey, removeKeys) {
QJsonObject badObject = jsonObject;
badObject.remove(removeKey);
......@@ -388,11 +375,50 @@ void MissionItemTest::_testLoadFromJsonV2(void)
QVERIFY(!errorString.isEmpty());
qDebug() << errorString;
// Test bad type
// Test good load
bool result = missionItem.load(jsonObject, _seq, errorString);
if (!result) {
qDebug() << errorString;
QVERIFY(result);
}
_checkExpectedMissionItem(missionItem);
}
void MissionItemTest::_testLoadFromJsonV3(void)
{
MissionItem missionItem;
QString errorString;
QJsonObject jsonObject = _createV3Json();
// Test missing key detection
QStringList removeKeys;
removeKeys << MissionItem::_jsonAutoContinueKey <<
MissionItem::_jsonCommandKey <<
MissionItem::_jsonFrameKey <<
MissionItem::_jsonParamsKey <<
VisualMissionItem::jsonTypeKey;
foreach(const QString& removeKey, removeKeys) {
QJsonObject badObject = jsonObject;
badObject.remove(removeKey);
QCOMPARE(missionItem.load(badObject, _seq, errorString), false);
QVERIFY(!errorString.isEmpty());
qDebug() << errorString;
}
// Bad type
QJsonObject badObject = jsonObject;
badObject[VisualMissionItem::jsonTypeKey] = "foo";
QCOMPARE(missionItem.load(badObject, _seq, errorString), false);
QVERIFY(!errorString.isEmpty());
qDebug() << errorString;
// Incorrect param count
badObject = jsonObject;
badObject.remove("type");
badObject["type"] = "foo";
QJsonArray rgParam = badObject[MissionItem::_jsonParamsKey].toArray();
rgParam.removeFirst();
badObject[MissionItem::_jsonParamsKey] = rgParam;
QCOMPARE(missionItem.load(badObject, _seq, errorString), false);
QVERIFY(!errorString.isEmpty());
qDebug() << errorString;
......@@ -407,6 +433,20 @@ void MissionItemTest::_testLoadFromJsonV2(void)
_checkExpectedMissionItem(missionItem);
}
void MissionItemTest::_testLoadFromJsonV3NaN(void)
{
MissionItem missionItem;
QString errorString;
QJsonObject jsonObject = _createV3Json(true /* allNaNs */);
bool result = missionItem.load(jsonObject, _seq, errorString);
if (!result) {
qDebug() << errorString;
QVERIFY(result);
}
_checkExpectedMissionItem(missionItem, true /* allNaNs */);
}
void MissionItemTest::_testSimpleLoadFromJson(void)
{
// We specifically test SimpleMissionItem loading as well since it has additional
......@@ -434,36 +474,75 @@ void MissionItemTest::_testSimpleLoadFromJson(void)
void MissionItemTest::_testSaveToJson(void)
{
MissionItem missionItem;
QString errorString;
missionItem.setSequenceNumber(_seq);
missionItem.setIsCurrentItem(true);
missionItem.setFrame((MAV_FRAME)3);
missionItem.setCommand((MAV_CMD)80);
missionItem.setParam1(10.1234567);
missionItem.setParam2(20.1234567);
missionItem.setParam3(30.1234567);
missionItem.setParam4(40.1234567);
missionItem.setParam5(-10.1234567);
missionItem.setParam6(-20.1234567);
missionItem.setParam7(-30.1234567);
missionItem.setAutoContinue(true);
// Round trip item
QJsonObject jsonObject;
QString errorString;
QJsonObject jsonObject = _createV3Json(false /* allNaNs */);
QVERIFY(missionItem.load(jsonObject, _seq, errorString));
missionItem.save(jsonObject);
QCOMPARE(jsonObject.contains(MissionItem::_jsonCoordinateKey), false);
QVERIFY(missionItem.load(jsonObject, _seq, errorString));
_checkExpectedMissionItem(missionItem, false /* allNaNs */);
QCOMPARE(missionItem.sequenceNumber(), _seq);
QCOMPARE(missionItem.isCurrentItem(), false);
QCOMPARE(missionItem.frame(), (MAV_FRAME)3);
QCOMPARE(missionItem.command(), (MAV_CMD)80);
QCOMPARE(missionItem.param1(), 10.1234567);
QCOMPARE(missionItem.param2(), 20.1234567);
QCOMPARE(missionItem.param3(), 30.1234567);
QCOMPARE(missionItem.param4(), 40.1234567);
QCOMPARE(missionItem.param5(), -10.1234567);
QCOMPARE(missionItem.param6(), -20.1234567);
QCOMPARE(missionItem.param7(), -30.1234567);
QCOMPARE(missionItem.autoContinue(), true);
jsonObject = _createV3Json(true /* allNaNs */);
QVERIFY(missionItem.load(jsonObject, _seq, errorString));
missionItem.save(jsonObject);
QVERIFY(missionItem.load(jsonObject, _seq, errorString));
_checkExpectedMissionItem(missionItem, true /* allNaNs */);
}
QJsonObject MissionItemTest::_createV1Json(void)
{
QJsonObject jsonObject;
QJsonArray coordinateArray;
coordinateArray << -10.0 << -20.0 <<-30.0;
jsonObject.insert(MissionItem::_jsonAutoContinueKey, true);
jsonObject.insert(MissionItem::_jsonCommandKey, 80);
jsonObject.insert(MissionItem::_jsonFrameKey, 3);
jsonObject.insert(MissionItem::_jsonParam1Key, 10);
jsonObject.insert(MissionItem::_jsonParam2Key, 20);
jsonObject.insert(MissionItem::_jsonParam3Key, 30);
jsonObject.insert(MissionItem::_jsonParam4Key, 40);
jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue);
jsonObject.insert(MissionItem::_jsonCoordinateKey, coordinateArray);
return jsonObject;
}
QJsonObject MissionItemTest::_createV2Json(void)
{
QJsonObject jsonObject;
QJsonArray coordinateArray;
coordinateArray << -10.0 << -20.0 <<-30.0;
jsonObject.insert(MissionItem::_jsonAutoContinueKey, true);
jsonObject.insert(MissionItem::_jsonCommandKey, 80);
jsonObject.insert(MissionItem::_jsonFrameKey, 3);
jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue);
jsonObject.insert(MissionItem::_jsonCoordinateKey, coordinateArray);
QJsonArray rgParams = { 10, 20, 30, 40 };
jsonObject.insert(MissionItem::_jsonParamsKey, rgParams);
return jsonObject;
}
QJsonObject MissionItemTest::_createV3Json(bool allNaNs)
{
QJsonObject jsonObject;
jsonObject.insert(MissionItem::_jsonAutoContinueKey, true);
jsonObject.insert(MissionItem::_jsonCommandKey, 80);
jsonObject.insert(MissionItem::_jsonFrameKey, 3);
jsonObject.insert(VisualMissionItem::jsonTypeKey, VisualMissionItem::jsonTypeSimpleItemValue);
if (allNaNs) {
QJsonArray rgParams = { NAN, NAN, NAN, NAN, NAN, NAN, NAN };
jsonObject.insert(MissionItem::_jsonParamsKey, rgParams);
} else {
QJsonArray rgParams = { 10, 20, 30, 40, -10, -20, -30 };
jsonObject.insert(MissionItem::_jsonParamsKey, rgParams);
}
return jsonObject;
}
......@@ -35,11 +35,16 @@ private slots:
void _testSimpleLoadFromStream(void);
void _testLoadFromJsonV1(void);
void _testLoadFromJsonV2(void);
void _testLoadFromJsonV3(void);
void _testLoadFromJsonV3NaN(void);
void _testSimpleLoadFromJson(void);
void _testSaveToJson(void);
private:
void _checkExpectedMissionItem(const MissionItem& missionItem);
void _checkExpectedMissionItem(const MissionItem& missionItem, bool allNaNs = false);
QJsonObject _createV1Json(void);
QJsonObject _createV2Json(void);
QJsonObject _createV3Json(bool allNaNs = false);
int _seq = 10;
Vehicle* _offlineVehicle;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment