Newer
Older
#include "MissionController.h"
#include "MissionSettingsItem.h"
#include "PlanMasterController.h"
#include "QGCApplication.h"
#include "SimpleMissionItem.h"
#include "Snake/QNemoHeartbeat.h"
#include <QScopedPointer>
template <typename T>
constexpr typename std::underlying_type<T>::type integral(T value) {
return static_cast<typename std::underlying_type<T>::type>(value);
}
#define SMART_RTL_MAX_ATTEMPTS 3 // times
#define SMART_RTL_ATTEMPT_INTERVAL 200 // ms
#define EVENT_TIMER_INTERVAL 50 // ms
const char *WimaController::areaItemsName = "AreaItems";
const char *WimaController::missionItemsName = "MissionItems";
const char *WimaController::settingsGroup = "WimaController";
const char *WimaController::enableWimaControllerName = "EnableWimaController";
const char *WimaController::overlapWaypointsName = "OverlapWaypoints";
const char *WimaController::maxWaypointsPerPhaseName = "MaxWaypointsPerPhase";
const char *WimaController::startWaypointIndexName = "StartWaypointIndex";
const char *WimaController::showAllMissionItemsName = "ShowAllMissionItems";
const char *WimaController::showCurrentMissionItemsName =
"ShowCurrentMissionItems";
const char *WimaController::flightSpeedName = "FlightSpeed";
const char *WimaController::arrivalReturnSpeedName = "ArrivalReturnSpeed";
const char *WimaController::altitudeName = "Altitude";
WimaController::StatusMap WimaController::_nemoStatusMap{
std::make_pair<int, QString>(0, "No Heartbeat"),
std::make_pair<int, QString>(1, "Connected"),
std::make_pair<int, QString>(-1, "Timeout"),
std::make_pair<int, QString>(-2, "Error")};
WimaController::WimaController(QObject *parent)
: QObject(parent), _joinedArea(), _measurementArea(), _serviceArea(),
_corridor(), _localPlanDataValid(false),
_areaInterface(&_measurementArea, &_serviceArea, &_corridor,
&_joinedArea),
_WMSettings(), _defaultWM(_WMSettings, _areaInterface),
_snakeWM(_WMSettings, _areaInterface),
_rtlWM(_WMSettings, _areaInterface),
_currentWM(&_defaultWM), _WMList{&_defaultWM, &_snakeWM, &_rtlWM},
_metaDataMap(FactMetaData::createMapFromJsonFile(
QStringLiteral(":/json/WimaController.SettingsGroup.json"), this)),
_enableWimaController(settingsGroup,
_metaDataMap[enableWimaControllerName]),
_overlapWaypoints(settingsGroup, _metaDataMap[overlapWaypointsName]),
_maxWaypointsPerPhase(settingsGroup,
_metaDataMap[maxWaypointsPerPhaseName]),
_nextPhaseStartWaypointIndex(settingsGroup,
_metaDataMap[startWaypointIndexName]),
_showAllMissionItems(settingsGroup,
_metaDataMap[showAllMissionItemsName]),
_showCurrentMissionItems(settingsGroup,
_metaDataMap[showCurrentMissionItemsName]),
_flightSpeed(settingsGroup, _metaDataMap[flightSpeedName]),
_arrivalReturnSpeed(settingsGroup, _metaDataMap[arrivalReturnSpeedName]),
_altitude(settingsGroup, _metaDataMap[altitudeName]),
_lowBatteryHandlingTriggered(false), _measurementPathLength(-1),
_batteryLevelTicker(EVENT_TIMER_INTERVAL, 1000 /*ms*/) {
_showAllMissionItems.setRawValue(true);
_showCurrentMissionItems.setRawValue(true);
connect(&_overlapWaypoints, &Fact::rawValueChanged, this,
&WimaController::_updateOverlap);
connect(&_maxWaypointsPerPhase, &Fact::rawValueChanged, this,
&WimaController::_updateMaxWaypoints);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this,
&WimaController::_setStartIndex);
connect(&_flightSpeed, &Fact::rawValueChanged, this,
&WimaController::_updateflightSpeed);
connect(&_arrivalReturnSpeed, &Fact::rawValueChanged, this,
&WimaController::_updateArrivalReturnSpeed);
connect(&_altitude, &Fact::rawValueChanged, this,
&WimaController::_updateAltitude);
// Nemo stuff.
connect(&_nemoInterface, &NemoInterface::progressChanged, this,
&WimaController::_progressChangedHandler);
connect(&_nemoInterface, &NemoInterface::statusChanged, this,
&WimaController::nemoStatusChanged);
connect(&_nemoInterface, &NemoInterface::statusChanged, this,
&WimaController::nemoStatusStringChanged);
// Init waypoint managers.
bool value;
size_t overlap = _overlapWaypoints.rawValue().toUInt(&value);
Q_ASSERT(value);
size_t N = _maxWaypointsPerPhase.rawValue().toUInt(&value);
Q_ASSERT(value);
size_t startIdx = _nextPhaseStartWaypointIndex.rawValue().toUInt(&value);
Q_ASSERT(value);
(void)value;
for (auto manager : _WMList) {
manager->setOverlap(overlap);
manager->setN(N);
manager->setStartIndex(startIdx);
}
// Periodic.
connect(&_eventTimer, &QTimer::timeout, this,
&WimaController::_eventTimerHandler);
_eventTimer.start(EVENT_TIMER_INTERVAL);
// NemoInterface.
connect(&_nemoInterface, &NemoInterface::progressChanged, this,
&WimaController::_progressChangedHandler);
connect(&_nemoInterface, &NemoInterface::statusChanged, this,
&WimaController::nemoStatusChanged);
connect(&_nemoInterface, &NemoInterface::statusChanged, this,
&WimaController::nemoStatusStringChanged);
connect(&_enableSnake, &Fact::rawValueChanged, this,
&WimaController::_enableSnakeChangedHandler);
_enableSnakeChangedHandler();
connect(&_enableWimaController, &Fact::rawValueChanged, [this] {
if (!this->_enableWimaController.rawValue().toBool()) {
this->_enableSnake.setCookedValue(QVariant(false));
}
});
// Snake Waypoint Manager.
connect(&_enableSnake, &Fact::rawValueChanged, this,
&WimaController::_switchToSnakeWaypointManager);
_switchToSnakeWaypointManager(_enableSnake.rawValue());
PlanMasterController *WimaController::masterController() {
}
MissionController *WimaController::missionController() {
QmlObjectListModel *WimaController::visualItems() { return &_areas; }
QmlObjectListModel *WimaController::missionItems() {
return const_cast<QmlObjectListModel *>(&_currentWM->missionItems());
}
QmlObjectListModel *WimaController::currentMissionItems() {
return const_cast<QmlObjectListModel *>(&_currentWM->currentMissionItems());
QVariantList WimaController::waypointPath() {
return const_cast<QVariantList &>(_currentWM->waypointsVariant());
QVariantList WimaController::currentWaypointPath() {
return const_cast<QVariantList &>(_currentWM->currentWaypointsVariant());
Fact *WimaController::enableWimaController() { return &_enableWimaController; }
Fact *WimaController::overlapWaypoints() { return &_overlapWaypoints; }
Fact *WimaController::maxWaypointsPerPhase() { return &_maxWaypointsPerPhase; }
Fact *WimaController::startWaypointIndex() {
return &_nextPhaseStartWaypointIndex;
Fact *WimaController::showAllMissionItems() { return &_showAllMissionItems; }
Fact *WimaController::showCurrentMissionItems() {
Fact *WimaController::flightSpeed() { return &_flightSpeed; }
Fact *WimaController::arrivalReturnSpeed() { return &_arrivalReturnSpeed; }
Fact *WimaController::altitude() { return &_altitude; }
QmlObjectListModel *WimaController::snakeTiles() {
QVariantList WimaController::snakeTileCenterPoints() {
return this->_measurementArea.tileCenterPoints();
QVector<int> WimaController::nemoProgress() {
double WimaController::phaseDistance() const {
qWarning() << "using phaseDistance dummy";
return 0.0;
double WimaController::phaseDuration() const {
qWarning() << "using phaseDuration dummy";
return 0.0;
int WimaController::nemoStatus() const {
return integral(_nemoInterface.status());
}
QString WimaController::nemoStatusString() const {
return _nemoStatusMap.at(nemoStatus());
bool WimaController::snakeCalcInProgress() const {
qWarning() << "using snakeCalcInProgress dummy";
return true;
void WimaController::setMasterController(PlanMasterController *masterC) {
_masterController = masterC;
_WMSettings.setMasterController(masterC);
emit masterControllerChanged();
void WimaController::setMissionController(MissionController *missionC) {
_missionController = missionC;
_WMSettings.setMissionController(missionC);
emit missionControllerChanged();
void WimaController::nextPhase() { _calcNextPhase(); }
void WimaController::previousPhase() {
if (!_currentWM->previous()) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
Valentin Platzgummer
committed
}
void WimaController::resetPhase() {
if (!_currentWM->reset()) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
Valentin Platzgummer
committed
}
void WimaController::requestSmartRTL() {
#ifdef DEBUG_SRTL
qWarning() << "WimaController::requestSmartRTL() called";
#endif
QString errorString("Smart RTL requested.");
if (!_SRTLPrecondition(errorString)) {
qgcApp()->showMessage(errorString);
return;
}
emit smartRTLRequestConfirm();
Valentin Platzgummer
committed
}
auto &items = _currentWM->currentMissionItems();
if (_masterController && _masterController->managerVehicle() &&
items.count() > 0) {
if (!_joinedArea.containsCoordinate(
_masterController->managerVehicle()->coordinate())) {
emit forceUploadConfirm();
return false;
} else {
return forceUpload();
}
} else {
Valentin Platzgummer
committed
}
bool WimaController::forceUpload() {
auto ¤tMissionItems = _currentWM->currentMissionItems();
if (currentMissionItems.count() < 1 || !_missionController ||
!_masterController) {
qWarning() << "WimaController::forceUpload(): error:";
qWarning() << "currentMissionItems.count(): "
<< currentMissionItems.count();
qWarning() << "_missionController: " << _missionController;
qWarning() << "_masterController: " << _masterController;
} else {
_missionController->removeAll();
// Set homeposition of settingsItem.
QmlObjectListModel *visuals = _missionController->visualItems();
MissionSettingsItem *settingsItem =
visuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
Q_ASSERT(false);
qWarning("WimaController::updateCurrentMissionItems(): nullptr");
return false;
} else {
settingsItem->setCoordinate(_WMSettings.homePosition());
// Copy mission items to _missionController and send them.
for (int i = 1; i < currentMissionItems.count(); i++) {
auto *item = currentMissionItems.value<const SimpleMissionItem *>(i);
_missionController->insertSimpleMissionItem(*item, visuals->count());
}
_masterController->sendToVehicle();
return true;
}
Valentin Platzgummer
committed
void WimaController::removeFromVehicle() {
if (_masterController && _missionController) {
_masterController->removeAllFromVehicle();
_missionController->removeAll();
}
void WimaController::executeSmartRTL() {
#ifdef DEBUG_SRTL
qWarning() << "WimaController::executeSmartRTL() called";
#endif
if (_masterController && _masterController->managerVehicle()) {
forceUpload();
_masterController->managerVehicle()->startMission();
}
void WimaController::initSmartRTL() {
#ifdef DEBUG_SRTL
qWarning() << "WimaController::initSmartRTL() called";
#endif
_initSmartRTL();
}
void WimaController::removeVehicleTrajectoryHistory() {
if (_masterController && _masterController->managerVehicle()) {
_masterController->managerVehicle()
->trajectoryPoints()
->clearAndDeleteContents();
}
Valentin Platzgummer
committed
}
bool WimaController::_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;
toCartesian(destination, start, end2D);
QVector<QPointF> path2D;
Valentin Platzgummer
committed
bool retVal =
PolygonCalculus::shortestPath(polygon2D, start2D, end2D, path2D);
toGeoList(path2D, /*origin*/ start, path);
Valentin Platzgummer
committed
Valentin Platzgummer
committed
bool WimaController::setWimaPlanData(QSharedPointer<WimaPlanData> planData) {
// reset visual items
_areas.clear();
_defaultWM.clear();
_snakeWM.clear();
_measurementArea = WimaMeasurementAreaData();
_serviceArea = WimaServiceAreaData();
_corridor = WimaCorridorData();
_joinedArea = WimaJoinedAreaData();
emit visualItemsChanged();
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit waypointPathChanged();
emit currentWaypointPathChanged();
emit snakeTilesChanged();
emit nemoProgressChanged();
Valentin Platzgummer
committed
Valentin Platzgummer
committed
QList<const WimaAreaData *> areaList = planData->areaList();
Valentin Platzgummer
committed
const int numAreas = 4; // extract only numAreas Areas, if there are more
// they are invalid and ignored
for (int i = 0; i < areaList.size(); i++) {
const WimaAreaData *areaData = areaList[i];
Valentin Platzgummer
committed
if (areaData->type() ==
WimaServiceAreaData::typeString) { // is it a service area?
_serviceArea = *qobject_cast<const WimaServiceAreaData *>(areaData);
areaCounter++;
_areas.append(&_serviceArea);
Valentin Platzgummer
committed
Valentin Platzgummer
committed
if (areaData->type() ==
WimaMeasurementAreaData::typeString) { // is it a measurement area?
_measurementArea =
*qobject_cast<const WimaMeasurementAreaData *>(areaData);
areaCounter++;
_areas.append(&_measurementArea);
if (areaData->type() == WimaCorridorData::typeString) { // is it a corridor?
_corridor = *qobject_cast<const WimaCorridorData *>(areaData);
areaCounter++;
//_visualItems.append(&_corridor); // not needed
if (areaData->type() ==
WimaJoinedAreaData::typeString) { // is it a corridor?
_joinedArea = *qobject_cast<const WimaJoinedAreaData *>(areaData);
areaCounter++;
_areas.append(&_joinedArea);
if (areaCounter >= numAreas)
break;
}
if (areaCounter != numAreas) {
Q_ASSERT(false);
return false;
}
Valentin Platzgummer
committed
emit snakeTilesChanged();
// Publish tiles if necessary.
if (!this->_nemoInterface.hasTileData(this->_measurementArea.tileData())) {
this->_nemoInterface.publishTileData(this->_measurementArea.tileData());
this->_measurementArea.progress() =
QVector<int>(this->_measurementArea.tiles()->count, 0);
emit nemoProgressChanged();
} else if (this->_enableSnake.rawValue().toBool()) {
const auto progess = this->_nemoInterface.progress();
if (progess.size() == this->_measurementArea.tiles()->count()) {
this->_measurementArea.progress() = std::move(progress);
emit nemoProgressChanged();
}
}
// Copy raw transects.
this->_rawTransects = planData->transects();
auto tempMissionItems = planData->missionItems();
if (tempMissionItems.size() < 1) {
qWarning("WimaController: Mission items from WimaPlaner empty!");
return false;
}
for (auto *item : tempMissionItems) {
_defaultWM.push_back(item->coordinate());
}
_WMSettings.setHomePosition(QGeoCoordinate(
_serviceArea.depot().latitude(), _serviceArea.depot().longitude(), 0));
// auto tempMissionItems = planData->missionItems();
if (!_defaultWM.reset()) {
Q_ASSERT(false);
return false;
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit waypointPathChanged();
emit currentWaypointPathChanged();
qWarning("WimaController: add snake update here lkjdfl!");
_localPlanDataValid = true;
return true;
WimaController *WimaController::thisPointer() { return this; }
bool WimaController::_calcNextPhase() {
if (!_currentWM->next()) {
Q_ASSERT(false);
return false;
}
Valentin Platzgummer
committed
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
bool WimaController::_setStartIndex() {
bool value;
_currentWM->setStartIndex(
_nextPhaseStartWaypointIndex.rawValue().toUInt(&value) - 1);
Q_ASSERT(value);
(void)value;
Valentin Platzgummer
committed
if (!_currentWM->update()) {
Q_ASSERT(false);
return false;
}
Valentin Platzgummer
committed
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
void WimaController::_recalcCurrentPhase() {
if (!_currentWM->update()) {
Q_ASSERT(false);
}
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
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
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
}
void WimaController::_updateOverlap() {
bool value;
_currentWM->setOverlap(_overlapWaypoints.rawValue().toUInt(&value));
Q_ASSERT(value);
(void)value;
if (!_currentWM->update()) {
assert(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
}
void WimaController::_updateMaxWaypoints() {
bool value;
_currentWM->setN(_maxWaypointsPerPhase.rawValue().toUInt(&value));
Q_ASSERT(value);
(void)value;
if (!_currentWM->update()) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
}
void WimaController::_updateflightSpeed() {
bool value;
_WMSettings.setFlightSpeed(_flightSpeed.rawValue().toDouble(&value));
Q_ASSERT(value);
(void)value;
if (!_currentWM->update()) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
}
void WimaController::_updateArrivalReturnSpeed() {
bool value;
_WMSettings.setArrivalReturnSpeed(
_arrivalReturnSpeed.rawValue().toDouble(&value));
Q_ASSERT(value);
(void)value;
if (!_currentWM->update()) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
}
void WimaController::_updateAltitude() {
bool value;
_WMSettings.setAltitude(_altitude.rawValue().toDouble(&value));
Q_ASSERT(value);
(void)value;
if (!_currentWM->update()) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
}
void WimaController::_checkBatteryLevel() {
if (_missionController && _masterController &&
_masterController->managerVehicle()) {
Vehicle *managerVehicle = masterController()->managerVehicle();
WimaSettings *wimaSettings =
qgcApp()->toolbox()->settingsManager()->wimaSettings();
int threshold = wimaSettings->lowBatteryThreshold()->rawValue().toInt();
bool enabled = _enableWimaController.rawValue().toBool();
unsigned int minTime =
wimaSettings->minimalRemainingMissionTime()->rawValue().toUInt();
if (enabled) {
Fact *battery1percentRemaining =
managerVehicle->battery1FactGroup()->getFact(
VehicleBatteryFactGroup::_percentRemainingFactName);
Fact *battery2percentRemaining =
managerVehicle->battery2FactGroup()->getFact(
VehicleBatteryFactGroup::_percentRemainingFactName);
if (battery1percentRemaining->rawValue().toDouble() < threshold &&
battery2percentRemaining->rawValue().toDouble() < threshold) {
if (!_lowBatteryHandlingTriggered) {
_lowBatteryHandlingTriggered = true;
if (!(_missionController->remainingTime() <= minTime)) {
requestSmartRTL();
}
} else {
_lowBatteryHandlingTriggered = false;
void WimaController::_eventTimerHandler() {
// Battery level check necessary?
Fact *enableLowBatteryHandling = qgcApp()
->toolbox()
->settingsManager()
->wimaSettings()
->enableLowBatteryHandling();
if (enableLowBatteryHandling->rawValue().toBool() &&
_batteryLevelTicker.ready())
_checkBatteryLevel();
void WimaController::_smartRTLCleanUp(bool flying) {
if (!flying && _missionController) { // vehicle has landed
_switchWaypointManager(_defaultWM);
_missionController->removeAll();
disconnect(masterController()->managerVehicle(), &Vehicle::flyingChanged,
this, &WimaController::_smartRTLCleanUp);
}
void WimaController::_setPhaseDistance(double distance) {
(void)distance;
// if (!qFuzzyCompare(distance, _phaseDistance)) {
// _phaseDistance = distance;
// emit phaseDistanceChanged();
// }
void WimaController::_setPhaseDuration(double duration) {
(void)duration;
// if (!qFuzzyCompare(duration, _phaseDuration)) {
// _phaseDuration = duration;
// emit phaseDurationChanged();
// }
bool WimaController::_SRTLPrecondition(QString &errorString) {
if (!_localPlanDataValid) {
errorString.append(tr("No WiMA data available. Please define at least a "
"measurement and a service area."));
return false;
}
return _rtlWM.checkPrecondition(errorString);
void WimaController::_switchWaypointManager(
WaypointManager::ManagerBase &manager) {
if (_currentWM != &manager) {
_currentWM = &manager;
disconnect(&_overlapWaypoints, &Fact::rawValueChanged, this,
&WimaController::_updateOverlap);
disconnect(&_maxWaypointsPerPhase, &Fact::rawValueChanged, this,
&WimaController::_updateMaxWaypoints);
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this,
&WimaController::_setStartIndex);
_maxWaypointsPerPhase.setRawValue(_currentWM->N());
_overlapWaypoints.setRawValue(_currentWM->overlap());
_nextPhaseStartWaypointIndex.setRawValue(_currentWM->startIndex());
connect(&_overlapWaypoints, &Fact::rawValueChanged, this,
&WimaController::_updateOverlap);
connect(&_maxWaypointsPerPhase, &Fact::rawValueChanged, this,
&WimaController::_updateMaxWaypoints);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this,
&WimaController::_setStartIndex);
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit waypointPathChanged();
qWarning() << "WimaController::_switchWaypointManager: statistics update "
"missing.";
}
}
void WimaController::_initSmartRTL() {
static int attemptCounter = 0;
attemptCounter++;
QString errorString;
if (_SRTLPrecondition(errorString)) {
if (_missionController && _masterController &&
_masterController->managerVehicle()) {
_masterController->managerVehicle()->pauseVehicle();
connect(_masterController->managerVehicle(), &Vehicle::flyingChanged,
this, &WimaController::_smartRTLCleanUp);
if (_rtlWM.update()) { // Calculate return path.
_switchWaypointManager(_rtlWM);
removeFromVehicle();
attemptCounter = 0;
emit smartRTLPathConfirm();
}
}
} else if (attemptCounter > SMART_RTL_MAX_ATTEMPTS) {
errorString.append(
tr("Smart RTL: No success after maximum number of attempts."));
qgcApp()->showMessage(errorString);
attemptCounter = 0;
} else {
_smartRTLTimer.singleShot(SMART_RTL_ATTEMPT_INTERVAL, this,
&WimaController::_initSmartRTL);
}
}
auto start = std::chrono::high_resolution_clock::now();
#endif
// Copy waypoints to waypoint manager.
_snakeWM.clear();
auto waypoints = 1;
if (waypoints.size() < 1) {
return;
for (auto &vertex : waypoints) {
_snakeWM.push_back(vertex);
// Do update.
this->_snakeWM.update(); // this can take a while (ca. 200ms)
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
#ifdef SNAKE_SHOW_TIME
auto end = std::chrono::high_resolution_clock::now();
std::cout << "WimaController::_threadFinishedHandler(): waypoints: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end -
start)
.count()
<< " ms" << std::endl;
#endif
}
void WimaController::_switchToSnakeWaypointManager(QVariant variant) {
if (variant.value<bool>()) {
_switchWaypointManager(_snakeWM);
} else {
_switchWaypointManager(_defaultWM);
}
}
void WimaController::_progressChangedHandler() {
const auto progress = this->_nemoInterface.progress();
if (this->_measurementArea.tiles().count() == progress.size()) {
this->_measurementArea.progress() = std::move(progress);
} else if (_localPlanDataValid) {
this->_nemoInterface.publishTileData(this->_measurementArea.tileData());
void WimaController::_enableSnakeChangedHandler() {
if (this->_enableSnake.rawValue().toBool()) {
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
}
}
void WimaController::_updateRoute() {
if (_localPlanDataValid && this->_joinedArea.coordinateList().size() > 0) {
auto safeArea = this->_joinedArea.coordinateList();
for (auto &v : safeArea) {
v.setAltitude(0);
}
const auto &origin = safeArea.front();
snake::BoostPolygon safeAreaENU;
snake::areaToEnu(origin, safeArea, safeAreaENU);
const auto &depot = this->_serviceArea.depot();
const auto &geoTransects = this->_rawTransects;
const auto progess = this->_nemoInterface.progress();
auto pTiles = std::make_shared<QList<QList<QGeoCoordinate>>>();
auto generator = [origin, depot,
geoTransects](snake::Transects &transects) -> bool {
snake::BoostPolygon depotENU;
snake::toENU(origin, depot, depotENU);
transects.push_back(snake::BoostLineString{depotENU});
for (auto &geoTransect : geoTransects) {
snake::BoostLineString t;
for (auto &geoVertex : geoTransect) {
snake::BoostPoint v;
snake::toENU(origin, geoVertex, v);
t.push_back(v);
}
transects.push_back(t);
}
return true;
};
this->_routingThread.route(safeAreaENU, generator);