Newer
Older
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::reverseName = "Reverse";
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";
using namespace snake;
using namespace snake_geometry;
WimaController::WimaController(QObject *parent)
: QObject (parent)
, _container (nullptr)
, _joinedArea (this)
, _measurementArea (this)
, _serviceArea (this)
, _corridor (this)
, _localPlanDataValid (false)
, _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])
, _reverse (settingsGroup, _metaDataMap[reverseName])
Valentin Platzgummer
committed
, _startWaypointIndex (0)
, _uploadOverrideRequired (false)
, _measurementPathLength (-1)
, _arrivalPathLength (-1)
, _returnPathLength (-1)
, _phaseDistance (-1)
, _phaseDuration (-1)
, _phaseDistanceBuffer (-1)
, _phaseDurationBuffer (-1)
, _vehicleHasLowBattery (false)
, _lowBatteryHandlingTriggered (false)
, _executingSmartRTL (false)
, _snakeConnectionStatus (SnakeConnectionStatus::Connected) // TODO: implement automatic connection
, _snakeCalcInProgress (false)
, _scenarioDefinedBool (false)
, _snakeTileWidth (settingsGroup, _metaDataMap[snakeTileWidthName])
, _snakeTileHeight (settingsGroup, _metaDataMap[snakeTileHeightName])
, _snakeMinTileArea (settingsGroup, _metaDataMap[snakeMinTileAreaName])
, _snakeLineDistance (settingsGroup, _metaDataMap[snakeLineDistanceName])
, _snakeMinTransectLength (settingsGroup, _metaDataMap[snakeMinTransectLengthName])
{
_showAllMissionItems.setRawValue(true);
_showCurrentMissionItems.setRawValue(true);
connect(&_overlapWaypoints, &Fact::rawValueChanged, this, &WimaController::_updateNextWaypoint);
connect(&_maxWaypointsPerPhase, &Fact::rawValueChanged, this, &WimaController::_recalcCurrentPhase);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
connect(&_flightSpeed, &Fact::rawValueChanged, this, &WimaController::_updateflightSpeed);
connect(&_arrivalReturnSpeed, &Fact::rawValueChanged, this, &WimaController::_updateArrivalReturnSpeed);
connect(&_altitude, &Fact::rawValueChanged, this, &WimaController::_updateAltitude);
connect(&_reverse, &Fact::rawValueChanged, this, &WimaController::_reverseChangedHandler);
// setup low battery handling
connect(&_eventTimer, &QTimer::timeout, this, &WimaController::_eventTimerHandler);
_eventTimer.setInterval(EVENT_TIMER_INTERVAL);
Fact *enableLowBatteryHandling = qgcApp()->toolbox()->settingsManager()->wimaSettings()->enableLowBatteryHandling();
connect(enableLowBatteryHandling, &Fact::rawValueChanged, this, &WimaController::_enableDisableLowBatteryHandling);
_enableDisableLowBatteryHandling(enableLowBatteryHandling->rawValue());
// Snake Worker Thread.
connect(&_snakeWorker, &SnakeWorker::resultReady, this, &WimaController::_snakeStoreWorkerResults);
Valentin Platzgummer
committed
QmlObjectListModel* WimaController::visualItems()
{
}
QStringList WimaController::loadNameFilters() const
{
QStringList filters;
filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension) <<
}
QStringList WimaController::saveNameFilters() const
{
QStringList filters;
filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension);
return filters;
WimaDataContainer *WimaController::dataContainer()
{
Valentin Platzgummer
committed
return _container;
}
QmlObjectListModel *WimaController::missionItems()
{
return &_missionItems;
}
QmlObjectListModel *WimaController::currentMissionItems()
{
return &_currentMissionItems;
}
QVariantList WimaController::waypointPath()
{
return _waypointPath;
}
QVariantList WimaController::currentWaypointPath()
{
return _currentWaypointPath;
}
Fact *WimaController::enableWimaController()
{
return &_enableWimaController;
}
Fact *WimaController::overlapWaypoints()
{
return &_overlapWaypoints;
}
Fact *WimaController::maxWaypointsPerPhase()
{
return &_maxWaypointsPerPhase;
}
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;
}
Fact *WimaController::reverse()
{
return &_reverse;
}
Fact *WimaController::enableSnake()
{
return &_enableSnake;
}
Valentin Platzgummer
committed
bool WimaController::uploadOverrideRequired() const
{
return _uploadOverrideRequired;
}
double WimaController::phaseDistance() const
{
return _phaseDistance;
}
double WimaController::phaseDuration() const
{
return _phaseDuration;
}
bool WimaController::vehicleHasLowBattery() const
{
return _vehicleHasLowBattery;
}
long WimaController::snakeConnectionStatus() const
{
return _snakeConnectionStatus;
}
bool WimaController::snakeCalcInProgress() const
{
return _snakeCalcInProgress;
}
Fact *WimaController::startWaypointIndex()
{
void WimaController::setMasterController(PlanMasterController *masterC)
{
_masterController = masterC;
emit masterControllerChanged();
}
void WimaController::setMissionController(MissionController *missionC)
{
_missionController = missionC;
emit missionControllerChanged();
}
Valentin Platzgummer
committed
/*!
* \fn void WimaController::setDataContainer(WimaDataContainer *container)
* Sets the pointer to the \c WimaDataContainer, which is meant to exchange data between the \c WimaController and the \c WimaPlaner.
*
* \sa WimaPlaner, WimaDataContainer, WimaPlanData
*/
void WimaController::setDataContainer(WimaDataContainer *container)
{
Valentin Platzgummer
committed
if (container != nullptr) {
if (_container != nullptr) {
disconnect(_container, &WimaDataContainer::newDataAvailable, this, &WimaController::_fetchContainerData);
Valentin Platzgummer
committed
}
connect(_container, &WimaDataContainer::newDataAvailable, this, &WimaController::_fetchContainerData);
emit dataContainerChanged();
}
}
Valentin Platzgummer
committed
void WimaController::setUploadOverrideRequired(bool overrideRequired)
{
if (_uploadOverrideRequired != overrideRequired) {
_uploadOverrideRequired = overrideRequired;
emit uploadOverrideRequiredChanged();
}
}
void WimaController::nextPhase()
{
Valentin Platzgummer
committed
void WimaController::previousPhase()
{
bool reverseBool = _reverse.rawValue().toBool();
if (!reverseBool){
int startIndex = _nextPhaseStartWaypointIndex.rawValue().toInt();
if (startIndex > 0) {
_nextPhaseStartWaypointIndex.setRawValue(1+std::max(_startWaypointIndex
- _maxWaypointsPerPhase.rawValue().toInt()
+ _overlapWaypoints.rawValue().toInt(), 0));
}
}
else {
int startIndex = _nextPhaseStartWaypointIndex.rawValue().toInt();
if (startIndex <= _missionItems.count()) {
_nextPhaseStartWaypointIndex.setRawValue(1+std::min(_startWaypointIndex
+ _maxWaypointsPerPhase.rawValue().toInt()
- _overlapWaypoints.rawValue().toInt(), _missionItems.count()-1));
}
Valentin Platzgummer
committed
}
void WimaController::resetPhase()
{
bool reverseBool = _reverse.rawValue().toBool();
if (!reverseBool) {
_nextPhaseStartWaypointIndex.setRawValue(int(1));
}
else {
_nextPhaseStartWaypointIndex.setRawValue(_missionItems.count());
}
Valentin Platzgummer
committed
}
Valentin Platzgummer
committed
{
Valentin Platzgummer
committed
if ( !_serviceArea.containsCoordinate(_masterController->managerVehicle()->coordinate())
&& _currentMissionItems.count() > 0) {
Valentin Platzgummer
committed
setUploadOverrideRequired(true);
return false;
}
return forceUploadToVehicle();
}
bool WimaController::forceUploadToVehicle()
{
setUploadOverrideRequired(false);
if (_currentMissionItems.count() < 1)
_missionController->removeAll();
// set homeposition of settingsItem
QmlObjectListModel* visuals = _missionController->visualItems();
MissionSettingsItem* settingsItem = visuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
qWarning("WimaController::updateCurrentMissionItems(): nullptr");
}
settingsItem->setCoordinate(_takeoffLandPostion);
// copy mission items from _currentMissionItems to _missionController
for (int i = 0; i < _currentMissionItems.count(); i++){
SimpleMissionItem *item = _currentMissionItems.value<SimpleMissionItem *>(i);
_missionController->insertSimpleMissionItem(*item, visuals->count());
if (item->command() == MAV_CMD_DO_CHANGE_SPEED) {
}
}
for (int i = 0; i < _missionController->visualItems()->count(); i++){
SimpleMissionItem *item = _missionController->visualItems()->value<SimpleMissionItem*>(i);
if (item == nullptr)
continue;
if (item->command() == MAV_CMD_DO_CHANGE_SPEED) {
}
}
for (int i = 0; i < _missionController->visualItems()->count(); i++){
SimpleMissionItem *item = _missionController->visualItems()->value<SimpleMissionItem*>(i);
if (item == nullptr)
continue;
Valentin Platzgummer
committed
void WimaController::removeFromVehicle()
{
_masterController->removeAllFromVehicle();
_missionController->removeAll();
}
bool WimaController::checkSmartRTLPreCondition()
{
QString errorString;
bool retValue = _checkSmartRTLPreCondition(errorString);
if (retValue == false) {
qgcApp()->showMessage(errorString);
return false;
}
return true;
}
bool WimaController::calcReturnPath()
{
QString errorString;
bool retValue = _calcReturnPath(errorString);
if (retValue == false) {
qgcApp()->showMessage(errorString);
return false;
}
return true;
Valentin Platzgummer
committed
}
void WimaController::executeSmartRTL()
_executeSmartRTL();
void WimaController::initSmartRTL()
_srtlReason = UserRequest;
_initSmartRTL();
Valentin Platzgummer
committed
void WimaController::removeVehicleTrajectoryHistory()
{
Vehicle *managerVehicle = masterController()->managerVehicle();
managerVehicle->trajectoryPoints()->clear();
}
void WimaController::saveToFile(const QString& filename)
{
}
bool WimaController::loadFromFile(const QString &filename)
{
QJsonDocument WimaController::saveToJson(FileType fileType)
Valentin Platzgummer
committed
return QJsonDocument();
bool WimaController::calcShortestPath(const QGeoCoordinate &start, const QGeoCoordinate &destination, QVector<QGeoCoordinate> &path)
{
using namespace GeoUtilities;
using namespace PolygonCalculus;
bool retVal = PolygonCalculus::shortestPath(
toQPolygonF(toCartesian2D(_joinedArea.coordinateList(), /*origin*/ start)),
/*start point*/ QPointF(0,0),
/*destination*/ toCartesian2D(destination, start),
/*shortest path*/ path2D);
path.append(toGeo(path2D, /*origin*/ start));
return retVal;
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVector<QGeoCoordinate> &coordinateList)
{
return extractCoordinateList(missionItems, coordinateList, 0, missionItems.count()-1);
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVector<QGeoCoordinate> &coordinateList, int startIndex, int endIndex)
{
if ( startIndex >= 0
&& startIndex < missionItems.count()
&& endIndex >= 0
&& endIndex < missionItems.count()) {
if (startIndex > endIndex) {
if (!extractCoordinateList(missionItems, coordinateList, startIndex, missionItems.count()-1))
return false;
if (!extractCoordinateList(missionItems, coordinateList, 0, endIndex))
return false;
} else {
for (int i = startIndex; i <= endIndex; i++) {
SimpleMissionItem *mItem = missionItems.value<SimpleMissionItem *>(i);
if (mItem == nullptr) {
coordinateList.clear();
return false;
}
coordinateList.append(mItem->coordinate());
}
}
} else
return false;
return true;
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVariantList &coordinateList)
{
return extractCoordinateList(missionItems, coordinateList, 0 , missionItems.count()-1);
}
bool WimaController::extractCoordinateList(QmlObjectListModel &missionItems, QVariantList &coordinateList, int startIndex, int endIndex)
QVector<QGeoCoordinate> geoCoordintateList;
bool retValue = extractCoordinateList(missionItems, geoCoordintateList, startIndex, endIndex);
if (!retValue)
return false;
for (int i = 0; i < geoCoordintateList.size(); i++) {
QGeoCoordinate vertex = geoCoordintateList[i];
if ( (qFuzzyIsNull(vertex.latitude()) && qFuzzyIsNull(vertex.longitude()))
|| !vertex.isValid())
geoCoordintateList.removeAt(i);
}
for (auto coordinate : geoCoordintateList)
coordinateList.append(QVariant::fromValue(coordinate));
return true;
}
Valentin Platzgummer
committed
/*!
* \fn void WimaController::containerDataValidChanged(bool valid)
* Pulls plan data generated by \c WimaPlaner from the \c _container if the data is valid (\a valid equals true).
* Is connected to the dataValidChanged() signal of the \c WimaDataContainer.
*
* \sa WimaDataContainer, WimaPlaner, WimaPlanData
*/
Valentin Platzgummer
committed
// reset visual items
_visualItems.clear();
_missionItems.clearAndDeleteContents();
_currentMissionItems.clearAndDeleteContents();
_waypointPath.clear();
_currentWaypointPath.clear();
Valentin Platzgummer
committed
emit visualItemsChanged();
emit missionItemsChanged();
emit currentMissionItemsChanged();
emit currentWaypointPathChanged();
Valentin Platzgummer
committed
Valentin Platzgummer
committed
if (_container == nullptr) {
qWarning("WimaController::fetchContainerData(): No container assigned!");
return false;
}
Valentin Platzgummer
committed
Valentin Platzgummer
committed
// extract list with WimaAreas
QList<const WimaAreaData*> areaList = planData.areaList();
Valentin Platzgummer
committed
int areaCounter = 0;
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++;
_visualItems.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++;
_visualItems.append(&_measurementArea);
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++;
_visualItems.append(&_joinedArea);
Valentin Platzgummer
committed
Valentin Platzgummer
committed
Valentin Platzgummer
committed
QList<MissionItem> tempMissionItems = planData.missionItems();
if (tempMissionItems.size() < 1)
return false;
Valentin Platzgummer
committed
// create mission items
_missionController->removeAll();
QmlObjectListModel* missionControllerVisualItems = _missionController->visualItems();
// create SimpleMissionItem by using _missionController
for ( int i = 0; i < tempMissionItems.size(); i++) {
_missionController->insertSimpleMissionItem(tempMissionItems[i], missionControllerVisualItems->count());
}
// copy mission items from _missionController to _missionItems
for ( int i = 1; i < missionControllerVisualItems->count(); i++) {
SimpleMissionItem *visualItem = qobject_cast<SimpleMissionItem *>((*missionControllerVisualItems)[i]);
if (visualItem == nullptr) {
qWarning("WimaController::fetchContainerData(): Nullptr at SimpleMissionItem!");
return false;
Valentin Platzgummer
committed
}
SimpleMissionItem *visualItemCopy = new SimpleMissionItem(*visualItem, true, this);
_missionItems.append(visualItemCopy);
}
if (areaCounter != numAreas)
return false;
Valentin Platzgummer
committed
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
bool reverse = _reverse.rawValue().toBool();
_nextPhaseStartWaypointIndex.setRawValue(reverse? _missionItems.count() : int(1));
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
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
// Initialize _scenario.
Area mArea;
for (auto variant : _measurementArea.path()){
QGeoCoordinate c{variant.value<QGeoCoordinate>()};
mArea.geoPolygon.push_back(GeoPoint2D{c.latitude(), c.longitude()});
}
mArea.type = AreaType::MeasurementArea;
Area sArea;
for (auto variant : _serviceArea.path()){
QGeoCoordinate c{variant.value<QGeoCoordinate>()};
sArea.geoPolygon.push_back(GeoPoint2D{c.latitude(), c.longitude()});
}
sArea.type = AreaType::ServiceArea;
Area corridor;
for (auto variant : _corridor.path()){
QGeoCoordinate c{variant.value<QGeoCoordinate>()};
corridor.geoPolygon.push_back(GeoPoint2D{c.latitude(), c.longitude()});
}
corridor.type = AreaType::Corridor;
_scenario.addArea(mArea);
_scenario.addArea(sArea);
_scenario.addArea(corridor);
_verifyScenarioDefinedWithErrorMessage();
if (_missionItems.count() < 1) {
_startWaypointIndex = 0;
_endWaypointIndex = 0;
_currentMissionItems.clearAndDeleteContents();
bool reverse = _reverse.rawValue().toBool(); // Reverses the phase direction. Phases go from high to low waypoint numbers, if true.
int startIndex = _nextPhaseStartWaypointIndex.rawValue().toInt()-1;
if (!reverse) {
if (startIndex > _missionItems.count()-1)
return false;
}
else {
int maxWaypointsPerPhase = _maxWaypointsPerPhase.rawValue().toInt();
bool lastMissionPhaseReached = false;
if (!reverse) {
_endWaypointIndex = std::min(_startWaypointIndex + maxWaypointsPerPhase - 1, _missionItems.count()-1);
if (_endWaypointIndex == _missionItems.count() - 1)
_endWaypointIndex = std::max(_startWaypointIndex - maxWaypointsPerPhase + 1, 0);
if (_endWaypointIndex == 0)
QVector<QGeoCoordinate> CSWpList; // list with potential waypoints (from _missionItems), for _currentMissionItems
if (!extractCoordinateList(_missionItems, CSWpList, _startWaypointIndex, _endWaypointIndex)) {
qWarning("WimaController::calcNextPhase(): error on waypoint extraction.");
return false;
}
} else {
if (!extractCoordinateList(_missionItems, CSWpList, _endWaypointIndex, _startWaypointIndex)) {
qWarning("WimaController::calcNextPhase(): error on waypoint extraction.");
return false;
}
// reverse path
QVector<QGeoCoordinate> reversePath;
for (QGeoCoordinate c : CSWpList)
reversePath.prepend(c);
CSWpList.clear();
CSWpList.append(reversePath);
// calculate phase length
_measurementPathLength = 0;
for (int i = 0; i < CSWpList.size()-1; ++i)
_measurementPathLength += CSWpList[i].distanceTo(CSWpList[i+1]);
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
int untruncated = std::max(_endWaypointIndex + 1 - _overlapWaypoints.rawValue().toInt(), 0);
int truncated = std::min(untruncated , _missionItems.count()-1);
_nextPhaseStartWaypointIndex.setRawValue(truncated + 1);
}
else {
int untruncated = std::min(_endWaypointIndex - 1 + _overlapWaypoints.rawValue().toInt(), _missionItems.count()-1);
int truncated = std::max(untruncated , 0);
_nextPhaseStartWaypointIndex.setRawValue(truncated + 1);
}
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
// calculate path from home to first waypoint
QVector<QGeoCoordinate> arrivalPath;
if (!_takeoffLandPostion.isValid()){
qWarning("WimaController::calcNextPhase(): _takeoffLandPostion not valid.");
return false;
}
if ( !calcShortestPath(_takeoffLandPostion, CSWpList.first(), arrivalPath) ) {
qWarning("WimaController::calcNextPhase(): Not able to calc path from home to first waypoint.");
return false;
// calculate arrival path length
_arrivalPathLength = 0;
for (int i = 0; i < arrivalPath.size()-1; ++i)
_arrivalPathLength += arrivalPath[i].distanceTo(arrivalPath[i+1]);
// calculate path from last waypoint to home
QVector<QGeoCoordinate> returnPath;
if ( !calcShortestPath(CSWpList.last(), _takeoffLandPostion, returnPath) ) {
qWarning("WimaController::calcNextPhase(): Not able to calc path from home to first waypoint.");
return false;
}
// calculate arrival path length
_returnPathLength = 0;
for (int i = 0; i < returnPath.size()-1; ++i)
_returnPathLength += returnPath[i].distanceTo(returnPath[i+1]);
returnPath.removeFirst();
returnPath.removeLast();
Valentin Platzgummer
committed
// create Mission Items
_missionController->removeAll();
QmlObjectListModel* missionControllerVisuals = _missionController->visualItems();
Valentin Platzgummer
committed
// set homeposition of settingsItem
MissionSettingsItem* settingsItem = missionControllerVisuals->value<MissionSettingsItem *>(0);
if (settingsItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
Valentin Platzgummer
committed
}
settingsItem->setCoordinate(_takeoffLandPostion);
// set takeoff position for first mission item (bug)
missionController()->insertSimpleMissionItem(_takeoffLandPostion, 1);
SimpleMissionItem *takeoffItem = missionControllerVisuals->value<SimpleMissionItem*>(1);
if (takeoffItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
Valentin Platzgummer
committed
}
takeoffItem->setCoordinate(_takeoffLandPostion);
Valentin Platzgummer
committed
// create change speed item, after take off
_missionController->insertSimpleMissionItem(_takeoffLandPostion, 2);
SimpleMissionItem *speedItem = missionControllerVisuals->value<SimpleMissionItem*>(2);
if (speedItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
speedItem->setCommand(MAV_CMD_DO_CHANGE_SPEED);// set coordinate must be after setCommand (setCommand sets coordinate to zero)
speedItem->setCoordinate(_takeoffLandPostion);
speedItem->missionItem().setParam2(_arrivalReturnSpeed.rawValue().toDouble());
// insert arrival path
for (auto coordinate : arrivalPath)
_missionController->insertSimpleMissionItem(coordinate, missionControllerVisuals->count());
// create change speed item, after arrival path
int index = missionControllerVisuals->count();
_missionController->insertSimpleMissionItem(CSWpList.first(), index);
speedItem = missionControllerVisuals->value<SimpleMissionItem*>(index);
if (speedItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
speedItem->setCommand(MAV_CMD_DO_CHANGE_SPEED); // set coordinate must be after setCommand (setCommand sets coordinate to zero)
speedItem->setCoordinate(CSWpList.first());
speedItem->missionItem().setParam2(_flightSpeed.rawValue().toDouble());
// insert Circular Survey coordinates
for (auto coordinate : CSWpList)
_missionController->insertSimpleMissionItem(coordinate, missionControllerVisuals->count());
// create change speed item, after circular survey
index = missionControllerVisuals->count();
_missionController->insertSimpleMissionItem(CSWpList.last(), index);
speedItem = missionControllerVisuals->value<SimpleMissionItem*>(index);
if (speedItem == nullptr) {
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
}
speedItem->setCommand(MAV_CMD_DO_CHANGE_SPEED); // set coordinate must be after setCommand (setCommand sets coordinate to zero)
speedItem->setCoordinate(CSWpList.last());
speedItem->missionItem().setParam2(_arrivalReturnSpeed.rawValue().toDouble());
// insert return path coordinates
for (auto coordinate : returnPath)
_missionController->insertSimpleMissionItem(coordinate, missionControllerVisuals->count());
// set land command for last mission item
index = missionControllerVisuals->count();
_missionController->insertSimpleMissionItem(_takeoffLandPostion, index);
SimpleMissionItem *landItem = missionControllerVisuals->value<SimpleMissionItem*>(index);
qWarning("WimaController::calcNextPhase(): nullptr");
return false;
_missionController->setLandCommand(*landItem);
Valentin Platzgummer
committed
// copy to _currentMissionItems
for ( int i = 1; i < missionControllerVisuals->count(); i++) {
SimpleMissionItem *visualItem = missionControllerVisuals->value<SimpleMissionItem*>(i);
if (visualItem == nullptr) {
qWarning("WimaController::calcNextPhase(): Nullptr at SimpleMissionItem!");
Valentin Platzgummer
committed
Valentin Platzgummer
committed
SimpleMissionItem *visualItemCopy = new SimpleMissionItem(*visualItem, true, this);
_currentMissionItems.append(visualItemCopy);
}
double dist = 0;
double time = 0;
if (!_missionController->distanceTimeToMissionEnd(dist, time, 1, false))
qWarning("WimaController::calcNextPhase: distanceTimeToMissionEnd returned false!");
_setPhaseDistance(dist);
_setPhaseDuration(time);
_missionController->removeAll(); // remove items from _missionController, will be added on upload
Valentin Platzgummer
committed
extractCoordinateList(_missionItems, _waypointPath, 0, _missionItems.count()-1);
Valentin Platzgummer
committed
extractCoordinateList(_currentMissionItems, _currentWaypointPath, 0, _currentMissionItems.count()-1);
emit currentWaypointPathChanged();
}
{
if (_endWaypointIndex < _missionItems.count()-2) {
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
_nextPhaseStartWaypointIndex.setRawValue(1 + std::max(_endWaypointIndex + 1 - _overlapWaypoints.rawValue().toInt(), 0));
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
disconnect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
Valentin Platzgummer
committed
_nextPhaseStartWaypointIndex.setRawValue(_startWaypointIndex + 1);
connect(&_nextPhaseStartWaypointIndex, &Fact::rawValueChanged, this, &WimaController::_calcNextPhase);
_calcNextPhase();
{
_takeoffLandPostion.setAltitude(0);
_takeoffLandPostion.setLongitude(_serviceArea.center().longitude());
_takeoffLandPostion.setLatitude(_serviceArea.center().latitude());
return true;
int speedItemCounter = 0;
for (int i = 0; i < _currentMissionItems.count(); i++) {
SimpleMissionItem *item = _currentMissionItems.value<SimpleMissionItem *>(i);
if (item != nullptr && item->command() == MAV_CMD_DO_CHANGE_SPEED) {
speedItemCounter++;
if (speedItemCounter == 2) {
item->missionItem().setParam2(_flightSpeed.rawValue().toDouble());
}
}
_setPhaseDuration(_phaseDistance/_flightSpeed.rawValue().toDouble()
+ (_arrivalPathLength + _returnPathLength)
/ _arrivalReturnSpeed.rawValue().toDouble());
if (speedItemCounter != 3)
qWarning("WimaController::updateflightSpeed(): internal error.");
}
void WimaController::_updateArrivalReturnSpeed()
{
int speedItemCounter = 0;
for (int i = 0; i < _currentMissionItems.count(); i++) {
SimpleMissionItem *item = _currentMissionItems.value<SimpleMissionItem *>(i);
if (item != nullptr && item->command() == MAV_CMD_DO_CHANGE_SPEED) {
speedItemCounter++;
if (speedItemCounter != 2) {
item->missionItem().setParam2(_arrivalReturnSpeed.rawValue().toDouble());
}
}
_setPhaseDuration(_phaseDistance/_flightSpeed.rawValue().toDouble()
+ (_arrivalPathLength + _returnPathLength)
/ _arrivalReturnSpeed.rawValue().toDouble());
if (speedItemCounter != 3)
qWarning("WimaController::updateArrivalReturnSpeed(): internal error.");
{
for (int i = 0; i < _currentMissionItems.count(); i++) {
SimpleMissionItem *item = _currentMissionItems.value<SimpleMissionItem *>(i);
if (item == nullptr) {
qWarning("WimaController::updateAltitude(): nullptr");
return;
}
item->altitude()->setRawValue(_altitude.rawValue().toDouble());
}
}
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) {
_setVehicleHasLowBattery(true);
if (!_lowBatteryHandlingTriggered) {
Valentin Platzgummer
committed
if (_missionController->remainingTime() <= minTime) {
_lowBatteryHandlingTriggered = true;
}
else {
_lowBatteryHandlingTriggered = true;