Commit 855da00e authored by DonLakeFlyer's avatar DonLakeFlyer
Browse files

Major work on GeoFence, clear mission on flight end

parent a25626fd
......@@ -27,7 +27,6 @@
<file alias="FlightDisplayViewUVC.qml">src/FlightDisplay/FlightDisplayViewUVC.qml</file>
<file alias="FlightModesComponentSummary.qml">src/AutoPilotPlugins/PX4/FlightModesComponentSummary.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="JoystickConfig.qml">src/VehicleSetup/JoystickConfig.qml</file>
<file alias="LinkSettings.qml">src/ui/preferences/LinkSettings.qml</file>
......@@ -57,6 +56,8 @@
<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/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/IndicatorButton.qml">src/QmlControls/IndicatorButton.qml</file>
<file alias="QGroundControl/Controls/JoystickThumbPad.qml">src/QmlControls/JoystickThumbPad.qml</file>
......
......@@ -13,6 +13,8 @@
#include "MAVLinkProtocol.h"
#include "QGCApplication.h"
#include "ParameterManager.h"
#include "QmlObjectListModel.h"
#include "QGCQGeoCoordinate.h"
const char* APMGeoFenceManager::_fenceTotalParam = "FENCE_TOTAL";
const char* APMGeoFenceManager::_fenceActionParam = "FENCE_ACTION";
......@@ -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()) {
return;
......@@ -61,21 +63,20 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, const
// Validate
int validatedPolygonCount = 0;
if (polygonEnabled()) {
if (polygon.count() >= 3) {
validatedPolygonCount = polygon.count();
}
if (polygon.count() > std::numeric_limits<uint8_t>::max()) {
_sendError(TooManyPoints, QStringLiteral("Geo-Fence polygon has too many points: %1.").arg(_polygon.count()));
validatedPolygonCount = 0;
}
if (polygon.count() >= 3) {
validatedPolygonCount = polygon.count();
}
if (polygon.count() > std::numeric_limits<uint8_t>::max()) {
_sendError(TooManyPoints, QStringLiteral("Geo-Fence polygon has too many points: %1.").arg(_polygon.count()));
validatedPolygonCount = 0;
}
_breachReturnPoint = breachReturn;
_polygon.clear();
if (validatedPolygonCount) {
_polygon = polygon;
} else {
_polygon.clear();
for (int i=0; i<polygon.count(); i++) {
_polygon.append(polygon.value<QGCQGeoCoordinate*>(i)->coordinate());
}
}
// Total point count, +1 polygon close in last index, +1 for breach in index 0
......@@ -306,7 +307,7 @@ void APMGeoFenceManager::_parametersReady(void)
float APMGeoFenceManager::circleRadius(void) const
{
if (_circleEnabled) {
if (_circleRadiusFact) {
return _circleRadiusFact->rawValue().toFloat();
} else {
return 0.0;
......@@ -328,3 +329,10 @@ QString APMGeoFenceManager::editorQml(void) const
return QStringLiteral("qrc:/FirmwarePlugin/NoGeoFenceEditor.qml");
}
}
void APMGeoFenceManager::removeAll(void)
{
QmlObjectListModel emptyPolygon;
sendToVehicle(_breachReturnPoint, emptyPolygon);
}
......@@ -14,6 +14,8 @@
#include "QGCMAVLink.h"
#include "FactSystem.h"
class QmlObjectListModel;
class APMGeoFenceManager : public GeoFenceManager
{
Q_OBJECT
......@@ -25,7 +27,7 @@ public:
// Overrides from GeoFenceManager
bool inProgress (void) const 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 polygonEnabled (void) const final { return _polygonEnabled; }
bool breachReturnEnabled (void) const final { return _breachReturnEnabled; }
......@@ -33,6 +35,7 @@ public:
QVariantList params (void) const final { return _params; }
QStringList paramLabels (void) const final { return _paramLabels; }
QString editorQml (void) const final;
void removeAll (void) final;
private slots:
void _mavlinkMessageReceived(const mavlink_message_t& message);
......
......@@ -149,3 +149,10 @@ bool APMRallyPointManager::rallyPointsSupported(void) const
{
return _vehicle->parameterManager()->parameterExists(_vehicle->defaultComponentId(), _rallyTotalParam);
}
void APMRallyPointManager::removeAll(void)
{
QList<QGeoCoordinate> noRallyPoints;
sendToVehicle(noRallyPoints);
}
......@@ -27,6 +27,8 @@ public:
void sendToVehicle (const QList<QGeoCoordinate>& rgPoints) final;
bool rallyPointsSupported (void) const final;
void removeAll (void);
QString editorQml(void) const final { return QStringLiteral("qrc:/FirmwarePlugin/APM/APMRallyPointEditor.qml"); }
private slots:
......
......@@ -24,7 +24,6 @@ Column {
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("Click in map to set breach return point.")
visible: geoFenceController.breachReturnSupported
}
QGCLabel { text: qsTr("Fence Settings:") }
......@@ -73,14 +72,15 @@ Column {
}
}
QGCMapPolygonControls {
anchors.left: parent.left
anchors.right: parent.right
flightMap: editorMap
polygon: geoFenceController.polygon
sectionLabel: qsTr("Fence Polygon:")
visible: geoFenceController.polygonSupported
QGCButton {
text: qsTr("Add fence")
visible: geoFenceController.mapPolygon.count < 3
onClicked: geoFenceController.addFence()
}
onPolygonEditCompleted: geoFenceController.validateBreachReturn()
QGCButton {
text: qsTr("Remove fence")
visible: geoFenceController.mapPolygon.count >= 3
onClicked: geoFenceController.removeFence()
}
}
......@@ -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.
*/
QGCMapPolygonControls {
anchors.left: parent.left
anchors.right: parent.right
flightMap: editorMap
polygon: geoFenceController.polygon
sectionLabel: qsTr("Fence Polygon:")
QGCButton {
text: qsTr("Add fence")
visible: geoFenceController.mapPolygon.count < 3
onClicked: geoFenceController.addFence()
}
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)
emit circleRadiusChanged(value.toFloat());
}
void PX4GeoFenceManager::removeAll(void)
{
// Only params so nothing to do
}
......@@ -28,6 +28,7 @@ public:
QVariantList params (void) const final { return _params; }
QStringList paramLabels (void) const final { return _paramLabels; }
QString editorQml (void) const final { return QStringLiteral("qrc:/FirmwarePlugin/PX4/PX4GeoFenceEditor.qml"); }
void removeAll (void) final;
private slots:
void _circleRadiusRawValueChanged(QVariant value);
......
......@@ -148,6 +148,7 @@ QGCView {
anchors.fill: parent
flightWidgets: flightDisplayViewWidgets
rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9
qgcView: root
}
}
......
......@@ -8,10 +8,11 @@
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtLocation 5.3
import QtPositioning 5.3
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtLocation 5.3
import QtPositioning 5.3
import QtQuick.Dialogs 1.2
import QGroundControl 1.0
import QGroundControl.FlightDisplay 1.0
......@@ -34,6 +35,7 @@ FlightMap {
property alias missionController: missionController
property var flightWidgets
property var rightPanelWidth
property var qgcView ///< QGCView control which contains this map
property bool _followVehicle: true
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
......@@ -77,6 +79,49 @@ FlightMap {
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 {
id: _mapTypeButtonsExclusiveGroup
}
......@@ -224,32 +269,11 @@ FlightMap {
model: _mainIsMap ? missionController.waypointLines : 0
}
// GeoFence polygon
MapPolygon {
border.color: "#80FF0000"
border.width: 3
path: geoFenceController.polygon.path
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
GeoFenceMapVisuals {
map: flightMap
myGeoFenceController: geoFenceController
interactive: false
homePosition: _activeVehicle && _activeVehicle.homePositionAvailable ? _activeVehicle.homePosition : undefined
}
// Rally points on map
......
......@@ -113,9 +113,9 @@ Item {
coordList.push(edgeCoordinate)
}
}
if (mapGeoFenceController.polygonEnabled && mapGeoFenceController.polygon.count() > 2) {
for (var i=0; i<mapGeoFenceController.polygon.count(); i++) {
coordList.push(mapGeoFenceController.polygon.path[i])
if (mapGeoFenceController.polygonEnabled && mapGeoFenceController.mapPolygon.path.count > 2) {
for (var i=0; i<mapGeoFenceController.mapPolygon.path.count; i++) {
coordList.push(mapGeoFenceController.mapPolygon.path[i])
}
}
}
......
......@@ -7,8 +7,9 @@
*
****************************************************************************/
#include "JsonHelper.h"
#include "QGCQGeoCoordinate.h"
#include "QmlObjectListModel.h"
#include <QJsonArray>
#include <QJsonParseError>
......@@ -308,3 +309,30 @@ QString JsonHelper::_jsonValueTypeToString(QJsonValue::Type 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 @@
#include <QVariantList>
#include <QGeoCoordinate>
class QmlObjectListModel;
class JsonHelper
{
public:
......@@ -52,6 +54,12 @@ public:
QGeoCoordinate& coordinate, ///< returned QGeoCordinate
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
static void saveGeoCoordinate(const QGeoCoordinate& coordinate, ///< QGeoCoordinate to save
bool writeAltitude, ///< true: write altitude to json
......@@ -76,6 +84,10 @@ public:
bool writeAltitude, ///< true: write altitide value
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);
......
......@@ -12,11 +12,16 @@ QGCFlickable {
contentHeight: geoFenceEditorRect.height
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 _margin: ScreenTools.defaultFontPixelWidth / 2
readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2
property var polygon: geoFenceController.polygon
property var polygon: myGeoFenceController.polygon
Rectangle {
id: geoFenceEditorRect
......@@ -60,9 +65,11 @@ QGCFlickable {
anchors.margins: _margin
anchors.top: geoLabel.bottom
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
}
}
}
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtLocation 5.3
import QtPositioning 5.3
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.FlightMap 1.0
/// Survey Complex Mission Item visuals
Item {
z: QGroundControl.zOrderMapItems
property var map
property var myGeoFenceController
property bool interactive: false ///< true: user can interact with items
property bool planView: false ///< true: visuals showing in plan view
property var homePosition
property var _polygonComponent
property var _dragHandles
property var _splitHandles
property var _breachReturnPointComponent
property var _mouseAreaComponent
property var _circleComponent
property var _mapPolygon: myGeoFenceController.mapPolygon
function _addVisualElements() {
_polygonComponent = polygonComponent.createObject(map)
map.addMapItem(_polygonComponent)
_circleComponent = circleComponent.createObject(map)
map.addMapItem(_circleComponent)
_breachReturnPointComponent = breachReturnPointComponent.createObject(map)
map.addMapItem(_breachReturnPointComponent)
_mouseAreaComponent = mouseAreaComponent.createObject(map)
}
function _destroyVisualElements() {
_polygonComponent.destroy()
_circleComponent.destroy()
_breachReturnPointComponent.destroy()
_mouseAreaComponent.destroy()
}
function _addDragHandles() {
if (!_dragHandles) {
_dragHandles = dragHandlesComponent.createObject(map)
}
if (!_splitHandles) {
_splitHandles = splitHandlesComponent.createObject(map)
}
}
function _destroyDragHandles() {
if (_dragHandles) {
_dragHandles.destroy()
_dragHandles = undefined
}
if (_splitHandles) {
_splitHandles.destroy()
_splitHandles = undefined
}
}
/// Add an initial 4 sided polygon if there is none
function _addInitialPolygon() {
// Initial polygon is inset to take 2/3rds space
var rect = map.centerViewport
rect.x += (rect.width * 0.25) / 2
rect.y += (rect.height * 0.25) / 2
rect.width *= 0.75
rect.height *= 0.75
var topLeft = Qt.point(rect.x, rect.y)
var topRight = Qt.point(rect.x + rect.width, rect.y)
var bottomLeft = Qt.point(rect.x, rect.y + rect.height)
var bottomRight = Qt.point(rect.x + rect.width, rect.y + rect.height)
_mapPolygon.clear()
_mapPolygon.appendVertex(map.toCoordinate(topLeft, false /* clipToViewPort */))
_mapPolygon.appendVertex(map.toCoordinate(topRight, false /* clipToViewPort */))
_mapPolygon.appendVertex(map.toCoordinate(bottomRight, false /* clipToViewPort */))
_mapPolygon.appendVertex(map.toCoordinate(bottomLeft, false /* clipToViewPort */))
}
Component.onCompleted: {
_addVisualElements()
_addDragHandles()
}
Component.onDestruction: {
_destroyVisualElements()
_destroyDragHandles()
}
Connections {
target: myGeoFenceController
onAddFencePolygon: {
_addInitialPolygon()
}
}
// Mouse area to capture breach return point coordinate
Component {
id: mouseAreaComponent
MouseArea {
anchors.fill: map
visible: interactive
onClicked: myGeoFenceController.breachReturnPoint = map.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
}
}
// GeoFence polygon
Component {
id: polygonComponent
MapPolygon {
z: QGroundControl.zOrderMapItems
border.width: 2
border.color: "orange"
color: "transparent"
opacity: 0.5
path: _mapPolygon.path
visible: planView || geoFenceController.polygonEnabled
}
}
// GeoFence circle
Component {
id: circleComponent
MapCircle {
z: QGroundControl.zOrderMapItems
border.width: 2
border.color: "orange"
color: "transparent"
center: homePosition ? homePosition : undefined
radius: myGeoFenceController.circleRadius
visible: planView || geoFenceController.circleEnabled
}
}
Component {
id: splitHandleComponent
MapQuickItem {
id: mapQuickItem
anchorPoint.x: dragHandle.width / 2
anchorPoint.y: dragHandle.height / 2
z: QGroundControl.zOrderMapItems + 1
visible: interactive
property int vertexIndex
sourceItem: Rectangle {
id: dragHandle
width: ScreenTools.defaultFontPixelHeight * 1.5
height: width
radius: width / 2
color: "white"
opacity: .50
QGCLabel {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "+"
}
QGCMouseArea {
fillItem: parent
onClicked: _mapPolygon.splitPolygonSegment(mapQuickItem.vertexIndex)
}
}
}
}
Component {
id: splitHandlesComponent
Repeater {
model: _mapPolygon.path.length > 2 ? _mapPolygon.path : 0
delegate: Item {
property var _splitHandle
property var _vertices: _mapPolygon.path
function _setHandlePosition() {
var nextIndex = index + 1
if (nextIndex > _vertices.length - 1) {
nextIndex = 0
}
var distance = _vertices[index].distanceTo(_vertices[nextIndex])
var azimuth = _vertices[index].azimuthTo(_vertices[nextIndex])
_splitHandle.coordinate = _vertices[index].atDistanceAndAzimuth(distance / 2, azimuth)
}
Component.onCompleted: {
_splitHandle = splitHandleComponent.createObject(map)
_splitHandle.vertexIndex = index
_setHandlePosition()
map.addMapItem(_splitHandle)
}
Component.onDestruction: {
_splitHandle.destroy()
}
}
}
}
// Control which is used to drag polygon vertices
Component {
id: dragAreaComponent
MissionItemIndicatorDrag {
id: dragArea
visible: interactive
property int polygonVertex
property bool _creationComplete: false
Component.onCompleted: _creationComplete = true
onItemCoordinateChanged: {
if (_creationComplete) {
// During component creation some bad coordinate values got through which screws up polygon draw
_mapPolygon.adjustVertex(polygonVertex, itemCoordinate)
}
}
onClicked: _mapPolygon.removePolygonVertex(polygonVertex)
}
}
Component {
id: dragHandleComponent
MapQuickItem {
id: mapQuickItem
anchorPoint.x: dragHandle.width / 2
anchorPoint.y: dragHandle.height / 2
z: QGroundControl.zOrderMapItems + 2
visible: interactive
sourceItem: Rectangle {
id: dragHandle
width: ScreenTools.defaultFontPixelHeight * 1.5
height: width
radius: width / 2
color: "white"
opacity: .90
}
}
}
// Add all polygon vertex drag handles to the map
Component {
id: dragHandlesComponent
Repeater {
model: _mapPolygon.pathModel
delegate: Item {
property var _visuals: [ ]
Component.onCompleted: {
var dragHandle = dragHandleComponent.createObject(map)
dragHandle.coordinate = Qt.binding(function() { return object.coordinate })
map.addMapItem(dragHandle)
var dragArea = dragAreaComponent.createObject(map, { "itemIndicator": dragHandle, "itemCoordinate": object.coordinate })
dragArea.polygonVertex = Qt.binding(function() { return index })
_visuals.push(dragHandle)
_visuals.push(dragArea)
}
Component.onDestruction: {
for (var i=0; i<_visuals.length; i++) {
_visuals[i].destroy()
}
_visuals = [ ]
}
}
}
}
// Breach return point
Component {
id: breachReturnPointComponent
MapQuickItem {
anchorPoint.x: sourceItem.anchorPointX
anchorPoint.y: sourceItem.anchorPointY
z: QGroundControl.zOrderMapItems
coordinate: myGeoFenceController.breachReturnPoint
sourceItem: MissionItemIndexLabel {
label: "B"
}
}
}
}
......@@ -129,9 +129,7 @@ QGCView {
mapFitFunctions.fitMapViewportToMissionItems()
}
onVisualItemsChanged: {
itemDragger.clearItem()
}
onVisualItemsChanged: itemDragger.clearItem()
onNewItemsFromVehicle: {
if (_visualItems && _visualItems.count != 1) {
......@@ -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() {
mapFitFunctions.fitMapViewportToFenceItems()
}
......@@ -393,12 +380,6 @@ QGCView {
insertSimpleMissionItem(coordinate, missionController.visualItems.count)
}
break
case _layerGeoFence:
if (geoFenceController.breachReturnEnabled) {
geoFenceController.breachReturnPoint = coordinate
geoFenceController.validateBreachReturn()
}
break
case _layerRallyPoints:
if (rallyPointController.rallyPointsSupported) {
rallyPointController.addPoint(coordinate)
......@@ -492,6 +473,7 @@ QGCView {
anchors.top: parent.top
anchors.leftMargin: parent.width - _rightPanelWidth
anchors.left: parent.left
z: QGroundControl.zOrderWidgets
spacing: _horizontalMargin
visible: QGroundControl.corePlugin.options.enablePlanViewSelector
......@@ -613,40 +595,20 @@ QGCView {
anchors.top: planElementSelectorRow.bottom
anchors.right: parent.right
opacity: _rightPanelOpacity
z: QGroundControl.zOrderTopMost
source: _editingLayer == _layerGeoFence ? "qrc:/qml/GeoFenceEditor.qml" : ""
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
}
z: QGroundControl.zOrderWidgets
sourceComponent: _editingLayer == _layerGeoFence ? geoFenceEditorComponent : undefined
// GeoFence circle
MapCircle {
border.color: "#80FF0000"
border.width: 3
center: missionController.plannedHomePosition
radius: geoFenceController.circleRadius
z: QGroundControl.zOrderMapItems
visible: geoFenceController.circleEnabled
property real availableWidth: _rightPanelWidth
property real availableHeight: ScreenTools.availableHeight
property var myGeoFenceController: geoFenceController
}
// 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
GeoFenceMapVisuals {
map: editorMap
myGeoFenceController: geoFenceController
interactive: _editingLayer == _layerGeoFence
homePosition: missionController.plannedHomePosition
planView: true
}
// Rally Point Editor
......@@ -997,4 +959,15 @@ QGCView {
}
} // Column
}
Component {
id: geoFenceEditorComponent
GeoFenceEditor {
availableWidth: _rightPanelWidth
availableHeight: ScreenTools.availableHeight
myGeoFenceController: geoFenceController
flightMap: editorMap
}
}
} // QGCVIew
......@@ -18,6 +18,7 @@
#include "QGCApplication.h"
#include "ParameterManager.h"
#include "JsonHelper.h"
#include "QGCQGeoCoordinate.h"
#ifndef __mobile__
#include "MainWindow.h"
......@@ -25,6 +26,7 @@
#endif
#include <QJsonDocument>
#include <QJsonArray>
QGC_LOGGING_CATEGORY(GeoFenceControllerLog, "GeoFenceControllerLog")
......@@ -34,8 +36,10 @@ const char* GeoFenceController::_jsonBreachReturnKey = "breachReturn";
GeoFenceController::GeoFenceController(QObject* parent)
: PlanElementController(parent)
, _dirty(false)
, _mapPolygon(this)
{
connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::countChanged, this, &GeoFenceController::_updateContainsItems);
connect(_mapPolygon.qmlPathModel(), &QmlObjectListModel::dirtyChanged, this, &GeoFenceController::_polygonDirtyChanged);
}
GeoFenceController::~GeoFenceController()
......@@ -61,7 +65,7 @@ void GeoFenceController::startStaticActiveVehicle(Vehicle* vehicle)
void GeoFenceController::_init(void)
{
connect(&_polygon, &QGCMapPolygon::dirtyChanged, this, &GeoFenceController::_polygonDirtyChanged);
}
void GeoFenceController::setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint)
......@@ -139,13 +143,11 @@ bool GeoFenceController::_loadJsonFile(QJsonDocument& jsonDoc, QString& errorStr
}
if (polygonEnabled()) {
if (!_polygon.loadFromJson(json, false /* reauired */, errorString)) {
if (!_mapPolygon.loadFromJson(json, true, errorString)) {
return false;
}
} else {
_polygon.clear();
}
_polygon.setDirty(false);
_mapPolygon.setDirty(false);
return true;
}
......@@ -289,7 +291,7 @@ void GeoFenceController::saveToFile(const QString& filename)
}
if (polygonEnabled()) {
_polygon.saveToJson(fenceFileObject);
_mapPolygon.saveToJson(fenceFileObject);
}
QJsonDocument saveDoc(fenceFileObject);
......@@ -314,7 +316,7 @@ void GeoFenceController::saveToFilePicker(void)
void GeoFenceController::removeAll(void)
{
setBreachReturnPoint(QGeoCoordinate());
_polygon.clear();
_mapPolygon.clear();
}
void GeoFenceController::loadFromVehicle(void)
......@@ -329,8 +331,8 @@ void GeoFenceController::loadFromVehicle(void)
void GeoFenceController::sendToVehicle(void)
{
if (_activeVehicle->parameterManager()->parametersReady() && !syncInProgress()) {
_activeVehicle->geoFenceManager()->sendToVehicle(_breachReturnPoint, _polygon.coordinateList());
_polygon.setDirty(false);
_activeVehicle->geoFenceManager()->sendToVehicle(_breachReturnPoint, _mapPolygon.pathModel());
_mapPolygon.setDirty(false);
setDirty(false);
} else {
qCWarning(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle call at wrong time" << _activeVehicle->parameterManager()->parametersReady() << syncInProgress();
......@@ -344,7 +346,7 @@ bool GeoFenceController::syncInProgress(void) const
bool GeoFenceController::dirty(void) const
{
return _dirty | _polygon.dirty();
return _dirty;
}
......@@ -353,7 +355,7 @@ void GeoFenceController::setDirty(bool dirty)
if (dirty != _dirty) {
_dirty = dirty;
if (!dirty) {
_polygon.setDirty(dirty);
_mapPolygon.setDirty(dirty);
}
emit dirtyChanged(dirty);
}
......@@ -388,9 +390,11 @@ void GeoFenceController::_setDirty(void)
void GeoFenceController::_setPolygonFromManager(const QList<QGeoCoordinate>& polygon)
{
_polygon.setPath(polygon);
_polygon.setDirty(false);
emit polygonPathChanged(_polygon.path());
_mapPolygon.clear();
for (int i=0; i<polygon.count(); i++) {
_mapPolygon.appendVertex(polygon[i]);
}
_mapPolygon.setDirty(false);
}
void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint)
......@@ -431,3 +435,30 @@ QString GeoFenceController::fileExtension(void) const
{
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
public:
GeoFenceController(QObject* parent = NULL);
~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(QGCMapPolygon* polygon READ polygon CONSTANT)
Q_PROPERTY(bool circleEnabled READ circleEnabled NOTIFY circleEnabledChanged)
Q_PROPERTY(float circleRadius READ circleRadius NOTIFY circleRadiusChanged)
Q_PROPERTY(bool breachReturnEnabled READ breachReturnEnabled NOTIFY breachReturnEnabledChanged)
Q_PROPERTY(QGeoCoordinate breachReturnPoint READ breachReturnPoint WRITE setBreachReturnPoint NOTIFY breachReturnPointChanged)
Q_PROPERTY(bool polygonEnabled READ polygonEnabled NOTIFY polygonEnabledChanged)
Q_PROPERTY(QGCMapPolygon* mapPolygon READ mapPolygon CONSTANT)
Q_PROPERTY(QVariantList params READ params NOTIFY paramsChanged)
Q_PROPERTY(QStringList paramLabels READ paramLabels NOTIFY paramLabelsChanged)
Q_PROPERTY(QString editorQml READ editorQml NOTIFY editorQmlChanged)
Q_PROPERTY(bool breachReturnEnabled READ breachReturnEnabled NOTIFY breachReturnEnabledChanged)
Q_PROPERTY(QGeoCoordinate breachReturnPoint READ breachReturnPoint WRITE setBreachReturnPoint NOTIFY breachReturnPointChanged)
#if 0
Q_PROPERTY(bool fenceSupported READ fenceSupported NOTIFY fenceSupportedChanged)
Q_PROPERTY(bool fenceEnabled READ fenceEnabled NOTIFY fenceEnabledChanged)
Q_PROPERTY(bool circleSupported READ circleSupported NOTIFY circleSupportedChanged)
Q_PROPERTY(bool polygonSupported READ polygonSupported NOTIFY polygonSupportedChanged)
Q_PROPERTY(bool breachReturnSupported READ breachReturnSupported NOTIFY breachReturnSupportedChanged)
#endif
Q_PROPERTY(QVariantList params READ params NOTIFY paramsChanged)
Q_PROPERTY(QStringList paramLabels READ paramLabels NOTIFY paramLabelsChanged)
Q_PROPERTY(QString editorQml READ editorQml NOTIFY editorQmlChanged)
Q_INVOKABLE void addFence(void);
Q_INVOKABLE void removeFence(void);
void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final;
......@@ -59,9 +54,11 @@ public:
void saveToFilePicker (void) final;
void saveToFile (const QString& filename) final;
void removeAll (void) final;
void removeAllFromVehicle (void) final;
bool syncInProgress (void) const final;
bool dirty (void) const final;
void setDirty (bool dirty) final;
bool containsItems (void) const final;
QString fileExtension(void) const final;
......@@ -69,7 +66,7 @@ public:
bool polygonEnabled (void) const;
bool breachReturnEnabled (void) const;
float circleRadius (void) const;
QGCMapPolygon* polygon (void) { return &_polygon; }
QGCMapPolygon* mapPolygon (void) { return &_mapPolygon; }
QGeoCoordinate breachReturnPoint (void) const { return _breachReturnPoint; }
QVariantList params (void) const;
QStringList paramLabels (void) const;
......@@ -78,11 +75,11 @@ public:
void setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint);
signals:
void addFencePolygon (void);
void circleEnabledChanged (bool circleEnabled);
void polygonEnabledChanged (bool polygonEnabled);
void breachReturnEnabledChanged (bool breachReturnEnabled);
void circleRadiusChanged (float circleRadius);
void polygonPathChanged (const QVariantList& polygonPath);
void breachReturnPointChanged (QGeoCoordinate breachReturnPoint);
void paramsChanged (QVariantList params);
void paramLabelsChanged (QStringList paramLabels);
......@@ -95,6 +92,7 @@ private slots:
void _setPolygonFromManager(const QList<QGeoCoordinate>& polygon);
void _setReturnPointFromManager(QGeoCoordinate breachReturnPoint);
void _loadComplete(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon);
void _updateContainsItems(void);
private:
void _init(void);
......@@ -105,7 +103,7 @@ private:
void _activeVehicleSet(void) final;
bool _dirty;
QGCMapPolygon _polygon;
QGCMapPolygon _mapPolygon;
QGeoCoordinate _breachReturnPoint;
QVariantList _params;
......
......@@ -9,6 +9,7 @@
#include "GeoFenceManager.h"
#include "Vehicle.h"
#include "QmlObjectListModel.h"
QGC_LOGGING_CATEGORY(GeoFenceManagerLog, "GeoFenceManagerLog")
......@@ -37,7 +38,7 @@ void GeoFenceManager::loadFromVehicle(void)
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(polygon);
......
Supports Markdown
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