Newer
Older
#include "WimaPlaner.h"
Valentin Platzgummer
committed
#include "MissionController.h"
#include "MissionSettingsItem.h"
#include "PlanMasterController.h"
#include "QGCApplication.h"
#include "QGCMapPolygon.h"
#include "SimpleMissionItem.h"
#include "Geometry/GeoUtilities.h"
#include "Geometry/PlanimetryCalculus.h"
#include "OptimisationTools.h"
#include "CircularSurvey.h"
#include "Geometry/WimaArea.h"
#include "Geometry/WimaAreaData.h"
#include "WimaBridge.h"
const char *WimaPlaner::wimaFileExtension = "wima";
const char *WimaPlaner::areaItemsName = "AreaItems";
const char *WimaPlaner::missionItemsName = "MissionItems";
WimaPlaner::WimaPlaner(QObject *parent)
: QObject(parent), _currentAreaIndex(-1), _wimaBridge(nullptr),
_joinedArea(this), _joinedAreaValid(false), _measurementArea(this),
_serviceArea(this), _corridor(this), _TSComplexItem(nullptr),
_surveyRefChanging(false), _measurementAreaChanging(false),
_corridorChanging(false), _serviceAreaChanging(false),
_syncronizedWithController(false), _readyForSync(false) {
_lastMeasurementAreaPath = _measurementArea.path();
_lastServiceAreaPath = _serviceArea.path();
_lastCorridorPath = _corridor.path();
connect(this, &WimaPlaner::currentPolygonIndexChanged, this,
&WimaPlaner::recalcPolygonInteractivity);
connect(&_updateTimer, &QTimer::timeout, this, &WimaPlaner::updateTimerSlot);
connect(this, &WimaPlaner::joinedAreaValidChanged, this,
&WimaPlaner::updateMission);
_updateTimer.setInterval(300); // 300 ms means: max update time 2*300 ms
_updateTimer.start();
// for debugging and testing purpose, remove if not needed anymore
connect(&_autoLoadTimer, &QTimer::timeout, this,
&WimaPlaner::autoLoadMission);
_autoLoadTimer.setSingleShot(true);
_autoLoadTimer.start(300);
_calcArrivalAndReturnPathTimer.setInterval(100);
_calcArrivalAndReturnPathTimer.setSingleShot(true);
connect(&_calcArrivalAndReturnPathTimer, &QTimer::timeout, this,
&WimaPlaner::calcArrivalAndReturnPath);
QmlObjectListModel *WimaPlaner::visualItems() { return &_visualItems; }
QStringList WimaPlaner::loadNameFilters() const {
QStringList filters;
filters << tr("Supported types (*.%1 *.%2)")
.arg(wimaFileExtension)
.arg(AppSettings::planFileExtension)
<< tr("All Files (*.*)");
return filters;
QStringList WimaPlaner::saveNameFilters() const {
QStringList filters;
filters << tr("Supported types (*.%1 *.%2)")
.arg(wimaFileExtension)
.arg(AppSettings::planFileExtension);
return filters;
QGeoCoordinate WimaPlaner::joinedAreaCenter() const {
return _joinedArea.center();
void WimaPlaner::setMasterController(PlanMasterController *masterC) {
_masterController = masterC;
emit masterControllerChanged();
void WimaPlaner::setMissionController(MissionController *missionC) {
_missionController = missionC;
emit missionControllerChanged();
void WimaPlaner::setCurrentPolygonIndex(int index) {
if (index >= 0 && index < _visualItems.count() &&
index != _currentAreaIndex) {
_currentAreaIndex = index;
emit currentPolygonIndexChanged(index);
}
void WimaPlaner::setWimaBridge(WimaBridge *bridge) {
if (bridge != nullptr) {
_wimaBridge = bridge;
emit wimaBridgeChanged();
}
bool WimaPlaner::syncronizedWithController() {
return _syncronizedWithController;
Valentin Platzgummer
committed
}
bool WimaPlaner::readyForSync() { return _readyForSync; }
WimaPlaner *WimaPlaner::thisPointer() { return this; }
void WimaPlaner::removeArea(int index) {
if (index >= 0 && index < _visualItems.count()) {
WimaArea *area = qobject_cast<WimaArea *>(_visualItems.removeAt(index));
if (area == nullptr) {
qWarning("WimaPlaner::removeArea(): nullptr catched, internal error.");
return;
area->clear();
area->borderPolygon()->clear();
emit visualItemsChanged();
if (_visualItems.count() == 0) {
// this branch is reached if all items are removed
// to guarentee proper behavior, _currentAreaIndex must be set to a
// invalid value, as on constructor init.
resetAllInteractive();
_currentAreaIndex = -1;
return;
if (_currentAreaIndex >= _visualItems.count()) {
setCurrentPolygonIndex(_visualItems.count() - 1);
recalcPolygonInteractivity(_currentAreaIndex);
} else {
qWarning("Index out of bounds!");
}
bool WimaPlaner::addMeasurementArea() {
if (!_visualItems.contains(&_measurementArea)) {
_visualItems.append(&_measurementArea);
int newIndex = _visualItems.count() - 1;
setCurrentPolygonIndex(newIndex);
emit visualItemsChanged();
return true;
} else {
return false;
}
bool WimaPlaner::addServiceArea() {
if (!_visualItems.contains(&_serviceArea)) {
_visualItems.append(&_serviceArea);
int newIndex = _visualItems.count() - 1;
setCurrentPolygonIndex(newIndex);
emit visualItemsChanged();
return true;
} else {
return false;
}
}
bool WimaPlaner::addCorridor() {
if (!_visualItems.contains(&_corridor)) {
_visualItems.append(&_corridor);
int newIndex = _visualItems.count() - 1;
setCurrentPolygonIndex(newIndex);
emit visualItemsChanged();
return true;
} else {
return false;
}
void WimaPlaner::removeAll() {
bool changesApplied = false;
while (_visualItems.count() > 0) {
removeArea(0);
changesApplied = true;
}
_missionController->removeAll();
_TSComplexItem = nullptr;
_surveyRefChanging = false;
emit currentFileChanged();
if (changesApplied)
emit visualItemsChanged();
}
bool WimaPlaner::updateMission() {
setReadyForSync(false);
if (!_joinedAreaValid)
return false;
// extract old survey data
QmlObjectListModel *missionItems = _missionController->visualItems();
int surveyIndex = missionItems->indexOf(_TSComplexItem);
// create survey item if not yet present
if (surveyIndex == -1) {
_missionController->insertComplexMissionItem(
_missionController->circularSurveyComplexItemName(),
_measurementArea.center(), missionItems->count());
_TSComplexItem = qobject_cast<CircularSurvey *>(
missionItems->get(missionItems->count() - 1));
if (_TSComplexItem == nullptr) {
qWarning("WimaPlaner::updateMission(): survey == nullptr");
return false;
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
// establish connections
_TSComplexItem->setRefPoint(_measurementArea.center());
_lastSurveyRefPoint = _measurementArea.center();
_surveyRefChanging = false;
_TSComplexItem->setIsInitialized(
true); // prevents reinitialisation from gui
connect(_TSComplexItem, &TransectStyleComplexItem::missionItemReady, this,
&WimaPlaner::calcArrivalAndReturnPath);
}
// update survey area
_TSComplexItem->surveyAreaPolygon()->clear();
_TSComplexItem->surveyAreaPolygon()->appendVertices(
_measurementArea.coordinateList());
setReadyForSync(true);
return true;
}
void WimaPlaner::saveToCurrent() { saveToFile(_currentFile); }
void WimaPlaner::saveToFile(const QString &filename) {
if (filename.isEmpty()) {
return;
}
QString planFilename = filename;
if (!QFileInfo(filename).fileName().contains(".")) {
planFilename += QString(".%1").arg(wimaFileExtension);
}
QFile file(planFilename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qgcApp()->showMessage(
tr("Plan save error %1 : %2").arg(filename).arg(file.errorString()));
_currentFile.clear();
emit currentFileChanged();
} else {
FileType fileType = FileType::WimaFile;
if (planFilename.contains(QString(".%1").arg(wimaFileExtension))) {
fileType = FileType::WimaFile;
} else if (planFilename.contains(
QString(".%1").arg(AppSettings::planFileExtension))) {
fileType = FileType::PlanFile;
if (planFilename.contains(".")) {
qgcApp()->showMessage(tr("File format not supported"));
} else {
qgcApp()->showMessage(tr("File without file extension not accepted."));
return;
}
}
QJsonDocument saveDoc = saveToJson(fileType);
file.write(saveDoc.toJson());
if (_currentFile != planFilename) {
_currentFile = planFilename;
emit currentFileChanged();
bool WimaPlaner::loadFromCurrent() { return loadFromFile(_currentFile); }
bool WimaPlaner::loadFromFile(const QString &filename) {
#define debug 0
QString errorString;
QString errorMessage =
tr("Error loading Plan file (%1). %2").arg(filename).arg("%1");
if (filename.isEmpty()) {
return false;
}
QFileInfo fileInfo(filename);
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorString = file.errorString() + QStringLiteral(" ") + filename;
qgcApp()->showMessage(errorMessage.arg(errorString));
return false;
}
if (fileInfo.suffix() == wimaFileExtension) {
QJsonDocument jsonDoc;
QByteArray bytes = file.readAll();
if (!JsonHelper::isJsonFile(bytes, jsonDoc, errorString)) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return false;
}
QJsonObject json = jsonDoc.object();
// AreaItems
QJsonArray areaArray = json[areaItemsName].toArray();
_visualItems.clear();
int validAreaCounter = 0;
for (int i = 0; i < areaArray.size() && validAreaCounter < 3; i++) {
QJsonObject jsonArea = areaArray[i].toObject();
if (jsonArea.contains(WimaArea::areaTypeName) &&
jsonArea[WimaArea::areaTypeName].isString()) {
if (jsonArea[WimaArea::areaTypeName] ==
WimaMeasurementArea::WimaMeasurementAreaName) {
bool success = _measurementArea.loadFromJson(jsonArea, errorString);
if (!success) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return false;
}
_lastMeasurementAreaPath =
_measurementArea.path(); // prevents error messages at this point
validAreaCounter++;
_visualItems.append(&_measurementArea);
emit visualItemsChanged();
} else if (jsonArea[WimaArea::areaTypeName] ==
WimaServiceArea::wimaServiceAreaName) {
bool success = _serviceArea.loadFromJson(jsonArea, errorString);
if (!success) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return false;
}
_lastServiceAreaPath =
_serviceArea.path(); // prevents error messages at this point
validAreaCounter++;
_visualItems.append(&_serviceArea);
emit visualItemsChanged();
} else if (jsonArea[WimaArea::areaTypeName] ==
WimaCorridor::WimaCorridorName) {
bool success = _corridor.loadFromJson(jsonArea, errorString);
if (!success) {
qgcApp()->showMessage(errorMessage.arg(errorString));
return false;
}
_lastCorridorPath =
_corridor.path(); // prevents error messages at this point
validAreaCounter++;
_visualItems.append(&_corridor);
emit visualItemsChanged();
} else {
errorString +=
QString(tr("%s not supported.\n").arg(WimaArea::areaTypeName));
qgcApp()->showMessage(errorMessage.arg(errorString));
return false;
} else {
errorString += QString(tr("Invalid or non existing entry for %s.\n")
.arg(WimaArea::areaTypeName));
_currentFile.sprintf("%s/%s.%s", fileInfo.path().toLocal8Bit().data(),
fileInfo.completeBaseName().toLocal8Bit().data(),
wimaFileExtension);
emit currentFileChanged();
QJsonObject missionObject = json[missionItemsName].toObject();
// qWarning() << json[missionItemsName].type();
QJsonDocument missionJsonDoc = QJsonDocument(missionObject);
// create temporary file with missionItems
QFile temporaryFile;
QString cropedFileName = filename.section("/", 0, -2);
#if debug
qWarning() << cropedFileName;
#endif
QString temporaryFileName;
for (int i = 0;; i++) {
temporaryFileName =
cropedFileName +
QString("/temp%1.%2").arg(i).arg(AppSettings::planFileExtension);
// qWarning() << temporaryFileName;
if (!QFile::exists(temporaryFileName)) {
temporaryFile.setFileName(temporaryFileName);
if (temporaryFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
break;
}
}
if (i > 1000) {
qWarning(
"WimaPlaner::loadFromFile(): not able to create temporary file.");
// qWarning() << missionJsonDoc.toVariant().toString();
temporaryFile.write(missionJsonDoc.toJson());
temporaryFile.close();
// load from temporary file
_masterController->loadFromFile(temporaryFileName);
QmlObjectListModel *missionItems = _missionController->visualItems();
_TSComplexItem = nullptr;
for (int i = 0; i < missionItems->count(); i++) {
_TSComplexItem = missionItems->value<CircularSurvey *>(i);
if (_TSComplexItem != nullptr) {
_lastSurveyRefPoint = _TSComplexItem->refPoint();
_surveyRefChanging = false;
_TSComplexItem->setIsInitialized(
true); // prevents reinitialisation from gui
connect(_TSComplexItem, &TransectStyleComplexItem::missionItemReady,
this, &WimaPlaner::calcArrivalAndReturnPath);
break;
}
// if (_circularSurvey == nullptr)
if (!recalcJoinedArea())
return false;
if (!updateMission())
return false;
// remove temporary file
if (!temporaryFile.remove()) {
qWarning(
"WimaPlaner::loadFromFile(): not able to remove temporary file.");
setSyncronizedWithController(false);
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
} else if (fileInfo.suffix() == AppSettings::planFileExtension) {
_masterController->loadFromFile(filename);
return true; // might be wrong return value
} else {
errorString += QString(tr("File extension not supported.\n"));
qgcApp()->showMessage(errorMessage.arg(errorString));
return false;
}
}
void WimaPlaner::recalcPolygonInteractivity(int index) {
if (index >= 0 && index < _visualItems.count()) {
resetAllInteractive();
WimaArea *interactivePoly =
qobject_cast<WimaArea *>(_visualItems.get(index));
if (interactivePoly != nullptr)
interactivePoly->setWimaAreaInteractive(true);
}
}
bool WimaPlaner::calcArrivalAndReturnPath() {
setReadyForSync(false);
// extract old survey data
QmlObjectListModel *missionItems = _missionController->visualItems();
int surveyIndex = missionItems->indexOf(_TSComplexItem);
if (surveyIndex == -1) {
qWarning("WimaPlaner::calcArrivalAndReturnPath(): no survey item");
return false;
}
bool restorePlanViewIndex = false;
if (surveyIndex == _missionController->currentPlanViewIndex())
restorePlanViewIndex = true;
// remove old arrival and return path
int size = missionItems->count();
for (int i = surveyIndex + 1; i < size; i++)
_missionController->removeMissionItem(surveyIndex + 1);
for (int i = surveyIndex - 1; i > 1; i--)
_missionController->removeMissionItem(i);
// set home position to serArea center
MissionSettingsItem *settingsItem =
qobject_cast<MissionSettingsItem *>(missionItems->get(0));
if (settingsItem == nullptr) {
qWarning("WimaPlaner::calcArrivalAndReturnPath(): settingsItem == nullptr");
return false;
}
// set altitudes, temporary measure to solve bugs
QGeoCoordinate center = _serviceArea.center();
center.setAltitude(0);
_serviceArea.setCenter(center);
center = _measurementArea.center();
center.setAltitude(0);
_measurementArea.setCenter(center);
center = _corridor.center();
center.setAltitude(0);
_corridor.setCenter(center);
// set HomePos. to serArea center
settingsItem->setCoordinate(_serviceArea.center());
// set takeoff position
bool setCommandNeeded = false;
if (missionItems->count() < 3) {
setCommandNeeded = true;
_missionController->insertSimpleMissionItem(_serviceArea.center(), 1);
}
SimpleMissionItem *takeOffItem =
qobject_cast<SimpleMissionItem *>(missionItems->get(1));
if (takeOffItem == nullptr) {
qWarning("WimaPlaner::calcArrivalAndReturnPath(): takeOffItem == nullptr");
return false;
}
if (setCommandNeeded)
_missionController->setTakeoffCommand(*takeOffItem);
takeOffItem->setCoordinate(_serviceArea.center());
if (_TSComplexItem->visualTransectPoints().size() == 0) {
qWarning("WimaPlaner::calcArrivalAndReturnPath(): survey no points.");
return false;
}
// calculate path from take off to survey
QGeoCoordinate start = _serviceArea.center();
QGeoCoordinate end = _TSComplexItem->coordinate();
#ifdef QT_DEBUG
// if (!_visualItems.contains(&_joinedArea))
//_visualItems.append(&_joinedArea);
#endif
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
QVector<QGeoCoordinate> path;
if (!calcShortestPath(start, end, path)) {
qgcApp()->showMessage(QString(tr("Not able to calculate the path from "
"takeoff position to measurement area."))
.toLocal8Bit()
.data());
return false;
}
_arrivalPathLength = path.size() - 1;
int sequenceNumber = 0;
for (int i = 1; i < path.count() - 1; i++) {
sequenceNumber = _missionController->insertSimpleMissionItem(
path[i], missionItems->count() - 1);
_missionController->setCurrentPlanViewIndex(sequenceNumber, true);
}
// calculate return path
start = _TSComplexItem->exitCoordinate();
end = _serviceArea.center();
path.clear();
if (!calcShortestPath(start, end, path)) {
qgcApp()->showMessage(QString(tr("Not able to calculate the path from "
"measurement area to landing position."))
.toLocal8Bit()
.data());
return false;
}
_returnPathLength =
path.size() - 1; // -1: fist item is last measurement point
for (int i = 1; i < path.count() - 1; i++) {
sequenceNumber = _missionController->insertSimpleMissionItem(
path[i], missionItems->count());
_missionController->setCurrentPlanViewIndex(sequenceNumber, true);
}
// create land position item
sequenceNumber = _missionController->insertSimpleMissionItem(
_serviceArea.center(), missionItems->count());
_missionController->setCurrentPlanViewIndex(sequenceNumber, true);
SimpleMissionItem *landItem = qobject_cast<SimpleMissionItem *>(
missionItems->get(missionItems->count() - 1));
if (landItem == nullptr) {
qWarning("WimaPlaner::calcArrivalAndReturnPath(): landItem == nullptr");
return false;
} else {
if (!_missionController->setLandCommand(*landItem))
return false;
}
if (restorePlanViewIndex)
_missionController->setCurrentPlanViewIndex(
missionItems->indexOf(_TSComplexItem), false);
setSyncronizedWithControllerFalse();
setReadyForSync(true);
return true;
}
bool WimaPlaner::recalcJoinedArea() {
setJoinedAreaValid(false);
// check if at least service area and measurement area are available
if (_visualItems.indexOf(&_serviceArea) == -1 ||
_visualItems.indexOf(&_measurementArea) == -1)
return false;
// check if area paths form simple polygons
if (!_serviceArea.isSimplePolygon()) {
qgcApp()->showMessage(
tr("Service area is self intersecting and thus not a simple polygon. "
"Only simple polygons allowed.\n"));
return false;
}
if (!_corridor.isSimplePolygon() && _corridor.count() > 0) {
qgcApp()->showMessage(
tr("Corridor is self intersecting and thus not a simple polygon. Only "
"simple polygons allowed.\n"));
return false;
}
if (!_measurementArea.isSimplePolygon()) {
qgcApp()->showMessage(
tr("Measurement area is self intersecting and thus not a simple "
"polygon. Only simple polygons allowed.\n"));
return false;
}
_joinedArea.setPath(_serviceArea.path());
_joinedArea.join(_corridor);
if (!_joinedArea.join(_measurementArea)) {
/*qgcApp()->showMessage(tr("Not able to join areas. Service area and
measurement"
" must have a overlapping section, or be connected
through a corridor."));*/
return false; // this happens if all areas are pairwise disjoint
}
// join service area, op area and corridor
setJoinedAreaValid(true);
return true;
}
void WimaPlaner::pushToWimaController() {
if (_wimaBridge != nullptr) {
if (!_readyForSync)
return;
WimaPlanData planData = toPlanData();
(void)_wimaBridge->setWimaPlanData(planData);
setSyncronizedWithController(true);
} else {
qWarning("WimaPlaner::uploadToContainer(): no container assigned.");
}
bool WimaPlaner::calcShortestPath(const QGeoCoordinate &start,
const QGeoCoordinate &destination,
QVector<QGeoCoordinate> &path) {
using namespace GeoUtilities;
using namespace PolygonCalculus;
QPolygonF polygon2D;
toCartesianList(_joinedArea.coordinateList(), /*origin*/ start, polygon2D);
QPointF start2D(0, 0);
QPointF end2D;
QVector<QPointF> path2D;
toCartesian(destination, start, end2D);
bool retVal =
PolygonCalculus::shortestPath(polygon2D, start2D, end2D, path2D);
toGeoList(path2D, /*origin*/ start, path);
return retVal;
}
void WimaPlaner::resetAllInteractive() {
// Marks all areas as inactive (area.interactive == false)
int itemCount = _visualItems.count();
if (itemCount > 0) {
for (int i = 0; i < itemCount; i++) {
WimaArea *iteratorPoly = qobject_cast<WimaArea *>(_visualItems.get(i));
iteratorPoly->setWimaAreaInteractive(false);
void WimaPlaner::setInteractive() {
recalcPolygonInteractivity(_currentAreaIndex);
Valentin Platzgummer
committed
/*!
* \fn WimaPlanData WimaPlaner::toPlanData()
*
* Returns a \c WimaPlanData object containing information about the current
* mission. The \c WimaPlanData object holds only the data which is relevant for
* the \c WimaController class. Should only be called if updateMission() was
* successful.
Valentin Platzgummer
committed
*
* \sa WimaController, WimaPlanData
*/
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
WimaPlanData WimaPlaner::toPlanData() {
WimaPlanData planData;
// store areas
planData.append(WimaMeasurementAreaData(_measurementArea));
planData.append(WimaServiceAreaData(_serviceArea));
planData.append(WimaCorridorData(_corridor));
planData.append(WimaJoinedAreaData(_joinedArea));
// convert mission items to mavlink commands
QObject deleteObject; // used to automatically delete content of
// rgMissionItems after this function call
QList<MissionItem *> rgMissionItems;
QmlObjectListModel *visualItems = _missionController->visualItems();
QmlObjectListModel visualItemsToCopy;
for (unsigned long i = _arrivalPathLength + 1;
i < visualItems->count() - _returnPathLength; i++)
visualItemsToCopy.append(visualItems->get(i));
MissionController::convertToMissionItems(&visualItemsToCopy, rgMissionItems,
&deleteObject);
// store mavlink commands
planData.append(rgMissionItems);
return planData;
}
void WimaPlaner::setSyncronizedWithController(bool sync) {
if (_syncronizedWithController != sync) {
_syncronizedWithController = sync;
emit syncronizedWithControllerChanged();
}
}
void WimaPlaner::setReadyForSync(bool ready) {
if (_readyForSync != ready) {
_readyForSync = ready;
emit readyForSyncChanged();
}
}
void WimaPlaner::setJoinedAreaValid(bool valid) {
if (_joinedAreaValid != valid) {
_joinedAreaValid = valid;
emit joinedAreaValidChanged();
}
}
void WimaPlaner::updateTimerSlot() {
// General operation of this function:
// Check if parameter has changed, wait until it stops changing, update
// mission
// circular survey reference point
// if (_missionController != nullptr
// && _missionController->visualItems()->indexOf(_circularSurvey)
// != -1
// && _circularSurvey != nullptr)
// {
// if (_surveyRefChanging) {
// if (_circularSurvey->refPoint() == _lastSurveyRefPoint) { // is
// it still changing?
// calcArrivalAndReturnPath();
// _surveyRefChanging = false;
// }
// } else {
// if (_circularSurvey->refPoint() != _lastSurveyRefPoint) // does
// it started changing?
// _surveyRefChanging = true;
// }
// }
// measurementArea
if (_measurementAreaChanging) {
if (_measurementArea.path() ==
_lastMeasurementAreaPath) { // is it still changing?
setReadyForSync(false);
if (recalcJoinedArea() && calcArrivalAndReturnPath())
setReadyForSync(true);
_measurementAreaChanging = false;
}
} else {
if (_measurementArea.path() !=
_lastMeasurementAreaPath) // does it started changing?
_measurementAreaChanging = true;
}
// corridor
if (_corridorChanging) {
if (_corridor.path() == _lastCorridorPath) { // is it still changing?
setReadyForSync(false);
if (recalcJoinedArea() && calcArrivalAndReturnPath())
setReadyForSync(true);
_corridorChanging = false;
}
} else {
if (_corridor.path() != _lastCorridorPath) // does it started changing?
_corridorChanging = true;
}
// service area
if (_serviceAreaChanging) {
if (_serviceArea.path() == _lastServiceAreaPath) { // is it still changing?
setReadyForSync(false);
if (recalcJoinedArea() && calcArrivalAndReturnPath())
setReadyForSync(true);
_serviceAreaChanging = false;
}
} else {
if (_serviceArea.path() !=
_lastServiceAreaPath) // does it started changing?
_serviceAreaChanging = true;
}
// update old values
// if (_missionController != nullptr
// && _missionController->visualItems()->indexOf(_circularSurvey)
// != -1
// && _circularSurvey != nullptr)
// _lastSurveyRefPoint = _circularSurvey->refPoint();
_lastMeasurementAreaPath = _measurementArea.path();
_lastCorridorPath = _corridor.path();
_lastServiceAreaPath = _serviceArea.path();
}
void WimaPlaner::setSyncronizedWithControllerFalse() {
setSyncronizedWithController(false);
Valentin Platzgummer
committed
}
#ifndef NDEBUG
void WimaPlaner::autoLoadMission() {
loadFromFile("/home/valentin/Desktop/drones/qgroundcontrol/Paths/"
"KlingenbachTest.wima");
pushToWimaController();
void WimaPlaner::startCalcArrivalAndReturnTimer() {
_calcArrivalAndReturnPathTimer.start();
QJsonDocument WimaPlaner::saveToJson(FileType fileType) {
/// This function save all areas (of WimaPlaner) and all mission items (of
/// MissionController) to a QJsonDocument
/// @param fileType is either WimaFile or PlanFile (enum), if fileType ==
/// PlanFile only mission items are stored
QJsonObject json;
if (fileType == FileType::WimaFile) {
QJsonArray jsonArray;
for (int i = 0; i < _visualItems.count(); i++) {
QJsonObject json;
WimaArea *area = qobject_cast<WimaArea *>(_visualItems.get(i));
if (area == nullptr) {
qWarning("WimaPlaner::saveToJson(): Internal error, area == nullptr!");
return QJsonDocument();
}
// check the type of area, create and append the JsonObject to the
// JsonArray once determined
WimaMeasurementArea *opArea = qobject_cast<WimaMeasurementArea *>(area);
if (opArea != nullptr) {
opArea->saveToJson(json);
jsonArray.append(json);
continue;
}
WimaServiceArea *serArea = qobject_cast<WimaServiceArea *>(area);
if (serArea != nullptr) {
serArea->saveToJson(json);
jsonArray.append(json);
continue;
}
WimaCorridor *corridor = qobject_cast<WimaCorridor *>(area);
if (corridor != nullptr) {
corridor->saveToJson(json);
jsonArray.append(json);
continue;
}
// if non of the obove branches was trigger, type must be WimaArea
area->saveToJson(json);
jsonArray.append(json);
json[areaItemsName] = jsonArray;
json[missionItemsName] = _masterController->saveToJson().object();
return QJsonDocument(json);
} else if (fileType == FileType::PlanFile) {
return _masterController->saveToJson();
}
return QJsonDocument(json);
}