From 196165c5a44a476aec0c1ce9523bda10f34af407 Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Tue, 31 Oct 2017 19:49:52 -0700 Subject: [PATCH] Structure Scan persistence and mission creation --- src/MissionManager/CameraCalc.cc | 254 ++++---------- src/MissionManager/CameraCalc.h | 11 +- src/MissionManager/CameraSpec.cc | 319 ++---------------- src/MissionManager/CameraSpec.h | 24 -- src/MissionManager/MissionController.cc | 20 +- .../StructureScanComplexItem.cc | 232 ++++--------- src/MissionManager/StructureScanComplexItem.h | 3 + src/PlanView/StructureScanEditor.qml | 2 +- src/PlanView/StructureScanMapVisual.qml | 2 +- 9 files changed, 192 insertions(+), 675 deletions(-) diff --git a/src/MissionManager/CameraCalc.cc b/src/MissionManager/CameraCalc.cc index 1513961fb..7e0d65157 100644 --- a/src/MissionManager/CameraCalc.cc +++ b/src/MissionManager/CameraCalc.cc @@ -21,6 +21,8 @@ const char* CameraCalc::_frontalOverlapName = "FrontalOverlap"; const char* CameraCalc::_sideOverlapName = "SideOverlap"; const char* CameraCalc::_adjustedFootprintFrontalName = "AdjustedFootprintFrontal"; const char* CameraCalc::_adjustedFootprintSideName = "AdjustedFootprintSide"; +const char* CameraCalc::_jsonCameraSpecTypeKey = "CameraSpecType"; +const char* CameraCalc::_jsonKnownCameraNameKey = "CameraName"; CameraCalc::CameraCalc(Vehicle* vehicle, QObject* parent) : CameraSpec (parent) @@ -47,8 +49,8 @@ CameraCalc::CameraCalc(Vehicle* vehicle, QObject* parent) _imageDensityFact.setMetaData (_metaDataMap[_imageDensityName], true); _frontalOverlapFact.setMetaData (_metaDataMap[_frontalOverlapName], true); _sideOverlapFact.setMetaData (_metaDataMap[_sideOverlapName], true); - _adjustedFootprintSideFact.setMetaData (_metaDataMap[_adjustedFootprintSideName], false); - _adjustedFootprintFrontalFact.setMetaData (_metaDataMap[_adjustedFootprintFrontalName], false); + _adjustedFootprintSideFact.setMetaData (_metaDataMap[_adjustedFootprintSideName], true); + _adjustedFootprintFrontalFact.setMetaData (_metaDataMap[_adjustedFootprintFrontalName], true); connect(this, &CameraCalc::knownCameraNameChanged, this, &CameraCalc::_knownCameraNameChanged); @@ -71,6 +73,22 @@ void CameraCalc::setDirty(bool dirty) } } +void CameraCalc::setCameraSpecType(CameraSpecType cameraSpecType) +{ + if (cameraSpecType != _cameraSpecType) { + _cameraSpecType = cameraSpecType; + emit cameraSpecTypeChanged(_cameraSpecType); + } +} + +void CameraCalc::setKnownCameraName(QString knownCameraName) +{ + if (knownCameraName != _knownCameraName) { + _knownCameraName = knownCameraName; + emit knownCameraNameChanged(_knownCameraName); + } +} + void CameraCalc::_knownCameraNameChanged(QString knownCameraName) { if (_cameraSpecType == CameraSpecKnown) { @@ -150,206 +168,76 @@ void CameraCalc::_recalcTriggerDistance(void) void CameraCalc::save(QJsonObject& json) const { - Q_UNUSED(json); - -#if 0 - QJsonObject saveObject; - - saveObject[JsonHelper::jsonVersionKey] = 3; - saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; - saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; - saveObject[_jsonManualGridKey] = _manualGridFact.rawValue().toBool(); - saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitudeFact.rawValue().toBool(); - saveObject[_jsonHoverAndCaptureKey] = _hoverAndCaptureFact.rawValue().toBool(); - saveObject[_jsonRefly90DegreesKey] = _refly90Degrees; - saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble(); - saveObject[_jsonCameraTriggerInTurnaroundKey] = _cameraTriggerInTurnaroundFact.rawValue().toBool(); - - QJsonObject gridObject; - gridObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble(); - gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelativeFact.rawValue().toBool(); - gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble(); - gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble(); - gridObject[_jsonGridEntryLocationKey] = _gridEntryLocationFact.rawValue().toDouble(); - gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble(); - - saveObject[_jsonGridObjectKey] = gridObject; - - if (!_manualGridFact.rawValue().toBool()) { - QJsonObject cameraObject; - cameraObject[_jsonCameraNameKey] = _cameraFact.rawValue().toString(); - cameraObject[_jsonCameraOrientationLandscapeKey] = _cameraOrientationLandscapeFact.rawValue().toBool(); - cameraObject[_jsonCameraSensorWidthKey] = _cameraSensorWidthFact.rawValue().toDouble(); - cameraObject[_jsonCameraSensorHeightKey] = _cameraSensorHeightFact.rawValue().toDouble(); - cameraObject[_jsonCameraResolutionWidthKey] = _cameraResolutionWidthFact.rawValue().toDouble(); - cameraObject[_jsonCameraResolutionHeightKey] = _cameraResolutionHeightFact.rawValue().toDouble(); - cameraObject[_jsonCameraFocalLengthKey] = _cameraFocalLengthFact.rawValue().toDouble(); - cameraObject[_jsonCameraMinTriggerIntervalKey] = _cameraMinTriggerInterval; - cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble(); - cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt(); - cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt(); - - saveObject[_jsonCameraObjectKey] = cameraObject; + json[_jsonCameraSpecTypeKey] = (int)_cameraSpecType; + json[_adjustedFootprintSideName] = _adjustedFootprintSideFact.rawValue().toDouble(); + json[_adjustedFootprintFrontalName] = _adjustedFootprintFrontalFact.rawValue().toDouble(); + json[_distanceToSurfaceName] = _distanceToSurfaceFact.rawValue().toDouble(); + + if (_cameraSpecType != CameraSpecNone) { + CameraSpec::save(json); + json[_jsonKnownCameraNameKey] = _knownCameraName; + json[_valueSetIsDistanceName] = _valueSetIsDistanceFact.rawValue().toBool(); + json[_imageDensityName] = _imageDensityFact.rawValue().toDouble(); + json[_frontalOverlapName] = _frontalOverlapFact.rawValue().toDouble(); + json[_sideOverlapName] = _sideOverlapFact.rawValue().toDouble(); } - - // Polygon shape - _mapPolygon.saveToJson(saveObject); - - missionItems.append(saveObject); -#endif } -bool CameraCalc::load(const QJsonObject& complexObject, QString& errorString) -{ - Q_UNUSED(complexObject); - Q_UNUSED(errorString); -#if 0 - QJsonObject v2Object = complexObject; - - // We need to pull version first to determine what validation/conversion needs to be performed. - QList versionKeyInfoList = { - { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, - }; - if (!JsonHelper::validateKeys(v2Object, versionKeyInfoList, errorString)) { - return false; - } - - int version = v2Object[JsonHelper::jsonVersionKey].toInt(); - if (version != 2 && version != 3) { - errorString = tr("%1 does not support this version of survey items").arg(qgcApp()->applicationName()); - return false; - } - if (version == 2) { - // Convert to v3 - if (v2Object.contains(VisualMissionItem::jsonTypeKey) && v2Object[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("survey")) { - v2Object[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; - v2Object[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; - } - } - - QList mainKeyInfoList = { - { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, - { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, - { ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true }, - { QGCMapPolygon::jsonPolygonKey, QJsonValue::Array, true }, - { _jsonGridObjectKey, QJsonValue::Object, true }, - { _jsonCameraObjectKey, QJsonValue::Object, false }, - { _jsonCameraTriggerDistanceKey, QJsonValue::Double, true }, - { _jsonManualGridKey, QJsonValue::Bool, true }, - { _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true }, - { _jsonHoverAndCaptureKey, QJsonValue::Bool, false }, - { _jsonRefly90DegreesKey, QJsonValue::Bool, false }, - { _jsonCameraTriggerInTurnaroundKey, QJsonValue::Bool, false }, // Should really be required, but it was missing from initial code due to bug +bool CameraCalc::load(const QJsonObject& json, QString& errorString) +{ + QList keyInfoList1 = { + { _jsonCameraSpecTypeKey, QJsonValue::Double, true }, + { _adjustedFootprintSideName, QJsonValue::Double, true }, + { _adjustedFootprintFrontalName, QJsonValue::Double, true }, + { _distanceToSurfaceName, QJsonValue::Double, true }, }; - if (!JsonHelper::validateKeys(v2Object, mainKeyInfoList, errorString)) { + if (!JsonHelper::validateKeys(json, keyInfoList1, errorString)) { return false; } - QString itemType = v2Object[VisualMissionItem::jsonTypeKey].toString(); - QString complexType = v2Object[ComplexMissionItem::jsonComplexItemTypeKey].toString(); - if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) { - errorString = tr("%1 does not support loading this complex mission item type: %2:%3").arg(qgcApp()->applicationName()).arg(itemType).arg(complexType); + int cameraSpecType = json[_jsonCameraSpecTypeKey].toInt(); + switch (cameraSpecType) { + case CameraSpecNone: + case CameraSpecCustom: + case CameraSpecKnown: + break; + default: + errorString = tr("Unsupported CameraSpecType %d").arg(cameraSpecType); return false; } - _ignoreRecalc = true; - - _mapPolygon.clear(); - - setSequenceNumber(sequenceNumber); - - _manualGridFact.setRawValue (v2Object[_jsonManualGridKey].toBool(true)); - _fixedValueIsAltitudeFact.setRawValue (v2Object[_jsonFixedValueIsAltitudeKey].toBool(true)); - _gridAltitudeRelativeFact.setRawValue (v2Object[_jsonGridAltitudeRelativeKey].toBool(true)); - _hoverAndCaptureFact.setRawValue (v2Object[_jsonHoverAndCaptureKey].toBool(false)); - _cameraTriggerInTurnaroundFact.setRawValue (v2Object[_jsonCameraTriggerInTurnaroundKey].toBool(true)); - - _refly90Degrees = v2Object[_jsonRefly90DegreesKey].toBool(false); - - QList gridKeyInfoList = { - { _jsonGridAltitudeKey, QJsonValue::Double, true }, - { _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true }, - { _jsonGridAngleKey, QJsonValue::Double, true }, - { _jsonGridSpacingKey, QJsonValue::Double, true }, - { _jsonGridEntryLocationKey, QJsonValue::Double, false }, - { _jsonTurnaroundDistKey, QJsonValue::Double, true }, - }; - QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject(); - if (!JsonHelper::validateKeys(gridObject, gridKeyInfoList, errorString)) { - return false; - } - _gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble()); - _gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble()); - _gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble()); - _turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble()); - _cameraTriggerDistanceFact.setRawValue (v2Object[_jsonCameraTriggerDistanceKey].toDouble()); - if (gridObject.contains(_jsonGridEntryLocationKey)) { - _gridEntryLocationFact.setRawValue(gridObject[_jsonGridEntryLocationKey].toDouble()); - } else { - _gridEntryLocationFact.setRawValue(_gridEntryLocationFact.rawDefaultValue()); - } + _disableRecalc = true; - if (!_manualGridFact.rawValue().toBool()) { - if (!v2Object.contains(_jsonCameraObjectKey)) { - errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera"); + setCameraSpecType((CameraSpecType)cameraSpecType); + _adjustedFootprintSideFact.setRawValue (json[_adjustedFootprintSideName].toDouble()); + _adjustedFootprintFrontalFact.setRawValue (json[_adjustedFootprintFrontalName].toDouble()); + _distanceToSurfaceFact.setRawValue (json[_distanceToSurfaceName].toDouble()); + + if (_cameraSpecType != CameraSpecNone) { + QList keyInfoList2 = { + { _jsonKnownCameraNameKey, QJsonValue::String, true }, + { _valueSetIsDistanceName, QJsonValue::Bool, true }, + { _imageDensityName, QJsonValue::Double, true }, + { _frontalOverlapName, QJsonValue::Double, true }, + { _sideOverlapName, QJsonValue::Double, true }, + }; + if (!JsonHelper::validateKeys(json, keyInfoList2, errorString)) { return false; + _disableRecalc = false; } - QJsonObject cameraObject = v2Object[_jsonCameraObjectKey].toObject(); + setKnownCameraName(json[_jsonKnownCameraNameKey].toString()); + _valueSetIsDistanceFact.setRawValue (json[_valueSetIsDistanceName].toBool()); + _imageDensityFact.setRawValue (json[_imageDensityName].toDouble()); + _frontalOverlapFact.setRawValue (json[_frontalOverlapName].toDouble()); + _sideOverlapFact.setRawValue (json[_sideOverlapName].toDouble()); - // Older code had typo on "imageSideOverlap" incorrectly being "imageSizeOverlap" - QString incorrectImageSideOverlap = "imageSizeOverlap"; - if (cameraObject.contains(incorrectImageSideOverlap)) { - cameraObject[_jsonSideOverlapKey] = cameraObject[incorrectImageSideOverlap]; - cameraObject.remove(incorrectImageSideOverlap); - } - - QList cameraKeyInfoList = { - { _jsonGroundResolutionKey, QJsonValue::Double, true }, - { _jsonFrontalOverlapKey, QJsonValue::Double, true }, - { _jsonSideOverlapKey, QJsonValue::Double, true }, - { _jsonCameraSensorWidthKey, QJsonValue::Double, true }, - { _jsonCameraSensorHeightKey, QJsonValue::Double, true }, - { _jsonCameraResolutionWidthKey, QJsonValue::Double, true }, - { _jsonCameraResolutionHeightKey, QJsonValue::Double, true }, - { _jsonCameraFocalLengthKey, QJsonValue::Double, true }, - { _jsonCameraNameKey, QJsonValue::String, true }, - { _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true }, - { _jsonCameraMinTriggerIntervalKey, QJsonValue::Double, false }, - }; - if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) { + if (!CameraSpec::load(json, errorString)) { return false; } - - _cameraFact.setRawValue(cameraObject[_jsonCameraNameKey].toString()); - _cameraOrientationLandscapeFact.setRawValue(cameraObject[_jsonCameraOrientationLandscapeKey].toBool(true)); - - _groundResolutionFact.setRawValue (cameraObject[_jsonGroundResolutionKey].toDouble()); - _frontalOverlapFact.setRawValue (cameraObject[_jsonFrontalOverlapKey].toInt()); - _sideOverlapFact.setRawValue (cameraObject[_jsonSideOverlapKey].toInt()); - _cameraSensorWidthFact.setRawValue (cameraObject[_jsonCameraSensorWidthKey].toDouble()); - _cameraSensorHeightFact.setRawValue (cameraObject[_jsonCameraSensorHeightKey].toDouble()); - _cameraResolutionWidthFact.setRawValue (cameraObject[_jsonCameraResolutionWidthKey].toDouble()); - _cameraResolutionHeightFact.setRawValue (cameraObject[_jsonCameraResolutionHeightKey].toDouble()); - _cameraFocalLengthFact.setRawValue (cameraObject[_jsonCameraFocalLengthKey].toDouble()); - _cameraMinTriggerInterval = cameraObject[_jsonCameraMinTriggerIntervalKey].toDouble(0); } - // Polygon shape - /// Load a polygon from json - /// @param json Json object to load from - /// @param required true: no polygon in object will generate error - /// @param errorString Error string if return is false - /// @return true: success, false: failure (errorString set) - if (!_mapPolygon.loadFromJson(v2Object, true /* required */, errorString)) { - _mapPolygon.clear(); - return false; - } - - _ignoreRecalc = false; - _generateGrid(); + _disableRecalc = false; return true; -#endif - return false; } diff --git a/src/MissionManager/CameraCalc.h b/src/MissionManager/CameraCalc.h index 328644320..be714a1eb 100644 --- a/src/MissionManager/CameraCalc.h +++ b/src/MissionManager/CameraCalc.h @@ -22,8 +22,8 @@ public: Q_ENUMS(CameraSpecType) - Q_PROPERTY(CameraSpecType cameraSpecType MEMBER _cameraSpecType NOTIFY cameraSpecTypeChanged) - Q_PROPERTY(QString knownCameraName MEMBER _knownCameraName NOTIFY knownCameraNameChanged) + Q_PROPERTY(CameraSpecType cameraSpecType READ cameraSpecType WRITE setCameraSpecType NOTIFY cameraSpecTypeChanged) + Q_PROPERTY(QString knownCameraName READ knownCameraName WRITE setKnownCameraName NOTIFY knownCameraNameChanged) Q_PROPERTY(Fact* valueSetIsDistance READ valueSetIsDistance CONSTANT) ///< true: distance specified, resolution calculated Q_PROPERTY(Fact* distanceToSurface READ distanceToSurface CONSTANT) ///< Distance to surface for image foot print calculation Q_PROPERTY(Fact* imageDensity READ imageDensity CONSTANT) ///< Image density on surface (cm/px) @@ -42,6 +42,11 @@ public: CameraSpecKnown }; + CameraSpecType cameraSpecType(void) const { return _cameraSpecType; } + QString knownCameraName(void) const { return _knownCameraName; } + void setCameraSpecType(CameraSpecType cameraSpecType); + void setKnownCameraName(QString knownCameraName); + Fact* valueSetIsDistance (void) { return &_valueSetIsDistanceFact; } Fact* distanceToSurface (void) { return &_distanceToSurfaceFact; } Fact* imageDensity (void) { return &_imageDensityFact; } @@ -99,4 +104,6 @@ private: static const char* _sideOverlapName; static const char* _adjustedFootprintSideName; static const char* _adjustedFootprintFrontalName; + static const char* _jsonCameraSpecTypeKey; + static const char* _jsonKnownCameraNameKey; }; diff --git a/src/MissionManager/CameraSpec.cc b/src/MissionManager/CameraSpec.cc index 7b7dc324b..d07cb293b 100644 --- a/src/MissionManager/CameraSpec.cc +++ b/src/MissionManager/CameraSpec.cc @@ -12,16 +12,6 @@ #include -const char* CameraSpec::_jsonSensorWidthKey = "sensorWidth"; -const char* CameraSpec::_jsonSensorHeightKey = "sensorHeight"; -const char* CameraSpec::_jsonImageWidthKey = "imageWidth"; -const char* CameraSpec::_jsonImageHeightKey = "imageHeight"; -const char* CameraSpec::_jsonFocalLengthKey = "focalLength"; -const char* CameraSpec::_jsonMinTriggerIntervalKey = "minTriggerInterval"; -const char* CameraSpec::_jsonNameKey = "name"; -const char* CameraSpec::_jsonLandscapeKey = "orientationLandscape"; - -const char* CameraSpec::_nameName = "Camera"; const char* CameraSpec::_sensorWidthName = "SensorWidth"; const char* CameraSpec::_sensorHeightName = "SensorHeight"; const char* CameraSpec::_imageWidthName = "ImageWidth"; @@ -35,7 +25,6 @@ CameraSpec::CameraSpec(QObject* parent) : QObject (parent) , _dirty (false) , _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSpec.FactMetaData.json"), this)) - , _nameFact (0, _nameName, FactMetaData::valueTypeString) , _sensorWidthFact (0, _sensorWidthName, FactMetaData::valueTypeDouble) , _sensorHeightFact (0, _sensorHeightName, FactMetaData::valueTypeDouble) , _imageWidthFact (0, _imageWidthName, FactMetaData::valueTypeUint32) @@ -48,47 +37,10 @@ CameraSpec::CameraSpec(QObject* parent) _init(true); } -CameraSpec::CameraSpec(const QString& name, - double sensorWidth, - double sensorHeight, - double imageWidth, - double imageHeight, - double focalLength, - bool landscape, - bool fixedOrientation, - double minTriggerInterval, - QObject* parent) - : QObject (parent) - , _dirty (false) - , _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSpec.FactMetaData.json"), this)) - , _nameFact (0, _nameName, FactMetaData::valueTypeString) - , _sensorWidthFact (0, _sensorWidthName, FactMetaData::valueTypeDouble) - , _sensorHeightFact (0, _sensorHeightName, FactMetaData::valueTypeDouble) - , _imageWidthFact (0, _imageWidthName, FactMetaData::valueTypeUint32) - , _imageHeightFact (0, _imageHeightName, FactMetaData::valueTypeUint32) - , _focalLengthFact (0, _focalLengthName, FactMetaData::valueTypeDouble) - , _landscapeFact (0, _landscapeName, FactMetaData::valueTypeBool) - , _fixedOrientationFact (0, _fixedOrientationName, FactMetaData::valueTypeBool) - , _minTriggerIntervalFact (0, _minTriggerIntervalName, FactMetaData::valueTypeDouble) -{ - _init(false); - - _nameFact.setRawValue (name); - _sensorWidthFact.setRawValue (sensorWidth); - _sensorHeightFact.setRawValue (sensorHeight); - _imageWidthFact.setRawValue (imageWidth); - _imageHeightFact.setRawValue (imageHeight); - _focalLengthFact.setRawValue (focalLength); - _landscapeFact.setRawValue (landscape); - _fixedOrientationFact.setRawValue (fixedOrientation); - _minTriggerIntervalFact.setRawValue (minTriggerInterval); -} - CameraSpec::CameraSpec(const CameraSpec& other, QObject* parent) : QObject (parent) , _dirty (false) , _metaDataMap (FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/CameraSpec.FactMetaData.json"), this)) - , _nameFact (0, _nameName, FactMetaData::valueTypeString) , _sensorWidthFact (0, _sensorWidthName, FactMetaData::valueTypeDouble) , _sensorHeightFact (0, _sensorHeightName, FactMetaData::valueTypeDouble) , _imageWidthFact (0, _imageWidthName, FactMetaData::valueTypeUint32) @@ -105,7 +57,6 @@ CameraSpec::CameraSpec(const CameraSpec& other, QObject* parent) const CameraSpec& CameraSpec::operator=(const CameraSpec& other) { - _nameFact.setRawValue (other._nameFact.rawValue()); _sensorWidthFact.setRawValue (other._sensorWidthFact.rawValue()); _sensorHeightFact.setRawValue (other._sensorHeightFact.rawValue()); _imageWidthFact.setRawValue (other._imageWidthFact.rawValue()); @@ -122,7 +73,6 @@ void CameraSpec::_init(bool setDefaults) { QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); - _nameFact.setMetaData (_metaDataMap[_nameName], setDefaults /* setDefaultFromMetaData */); _sensorWidthFact.setMetaData (_metaDataMap[_sensorWidthName], setDefaults); _sensorHeightFact.setMetaData (_metaDataMap[_sensorHeightName], setDefaults); _imageWidthFact.setMetaData (_metaDataMap[_imageWidthName], setDefaults); @@ -143,255 +93,40 @@ void CameraSpec::setDirty(bool dirty) void CameraSpec::save(QJsonObject& json) const { - Q_UNUSED(json); -#if 0 - QJsonObject saveObject; - - saveObject[JsonHelper::jsonVersionKey] = 3; - saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; - saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; - saveObject[_jsonManualGridKey] = _manualGridFact.rawValue().toBool(); - saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitudeFact.rawValue().toBool(); - saveObject[_jsonHoverAndCaptureKey] = _hoverAndCaptureFact.rawValue().toBool(); - saveObject[_jsonRefly90DegreesKey] = _refly90Degrees; - saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble(); - saveObject[_jsonCameraTriggerInTurnaroundKey] = _cameraTriggerInTurnaroundFact.rawValue().toBool(); - - QJsonObject gridObject; - gridObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble(); - gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelativeFact.rawValue().toBool(); - gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble(); - gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble(); - gridObject[_jsonGridEntryLocationKey] = _gridEntryLocationFact.rawValue().toDouble(); - gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble(); - - saveObject[_jsonGridObjectKey] = gridObject; - - if (!_manualGridFact.rawValue().toBool()) { - QJsonObject cameraObject; - cameraObject[_jsonCameraNameKey] = _cameraFact.rawValue().toString(); - cameraObject[_jsonCameraOrientationLandscapeKey] = _cameraOrientationLandscapeFact.rawValue().toBool(); - cameraObject[_jsonCameraSensorWidthKey] = _cameraSensorWidthFact.rawValue().toDouble(); - cameraObject[_jsonCameraSensorHeightKey] = _cameraSensorHeightFact.rawValue().toDouble(); - cameraObject[_jsonCameraResolutionWidthKey] = _cameraResolutionWidthFact.rawValue().toDouble(); - cameraObject[_jsonCameraResolutionHeightKey] = _cameraResolutionHeightFact.rawValue().toDouble(); - cameraObject[_jsonCameraFocalLengthKey] = _cameraFocalLengthFact.rawValue().toDouble(); - cameraObject[_jsonCameraMinTriggerIntervalKey] = _cameraMinTriggerInterval; - cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble(); - cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt(); - cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt(); - - saveObject[_jsonCameraObjectKey] = cameraObject; - } - - // Polygon shape - _mapPolygon.saveToJson(saveObject); - - missionItems.append(saveObject); -#endif + json[_sensorWidthName] = _sensorWidthFact.rawValue().toDouble(); + json[_sensorHeightName] = _sensorHeightFact.rawValue().toDouble(); + json[_imageWidthName] = _imageWidthFact.rawValue().toDouble(); + json[_imageHeightName] = _imageHeightFact.rawValue().toDouble(); + json[_focalLengthName] = _focalLengthFact.rawValue().toDouble(); + json[_landscapeName] = _landscapeFact.rawValue().toBool(); + json[_fixedOrientationName] = _fixedOrientationFact.rawValue().toBool(); + json[_minTriggerIntervalName] = _minTriggerIntervalFact.rawValue().toDouble(); } -bool CameraSpec::load(const QJsonObject& complexObject, QString& errorString) +bool CameraSpec::load(const QJsonObject& json, QString& errorString) { - Q_UNUSED(complexObject); - Q_UNUSED(errorString); -#if 0 - QJsonObject v2Object = complexObject; - - // We need to pull version first to determine what validation/conversion needs to be performed. - QList versionKeyInfoList = { - { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, - }; - if (!JsonHelper::validateKeys(v2Object, versionKeyInfoList, errorString)) { - return false; - } - - int version = v2Object[JsonHelper::jsonVersionKey].toInt(); - if (version != 2 && version != 3) { - errorString = tr("%1 does not support this version of survey items").arg(qgcApp()->applicationName()); - return false; - } - if (version == 2) { - // Convert to v3 - if (v2Object.contains(VisualMissionItem::jsonTypeKey) && v2Object[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("survey")) { - v2Object[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; - v2Object[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; - } - } - - QList mainKeyInfoList = { - { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, - { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, - { ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true }, - { QGCMapPolygon::jsonPolygonKey, QJsonValue::Array, true }, - { _jsonGridObjectKey, QJsonValue::Object, true }, - { _jsonCameraObjectKey, QJsonValue::Object, false }, - { _jsonCameraTriggerDistanceKey, QJsonValue::Double, true }, - { _jsonManualGridKey, QJsonValue::Bool, true }, - { _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true }, - { _jsonHoverAndCaptureKey, QJsonValue::Bool, false }, - { _jsonRefly90DegreesKey, QJsonValue::Bool, false }, - { _jsonCameraTriggerInTurnaroundKey, QJsonValue::Bool, false }, // Should really be required, but it was missing from initial code due to bug + QList keyInfoList = { + { _sensorWidthName, QJsonValue::Double, true }, + { _sensorHeightName, QJsonValue::Double, true }, + { _imageWidthName, QJsonValue::Double, true }, + { _imageHeightName, QJsonValue::Double, true }, + { _focalLengthName, QJsonValue::Double, true }, + { _landscapeName, QJsonValue::Bool, true }, + { _fixedOrientationName, QJsonValue::Bool, true }, + { _minTriggerIntervalName, QJsonValue::Double, true }, }; - if (!JsonHelper::validateKeys(v2Object, mainKeyInfoList, errorString)) { + if (!JsonHelper::validateKeys(json, keyInfoList, errorString)) { return false; } - QString itemType = v2Object[VisualMissionItem::jsonTypeKey].toString(); - QString complexType = v2Object[ComplexMissionItem::jsonComplexItemTypeKey].toString(); - if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) { - errorString = tr("%1 does not support loading this complex mission item type: %2:%3").arg(qgcApp()->applicationName()).arg(itemType).arg(complexType); - return false; - } - - _ignoreRecalc = true; - - _mapPolygon.clear(); - - setSequenceNumber(sequenceNumber); - - _manualGridFact.setRawValue (v2Object[_jsonManualGridKey].toBool(true)); - _fixedValueIsAltitudeFact.setRawValue (v2Object[_jsonFixedValueIsAltitudeKey].toBool(true)); - _gridAltitudeRelativeFact.setRawValue (v2Object[_jsonGridAltitudeRelativeKey].toBool(true)); - _hoverAndCaptureFact.setRawValue (v2Object[_jsonHoverAndCaptureKey].toBool(false)); - _cameraTriggerInTurnaroundFact.setRawValue (v2Object[_jsonCameraTriggerInTurnaroundKey].toBool(true)); - - _refly90Degrees = v2Object[_jsonRefly90DegreesKey].toBool(false); - - QList gridKeyInfoList = { - { _jsonGridAltitudeKey, QJsonValue::Double, true }, - { _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true }, - { _jsonGridAngleKey, QJsonValue::Double, true }, - { _jsonGridSpacingKey, QJsonValue::Double, true }, - { _jsonGridEntryLocationKey, QJsonValue::Double, false }, - { _jsonTurnaroundDistKey, QJsonValue::Double, true }, - }; - QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject(); - if (!JsonHelper::validateKeys(gridObject, gridKeyInfoList, errorString)) { - return false; - } - _gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble()); - _gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble()); - _gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble()); - _turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble()); - _cameraTriggerDistanceFact.setRawValue (v2Object[_jsonCameraTriggerDistanceKey].toDouble()); - if (gridObject.contains(_jsonGridEntryLocationKey)) { - _gridEntryLocationFact.setRawValue(gridObject[_jsonGridEntryLocationKey].toDouble()); - } else { - _gridEntryLocationFact.setRawValue(_gridEntryLocationFact.rawDefaultValue()); - } - - if (!_manualGridFact.rawValue().toBool()) { - if (!v2Object.contains(_jsonCameraObjectKey)) { - errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera"); - return false; - } - - QJsonObject cameraObject = v2Object[_jsonCameraObjectKey].toObject(); - - // Older code had typo on "imageSideOverlap" incorrectly being "imageSizeOverlap" - QString incorrectImageSideOverlap = "imageSizeOverlap"; - if (cameraObject.contains(incorrectImageSideOverlap)) { - cameraObject[_jsonSideOverlapKey] = cameraObject[incorrectImageSideOverlap]; - cameraObject.remove(incorrectImageSideOverlap); - } - - QList cameraKeyInfoList = { - { _jsonGroundResolutionKey, QJsonValue::Double, true }, - { _jsonFrontalOverlapKey, QJsonValue::Double, true }, - { _jsonSideOverlapKey, QJsonValue::Double, true }, - { _jsonCameraSensorWidthKey, QJsonValue::Double, true }, - { _jsonCameraSensorHeightKey, QJsonValue::Double, true }, - { _jsonCameraResolutionWidthKey, QJsonValue::Double, true }, - { _jsonCameraResolutionHeightKey, QJsonValue::Double, true }, - { _jsonCameraFocalLengthKey, QJsonValue::Double, true }, - { _jsonCameraNameKey, QJsonValue::String, true }, - { _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true }, - { _jsonCameraMinTriggerIntervalKey, QJsonValue::Double, false }, - }; - if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) { - return false; - } - - _cameraFact.setRawValue(cameraObject[_jsonCameraNameKey].toString()); - _cameraOrientationLandscapeFact.setRawValue(cameraObject[_jsonCameraOrientationLandscapeKey].toBool(true)); - - _groundResolutionFact.setRawValue (cameraObject[_jsonGroundResolutionKey].toDouble()); - _frontalOverlapFact.setRawValue (cameraObject[_jsonFrontalOverlapKey].toInt()); - _sideOverlapFact.setRawValue (cameraObject[_jsonSideOverlapKey].toInt()); - _cameraSensorWidthFact.setRawValue (cameraObject[_jsonCameraSensorWidthKey].toDouble()); - _cameraSensorHeightFact.setRawValue (cameraObject[_jsonCameraSensorHeightKey].toDouble()); - _cameraResolutionWidthFact.setRawValue (cameraObject[_jsonCameraResolutionWidthKey].toDouble()); - _cameraResolutionHeightFact.setRawValue (cameraObject[_jsonCameraResolutionHeightKey].toDouble()); - _cameraFocalLengthFact.setRawValue (cameraObject[_jsonCameraFocalLengthKey].toDouble()); - _cameraMinTriggerInterval = cameraObject[_jsonCameraMinTriggerIntervalKey].toDouble(0); - } - - // Polygon shape - /// Load a polygon from json - /// @param json Json object to load from - /// @param required true: no polygon in object will generate error - /// @param errorString Error string if return is false - /// @return true: success, false: failure (errorString set) - if (!_mapPolygon.loadFromJson(v2Object, true /* required */, errorString)) { - _mapPolygon.clear(); - return false; - } - - _ignoreRecalc = false; - _generateGrid(); + _sensorWidthFact.setRawValue (json[_sensorWidthName].toDouble()); + _sensorHeightFact.setRawValue (json[_sensorHeightName].toDouble()); + _imageWidthFact.setRawValue (json[_imageWidthName].toDouble()); + _imageHeightFact.setRawValue (json[_imageHeightName].toDouble()); + _focalLengthFact.setRawValue (json[_focalLengthName].toDouble()); + _landscapeFact.setRawValue (json[_landscapeName].toBool()); + _fixedOrientationFact.setRawValue (json[_fixedOrientationName].toBool()); + _minTriggerIntervalFact.setRawValue (json[_minTriggerIntervalName].toDouble()); return true; -#endif - return false; -} - -#if 0 -void CameraSpec::recalcImageOnGround(bool valueIsAltitude, double value) -{ - var focalLength = missionItem.cameraFocalLength.rawValue - var sensorWidth = missionItem.cameraSensorWidth.rawValue - var sensorHeight = missionItem.cameraSensorHeight.rawValue - var imageWidth = missionItem.cameraResolutionWidth.rawValue - var imageHeight = missionItem.cameraResolutionHeight.rawValue - - var altitude = missionItem.gridAltitude.rawValue - var groundResolution= missionItem.groundResolution.rawValue - var frontalOverlap = missionItem.frontalOverlap.rawValue - var sideOverlap = missionItem.sideOverlap.rawValue - - if (focalLength <= 0 || sensorWidth <= 0 || sensorHeight <= 0 || imageWidth <= 0 || imageHeight <= 0 || groundResolution <= 0) { - return - } - - var imageSizeSideGround //size in side (non flying) direction of the image on the ground - var imageSizeFrontGround //size in front (flying) direction of the image on the ground - var gridSpacing - var cameraTriggerDistance - - if (missionItem.fixedValueIsAltitude.value) { - groundResolution = (altitude * sensorWidth * 100) / (imageWidth * focalLength) - } else { - altitude = (imageWidth * groundResolution * focalLength) / (sensorWidth * 100) - } - - if (missionItem.cameraOrientationLandscape.value) { - imageSizeSideGround = (imageWidth * groundResolution) / 100 - imageSizeFrontGround = (imageHeight * groundResolution) / 100 - } else { - imageSizeSideGround = (imageHeight * groundResolution) / 100 - imageSizeFrontGround = (imageWidth * groundResolution) / 100 - } - - gridSpacing = imageSizeSideGround * ( (100-sideOverlap) / 100 ) - cameraTriggerDistance = imageSizeFrontGround * ( (100-frontalOverlap) / 100 ) - - if (missionItem.fixedValueIsAltitude.value) { - missionItem.groundResolution.rawValue = groundResolution - } else { - missionItem.gridAltitude.rawValue = altitude - } - missionItem.gridSpacing.rawValue = gridSpacing - missionItem.cameraTriggerDistance.rawValue = cameraTriggerDistance } -#endif diff --git a/src/MissionManager/CameraSpec.h b/src/MissionManager/CameraSpec.h index 9b1f87aa5..fe49ba2b1 100644 --- a/src/MissionManager/CameraSpec.h +++ b/src/MissionManager/CameraSpec.h @@ -17,22 +17,11 @@ class CameraSpec : public QObject public: CameraSpec(QObject* parent = NULL); - CameraSpec(const QString& name, - double sensorWidth, - double sensorHeight, - double imageWidth, - double imageHeight, - double focalLength, - bool landscape, - bool fixedOrientation, - double minTriggerInterval, - QObject* parent = NULL); CameraSpec(const CameraSpec& other, QObject* parent); const CameraSpec& operator=(const CameraSpec& other); // These properties are persisted to Json - Q_PROPERTY(Fact* name READ name CONSTANT) ///< Camera name Q_PROPERTY(Fact* sensorWidth READ sensorWidth CONSTANT) ///< Sensor size in millimeters Q_PROPERTY(Fact* sensorHeight READ sensorHeight CONSTANT) ///< Sensor size in millimeters Q_PROPERTY(Fact* imageWidth READ imageWidth CONSTANT) ///< Image size in pixels @@ -42,7 +31,6 @@ public: Q_PROPERTY(Fact* fixedOrientation READ fixedOrientation CONSTANT) ///< true: camera is in fixed orientation Q_PROPERTY(Fact* minTriggerInterval READ minTriggerInterval CONSTANT) ///< Minimum time in seconds between each photo taken, 0 for not specified - Fact* name (void) { return &_nameFact; } Fact* sensorWidth (void) { return &_sensorWidthFact; } Fact* sensorHeight (void) { return &_sensorHeightFact; } Fact* imageWidth (void) { return &_imageWidthFact; } @@ -68,7 +56,6 @@ private: QMap _metaDataMap; - Fact _nameFact; Fact _sensorWidthFact; Fact _sensorHeightFact; Fact _imageWidthFact; @@ -78,7 +65,6 @@ private: Fact _fixedOrientationFact; Fact _minTriggerIntervalFact; - static const char* _nameName; static const char* _sensorWidthName; static const char* _sensorHeightName; static const char* _imageWidthName; @@ -87,14 +73,4 @@ private: static const char* _landscapeName; static const char* _fixedOrientationName; static const char* _minTriggerIntervalName; - - static const char* _jsonNameKey; - static const char* _jsonSensorWidthKey; - static const char* _jsonSensorHeightKey; - static const char* _jsonImageWidthKey; - static const char* _jsonImageHeightKey; - static const char* _jsonFocalLengthKey; - static const char* _jsonLandscapeKey; - static const char* _jsonFixedOrientationKey; - static const char* _jsonMinTriggerIntervalKey; }; diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index db8dfa82b..27e112c67 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -19,6 +19,7 @@ #include "SurveyMissionItem.h" #include "FixedWingLandingComplexItem.h" #include "StructureScanComplexItem.h" +#include "StructureScanComplexItem.h" #include "JsonHelper.h" #include "ParameterManager.h" #include "QGroundControlQmlGlobal.h" @@ -264,11 +265,15 @@ void MissionController::convertToKMLDocument(QDomDocument& document) { QJsonObject missionJson; QmlObjectListModel* visualItems = new QmlObjectListModel(); - QList missionItens; + QList missionItems; QString error; save(missionJson); _loadItemsFromJson(missionJson, visualItems, error); - _convertToMissionItems(visualItems, missionItens, this); + _convertToMissionItems(visualItems, missionItems, this); + + if (missionItems.count() == 0) { + return; + } float altitude = missionJson[_jsonPlannedHomePositionKey].toArray()[2].toDouble(); @@ -276,7 +281,7 @@ void MissionController::convertToKMLDocument(QDomDocument& document) QStringList coords; // Drop home position bool dropPoint = true; - for(const auto& item : missionItens) { + for(const auto& item : missionItems) { if(dropPoint) { dropPoint = false; continue; @@ -655,6 +660,15 @@ bool MissionController::_loadJsonMissionFileV2(const QJsonObject& json, QmlObjec nextSequenceNumber = landingItem->lastSequenceNumber() + 1; qCDebug(MissionControllerLog) << "FW Landing Pattern load complete: nextSequenceNumber" << nextSequenceNumber; visualItems->append(landingItem); + } else if (complexItemType == StructureScanComplexItem::jsonComplexItemTypeValue) { + qCDebug(MissionControllerLog) << "Loading Structure Scan: nextSequenceNumber" << nextSequenceNumber; + StructureScanComplexItem* structureItem = new StructureScanComplexItem(_controllerVehicle, visualItems); + if (!structureItem->load(itemObject, nextSequenceNumber++, errorString)) { + return false; + } + nextSequenceNumber = structureItem->lastSequenceNumber() + 1; + qCDebug(MissionControllerLog) << "Structure Scan load complete: nextSequenceNumber" << nextSequenceNumber; + visualItems->append(structureItem); } else if (complexItemType == MissionSettingsItem::jsonComplexItemTypeValue) { qCDebug(MissionControllerLog) << "Loading Mission Settings: nextSequenceNumber" << nextSequenceNumber; MissionSettingsItem* settingsItem = new MissionSettingsItem(_controllerVehicle, visualItems); diff --git a/src/MissionManager/StructureScanComplexItem.cc b/src/MissionManager/StructureScanComplexItem.cc index d2e4859fe..70528ad12 100644 --- a/src/MissionManager/StructureScanComplexItem.cc +++ b/src/MissionManager/StructureScanComplexItem.cc @@ -21,10 +21,11 @@ QGC_LOGGING_CATEGORY(StructureScanComplexItemLog, "StructureScanComplexItemLog") -const char* StructureScanComplexItem::jsonComplexItemTypeValue = "StructureScan-WIP"; - -const char* StructureScanComplexItem::_altitudeFactName = "Altitude"; -const char* StructureScanComplexItem::_layersFactName = "Layers"; +const char* StructureScanComplexItem::jsonComplexItemTypeValue = "StructureScan"; +const char* StructureScanComplexItem::_altitudeFactName = "Altitude"; +const char* StructureScanComplexItem::_layersFactName = "Layers"; +const char* StructureScanComplexItem::_jsonCameraCalcKey = "CameraCalc"; +const char* StructureScanComplexItem::_jsonAltitudeRelativeKey = "altitudeRelative"; QMap StructureScanComplexItem::_metaDataMap; @@ -121,51 +122,24 @@ void StructureScanComplexItem::setDirty(bool dirty) void StructureScanComplexItem::save(QJsonArray& missionItems) { - Q_UNUSED(missionItems); -#if 0 QJsonObject saveObject; - saveObject[JsonHelper::jsonVersionKey] = 3; + // Header + saveObject[JsonHelper::jsonVersionKey] = 1; saveObject[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; saveObject[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; - saveObject[_jsonManualGridKey] = _manualGridFact.rawValue().toBool(); - saveObject[_jsonFixedValueIsAltitudeKey] = _fixedValueIsAltitudeFact.rawValue().toBool(); - saveObject[_jsonHoverAndCaptureKey] = _hoverAndCaptureFact.rawValue().toBool(); - saveObject[_jsonRefly90DegreesKey] = _refly90Degrees; - saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble(); - - QJsonObject gridObject; - gridObject[_jsonGridAltitudeKey] = _gridAltitudeFact.rawValue().toDouble(); - gridObject[_jsonGridAltitudeRelativeKey] = _gridAltitudeRelativeFact.rawValue().toBool(); - gridObject[_jsonGridAngleKey] = _gridAngleFact.rawValue().toDouble(); - gridObject[_jsonGridSpacingKey] = _gridSpacingFact.rawValue().toDouble(); - gridObject[_jsonGridEntryLocationKey] = _gridEntryLocationFact.rawValue().toDouble(); - gridObject[_jsonTurnaroundDistKey] = _turnaroundDistFact.rawValue().toDouble(); - - saveObject[_jsonGridObjectKey] = gridObject; - - if (!_manualGridFact.rawValue().toBool()) { - QJsonObject cameraObject; - cameraObject[_jsonCameraNameKey] = _cameraFact.rawValue().toString(); - cameraObject[_jsonCameraOrientationLandscapeKey] = _cameraOrientationLandscapeFact.rawValue().toBool(); - cameraObject[_jsonCameraSensorWidthKey] = _cameraSensorWidthFact.rawValue().toDouble(); - cameraObject[_jsonCameraSensorHeightKey] = _cameraSensorHeightFact.rawValue().toDouble(); - cameraObject[_jsonCameraResolutionWidthKey] = _cameraResolutionWidthFact.rawValue().toDouble(); - cameraObject[_jsonCameraResolutionHeightKey] = _cameraResolutionHeightFact.rawValue().toDouble(); - cameraObject[_jsonCameraFocalLengthKey] = _cameraFocalLengthFact.rawValue().toDouble(); - cameraObject[_jsonCameraMinTriggerIntervalKey] = _cameraMinTriggerInterval; - cameraObject[_jsonGroundResolutionKey] = _groundResolutionFact.rawValue().toDouble(); - cameraObject[_jsonFrontalOverlapKey] = _frontalOverlapFact.rawValue().toInt(); - cameraObject[_jsonSideOverlapKey] = _sideOverlapFact.rawValue().toInt(); - - saveObject[_jsonCameraObjectKey] = cameraObject; - } - // Polygon shape + saveObject[_altitudeFactName] = _altitudeFact.rawValue().toDouble(); + saveObject[_jsonAltitudeRelativeKey] = _altitudeRelative; + saveObject[_layersFactName] = _layersFact.rawValue().toDouble(); + + QJsonObject cameraCalcObject; + _cameraCalc.save(cameraCalcObject); + saveObject[_jsonCameraCalcKey] = cameraCalcObject; + _structurePolygon.saveToJson(saveObject); missionItems.append(saveObject); -#endif } void StructureScanComplexItem::setSequenceNumber(int sequenceNumber) @@ -179,158 +153,50 @@ void StructureScanComplexItem::setSequenceNumber(int sequenceNumber) bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequenceNumber, QString& errorString) { -#if 0 - QJsonObject v2Object = complexObject; - - // We need to pull version first to determine what validation/conversion needs to be performed. - QList versionKeyInfoList = { - { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, - }; - if (!JsonHelper::validateKeys(v2Object, versionKeyInfoList, errorString)) { - return false; - } - - int version = v2Object[JsonHelper::jsonVersionKey].toInt(); - if (version != 2 && version != 3) { - errorString = tr("%1 does not support this version of survey items").arg(qgcApp()->applicationName()); - return false; - } - if (version == 2) { - // Convert to v3 - if (v2Object.contains(VisualMissionItem::jsonTypeKey) && v2Object[VisualMissionItem::jsonTypeKey].toString() == QStringLiteral("survey")) { - v2Object[VisualMissionItem::jsonTypeKey] = VisualMissionItem::jsonTypeComplexItemValue; - v2Object[ComplexMissionItem::jsonComplexItemTypeKey] = jsonComplexItemTypeValue; - } - } - - QList mainKeyInfoList = { + QList keyInfoList = { { JsonHelper::jsonVersionKey, QJsonValue::Double, true }, { VisualMissionItem::jsonTypeKey, QJsonValue::String, true }, { ComplexMissionItem::jsonComplexItemTypeKey, QJsonValue::String, true }, { QGCMapPolygon::jsonPolygonKey, QJsonValue::Array, true }, - { _jsonGridObjectKey, QJsonValue::Object, true }, - { _jsonCameraObjectKey, QJsonValue::Object, false }, - { _jsonCameraTriggerDistanceKey, QJsonValue::Double, true }, - { _jsonManualGridKey, QJsonValue::Bool, true }, - { _jsonFixedValueIsAltitudeKey, QJsonValue::Bool, true }, - { _jsonHoverAndCaptureKey, QJsonValue::Bool, false }, - { _jsonRefly90DegreesKey, QJsonValue::Bool, false }, + { _altitudeFactName, QJsonValue::Double, true }, + { _jsonAltitudeRelativeKey, QJsonValue::Bool, false }, + { _layersFactName, QJsonValue::Double, true }, + { _jsonCameraCalcKey, QJsonValue::Object, true }, }; - if (!JsonHelper::validateKeys(v2Object, mainKeyInfoList, errorString)) { + if (!JsonHelper::validateKeys(complexObject, keyInfoList, errorString)) { return false; } - QString itemType = v2Object[VisualMissionItem::jsonTypeKey].toString(); - QString complexType = v2Object[ComplexMissionItem::jsonComplexItemTypeKey].toString(); + _structurePolygon.clear(); + + QString itemType = complexObject[VisualMissionItem::jsonTypeKey].toString(); + QString complexType = complexObject[ComplexMissionItem::jsonComplexItemTypeKey].toString(); if (itemType != VisualMissionItem::jsonTypeComplexItemValue || complexType != jsonComplexItemTypeValue) { errorString = tr("%1 does not support loading this complex mission item type: %2:%3").arg(qgcApp()->applicationName()).arg(itemType).arg(complexType); return false; } - _ignoreRecalc = true; - - _structurePolygon.clear(); - - setSequenceNumber(sequenceNumber); - - _manualGridFact.setRawValue (v2Object[_jsonManualGridKey].toBool(true)); - _fixedValueIsAltitudeFact.setRawValue (v2Object[_jsonFixedValueIsAltitudeKey].toBool(true)); - _gridAltitudeRelativeFact.setRawValue (v2Object[_jsonGridAltitudeRelativeKey].toBool(true)); - _hoverAndCaptureFact.setRawValue (v2Object[_jsonHoverAndCaptureKey].toBool(false)); - - _refly90Degrees = v2Object[_jsonRefly90DegreesKey].toBool(false); - - QList gridKeyInfoList = { - { _jsonGridAltitudeKey, QJsonValue::Double, true }, - { _jsonGridAltitudeRelativeKey, QJsonValue::Bool, true }, - { _jsonGridAngleKey, QJsonValue::Double, true }, - { _jsonGridSpacingKey, QJsonValue::Double, true }, - { _jsonGridEntryLocationKey, QJsonValue::Double, false }, - { _jsonTurnaroundDistKey, QJsonValue::Double, true }, - }; - QJsonObject gridObject = v2Object[_jsonGridObjectKey].toObject(); - if (!JsonHelper::validateKeys(gridObject, gridKeyInfoList, errorString)) { + int version = complexObject[JsonHelper::jsonVersionKey].toInt(); + if (version != 1) { + errorString = tr("Version %1 not supported").arg(version); return false; } - _gridAltitudeFact.setRawValue (gridObject[_jsonGridAltitudeKey].toDouble()); - _gridAngleFact.setRawValue (gridObject[_jsonGridAngleKey].toDouble()); - _gridSpacingFact.setRawValue (gridObject[_jsonGridSpacingKey].toDouble()); - _turnaroundDistFact.setRawValue (gridObject[_jsonTurnaroundDistKey].toDouble()); - _cameraTriggerDistanceFact.setRawValue (v2Object[_jsonCameraTriggerDistanceKey].toDouble()); - if (gridObject.contains(_jsonGridEntryLocationKey)) { - _gridEntryLocationFact.setRawValue(gridObject[_jsonGridEntryLocationKey].toDouble()); - } else { - _gridEntryLocationFact.setRawValue(_gridEntryLocationFact.rawDefaultValue()); - } - - if (!_manualGridFact.rawValue().toBool()) { - if (!v2Object.contains(_jsonCameraObjectKey)) { - errorString = tr("%1 but %2 object is missing").arg("manualGrid = false").arg("camera"); - return false; - } - QJsonObject cameraObject = v2Object[_jsonCameraObjectKey].toObject(); - - // Older code had typo on "imageSideOverlap" incorrectly being "imageSizeOverlap" - QString incorrectImageSideOverlap = "imageSizeOverlap"; - if (cameraObject.contains(incorrectImageSideOverlap)) { - cameraObject[_jsonSideOverlapKey] = cameraObject[incorrectImageSideOverlap]; - cameraObject.remove(incorrectImageSideOverlap); - } + setSequenceNumber(sequenceNumber); - QList cameraKeyInfoList = { - { _jsonGroundResolutionKey, QJsonValue::Double, true }, - { _jsonFrontalOverlapKey, QJsonValue::Double, true }, - { _jsonSideOverlapKey, QJsonValue::Double, true }, - { _jsonCameraSensorWidthKey, QJsonValue::Double, true }, - { _jsonCameraSensorHeightKey, QJsonValue::Double, true }, - { _jsonCameraResolutionWidthKey, QJsonValue::Double, true }, - { _jsonCameraResolutionHeightKey, QJsonValue::Double, true }, - { _jsonCameraFocalLengthKey, QJsonValue::Double, true }, - { _jsonCameraNameKey, QJsonValue::String, true }, - { _jsonCameraOrientationLandscapeKey, QJsonValue::Bool, true }, - { _jsonCameraMinTriggerIntervalKey, QJsonValue::Double, false }, - }; - if (!JsonHelper::validateKeys(cameraObject, cameraKeyInfoList, errorString)) { - return false; - } + _altitudeFact.setRawValue (complexObject[_altitudeFactName].toDouble()); + _layersFact.setRawValue (complexObject[_layersFactName].toDouble()); + _altitudeRelative = complexObject[_jsonAltitudeRelativeKey].toBool(true); - _cameraFact.setRawValue(cameraObject[_jsonCameraNameKey].toString()); - _cameraOrientationLandscapeFact.setRawValue(cameraObject[_jsonCameraOrientationLandscapeKey].toBool(true)); - - _groundResolutionFact.setRawValue (cameraObject[_jsonGroundResolutionKey].toDouble()); - _frontalOverlapFact.setRawValue (cameraObject[_jsonFrontalOverlapKey].toInt()); - _sideOverlapFact.setRawValue (cameraObject[_jsonSideOverlapKey].toInt()); - _cameraSensorWidthFact.setRawValue (cameraObject[_jsonCameraSensorWidthKey].toDouble()); - _cameraSensorHeightFact.setRawValue (cameraObject[_jsonCameraSensorHeightKey].toDouble()); - _cameraResolutionWidthFact.setRawValue (cameraObject[_jsonCameraResolutionWidthKey].toDouble()); - _cameraResolutionHeightFact.setRawValue (cameraObject[_jsonCameraResolutionHeightKey].toDouble()); - _cameraFocalLengthFact.setRawValue (cameraObject[_jsonCameraFocalLengthKey].toDouble()); - _cameraMinTriggerInterval = cameraObject[_jsonCameraMinTriggerIntervalKey].toDouble(0); + if (!_cameraCalc.load(complexObject[_jsonCameraCalcKey].toObject(), errorString)) { + return false; } - - // Polygon shape - /// Load a polygon from json - /// @param json Json object to load from - /// @param required true: no polygon in object will generate error - /// @param errorString Error string if return is false - /// @return true: success, false: failure (errorString set) - if (!_structurePolygon.loadFromJson(v2Object, true /* required */, errorString)) { + if (!_structurePolygon.loadFromJson(complexObject, true /* required */, errorString)) { _structurePolygon.clear(); return false; } - _ignoreRecalc = false; - _generateGrid(); - return true; -#else - Q_UNUSED(complexObject); - Q_UNUSED(sequenceNumber); - Q_UNUSED(errorString); - - return false; -#endif } void StructureScanComplexItem::_flightPathChanged(void) @@ -380,6 +246,7 @@ void StructureScanComplexItem::appendMissionItems(QList& items, QO items.append(item); for (int layer=0; layer<_layersFact.rawValue().toInt(); layer++) { + bool addTriggerStart = true; double layerAltitude = baseAltitude + (layer * _cameraCalc.adjustedFootprintFrontal()->rawValue().toDouble()); for (int i=0; i<_flightPolygon.count(); i++) { @@ -399,6 +266,21 @@ void StructureScanComplexItem::appendMissionItems(QList& items, QO false, // isCurrentItem missionItemParent); items.append(item); + + if (addTriggerStart) { + addTriggerStart = false; + item = new MissionItem(seqNum++, + MAV_CMD_DO_SET_CAM_TRIGG_DIST, + MAV_FRAME_MISSION, + _cameraCalc.adjustedFootprintSide()->rawValue().toDouble(), // trigger distance + 0, // shutter integration (ignore) + 1, // trigger immediately when starting + 0, 0, 0, 0, // param 4-7 unused + true, // autoContinue + false, // isCurrentItem + missionItemParent); + items.append(item); + } } QGeoCoordinate vertexCoord = _flightPolygon.vertexCoordinate(0); @@ -417,6 +299,18 @@ void StructureScanComplexItem::appendMissionItems(QList& items, QO false, // isCurrentItem missionItemParent); items.append(item); + + item = new MissionItem(seqNum++, + MAV_CMD_DO_SET_CAM_TRIGG_DIST, + MAV_FRAME_MISSION, + 0, // stop triggering + 0, // shutter integration (ignore) + 0, // trigger immediately when starting + 0, 0, 0, 0, // param 4-7 unused + true, // autoContinue + false, // isCurrentItem + missionItemParent); + items.append(item); } } diff --git a/src/MissionManager/StructureScanComplexItem.h b/src/MissionManager/StructureScanComplexItem.h index 95bd06d6a..f06d5090c 100644 --- a/src/MissionManager/StructureScanComplexItem.h +++ b/src/MissionManager/StructureScanComplexItem.h @@ -129,6 +129,9 @@ private: static const char* _altitudeFactName; static const char* _layersFactName; + + static const char* _jsonCameraCalcKey; + static const char* _jsonAltitudeRelativeKey; }; #endif diff --git a/src/PlanView/StructureScanEditor.qml b/src/PlanView/StructureScanEditor.qml index e8f6a4c6f..6a27f88fb 100644 --- a/src/PlanView/StructureScanEditor.qml +++ b/src/PlanView/StructureScanEditor.qml @@ -60,7 +60,7 @@ Rectangle { QGCLabel { anchors.left: parent.left anchors.right: parent.right - text: qsTr("WARNING: WORK IN PROGRESS. DO NOT FLY. NO BUG REPORTS.") + text: qsTr("WORK IN PROGRESS. CAREFUL!") wrapMode: Text.WordWrap color: qgcPal.warningText } diff --git a/src/PlanView/StructureScanMapVisual.qml b/src/PlanView/StructureScanMapVisual.qml index 7d12f9135..0f691ea5f 100644 --- a/src/PlanView/StructureScanMapVisual.qml +++ b/src/PlanView/StructureScanMapVisual.qml @@ -91,7 +91,7 @@ Item { borderWidth: 1 borderColor: "black" interiorColor: "green" - interiorOpacity: 0.5 + interiorOpacity: 0.25 } QGCMapPolygonVisuals { -- 2.22.0