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) {
268 for (
int i=0; i<_polygons.
count(); i++) {
272 for (
int i=0; i<_circles.
count(); i++) {
281void GeoFenceController::_polygonDirtyChanged(
bool dirty)
288void GeoFenceController::_setDirty(
void)
293void GeoFenceController::_setFenceFromManager(
const QList<QGCFencePolygon>& polygons,
294 const QList<QGCFenceCircle>& circles)
310void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint)
314 if (_breachReturnPoint.isValid()) {
315 _breachReturnAltitudeFact.
setRawValue(_breachReturnPoint.altitude());
317 _breachReturnAltitudeFact.
setRawValue(_breachReturnDefaultAltitude);
321void GeoFenceController::_managerLoadComplete(
void)
329 _setFenceFromManager(_geoFenceManager->
polygons(), _geoFenceManager->
circles());
333 _itemsRequested =
false;
336void GeoFenceController::_managerSendComplete(
bool error)
344void GeoFenceController::_managerRemoveAllComplete(
bool error)
354 return _polygons.
count() > 0 || _circles.
count() > 0;
359 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle _flyView" <<
_flyView;
361 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::showPlanFromManagerVehicle called while offline";
364 _itemsRequested =
true;
367 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: !initialPlanRequestComplete, wait for signal";
371 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: syncInProgress wait for signal";
375 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: sync complete simulate signal";
376 _itemsRequested =
true;
377 _managerLoadComplete();
385 QGeoCoordinate topRight(topLeft.latitude(), bottomRight.longitude());
386 QGeoCoordinate bottomLeft(bottomRight.latitude(), topLeft.longitude());
388 double halfWidthMeters = topLeft.distanceTo(topRight) / 2.0;
389 double halfHeightMeters = topLeft.distanceTo(bottomLeft) / 2.0;
391 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
392 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
393 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
396 halfWidthMeters = qMin(halfWidthMeters * 0.75, 1500.0);
397 halfHeightMeters = qMin(halfHeightMeters * 0.75, 1500.0);
400 topLeft = center.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 0);
401 topRight = center.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 0);
402 bottomLeft = center.atDistanceAndAzimuth(halfWidthMeters, -90).atDistanceAndAzimuth(halfHeightMeters, 180);
403 bottomRight = center.atDistanceAndAzimuth(halfWidthMeters, 90).atDistanceAndAzimuth(halfHeightMeters, 180);
410 _polygons.
append(polygon);
418 QGeoCoordinate topRight(topLeft.latitude(), bottomRight.longitude());
419 QGeoCoordinate bottomLeft(bottomRight.latitude(), topLeft.longitude());
422 double halfWidthMeters = topLeft.distanceTo(topRight) / 2.0;
423 double halfHeightMeters = topLeft.distanceTo(bottomLeft) / 2.0;
424 double radius = qMin(qMin(halfWidthMeters, halfHeightMeters) * 0.75, 1500.0);
426 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
427 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
428 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
439 if (index < 0 || index > _polygons.
count() - 1) {
444 polygon->deleteLater();
449 if (index < 0 || index > _circles.
count() - 1) {
454 circle->deleteLater();
459 for (
int i=0; i<_polygons.
count(); i++) {
462 for (
int i=0; i<_circles.
count(); i++) {
469 return _managerVehicle->
capabilityBits() & MAV_PROTOCOL_CAPABILITY_MISSION_FENCE;
500 if(!apm_fence_enabled || !apm_fence_type_circle)
509void GeoFenceController::_parametersReady(
void)
516 if (_px4ParamCircularFenceFact) {
517 _px4ParamCircularFenceFact->disconnect(
this);
518 _px4ParamCircularFenceFact =
nullptr;
520 if (_apmParamCircularFenceRadiusFact) {
521 _apmParamCircularFenceRadiusFact->disconnect(
this);
522 _apmParamCircularFenceRadiusFact =
nullptr;
524 if (_apmParamCircularFenceEnabledFact) {
525 _apmParamCircularFenceEnabledFact->disconnect(
this);
526 _apmParamCircularFenceEnabledFact =
nullptr;
528 if (_apmParamCircularFenceTypeFact) {
529 _apmParamCircularFenceTypeFact->disconnect(
this);
530 _apmParamCircularFenceTypeFact =
nullptr;
573 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
Value after translation.
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 setDirty(bool dirty)
void setDirty(bool dirty)
void setInteractive(bool interactive)
Q_INVOKABLE void appendVertex(const QGeoCoordinate &coordinate)
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
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