QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GeoFenceController.cc
Go to the documentation of this file.
2#include "Vehicle.h"
3#include "ParameterManager.h"
4#include "GeoJsonHelper.h"
5#include "JsonParsing.h"
7#include "SettingsManager.h"
8#include "AppSettings.h"
9#include "GeoFenceManager.h"
10#include "QGCFenceCircle.h"
11#include "QGCFencePolygon.h"
12#include "QGCLoggingCategory.h"
13
14#include <QtCore/QJsonArray>
15#include <QtCore/QJsonDocument>
16
17QGC_LOGGING_CATEGORY(GeoFenceControllerLog, "PlanManager.GeoFenceController")
18
19QMap<QString, FactMetaData*> GeoFenceController::_metaDataMap;
20
22 : PlanElementController (masterController, parent)
23 , _managerVehicle (masterController->managerVehicle())
24 , _geoFenceManager (masterController->managerVehicle()->geoFenceManager())
25 , _breachReturnAltitudeFact (0, _breachReturnAltitudeFactName, FactMetaData::valueTypeDouble)
26 , _breachReturnDefaultAltitude (SettingsManager::instance()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble())
27{
28 if (_metaDataMap.isEmpty()) {
29 _metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/BreachReturn.FactMetaData.json"), nullptr /* metaDataParent */);
30 }
31
32 _breachReturnAltitudeFact.setMetaData(_metaDataMap[_breachReturnAltitudeFactName]);
33 _breachReturnAltitudeFact.setRawValue(_breachReturnDefaultAltitude);
34
37
38 connect(this, &GeoFenceController::breachReturnPointChanged, this, &GeoFenceController::_setDirty);
39 connect(&_breachReturnAltitudeFact, &Fact::rawValueChanged, this, &GeoFenceController::_setDirty);
40 connect(&_polygons, &QmlObjectListModel::dirtyChanged, this, &GeoFenceController::_fenceListDirtyChanged);
41 connect(&_circles, &QmlObjectListModel::dirtyChanged, this, &GeoFenceController::_fenceListDirtyChanged);
42}
43
48
49void GeoFenceController::start(bool flyView)
50{
51 qCDebug(GeoFenceControllerLog) << "start flyView" << flyView;
52
53 _managerVehicleChanged(_masterController->managerVehicle());
54 connect(_masterController, &PlanMasterController::managerVehicleChanged, this, &GeoFenceController::_managerVehicleChanged);
55
57 _init();
58}
59
60void GeoFenceController::_init(void)
61{
62
63}
64
65void GeoFenceController::setBreachReturnPoint(const QGeoCoordinate& breachReturnPoint)
66{
67 if (_breachReturnPoint != breachReturnPoint) {
68 _breachReturnPoint = breachReturnPoint;
69 setDirty(true);
71 }
72}
73
74void GeoFenceController::_managerVehicleChanged(Vehicle* managerVehicle)
75{
76 if (_managerVehicle) {
77 _geoFenceManager->disconnect(this);
78 _managerVehicle->disconnect(this);
79 _managerVehicle->parameterManager()->disconnect(this);
80 _managerVehicle = nullptr;
81 _geoFenceManager = nullptr;
82 }
83
84 _managerVehicle = managerVehicle;
85 if (!_managerVehicle) {
86 qWarning() << "GeoFenceController::managerVehicleChanged managerVehicle=nullptr";
87 return;
88 }
89
90 _geoFenceManager = _managerVehicle->geoFenceManager();
91 connect(_geoFenceManager, &GeoFenceManager::loadComplete, this, &GeoFenceController::_managerLoadComplete);
92 connect(_geoFenceManager, &GeoFenceManager::sendComplete, this, &GeoFenceController::_managerSendComplete);
93 connect(_geoFenceManager, &GeoFenceManager::removeAllComplete, this, &GeoFenceController::_managerRemoveAllComplete);
95
96 (void) connect(_managerVehicle, &Vehicle::capabilityBitsChanged, this, [this](uint64_t capabilityBits) {
97 Q_UNUSED(capabilityBits);
99 });
100
101 connect(_managerVehicle->parameterManager(), &ParameterManager::parametersReadyChanged, this, &GeoFenceController::_parametersReady);
102 _parametersReady();
103
105}
106
107bool GeoFenceController::load(const QJsonObject& json, QString& errorString)
108{
109 removeAll();
110
111 errorString.clear();
112
113 if (!json.contains(JsonParsing::jsonVersionKey) ||
114 (json.contains(JsonParsing::jsonVersionKey) && json[JsonParsing::jsonVersionKey].toInt() == 1)) {
115 // We just ignore old version 1 or prior data
116 return true;
117 }
118
119 QList<JsonParsing::KeyValidateInfo> keyInfoList = {
120 { JsonParsing::jsonVersionKey, QJsonValue::Double, true },
121 { _jsonCirclesKey, QJsonValue::Array, true },
122 { _jsonPolygonsKey, QJsonValue::Array, true },
123 { _jsonBreachReturnKey, QJsonValue::Array, false },
124 };
125 if (!JsonParsing::validateKeys(json, keyInfoList, errorString)) {
126 return false;
127 }
128
129 if (json[JsonParsing::jsonVersionKey].toInt() != _jsonCurrentVersion) {
130 errorString = tr("GeoFence supports version %1").arg(_jsonCurrentVersion);
131 return false;
132 }
133
134 QJsonArray jsonPolygonArray = json[_jsonPolygonsKey].toArray();
135 for (const QJsonValue jsonPolygonValue: jsonPolygonArray) {
136 if (jsonPolygonValue.type() != QJsonValue::Object) {
137 errorString = tr("GeoFence polygon not stored as object");
138 return false;
139 }
140
141 QGCFencePolygon* fencePolygon = new QGCFencePolygon(false /* inclusion */, this /* parent */);
142 if (!fencePolygon->loadFromJson(jsonPolygonValue.toObject(), true /* required */, errorString)) {
143 return false;
144 }
145 _polygons.append(fencePolygon);
146 }
147
148 QJsonArray jsonCircleArray = json[_jsonCirclesKey].toArray();
149 for (const QJsonValue jsonCircleValue: jsonCircleArray) {
150 if (jsonCircleValue.type() != QJsonValue::Object) {
151 errorString = tr("GeoFence circle not stored as object");
152 return false;
153 }
154
155 QGCFenceCircle* fenceCircle = new QGCFenceCircle(this /* parent */);
156 if (!fenceCircle->loadFromJson(jsonCircleValue.toObject(), errorString)) {
157 return false;
158 }
159 _circles.append(fenceCircle);
160 }
161
162 if (json.contains(_jsonBreachReturnKey)) {
163 if (!GeoJsonHelper::loadGeoCoordinate(json[_jsonBreachReturnKey], true /* altitudeRequred */, _breachReturnPoint, errorString)) {
164 return false;
165 }
166 _breachReturnAltitudeFact.setRawValue(_breachReturnPoint.altitude());
167 } else {
168 _breachReturnPoint = QGeoCoordinate();
169 _breachReturnAltitudeFact.setRawValue(_breachReturnDefaultAltitude);
170 }
171 emit breachReturnPointChanged(_breachReturnPoint);
172
173 setDirty(false);
174
175 return true;
176}
177
178void GeoFenceController::save(QJsonObject& json)
179{
180 json[JsonParsing::jsonVersionKey] = _jsonCurrentVersion;
181
182 QJsonArray jsonPolygonArray;
183 for (int i=0; i<_polygons.count(); i++) {
184 QJsonObject jsonPolygon;
185 QGCFencePolygon* fencePolygon = _polygons.value<QGCFencePolygon*>(i);
186 fencePolygon->saveToJson(jsonPolygon);
187 jsonPolygonArray.append(jsonPolygon);
188 }
189 json[_jsonPolygonsKey] = jsonPolygonArray;
190
191 QJsonArray jsonCircleArray;
192 for (int i=0; i<_circles.count(); i++) {
193 QJsonObject jsonCircle;
194 QGCFenceCircle* fenceCircle = _circles.value<QGCFenceCircle*>(i);
195 fenceCircle->saveToJson(jsonCircle);
196 jsonCircleArray.append(jsonCircle);
197 }
198 json[_jsonCirclesKey] = jsonCircleArray;
199
200 if (_breachReturnPoint.isValid()) {
201 QJsonValue jsonCoordinate;
202
203 _breachReturnPoint.setAltitude(_breachReturnAltitudeFact.rawValue().toDouble());
204 GeoJsonHelper::saveGeoCoordinate(_breachReturnPoint, true /* writeAltitude */, jsonCoordinate);
205 json[_jsonBreachReturnKey] = jsonCoordinate;
206 }
207}
208
210{
211 setBreachReturnPoint(QGeoCoordinate());
212 _polygons.clearAndDeleteContents();
213 _circles.clearAndDeleteContents();
214}
215
217{
218 if (_masterController->offline()) {
219 qCCritical(GeoFenceControllerLog) << "GeoFenceController::removeAllFromVehicle called while offline";
220 } else if (syncInProgress()) {
221 qCCritical(GeoFenceControllerLog) << "GeoFenceController::removeAllFromVehicle called while syncInProgress";
222 } else {
223 _geoFenceManager->removeAll();
224 }
225}
226
228{
229 if (_masterController->offline()) {
230 qCCritical(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle called while offline";
231 } else if (syncInProgress()) {
232 qCCritical(GeoFenceControllerLog) << "GeoFenceController::loadFromVehicle called while syncInProgress";
233 } else {
234 _itemsRequested = true;
235 _geoFenceManager->loadFromVehicle();
236 }
237}
238
240{
241 if (_masterController->offline()) {
242 qCCritical(GeoFenceControllerLog) << "GeoFenceController::sendToVehicle called while offline";
243 } else if (syncInProgress()) {
244 qCCritical(GeoFenceControllerLog) << "GeoFenceController::sendToVehicle called while syncInProgress";
245 } else {
246 qCDebug(GeoFenceControllerLog) << "GeoFenceController::sendToVehicle";
247 _geoFenceManager->sendToVehicle(_breachReturnPoint, _polygons, _circles);
248 setDirty(false);
249 }
250}
251
253{
254 return _geoFenceManager->inProgress();
255}
256
258{
259 return _dirty;
260}
261
262
264{
265 if (dirty != _dirty) {
266 _dirty = dirty;
267 if (!dirty) {
268 // Clearing the lists also clears their items; a still-dirty list would swallow the next item edit
269 _polygons.setDirty(false);
270 _circles.setDirty(false);
271 }
272 emit dirtyChanged(dirty);
273 }
274}
275
276void GeoFenceController::_fenceListDirtyChanged(bool dirty)
277{
278 if (dirty) {
279 setDirty(true);
280 }
281}
282
283void GeoFenceController::_setDirty(void)
284{
285 setDirty(true);
286}
287
288void GeoFenceController::_setFenceFromManager(const QList<QGCFencePolygon>& polygons,
289 const QList<QGCFenceCircle>& circles)
290{
291 _polygons.clearAndDeleteContents();
292 _circles.clearAndDeleteContents();
293
294 for (int i=0; i<polygons.count(); i++) {
295 _polygons.append(new QGCFencePolygon(polygons[i], this));
296 }
297
298 for (int i=0; i<circles.count(); i++) {
299 _circles.append(new QGCFenceCircle(circles[i], this));
300 }
301
302 setDirty(false);
303}
304
305void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint)
306{
307 _breachReturnPoint = breachReturnPoint;
308 emit breachReturnPointChanged(_breachReturnPoint);
309 if (_breachReturnPoint.isValid()) {
310 _breachReturnAltitudeFact.setRawValue(_breachReturnPoint.altitude());
311 } else {
312 _breachReturnAltitudeFact.setRawValue(_breachReturnDefaultAltitude);
313 }
314}
315
316void GeoFenceController::_managerLoadComplete(void)
317{
318 // Fly view always reloads on _loadComplete
319 // Plan view only reloads if:
320 // - Load was specifically requested
321 // - There is no current Plan
322 if (_flyView || _itemsRequested || isEmpty()) {
323 _setReturnPointFromManager(_geoFenceManager->breachReturnPoint());
324 _setFenceFromManager(_geoFenceManager->polygons(), _geoFenceManager->circles());
325 setDirty(false);
326 emit loadComplete();
327 }
328 _itemsRequested = false;
329}
330
331void GeoFenceController::_managerSendComplete(bool error)
332{
333 // Fly view always reloads on manager sendComplete
334 if (!error && _flyView) {
336 }
337}
338
339void GeoFenceController::_managerRemoveAllComplete(bool error)
340{
341 if (!error) {
342 // Remove all from vehicle so we always update
344 }
345}
346
348{
349 return _polygons.count() > 0 || _circles.count() > 0;
350}
351
353{
354 qCDebug(GeoFenceControllerLog) << "showPlanFromManagerVehicle _flyView" << _flyView;
355 if (_masterController->offline()) {
356 qCCritical(GeoFenceControllerLog) << "GeoFenceController::showPlanFromManagerVehicle called while offline";
357 return true; // stops further propagation of showPlanFromManagerVehicle due to error
358 } else {
359 _itemsRequested = true;
360 if (!_managerVehicle->initialPlanRequestComplete()) {
361 // The vehicle hasn't completed initial load, we can just wait for loadComplete to be signalled automatically
362 qCDebug(GeoFenceControllerLog) << "showPlanFromManagerVehicle: !initialPlanRequestComplete, wait for signal";
363 return true;
364 } else if (syncInProgress()) {
365 // If the sync is already in progress, _loadComplete will be called automatically when it is done. So no need to do anything.
366 qCDebug(GeoFenceControllerLog) << "showPlanFromManagerVehicle: syncInProgress wait for signal";
367 return true;
368 } else {
369 // Fake a _loadComplete with the current items
370 qCDebug(GeoFenceControllerLog) << "showPlanFromManagerVehicle: sync complete simulate signal";
371 _itemsRequested = true;
372 _managerLoadComplete();
373 return false;
374 }
375 }
376}
377
378void GeoFenceController::addInclusionPolygon(QGeoCoordinate topLeft, QGeoCoordinate bottomRight)
379{
380 QGeoCoordinate topRight(topLeft.latitude(), bottomRight.longitude());
381 QGeoCoordinate bottomLeft(bottomRight.latitude(), topLeft.longitude());
382
383 double halfWidthMeters = topLeft.distanceTo(topRight) / 2.0;
384 double halfHeightMeters = topLeft.distanceTo(bottomLeft) / 2.0;
385
386 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
387 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
388 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
389
390 // Initial polygon is inset to take 3/4s of viewport with max width/height of 3000 meters
391 halfWidthMeters = qMin(halfWidthMeters * 0.75, 1500.0);
392 halfHeightMeters = qMin(halfHeightMeters * 0.75, 1500.0);
393
394 // Initial polygon has max width and height of 3000 meters
395 topLeft = center.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0);
396 topRight = center.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0);
397 bottomLeft = center.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180);
398 bottomRight = center.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180);
399
400 QGCFencePolygon* polygon = new QGCFencePolygon(true /* inclusion */, this);
401 polygon->appendVertex(topLeft);
402 polygon->appendVertex(topRight);
403 polygon->appendVertex(bottomRight);
404 polygon->appendVertex(bottomLeft);
405 _polygons.append(polygon);
406
408 polygon->setInteractive(true);
409}
410
411void GeoFenceController::addInclusionCircle(QGeoCoordinate topLeft, QGeoCoordinate bottomRight)
412{
413 QGeoCoordinate topRight(topLeft.latitude(), bottomRight.longitude());
414 QGeoCoordinate bottomLeft(bottomRight.latitude(), topLeft.longitude());
415
416 // Initial radius is inset to take 3/4s of viewport and max of 1500 meters
417 double halfWidthMeters = topLeft.distanceTo(topRight) / 2.0;
418 double halfHeightMeters = topLeft.distanceTo(bottomLeft) / 2.0;
419 double radius = qMin(qMin(halfWidthMeters, halfHeightMeters) * 0.75, 1500.0);
420
421 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
422 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
423 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
424
425 QGCFenceCircle* circle = new QGCFenceCircle(center, radius, true /* inclusion */, this);
426 _circles.append(circle);
427
429 circle->setInteractive(true);
430}
431
433{
434 if (index < 0 || index > _polygons.count() - 1) {
435 return;
436 }
437
438 QGCFencePolygon* polygon = qobject_cast<QGCFencePolygon*>(_polygons.removeAt(index));
439 polygon->deleteLater();
440}
441
443{
444 if (index < 0 || index > _circles.count() - 1) {
445 return;
446 }
447
448 QGCFenceCircle* circle = qobject_cast<QGCFenceCircle*>(_circles.removeAt(index));
449 circle->deleteLater();
450}
451
453{
454 for (int i=0; i<_polygons.count(); i++) {
455 _polygons.value<QGCFencePolygon*>(i)->setInteractive(false);
456 }
457 for (int i=0; i<_circles.count(); i++) {
458 _circles.value<QGCFenceCircle*>(i)->setInteractive(false);
459 }
460}
461
463{
464 return _managerVehicle->capabilityBits() & MAV_PROTOCOL_CAPABILITY_MISSION_FENCE;
465}
466
467/* Returns the radius of the "paramCircularFence"
468 * which is called the "Geofence Failsafe" in PX4 and the "Circular Geofence" on Ardupilot
469 * this code should ideally live in the firmware plugin since it is specific to apm and px4 firmwares */
471{
472 if(_managerVehicle->isOfflineEditingVehicle()){
473 return 0;
474 }
475
476 if(_managerVehicle->px4Firmware()){
477 if(!_managerVehicle->parameterManager()->parameterExists(ParameterManager::defaultComponentId, _px4ParamCircularFence)){
478 return 0;
479 }
480
481 return _managerVehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, _px4ParamCircularFence)->rawValue().toDouble();
482 }
483
484 if(_managerVehicle->apmFirmware())
485 {
486 if (!_managerVehicle->parameterManager()->parameterExists(ParameterManager::defaultComponentId, _apmParamCircularFenceRadius) ||
487 !_managerVehicle->parameterManager()->parameterExists(ParameterManager::defaultComponentId, _apmParamCircularFenceEnabled) ||
488 !_managerVehicle->parameterManager()->parameterExists(ParameterManager::defaultComponentId, _apmParamCircularFenceType)){
489 return 0;
490 }
491
492 bool apm_fence_enabled = _managerVehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, _apmParamCircularFenceEnabled)->rawValue().toBool();
493 bool apm_fence_type_circle = (1 << 1) & _managerVehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, _apmParamCircularFenceType)->rawValue().toUInt();
494
495 if(!apm_fence_enabled || !apm_fence_type_circle)
496 return 0;
497
498 return _managerVehicle->parameterManager()->getParameter(ParameterManager::defaultComponentId, _apmParamCircularFenceRadius)->rawValue().toDouble();
499 }
500
501 return 0;
502}
503
504void GeoFenceController::_parametersReady(void)
505{
506 /* When parameters are ready we setup notifications of param changes
507 * so that if a param changes we can emit paramCircularFenceChanged
508 * and trigger an update to the UI */
509
510 // First disconnect from any existing facts
511 if (_px4ParamCircularFenceFact) {
512 _px4ParamCircularFenceFact->disconnect(this);
513 _px4ParamCircularFenceFact = nullptr;
514 }
515 if (_apmParamCircularFenceRadiusFact) {
516 _apmParamCircularFenceRadiusFact->disconnect(this);
517 _apmParamCircularFenceRadiusFact = nullptr;
518 }
519 if (_apmParamCircularFenceEnabledFact) {
520 _apmParamCircularFenceEnabledFact->disconnect(this);
521 _apmParamCircularFenceEnabledFact = nullptr;
522 }
523 if (_apmParamCircularFenceTypeFact) {
524 _apmParamCircularFenceTypeFact->disconnect(this);
525 _apmParamCircularFenceTypeFact = nullptr;
526 }
527
528 // then connect to needed paremters
529 // While checking they exist to avoid errors
530 ParameterManager* _paramManager = _managerVehicle->parameterManager();
531
532 if(_managerVehicle->isOfflineEditingVehicle()){
534 return;
535 }
536
537 if(_managerVehicle->px4Firmware()){
538 if(!_paramManager->parameterExists(ParameterManager::defaultComponentId, _px4ParamCircularFence)){
540 return;
541 }
542
543 _px4ParamCircularFenceFact = _paramManager->getParameter(ParameterManager::defaultComponentId, _px4ParamCircularFence);
544 connect(_px4ParamCircularFenceFact, &Fact::rawValueChanged, this, &GeoFenceController::paramCircularFenceChanged);
545 }
546 else if(_managerVehicle->apmFirmware())
547 {
548 if (!_paramManager->parameterExists(ParameterManager::defaultComponentId, _apmParamCircularFenceRadius) ||
549 !_paramManager->parameterExists(ParameterManager::defaultComponentId, _apmParamCircularFenceEnabled) ||
550 !_paramManager->parameterExists(ParameterManager::defaultComponentId, _apmParamCircularFenceType)){
552 return;
553 }
554
555 _apmParamCircularFenceRadiusFact = _paramManager->getParameter(ParameterManager::defaultComponentId, _apmParamCircularFenceRadius);
556 _apmParamCircularFenceEnabledFact = _paramManager->getParameter(ParameterManager::defaultComponentId, _apmParamCircularFenceEnabled);
557 _apmParamCircularFenceTypeFact = _paramManager->getParameter(ParameterManager::defaultComponentId, _apmParamCircularFenceType);
558 connect(_apmParamCircularFenceRadiusFact, &Fact::rawValueChanged, this, &GeoFenceController::paramCircularFenceChanged);
559 connect(_apmParamCircularFenceEnabledFact, &Fact::rawValueChanged, this, &GeoFenceController::paramCircularFenceChanged);
560 connect(_apmParamCircularFenceTypeFact, &Fact::rawValueChanged, this, &GeoFenceController::paramCircularFenceChanged);
561 }
562
564}
565
567{
568 return _polygons.count() == 0 && _circles.count() == 0 && !_breachReturnPoint.isValid();
569
570}
QString errorString
Error error
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Holds the meta data associated with a Fact.
static QMap< QString, FactMetaData * > createMapFromJsonFile(const QString &jsonFilename, QObject *metaDataParent)
void rawValueChanged(const QVariant &value)
void setRawValue(const QVariant &value)
Definition Fact.cc:135
QVariant rawValue() const
Definition Fact.h:87
bool showPlanFromManagerVehicle(void) final
Q_INVOKABLE void addInclusionPolygon(QGeoCoordinate topLeft, QGeoCoordinate bottomRight)
void removeAllFromVehicle(void) final
void breachReturnPointChanged(QGeoCoordinate breachReturnPoint)
void setDirty(bool dirty) final
bool containsItems(void) const final
double paramCircularFence(void)
QmlObjectListModel * polygons(void)
void sendToVehicle(void) final
Q_INVOKABLE void deletePolygon(int index)
QmlObjectListModel * circles(void)
bool syncInProgress(void) const final
void loadComplete(void)
void removeAll(void) final
Removes all from controller only.
void paramCircularFenceChanged(void)
Q_INVOKABLE void addInclusionCircle(QGeoCoordinate topLeft, QGeoCoordinate bottomRight)
void setBreachReturnPoint(const QGeoCoordinate &breachReturnPoint)
bool load(const QJsonObject &json, QString &errorString) final
bool supported(void) const final
true: controller is waiting for the current load to complete
void loadFromVehicle(void) final
bool isEmpty(void) const
bool dirty(void) const final
void start(bool flyView) final
Should be called immediately upon Component.onCompleted.
void save(QJsonObject &json) final
QGeoCoordinate breachReturnPoint(void) const
Q_INVOKABLE void clearAllInteractive(void)
Clears the interactive bit from all fence items.
Q_INVOKABLE void deleteCircle(int index)
void removeAll(void)
Signals removeAllComplete when done.
void sendToVehicle(const QGeoCoordinate &breachReturn, QmlObjectListModel &polygons, QmlObjectListModel &circles)
Signals sendComplete when done.
void inProgressChanged(bool inProgress)
const QGeoCoordinate & breachReturnPoint(void) const
const QList< QGCFencePolygon > & polygons(void)
void loadComplete(void)
void removeAllComplete(bool error)
void sendComplete(bool error)
const QList< QGCFenceCircle > & circles(void)
void dirtyChanged(bool dirty)
void countChanged(int count)
bool parameterExists(int componentId, const QString &paramName) const
Fact * getParameter(int componentId, const QString &paramName)
void parametersReadyChanged(bool parametersReady)
static constexpr int defaultComponentId
This is the abstract base clas for Plan Element controllers.
void supportedChanged(bool supported)
void syncInProgressChanged(bool syncInProgress)
PlanMasterController * _masterController
virtual void start(bool flyView)
Should be called immediately upon Component.onCompleted.
void dirtyChanged(bool dirty)
void loadFromVehicle(void)
bool inProgress(void) const
Master controller for mission, fence, rally.
void managerVehicleChanged(Vehicle *managerVehicle)
The QGCFenceCircle class provides a cicle used by GeoFence support.
bool loadFromJson(const QJsonObject &json, QString &errorString)
void saveToJson(QJsonObject &json)
The QGCFencePolygon class provides a polygon used by GeoFence support.
void saveToJson(QJsonObject &json)
bool loadFromJson(const QJsonObject &json, bool required, QString &errorString)
void setInteractive(bool interactive)
void setInteractive(bool interactive)
Q_INVOKABLE void appendVertex(const QGeoCoordinate &coordinate)
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
T value(int index) const
void setDirty(bool dirty) override final
QObject * removeAt(int index)
int count() const override final
void clearAndDeleteContents() override final
Clears the list and calls deleteLater on each entry.
Provides access to all app settings.
bool px4Firmware() const
Definition Vehicle.h:512
void capabilityBitsChanged(uint64_t capabilityBits)
uint64_t capabilityBits() const
Definition Vehicle.h:727
bool isOfflineEditingVehicle() const
Definition Vehicle.h:532
GeoFenceManager * geoFenceManager()
Definition Vehicle.h:593
bool apmFirmware() const
Definition Vehicle.h:513
ParameterManager * parameterManager()
Definition Vehicle.h:595
bool initialPlanRequestComplete() const
Definition Vehicle.h:733
bool loadGeoCoordinate(const QJsonValue &jsonValue, bool altitudeRequired, QGeoCoordinate &coordinate, QString &errorString)
void saveGeoCoordinate(const QGeoCoordinate &coordinate, bool writeAltitude, QJsonValue &jsonValue)
Saves a QGeoCoordinate as [lat, lon, alt] array (QGC plan format).
bool validateKeys(const QJsonObject &jsonObject, const QList< KeyValidateInfo > &keyInfo, QString &errorString)
Validates that all required keys are present and that listed keys have the expected type.
constexpr const char * jsonVersionKey
Definition JsonParsing.h:14