Newer
Older
#include "ros_bridge/rapidjson/include/rapidjson/document.h"
#include "ros_bridge/rapidjson/include/rapidjson/writer.h"
#include "ros_bridge/rapidjson/include/rapidjson/ostreamwrapper.h"
#include "Snake/QtROSJsonFactory.h"
#include "Snake/QtROSTypeFactory.h"
#include "Snake/QNemoProgress.h"
#include "Snake/QNemoHeartbeat.h"
#include <QScopedPointer>
// const char* WimaController::wimaFileExtension = "wima";
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";
const char* WimaController::snakeTileWidthName = "SnakeTileWidth";
const char* WimaController::snakeTileHeightName = "SnakeTileHeight";
const char* WimaController::snakeMinTileAreaName = "SnakeMinTileArea";
const char* WimaController::snakeLineDistanceName = "SnakeLineDistance";
const char* WimaController::snakeMinTransectLengthName = "SnakeMinTransectLength";
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")};
using namespace snake;
using namespace snake_geometry;
WimaController::WimaController(QObject *parent)
, _joinedArea ()
, _measurementArea ()
, _serviceArea ()
, _corridor ()
, _areaInterface (&_measurementArea, &_serviceArea, &_corridor, &_joinedArea)
, _managerSettings ()
, _defaultManager (_managerSettings, _areaInterface)
, _snakeManager (_managerSettings, _areaInterface)
Valentin Platzgummer
committed
, _rtlManager (_managerSettings, _areaInterface)
, _currentManager (&_defaultManager)
, _managerList {&_defaultManager, &_snakeManager, &_rtlManager}
, _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])
, _measurementPathLength (-1)
, _lowBatteryHandlingTriggered (false)
, _snakeCalcInProgress (false)
, _snakeTileWidth (settingsGroup, _metaDataMap[snakeTileWidthName])
, _snakeTileHeight (settingsGroup, _metaDataMap[snakeTileHeightName])
, _snakeMinTileArea (settingsGroup, _metaDataMap[snakeMinTileAreaName])
, _snakeLineDistance (settingsGroup, _metaDataMap[snakeLineDistanceName])
, _snakeMinTransectLength (settingsGroup, _metaDataMap[snakeMinTransectLengthName])
, _nemoHeartbeat (0 /*status: not connected*/)
, _fallbackStatus (0 /*status: not connected*/)
, _bridgeSetupDone (false)
_showAllMissionItems.setRawValue(true);
_showCurrentMissionItems.setRawValue(true);
connect(&_overlapWaypoints, &Fact::rawValueChanged, this, &WimaController::_updateOverlap);
connect(&_maxWaypointsPerPhase, &Fact::rawValueChanged, this, &WimaController::_updateMaxWaypoints);
Valentin Platzgummer
committed
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);
// 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 : _managerList){
manager->setOverlap(overlap);
manager->setN(N);
manager->setStartIndex(startIdx);
}
connect(&_eventTimer, &QTimer::timeout, this, &WimaController::_eventTimerHandler);
//_eventTimer.setInterval(EVENT_TIMER_INTERVAL);
_eventTimer.start(EVENT_TIMER_INTERVAL);
connect(&_snakeWorker, &SnakeWorker::finished, this, &WimaController::_snakeStoreWorkerResults);
connect(this, &WimaController::nemoProgressChanged, this, &WimaController::_initStartSnakeWorker);
connect(this, &QObject::destroyed, &this->_snakeWorker, &SnakeWorker::quit);
Valentin Platzgummer
committed
connect(&_enableSnake, &Fact::rawValueChanged, this, &WimaController::_switchSnakeManager);
_switchSnakeManager(_enableSnake.rawValue());
PlanMasterController *WimaController::masterController() {
return _masterController;
}
MissionController *WimaController::missionController() {
return _missionController;
}
QmlObjectListModel *WimaController::visualItems() {
return &_areas;
}
QmlObjectListModel *WimaController::missionItems() {
Valentin Platzgummer
committed
return const_cast<QmlObjectListModel*>(&_currentManager->missionItems());
}
QmlObjectListModel *WimaController::currentMissionItems() {
Valentin Platzgummer
committed
return const_cast<QmlObjectListModel*>(&_currentManager->currentMissionItems());
}
QVariantList WimaController::waypointPath()
{
Valentin Platzgummer
committed
return const_cast<QVariantList&>(_currentManager->waypointsVariant());
QVariantList WimaController::currentWaypointPath()
Valentin Platzgummer
committed
return const_cast<QVariantList&>(_currentManager->currentWaypointsVariant());
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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() {
return &_showCurrentMissionItems;
}
Fact *WimaController::flightSpeed() {
return &_flightSpeed;
}
Fact *WimaController::arrivalReturnSpeed() {
return &_arrivalReturnSpeed;
}
Fact *WimaController::altitude() {
return &_altitude;
}
QVector<int> WimaController::nemoProgress() {
if ( _nemoProgress.progress().size() == _snakeTileCenterPoints.size() )
return _nemoProgress.progress();
else
return QVector<int>(_snakeTileCenterPoints.size(), 0);
}
double WimaController::phaseDistance() const
{
}
double WimaController::phaseDuration() const
{
int WimaController::nemoStatus() const
{
return _nemoHeartbeat.status();
}
QString WimaController::nemoStatusString() const
return _nemoStatusMap.at(_nemoHeartbeat.status());
}
bool WimaController::snakeCalcInProgress() const
{
return _snakeCalcInProgress;
}
void WimaController::setMasterController(PlanMasterController *masterC)
{
_masterController = masterC;
_managerSettings.setMasterController(masterC);
emit masterControllerChanged();
}
void WimaController::setMissionController(MissionController *missionC)
{
_missionController = missionC;
_managerSettings.setMissionController(missionC);
emit missionControllerChanged();
}
void WimaController::nextPhase()
{
Valentin Platzgummer
committed
void WimaController::previousPhase()
Valentin Platzgummer
committed
if ( !_currentManager->previous() ) {
Q_ASSERT(false);
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
Valentin Platzgummer
committed
}
void WimaController::resetPhase()
{
Valentin Platzgummer
committed
if ( !_currentManager->reset() ) {
Q_ASSERT(false);
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
Valentin Platzgummer
committed
}
Valentin Platzgummer
committed
void WimaController::requestSmartRTL()
{
QString errorString("Smart RTL requested. ");
if ( !_checkSmartRTLPreCondition(errorString) ){
qgcApp()->showMessage(errorString);
return;
}
Valentin Platzgummer
committed
emit smartRTLRequestConfirm();
}
bool WimaController::upload()
Valentin Platzgummer
committed
{
auto ¤tMissionItems = _defaultManager.currentMissionItems();
Valentin Platzgummer
committed
if ( !_serviceArea.containsCoordinate(_masterController->managerVehicle()->coordinate())
&& currentMissionItems.count() > 0) {
Valentin Platzgummer
committed
emit forceUploadConfirm();
Valentin Platzgummer
committed
return false;
}
Valentin Platzgummer
committed
return forceUpload();
Valentin Platzgummer
committed
}
Valentin Platzgummer
committed
bool WimaController::forceUpload()
Valentin Platzgummer
committed
{
auto ¤tMissionItems = _defaultManager.currentMissionItems();
if (currentMissionItems.count() < 1)
_missionController->removeAll();
Valentin Platzgummer
committed
// Set homeposition of settingsItem.
QmlObjectListModel* visuals = _missionController->visualItems();
MissionSettingsItem* settingsItem = visuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
Valentin Platzgummer
committed
Q_ASSERT(false);
qWarning("WimaController::updateCurrentMissionItems(): nullptr");
settingsItem->setCoordinate(_managerSettings.homePosition());
// Copy mission items to _missionController.
Valentin Platzgummer
committed
for (int i = 1; i < currentMissionItems.count(); i++){
auto *item = currentMissionItems.value<const SimpleMissionItem *>(i);
_missionController->insertSimpleMissionItem(*item, visuals->count());
}
Valentin Platzgummer
committed
void WimaController::removeFromVehicle()
{
_masterController->removeAllFromVehicle();
_missionController->removeAll();
}
void WimaController::executeSmartRTL()
Valentin Platzgummer
committed
forceUpload();
masterController()->managerVehicle()->startMission();
void WimaController::initSmartRTL()
_initSmartRTL();
Valentin Platzgummer
committed
void WimaController::removeVehicleTrajectoryHistory()
{
Vehicle *managerVehicle = masterController()->managerVehicle();
managerVehicle->trajectoryPoints()->clear();
}
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);
bool retVal = PolygonCalculus::shortestPath(polygon2D, start2D, end2D, path2D);
toGeoList(path2D, /*origin*/ start, path);
Valentin Platzgummer
committed
bool WimaController::setWimaPlanData(const WimaPlanData &planData)
_areas.clear();
_defaultManager.clear();
_snakeTiles.polygons().clear();
_snakeTilesLocal.polygons().clear();
Valentin Platzgummer
committed
_snakeTileCenterPoints.clear();
Valentin Platzgummer
committed
emit visualItemsChanged();
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit snakeTilesChanged();
Valentin Platzgummer
committed
emit snakeTileCenterPointsChanged();
Valentin Platzgummer
committed
Valentin Platzgummer
committed
// extract list with WimaAreas
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++;
Valentin Platzgummer
committed
Valentin Platzgummer
committed
if (areaData->type() == WimaMeasurementAreaData::typeString) { // is it a measurement area?
_measurementArea = *qobject_cast<const WimaMeasurementAreaData*>(areaData);
areaCounter++;
Valentin Platzgummer
committed
Valentin Platzgummer
committed
}
if (areaData->type() == WimaCorridorData::typeString) { // is it a corridor?
_corridor = *qobject_cast<const WimaCorridorData*>(areaData);
areaCounter++;
//_visualItems.append(&_corridor); // not needed
Valentin Platzgummer
committed
Valentin Platzgummer
committed
if (areaData->type() == WimaJoinedAreaData::typeString) { // is it a corridor?
_joinedArea = *qobject_cast<const WimaJoinedAreaData*>(areaData);
areaCounter++;
Valentin Platzgummer
committed
Valentin Platzgummer
committed
Valentin Platzgummer
committed
Valentin Platzgummer
committed
Q_ASSERT(false);
Valentin Platzgummer
committed
Valentin Platzgummer
committed
emit visualItemsChanged();
// extract mission items
QList<MissionItem> tempMissionItems = planData.missionItems();
if (tempMissionItems.size() < 1) {
qWarning("WimaController: Mission items from WimaPlaner empty!");
for (auto item : tempMissionItems) {
_defaultManager.push_back(item.coordinate());
_managerSettings.setHomePosition( QGeoCoordinate(_serviceArea.center().latitude(),
_serviceArea.center().longitude(),
0) );
Valentin Platzgummer
committed
Q_ASSERT(false);
Valentin Platzgummer
committed
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit waypointPathChanged();
emit currentWaypointPathChanged();
Valentin Platzgummer
committed
Valentin Platzgummer
committed
return true;
}
Valentin Platzgummer
committed
WimaController *WimaController::thisPointer()
{
return this;
}
bool WimaController::_calcNextPhase()
{
if ( !_currentManager->next() ) {
Q_ASSERT(false);
return false;
}
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
Valentin Platzgummer
committed
emit waypointPathChanged();
Valentin Platzgummer
committed
bool WimaController::_setStartIndex()
Valentin Platzgummer
committed
bool value;
_currentManager->setStartIndex(_nextPhaseStartWaypointIndex.rawValue().toUInt(&value)-1);
Valentin Platzgummer
committed
Q_ASSERT(value);
(void)value;
if ( !_currentManager->update() ) {
Q_ASSERT(false);
return false;
}
emit currentWaypointPathChanged();
emit waypointPathChanged();
void WimaController::_recalcCurrentPhase()
Valentin Platzgummer
committed
if ( !_currentManager->update() ) {
Q_ASSERT(false);
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
void WimaController::_updateOverlap()
Valentin Platzgummer
committed
_currentManager->setOverlap(_overlapWaypoints.rawValue().toUInt(&value));
Valentin Platzgummer
committed
if ( !_currentManager->update() ) {
assert(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
void WimaController::_updateMaxWaypoints()
Valentin Platzgummer
committed
_currentManager->setN(_maxWaypointsPerPhase.rawValue().toUInt(&value));
Valentin Platzgummer
committed
if ( !_currentManager->update() ) {
Q_ASSERT(false);
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
Valentin Platzgummer
committed
bool value;
_managerSettings.setFlightSpeed(_flightSpeed.rawValue().toDouble(&value));
Valentin Platzgummer
committed
Q_ASSERT(value);
(void)value;
if ( !_currentManager->update() ) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
void WimaController::_updateArrivalReturnSpeed()
Valentin Platzgummer
committed
bool value;
_managerSettings.setArrivalReturnSpeed(_arrivalReturnSpeed.rawValue().toDouble(&value));
Valentin Platzgummer
committed
Q_ASSERT(value);
(void)value;
if ( !_currentManager->update() ) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
Valentin Platzgummer
committed
bool value;
_managerSettings.setAltitude(_altitude.rawValue().toDouble(&value));
Valentin Platzgummer
committed
Q_ASSERT(value);
(void)value;
if ( !_currentManager->update() ) {
Q_ASSERT(false);
}
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
Valentin Platzgummer
committed
Vehicle *managerVehicle = masterController()->managerVehicle();
WimaSettings* wimaSettings = qgcApp()->toolbox()->settingsManager()->wimaSettings();
int batteryThreshold = wimaSettings->lowBatteryThreshold()->rawValue().toInt();
bool enabled = _enableWimaController.rawValue().toBool();
unsigned int minTime = wimaSettings->minimalRemainingMissionTime()->rawValue().toUInt();
Fact *battery1percentRemaining = managerVehicle->battery1FactGroup()->getFact(VehicleBatteryFactGroup::_percentRemainingFactName);
Fact *battery2percentRemaining = managerVehicle->battery2FactGroup()->getFact(VehicleBatteryFactGroup::_percentRemainingFactName);
if (battery1percentRemaining->rawValue().toDouble() < batteryThreshold
&& battery2percentRemaining->rawValue().toDouble() < batteryThreshold) {
Valentin Platzgummer
committed
if (!_lowBatteryHandlingTriggered) {
_lowBatteryHandlingTriggered = true;
if ( !(_missionController->remainingTime() <= minTime) ) {
}
}
}
else {
_lowBatteryHandlingTriggered = false;
}
}
}
void WimaController::_eventTimerHandler()
{
static EventTicker batteryLevelTicker(EVENT_TIMER_INTERVAL, CHECK_BATTERY_INTERVAL);
static EventTicker snakeTicker(EVENT_TIMER_INTERVAL, SNAKE_EVENT_LOOP_INTERVAL);
static EventTicker nemoStatusTicker(EVENT_TIMER_INTERVAL, 5000);
Valentin Platzgummer
committed
Fact *enableLowBatteryHandling = qgcApp()->toolbox()->settingsManager()->wimaSettings()->enableLowBatteryHandling();
if ( enableLowBatteryHandling->rawValue().toBool() && batteryLevelTicker.ready() )
_checkBatteryLevel();
// Snake flight plan update necessary?
// if ( snakeEventLoopTicker.ready() ) {
// if ( _enableSnake.rawValue().toBool() && _localPlanDataValid && !_snakeCalcInProgress && _scenarioDefinedBool) {
// }
// }
if ( nemoStatusTicker.ready() ) {
this->_nemoHeartbeat.setStatus(_fallbackStatus);
emit WimaController::nemoStatusChanged();
emit WimaController::nemoStatusStringChanged();
}
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
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
if ( snakeTicker.ready() ) {
if ( _enableSnake.rawValue().toBool()
&& _pRosBridge->connected() ) {
if ( !_bridgeSetupDone ) {
qWarning() << "ROS Bridge setup. ";
auto start = std::chrono::high_resolution_clock::now();
_pRosBridge->start();
auto end = std::chrono::high_resolution_clock::now();
qWarning() << "_pRosBridge->start() time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count()
<< " ms";
start = std::chrono::high_resolution_clock::now();
_pRosBridge->publish(_snakeOrigin, "/snake/origin");
end = std::chrono::high_resolution_clock::now();
qWarning() << "_pRosBridge->publish(_snakeOrigin, \"/snake/origin\") time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count()
<< " ms";
start = std::chrono::high_resolution_clock::now();
_pRosBridge->publish(_snakeTilesLocal, "/snake/tiles");
end = std::chrono::high_resolution_clock::now();
qWarning() << "_pRosBridge->publish(_snakeTilesLocal, \"/snake/tiles\") time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count()
<< " ms";
start = std::chrono::high_resolution_clock::now();
_pRosBridge->subscribe("/nemo/progress",
/* callback */ [this](JsonDocUPtr pDoc){
int requiredSize = this->_snakeTilesLocal.polygons().size();
auto& progress = this->_nemoProgress;
if ( !this->_pRosBridge->casePacker()->unpack(pDoc, progress)
|| progress.progress().size() != requiredSize ) {
progress.progress().fill(0, requiredSize);
}
emit WimaController::nemoProgressChanged();
});
end = std::chrono::high_resolution_clock::now();
qWarning() << "_pRosBridge->subscribe(\"/nemo/progress\" time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count()
<< " ms";
start = std::chrono::high_resolution_clock::now();
_pRosBridge->subscribe("/nemo/heartbeat",
/* callback */ [this, &nemoStatusTicker](JsonDocUPtr pDoc){
if ( !this->_pRosBridge->casePacker()->unpack(pDoc, this->_nemoHeartbeat) ) {
if ( this->_nemoHeartbeat.status() == this->_fallbackStatus )
return;
this->_nemoHeartbeat.setStatus(this->_fallbackStatus);
}
nemoStatusTicker.reset();
this->_fallbackStatus = -1; /*Timeout*/
emit WimaController::nemoStatusChanged();
emit WimaController::nemoStatusStringChanged();
});
end = std::chrono::high_resolution_clock::now();
qWarning() << "_pRosBridge->subscribe(\"/nemo/heartbeat\" time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count()
<< " ms";
_bridgeSetupDone = true;
}
} else if ( _bridgeSetupDone) {
_pRosBridge->reset();
_bridgeSetupDone = false;
}
}
void WimaController::_smartRTLCleanUp(bool flying)
Valentin Platzgummer
committed
if ( !flying) { // vehicle has landed
_switchWaypointManager(_defaultManager);
_missionController->removeAllFromVehicle();
_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::_checkSmartRTLPreCondition(QString &errorString)
{
if (!_localPlanDataValid) {
errorString.append(tr("No WiMA data available. Please define at least a measurement and a service area."));
return false;
return _rtlManager.checkPrecondition(errorString);
Valentin Platzgummer
committed
void WimaController::_switchWaypointManager(WaypointManager::ManagerBase &manager)
Valentin Platzgummer
committed
if (_currentManager != &manager) {
_currentManager = &manager;
disconnect(&_overlapWaypoints, &Fact::rawValueChanged,
this, &WimaController::_updateOverlap);
disconnect(&_maxWaypointsPerPhase, &Fact::rawValueChanged,
this, &WimaController::_updateMaxWaypoints);
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged,
this, &WimaController::_setStartIndex);
_maxWaypointsPerPhase.setRawValue(_currentManager->N());
_overlapWaypoints.setRawValue(_currentManager->overlap());
_nextPhaseStartWaypointIndex.setRawValue(_currentManager->startIndex());
connect(&_overlapWaypoints, &Fact::rawValueChanged,
this, &WimaController::_updateOverlap);
connect(&_maxWaypointsPerPhase, &Fact::rawValueChanged,
this, &WimaController::_updateMaxWaypoints);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged,
this, &WimaController::_setStartIndex);
Valentin Platzgummer
committed
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit waypointPathChanged();
emit currentWaypointPathChanged();
Valentin Platzgummer
committed
qWarning() << "WimaController::_switchWaypointManager: statistics update missing.";
void WimaController::_initSmartRTL()
{
Valentin Platzgummer
committed
QString errorString;
static int attemptCounter = 0;
attemptCounter++;
if ( _checkSmartRTLPreCondition(errorString) ) {
Valentin Platzgummer
committed
_masterController->managerVehicle()->pauseVehicle();
connect(masterController()->managerVehicle(), &Vehicle::flyingChanged, this, &WimaController::_smartRTLCleanUp);
if ( _rtlManager.update() ) { // Calculate return path.
_switchWaypointManager(_rtlManager);
attemptCounter = 0;
emit smartRTLPathConfirm();
return;
}
} 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);
}
void WimaController::_setSnakeCalcInProgress(bool inProgress)
{
if (_snakeCalcInProgress != inProgress){
_snakeCalcInProgress = inProgress;
emit snakeCalcInProgressChanged();
}
}
void WimaController::_snakeStoreWorkerResults()
{
auto start = std::chrono::high_resolution_clock::now();
_setSnakeCalcInProgress(false);
if (!r.success) {
//qgcApp()->showMessage(r.errorMessage);
return;
}
// create Mission items from r.waypoints
long n = r.waypoints.size() - r.returnPathIdx.size() - r.arrivalPathIdx.size() + 2;
Valentin Platzgummer
committed
return;
}
// Create QVector<QGeoCoordinate> containing all waypoints;
unsigned long startIdx = r.arrivalPathIdx.last();
unsigned long endIdx = r.returnPathIdx.first();
for (unsigned long i = startIdx; i <= endIdx; ++i) {
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
emit waypointPathChanged();
auto end = std::chrono::high_resolution_clock::now();
double duration = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
qWarning() << "WimaController::_snakeStoreWorkerResults execution time: " << duration << " ms.";
void WimaController::_initStartSnakeWorker()
{
if ( !_enableSnake.rawValue().toBool() )
return;
// Stop worker thread if running.
if ( _snakeWorker.isRunning() ) {
_snakeWorker.quit();
}
// Initialize _snakeWorker.
_snakeWorker.setMeasurementArea(
_measurementArea.coordinateList());
_snakeWorker.setServiceArea(
_serviceArea.coordinateList());
_snakeWorker.setCorridor(
_corridor.coordinateList());
_snakeWorker.setProgress(
_nemoProgress.progress());
_snakeWorker.setLineDistance(
_snakeLineDistance.rawValue().toDouble());
_snakeWorker.setMinTransectLength(
_snakeMinTransectLength.rawValue().toDouble());
_snakeWorker.setTileHeight(
_snakeTileHeight.rawValue().toDouble());
_snakeWorker.setTileWidth(
_snakeTileWidth.rawValue().toDouble());
_snakeWorker.setMinTileArea(
_snakeMinTileArea.rawValue().toDouble());
_setSnakeCalcInProgress(true);
// Start worker thread.
_snakeWorker.start();
}
Valentin Platzgummer
committed
void WimaController::_switchSnakeManager(QVariant variant)
{
if (variant.value<bool>()){
_switchWaypointManager(_snakeManager);
} else {
_switchWaypointManager(_defaultManager);
}
}