Commit fb9b1767 authored by Valentin Platzgummer's avatar Valentin Platzgummer

plan creator added, area editor improved

parent 42fe8ce4
...@@ -195,5 +195,6 @@ ...@@ -195,5 +195,6 @@
<file alias="Yield.svg">src/ui/toolbar/Images/Yield.svg</file> <file alias="Yield.svg">src/ui/toolbar/Images/Yield.svg</file>
<file alias="ZoomMinus.svg">src/FlightMap/Images/ZoomMinus.svg</file> <file alias="ZoomMinus.svg">src/FlightMap/Images/ZoomMinus.svg</file>
<file alias="ZoomPlus.svg">src/FlightMap/Images/ZoomPlus.svg</file> <file alias="ZoomPlus.svg">src/FlightMap/Images/ZoomPlus.svg</file>
<file alias="PlanCreator/MeasurementPlanCreator.png">src/MeasurementComplexItem/MeasurementPlanCreator.png</file>
</qresource> </qresource>
</RCC> </RCC>
...@@ -447,6 +447,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) { ...@@ -447,6 +447,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
HEADERS += \ HEADERS += \
src/MeasurementComplexItem/IDArray.h \ src/MeasurementComplexItem/IDArray.h \
src/MeasurementComplexItem/LogicalArray.h \ src/MeasurementComplexItem/LogicalArray.h \
src/MeasurementComplexItem/MeasurementPlanCreator.h \
src/MeasurementComplexItem/TileArray.h \ src/MeasurementComplexItem/TileArray.h \
src/MeasurementComplexItem/TilePtrArray.h \ src/MeasurementComplexItem/TilePtrArray.h \
src/MeasurementComplexItem/geometry/ProgressArray.h \ src/MeasurementComplexItem/geometry/ProgressArray.h \
...@@ -527,6 +528,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) { ...@@ -527,6 +528,7 @@ contains (DEFINES, QGC_ENABLE_PAIRING) {
} }
SOURCES += \ SOURCES += \
src/MeasurementComplexItem/MeasurementPlanCreator.cpp \
src/MeasurementComplexItem/geometry/GeoArea.cc \ src/MeasurementComplexItem/geometry/GeoArea.cc \
src/MeasurementComplexItem/geometry/MeasurementArea.cc \ src/MeasurementComplexItem/geometry/MeasurementArea.cc \
src/MeasurementComplexItem/geometry/SafeArea.cc \ src/MeasurementComplexItem/geometry/SafeArea.cc \
......
#include "MeasurementPlanCreator.h"
#include "MeasurementComplexItem.h"
#include "PlanMasterController.h"
MeasurementPlanCreator::MeasurementPlanCreator(
PlanMasterController *planMasterController, QObject *parent)
: PlanCreator(
planMasterController, MeasurementComplexItem::name,
QStringLiteral("/qmlimages/PlanCreator/MeasurementPlanCreator.png"),
parent) {}
void MeasurementPlanCreator::createPlan(const QGeoCoordinate &mapCenterCoord) {
_planMasterController->removeAll();
VisualMissionItem *takeoffItem =
_missionController->insertTakeoffItem(mapCenterCoord, -1);
_missionController->insertComplexMissionItem(MeasurementComplexItem::name,
mapCenterCoord, -1);
_missionController->insertLandItem(mapCenterCoord, -1);
_missionController->setCurrentPlanViewSeqNum(takeoffItem->sequenceNumber(),
true);
}
#ifndef MEASUREMENTCOMPLEXITEMPLANCREATOR_H
#define MEASUREMENTCOMPLEXITEMPLANCREATOR_H
#include "PlanCreator.h"
class MeasurementPlanCreator : public PlanCreator {
Q_OBJECT
public:
MeasurementPlanCreator(PlanMasterController *planMasterController,
QObject *parent = nullptr);
Q_INVOKABLE void createPlan(const QGeoCoordinate &mapCenterCoord) final;
};
#endif // MEASUREMENTCOMPLEXITEMPLANCREATOR_H
...@@ -251,7 +251,7 @@ std::shared_future<QVariant> ...@@ -251,7 +251,7 @@ std::shared_future<QVariant>
NemoInterface::Impl::addTiles(const TilePtrArray &tileArray) { NemoInterface::Impl::addTiles(const TilePtrArray &tileArray) {
using namespace nemo_interface; using namespace nemo_interface;
qDebug() << "addTiles called"; // qDebug() << "addTiles called";
if (tileArray.size() > 0) { if (tileArray.size() > 0) {
...@@ -318,7 +318,7 @@ std::shared_future<QVariant> ...@@ -318,7 +318,7 @@ std::shared_future<QVariant>
NemoInterface::Impl::removeTiles(const IDArray &idArray) { NemoInterface::Impl::removeTiles(const IDArray &idArray) {
using namespace nemo_interface; using namespace nemo_interface;
qDebug() << "removeTiles called"; // qDebug() << "removeTiles called";
if (idArray.size() > 0) { if (idArray.size() > 0) {
...@@ -364,7 +364,7 @@ NemoInterface::Impl::removeTiles(const IDArray &idArray) { ...@@ -364,7 +364,7 @@ NemoInterface::Impl::removeTiles(const IDArray &idArray) {
std::shared_future<QVariant> NemoInterface::Impl::clearTiles() { std::shared_future<QVariant> NemoInterface::Impl::clearTiles() {
using namespace nemo_interface; using namespace nemo_interface;
qDebug() << "clearTiles called"; // qDebug() << "clearTiles called";
// clear local tiles (_localTiles) // clear local tiles (_localTiles)
if (!_localTiles.empty()) { if (!_localTiles.empty()) {
...@@ -396,6 +396,18 @@ std::shared_future<QVariant> NemoInterface::Impl::clearTiles() { ...@@ -396,6 +396,18 @@ std::shared_future<QVariant> NemoInterface::Impl::clearTiles() {
TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const { TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const {
TileArray tileArray; TileArray tileArray;
if (this->ready()) {
for (const auto &id : idArray) {
const auto it = _remoteTiles.find(id);
if (it != _remoteTiles.end()) {
MeasurementTile copy;
copy.setId(it->second->id());
copy.setProgress(it->second->progress());
copy.setPath(it->second->tile());
tileArray.append(std::move(copy));
}
}
} else {
for (const auto &id : idArray) { for (const auto &id : idArray) {
const auto it = _localTiles.find(id); const auto it = _localTiles.find(id);
if (it != _localTiles.end()) { if (it != _localTiles.end()) {
...@@ -406,6 +418,7 @@ TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const { ...@@ -406,6 +418,7 @@ TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const {
tileArray.append(std::move(copy)); tileArray.append(std::move(copy));
} }
} }
}
return tileArray; return tileArray;
} }
...@@ -413,6 +426,17 @@ TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const { ...@@ -413,6 +426,17 @@ TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) const {
TileArray NemoInterface::Impl::getAllTiles() const { TileArray NemoInterface::Impl::getAllTiles() const {
TileArray tileArray; TileArray tileArray;
if (this->ready()) {
for (const auto &entry : _remoteTiles) {
auto pTile = entry.second;
MeasurementTile copy;
copy.setId(pTile->id());
copy.setProgress(pTile->progress());
copy.setPath(pTile->tile());
tileArray.append(std::move(copy));
}
} else {
for (const auto &entry : _localTiles) { for (const auto &entry : _localTiles) {
auto pTile = entry.second; auto pTile = entry.second;
MeasurementTile copy; MeasurementTile copy;
...@@ -421,6 +445,7 @@ TileArray NemoInterface::Impl::getAllTiles() const { ...@@ -421,6 +445,7 @@ TileArray NemoInterface::Impl::getAllTiles() const {
copy.setPath(pTile->tile()); copy.setPath(pTile->tile());
tileArray.append(std::move(copy)); tileArray.append(std::move(copy));
} }
}
return tileArray; return tileArray;
} }
...@@ -518,7 +543,7 @@ const QString &NemoInterface::Impl::warningString() const { ...@@ -518,7 +543,7 @@ const QString &NemoInterface::Impl::warningString() const {
void NemoInterface::Impl::_updateProgress(std::shared_ptr<ProgressArray> pArray, void NemoInterface::Impl::_updateProgress(std::shared_ptr<ProgressArray> pArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_updateProgress called"; // qDebug() << "_updateProgress called";
bool error = false; bool error = false;
for (auto itLP = pArray->begin(); itLP != pArray->end();) { for (auto itLP = pArray->begin(); itLP != pArray->end();) {
...@@ -799,7 +824,7 @@ void NemoInterface::Impl::_doAction() { ...@@ -799,7 +824,7 @@ void NemoInterface::Impl::_doAction() {
QVariant NemoInterface::Impl::_callAddTiles( QVariant NemoInterface::Impl::_callAddTiles(
std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray) { std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray) {
qDebug() << "_callAddTiles called"; // qDebug() << "_callAddTiles called";
this->_lastCall = CALL_NAME::ADD_TILES; this->_lastCall = CALL_NAME::ADD_TILES;
...@@ -900,7 +925,7 @@ QVariant NemoInterface::Impl::_callAddTiles( ...@@ -900,7 +925,7 @@ QVariant NemoInterface::Impl::_callAddTiles(
QVariant QVariant
NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) { NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) {
qDebug() << "_callRemoveTiles called"; // qDebug() << "_callRemoveTiles called";
this->_lastCall = CALL_NAME::REMOVE_TILES; this->_lastCall = CALL_NAME::REMOVE_TILES;
...@@ -995,7 +1020,7 @@ NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) { ...@@ -995,7 +1020,7 @@ NemoInterface::Impl::_callRemoveTiles(std::shared_ptr<IDArray> pIdArray) {
QVariant NemoInterface::Impl::_callClearTiles() { QVariant NemoInterface::Impl::_callClearTiles() {
qDebug() << "_callClearTiles called"; // qDebug() << "_callClearTiles called";
this->_lastCall = CALL_NAME::CLEAR_TILES; this->_lastCall = CALL_NAME::CLEAR_TILES;
// create response handler. // create response handler.
...@@ -1068,7 +1093,7 @@ QVariant NemoInterface::Impl::_callClearTiles() { ...@@ -1068,7 +1093,7 @@ QVariant NemoInterface::Impl::_callClearTiles() {
QVariant QVariant
NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) { NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) {
qDebug() << "_callGetProgress called"; // qDebug() << "_callGetProgress called";
this->_lastCall = CALL_NAME::GET_PROGRESS; this->_lastCall = CALL_NAME::GET_PROGRESS;
...@@ -1168,7 +1193,7 @@ NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) { ...@@ -1168,7 +1193,7 @@ NemoInterface::Impl::_callGetProgress(std::shared_ptr<IDArray> pIdArray) {
} }
QVariant NemoInterface::Impl::_callGetAllProgress() { QVariant NemoInterface::Impl::_callGetAllProgress() {
qDebug() << "_callGetAllProgress called"; // qDebug() << "_callGetAllProgress called";
this->_lastCall = CALL_NAME::GET_ALL_PROGRESS; this->_lastCall = CALL_NAME::GET_ALL_PROGRESS;
...@@ -1279,7 +1304,7 @@ void NemoInterface::Impl::_addTilesRemote( ...@@ -1279,7 +1304,7 @@ void NemoInterface::Impl::_addTilesRemote(
std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray, std::shared_ptr<QVector<std::shared_ptr<const Tile>>> pTileArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_addTilesRemote called"; // qDebug() << "_addTilesRemote called";
auto pArrayDup = std::make_shared<QVector<std::shared_ptr<Tile>>>(); auto pArrayDup = std::make_shared<QVector<std::shared_ptr<Tile>>>();
for (auto pTile : *pTileArray) { for (auto pTile : *pTileArray) {
...@@ -1292,7 +1317,7 @@ void NemoInterface::Impl::_addTilesRemote2( ...@@ -1292,7 +1317,7 @@ void NemoInterface::Impl::_addTilesRemote2(
std::shared_ptr<QVector<std::shared_ptr<Tile>>> pTileArray, std::shared_ptr<QVector<std::shared_ptr<Tile>>> pTileArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_addTilesRemote2 called"; // qDebug() << "_addTilesRemote2 called";
bool anyChange = false; bool anyChange = false;
bool error = false; bool error = false;
...@@ -1326,7 +1351,7 @@ void NemoInterface::Impl::_addTilesRemote2( ...@@ -1326,7 +1351,7 @@ void NemoInterface::Impl::_addTilesRemote2(
void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray, void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray,
std::promise<bool> promise) { std::promise<bool> promise) {
qDebug() << "_removeTilesRemote called"; // qDebug() << "_removeTilesRemote called";
bool anyChange = false; bool anyChange = false;
for (const auto id : *idArray) { for (const auto id : *idArray) {
...@@ -1351,7 +1376,7 @@ void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray, ...@@ -1351,7 +1376,7 @@ void NemoInterface::Impl::_removeTilesRemote(std::shared_ptr<IDArray> idArray,
} }
void NemoInterface::Impl::_clearTilesRemote(std::promise<bool> promise) { void NemoInterface::Impl::_clearTilesRemote(std::promise<bool> promise) {
qDebug() << "_clearTilesRemote called"; // qDebug() << "_clearTilesRemote called";
if (_remoteTiles.size() > 0) { if (_remoteTiles.size() > 0) {
_remoteTiles.clear(); _remoteTiles.clear();
if (this->_isSynchronized()) { if (this->_isSynchronized()) {
......
...@@ -12,44 +12,62 @@ import QGroundControl.Palette 1.0 ...@@ -12,44 +12,62 @@ import QGroundControl.Palette 1.0
Rectangle { Rectangle {
id: _root id: _root
width: mainGrid.width width: mainColumn.width
height: mainGrid.height height: mainColumn.height
color: qgcPal.windowShadeDark color: qgcPal.windowShadeDark
property bool checked: true property bool editing: missionItem.editing
property var missionItem: undefined property var missionItem: undefined
property int availableWidth: 300 property int availableWidth: 300
property bool areasCorrect: false property bool areasCorrect: false
property string errorString: "" property string errorString: ""
signal abort
property var _areaData: missionItem.areaData property var _areaData: missionItem.areaData
property real _margin: ScreenTools.defaultFontPixelWidth / 2 property real _margin: ScreenTools.defaultFontPixelWidth / 2
Component.onCompleted: { Component.onCompleted: {
console.assert(missionItem !== undefined, console.assert(missionItem !== undefined,
"please set the missionItem property") "please set the missionItem property")
if (checked) { if (editing) {
areasCorrectTimer.start() areasCorrectTimer.start()
} }
} }
onCheckedChanged: { onEditingChanged: {
if (checked) { if (editing){
areasCorrectTimer.start() areasCorrectTimer.start()
} else { } else {
areasCorrectTimer.stop() areasCorrectTimer.stop()
} }
} }
ColumnLayout {
id: mainColumn
width: availableWidth
spacing: _margin
QGCButton {
id: editButton
text: _root.editing ? qsTr("Done") : qsTr("Edit")
enabled: (_root.editing && _root.areasCorrect) || !_root.editing
onClicked: {
if (_root.editing) {
_root.missionItem.stopEditing()
} else {
_root.missionItem.startEditing()
}
}
Layout.fillWidth: true
}
GridLayout { GridLayout {
id: mainGrid
width: availableWidth width: availableWidth
columnSpacing: _margin columnSpacing: _margin
Layout.fillWidth: true
rowSpacing: _margin rowSpacing: _margin
columns: 2 columns: 2
enabled: _root.editing
QGCLabel { QGCLabel {
text: _root.errorString text: _root.errorString
...@@ -73,7 +91,6 @@ Rectangle { ...@@ -73,7 +91,6 @@ Rectangle {
model: _missionItem.areaData.areaList model: _missionItem.areaData.areaList
delegate: QGCRadioButton { delegate: QGCRadioButton {
text: object.objectName text: object.objectName
checkable: _root.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
...@@ -88,7 +105,7 @@ Rectangle { ...@@ -88,7 +105,7 @@ Rectangle {
checked = true checked = true
} }
object.interactive = Qt.binding(function () { object.interactive = Qt.binding(function () {
return checked && _root.checked return checked && _root.editing && _missionItem.isCurrentItem
}) })
} }
} }
...@@ -116,19 +133,22 @@ Rectangle { ...@@ -116,19 +133,22 @@ Rectangle {
Component.onCompleted: { Component.onCompleted: {
if (geoArea.editorQML && !_visualItem) { if (geoArea.editorQML && !_visualItem) {
var component = Qt.createComponent(geoArea.editorQML) var component = Qt.createComponent(
geoArea.editorQML)
if (component.status === Component.Error) { if (component.status === Component.Error) {
console.log("Error loading Qml: ", console.log("Error loading Qml: ",
geoArea.editorQML, geoArea.editorQML,
component.errorString()) component.errorString())
} else { } else {
_visualItem = component.createObject(editorParent, { _visualItem = component.createObject(
editorParent, {
"geoArea": editor.geoArea, "geoArea": editor.geoArea,
"visible": Qt.binding( "visible": Qt.binding(
function () { function () {
return editor.visible return editor.visible
}), }),
"availableWidth": Qt.binding(function () { "availableWidth": Qt.binding(
function () {
return editorParent.width return editorParent.width
}) })
}) })
...@@ -161,7 +181,6 @@ Rectangle { ...@@ -161,7 +181,6 @@ Rectangle {
QGCButton { QGCButton {
text: "Intersection" text: "Intersection"
enabled: _root.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: parent.columns Layout.columnSpan: parent.columns
onClicked: { onClicked: {
...@@ -171,18 +190,11 @@ Rectangle { ...@@ -171,18 +190,11 @@ Rectangle {
QGCButton { QGCButton {
text: "Reset" text: "Reset"
onClicked: {
missionItem.reset()
}
Layout.fillWidth: true Layout.fillWidth: true
} Layout.columnSpan: parent.columns
QGCButton {
text: "Abort"
onClicked: { onClicked: {
_root.abort() missionItem.reset()
} }
Layout.fillWidth: true
} }
} }
...@@ -235,4 +247,5 @@ Use the Abort button to reset the areas and leave the tab.") ...@@ -235,4 +247,5 @@ Use the Abort button to reset the areas and leave the tab.")
property alias showHint: hintHeader.checked property alias showHint: hintHeader.checked
} }
} // GridLayout } // GridLayout
} // GridLayout
} // Rectangle } // Rectangle
...@@ -49,13 +49,12 @@ Rectangle { ...@@ -49,13 +49,12 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
enabled: !editing || editing && correct enabled: !editing
readonly property int areaEditorIndex: 0 readonly property int areaEditorIndex: 0
readonly property int parameterEditorIndex: 1 readonly property int parameterEditorIndex: 1
readonly property int nemoEditorIndex: 2 readonly property int nemoEditorIndex: 2
property bool editing: _missionItem.editing property bool editing: _missionItem.editing
property bool correct: false
Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex Component.onCompleted: currentIndex = editing ? areaEditorIndex : parameterEditorIndex
...@@ -71,47 +70,18 @@ Rectangle { ...@@ -71,47 +70,18 @@ Rectangle {
icon.source: "qrc:/res/fish.svg" icon.source: "qrc:/res/fish.svg"
icon.height: ScreenTools.defaultFontPixelHeight icon.height: ScreenTools.defaultFontPixelHeight
} }
onEditingChanged: {
if (editing) {
areasCorrectTimer.start()
} else {
areasCorrectTimer.stop()
}
}
onCurrentIndexChanged: {
if (currentIndex === areaEditorIndex) {
_missionItem.startEditing()
} else {
_missionItem.stopEditing()
}
}
Timer {
id: areasCorrectTimer
running: false
interval: 100
repeat: true
onTriggered: {
tabBar.correct = _missionItem.areaData.isCorrect(
false /*show gui message*/
)
}
}
} }
MCI.AreaDataEditor { MCI.AreaDataEditor {
id: areaEditor id: areaEditor
visible: tabBar.currentIndex === tabBar.areaEditorIndex visible: tabBar.currentIndex === tabBar.areaEditorIndex
checked: visible
missionItem: _root._missionItem missionItem: _root._missionItem
availableWidth: mainColumn.width availableWidth: mainColumn.width
onAbort: { onVisibleChanged:{
missionItem.abortEditing() if (visible){
tabBar.currentIndex = tabBar.parameterEditorIndex _missionItem.startEditing()
}
} }
} }
...@@ -119,7 +89,6 @@ Rectangle { ...@@ -119,7 +89,6 @@ Rectangle {
id: parameterEditor id: parameterEditor
visible: tabBar.currentIndex === tabBar.parameterEditorIndex visible: tabBar.currentIndex === tabBar.parameterEditorIndex
checked: visible
missionItem: _root._missionItem missionItem: _root._missionItem
availableWidth: mainColumn.width availableWidth: mainColumn.width
} }
...@@ -128,7 +97,6 @@ Rectangle { ...@@ -128,7 +97,6 @@ Rectangle {
id: nemoEditor id: nemoEditor
visible: tabBar.currentIndex === tabBar.nemoEditorIndex visible: tabBar.currentIndex === tabBar.nemoEditorIndex
checked: visible
missionItem: _root._missionItem missionItem: _root._missionItem
availableWidth: mainColumn.width availableWidth: mainColumn.width
} }
......
...@@ -8,106 +8,116 @@ ...@@ -8,106 +8,116 @@
****************************************************************************/ ****************************************************************************/
#include "PlanMasterController.h" #include "PlanMasterController.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
#include "MultiVehicleManager.h"
#include "SettingsManager.h"
#include "AppSettings.h" #include "AppSettings.h"
#include "BlankPlanCreator.h"
#include "CorridorScanPlanCreator.h"
#include "JsonHelper.h" #include "JsonHelper.h"
#include "MissionManager.h"
#include "KMLPlanDomDocument.h" #include "KMLPlanDomDocument.h"
#include "SurveyPlanCreator.h" #include "MeasurementPlanCreator.h"
#include "MissionManager.h"
#include "MultiVehicleManager.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
#include "SettingsManager.h"
#include "StructureScanPlanCreator.h" #include "StructureScanPlanCreator.h"
#include "CorridorScanPlanCreator.h" #include "SurveyPlanCreator.h"
#include "BlankPlanCreator.h"
#if defined(QGC_AIRMAP_ENABLED) #if defined(QGC_AIRMAP_ENABLED)
#include "AirspaceFlightPlanProvider.h" #include "AirspaceFlightPlanProvider.h"
#endif #endif
#include <QDomDocument> #include <QDomDocument>
#include <QJsonDocument>
#include <QFileInfo> #include <QFileInfo>
#include <QJsonDocument>
QGC_LOGGING_CATEGORY(PlanMasterControllerLog, "PlanMasterControllerLog") QGC_LOGGING_CATEGORY(PlanMasterControllerLog, "PlanMasterControllerLog")
const int PlanMasterController::kPlanFileVersion = 1; const int PlanMasterController::kPlanFileVersion = 1;
const char* PlanMasterController::kPlanFileType = "Plan"; const char *PlanMasterController::kPlanFileType = "Plan";
const char* PlanMasterController::kJsonMissionObjectKey = "mission"; const char *PlanMasterController::kJsonMissionObjectKey = "mission";
const char* PlanMasterController::kJsonGeoFenceObjectKey = "geoFence"; const char *PlanMasterController::kJsonGeoFenceObjectKey = "geoFence";
const char* PlanMasterController::kJsonRallyPointsObjectKey = "rallyPoints"; const char *PlanMasterController::kJsonRallyPointsObjectKey = "rallyPoints";
PlanMasterController::PlanMasterController(QObject* parent) PlanMasterController::PlanMasterController(QObject *parent)
: QObject (parent) : QObject(parent),
, _multiVehicleMgr (qgcApp()->toolbox()->multiVehicleManager()) _multiVehicleMgr(qgcApp()->toolbox()->multiVehicleManager()),
, _controllerVehicle (new Vehicle(Vehicle::MAV_AUTOPILOT_TRACK, Vehicle::MAV_TYPE_TRACK, qgcApp()->toolbox()->firmwarePluginManager(), this)) _controllerVehicle(
, _managerVehicle (_controllerVehicle) new Vehicle(Vehicle::MAV_AUTOPILOT_TRACK, Vehicle::MAV_TYPE_TRACK,
, _missionController (this) qgcApp()->toolbox()->firmwarePluginManager(), this)),
, _geoFenceController (this) _managerVehicle(_controllerVehicle), _missionController(this),
, _rallyPointController (this) _geoFenceController(this), _rallyPointController(this) {
{
_commonInit(); _commonInit();
} }
#ifdef QT_DEBUG #ifdef QT_DEBUG
PlanMasterController::PlanMasterController(MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType, QObject* parent) PlanMasterController::PlanMasterController(MAV_AUTOPILOT firmwareType,
: QObject (parent) MAV_TYPE vehicleType,
, _multiVehicleMgr (qgcApp()->toolbox()->multiVehicleManager()) QObject *parent)
, _controllerVehicle (new Vehicle(firmwareType, vehicleType, qgcApp()->toolbox()->firmwarePluginManager())) : QObject(parent),
, _managerVehicle (_controllerVehicle) _multiVehicleMgr(qgcApp()->toolbox()->multiVehicleManager()),
, _missionController (this) _controllerVehicle(
, _geoFenceController (this) new Vehicle(firmwareType, vehicleType,
, _rallyPointController (this) qgcApp()->toolbox()->firmwarePluginManager())),
{ _managerVehicle(_controllerVehicle), _missionController(this),
_geoFenceController(this), _rallyPointController(this) {
_commonInit(); _commonInit();
} }
#endif #endif
void PlanMasterController::_commonInit(void) void PlanMasterController::_commonInit(void) {
{ connect(&_missionController, &MissionController::dirtyChanged, this,
connect(&_missionController, &MissionController::dirtyChanged, this, &PlanMasterController::dirtyChanged); &PlanMasterController::dirtyChanged);
connect(&_geoFenceController, &GeoFenceController::dirtyChanged, this, &PlanMasterController::dirtyChanged); connect(&_geoFenceController, &GeoFenceController::dirtyChanged, this,
connect(&_rallyPointController, &RallyPointController::dirtyChanged, this, &PlanMasterController::dirtyChanged); &PlanMasterController::dirtyChanged);
connect(&_rallyPointController, &RallyPointController::dirtyChanged, this,
connect(&_missionController, &MissionController::containsItemsChanged, this, &PlanMasterController::containsItemsChanged); &PlanMasterController::dirtyChanged);
connect(&_geoFenceController, &GeoFenceController::containsItemsChanged, this, &PlanMasterController::containsItemsChanged);
connect(&_rallyPointController, &RallyPointController::containsItemsChanged, this, &PlanMasterController::containsItemsChanged); connect(&_missionController, &MissionController::containsItemsChanged, this,
&PlanMasterController::containsItemsChanged);
connect(&_missionController, &MissionController::syncInProgressChanged, this, &PlanMasterController::syncInProgressChanged); connect(&_geoFenceController, &GeoFenceController::containsItemsChanged, this,
connect(&_geoFenceController, &GeoFenceController::syncInProgressChanged, this, &PlanMasterController::syncInProgressChanged); &PlanMasterController::containsItemsChanged);
connect(&_rallyPointController, &RallyPointController::syncInProgressChanged, this, &PlanMasterController::syncInProgressChanged); connect(&_rallyPointController, &RallyPointController::containsItemsChanged,
this, &PlanMasterController::containsItemsChanged);
connect(&_missionController, &MissionController::syncInProgressChanged, this,
&PlanMasterController::syncInProgressChanged);
connect(&_geoFenceController, &GeoFenceController::syncInProgressChanged,
this, &PlanMasterController::syncInProgressChanged);
connect(&_rallyPointController, &RallyPointController::syncInProgressChanged,
this, &PlanMasterController::syncInProgressChanged);
// Offline vehicle can change firmware/vehicle type // Offline vehicle can change firmware/vehicle type
connect(_controllerVehicle, &Vehicle::vehicleTypeChanged, this, &PlanMasterController::_updatePlanCreatorsList); connect(_controllerVehicle, &Vehicle::vehicleTypeChanged, this,
&PlanMasterController::_updatePlanCreatorsList);
} }
PlanMasterController::~PlanMasterController() {}
PlanMasterController::~PlanMasterController() void PlanMasterController::start(void) {
{ _missionController.start(_flyView);
_geoFenceController.start(_flyView);
} _rallyPointController.start(_flyView);
void PlanMasterController::start(void)
{
_missionController.start (_flyView);
_geoFenceController.start (_flyView);
_rallyPointController.start (_flyView);
_activeVehicleChanged(_multiVehicleMgr->activeVehicle()); _activeVehicleChanged(_multiVehicleMgr->activeVehicle());
connect(_multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &PlanMasterController::_activeVehicleChanged); connect(_multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this,
&PlanMasterController::_activeVehicleChanged);
_updatePlanCreatorsList(); _updatePlanCreatorsList();
#if defined(QGC_AIRMAP_ENABLED) #if defined(QGC_AIRMAP_ENABLED)
//-- This assumes there is one single instance of PlanMasterController in edit mode. //-- This assumes there is one single instance of PlanMasterController in edit
if(!flyView) { //mode.
// Wait for signal confirming AirMap client connection before starting flight planning if (!flyView) {
connect(qgcApp()->toolbox()->airspaceManager(), &AirspaceManager::connectStatusChanged, this, &PlanMasterController::_startFlightPlanning); // Wait for signal confirming AirMap client connection before starting
// flight planning
connect(qgcApp()->toolbox()->airspaceManager(),
&AirspaceManager::connectStatusChanged, this,
&PlanMasterController::_startFlightPlanning);
} }
#endif #endif
} }
void PlanMasterController::startStaticActiveVehicle(Vehicle* vehicle, bool deleteWhenSendCompleted) void PlanMasterController::startStaticActiveVehicle(
{ Vehicle *vehicle, bool deleteWhenSendCompleted) {
_flyView = true; _flyView = true;
_deleteWhenSendCompleted = deleteWhenSendCompleted; _deleteWhenSendCompleted = deleteWhenSendCompleted;
_missionController.start(_flyView); _missionController.start(_flyView);
...@@ -116,8 +126,7 @@ void PlanMasterController::startStaticActiveVehicle(Vehicle* vehicle, bool delet ...@@ -116,8 +126,7 @@ void PlanMasterController::startStaticActiveVehicle(Vehicle* vehicle, bool delet
_activeVehicleChanged(vehicle); _activeVehicleChanged(vehicle);
} }
void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) void PlanMasterController::_activeVehicleChanged(Vehicle *activeVehicle) {
{
if (_managerVehicle == activeVehicle) { if (_managerVehicle == activeVehicle) {
// We are already setup for this vehicle // We are already setup for this vehicle
return; return;
...@@ -126,7 +135,8 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) ...@@ -126,7 +135,8 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged" << activeVehicle; qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged" << activeVehicle;
if (_managerVehicle) { if (_managerVehicle) {
// Disconnect old vehicle. Be careful of wildcarding disconnect too much since _managerVehicle may equal _controllerVehicle // Disconnect old vehicle. Be careful of wildcarding disconnect too much
// since _managerVehicle may equal _controllerVehicle
disconnect(_managerVehicle->missionManager(), nullptr, nullptr, nullptr); disconnect(_managerVehicle->missionManager(), nullptr, nullptr, nullptr);
disconnect(_managerVehicle->geoFenceManager(), nullptr, nullptr, nullptr); disconnect(_managerVehicle->geoFenceManager(), nullptr, nullptr, nullptr);
disconnect(_managerVehicle->rallyPointManager(), nullptr, nullptr, nullptr); disconnect(_managerVehicle->rallyPointManager(), nullptr, nullptr, nullptr);
...@@ -134,7 +144,8 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) ...@@ -134,7 +144,8 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
bool newOffline = false; bool newOffline = false;
if (activeVehicle == nullptr) { if (activeVehicle == nullptr) {
// Since there is no longer an active vehicle we use the offline controller vehicle as the manager vehicle // Since there is no longer an active vehicle we use the offline controller
// vehicle as the manager vehicle
_managerVehicle = _controllerVehicle; _managerVehicle = _controllerVehicle;
newOffline = true; newOffline = true;
} else { } else {
...@@ -142,17 +153,30 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) ...@@ -142,17 +153,30 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
_managerVehicle = activeVehicle; _managerVehicle = activeVehicle;
// Update controllerVehicle to the currently connected vehicle // Update controllerVehicle to the currently connected vehicle
AppSettings* appSettings = qgcApp()->toolbox()->settingsManager()->appSettings(); AppSettings *appSettings =
appSettings->offlineEditingFirmwareClass()->setRawValue(QGCMAVLink::firmwareClass(_managerVehicle->firmwareType())); qgcApp()->toolbox()->settingsManager()->appSettings();
appSettings->offlineEditingVehicleClass()->setRawValue(QGCMAVLink::vehicleClass(_managerVehicle->vehicleType())); appSettings->offlineEditingFirmwareClass()->setRawValue(
QGCMAVLink::firmwareClass(_managerVehicle->firmwareType()));
// We use these signals to sequence upload and download to the multiple controller/managers appSettings->offlineEditingVehicleClass()->setRawValue(
connect(_managerVehicle->missionManager(), &MissionManager::newMissionItemsAvailable, this, &PlanMasterController::_loadMissionComplete); QGCMAVLink::vehicleClass(_managerVehicle->vehicleType()));
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::loadComplete, this, &PlanMasterController::_loadGeoFenceComplete);
connect(_managerVehicle->rallyPointManager(), &RallyPointManager::loadComplete, this, &PlanMasterController::_loadRallyPointsComplete); // We use these signals to sequence upload and download to the multiple
connect(_managerVehicle->missionManager(), &MissionManager::sendComplete, this, &PlanMasterController::_sendMissionComplete); // controller/managers
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::sendComplete, this, &PlanMasterController::_sendGeoFenceComplete); connect(_managerVehicle->missionManager(),
connect(_managerVehicle->rallyPointManager(), &RallyPointManager::sendComplete, this, &PlanMasterController::_sendRallyPointsComplete); &MissionManager::newMissionItemsAvailable, this,
&PlanMasterController::_loadMissionComplete);
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::loadComplete,
this, &PlanMasterController::_loadGeoFenceComplete);
connect(_managerVehicle->rallyPointManager(),
&RallyPointManager::loadComplete, this,
&PlanMasterController::_loadRallyPointsComplete);
connect(_managerVehicle->missionManager(), &MissionManager::sendComplete,
this, &PlanMasterController::_sendMissionComplete);
connect(_managerVehicle->geoFenceManager(), &GeoFenceManager::sendComplete,
this, &PlanMasterController::_sendGeoFenceComplete);
connect(_managerVehicle->rallyPointManager(),
&RallyPointManager::sendComplete, this,
&PlanMasterController::_sendRallyPointsComplete);
} }
_offline = newOffline; _offline = newOffline;
...@@ -163,11 +187,16 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) ...@@ -163,11 +187,16 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
// We are in the Fly View // We are in the Fly View
if (newOffline) { if (newOffline) {
// No active vehicle, clear mission // No active vehicle, clear mission
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly View - No active vehicle, clearing stale plan"; qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Fly View - No active vehicle, clearing "
"stale plan";
removeAll(); removeAll();
} else { } else {
// Fly view has changed to a new active vehicle, update to show correct mission // Fly view has changed to a new active vehicle, update to show correct
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Fly View - New active vehicle, loading new plan from manager vehicle"; // mission
qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Fly View - New active vehicle, loading "
"new plan from manager vehicle";
_showPlanFromManagerVehicle(); _showPlanFromManagerVehicle();
} }
} else { } else {
...@@ -176,17 +205,25 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) ...@@ -176,17 +205,25 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
// The plan view has a stale plan in it // The plan view has a stale plan in it
if (dirty()) { if (dirty()) {
// Plan is dirty, the user must decide what to do in all cases // Plan is dirty, the user must decide what to do in all cases
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous dirty plan exists, no new active vehicle, sending promptForPlanUsageOnVehicleChange signal"; qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Plan View - Previous dirty plan exists, "
"no new active vehicle, sending "
"promptForPlanUsageOnVehicleChange signal";
emit promptForPlanUsageOnVehicleChange(); emit promptForPlanUsageOnVehicleChange();
} else { } else {
// Plan is not dirty // Plan is not dirty
if (newOffline) { if (newOffline) {
// The active vehicle went away with no new active vehicle // The active vehicle went away with no new active vehicle
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous clean plan exists, no new active vehicle, clear stale plan"; qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Plan View - Previous clean plan "
"exists, no new active vehicle, clear stale plan";
removeAll(); removeAll();
} else { } else {
// We are transitioning from one active vehicle to another. Show the plan from the new vehicle. // We are transitioning from one active vehicle to another. Show the
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - Previous clean plan exists, new active vehicle, loading from new manager vehicle"; // plan from the new vehicle.
qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Plan View - Previous clean plan "
"exists, new active vehicle, loading from new manager vehicle";
_showPlanFromManagerVehicle(); _showPlanFromManagerVehicle();
} }
} }
...@@ -194,10 +231,14 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) ...@@ -194,10 +231,14 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
// There is no previous Plan in the view // There is no previous Plan in the view
if (newOffline) { if (newOffline) {
// Nothing special to do in this case // Nothing special to do in this case
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - No previous plan, no longer connected to vehicle, nothing to do"; qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Plan View - No previous plan, no longer "
"connected to vehicle, nothing to do";
} else { } else {
// Just show the plan from the new vehicle // Just show the plan from the new vehicle
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged: Plan View - No previous plan, new active vehicle, loading from new manager vehicle"; qCDebug(PlanMasterControllerLog)
<< "_activeVehicleChanged: Plan View - No previous plan, new "
"active vehicle, loading from new manager vehicle";
_showPlanFromManagerVehicle(); _showPlanFromManagerVehicle();
} }
} }
...@@ -211,38 +252,48 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle) ...@@ -211,38 +252,48 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
_updatePlanCreatorsList(); _updatePlanCreatorsList();
} }
void PlanMasterController::loadFromVehicle(void) void PlanMasterController::loadFromVehicle(void) {
{ if (_managerVehicle->vehicleLinkManager()
if (_managerVehicle->vehicleLinkManager()->primaryLink()->linkConfiguration()->isHighLatency()) { ->primaryLink()
qgcApp()->showAppMessage(tr("Download not supported on high latency links.")); ->linkConfiguration()
->isHighLatency()) {
qgcApp()->showAppMessage(
tr("Download not supported on high latency links."));
return; return;
} }
if (offline()) { if (offline()) {
qCWarning(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle called while offline"; qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::loadFromVehicle called while offline";
} else if (_flyView) { } else if (_flyView) {
qCWarning(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle called from Fly view"; qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::loadFromVehicle called from Fly view";
} else if (syncInProgress()) { } else if (syncInProgress()) {
qCWarning(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle called while syncInProgress"; qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::loadFromVehicle called while syncInProgress";
} else { } else {
_loadGeoFence = true; _loadGeoFence = true;
qCDebug(PlanMasterControllerLog) << "PlanMasterController::loadFromVehicle calling _missionController.loadFromVehicle"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::loadFromVehicle calling "
"_missionController.loadFromVehicle";
_missionController.loadFromVehicle(); _missionController.loadFromVehicle();
setDirty(false); setDirty(false);
} }
} }
void PlanMasterController::_loadMissionComplete(void) {
void PlanMasterController::_loadMissionComplete(void)
{
if (!_flyView && _loadGeoFence) { if (!_flyView && _loadGeoFence) {
_loadGeoFence = false; _loadGeoFence = false;
_loadRallyPoints = true; _loadRallyPoints = true;
if (_geoFenceController.supported()) { if (_geoFenceController.supported()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadMissionComplete calling _geoFenceController.loadFromVehicle"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::_loadMissionComplete calling "
"_geoFenceController.loadFromVehicle";
_geoFenceController.loadFromVehicle(); _geoFenceController.loadFromVehicle();
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadMissionComplete GeoFence not supported skipping"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::_loadMissionComplete GeoFence not "
"supported skipping";
_geoFenceController.removeAll(); _geoFenceController.removeAll();
_loadGeoFenceComplete(); _loadGeoFenceComplete();
} }
...@@ -250,15 +301,18 @@ void PlanMasterController::_loadMissionComplete(void) ...@@ -250,15 +301,18 @@ void PlanMasterController::_loadMissionComplete(void)
} }
} }
void PlanMasterController::_loadGeoFenceComplete(void) void PlanMasterController::_loadGeoFenceComplete(void) {
{
if (!_flyView && _loadRallyPoints) { if (!_flyView && _loadRallyPoints) {
_loadRallyPoints = false; _loadRallyPoints = false;
if (_rallyPointController.supported()) { if (_rallyPointController.supported()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadGeoFenceComplete calling _rallyPointController.loadFromVehicle"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::_loadGeoFenceComplete calling "
"_rallyPointController.loadFromVehicle";
_rallyPointController.loadFromVehicle(); _rallyPointController.loadFromVehicle();
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadMissionComplete Rally Points not supported skipping"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::_loadMissionComplete Rally Points not "
"supported skipping";
_rallyPointController.removeAll(); _rallyPointController.removeAll();
_loadRallyPointsComplete(); _loadRallyPointsComplete();
} }
...@@ -266,44 +320,46 @@ void PlanMasterController::_loadGeoFenceComplete(void) ...@@ -266,44 +320,46 @@ void PlanMasterController::_loadGeoFenceComplete(void)
} }
} }
void PlanMasterController::_loadRallyPointsComplete(void) void PlanMasterController::_loadRallyPointsComplete(void) {
{ qCDebug(PlanMasterControllerLog)
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_loadRallyPointsComplete"; << "PlanMasterController::_loadRallyPointsComplete";
} }
void PlanMasterController::_sendMissionComplete(void) void PlanMasterController::_sendMissionComplete(void) {
{
if (_sendGeoFence) { if (_sendGeoFence) {
_sendGeoFence = false; _sendGeoFence = false;
_sendRallyPoints = true; _sendRallyPoints = true;
if (_geoFenceController.supported()) { if (_geoFenceController.supported()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle start GeoFence sendToVehicle"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle start GeoFence sendToVehicle";
_geoFenceController.sendToVehicle(); _geoFenceController.sendToVehicle();
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle GeoFence not supported skipping"; qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle "
"GeoFence not supported skipping";
_sendGeoFenceComplete(); _sendGeoFenceComplete();
} }
setDirty(false); setDirty(false);
} }
} }
void PlanMasterController::_sendGeoFenceComplete(void) void PlanMasterController::_sendGeoFenceComplete(void) {
{
if (_sendRallyPoints) { if (_sendRallyPoints) {
_sendRallyPoints = false; _sendRallyPoints = false;
if (_rallyPointController.supported()) { if (_rallyPointController.supported()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle start rally sendToVehicle"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle start rally sendToVehicle";
_rallyPointController.sendToVehicle(); _rallyPointController.sendToVehicle();
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle Rally Points not support skipping"; qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle "
"Rally Points not support skipping";
_sendRallyPointsComplete(); _sendRallyPointsComplete();
} }
} }
} }
void PlanMasterController::_sendRallyPointsComplete(void) void PlanMasterController::_sendRallyPointsComplete(void) {
{ qCDebug(PlanMasterControllerLog)
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle Rally Point send complete"; << "PlanMasterController::sendToVehicle Rally Point send complete";
if (_deleteWhenSendCompleted) { if (_deleteWhenSendCompleted) {
this->deleteLater(); this->deleteLater();
} }
...@@ -312,35 +368,43 @@ void PlanMasterController::_sendRallyPointsComplete(void) ...@@ -312,35 +368,43 @@ void PlanMasterController::_sendRallyPointsComplete(void)
#if defined(QGC_AIRMAP_ENABLED) #if defined(QGC_AIRMAP_ENABLED)
void PlanMasterController::_startFlightPlanning(void) { void PlanMasterController::_startFlightPlanning(void) {
if (qgcApp()->toolbox()->airspaceManager()->connected()) { if (qgcApp()->toolbox()->airspaceManager()->connected()) {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::_startFlightPlanning client connected, start flight planning"; qCDebug(PlanMasterControllerLog)
qgcApp()->toolbox()->airspaceManager()->flightPlan()->startFlightPlanning(this); << "PlanMasterController::_startFlightPlanning client connected, start "
"flight planning";
qgcApp()->toolbox()->airspaceManager()->flightPlan()->startFlightPlanning(
this);
} }
} }
#endif #endif
void PlanMasterController::sendToVehicle(void) void PlanMasterController::sendToVehicle(void) {
{ if (_managerVehicle->vehicleLinkManager()
if (_managerVehicle->vehicleLinkManager()->primaryLink()->linkConfiguration()->isHighLatency()) { ->primaryLink()
->linkConfiguration()
->isHighLatency()) {
qgcApp()->showAppMessage(tr("Upload not supported on high latency links.")); qgcApp()->showAppMessage(tr("Upload not supported on high latency links."));
return; return;
} }
if (offline()) { if (offline()) {
qCWarning(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle called while offline"; qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle called while offline";
} else if (syncInProgress()) { } else if (syncInProgress()) {
qCWarning(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle called while syncInProgress"; qCWarning(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle called while syncInProgress";
} else { } else {
qCDebug(PlanMasterControllerLog) << "PlanMasterController::sendToVehicle start mission sendToVehicle"; qCDebug(PlanMasterControllerLog)
<< "PlanMasterController::sendToVehicle start mission sendToVehicle";
_sendGeoFence = true; _sendGeoFence = true;
_missionController.sendToVehicle(); _missionController.sendToVehicle();
setDirty(false); setDirty(false);
} }
} }
void PlanMasterController::loadFromFile(const QString& filename) void PlanMasterController::loadFromFile(const QString &filename) {
{
QString errorString; QString errorString;
QString errorMessage = tr("Error loading Plan file (%1). %2").arg(filename).arg("%1"); QString errorMessage =
tr("Error loading Plan file (%1). %2").arg(filename).arg("%1");
if (filename.isEmpty()) { if (filename.isEmpty()) {
return; return;
...@@ -356,7 +420,7 @@ void PlanMasterController::loadFromFile(const QString& filename) ...@@ -356,7 +420,7 @@ void PlanMasterController::loadFromFile(const QString& filename)
} }
bool success = false; bool success = false;
if(fileInfo.suffix() == AppSettings::planFileExtension) { if (fileInfo.suffix() == AppSettings::planFileExtension) {
QJsonDocument jsonDoc; QJsonDocument jsonDoc;
QByteArray bytes = file.readAll(); QByteArray bytes = file.readAll();
...@@ -370,24 +434,29 @@ void PlanMasterController::loadFromFile(const QString& filename) ...@@ -370,24 +434,29 @@ void PlanMasterController::loadFromFile(const QString& filename)
qgcApp()->toolbox()->corePlugin()->preLoadFromJson(this, json); qgcApp()->toolbox()->corePlugin()->preLoadFromJson(this, json);
int version; int version;
if (!JsonHelper::validateExternalQGCJsonFile(json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version, errorString)) { if (!JsonHelper::validateExternalQGCJsonFile(
json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version,
errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString)); qgcApp()->showAppMessage(errorMessage.arg(errorString));
return; return;
} }
QList<JsonHelper::KeyValidateInfo> rgKeyInfo = { QList<JsonHelper::KeyValidateInfo> rgKeyInfo = {
{ kJsonMissionObjectKey, QJsonValue::Object, true }, {kJsonMissionObjectKey, QJsonValue::Object, true},
{ kJsonGeoFenceObjectKey, QJsonValue::Object, true }, {kJsonGeoFenceObjectKey, QJsonValue::Object, true},
{ kJsonRallyPointsObjectKey, QJsonValue::Object, true }, {kJsonRallyPointsObjectKey, QJsonValue::Object, true},
}; };
if (!JsonHelper::validateKeys(json, rgKeyInfo, errorString)) { if (!JsonHelper::validateKeys(json, rgKeyInfo, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString)); qgcApp()->showAppMessage(errorMessage.arg(errorString));
return; return;
} }
if (!_missionController.load(json[kJsonMissionObjectKey].toObject(), errorString) || if (!_missionController.load(json[kJsonMissionObjectKey].toObject(),
!_geoFenceController.load(json[kJsonGeoFenceObjectKey].toObject(), errorString) || errorString) ||
!_rallyPointController.load(json[kJsonRallyPointsObjectKey].toObject(), errorString)) { !_geoFenceController.load(json[kJsonGeoFenceObjectKey].toObject(),
errorString) ||
!_rallyPointController.load(json[kJsonRallyPointsObjectKey].toObject(),
errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString)); qgcApp()->showAppMessage(errorMessage.arg(errorString));
} else { } else {
//-- Allow plugins to post process the load //-- Allow plugins to post process the load
...@@ -400,7 +469,8 @@ void PlanMasterController::loadFromFile(const QString& filename) ...@@ -400,7 +469,8 @@ void PlanMasterController::loadFromFile(const QString& filename)
} else { } else {
success = true; success = true;
} }
} else if (fileInfo.suffix() == AppSettings::waypointsFileExtension || fileInfo.suffix() == QStringLiteral("txt")) { } else if (fileInfo.suffix() == AppSettings::waypointsFileExtension ||
fileInfo.suffix() == QStringLiteral("txt")) {
if (!_missionController.loadTextFile(file, errorString)) { if (!_missionController.loadTextFile(file, errorString)) {
qgcApp()->showAppMessage(errorMessage.arg(errorString)); qgcApp()->showAppMessage(errorMessage.arg(errorString));
} else { } else {
...@@ -410,8 +480,11 @@ void PlanMasterController::loadFromFile(const QString& filename) ...@@ -410,8 +480,11 @@ void PlanMasterController::loadFromFile(const QString& filename)
//-- TODO: What then? //-- TODO: What then?
} }
if(success){ if (success) {
_currentPlanFile = QString::asprintf("%s/%s.%s", fileInfo.path().toLocal8Bit().data(), fileInfo.completeBaseName().toLocal8Bit().data(), AppSettings::planFileExtension); _currentPlanFile =
QString::asprintf("%s/%s.%s", fileInfo.path().toLocal8Bit().data(),
fileInfo.completeBaseName().toLocal8Bit().data(),
AppSettings::planFileExtension);
} else { } else {
_currentPlanFile.clear(); _currentPlanFile.clear();
} }
...@@ -422,8 +495,7 @@ void PlanMasterController::loadFromFile(const QString& filename) ...@@ -422,8 +495,7 @@ void PlanMasterController::loadFromFile(const QString& filename)
} }
} }
QJsonDocument PlanMasterController::saveToJson() QJsonDocument PlanMasterController::saveToJson() {
{
QJsonObject planJson; QJsonObject planJson;
qgcApp()->toolbox()->corePlugin()->preSaveToJson(this, planJson); qgcApp()->toolbox()->corePlugin()->preSaveToJson(this, planJson);
QJsonObject missionJson; QJsonObject missionJson;
...@@ -444,16 +516,13 @@ QJsonDocument PlanMasterController::saveToJson() ...@@ -444,16 +516,13 @@ QJsonDocument PlanMasterController::saveToJson()
return QJsonDocument(planJson); return QJsonDocument(planJson);
} }
void void PlanMasterController::saveToCurrent() {
PlanMasterController::saveToCurrent() if (!_currentPlanFile.isEmpty()) {
{
if(!_currentPlanFile.isEmpty()) {
saveToFile(_currentPlanFile); saveToFile(_currentPlanFile);
} }
} }
void PlanMasterController::saveToFile(const QString& filename) void PlanMasterController::saveToFile(const QString &filename) {
{
if (filename.isEmpty()) { if (filename.isEmpty()) {
return; return;
} }
...@@ -466,13 +535,14 @@ void PlanMasterController::saveToFile(const QString& filename) ...@@ -466,13 +535,14 @@ void PlanMasterController::saveToFile(const QString& filename)
QFile file(planFilename); QFile file(planFilename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qgcApp()->showAppMessage(tr("Plan save error %1 : %2").arg(filename).arg(file.errorString())); qgcApp()->showAppMessage(
tr("Plan save error %1 : %2").arg(filename).arg(file.errorString()));
_currentPlanFile.clear(); _currentPlanFile.clear();
emit currentPlanFileChanged(); emit currentPlanFileChanged();
} else { } else {
QJsonDocument saveDoc = saveToJson(); QJsonDocument saveDoc = saveToJson();
file.write(saveDoc.toJson()); file.write(saveDoc.toJson());
if(_currentPlanFile != planFilename) { if (_currentPlanFile != planFilename) {
_currentPlanFile = planFilename; _currentPlanFile = planFilename;
emit currentPlanFileChanged(); emit currentPlanFileChanged();
} }
...@@ -484,8 +554,7 @@ void PlanMasterController::saveToFile(const QString& filename) ...@@ -484,8 +554,7 @@ void PlanMasterController::saveToFile(const QString& filename)
} }
} }
void PlanMasterController::saveToKml(const QString& filename) void PlanMasterController::saveToKml(const QString &filename) {
{
if (filename.isEmpty()) { if (filename.isEmpty()) {
return; return;
} }
...@@ -498,7 +567,8 @@ void PlanMasterController::saveToKml(const QString& filename) ...@@ -498,7 +567,8 @@ void PlanMasterController::saveToKml(const QString& filename)
QFile file(kmlFilename); QFile file(kmlFilename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qgcApp()->showAppMessage(tr("KML save error %1 : %2").arg(filename).arg(file.errorString())); qgcApp()->showAppMessage(
tr("KML save error %1 : %2").arg(filename).arg(file.errorString()));
} else { } else {
KMLPlanDomDocument planKML; KMLPlanDomDocument planKML;
_missionController.addMissionToKML(planKML); _missionController.addMissionToKML(planKML);
...@@ -508,8 +578,7 @@ void PlanMasterController::saveToKml(const QString& filename) ...@@ -508,8 +578,7 @@ void PlanMasterController::saveToKml(const QString& filename)
} }
} }
void PlanMasterController::removeAll(void) void PlanMasterController::removeAll(void) {
{
_missionController.removeAll(); _missionController.removeAll();
_geoFenceController.removeAll(); _geoFenceController.removeAll();
_rallyPointController.removeAll(); _rallyPointController.removeAll();
...@@ -522,8 +591,7 @@ void PlanMasterController::removeAll(void) ...@@ -522,8 +591,7 @@ void PlanMasterController::removeAll(void)
} }
} }
void PlanMasterController::removeAllFromVehicle(void) void PlanMasterController::removeAllFromVehicle(void) {
{
if (!offline()) { if (!offline()) {
_missionController.removeAllFromVehicle(); _missionController.removeAllFromVehicle();
if (_geoFenceController.supported()) { if (_geoFenceController.supported()) {
...@@ -534,72 +602,75 @@ void PlanMasterController::removeAllFromVehicle(void) ...@@ -534,72 +602,75 @@ void PlanMasterController::removeAllFromVehicle(void)
} }
setDirty(false); setDirty(false);
} else { } else {
qWarning() << "PlanMasterController::removeAllFromVehicle called while offline"; qWarning()
<< "PlanMasterController::removeAllFromVehicle called while offline";
} }
} }
bool PlanMasterController::containsItems(void) const bool PlanMasterController::containsItems(void) const {
{ return _missionController.containsItems() ||
return _missionController.containsItems() || _geoFenceController.containsItems() || _rallyPointController.containsItems(); _geoFenceController.containsItems() ||
_rallyPointController.containsItems();
} }
bool PlanMasterController::dirty(void) const bool PlanMasterController::dirty(void) const {
{ return _missionController.dirty() || _geoFenceController.dirty() ||
return _missionController.dirty() || _geoFenceController.dirty() || _rallyPointController.dirty(); _rallyPointController.dirty();
} }
void PlanMasterController::setDirty(bool dirty) void PlanMasterController::setDirty(bool dirty) {
{
_missionController.setDirty(dirty); _missionController.setDirty(dirty);
_geoFenceController.setDirty(dirty); _geoFenceController.setDirty(dirty);
_rallyPointController.setDirty(dirty); _rallyPointController.setDirty(dirty);
} }
QString PlanMasterController::fileExtension(void) const QString PlanMasterController::fileExtension(void) const {
{
return AppSettings::planFileExtension; return AppSettings::planFileExtension;
} }
QString PlanMasterController::kmlFileExtension(void) const QString PlanMasterController::kmlFileExtension(void) const {
{
return AppSettings::kmlFileExtension; return AppSettings::kmlFileExtension;
} }
QStringList PlanMasterController::loadNameFilters(void) const QStringList PlanMasterController::loadNameFilters(void) const {
{
QStringList filters; QStringList filters;
filters << tr("Supported types (*.%1 *.%2 *.%3 *.%4)").arg(AppSettings::planFileExtension).arg(AppSettings::missionFileExtension).arg(AppSettings::waypointsFileExtension).arg("txt") << filters << tr("Supported types (*.%1 *.%2 *.%3 *.%4)")
tr("All Files (*.*)"); .arg(AppSettings::planFileExtension)
.arg(AppSettings::missionFileExtension)
.arg(AppSettings::waypointsFileExtension)
.arg("txt")
<< tr("All Files (*.*)");
return filters; return filters;
} }
QStringList PlanMasterController::saveNameFilters(void) const {
QStringList PlanMasterController::saveNameFilters(void) const
{
QStringList filters; QStringList filters;
filters << tr("Plan Files (*.%1)").arg(fileExtension()) << tr("All Files (*.*)"); filters << tr("Plan Files (*.%1)").arg(fileExtension())
<< tr("All Files (*.*)");
return filters; return filters;
} }
void PlanMasterController::sendPlanToVehicle(Vehicle* vehicle, const QString& filename) void PlanMasterController::sendPlanToVehicle(Vehicle *vehicle,
{ const QString &filename) {
// Use a transient PlanMasterController to accomplish this // Use a transient PlanMasterController to accomplish this
PlanMasterController* controller = new PlanMasterController(); PlanMasterController *controller = new PlanMasterController();
controller->startStaticActiveVehicle(vehicle, true /* deleteWhenSendCompleted */); controller->startStaticActiveVehicle(vehicle,
true /* deleteWhenSendCompleted */);
controller->loadFromFile(filename); controller->loadFromFile(filename);
controller->sendToVehicle(); controller->sendToVehicle();
} }
void PlanMasterController::_showPlanFromManagerVehicle(void) void PlanMasterController::_showPlanFromManagerVehicle(void) {
{
if (!_managerVehicle->initialPlanRequestComplete() && !syncInProgress()) { if (!_managerVehicle->initialPlanRequestComplete() && !syncInProgress()) {
// Something went wrong with initial load. All controllers are idle, so just force it off // Something went wrong with initial load. All controllers are idle, so just
// force it off
_managerVehicle->forceInitialPlanRequestComplete(); _managerVehicle->forceInitialPlanRequestComplete();
} }
// The crazy if structure is to handle the load propagating by itself through the system // The crazy if structure is to handle the load propagating by itself through
// the system
if (!_missionController.showPlanFromManagerVehicle()) { if (!_missionController.showPlanFromManagerVehicle()) {
if (!_geoFenceController.showPlanFromManagerVehicle()) { if (!_geoFenceController.showPlanFromManagerVehicle()) {
_rallyPointController.showPlanFromManagerVehicle(); _rallyPointController.showPlanFromManagerVehicle();
...@@ -607,52 +678,52 @@ void PlanMasterController::_showPlanFromManagerVehicle(void) ...@@ -607,52 +678,52 @@ void PlanMasterController::_showPlanFromManagerVehicle(void)
} }
} }
bool PlanMasterController::syncInProgress(void) const bool PlanMasterController::syncInProgress(void) const {
{
return _missionController.syncInProgress() || return _missionController.syncInProgress() ||
_geoFenceController.syncInProgress() || _geoFenceController.syncInProgress() ||
_rallyPointController.syncInProgress(); _rallyPointController.syncInProgress();
} }
bool PlanMasterController::isEmpty(void) const bool PlanMasterController::isEmpty(void) const {
{ return _missionController.isEmpty() && _geoFenceController.isEmpty() &&
return _missionController.isEmpty() &&
_geoFenceController.isEmpty() &&
_rallyPointController.isEmpty(); _rallyPointController.isEmpty();
} }
void PlanMasterController::_updatePlanCreatorsList(void) void PlanMasterController::_updatePlanCreatorsList(void) {
{
if (!_flyView) { if (!_flyView) {
if (!_planCreators) { if (!_planCreators) {
_planCreators = new QmlObjectListModel(this); _planCreators = new QmlObjectListModel(this);
_planCreators->append(new BlankPlanCreator(this, this)); _planCreators->append(new BlankPlanCreator(this, this));
_planCreators->append(new SurveyPlanCreator(this, this)); _planCreators->append(new SurveyPlanCreator(this, this));
_planCreators->append(new CorridorScanPlanCreator(this, this)); _planCreators->append(new CorridorScanPlanCreator(this, this));
_planCreators->append(new MeasurementPlanCreator(this, this));
emit planCreatorsChanged(_planCreators); emit planCreatorsChanged(_planCreators);
} }
if (_managerVehicle->fixedWing()) { if (_managerVehicle->fixedWing()) {
if (_planCreators->count() == 4) { if (_planCreators->count() == 5) {
_planCreators->removeAt(_planCreators->count() - 1); _planCreators->removeAt(_planCreators->count() - 1);
} }
} else { } else {
if (_planCreators->count() != 4) { if (_planCreators->count() != 5) {
_planCreators->append(new StructureScanPlanCreator(this, this)); _planCreators->append(new StructureScanPlanCreator(this, this));
} }
} }
} }
} }
void PlanMasterController::showPlanFromManagerVehicle(void) void PlanMasterController::showPlanFromManagerVehicle(void) {
{
if (offline()) { if (offline()) {
// There is no new vehicle so clear any previous plan // There is no new vehicle so clear any previous plan
qCDebug(PlanMasterControllerLog) << "showPlanFromManagerVehicle: Plan View - No new vehicle, clear any previous plan"; qCDebug(PlanMasterControllerLog)
<< "showPlanFromManagerVehicle: Plan View - No new vehicle, clear any "
"previous plan";
removeAll(); removeAll();
} else { } else {
// We have a new active vehicle, show the plan from that // We have a new active vehicle, show the plan from that
qCDebug(PlanMasterControllerLog) << "showPlanFromManagerVehicle: Plan View - New vehicle available, show plan from new manager vehicle"; qCDebug(PlanMasterControllerLog)
<< "showPlanFromManagerVehicle: Plan View - New vehicle available, "
"show plan from new manager vehicle";
_showPlanFromManagerVehicle(); _showPlanFromManagerVehicle();
} }
} }
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