diff --git a/src/MissionManager/StructureScan.SettingsGroup.json b/src/MissionManager/StructureScan.SettingsGroup.json index ac79f33887cf79cc1673019757be80449c2ba943..ccfdf63c7d34d17cf815a97321affae40d246962 100644 --- a/src/MissionManager/StructureScan.SettingsGroup.json +++ b/src/MissionManager/StructureScan.SettingsGroup.json @@ -32,5 +32,11 @@ "units": "m", "min": 1, "defaultValue": 100 +}, +{ + "name": "StartFromTop", + "shortDescription": "Start scan from top of structure.", + "type": "bool", + "defaultValue": true } ] diff --git a/src/MissionManager/StructureScanComplexItem.cc b/src/MissionManager/StructureScanComplexItem.cc index ce37b8cb01fe199f24bf7de0e1ee27ea78773ef8..629842eef6e3f003d8702f1a90a16b552092c123 100644 --- a/src/MissionManager/StructureScanComplexItem.cc +++ b/src/MissionManager/StructureScanComplexItem.cc @@ -26,6 +26,7 @@ const char* StructureScanComplexItem::altitudeName = "Altitude"; const char* StructureScanComplexItem::structureHeightName = "StructureHeight"; const char* StructureScanComplexItem::layersName = "Layers"; const char* StructureScanComplexItem::gimbalPitchName = "GimbalPitch"; +const char* StructureScanComplexItem::startFromTopName = "StartFromTop"; const char* StructureScanComplexItem::jsonComplexItemTypeValue = "StructureScan"; const char* StructureScanComplexItem::_jsonCameraCalcKey = "CameraCalc"; @@ -46,6 +47,7 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, bool flyVie , _structureHeightFact (settingsGroup, _metaDataMap[structureHeightName]) , _layersFact (settingsGroup, _metaDataMap[layersName]) , _gimbalPitchFact (settingsGroup, _metaDataMap[gimbalPitchName]) + , _startFromTopFact (settingsGroup, _metaDataMap[startFromTopName]) { _editorQml = "qrc:/qml/StructureScanEditor.qml"; @@ -54,6 +56,7 @@ StructureScanComplexItem::StructureScanComplexItem(Vehicle* vehicle, bool flyVie connect(&_altitudeFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty); connect(&_layersFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty); connect(&_gimbalPitchFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty); + connect(&_startFromTopFact, &Fact::valueChanged, this, &StructureScanComplexItem::_setDirty); connect(&_layersFact, &Fact::valueChanged, this, &StructureScanComplexItem::_recalcLayerInfo); connect(&_structureHeightFact, &Fact::valueChanged, this, &StructureScanComplexItem::_recalcLayerInfo); @@ -156,6 +159,7 @@ void StructureScanComplexItem::save(QJsonArray& missionItems) saveObject[_jsonAltitudeRelativeKey] = _altitudeRelative; saveObject[layersName] = _layersFact.rawValue().toDouble(); saveObject[gimbalPitchName] = _gimbalPitchFact.rawValue().toDouble(); + saveObject[startFromTopName] = _startFromTopFact.rawValue().toBool(); QJsonObject cameraCalcObject; _cameraCalc.save(cameraCalcObject); @@ -187,6 +191,7 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen { _jsonAltitudeRelativeKey, QJsonValue::Bool, true }, { layersName, QJsonValue::Double, true }, { gimbalPitchName, QJsonValue::Double, false }, // This value was added after initial implementation so may be missing from older files + { startFromTopName, QJsonValue::Bool, false }, // This value was added after initial implementation so may be missing from older files { _jsonCameraCalcKey, QJsonValue::Object, true }, }; if (!JsonHelper::validateKeys(complexObject, keyInfoList, errorString)) { @@ -218,6 +223,7 @@ bool StructureScanComplexItem::load(const QJsonObject& complexObject, int sequen _altitudeFact.setRawValue (complexObject[altitudeName].toDouble()); _layersFact.setRawValue (complexObject[layersName].toDouble()); _structureHeightFact.setRawValue(complexObject[structureHeightName].toDouble()); + _startFromTopFact.setRawValue (complexObject[startFromTopName].toBool(false)); // Set the false if doesn't exist, which matches previous functionality prior to setting _altitudeRelative = complexObject[_jsonAltitudeRelativeKey].toBool(true); @@ -289,8 +295,9 @@ bool StructureScanComplexItem::specifiesCoordinate(void) const void StructureScanComplexItem::appendMissionItems(QList& items, QObject* missionItemParent) { - int seqNum = _sequenceNumber; - double baseAltitude = _altitudeFact.rawValue().toDouble(); + int seqNum = _sequenceNumber; + bool startFromTop = _startFromTopFact.rawValue().toBool(); + double startAltitude = _altitudeFact.rawValue().toDouble() + (startFromTop ? _structureHeightFact.rawValue().toDouble() : 0); MissionItem* item = new MissionItem(seqNum++, MAV_CMD_DO_SET_ROI_WPNEXT_OFFSET, @@ -305,10 +312,15 @@ void StructureScanComplexItem::appendMissionItems(QList& items, QO items.append(item); for (int layer=0; layer<_layersFact.rawValue().toInt(); layer++) { - bool addTriggerStart = true; - // baseAltitude is the bottom of the first layer. Hence we need to move up half the distance of the camera footprint to center the camera - // within the layer. - double layerAltitude = baseAltitude + (_cameraCalc.adjustedFootprintFrontal()->rawValue().toDouble() / 2.0) + (layer * _cameraCalc.adjustedFootprintFrontal()->rawValue().toDouble()); + bool addTriggerStart = true; + double layerIncrement = (_cameraCalc.adjustedFootprintFrontal()->rawValue().toDouble() / 2.0) + (layer * _cameraCalc.adjustedFootprintFrontal()->rawValue().toDouble()); + double layerAltitude; + + if (startFromTop) { + layerAltitude = startAltitude - layerIncrement; + } else { + layerAltitude = startAltitude + layerIncrement; + } for (int i=0; i<_flightPolygon.count(); i++) { QGeoCoordinate vertexCoord = _flightPolygon.vertexCoordinate(i); diff --git a/src/MissionManager/StructureScanComplexItem.h b/src/MissionManager/StructureScanComplexItem.h index 9b8b09d4c0f88611acee601fa6bb96b9839eee8b..810a6dae02720616e634b1d92f36becce08b35ac 100644 --- a/src/MissionManager/StructureScanComplexItem.h +++ b/src/MissionManager/StructureScanComplexItem.h @@ -35,6 +35,7 @@ public: Q_PROPERTY(Fact* structureHeight READ structureHeight CONSTANT) Q_PROPERTY(Fact* layers READ layers CONSTANT) Q_PROPERTY(Fact* gimbalPitch READ gimbalPitch CONSTANT) + Q_PROPERTY(Fact* startFromTop READ startFromTop CONSTANT) Q_PROPERTY(bool altitudeRelative READ altitudeRelative WRITE setAltitudeRelative NOTIFY altitudeRelativeChanged) Q_PROPERTY(int cameraShots READ cameraShots NOTIFY cameraShotsChanged) Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged) @@ -46,6 +47,7 @@ public: Fact* structureHeight (void) { return &_structureHeightFact; } Fact* layers (void) { return &_layersFact; } Fact* gimbalPitch (void) { return &_gimbalPitchFact; } + Fact* startFromTop (void) { return &_startFromTopFact; } bool altitudeRelative (void) const { return _altitudeRelative; } int cameraShots (void) const; @@ -102,6 +104,7 @@ public: static const char* structureHeightName; static const char* layersName; static const char* gimbalPitchName; + static const char* startFromTopName; signals: void cameraShotsChanged (int cameraShots); @@ -147,6 +150,7 @@ private: SettingsFact _structureHeightFact; SettingsFact _layersFact; SettingsFact _gimbalPitchFact; + SettingsFact _startFromTopFact; static const char* _jsonCameraCalcKey; static const char* _jsonAltitudeRelativeKey; diff --git a/src/PlanView/StructureScanEditor.qml b/src/PlanView/StructureScanEditor.qml index 355ce0889e4c0094dd7fa63a782ac77fd4e1f78b..827a6a5dfff0c69d6b5689a64a6c8fe6054b10a2 100644 --- a/src/PlanView/StructureScanEditor.qml +++ b/src/PlanView/StructureScanEditor.qml @@ -100,6 +100,14 @@ Rectangle { rowSpacing: _margin columns: 2 + FactComboBox { + fact: missionItem.startFromTop + indexModel: true + model: [ qsTr("Start Scan From Bottom"), qsTr("Start Scan From Top") ] + Layout.columnSpan: 2 + Layout.fillWidth: true + } + QGCLabel { text: qsTr("Structure height") visible: !missionItem.cameraCalc.isManualCamera @@ -165,13 +173,19 @@ Rectangle { columnSpacing: ScreenTools.defaultFontPixelWidth visible: statsHeader.checked + QGCLabel { text: qsTr("Layers") } + QGCLabel { text: missionItem.layers.valueString } + + QGCLabel { text: qsTr("Layer height") } + QGCLabel { text: missionItem.cameraCalc.adjustedFootprintFrontal.valueString + " " + QGroundControl.appSettingsDistanceUnitsString } + QGCLabel { text: qsTr("Photo count") } QGCLabel { text: missionItem.cameraShots } QGCLabel { text: qsTr("Photo interval") } QGCLabel { text: missionItem.timeBetweenShots.toFixed(1) + " " + qsTr("secs") } - QGCLabel { text: qsTr("Trigger Distance") } + QGCLabel { text: qsTr("Trigger distance") } QGCLabel { text: missionItem.cameraCalc.adjustedFootprintSide.valueString + " " + QGroundControl.appSettingsDistanceUnitsString } } } // Column