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