diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index fb874cc97562a83baca600012f0410d9854d4c48..80fa382b73a37229cfb6c8b93439af1e9549a003 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -220,7 +220,7 @@ src/WimaView/WimaMeasurementAreaMapVisual.qml src/WimaView/WimaCorridorMapVisual.qml src/WimaView/WimaMeasurementAreaEditor.qml - src/PlanView/CircularSurveyItemEditor.qml + src/PlanView/CircularSurveyItemEditor.qml src/WimaView/DragCoordinate.qml src/WimaView/CoordinateIndicatorDrag.qml src/WimaView/CoordinateIndicator.qml @@ -229,7 +229,7 @@ src/FlightMap/MapItems/WimaPlanMapItems.qml src/PlanView/WimaMissionItemMapVisual.qml src/FlightDisplay/FlightDisplayWimaMenu.qml - src/WimaView/CircularSurveyMapVisual.qml + src/WimaView/CircularSurveyMapVisual.qml src/Settings/APMMavlinkStreamRate.SettingsGroup.json diff --git a/src/MissionManager/TransectStyleComplexItem.cc b/src/MissionManager/TransectStyleComplexItem.cc index 36ec81206e68d04bcfb4ebc84da673ba1d717567..c09291a02b7e496e5b1b48a7004ec5ad937509a4 100644 --- a/src/MissionManager/TransectStyleComplexItem.cc +++ b/src/MissionManager/TransectStyleComplexItem.cc @@ -358,10 +358,10 @@ void TransectStyleComplexItem::_rebuildTransects(void) } //CALLGRIND_TOGGLE_COLLECT; - auto startTime = std::chrono::high_resolution_clock::now(); + //auto startTime = std::chrono::high_resolution_clock::now(); _rebuildTransectsPhase1(); - auto delta = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startTime).count(); - qWarning() << "TransectStyleComplexItem::_rebuildTransects(): time: " << delta << " us"; + //auto delta = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startTime).count(); + //qWarning() << "TransectStyleComplexItem::_rebuildTransects(): time: " << delta << " us"; //CALLGRIND_TOGGLE_COLLECT; if (_followTerrain) { diff --git a/src/PlanView/CircularSurveyItemEditor.qml b/src/PlanView/CircularSurveyItemEditor.qml index 347a348c4253410f89058eaba0e124bd00aff223..1ed15fdc4c44ae948afddc9a7366f57298529bf8 100644 --- a/src/PlanView/CircularSurveyItemEditor.qml +++ b/src/PlanView/CircularSurveyItemEditor.qml @@ -166,18 +166,35 @@ Rectangle { onClicked: missionItem.resetReference(); Layout.fillWidth: true } + } - /* - Temporarily removed due to bug https://github.com/mavlink/qgroundcontrol/issues/7005 - FactCheckBox { - text: qsTr("Split concave polygons") - fact: _splitConcave - visible: _splitConcave.visible - property Fact _splitConcave: missionItem.splitConcavePolygons - } - */ + SectionHeader { + id: miscellaneousHeader + text: qsTr("Miscellaneous") } + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + spacing: _margin + visible: miscellaneousHeader.checked + + GridLayout { + Layout.fillWidth: true + columnSpacing: _margin + rowSpacing: _margin + columns: 2 + + QGCLabel { text: qsTr("Max Waypoints") } + FactTextField { + fact: missionItem.maxWaypoints + Layout.fillWidth: true + } + } // GridLayout + } // ColumnLayout + + /* + // The following code causes seg. faults from time to time SectionHeader { id: terrainHeader text: qsTr("Terrain") @@ -222,7 +239,7 @@ Rectangle { Layout.fillWidth: true } } - } + }*/ /*SectionHeader { id: statsHeader diff --git a/src/Terrain/TerrainQuery.cc b/src/Terrain/TerrainQuery.cc index b2d1dada9cf3c539581f261fc570ba2d46e411f1..6b01d6ba959a50030f48ea60b3b4a8f28cca10d0 100644 --- a/src/Terrain/TerrainQuery.cc +++ b/src/Terrain/TerrainQuery.cc @@ -362,10 +362,13 @@ void TerrainTileManager::addCoordinateQuery(TerrainOfflineAirMapQuery* terrainQu void TerrainTileManager::addPathQuery(TerrainOfflineAirMapQuery* terrainQueryInterface, const QGeoCoordinate &startPoint, const QGeoCoordinate &endPoint) { // Convert to individual coordinate queries + //qDebug() << "TerrainTileManager::addPathQuery()" << startPoint; QList coordinates; double lat = startPoint.latitude(); double lon = startPoint.longitude(); double steps = ceil(endPoint.distanceTo(startPoint) / TerrainTile::terrainAltitudeSpacing); +// if (qFuzzyIsNull(steps)) +// return; double latDiff = endPoint.latitude() - lat; double lonDiff = endPoint.longitude() - lon; for (double i = 0.0; i <= steps; i = i + 1) { diff --git a/src/Wima/CircularSurvey.SettingsGroup.json b/src/Wima/CircularSurvey.SettingsGroup.json index 2c54c8954347bd3b05e733d4ccedbb0dba4e23dd..42ac9584313430a951fc5fefe4f1e80f7b646761 100644 --- a/src/Wima/CircularSurvey.SettingsGroup.json +++ b/src/Wima/CircularSurvey.SettingsGroup.json @@ -35,8 +35,15 @@ }, { "name": "Reverse", - "shortDescription": "Reverses the transect path", + "shortDescription": "Reverses the transect path.", "type": "bool", "defaultValue": 0 +}, +{ + "name": "MaxWaypoints", + "shortDescription": "The maximum number of waypoints the circular survey can containt. To many waypoints cause a performance hit.", + "type": "uint32", + "defaultValue": 2000, + "min": 1 } ] diff --git a/src/Wima/CircularSurveyComplexItem.cc b/src/Wima/CircularSurveyComplexItem.cc index 121a1061ee82ef274d7dc28bf65b9d157cf5c6a3..ca613e297db6224a830916be1aa06fa495f4436b 100644 --- a/src/Wima/CircularSurveyComplexItem.cc +++ b/src/Wima/CircularSurveyComplexItem.cc @@ -10,6 +10,7 @@ const char* CircularSurveyComplexItem::deltaAlphaName = "DeltaAlpha" const char* CircularSurveyComplexItem::transectMinLengthName = "TransectMinLength"; const char* CircularSurveyComplexItem::isSnakePathName = "IsSnakePath"; const char* CircularSurveyComplexItem::reverseName = "Reverse"; +const char* CircularSurveyComplexItem::maxWaypointsName = "MaxWaypoints"; const char* CircularSurveyComplexItem::jsonComplexItemTypeValue = "circularSurvey"; @@ -17,6 +18,7 @@ const char* CircularSurveyComplexItem::jsonDeltaRKey = "deltaR" const char* CircularSurveyComplexItem::jsonDeltaAlphaKey = "deltaAlpha"; const char* CircularSurveyComplexItem::jsonTransectMinLengthKey = "transectMinLength"; const char* CircularSurveyComplexItem::jsonIsSnakePathKey = "isSnakePath"; +const char* CircularSurveyComplexItem::jsonReverseKey = "reverse"; const char* CircularSurveyComplexItem::jsonReferencePointLatKey = "referencePointLat"; const char* CircularSurveyComplexItem::jsonReferencePointLongKey = "referencePointLong"; const char* CircularSurveyComplexItem::jsonReferencePointAltKey = "referencePointAlt"; @@ -30,6 +32,7 @@ CircularSurveyComplexItem::CircularSurveyComplexItem(Vehicle *vehicle, bool flyV , _transectMinLength (settingsGroup, _metaDataMap[transectMinLengthName]) , _isSnakePath (settingsGroup, _metaDataMap[isSnakePathName]) , _reverse (settingsGroup, _metaDataMap[reverseName]) + , _maxWaypoints (settingsGroup, _metaDataMap[maxWaypointsName]) , _isInitialized (false) , _reverseOnly (false) , _referencePointBeingChanged (false) @@ -41,6 +44,7 @@ CircularSurveyComplexItem::CircularSurveyComplexItem(Vehicle *vehicle, bool flyV connect(&_deltaAlpha, &Fact::valueChanged, this, &CircularSurveyComplexItem::_rebuildTransects); connect(&_transectMinLength, &Fact::valueChanged, this, &CircularSurveyComplexItem::_rebuildTransects); connect(&_isSnakePath, &Fact::valueChanged, this, &CircularSurveyComplexItem::_rebuildTransects); + connect(&_maxWaypoints, &Fact::valueChanged, this, &CircularSurveyComplexItem::_rebuildTransects); connect(&_reverse, &Fact::valueChanged, this, &CircularSurveyComplexItem::_reverseTransects); connect(this, &CircularSurveyComplexItem::refPointChanged, this, &CircularSurveyComplexItem::_rebuildTransects); //connect(&_cameraCalc.distanceToSurface(), &Fact::rawValueChanged, this->) @@ -123,6 +127,7 @@ bool CircularSurveyComplexItem::load(const QJsonObject &complexObject, int seque { jsonDeltaAlphaKey, QJsonValue::Double, true }, { jsonTransectMinLengthKey, QJsonValue::Double, true }, { jsonIsSnakePathKey, QJsonValue::Bool, true }, + { jsonReverseKey, QJsonValue::Bool, true }, { jsonReferencePointLatKey, QJsonValue::Double, true }, { jsonReferencePointLongKey, QJsonValue::Double, true }, { jsonReferencePointAltKey, QJsonValue::Double, true }, @@ -160,6 +165,7 @@ bool CircularSurveyComplexItem::load(const QJsonObject &complexObject, int seque _referencePoint.setLatitude (complexObject[jsonReferencePointLatKey].toDouble()); _referencePoint.setAltitude (complexObject[jsonReferencePointAltKey].toDouble()); _isSnakePath.setRawValue (complexObject[jsonIsSnakePathKey].toBool()); + _reverse.setRawValue (complexObject[jsonReverseKey].toBool()); setIsInitialized(true); _ignoreRecalc = false; @@ -187,6 +193,7 @@ void CircularSurveyComplexItem::save(QJsonArray &planItems) saveObject[jsonDeltaAlphaKey] = _deltaAlpha.rawValue().toDouble(); saveObject[jsonTransectMinLengthKey] = _transectMinLength.rawValue().toDouble(); saveObject[jsonIsSnakePathKey] = _isSnakePath.rawValue().toBool(); + saveObject[jsonReverseKey] = _reverse.rawValue().toBool(); saveObject[jsonReferencePointLongKey] = _referencePoint.longitude(); saveObject[jsonReferencePointLatKey] = _referencePoint.latitude(); saveObject[jsonReferencePointAltKey] = _referencePoint.altitude(); @@ -372,6 +379,7 @@ void CircularSurveyComplexItem::_rebuildTransectsPhase1() return; _updateCounter++; + unsigned int waypointCounter = 0; // If the transects are getting rebuilt then any previously loaded mission items are now invalid if (_loadedMissionItemsParent) { @@ -389,21 +397,23 @@ void CircularSurveyComplexItem::_rebuildTransectsPhase1() // reverse transects and return if (_reverseOnly) { - QList> transectsReverse; + _reverseOnly = false; - for (auto list : _transects) { - QList listReverse; - for (auto coordinate : list) - listReverse.prepend(coordinate); + if (_transects.size() > 1) { + QList> transectsReverse; + transectsReverse.reserve(_transects.size()); - transectsReverse.prepend(listReverse); - } + for (auto list : _transects) { + QList listReverse; + for (auto coordinate : list) + listReverse.prepend(coordinate); - _transects.clear(); - _transects.append(transectsReverse); + transectsReverse.prepend(listReverse); + } + _transects = transectsReverse; - _reverseOnly = false; - return; + return; + } } _transects.clear(); @@ -437,6 +447,7 @@ void CircularSurveyComplexItem::_rebuildTransectsPhase1() double lmin = _transectMinLength.rawValue().toDouble(); double r_min = dr; // meter double r_max = (*std::max_element(distances.begin(), distances.end())); // meter + unsigned int maxWaypoints = _maxWaypoints.rawValue().toUInt(); QPointF origin(0, 0); IntersectType type; @@ -546,14 +557,21 @@ void CircularSurveyComplexItem::_rebuildTransectsPhase1() QVector sectorPath = circle.approximateSektor(numNodes, alpha1, alpha2); // use shortestPath() here if necessary, could be a problem if dr >> - if (sectorPath.size() > 0) + if (sectorPath.size() > 0) { + waypointCounter += uint(sectorPath.size()); + if (waypointCounter > maxWaypoints ) + return; transectPath.append(sectorPath); + } } } else if (originInside) { // circle fully inside polygon int numNodes = int(ceil(2*M_PI/dalpha)) + 1; QVector sectorPath = circle.approximateSektor(numNodes, 0, 2*M_PI); // use shortestPath() here if necessary, could be a problem if dr >> + waypointCounter += uint(sectorPath.size()); + if (waypointCounter > maxWaypoints ) + return; transectPath.append(sectorPath); } r += dr; @@ -613,6 +631,9 @@ void CircularSurveyComplexItem::_rebuildTransectsPhase1() optiPath.append(currentSection); // append last section + if (optiPath.size() > _maxWaypoints.rawValue().toInt()) + return; + // convert to CoordInfo_t if (_reverse.rawValue().toBool()) @@ -669,6 +690,11 @@ Fact *CircularSurveyComplexItem::reverse() return &_reverse; } +Fact *CircularSurveyComplexItem::maxWaypoints() +{ + return &_maxWaypoints; +} + diff --git a/src/Wima/CircularSurveyComplexItem.h b/src/Wima/CircularSurveyComplexItem.h index f9be3a8b51804b23e280cd3ea38e96ffb609fc3b..e6cf37f34d82316bcbca77db45ebf571b40581ab 100644 --- a/src/Wima/CircularSurveyComplexItem.h +++ b/src/Wima/CircularSurveyComplexItem.h @@ -24,6 +24,7 @@ public: Q_PROPERTY(Fact* transectMinLength READ transectMinLength CONSTANT) Q_PROPERTY(Fact* isSnakePath READ isSnakePath CONSTANT) Q_PROPERTY(Fact* reverse READ reverse CONSTANT) + Q_PROPERTY(Fact* maxWaypoints READ maxWaypoints CONSTANT) Q_PROPERTY(bool isInitialized READ isInitialized WRITE setIsInitialized NOTIFY isInitializedChanged) Q_INVOKABLE void resetReference(void); @@ -41,6 +42,7 @@ public: Fact *transectMinLength(); Fact *isSnakePath(); Fact *reverse(); + Fact *maxWaypoints(); // Is true if survey was automatically generated, prevents initialisation from gui. bool isInitialized(); bool referencePointBeingChanged(); // returns true if the referencepoint is being changed (dragged by user) @@ -69,12 +71,14 @@ public: static const char* transectMinLengthName; static const char* isSnakePathName; static const char* reverseName; + static const char* maxWaypointsName; static const char* jsonComplexItemTypeValue; static const char* jsonDeltaRKey; static const char* jsonDeltaAlphaKey; - static const char* jsonTransectMinLengthKey; + static const char* jsonTransectMinLengthKey; static const char* jsonIsSnakePathKey; + static const char* jsonReverseKey; static const char* jsonReferencePointLongKey; static const char* jsonReferencePointLatKey; static const char* jsonReferencePointAltKey; @@ -108,6 +112,7 @@ private: SettingsFact _transectMinLength; // minimal transect lenght, transects are rejected if they are shorter than this value SettingsFact _isSnakePath; // bool value, determining if transects are connected in a snake like or zig zag like manner SettingsFact _reverse; // reverses the _transects path + SettingsFact _maxWaypoints; // the maximum number of waypoints _transects (TransectStyleComplexItem) can contain (to avoid performance hits) QTimer _updateTimer;