Commit 855da00e authored by DonLakeFlyer's avatar DonLakeFlyer

Major work on GeoFence, clear mission on flight end

parent a25626fd
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
<file alias="FlightDisplayViewUVC.qml">src/FlightDisplay/FlightDisplayViewUVC.qml</file> <file alias="FlightDisplayViewUVC.qml">src/FlightDisplay/FlightDisplayViewUVC.qml</file>
<file alias="FlightModesComponentSummary.qml">src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml</file> <file alias="FlightModesComponentSummary.qml">src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml</file>
<file alias="GeneralSettings.qml">src/ui/preferences/GeneralSettings.qml</file> <file alias="GeneralSettings.qml">src/ui/preferences/GeneralSettings.qml</file>
<file alias="GeoFenceEditor.qml">src/MissionEditor/GeoFenceEditor.qml</file>
<file alias="GeoTagPage.qml">src/AnalyzeView/GeoTagPage.qml</file> <file alias="GeoTagPage.qml">src/AnalyzeView/GeoTagPage.qml</file>
<file alias="JoystickConfig.qml">src/VehicleSetup/JoystickConfig.qml</file> <file alias="JoystickConfig.qml">src/VehicleSetup/JoystickConfig.qml</file>
<file alias="LinkSettings.qml">src/ui/preferences/LinkSettings.qml</file> <file alias="LinkSettings.qml">src/ui/preferences/LinkSettings.qml</file>
...@@ -57,6 +56,8 @@ ...@@ -57,6 +56,8 @@
<file alias="QGroundControl/Controls/FlightModeDropdown.qml">src/QmlControls/FlightModeDropdown.qml</file> <file alias="QGroundControl/Controls/FlightModeDropdown.qml">src/QmlControls/FlightModeDropdown.qml</file>
<file alias="QGroundControl/Controls/FlightModeMenu.qml">src/QmlControls/FlightModeMenu.qml</file> <file alias="QGroundControl/Controls/FlightModeMenu.qml">src/QmlControls/FlightModeMenu.qml</file>
<file alias="QGroundControl/Controls/FWLandingPatternMapVisual.qml">src/MissionEditor/FWLandingPatternMapVisual.qml</file> <file alias="QGroundControl/Controls/FWLandingPatternMapVisual.qml">src/MissionEditor/FWLandingPatternMapVisual.qml</file>
<file alias="QGroundControl/Controls/GeoFenceEditor.qml">src/MissionEditor/GeoFenceEditor.qml</file>
<file alias="QGroundControl/Controls/GeoFenceMapVisuals.qml">src/MissionEditor/GeoFenceMapVisuals.qml</file>
<file alias="QGroundControl/Controls/GuidedBar.qml">src/QmlControls/GuidedBar.qml</file> <file alias="QGroundControl/Controls/GuidedBar.qml">src/QmlControls/GuidedBar.qml</file>
<file alias="QGroundControl/Controls/IndicatorButton.qml">src/QmlControls/IndicatorButton.qml</file> <file alias="QGroundControl/Controls/IndicatorButton.qml">src/QmlControls/IndicatorButton.qml</file>
<file alias="QGroundControl/Controls/JoystickThumbPad.qml">src/QmlControls/JoystickThumbPad.qml</file> <file alias="QGroundControl/Controls/JoystickThumbPad.qml">src/QmlControls/JoystickThumbPad.qml</file>
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "MAVLinkProtocol.h" #include "MAVLinkProtocol.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "ParameterManager.h" #include "ParameterManager.h"
#include "QmlObjectListModel.h"
#include "QGCQGeoCoordinate.h"
const char* APMGeoFenceManager::_fenceTotalParam = "FENCE_TOTAL"; const char* APMGeoFenceManager::_fenceTotalParam = "FENCE_TOTAL";
const char* APMGeoFenceManager::_fenceActionParam = "FENCE_ACTION"; const char* APMGeoFenceManager::_fenceActionParam = "FENCE_ACTION";
...@@ -44,7 +46,7 @@ APMGeoFenceManager::~APMGeoFenceManager() ...@@ -44,7 +46,7 @@ APMGeoFenceManager::~APMGeoFenceManager()
} }
void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon) void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, QmlObjectListModel& polygon)
{ {
if (_vehicle->isOfflineEditingVehicle()) { if (_vehicle->isOfflineEditingVehicle()) {
return; return;
...@@ -61,21 +63,20 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const ...@@ -61,21 +63,20 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const
// Validate // Validate
int validatedPolygonCount = 0; int validatedPolygonCount = 0;
if (polygonEnabled()) { if (polygon.count() >= 3) {
if (polygon.count() >= 3) { validatedPolygonCount = polygon.count();
validatedPolygonCount = polygon.count(); }
} if (polygon.count() > std::numeric_limits<uint8_t>::max()) {
if (polygon.count() > std::numeric_limits<uint8_t>::max()) { _sendError(TooManyPoints, QStringLiteral("Geo-Fence polygon has too many points: %1.").arg(_polygon.count()));
_sendError(TooManyPoints, QStringLiteral("Geo-Fence polygon has too many points: %1.").arg(_polygon.count())); validatedPolygonCount = 0;
validatedPolygonCount = 0;
}
} }
_breachReturnPoint = breachReturn; _breachReturnPoint = breachReturn;
_polygon.clear();
if (validatedPolygonCount) { if (validatedPolygonCount) {
_polygon = polygon; for (int i=0; i<polygon.count(); i++) {
} else { _polygon.append(polygon.value<QGCQGeoCoordinate*>(i)->coordinate());
_polygon.clear(); }
} }
// Total point count, +1 polygon close in last index, +1 for breach in index 0 // Total point count, +1 polygon close in last index, +1 for breach in index 0
...@@ -306,7 +307,7 @@ void APMGeoFenceManager::_parametersReady(void) ...@@ -306,7 +307,7 @@ void APMGeoFenceManager::_parametersReady(void)
float APMGeoFenceManager::circleRadius(void) const float APMGeoFenceManager::circleRadius(void) const
{ {
if (_circleEnabled) { if (_circleRadiusFact) {
return _circleRadiusFact->rawValue().toFloat(); return _circleRadiusFact->rawValue().toFloat();
} else { } else {
return 0.0; return 0.0;
...@@ -328,3 +329,10 @@ QString APMGeoFenceManager::editorQml(void) const ...@@ -328,3 +329,10 @@ QString APMGeoFenceManager::editorQml(void) const
return QStringLiteral("qrc:/FirmwarePlugin/NoGeoFenceEditor.qml"); return QStringLiteral("qrc:/FirmwarePlugin/NoGeoFenceEditor.qml");
} }
} }
void APMGeoFenceManager::removeAll(void)
{
QmlObjectListModel emptyPolygon;
sendToVehicle(_breachReturnPoint, emptyPolygon);
}
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include "QGCMAVLink.h" #include "QGCMAVLink.h"
#include "FactSystem.h" #include "FactSystem.h"
class QmlObjectListModel;
class APMGeoFenceManager : public GeoFenceManager class APMGeoFenceManager : public GeoFenceManager
{ {
Q_OBJECT Q_OBJECT
...@@ -25,7 +27,7 @@ public: ...@@ -25,7 +27,7 @@ public:
// Overrides from GeoFenceManager // Overrides from GeoFenceManager
bool inProgress (void) const final; bool inProgress (void) const final;
void loadFromVehicle (void) final; void loadFromVehicle (void) final;
void sendToVehicle (const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon) final; void sendToVehicle (const QGeoCoordinate& breachReturn, QmlObjectListModel& polygon) final;
bool circleEnabled (void) const final { return _circleEnabled; } bool circleEnabled (void) const final { return _circleEnabled; }
bool polygonEnabled (void) const final { return _polygonEnabled; } bool polygonEnabled (void) const final { return _polygonEnabled; }
bool breachReturnEnabled (void) const final { return _breachReturnEnabled; } bool breachReturnEnabled (void) const final { return _breachReturnEnabled; }
...@@ -33,6 +35,7 @@ public: ...@@ -33,6 +35,7 @@ public:
QVariantList params (void) const final { return _params; } QVariantList params (void) const final { return _params; }
QStringList paramLabels (void) const final { return _paramLabels; } QStringList paramLabels (void) const final { return _paramLabels; }
QString editorQml (void) const final; QString editorQml (void) const final;
void removeAll (void) final;
private slots: private slots:
void _mavlinkMessageReceived(const mavlink_message_t& message); void _mavlinkMessageReceived(const mavlink_message_t& message);
......
...@@ -149,3 +149,10 @@ bool APMRallyPointManager::rallyPointsSupported(void) const ...@@ -149,3 +149,10 @@ bool APMRallyPointManager::rallyPointsSupported(void) const
{ {
return _vehicle->parameterManager()->parameterExists(_vehicle->defaultComponentId(), _rallyTotalParam); return _vehicle->parameterManager()->parameterExists(_vehicle->defaultComponentId(), _rallyTotalParam);
} }
void APMRallyPointManager::removeAll(void)
{
QList<QGeoCoordinate> noRallyPoints;
sendToVehicle(noRallyPoints);
}
...@@ -27,6 +27,8 @@ public: ...@@ -27,6 +27,8 @@ public:
void sendToVehicle (const QList<QGeoCoordinate>& rgPoints) final; void sendToVehicle (const QList<QGeoCoordinate>& rgPoints) final;
bool rallyPointsSupported (void) const final; bool rallyPointsSupported (void) const final;
void removeAll (void);
QString editorQml(void) const final { return QStringLiteral("qrc:/FirmwarePlugin/APM/APMRallyPointEditor.qml"); } QString editorQml(void) const final { return QStringLiteral("qrc:/FirmwarePlugin/APM/APMRallyPointEditor.qml"); }
private slots: private slots:
......
...@@ -24,7 +24,6 @@ Column { ...@@ -24,7 +24,6 @@ Column {
anchors.right: parent.right anchors.right: parent.right
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: qsTr("Click in map to set breach return point.") text: qsTr("Click in map to set breach return point.")
visible: geoFenceController.breachReturnSupported
} }
QGCLabel { text: qsTr("Fence Settings:") } QGCLabel { text: qsTr("Fence Settings:") }
...@@ -73,14 +72,15 @@ Column { ...@@ -73,14 +72,15 @@ Column {
} }
} }
QGCMapPolygonControls { QGCButton {
anchors.left: parent.left text: qsTr("Add fence")
anchors.right: parent.right visible: geoFenceController.mapPolygon.count < 3
flightMap: editorMap onClicked: geoFenceController.addFence()
polygon: geoFenceController.polygon }
sectionLabel: qsTr("Fence Polygon:")
visible: geoFenceController.polygonSupported
onPolygonEditCompleted: geoFenceController.validateBreachReturn() QGCButton {
text: qsTr("Remove fence")
visible: geoFenceController.mapPolygon.count >= 3
onClicked: geoFenceController.removeFence()
} }
} }
...@@ -196,13 +196,15 @@ Column { ...@@ -196,13 +196,15 @@ Column {
FENCE_RET_RALLY - if set to 1 the aircraft will head to the nearest Rally Point rather than the fence return point when the fence is breached. Note that the loiter altitude of the Rally Point is used as the return altitude. FENCE_RET_RALLY - if set to 1 the aircraft will head to the nearest Rally Point rather than the fence return point when the fence is breached. Note that the loiter altitude of the Rally Point is used as the return altitude.
*/ */
QGCMapPolygonControls { QGCButton {
anchors.left: parent.left text: qsTr("Add fence")
anchors.right: parent.right visible: geoFenceController.mapPolygon.count < 3
flightMap: editorMap onClicked: geoFenceController.addFence()
polygon: geoFenceController.polygon }
sectionLabel: qsTr("Fence Polygon:")
onPolygonEditCompleted: geoFenceController.validateBreachReturn() QGCButton {
text: qsTr("Remove fence")
visible: geoFenceController.mapPolygon.count >= 3
onClicked: geoFenceController.removeFence()
} }
} }
...@@ -80,3 +80,7 @@ void PX4GeoFenceManager::_circleRadiusRawValueChanged(QVariant value) ...@@ -80,3 +80,7 @@ void PX4GeoFenceManager::_circleRadiusRawValueChanged(QVariant value)
emit circleRadiusChanged(value.toFloat()); emit circleRadiusChanged(value.toFloat());
} }
void PX4GeoFenceManager::removeAll(void)
{
// Only params so nothing to do
}
...@@ -28,6 +28,7 @@ public: ...@@ -28,6 +28,7 @@ public:
QVariantList params (void) const final { return _params; } QVariantList params (void) const final { return _params; }
QStringList paramLabels (void) const final { return _paramLabels; } QStringList paramLabels (void) const final { return _paramLabels; }
QString editorQml (void) const final { return QStringLiteral("qrc:/FirmwarePlugin/PX4/PX4GeoFenceEditor.qml"); } QString editorQml (void) const final { return QStringLiteral("qrc:/FirmwarePlugin/PX4/PX4GeoFenceEditor.qml"); }
void removeAll (void) final;
private slots: private slots:
void _circleRadiusRawValueChanged(QVariant value); void _circleRadiusRawValueChanged(QVariant value);
......
...@@ -148,6 +148,7 @@ QGCView { ...@@ -148,6 +148,7 @@ QGCView {
anchors.fill: parent anchors.fill: parent
flightWidgets: flightDisplayViewWidgets flightWidgets: flightDisplayViewWidgets
rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9 rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9
qgcView: root
} }
} }
......
...@@ -8,10 +8,11 @@ ...@@ -8,10 +8,11 @@
****************************************************************************/ ****************************************************************************/
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtLocation 5.3 import QtLocation 5.3
import QtPositioning 5.3 import QtPositioning 5.3
import QtQuick.Dialogs 1.2
import QGroundControl 1.0 import QGroundControl 1.0
import QGroundControl.FlightDisplay 1.0 import QGroundControl.FlightDisplay 1.0
...@@ -34,6 +35,7 @@ FlightMap { ...@@ -34,6 +35,7 @@ FlightMap {
property alias missionController: missionController property alias missionController: missionController
property var flightWidgets property var flightWidgets
property var rightPanelWidth property var rightPanelWidth
property var qgcView ///< QGCView control which contains this map
property bool _followVehicle: true property bool _followVehicle: true
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
...@@ -77,6 +79,49 @@ FlightMap { ...@@ -77,6 +79,49 @@ FlightMap {
Component.onCompleted: start(false /* editMode */) Component.onCompleted: start(false /* editMode */)
} }
// The following code is used to track vehicle states such that we prompt to remove mission from vehicle when mission completes
property bool vehicleArmed: _activeVehicle ? _activeVehicle.armed : false
property bool vehicleWasArmed: false
property bool vehicleInMissionFlightMode: _activeVehicle ? (_activeVehicle.flightMode === _activeVehicle.missionFlightMode) : false
property bool promptForMissionRemove: false
onVehicleArmedChanged: {
if (vehicleArmed) {
if (!promptForMissionRemove) {
promptForMissionRemove = vehicleInMissionFlightMode
vehicleWasArmed = true
}
} else {
if (promptForMissionRemove && (missionController.containsItems || geoFenceController.containsItems || rallyPointController.containsItems)) {
qgcView.showDialog(removeMissionDialogComponent, qsTr("Flight complete"), showDialogDefaultWidth, StandardButton.No | StandardButton.Yes)
}
promptForMissionRemove = false
}
}
onVehicleInMissionFlightModeChanged: {
if (!promptForMissionRemove && vehicleArmed) {
promptForMissionRemove = true
}
}
Component {
id: removeMissionDialogComponent
QGCViewMessage {
message: qsTr("Do you want to remove the mission from the vehicle?")
function accept() {
missionController.removeAllFromVehicle()
geoFenceController.removeAllFromVehicle()
rallyPointController.removeAllFromVehicle()
hideDialog()
}
}
}
ExclusiveGroup { ExclusiveGroup {
id: _mapTypeButtonsExclusiveGroup id: _mapTypeButtonsExclusiveGroup
} }
...@@ -224,32 +269,11 @@ FlightMap { ...@@ -224,32 +269,11 @@ FlightMap {
model: _mainIsMap ? missionController.waypointLines : 0 model: _mainIsMap ? missionController.waypointLines : 0
} }
// GeoFence polygon GeoFenceMapVisuals {
MapPolygon { map: flightMap
border.color: "#80FF0000" myGeoFenceController: geoFenceController
border.width: 3 interactive: false
path: geoFenceController.polygon.path homePosition: _activeVehicle && _activeVehicle.homePositionAvailable ? _activeVehicle.homePosition : undefined
visible: geoFenceController.polygonEnabled
}
// GeoFence circle
MapCircle {
border.color: "#80FF0000"
border.width: 3
center: missionController.plannedHomePosition
radius: geoFenceController.circleRadius
z: QGroundControl.zOrderMapItems
visible: geoFenceController.circleEnabled
}
// GeoFence breach return point
MapQuickItem {
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
coordinate: geoFenceController.breachReturnPoint
visible: geoFenceController.breachReturnEnabled
sourceItem: MissionItemIndexLabel { label: "F" }
z: QGroundControl.zOrderMapItems
} }
// Rally points on map // Rally points on map
......
...@@ -113,9 +113,9 @@ Item { ...@@ -113,9 +113,9 @@ Item {
coordList.push(edgeCoordinate) coordList.push(edgeCoordinate)
} }
} }
if (mapGeoFenceController.polygonEnabled && mapGeoFenceController.polygon.count() > 2) { if (mapGeoFenceController.polygonEnabled && mapGeoFenceController.mapPolygon.path.count > 2) {
for (var i=0; i<mapGeoFenceController.polygon.count(); i++) { for (var i=0; i<mapGeoFenceController.mapPolygon.path.count; i++) {
coordList.push(mapGeoFenceController.polygon.path[i]) coordList.push(mapGeoFenceController.mapPolygon.path[i])
} }
} }
} }
......
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
* *
****************************************************************************/ ****************************************************************************/
#include "JsonHelper.h" #include "JsonHelper.h"
#include "QGCQGeoCoordinate.h"
#include "QmlObjectListModel.h"
#include <QJsonArray> #include <QJsonArray>
#include <QJsonParseError> #include <QJsonParseError>
...@@ -308,3 +309,30 @@ QString JsonHelper::_jsonValueTypeToString(QJsonValue::Type type) ...@@ -308,3 +309,30 @@ QString JsonHelper::_jsonValueTypeToString(QJsonValue::Type type)
return QObject::tr("Unknown type: %1").arg(type); return QObject::tr("Unknown type: %1").arg(type);
} }
bool JsonHelper::loadPolygon(const QJsonArray& polygonArray, QmlObjectListModel& list, QObject* parent, QString& errorString)
{
for (int i=0; i<polygonArray.count(); i++) {
const QJsonValue& pointValue = polygonArray[i];
QGeoCoordinate pointCoord;
if (!JsonHelper::loadGeoCoordinate(pointValue, false /* altitudeRequired */, pointCoord, errorString)) {
list.clearAndDeleteContents();
return false;
}
list.append(new QGCQGeoCoordinate(pointCoord, parent));
}
return true;
}
void JsonHelper::savePolygon(QmlObjectListModel& list, QJsonArray& polygonArray)
{
for (int i=0; i<list.count(); i++) {
QGeoCoordinate vertex = list.value<QGCQGeoCoordinate*>(i)->coordinate();
QJsonValue jsonValue;
JsonHelper::saveGeoCoordinate(vertex, false /* writeAltitude */, jsonValue);
polygonArray.append(jsonValue);
}
}
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <QVariantList> #include <QVariantList>
#include <QGeoCoordinate> #include <QGeoCoordinate>
class QmlObjectListModel;
class JsonHelper class JsonHelper
{ {
public: public:
...@@ -52,6 +54,12 @@ public: ...@@ -52,6 +54,12 @@ public:
QGeoCoordinate& coordinate, ///< returned QGeoCordinate QGeoCoordinate& coordinate, ///< returned QGeoCordinate
QString& errorString); ///< returned error string if load failure QString& errorString); ///< returned error string if load failure
/// Loads a polygon from an array
static bool loadPolygon(const QJsonArray& polygonArray, ///< Array of coordinates
QmlObjectListModel& list, ///< Empty list to add vertices to
QObject* parent, ///< parent for newly allocated QGCQGeoCoordinates
QString& errorString); ///< returned error string if load failure
/// Saves a QGeoCoordinate /// Saves a QGeoCoordinate
static void saveGeoCoordinate(const QGeoCoordinate& coordinate, ///< QGeoCoordinate to save static void saveGeoCoordinate(const QGeoCoordinate& coordinate, ///< QGeoCoordinate to save
bool writeAltitude, ///< true: write altitude to json bool writeAltitude, ///< true: write altitude to json
...@@ -76,6 +84,10 @@ public: ...@@ -76,6 +84,10 @@ public:
bool writeAltitude, ///< true: write altitide value bool writeAltitude, ///< true: write altitide value
QJsonValue& jsonValue); ///< json value to save to QJsonValue& jsonValue); ///< json value to save to
/// Saves a polygon to a json array
static void savePolygon(QmlObjectListModel& list, ///< List which contains vertices
QJsonArray& polygonArray); ///< Array to save into
static bool parseEnum(const QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString); static bool parseEnum(const QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString);
......
...@@ -12,11 +12,16 @@ QGCFlickable { ...@@ -12,11 +12,16 @@ QGCFlickable {
contentHeight: geoFenceEditorRect.height contentHeight: geoFenceEditorRect.height
clip: true clip: true
property real availableWidth
property real availableHeight
property var myGeoFenceController
property var flightMap
readonly property real _editFieldWidth: Math.min(width - _margin * 2, ScreenTools.defaultFontPixelWidth * 15) readonly property real _editFieldWidth: Math.min(width - _margin * 2, ScreenTools.defaultFontPixelWidth * 15)
readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2 readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2
readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2 readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2
property var polygon: geoFenceController.polygon property var polygon: myGeoFenceController.polygon
Rectangle { Rectangle {
id: geoFenceEditorRect id: geoFenceEditorRect
...@@ -60,9 +65,11 @@ QGCFlickable { ...@@ -60,9 +65,11 @@ QGCFlickable {
anchors.margins: _margin anchors.margins: _margin
anchors.top: geoLabel.bottom anchors.top: geoLabel.bottom
anchors.left: parent.left anchors.left: parent.left
source: geoFenceController.editorQml source: myGeoFenceController.editorQml
property real availableWidth: parent.width - (_margin * 2) property real availableWidth: parent.width - (_margin * 2)
property var geoFenceController: myGeoFenceController
property var myFlightMap: flightMap
} }
} }
} }
......
This diff is collapsed.
...@@ -129,9 +129,7 @@ QGCView { ...@@ -129,9 +129,7 @@ QGCView {
mapFitFunctions.fitMapViewportToMissionItems() mapFitFunctions.fitMapViewportToMissionItems()
} }
onVisualItemsChanged: { onVisualItemsChanged: itemDragger.clearItem()
itemDragger.clearItem()
}
onNewItemsFromVehicle: { onNewItemsFromVehicle: {
if (_visualItems && _visualItems.count != 1) { if (_visualItems && _visualItems.count != 1) {
...@@ -165,17 +163,6 @@ QGCView { ...@@ -165,17 +163,6 @@ QGCView {
} }
} }
function validateBreachReturn() {
if (geoFenceController.polygon.path.length > 0) {
if (!geoFenceController.polygon.containsCoordinate(geoFenceController.breachReturnPoint)) {
geoFenceController.breachReturnPoint = geoFenceController.polygon.center()
}
if (!geoFenceController.polygon.containsCoordinate(geoFenceController.breachReturnPoint)) {
geoFenceController.breachReturnPoint = geoFenceController.polygon.path[0]
}
}
}
function fitViewportToItems() { function fitViewportToItems() {
mapFitFunctions.fitMapViewportToFenceItems() mapFitFunctions.fitMapViewportToFenceItems()
} }
...@@ -393,12 +380,6 @@ QGCView { ...@@ -393,12 +380,6 @@ QGCView {
insertSimpleMissionItem(coordinate, missionController.visualItems.count) insertSimpleMissionItem(coordinate, missionController.visualItems.count)
} }
break break
case _layerGeoFence:
if (geoFenceController.breachReturnEnabled) {
geoFenceController.breachReturnPoint = coordinate
geoFenceController.validateBreachReturn()
}
break
case _layerRallyPoints: case _layerRallyPoints:
if (rallyPointController.rallyPointsSupported) { if (rallyPointController.rallyPointsSupported) {
rallyPointController.addPoint(coordinate) rallyPointController.addPoint(coordinate)
...@@ -492,6 +473,7 @@ QGCView { ...@@ -492,6 +473,7 @@ QGCView {
anchors.top: parent.top anchors.top: parent.top
anchors.leftMargin: parent.width - _rightPanelWidth anchors.leftMargin: parent.width - _rightPanelWidth
anchors.left: parent.left anchors.left: parent.left
z: QGroundControl.zOrderWidgets
spacing: _horizontalMargin spacing: _horizontalMargin
visible: QGroundControl.corePlugin.options.enablePlanViewSelector visible: QGroundControl.corePlugin.options.enablePlanViewSelector
...@@ -613,40 +595,20 @@ QGCView { ...@@ -613,40 +595,20 @@ QGCView {
anchors.top: planElementSelectorRow.bottom anchors.top: planElementSelectorRow.bottom
anchors.right: parent.right anchors.right: parent.right
opacity: _rightPanelOpacity opacity: _rightPanelOpacity
z: QGroundControl.zOrderTopMost z: QGroundControl.zOrderWidgets
source: _editingLayer == _layerGeoFence ? "qrc:/qml/GeoFenceEditor.qml" : "" sourceComponent: _editingLayer == _layerGeoFence ? geoFenceEditorComponent : undefined
property real availableWidth: _rightPanelWidth
property real availableHeight: ScreenTools.availableHeight
}
// GeoFence polygon
MapPolygon {
border.color: "#80FF0000"
border.width: 3
path: geoFenceController.polygon.path
z: QGroundControl.zOrderMapItems
visible: geoFenceController.polygonEnabled
}
// GeoFence circle property real availableWidth: _rightPanelWidth
MapCircle { property real availableHeight: ScreenTools.availableHeight
border.color: "#80FF0000" property var myGeoFenceController: geoFenceController
border.width: 3
center: missionController.plannedHomePosition
radius: geoFenceController.circleRadius
z: QGroundControl.zOrderMapItems
visible: geoFenceController.circleEnabled
} }
// GeoFence breach return point GeoFenceMapVisuals {
MapQuickItem { map: editorMap
anchorPoint.x: sourceItem.anchorPointX myGeoFenceController: geoFenceController
anchorPoint.y: sourceItem.anchorPointY interactive: _editingLayer == _layerGeoFence
coordinate: geoFenceController.breachReturnPoint homePosition: missionController.plannedHomePosition
visible: geoFenceController.breachReturnEnabled planView: true
sourceItem: MissionItemIndexLabel { label: "F" }
z: QGroundControl.zOrderMapItems
} }
// Rally Point Editor // Rally Point Editor
...@@ -997,4 +959,15 @@ QGCView { ...@@ -997,4 +959,15 @@ QGCView {
} }
} // Column } // Column
} }
Component {
id: geoFenceEditorComponent
GeoFenceEditor {
availableWidth: _rightPanelWidth
availableHeight: ScreenTools.availableHeight
myGeoFenceController: geoFenceController
flightMap: editorMap
}
}
} // QGCVIew } // QGCVIew
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "QGCApplication.h" #include "QGCApplication.h"
#include "ParameterManager.h" #include "ParameterManager.h"
#include "JsonHelper.h" #include "JsonHelper.h"
#include "QGCQGeoCoordinate.h"
#ifndef __mobile__ #ifndef __mobile__
#include "MainWindow.h" #include "MainWindow.h"
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
#endif #endif
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonArray>
QGC_LOGGING_CATEGORY(GeoFenceControllerLog, "GeoFenceControllerLog") QGC_LOGGING_CATEGORY(GeoFenceControllerLog, "GeoFenceControllerLog")
...@@ -34,8 +36,10 @@ const char* GeoFenceController::_jsonBreachReturnKey = "breachReturn"; ...@@ -34,8 +36,10 @@ const char* GeoFenceController::_jsonBreachReturnKey = "breachReturn";
GeoFenceController::GeoFenceController(QObject* parent) GeoFenceController::GeoFenceController(QObject* parent)
: PlanElementController(parent) : PlanElementController(parent)
, _dirty(false) , _dirty(false)
, _mapPolygon(this)
{ {
connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::countChanged, this, &GeoFenceController::_updateContainsItems);
connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::dirtyChanged, this, &GeoFenceController::_polygonDirtyChanged);
} }
GeoFenceController::~GeoFenceController() GeoFenceController::~GeoFenceController()
...@@ -61,7 +65,7 @@ void GeoFenceController::startStaticActiveVehicle(Vehicle* vehicle) ...@@ -61,7 +65,7 @@ void GeoFenceController::startStaticActiveVehicle(Vehicle* vehicle)
void GeoFenceController::_init(void) void GeoFenceController::_init(void)
{ {
connect(&_polygon, &QGCMapPolygon::dirtyChanged, this, &GeoFenceController::_polygonDirtyChanged);
} }
void GeoFenceController::setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint) void GeoFenceController::setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint)
...@@ -139,13 +143,11 @@ bool GeoFenceController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorStr ...@@ -139,13 +143,11 @@ bool GeoFenceController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorStr
} }
if (polygonEnabled()) { if (polygonEnabled()) {
if (!_polygon.loadFromJson(json, false /* reauired */, errorString)) { if (!_mapPolygon.loadFromJson(json, true, errorString)) {
return false; return false;
} }
} else {
_polygon.clear();
} }
_polygon.setDirty(false); _mapPolygon.setDirty(false);
return true; return true;
} }
...@@ -289,7 +291,7 @@ void GeoFenceController::saveToFile(const QString& filename) ...@@ -289,7 +291,7 @@ void GeoFenceController::saveToFile(const QString& filename)
} }
if (polygonEnabled()) { if (polygonEnabled()) {
_polygon.saveToJson(fenceFileObject); _mapPolygon.saveToJson(fenceFileObject);
} }
QJsonDocument saveDoc(fenceFileObject); QJsonDocument saveDoc(fenceFileObject);
...@@ -314,7 +316,7 @@ void GeoFenceController::saveToFilePicker(void) ...@@ -314,7 +316,7 @@ void GeoFenceController::saveToFilePicker(void)
void GeoFenceController::removeAll(void) void GeoFenceController::removeAll(void)
{ {
setBreachReturnPoint(QGeoCoordinate()); setBreachReturnPoint(QGeoCoordinate());
_polygon.clear(); _mapPolygon.clear();
} }
void GeoFenceController::loadFromVehicle(void) void GeoFenceController::loadFromVehicle(void)
...@@ -329,8 +331,8 @@ void GeoFenceController::loadFromVehicle(void) ...@@ -329,8 +331,8 @@ void GeoFenceController::loadFromVehicle(void)
void GeoFenceController::sendToVehicle(void) void GeoFenceController::sendToVehicle(void)
{ {
if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) { if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) {
_activeVehicle->geoFenceManager()->sendToVehicle(_breachReturnPoint, _polygon.coordinateList()); _activeVehicle->geoFenceManager()->sendToVehicle(_breachReturnPoint, _mapPolygon.pathModel());
_polygon.setDirty(false); _mapPolygon.setDirty(false);
setDirty(false); setDirty(false);
} else { } else {
qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress(); qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
...@@ -344,7 +346,7 @@ bool GeoFenceController::syncInProgress(void) const ...@@ -344,7 +346,7 @@ bool GeoFenceController::syncInProgress(void) const
bool GeoFenceController::dirty(void) const bool GeoFenceController::dirty(void) const
{ {
return _dirty | _polygon.dirty(); return _dirty;
} }
...@@ -353,7 +355,7 @@ void GeoFenceController::setDirty(bool dirty) ...@@ -353,7 +355,7 @@ void GeoFenceController::setDirty(bool dirty)
if (dirty != _dirty) { if (dirty != _dirty) {
_dirty = dirty; _dirty = dirty;
if (!dirty) { if (!dirty) {
_polygon.setDirty(dirty); _mapPolygon.setDirty(dirty);
} }
emit dirtyChanged(dirty); emit dirtyChanged(dirty);
} }
...@@ -388,9 +390,11 @@ void GeoFenceController::_setDirty(void) ...@@ -388,9 +390,11 @@ void GeoFenceController::_setDirty(void)
void GeoFenceController::_setPolygonFromManager(const QList<QGeoCoordinate>& polygon) void GeoFenceController::_setPolygonFromManager(const QList<QGeoCoordinate>& polygon)
{ {
_polygon.setPath(polygon); _mapPolygon.clear();
_polygon.setDirty(false); for (int i=0; i<polygon.count(); i++) {
emit polygonPathChanged(_polygon.path()); _mapPolygon.appendVertex(polygon[i]);
}
_mapPolygon.setDirty(false);
} }
void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint) void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint)
...@@ -431,3 +435,30 @@ QString GeoFenceController::fileExtension(void) const ...@@ -431,3 +435,30 @@ QString GeoFenceController::fileExtension(void) const
{ {
return QGCApplication::fenceFileExtension; return QGCApplication::fenceFileExtension;
} }
bool GeoFenceController::containsItems(void) const
{
return _mapPolygon.count() > 2;
}
void GeoFenceController::_updateContainsItems(void)
{
emit containsItemsChanged(containsItems());
}
void GeoFenceController::removeAllFromVehicle(void)
{
_activeVehicle->geoFenceManager()->removeAll();
}
void GeoFenceController::addFence(void)
{
// GeoFenceMapVisuals control is resposible for this
emit addFencePolygon();
}
void GeoFenceController::removeFence(void)
{
_mapPolygon.clear();
}
...@@ -28,27 +28,22 @@ class GeoFenceController : public PlanElementController ...@@ -28,27 +28,22 @@ class GeoFenceController : public PlanElementController
public: public:
GeoFenceController(QObject* parent = NULL); GeoFenceController(QObject* parent = NULL);
~GeoFenceController(); ~GeoFenceController();
Q_PROPERTY(bool circleEnabled READ circleEnabled NOTIFY circleEnabledChanged)
Q_PROPERTY(float circleRadius READ circleRadius NOTIFY circleRadiusChanged)
Q_PROPERTY(bool polygonEnabled READ polygonEnabled NOTIFY polygonEnabledChanged) Q_PROPERTY(bool circleEnabled READ circleEnabled NOTIFY circleEnabledChanged)
Q_PROPERTY(QGCMapPolygon* polygon READ polygon CONSTANT) Q_PROPERTY(float circleRadius READ circleRadius NOTIFY circleRadiusChanged)
Q_PROPERTY(bool breachReturnEnabled READ breachReturnEnabled NOTIFY breachReturnEnabledChanged) Q_PROPERTY(bool polygonEnabled READ polygonEnabled NOTIFY polygonEnabledChanged)
Q_PROPERTY(QGeoCoordinate breachReturnPoint READ breachReturnPoint WRITE setBreachReturnPoint NOTIFY breachReturnPointChanged) Q_PROPERTY(QGCMapPolygon* mapPolygon READ mapPolygon CONSTANT)
Q_PROPERTY(QVariantList params READ params NOTIFY paramsChanged) Q_PROPERTY(bool breachReturnEnabled READ breachReturnEnabled NOTIFY breachReturnEnabledChanged)
Q_PROPERTY(QStringList paramLabels READ paramLabels NOTIFY paramLabelsChanged) Q_PROPERTY(QGeoCoordinate breachReturnPoint READ breachReturnPoint WRITE setBreachReturnPoint NOTIFY breachReturnPointChanged)
Q_PROPERTY(QString editorQml READ editorQml NOTIFY editorQmlChanged)
#if 0 Q_PROPERTY(QVariantList params READ params NOTIFY paramsChanged)
Q_PROPERTY(bool fenceSupported READ fenceSupported NOTIFY fenceSupportedChanged) Q_PROPERTY(QStringList paramLabels READ paramLabels NOTIFY paramLabelsChanged)
Q_PROPERTY(bool fenceEnabled READ fenceEnabled NOTIFY fenceEnabledChanged) Q_PROPERTY(QString editorQml READ editorQml NOTIFY editorQmlChanged)
Q_PROPERTY(bool circleSupported READ circleSupported NOTIFY circleSupportedChanged)
Q_PROPERTY(bool polygonSupported READ polygonSupported NOTIFY polygonSupportedChanged) Q_INVOKABLE void addFence(void);
Q_PROPERTY(bool breachReturnSupported READ breachReturnSupported NOTIFY breachReturnSupportedChanged) Q_INVOKABLE void removeFence(void);
#endif
void start (bool editMode) final; void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final; void startStaticActiveVehicle (Vehicle* vehicle) final;
...@@ -59,9 +54,11 @@ public: ...@@ -59,9 +54,11 @@ public:
void saveToFilePicker (void) final; void saveToFilePicker (void) final;
void saveToFile (const QString& filename) final; void saveToFile (const QString& filename) final;
void removeAll (void) final; void removeAll (void) final;
void removeAllFromVehicle (void) final;
bool syncInProgress (void) const final; bool syncInProgress (void) const final;
bool dirty (void) const final; bool dirty (void) const final;
void setDirty (bool dirty) final; void setDirty (bool dirty) final;
bool containsItems (void) const final;
QString fileExtension(void) const final; QString fileExtension(void) const final;
...@@ -69,7 +66,7 @@ public: ...@@ -69,7 +66,7 @@ public:
bool polygonEnabled (void) const; bool polygonEnabled (void) const;
bool breachReturnEnabled (void) const; bool breachReturnEnabled (void) const;
float circleRadius (void) const; float circleRadius (void) const;
QGCMapPolygon* polygon (void) { return &_polygon; } QGCMapPolygon* mapPolygon (void) { return &_mapPolygon; }
QGeoCoordinate breachReturnPoint (void) const { return _breachReturnPoint; } QGeoCoordinate breachReturnPoint (void) const { return _breachReturnPoint; }
QVariantList params (void) const; QVariantList params (void) const;
QStringList paramLabels (void) const; QStringList paramLabels (void) const;
...@@ -78,11 +75,11 @@ public: ...@@ -78,11 +75,11 @@ public:
void setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint); void setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint);
signals: signals:
void addFencePolygon (void);
void circleEnabledChanged (bool circleEnabled); void circleEnabledChanged (bool circleEnabled);
void polygonEnabledChanged (bool polygonEnabled); void polygonEnabledChanged (bool polygonEnabled);
void breachReturnEnabledChanged (bool breachReturnEnabled); void breachReturnEnabledChanged (bool breachReturnEnabled);
void circleRadiusChanged (float circleRadius); void circleRadiusChanged (float circleRadius);
void polygonPathChanged (const QVariantList& polygonPath);
void breachReturnPointChanged (QGeoCoordinate breachReturnPoint); void breachReturnPointChanged (QGeoCoordinate breachReturnPoint);
void paramsChanged (QVariantList params); void paramsChanged (QVariantList params);
void paramLabelsChanged (QStringList paramLabels); void paramLabelsChanged (QStringList paramLabels);
...@@ -95,6 +92,7 @@ private slots: ...@@ -95,6 +92,7 @@ private slots:
void _setPolygonFromManager(const QList<QGeoCoordinate>& polygon); void _setPolygonFromManager(const QList<QGeoCoordinate>& polygon);
void _setReturnPointFromManager(QGeoCoordinate breachReturnPoint); void _setReturnPointFromManager(QGeoCoordinate breachReturnPoint);
void _loadComplete(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon); void _loadComplete(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon);
void _updateContainsItems(void);
private: private:
void _init(void); void _init(void);
...@@ -105,7 +103,7 @@ private: ...@@ -105,7 +103,7 @@ private:
void _activeVehicleSet(void) final; void _activeVehicleSet(void) final;
bool _dirty; bool _dirty;
QGCMapPolygon _polygon; QGCMapPolygon _mapPolygon;
QGeoCoordinate _breachReturnPoint; QGeoCoordinate _breachReturnPoint;
QVariantList _params; QVariantList _params;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "GeoFenceManager.h" #include "GeoFenceManager.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "QmlObjectListModel.h"
QGC_LOGGING_CATEGORY(GeoFenceManagerLog, "GeoFenceManagerLog") QGC_LOGGING_CATEGORY(GeoFenceManagerLog, "GeoFenceManagerLog")
...@@ -37,7 +38,7 @@ void GeoFenceManager::loadFromVehicle(void) ...@@ -37,7 +38,7 @@ void GeoFenceManager::loadFromVehicle(void)
emit loadComplete(QGeoCoordinate(), QList<QGeoCoordinate>()); emit loadComplete(QGeoCoordinate(), QList<QGeoCoordinate>());
} }
void GeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon) void GeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, QmlObjectListModel& polygon)
{ {
Q_UNUSED(breachReturn); Q_UNUSED(breachReturn);
Q_UNUSED(polygon); Q_UNUSED(polygon);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "QGCLoggingCategory.h" #include "QGCLoggingCategory.h"
class Vehicle; class Vehicle;
class QmlObjectListModel;
Q_DECLARE_LOGGING_CATEGORY(GeoFenceManagerLog) Q_DECLARE_LOGGING_CATEGORY(GeoFenceManagerLog)
...@@ -36,7 +37,9 @@ public: ...@@ -36,7 +37,9 @@ public:
virtual void loadFromVehicle(void); virtual void loadFromVehicle(void);
/// Send the current settings to the vehicle /// Send the current settings to the vehicle
virtual void sendToVehicle(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon); virtual void sendToVehicle(const QGeoCoordinate& breachReturn, QmlObjectListModel& polygon);
virtual void removeAll(void) { };
virtual bool circleEnabled (void) const { return false; } virtual bool circleEnabled (void) const { return false; }
virtual bool polygonEnabled (void) const { return false; } virtual bool polygonEnabled (void) const { return false; }
......
...@@ -95,27 +95,41 @@ void MissionController::_init(void) ...@@ -95,27 +95,41 @@ void MissionController::_init(void)
} }
// Called when new mission items have completed downloading from Vehicle // Called when new mission items have completed downloading from Vehicle
void MissionController::_newMissionItemsAvailableFromVehicle(void) void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllRequested)
{ {
qCDebug(MissionControllerLog) << "_newMissionItemsAvailableFromVehicle"; qCDebug(MissionControllerLog) << "_newMissionItemsAvailableFromVehicle";
if (!_editMode || _missionItemsRequested || _visualItems->count() == 1) { if (!_editMode || removeAllRequested || _missionItemsRequested || _visualItems->count() == 1) {
// Fly Mode: // Fly Mode (accept if):
// - Always accepts new items from the vehicle so Fly view is kept up to date // - Always accepts new items from the vehicle so Fly view is kept up to date
// Edit Mode: // Edit Mode (accept if):
// - Either a load from vehicle was manually requested or // - Either a load from vehicle was manually requested or
// - The initial automatic load from a vehicle completed and the current editor is empty // - The initial automatic load from a vehicle completed and the current editor is empty
// - Remove all way requested from Fly view (clear mission on flight end)
QmlObjectListModel* newControllerMissionItems = new QmlObjectListModel(this); QmlObjectListModel* newControllerMissionItems = new QmlObjectListModel(this);
const QList<MissionItem*>& newMissionItems = _activeVehicle->missionManager()->missionItems(); const QList<MissionItem*>& newMissionItems = _activeVehicle->missionManager()->missionItems();
qCDebug(MissionControllerLog) << "loading from vehicle: count"<< newMissionItems.count();
int i = 0;
if (_activeVehicle->firmwarePlugin()->sendHomePositionToVehicle() && newMissionItems.count() != 0) {
// First item is fake home position
_addMissionSettings(_activeVehicle, newControllerMissionItems, false /* addToCenter */);
MissionSettingsComplexItem* settingsItem = newControllerMissionItems->value<MissionSettingsComplexItem*>(0);
if (!settingsItem) {
qWarning() << "First item is not settings item";
return;
}
settingsItem->setCoordinate(newMissionItems[0]->coordinate());
i = 1;
}
qCDebug(MissionControllerLog) << "loading from vehicle: count"<< _visualItems->count(); for (; i<newMissionItems.count(); i++) {
foreach(const MissionItem* missionItem, newMissionItems) { const MissionItem* missionItem = newMissionItems[i];
newControllerMissionItems->append(new SimpleMissionItem(_activeVehicle, *missionItem, this)); newControllerMissionItems->append(new SimpleMissionItem(_activeVehicle, *missionItem, this));
} }
_deinitAllVisualItems(); _deinitAllVisualItems();
_visualItems->deleteLater(); _visualItems->deleteLater();
_visualItems = newControllerMissionItems; _visualItems = newControllerMissionItems;
...@@ -1112,9 +1126,10 @@ void MissionController::_initAllVisualItems(void) ...@@ -1112,9 +1126,10 @@ void MissionController::_initAllVisualItems(void)
_recalcAll(); _recalcAll();
emit visualItemsChanged();
connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged); connect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged);
connect(_visualItems, &QmlObjectListModel::countChanged, this, &MissionController::_updateContainsItems);
emit visualItemsChanged();
_visualItems->setDirty(false); _visualItems->setDirty(false);
} }
...@@ -1126,6 +1141,7 @@ void MissionController::_deinitAllVisualItems(void) ...@@ -1126,6 +1141,7 @@ void MissionController::_deinitAllVisualItems(void)
} }
disconnect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged); disconnect(_visualItems, &QmlObjectListModel::dirtyChanged, this, &MissionController::dirtyChanged);
disconnect(_visualItems, &QmlObjectListModel::countChanged, this, &MissionController::_updateContainsItems);
} }
void MissionController::_initVisualItem(VisualMissionItem* visualItem) void MissionController::_initVisualItem(VisualMissionItem* visualItem)
...@@ -1494,3 +1510,19 @@ void MissionController::_scanForAdditionalSettings(QmlObjectListModel* visualIte ...@@ -1494,3 +1510,19 @@ void MissionController::_scanForAdditionalSettings(QmlObjectListModel* visualIte
scanIndex++; scanIndex++;
} }
} }
void MissionController::_updateContainsItems(void)
{
emit containsItemsChanged(containsItems());
}
bool MissionController::containsItems(void) const
{
return _visualItems ? _visualItems->count() > 1 : false;
}
void MissionController::removeAllFromVehicle(void)
{
_missionItemsRequested = true;
_activeVehicle->missionManager()->removeAll();
}
...@@ -82,9 +82,11 @@ public: ...@@ -82,9 +82,11 @@ public:
void saveToFilePicker (void) final; void saveToFilePicker (void) final;
void saveToFile (const QString& filename) final; void saveToFile (const QString& filename) final;
void removeAll (void) final; void removeAll (void) final;
void removeAllFromVehicle (void) final;
bool syncInProgress (void) const final; bool syncInProgress (void) const final;
bool dirty (void) const final; bool dirty (void) const final;
void setDirty (bool dirty) final; void setDirty (bool dirty) final;
bool containsItems (void) const final;
QString fileExtension(void) const final; QString fileExtension(void) const final;
...@@ -122,7 +124,7 @@ signals: ...@@ -122,7 +124,7 @@ signals:
void hoverSpeedChanged(double hoverSpeed); void hoverSpeedChanged(double hoverSpeed);
private slots: private slots:
void _newMissionItemsAvailableFromVehicle(); void _newMissionItemsAvailableFromVehicle(bool removeAllRequested);
void _itemCommandChanged(void); void _itemCommandChanged(void);
void _activeVehicleHomePositionAvailableChanged(bool homePositionAvailable); void _activeVehicleHomePositionAvailableChanged(bool homePositionAvailable);
void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition); void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
...@@ -131,6 +133,7 @@ private slots: ...@@ -131,6 +133,7 @@ private slots:
void _recalcWaypointLines(void); void _recalcWaypointLines(void);
void _recalcAltitudeRangeBearing(void); void _recalcAltitudeRangeBearing(void);
void _homeCoordinateChanged(void); void _homeCoordinateChanged(void);
void _updateContainsItems(void);
private: private:
void _init(void); void _init(void);
......
...@@ -73,7 +73,7 @@ void MissionManager::writeMissionItems(const QList<MissionItem*>& missionItems) ...@@ -73,7 +73,7 @@ void MissionManager::writeMissionItems(const QList<MissionItem*>& missionItems)
} }
} }
} }
emit newMissionItemsAvailable(); emit newMissionItemsAvailable(missionItems.count() == 0);
qCDebug(MissionManagerLog) << "writeMissionItems count:" << _missionItems.count(); qCDebug(MissionManagerLog) << "writeMissionItems count:" << _missionItems.count();
...@@ -306,7 +306,7 @@ void MissionManager::_readTransactionComplete(void) ...@@ -306,7 +306,7 @@ void MissionManager::_readTransactionComplete(void)
_vehicle->sendMessageOnLink(_dedicatedLink, message); _vehicle->sendMessageOnLink(_dedicatedLink, message);
_finishTransaction(true); _finishTransaction(true);
emit newMissionItemsAvailable(); emit newMissionItemsAvailable(false);
} }
void MissionManager::_handleMissionCount(const mavlink_message_t& message) void MissionManager::_handleMissionCount(const mavlink_message_t& message)
...@@ -737,7 +737,7 @@ void MissionManager::_finishTransaction(bool success) ...@@ -737,7 +737,7 @@ void MissionManager::_finishTransaction(bool success)
if (!success && _readTransactionInProgress) { if (!success && _readTransactionInProgress) {
// Read from vehicle failed, clear partial list // Read from vehicle failed, clear partial list
_missionItems.clear(); _missionItems.clear();
emit newMissionItemsAvailable(); emit newMissionItemsAvailable(false);
} }
_itemIndicesToRead.clear(); _itemIndicesToRead.clear();
...@@ -767,3 +767,10 @@ void MissionManager::_handleMissionCurrent(const mavlink_message_t& message) ...@@ -767,3 +767,10 @@ void MissionManager::_handleMissionCurrent(const mavlink_message_t& message)
emit currentItemChanged(_currentMissionItem); emit currentItemChanged(_currentMissionItem);
} }
} }
void MissionManager::removeAll(void)
{
QList<MissionItem*> emptyList;
writeMissionItems(emptyList);
}
...@@ -49,6 +49,9 @@ public: ...@@ -49,6 +49,9 @@ public:
/// @param altChangeOnly true: only altitude change, false: lat/lon/alt change /// @param altChangeOnly true: only altitude change, false: lat/lon/alt change
void writeArduPilotGuidedMissionItem(const QGeoCoordinate& gotoCoord, bool altChangeOnly); void writeArduPilotGuidedMissionItem(const QGeoCoordinate& gotoCoord, bool altChangeOnly);
/// Removes all mission items from vehicle
void removeAll(void);
/// Error codes returned in error signal /// Error codes returned in error signal
typedef enum { typedef enum {
InternalError, InternalError,
...@@ -66,7 +69,7 @@ public: ...@@ -66,7 +69,7 @@ public:
static const int _maxRetryCount = 5; static const int _maxRetryCount = 5;
signals: signals:
void newMissionItemsAvailable(void); void newMissionItemsAvailable(bool removeAllRequested);
void inProgressChanged(bool inProgress); void inProgressChanged(bool inProgress);
void error(int errorCode, const QString& errorMsg); void error(int errorCode, const QString& errorMsg);
void currentItemChanged(int currentItem); void currentItemChanged(int currentItem);
......
...@@ -25,17 +25,14 @@ public: ...@@ -25,17 +25,14 @@ public:
PlanElementController(QObject* parent = NULL); PlanElementController(QObject* parent = NULL);
~PlanElementController(); ~PlanElementController();
/// true: information is currently being saved/sent, false: no active save/send in progress Q_PROPERTY(bool containsItems READ containsItems NOTIFY containsItemsChanged) ///< true: Elemement is non-empty
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) ///< true: information is currently being saved/sent, false: no active save/send in progress
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< true: unsaved/sent changes are present, false: no changes since last save/send
Q_PROPERTY(QString fileExtension READ fileExtension CONSTANT) ///< Returns the file extention for plan element file type.
Q_PROPERTY(Vehicle* vehicle READ vehicle NOTIFY vehicleChanged)
/// true: unsaved/sent changes are present, false: no changes since last save/send
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
/// Returns the file extention for plan element file type.
Q_PROPERTY(QString fileExtension READ fileExtension CONSTANT)
virtual QString fileExtension(void) const = 0; virtual QString fileExtension(void) const = 0;
Q_PROPERTY(Vehicle* vehicle READ vehicle NOTIFY vehicleChanged)
/// Should be called immediately upon Component.onCompleted. /// Should be called immediately upon Component.onCompleted.
/// @param editMode true: controller being used in Plan view, false: controller being used in Fly view /// @param editMode true: controller being used in Plan view, false: controller being used in Fly view
...@@ -51,8 +48,10 @@ public: ...@@ -51,8 +48,10 @@ public:
Q_INVOKABLE virtual void loadFromFile(const QString& filename) = 0; Q_INVOKABLE virtual void loadFromFile(const QString& filename) = 0;
Q_INVOKABLE virtual void saveToFilePicker(void) = 0; Q_INVOKABLE virtual void saveToFilePicker(void) = 0;
Q_INVOKABLE virtual void saveToFile(const QString& filename) = 0; Q_INVOKABLE virtual void saveToFile(const QString& filename) = 0;
Q_INVOKABLE virtual void removeAll(void) = 0; Q_INVOKABLE virtual void removeAll(void) = 0; ///< Removes all from controller only, synce required to remove from vehicle
Q_INVOKABLE virtual void removeAllFromVehicle(void) = 0; ///< Removes all from vehicle and controller
virtual bool containsItems (void) const = 0;
virtual bool syncInProgress (void) const = 0; virtual bool syncInProgress (void) const = 0;
virtual bool dirty (void) const = 0; virtual bool dirty (void) const = 0;
virtual void setDirty (bool dirty) = 0; virtual void setDirty (bool dirty) = 0;
...@@ -60,6 +59,7 @@ public: ...@@ -60,6 +59,7 @@ public:
Vehicle* vehicle(void) { return _activeVehicle; } Vehicle* vehicle(void) { return _activeVehicle; }
signals: signals:
void containsItemsChanged (bool containsItems);
void syncInProgressChanged (bool syncInProgress); void syncInProgressChanged (bool syncInProgress);
void dirtyChanged (bool dirty); void dirtyChanged (bool dirty);
void vehicleChanged (Vehicle* vehicle); void vehicleChanged (Vehicle* vehicle);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "QGCMapPolygon.h" #include "QGCMapPolygon.h"
#include "QGCGeo.h" #include "QGCGeo.h"
#include "JsonHelper.h" #include "JsonHelper.h"
#include "QGCQGeoCoordinate.h"
#include <QGeoRectangle> #include <QGeoRectangle>
#include <QDebug> #include <QDebug>
...@@ -17,21 +18,13 @@ ...@@ -17,21 +18,13 @@
const char* QGCMapPolygon::_jsonPolygonKey = "polygon"; const char* QGCMapPolygon::_jsonPolygonKey = "polygon";
QGCMapPolygon::QGCMapPolygon(QObject* parent) QGCMapPolygon::QGCMapPolygon(QObject* newCoordParent, QObject* parent)
: QObject(parent) : QObject(parent)
, _newCoordParent(newCoordParent)
, _dirty(false) , _dirty(false)
{ {
connect(&_polygonModel, &QmlObjectListModel::dirtyChanged, this, &QGCMapPolygon::_polygonModelDirtyChanged);
} connect(&_polygonModel, &QmlObjectListModel::countChanged, this, &QGCMapPolygon::_polygonModelCountChanged);
const QGCMapPolygon& QGCMapPolygon::operator=(const QGCMapPolygon& other)
{
_polygonPath = other._polygonPath;
setDirty(true);
emit pathChanged();
return *this;
} }
void QGCMapPolygon::clear(void) void QGCMapPolygon::clear(void)
...@@ -48,13 +41,18 @@ void QGCMapPolygon::clear(void) ...@@ -48,13 +41,18 @@ void QGCMapPolygon::clear(void)
// will cause the polygon to go away. // will cause the polygon to go away.
_polygonPath.clear(); _polygonPath.clear();
_polygonModel.clearAndDeleteContents();
setDirty(true); setDirty(true);
} }
void QGCMapPolygon::adjustCoordinate(int vertexIndex, const QGeoCoordinate coordinate) void QGCMapPolygon::adjustVertex(int vertexIndex, const QGeoCoordinate coordinate)
{ {
_polygonPath[vertexIndex] = QVariant::fromValue(coordinate); _polygonPath[vertexIndex] = QVariant::fromValue(coordinate);
emit pathChanged(); emit pathChanged();
_polygonModel.value<QGCQGeoCoordinate*>(vertexIndex)->setCoordinate(coordinate);
setDirty(true); setDirty(true);
} }
...@@ -126,9 +124,12 @@ QGeoCoordinate QGCMapPolygon::center(void) const ...@@ -126,9 +124,12 @@ QGeoCoordinate QGCMapPolygon::center(void) const
void QGCMapPolygon::setPath(const QList<QGeoCoordinate>& path) void QGCMapPolygon::setPath(const QList<QGeoCoordinate>& path)
{ {
_polygonPath.clear(); _polygonPath.clear();
_polygonModel.clearAndDeleteContents();
foreach(const QGeoCoordinate& coord, path) { foreach(const QGeoCoordinate& coord, path) {
_polygonPath << QVariant::fromValue(coord); _polygonPath.append(QVariant::fromValue(coord));
_polygonModel.append(new QGCQGeoCoordinate(coord, _newCoordParent));
} }
setDirty(true); setDirty(true);
emit pathChanged(); emit pathChanged();
} }
...@@ -136,6 +137,12 @@ void QGCMapPolygon::setPath(const QList<QGeoCoordinate>& path) ...@@ -136,6 +137,12 @@ void QGCMapPolygon::setPath(const QList<QGeoCoordinate>& path)
void QGCMapPolygon::setPath(const QVariantList& path) void QGCMapPolygon::setPath(const QVariantList& path)
{ {
_polygonPath = path; _polygonPath = path;
_polygonModel.clearAndDeleteContents();
for (int i=0; i<_polygonPath.count(); i++) {
_polygonModel.append(new QGCQGeoCoordinate(_polygonPath[i].value<QGeoCoordinate>(), _newCoordParent));
}
setDirty(true); setDirty(true);
emit pathChanged(); emit pathChanged();
} }
...@@ -175,9 +182,70 @@ QList<QGeoCoordinate> QGCMapPolygon::coordinateList(void) const ...@@ -175,9 +182,70 @@ QList<QGeoCoordinate> QGCMapPolygon::coordinateList(void) const
{ {
QList<QGeoCoordinate> coords; QList<QGeoCoordinate> coords;
for (int i=0; i<count(); i++) { for (int i=0; i<_polygonPath.count(); i++) {
coords.append((*this)[i]); coords.append(_polygonPath[i].value<QGeoCoordinate>());
} }
return coords; return coords;
} }
void QGCMapPolygon::splitPolygonSegment(int vertexIndex)
{
int nextIndex = vertexIndex + 1;
if (nextIndex > _polygonPath.length() - 1) {
nextIndex = 0;
}
QGeoCoordinate firstVertex = _polygonPath[vertexIndex].value<QGeoCoordinate>();
QGeoCoordinate nextVertex = _polygonPath[nextIndex].value<QGeoCoordinate>();
double distance = firstVertex.distanceTo(nextVertex);
double azimuth = firstVertex.azimuthTo(nextVertex);
QGeoCoordinate newVertex = firstVertex.atDistanceAndAzimuth(distance / 2, azimuth);
if (nextIndex == 0) {
appendVertex(newVertex);
} else {
_polygonModel.insert(nextIndex, new QGCQGeoCoordinate(newVertex, this));
_polygonPath.insert(nextIndex, QVariant::fromValue(newVertex));
emit pathChanged();
}
}
void QGCMapPolygon::appendVertex(const QGeoCoordinate& coordinate)
{
_polygonPath.append(QVariant::fromValue(coordinate));
_polygonModel.append(new QGCQGeoCoordinate(coordinate, _newCoordParent));
emit pathChanged();
}
void QGCMapPolygon::_polygonModelDirtyChanged(bool dirty)
{
if (dirty) {
setDirty(true);
}
}
void QGCMapPolygon::removeVertex(int vertexIndex)
{
if (vertexIndex < 0 && vertexIndex > _polygonPath.length() - 1) {
qWarning() << "Call to removePolygonCoordinate with bad vertexIndex:count" << vertexIndex << _polygonPath.length();
return;
}
if (_polygonPath.length() <= 3) {
// Don't allow the user to trash the polygon
return;
}
QObject* coordObj = _polygonModel.removeAt(vertexIndex);
coordObj->deleteLater();
_polygonPath.removeAt(vertexIndex);
emit pathChanged();
}
void QGCMapPolygon::_polygonModelCountChanged(int count)
{
emit countChanged(count);
}
...@@ -15,33 +15,33 @@ ...@@ -15,33 +15,33 @@
#include <QVariantList> #include <QVariantList>
#include <QPolygon> #include <QPolygon>
/// The QGCMapPolygon class provides a polygon which can be displayed on a map using a MapPolygon control. #include "QmlObjectListModel.h"
/// It works in conjunction with the QGCMapPolygonControls control which provides the UI for drawing and
/// editing map polygons. /// The QGCMapPolygon class provides a polygon which can be displayed on a map using a map visuals control.
/// It maintains a representation of the polygon on QVariantList and QmlObjectListModel format.
class QGCMapPolygon : public QObject class QGCMapPolygon : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
QGCMapPolygon(QObject* parent = NULL); QGCMapPolygon(QObject* newCoordParent, QObject* parent = NULL);
const QGCMapPolygon& operator=(const QGCMapPolygon& other);
QGeoCoordinate operator[](int index) const { return _polygonPath[index].value<QGeoCoordinate>(); }
/// The polygon path to be bound to the MapPolygon.path property
Q_PROPERTY(QVariantList path READ path WRITE setPath NOTIFY pathChanged)
/// true: Polygon has changed since last time dirty was false Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) Q_PROPERTY(QVariantList path READ path NOTIFY pathChanged)
Q_PROPERTY(QmlObjectListModel* pathModel READ qmlPathModel CONSTANT)
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged)
/// Remove all points from polygon
Q_INVOKABLE void clear(void); Q_INVOKABLE void clear(void);
Q_INVOKABLE void appendVertex(const QGeoCoordinate& coordinate);
Q_INVOKABLE void removeVertex(int vertexIndex);
/// Adjust the value for the specified coordinate /// Adjust the value for the specified coordinate
/// @param vertexIndex Polygon point index to modify (0-based) /// @param vertexIndex Polygon point index to modify (0-based)
/// @param coordinate New coordinate for point /// @param coordinate New coordinate for point
Q_INVOKABLE void adjustCoordinate(int vertexIndex, const QGeoCoordinate coordinate); Q_INVOKABLE void adjustVertex(int vertexIndex, const QGeoCoordinate coordinate);
/// Splits the segment comprised of vertextIndex -> vertexIndex + 1
Q_INVOKABLE void splitPolygonSegment(int vertexIndex);
/// Returns the center point coordinate for the polygon /// Returns the center point coordinate for the polygon
Q_INVOKABLE QGeoCoordinate center(void) const; Q_INVOKABLE QGeoCoordinate center(void) const;
...@@ -49,9 +49,6 @@ public: ...@@ -49,9 +49,6 @@ public:
/// Returns true if the specified coordinate is within the polygon /// Returns true if the specified coordinate is within the polygon
Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate& coordinate) const; Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate& coordinate) const;
/// Returns the number of points in the polygon
Q_INVOKABLE int count(void) const { return _polygonPath.count(); }
/// Returns the path in a list of QGeoCoordinate's format /// Returns the path in a list of QGeoCoordinate's format
QList<QGeoCoordinate> coordinateList(void) const; QList<QGeoCoordinate> coordinateList(void) const;
...@@ -68,24 +65,35 @@ public: ...@@ -68,24 +65,35 @@ public:
// Property methods // Property methods
bool dirty(void) const { return _dirty; } int count (void) const { return _polygonPath.count(); }
void setDirty(bool dirty); bool dirty (void) const { return _dirty; }
void setDirty(bool dirty);
QVariantList path (void) const { return _polygonPath; }
QmlObjectListModel* qmlPathModel(void) { return &_polygonModel; }
QmlObjectListModel& pathModel (void) { return _polygonModel; }
QVariantList path(void) const { return _polygonPath; }
void setPath(const QList<QGeoCoordinate>& path); void setPath(const QList<QGeoCoordinate>& path);
void setPath(const QVariantList& path); void setPath(const QVariantList& path);
signals: signals:
void countChanged(int count);
void pathChanged(void); void pathChanged(void);
void dirtyChanged(bool dirty); void dirtyChanged(bool dirty);
private slots:
void _polygonModelCountChanged(int count);
void _polygonModelDirtyChanged(bool dirty);
private: private:
QPolygonF _toPolygonF(void) const; QPolygonF _toPolygonF(void) const;
QGeoCoordinate _coordFromPointF(const QPointF& point) const; QGeoCoordinate _coordFromPointF(const QPointF& point) const;
QPointF _pointFFromCoord(const QGeoCoordinate& coordinate) const; QPointF _pointFFromCoord(const QGeoCoordinate& coordinate) const;
QVariantList _polygonPath; QObject* _newCoordParent;
bool _dirty; QVariantList _polygonPath;
QmlObjectListModel _polygonModel;
bool _dirty;
static const char* _jsonPolygonKey; static const char* _jsonPolygonKey;
}; };
......
...@@ -40,7 +40,7 @@ RallyPointController::RallyPointController(QObject* parent) ...@@ -40,7 +40,7 @@ RallyPointController::RallyPointController(QObject* parent)
, _dirty(false) , _dirty(false)
, _currentRallyPoint(NULL) , _currentRallyPoint(NULL)
{ {
connect(&_points, &QmlObjectListModel::countChanged, this, &RallyPointController::_updateContainsItems);
} }
RallyPointController::~RallyPointController() RallyPointController::~RallyPointController()
...@@ -313,3 +313,18 @@ void RallyPointController::_setFirstPointCurrent(void) ...@@ -313,3 +313,18 @@ void RallyPointController::_setFirstPointCurrent(void)
{ {
setCurrentRallyPoint(_points.count() ? _points[0] : NULL); setCurrentRallyPoint(_points.count() ? _points[0] : NULL);
} }
bool RallyPointController::containsItems(void) const
{
return _points.count() > 0;
}
void RallyPointController::_updateContainsItems(void)
{
emit containsItemsChanged(containsItems());
}
void RallyPointController::removeAllFromVehicle(void)
{
_activeVehicle->rallyPointManager()->removeAll();
}
...@@ -37,16 +37,18 @@ public: ...@@ -37,16 +37,18 @@ public:
Q_INVOKABLE void addPoint(QGeoCoordinate point); Q_INVOKABLE void addPoint(QGeoCoordinate point);
Q_INVOKABLE void removePoint(QObject* rallyPoint); Q_INVOKABLE void removePoint(QObject* rallyPoint);
void loadFromVehicle (void) final; void loadFromVehicle (void) final;
void sendToVehicle (void) final; void sendToVehicle (void) final;
void loadFromFilePicker (void) final; void loadFromFilePicker (void) final;
void loadFromFile (const QString& filename) final; void loadFromFile (const QString& filename) final;
void saveToFilePicker (void) final; void saveToFilePicker (void) final;
void saveToFile (const QString& filename) final; void saveToFile (const QString& filename) final;
void removeAll (void) final; void removeAll (void) final;
bool syncInProgress (void) const final; void removeAllFromVehicle (void) final;
bool dirty (void) const final { return _dirty; } bool syncInProgress (void) const final;
void setDirty (bool dirty) final; bool dirty (void) const final { return _dirty; }
void setDirty (bool dirty) final;
bool containsItems (void) const final;
QString fileExtension(void) const final; QString fileExtension(void) const final;
...@@ -65,6 +67,7 @@ signals: ...@@ -65,6 +67,7 @@ signals:
private slots: private slots:
void _loadComplete(const QList<QGeoCoordinate> rgPoints); void _loadComplete(const QList<QGeoCoordinate> rgPoints);
void _setFirstPointCurrent(void); void _setFirstPointCurrent(void);
void _updateContainsItems(void);
private: private:
bool _loadJsonFile(QJsonDocument& jsonDoc, QString& errorString); bool _loadJsonFile(QJsonDocument& jsonDoc, QString& errorString);
......
...@@ -38,6 +38,8 @@ public: ...@@ -38,6 +38,8 @@ public:
/// Send the current settings to the vehicle /// Send the current settings to the vehicle
virtual void sendToVehicle(const QList<QGeoCoordinate>& rgPoints); virtual void sendToVehicle(const QList<QGeoCoordinate>& rgPoints);
virtual void removeAll(void) { };
virtual bool rallyPointsSupported(void) const { return false; } virtual bool rallyPointsSupported(void) const { return false; }
QList<QGeoCoordinate> points(void) const { return _rgPoints; } QList<QGeoCoordinate> points(void) const { return _rgPoints; }
......
...@@ -335,17 +335,8 @@ void SurveyMissionItem::save(QJsonArray& missionItems) ...@@ -335,17 +335,8 @@ void SurveyMissionItem::save(QJsonArray& missionItems)
} }
// Polygon shape // Polygon shape
QJsonArray polygonArray; QJsonArray polygonArray;
JsonHelper::savePolygon(_polygonModel, polygonArray);
for (int i=0; i<_polygonPath.count(); i++) {
const QVariant& polyVar = _polygonPath[i];
QJsonValue jsonValue;
JsonHelper::saveGeoCoordinate(polyVar.value<QGeoCoordinate>(), false /* writeAltitude */, jsonValue);
polygonArray += jsonValue;
}
saveObject[_jsonPolygonObjectKey] = polygonArray; saveObject[_jsonPolygonObjectKey] = polygonArray;
missionItems.append(saveObject); missionItems.append(saveObject);
...@@ -494,16 +485,12 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe ...@@ -494,16 +485,12 @@ bool SurveyMissionItem::load(const QJsonObject& complexObject, int sequenceNumbe
// Polygon shape // Polygon shape
QJsonArray polygonArray(v2Object[_jsonPolygonObjectKey].toArray()); QJsonArray polygonArray(v2Object[_jsonPolygonObjectKey].toArray());
for (int i=0; i<polygonArray.count(); i++) { if (!JsonHelper::loadPolygon(polygonArray, _polygonModel, this, errorString)) {
const QJsonValue& pointValue = polygonArray[i]; _clear();
return false;
QGeoCoordinate pointCoord; }
if (!JsonHelper::loadGeoCoordinate(pointValue, false /* altitudeRequired */, pointCoord, errorString)) { for (int i=0; i<_polygonModel.count(); i++) {
_clear(); _polygonPath << QVariant::fromValue(_polygonModel.value<QGCQGeoCoordinate*>(i)->coordinate());
return false;
}
_polygonPath << QVariant::fromValue(pointCoord);
_polygonModel.append(new QGCQGeoCoordinate(pointCoord, this));
} }
_generateGrid(); _generateGrid();
......
...@@ -10,6 +10,8 @@ ExclusiveGroupItem 1.0 ExclusiveGroupItem.qml ...@@ -10,6 +10,8 @@ ExclusiveGroupItem 1.0 ExclusiveGroupItem.qml
FactSliderPanel 1.0 FactSliderPanel.qml FactSliderPanel 1.0 FactSliderPanel.qml
FlightModeDropdown 1.0 FlightModeDropdown.qml FlightModeDropdown 1.0 FlightModeDropdown.qml
FlightModeMenu 1.0 FlightModeMenu.qml FlightModeMenu 1.0 FlightModeMenu.qml
GeoFenceEditor 1.0 GeoFenceEditor.qml
GeoFenceMapVisuals 1.0 GeoFenceMapVisuals.qml
GuidedBar 1.0 GuidedBar.qml GuidedBar 1.0 GuidedBar.qml
IndicatorButton 1.0 IndicatorButton.qml IndicatorButton 1.0 IndicatorButton.qml
JoystickThumbPad 1.0 JoystickThumbPad.qml JoystickThumbPad 1.0 JoystickThumbPad.qml
......
...@@ -33,7 +33,7 @@ public: ...@@ -33,7 +33,7 @@ public:
int count(void) const; int count(void) const;
bool dirty(void) { return _dirty; } bool dirty(void) const { return _dirty; }
void setDirty(bool dirty); void setDirty(bool dirty);
void append(QObject* object); void append(QObject* object);
......
...@@ -166,6 +166,7 @@ Vehicle::Vehicle(LinkInterface* link, ...@@ -166,6 +166,7 @@ Vehicle::Vehicle(LinkInterface* link,
connect(this, &Vehicle::_sendMessageOnLinkOnThread, this, &Vehicle::_sendMessageOnLink, Qt::QueuedConnection); connect(this, &Vehicle::_sendMessageOnLinkOnThread, this, &Vehicle::_sendMessageOnLink, Qt::QueuedConnection);
connect(this, &Vehicle::flightModeChanged, this, &Vehicle::_handleFlightModeChanged); connect(this, &Vehicle::flightModeChanged, this, &Vehicle::_handleFlightModeChanged);
connect(this, &Vehicle::armedChanged, this, &Vehicle::_announceArmedChanged); connect(this, &Vehicle::armedChanged, this, &Vehicle::_announceArmedChanged);
_uas = new UAS(_mavlink, this, _firmwarePluginManager); _uas = new UAS(_mavlink, this, _firmwarePluginManager);
connect(_uas, &UAS::imageReady, this, &Vehicle::_imageReady); connect(_uas, &UAS::imageReady, this, &Vehicle::_imageReady);
...@@ -317,14 +318,16 @@ void Vehicle::_commonInit(void) ...@@ -317,14 +318,16 @@ void Vehicle::_commonInit(void)
_firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType); _firmwarePlugin = _firmwarePluginManager->firmwarePluginForAutopilot(_firmwareType, _vehicleType);
_missionManager = new MissionManager(this); _missionManager = new MissionManager(this);
connect(_missionManager, &MissionManager::error, this, &Vehicle::_missionManagerError); connect(_missionManager, &MissionManager::error, this, &Vehicle::_missionManagerError);
connect(_missionManager, &MissionManager::newMissionItemsAvailable, this, &Vehicle::_newMissionItemsAvailable);
_parameterManager = new ParameterManager(this); _parameterManager = new ParameterManager(this);
connect(_parameterManager, &ParameterManager::parametersReadyChanged, this, &Vehicle::_parametersReady); connect(_parameterManager, &ParameterManager::parametersReadyChanged, this, &Vehicle::_parametersReady);
// GeoFenceManager needs to access ParameterManager so make sure to create after // GeoFenceManager needs to access ParameterManager so make sure to create after
_geoFenceManager = _firmwarePlugin->newGeoFenceManager(this); _geoFenceManager = _firmwarePlugin->newGeoFenceManager(this);
connect(_geoFenceManager, &GeoFenceManager::error, this, &Vehicle::_geoFenceManagerError); connect(_geoFenceManager, &GeoFenceManager::error, this, &Vehicle::_geoFenceManagerError);
connect(_geoFenceManager, &GeoFenceManager::loadComplete, this, &Vehicle::_newGeoFenceAvailable);
_rallyPointManager = _firmwarePlugin->newRallyPointManager(this); _rallyPointManager = _firmwarePlugin->newRallyPointManager(this);
connect(_rallyPointManager, &RallyPointManager::error, this, &Vehicle::_rallyPointManagerError); connect(_rallyPointManager, &RallyPointManager::error, this, &Vehicle::_rallyPointManagerError);
......
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