From bb3679d7c6048714558547b41276abcf975f312d Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Fri, 5 May 2017 09:32:23 -0700 Subject: [PATCH] Support load/save/default of NaN for param --- src/JsonHelper.cc | 13 +++++++++++++ src/JsonHelper.h | 22 +++++++++++++++++----- src/MissionManager/MavCmdInfoCommon.json | 7 +++++++ src/MissionManager/MissionCommandUIInfo.cc | 12 ++++++++++-- src/MissionManager/MissionItem.cc | 15 +++++++++++---- src/MissionManager/SimpleMissionItem.cc | 1 + 6 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/JsonHelper.cc b/src/JsonHelper.cc index e6ee750e0..8d44bcb09 100644 --- a/src/JsonHelper.cc +++ b/src/JsonHelper.cc @@ -102,6 +102,10 @@ bool JsonHelper::validateKeyTypes(const QJsonObject& jsonObject, const QStringLi QString valueKey = keys[i]; if (jsonObject.contains(valueKey)) { const QJsonValue& jsonValue = jsonObject[valueKey]; + if (types[i] == QJsonValue::Null && jsonValue.type() == QJsonValue::Double) { + // Null type signals a NaN on a double value + continue; + } if (jsonValue.type() != types[i]) { errorString = QObject::tr("Incorrect value type - key:type:expected %1:%2:%3").arg(valueKey).arg(_jsonValueTypeToString(jsonValue.type())).arg(_jsonValueTypeToString(types[i])); return false; @@ -342,3 +346,12 @@ void JsonHelper::savePolygon(QmlObjectListModel& list, QJsonArray& polygonArray) polygonArray.append(jsonValue); } } + +double JsonHelper::possibleNaNJsonValue(const QJsonValue& value) +{ + if (value.type() == QJsonValue::Null) { + return std::numeric_limits::quiet_NaN(); + } else { + return value.toDouble(); + } +} diff --git a/src/JsonHelper.h b/src/JsonHelper.h index dd6f7aa32..8f88dceab 100644 --- a/src/JsonHelper.h +++ b/src/JsonHelper.h @@ -34,20 +34,30 @@ public: /// jsonFileTypeKey - Required and checked to be equal to expectedFileType /// jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion /// jsonGroundStationKey - Required and checked to be string type - /// @return false: validation failed - static bool validateQGCJsonFile(const QJsonObject& jsonObject, ///< root json object + /// @return false: validation failed, errorString set + static bool validateQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate const QString& expectedFileType, ///< correct file type for file int minSupportedVersion, ///< minimum supported version int maxSupportedVersion, ///< maximum supported major version int &version, ///< returned file version QString& errorString); ///< returned error string if validation fails - static bool validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString); - static bool validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList& types, QString& errorString); + /// Validates that the specified keys are in the object + /// @return false: validation failed, errorString set + static bool validateRequiredKeys(const QJsonObject& jsonObject, ///< json object to validate + const QStringList& keys, ///< keys which are required to be present + QString& errorString); ///< returned error string if validation fails + + /// Validates the types of specified keys are in the object + /// @return false: validation failed, errorString set + static bool validateKeyTypes(const QJsonObject& jsonObject, ///< json object to validate + const QStringList& keys, ///< keys to validate + const QList& types, ///< required type for each key, QJsonValue::Null specifies double with possible NaN + QString& errorString); ///< returned error string if validation fails typedef struct { const char* key; ///< json key name - QJsonValue::Type type; ///< type of key + QJsonValue::Type type; ///< required type for key, QJsonValue::Null specifies double with possible NaN bool required; ///< true: key must be present } KeyValidateInfo; @@ -96,6 +106,8 @@ public: static bool parseEnum(const QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString); + /// Returns NaN if the value is null, or it not the double value + static double possibleNaNJsonValue(const QJsonValue& value); static const char* jsonVersionKey; static const char* jsonGroundStationKey; diff --git a/src/MissionManager/MavCmdInfoCommon.json b/src/MissionManager/MavCmdInfoCommon.json index 8ba01705b..1d6cc1f38 100644 --- a/src/MissionManager/MavCmdInfoCommon.json +++ b/src/MissionManager/MavCmdInfoCommon.json @@ -54,6 +54,7 @@ "label": "Heading", "units": "radians", "nanUnchanged": true, + "default": null, "decimalPlaces": 2 } }, @@ -75,6 +76,7 @@ "label": "Heading", "units": "radians", "nanUnchanged": true, + "default": null, "decimalPlaces": 2 } }, @@ -101,6 +103,7 @@ "label": "Heading", "units": "radians", "nanUnchanged": true, + "default": null, "decimalPlaces": 2 } }, @@ -157,6 +160,7 @@ "label": "Heading", "units": "radians", "nanUnchanged": true, + "default": null, "decimalPlaces": 2 } }, @@ -178,6 +182,7 @@ "label": "Heading", "units": "radians", "nanUnchanged": true, + "default": null, "decimalPlaces": 2 } }, @@ -316,6 +321,7 @@ "label": "Heading", "units": "deg", "nanUnchanged": true, + "default": null, "decimalPlaces": 2 } }, @@ -331,6 +337,7 @@ "label": "Heading", "units": "deg", "nanUnchanged": true, + "default": null, "decimalPlaces": 2 } }, diff --git a/src/MissionManager/MissionCommandUIInfo.cc b/src/MissionManager/MissionCommandUIInfo.cc index 8e9b1e3bb..ad63a6b1d 100644 --- a/src/MissionManager/MissionCommandUIInfo.cc +++ b/src/MissionManager/MissionCommandUIInfo.cc @@ -334,7 +334,7 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ // Validate key types QList types; - types << QJsonValue::Double << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Bool; + types << QJsonValue::Null << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Bool; if (!JsonHelper::validateKeyTypes(jsonObject, allParamKeys, types, internalError)) { errorString = _loadErrorString(internalError); return false; @@ -358,7 +358,15 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ paramInfo->_nanUnchanged = paramObject.value(_nanUnchangedJsonKey).toBool(false); if (paramObject.contains(_defaultJsonKey)) { - paramInfo->_defaultValue = paramObject.value(_defaultJsonKey).toDouble(0.0); + if (paramInfo->_nanUnchanged) { + paramInfo->_defaultValue = JsonHelper::possibleNaNJsonValue(paramObject[_defaultJsonKey]); + } else { + if (paramObject[_defaultJsonKey].type() == QJsonValue::Null) { + errorString = QString("Param %1 default value was null/NaN but NaN is not allowed"); + return false; + } + paramInfo->_defaultValue = paramObject.value(_defaultJsonKey).toDouble(0.0); + } } else { paramInfo->_defaultValue = paramInfo->_nanUnchanged ? std::numeric_limits::quiet_NaN() : 0; } diff --git a/src/MissionManager/MissionItem.cc b/src/MissionManager/MissionItem.cc index 80f9effb6..c5bc12c03 100644 --- a/src/MissionManager/MissionItem.cc +++ b/src/MissionManager/MissionItem.cc @@ -260,6 +260,13 @@ bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& err return false; } + for (int i=0; i<4; i++) { + if (rgParams[i].type() != QJsonValue::Double && rgParams[i].type() != QJsonValue::Null) { + errorString = tr("Param %1 incorrect type %2, must be double or null").arg(i+1).arg(rgParams[i].type()); + return false; + } + } + // Make sure to set these first since they can signal other changes setFrame((MAV_FRAME)v2Json[_jsonFrameKey].toInt()); setCommand((MAV_CMD)v2Json[_jsonCommandKey].toInt()); @@ -280,10 +287,10 @@ bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& err setSequenceNumber(sequenceNumber); setAutoContinue(v2Json[_jsonAutoContinueKey].toBool()); - setParam1(rgParams[0].toDouble()); - setParam2(rgParams[1].toDouble()); - setParam3(rgParams[2].toDouble()); - setParam4(rgParams[3].toDouble()); + setParam1(JsonHelper::possibleNaNJsonValue(rgParams[0])); + setParam2(JsonHelper::possibleNaNJsonValue(rgParams[1])); + setParam3(JsonHelper::possibleNaNJsonValue(rgParams[2])); + setParam4(JsonHelper::possibleNaNJsonValue(rgParams[3])); return true; } diff --git a/src/MissionManager/SimpleMissionItem.cc b/src/MissionManager/SimpleMissionItem.cc index 9a63c2cfa..83730e669 100644 --- a/src/MissionManager/SimpleMissionItem.cc +++ b/src/MissionManager/SimpleMissionItem.cc @@ -633,6 +633,7 @@ void SimpleMissionItem::setDefaultsForCommand(void) _missionItem.setParam2(0); break; + case MAV_CMD_NAV_VTOL_LAND: case MAV_CMD_NAV_LAND: _missionItem.setParam7(0); break; -- 2.22.0