13#include <QtCore/QJsonArray>
14#include <QtCore/QJsonDocument>
22 , _managerVehicle (masterController->managerVehicle())
23 , _geoFenceManager (masterController->managerVehicle()->geoFenceManager())
24 , _breachReturnAltitudeFact (0, _breachReturnAltitudeFactName,
FactMetaData::valueTypeDouble)
25 , _breachReturnDefaultAltitude (
SettingsManager::instance()->appSettings()->defaultMissionItemAltitude()->rawValue().toDouble())
27 if (_metaDataMap.isEmpty()) {
31 _breachReturnAltitudeFact.setMetaData(_metaDataMap[_breachReturnAltitudeFactName]);
32 _breachReturnAltitudeFact.setRawValue(_breachReturnDefaultAltitude);
50 qCDebug(GeoFenceControllerLog) <<
"start flyView" << flyView;
59void GeoFenceController::_init(
void)
73void GeoFenceController::_managerVehicleChanged(
Vehicle* managerVehicle)
75 if (_managerVehicle) {
76 _geoFenceManager->disconnect(
this);
77 _managerVehicle->disconnect(
this);
79 _managerVehicle =
nullptr;
80 _geoFenceManager =
nullptr;
83 _managerVehicle = managerVehicle;
84 if (!_managerVehicle) {
85 qWarning() <<
"GeoFenceController::managerVehicleChanged managerVehicle=nullptr";
96 Q_UNUSED(capabilityBits);
118 QList<JsonHelper::KeyValidateInfo> keyInfoList = {
120 { _jsonCirclesKey, QJsonValue::Array,
true },
121 { _jsonPolygonsKey, QJsonValue::Array,
true },
122 { _jsonBreachReturnKey, QJsonValue::Array,
false },
129 errorString = tr(
"GeoFence supports version %1").arg(_jsonCurrentVersion);
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");
144 _polygons.
append(fencePolygon);
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");
158 _circles.
append(fenceCircle);
161 if (json.contains(_jsonBreachReturnKey)) {
165 _breachReturnAltitudeFact.setRawValue(_breachReturnPoint.altitude());
167 _breachReturnPoint = QGeoCoordinate();
168 _breachReturnAltitudeFact.setRawValue(_breachReturnDefaultAltitude);
181 QJsonArray jsonPolygonArray;
182 for (
int i=0; i<_polygons.
count(); i++) {
183 QJsonObject jsonPolygon;
186 jsonPolygonArray.append(jsonPolygon);
188 json[_jsonPolygonsKey] = jsonPolygonArray;
190 QJsonArray jsonCircleArray;
191 for (
int i=0; i<_circles.
count(); i++) {
192 QJsonObject jsonCircle;
195 jsonCircleArray.append(jsonCircle);
197 json[_jsonCirclesKey] = jsonCircleArray;
199 if (_breachReturnPoint.isValid()) {
200 QJsonValue jsonCoordinate;
202 _breachReturnPoint.setAltitude(_breachReturnAltitudeFact.rawValue().toDouble());
204 json[_jsonBreachReturnKey] = jsonCoordinate;
218 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::removeAllFromVehicle called while offline";
220 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::removeAllFromVehicle called while syncInProgress";
229 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::loadFromVehicle called while offline";
231 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::loadFromVehicle called while syncInProgress";
233 _itemsRequested =
true;
241 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::sendToVehicle called while offline";
243 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::sendToVehicle called while syncInProgress";
245 qCDebug(GeoFenceControllerLog) <<
"GeoFenceController::sendToVehicle";
246 _geoFenceManager->
sendToVehicle(_breachReturnPoint, _polygons, _circles);
264 if (
dirty != _dirty) {
267 for (
int i=0; i<_polygons.
count(); i++) {
271 for (
int i=0; i<_circles.
count(); i++) {
280void GeoFenceController::_polygonDirtyChanged(
bool dirty)
287void GeoFenceController::_setDirty(
void)
292void GeoFenceController::_setFenceFromManager(
const QList<QGCFencePolygon>& polygons,
293 const QList<QGCFenceCircle>& circles)
309void GeoFenceController::_setReturnPointFromManager(QGeoCoordinate breachReturnPoint)
313 if (_breachReturnPoint.isValid()) {
314 _breachReturnAltitudeFact.setRawValue(_breachReturnPoint.altitude());
316 _breachReturnAltitudeFact.setRawValue(_breachReturnDefaultAltitude);
320void GeoFenceController::_managerLoadComplete(
void)
328 _setFenceFromManager(_geoFenceManager->
polygons(), _geoFenceManager->
circles());
332 _itemsRequested =
false;
335void GeoFenceController::_managerSendComplete(
bool error)
343void GeoFenceController::_managerRemoveAllComplete(
bool error)
353 return _polygons.
count() > 0 || _circles.
count() > 0;
358 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle _flyView" <<
_flyView;
360 qCCritical(GeoFenceControllerLog) <<
"GeoFenceController::showPlanFromManagerVehicle called while offline";
363 _itemsRequested =
true;
366 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: !initialPlanRequestComplete, wait for signal";
370 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: syncInProgress wait for signal";
374 qCDebug(GeoFenceControllerLog) <<
"showPlanFromManagerVehicle: sync complete simulate signal";
375 _itemsRequested =
true;
376 _managerLoadComplete();
382void GeoFenceController::addInclusionPolygon(QGeoCoordinate topLeft, QGeoCoordinate bottomRight)
384 QGeoCoordinate topRight(topLeft.latitude(),
bottomRight.longitude());
385 QGeoCoordinate bottomLeft(
bottomRight.latitude(), topLeft.longitude());
387 double halfWidthMeters = topLeft.distanceTo(topRight) / 2.0;
388 double halfHeightMeters = topLeft.distanceTo(bottomLeft) / 2.0;
390 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
391 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
392 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
395 halfWidthMeters = qMin(halfWidthMeters * 0.75, 1500.0);
396 halfHeightMeters = qMin(halfHeightMeters * 0.75, 1500.0);
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);
409 _polygons.
append(polygon);
417 QGeoCoordinate topRight(topLeft.latitude(),
bottomRight.longitude());
418 QGeoCoordinate bottomLeft(
bottomRight.latitude(), topLeft.longitude());
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);
425 QGeoCoordinate centerLeftEdge = topLeft.atDistanceAndAzimuth(halfHeightMeters, 180);
426 QGeoCoordinate centerTopEdge = topLeft.atDistanceAndAzimuth(halfWidthMeters, 90);
427 QGeoCoordinate center(centerLeftEdge.latitude(), centerTopEdge.longitude());
438 if (index < 0 || index > _polygons.
count() - 1) {
443 polygon->deleteLater();
448 if (index < 0 || index > _circles.
count() - 1) {
453 circle->deleteLater();
458 for (
int i=0; i<_polygons.
count(); i++) {
461 for (
int i=0; i<_circles.
count(); i++) {
468 return _managerVehicle->
capabilityBits() & MAV_PROTOCOL_CAPABILITY_MISSION_FENCE;
499 if(!apm_fence_enabled || !apm_fence_type_circle)
508void GeoFenceController::_parametersReady(
void)
515 if (_px4ParamCircularFenceFact) {
516 _px4ParamCircularFenceFact->disconnect(
this);
517 _px4ParamCircularFenceFact =
nullptr;
519 if (_apmParamCircularFenceRadiusFact) {
520 _apmParamCircularFenceRadiusFact->disconnect(
this);
521 _apmParamCircularFenceRadiusFact =
nullptr;
523 if (_apmParamCircularFenceEnabledFact) {
524 _apmParamCircularFenceEnabledFact->disconnect(
this);
525 _apmParamCircularFenceEnabledFact =
nullptr;
527 if (_apmParamCircularFenceTypeFact) {
528 _apmParamCircularFenceTypeFact->disconnect(
this);
529 _apmParamCircularFenceTypeFact =
nullptr;
572 return _polygons.
count() == 0 && _circles.
count() == 0 && !_breachReturnPoint.isValid();
#define QGC_LOGGING_CATEGORY(name, categoryStr)
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 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 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 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 ¶mName) const
Fact * getParameter(int componentId, const QString ¶mName)
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 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)
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.
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
constexpr const char * jsonVersionKey
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