14#include <QtCore/QJsonArray>
15#include <QtCore/QJsonDocument>
23 , _managerVehicle (masterController->managerVehicle())
24 , _geoFenceManager (masterController->managerVehicle()->geoFenceManager())
25 , _breachReturnAltitudeFact (0, _breachReturnAltitudeFactName,
FactMetaData::valueTypeDouble)
26 , _breachReturnDefaultAltitude (
SettingsManager::instance()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble())
28 if (_metaDataMap.isEmpty()) {
32 _breachReturnAltitudeFact.setMetaData(_metaDataMap[_breachReturnAltitudeFactName]);
33 _breachReturnAltitudeFact.setRawValue(_breachReturnDefaultAltitude);
51 qCDebug(GeoFenceControllerLog) <<
"start flyView" << flyView;
60void GeoFenceController::_init(
void)
74void GeoFenceController::_managerVehicleChanged(
Vehicle* managerVehicle)
76 if (_managerVehicle) {
77 _geoFenceManager->disconnect(
this);
78 _managerVehicle->disconnect(
this);
80 _managerVehicle =
nullptr;
81 _geoFenceManager =
nullptr;
84 _managerVehicle = managerVehicle;
85 if (!_managerVehicle) {
86 qWarning() <<
"GeoFenceController::managerVehicleChanged managerVehicle=nullptr";
97 Q_UNUSED(capabilityBits);
119 QList<JsonParsing::KeyValidateInfo> keyInfoList = {
121 { _jsonCirclesKey, QJsonValue::Array,
true },
122 { _jsonPolygonsKey, QJsonValue::Array,
true },
123 { _jsonBreachReturnKey, QJsonValue::Array,
false },
130 errorString = tr(
"GeoFence supports version %1").arg(_jsonCurrentVersion);
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");
145 _polygons.
append(fencePolygon);
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");
159 _circles.
append(fenceCircle);
162 if (json.contains(_jsonBreachReturnKey)) {
166 _breachReturnAltitudeFact.
setRawValue(_breachReturnPoint.altitude());
168 _breachReturnPoint = QGeoCoordinate();
169 _breachReturnAltitudeFact.
setRawValue(_breachReturnDefaultAltitude);
182 QJsonArray jsonPolygonArray;
183 for (
int i=0; i<_polygons.
count(); i++) {
184 QJsonObject jsonPolygon;
187 jsonPolygonArray.append(jsonPolygon);
189 json[_jsonPolygonsKey] = jsonPolygonArray;
191 QJsonArray jsonCircleArray;
192 for (
int i=0; i<_circles.
count(); i++) {
193 QJsonObject jsonCircle;
196 jsonCircleArray.append(jsonCircle);
198 json[_jsonCirclesKey] = jsonCircleArray;
200 if (_breachReturnPoint.isValid()) {
201 QJsonValue jsonCoordinate;
203 _breachReturnPoint.setAltitude(_breachReturnAltitudeFact.
rawValue().toDouble());
205 json[_jsonBreachReturnKey] = jsonCoordinate;
219 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::removeAllFromVehicle called while offline";
221 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::removeAllFromVehicle called while syncInProgress";
230 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::loadFromVehicle called while offline";
232 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::loadFromVehicle called while syncInProgress";
234 _itemsRequested =
true;
242 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::sendToVehicle called while offline";
244 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::sendToVehicle called while syncInProgress";
246 qCDebug(GeoFenceControllerLog) <<
"GeoFenceController::sendToVehicle";
247 _geoFenceManager->
sendToVehicle(_breachReturnPoint, _polygons, _circles);
265 if (
dirty != _dirty) {
276void GeoFenceController::_fenceListDirtyChanged(
bool dirty)
283void GeoFenceController::_setDirty(
void)
288void GeoFenceController::_setFenceFromManager(
const QList<QGCFencePolygon>& polygons,
289 const QList<QGCFenceCircle>& circles)
305void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint)
309 if (_breachReturnPoint.isValid()) {
310 _breachReturnAltitudeFact.
setRawValue(_breachReturnPoint.altitude());
312 _breachReturnAltitudeFact.
setRawValue(_breachReturnDefaultAltitude);
316void GeoFenceController::_managerLoadComplete(
void)
324 _setFenceFromManager(_geoFenceManager->
polygons(), _geoFenceManager->
circles());
328 _itemsRequested =
false;
331void GeoFenceController::_managerSendComplete(
bool error)
339void GeoFenceController::_managerRemoveAllComplete(
bool error)
349 return _polygons.
count() > 0 || _circles.
count() > 0;
354 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle _flyView" <<
_flyView;
356 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::showPlanFromManagerVehicle called while offline";
359 _itemsRequested =
true;
362 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: !initialPlanRequestComplete, wait for signal";
366 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: syncInProgress wait for signal";
370 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: sync complete simulate signal";
371 _itemsRequested =
true;
372 _managerLoadComplete();
380 QGeoCoordinate topRight(topLeft.latitude(), bottomRight.longitude());
381 QGeoCoordinate bottomLeft(bottomRight.latitude(), topLeft.longitude());
383 double halfWidthMeters = topLeft.distanceTo(topRight) / 2.0;
384 double halfHeightMeters = topLeft.distanceTo(bottomLeft) / 2.0;
386 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
387 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
388 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
391 halfWidthMeters = qMin(halfWidthMeters * 0.75, 1500.0);
392 halfHeightMeters = qMin(halfHeightMeters * 0.75, 1500.0);
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);
405 _polygons.
append(polygon);
413 QGeoCoordinate topRight(topLeft.latitude(), bottomRight.longitude());
414 QGeoCoordinate bottomLeft(bottomRight.latitude(), topLeft.longitude());
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);
421 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
422 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
423 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
434 if (index < 0 || index > _polygons.
count() - 1) {
439 polygon->deleteLater();
444 if (index < 0 || index > _circles.
count() - 1) {
449 circle->deleteLater();
454 for (
int i=0; i<_polygons.
count(); i++) {
457 for (
int i=0; i<_circles.
count(); i++) {
464 return _managerVehicle->
capabilityBits() & MAV_PROTOCOL_CAPABILITY_MISSION_FENCE;
495 if(!apm_fence_enabled || !apm_fence_type_circle)
504void GeoFenceController::_parametersReady(
void)
511 if (_px4ParamCircularFenceFact) {
512 _px4ParamCircularFenceFact->disconnect(
this);
513 _px4ParamCircularFenceFact =
nullptr;
515 if (_apmParamCircularFenceRadiusFact) {
516 _apmParamCircularFenceRadiusFact->disconnect(
this);
517 _apmParamCircularFenceRadiusFact =
nullptr;
519 if (_apmParamCircularFenceEnabledFact) {
520 _apmParamCircularFenceEnabledFact->disconnect(
this);
521 _apmParamCircularFenceEnabledFact =
nullptr;
523 if (_apmParamCircularFenceTypeFact) {
524 _apmParamCircularFenceTypeFact->disconnect(
this);
525 _apmParamCircularFenceTypeFact =
nullptr;
568 return _polygons.
count() == 0 && _circles.
count() == 0 && !_breachReturnPoint.isValid();
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void rawValueChanged(const QVariant &value)
void setRawValue(const QVariant &value)
QVariant rawValue() const
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 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 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 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 ¶mName) const
Fact * getParameter(int componentId, const QString ¶mName)
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 containsItemsChanged()
void dirtyChanged(bool dirty)
void loadFromVehicle(void)
bool inProgress(void) const
Master controller for mission, fence, rally.
void managerVehicleChanged(Vehicle *managerVehicle)
Vehicle * managerVehicle(void)
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.
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.
void capabilityBitsChanged(uint64_t capabilityBits)
uint64_t capabilityBits() const
bool isOfflineEditingVehicle() const
GeoFenceManager * geoFenceManager()
ParameterManager * parameterManager()
bool initialPlanRequestComplete() const
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