#include "WimaController.h" const char* WimaController::wimaFileExtension = "wima"; const char* WimaController::areaItemsName = "AreaItems"; const char* WimaController::missionItemsName = "MissionItems"; WimaController::WimaController(QObject *parent) : QObject (parent) , _container (nullptr) , _joinedArea (this) , _measurementArea (this) , _serviceArea (this) , _corridor (this) , _localPlanDataValid (false) , _firstWaypointIndex (2) // starts with 2, 0 is home position, 1 is takeoff { } QmlObjectListModel* WimaController::visualItems() { return &_visualItems; } QStringList WimaController::loadNameFilters() const { QStringList filters; filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension) << tr("All Files (*.*)"); return filters; } QStringList WimaController::saveNameFilters() const { QStringList filters; filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension); return filters; } WimaDataContainer *WimaController::dataContainer() { return _container; } QmlObjectListModel *WimaController::missionItems() { return &_missionItems; } QVariantList WimaController::waypointPath() { return _waypointPath; } void WimaController::setMasterController(PlanMasterController *masterC) { _masterController = masterC; emit masterControllerChanged(); } void WimaController::setMissionController(MissionController *missionC) { _missionController = missionC; emit missionControllerChanged(); } /*! * \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) { if (container != nullptr) { if (_container != nullptr) { disconnect(_container, &WimaDataContainer::dataValidChanged, this, &WimaController::containerDataValidChanged); } _container = container; connect(_container, &WimaDataContainer::dataValidChanged, this, &WimaController::containerDataValidChanged); emit dataContainerChanged(); } } void WimaController::startMission() { } void WimaController::abortMission() { } void WimaController::pauseMission() { } void WimaController::resumeMission() { } bool WimaController::updateMission() { return true; } void WimaController::saveToCurrent() { } void WimaController::saveToFile(const QString& filename) { QString file = filename; } bool WimaController::loadFromCurrent() { return true; } bool WimaController::loadFromFile(const QString &filename) { QString file = filename; return true; } QJsonDocument WimaController::saveToJson(FileType fileType) { if(fileType) { } return QJsonDocument(); } bool WimaController::calcShortestPath(const QGeoCoordinate &start, const QGeoCoordinate &destination, QList &path) { using namespace GeoUtilities; using namespace PolygonCalculus; QList path2D; 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(const QmlObjectListModel &missionItems, QList &coordinateList) { return extractCoordinateList(missionItems, coordinateList, 0, missionItems.count()-1); } bool WimaController::extractCoordinateList(const QmlObjectListModel &missionItems, QList &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++) { const MissionItem *mItem = qobject_cast(missionItems[i]); if (mItem == nullptr) { coordinateList.clear(); return false; } coordinateList.append(mItem->coordinate()); } } } else return false; return true; } bool WimaController::extractCoordinateList(const QmlObjectListModel &missionItems, QVariantList &coordinateList) { return extractCoordinateList(missionItems, coordinateList, 0 , missionItems.count()-1); } bool WimaController::extractCoordinateList(const QmlObjectListModel &missionItems, QVariantList &coordinateList, int startIndex, int endIndex) { QList geoCoordintateList; bool retValue = extractCoordinateList(missionItems, geoCoordintateList, startIndex, endIndex); if (!retValue) return false; for (auto coordinate : geoCoordintateList) coordinateList.append(QVariant::fromValue(coordinate)); return true; } /*! * \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 */ void WimaController::containerDataValidChanged(bool valid) { if ( valid ) { if (_container == nullptr) { qWarning("WimaController::containerDataValidChanged(): No container assigned!"); } _localPlanDataValid = false; _visualItems.clear(); _missionItems.clear(); WimaPlanData planData = _container->pull(); // extract list with WimaAreas QList areaList = planData.areaList(); 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]; if (areaData->type() == WimaServiceAreaData::typeString) { // is it a service area? _serviceArea = *qobject_cast(areaData); areaCounter++; _visualItems.append(&_serviceArea); continue; } if (areaData->type() == WimaMeasurementAreaData::typeString) { // is it a measurement area? _measurementArea = *qobject_cast(areaData); areaCounter++; _visualItems.append(&_measurementArea); continue; } if (areaData->type() == WimaCorridorData::typeString) { // is it a corridor? _corridor = *qobject_cast(areaData); areaCounter++; //_visualItems.append(&_corridor); // not needed continue; } if (areaData->type() == WimaJoinedAreaData::typeString) { // is it a corridor? _joinedArea = *qobject_cast(areaData); areaCounter++; _visualItems.append(&_joinedArea); continue; } if (areaCounter >= numAreas) break; } #ifdef QT_DEBUG //qWarning("containerDataValidChanged(): count:"); //qWarning() << planData.missionItems().count(); #endif QList tempMissionItems = planData.missionItems(); _missionController->removeAll(); QmlObjectListModel* missionControllerVisualItems = _missionController->visualItems(); for ( auto missionItem : tempMissionItems) { _missionController->insertSimpleMissionItem(*missionItem, missionControllerVisualItems->count()); } MissionSettingsItem *settingsItem = qobject_cast((*missionControllerVisualItems)[0]); if (settingsItem == nullptr) { qWarning("WimaController::containerDataValidChanged(): Nullptr at MissionSettingsItem!"); return; } //_missionItems.append(settingsItem); for ( int i = 1; i < missionControllerVisualItems->count(); i++) { SimpleMissionItem *visualItem = qobject_cast((*missionControllerVisualItems)[i]); if (visualItem == nullptr) { qWarning("WimaController::containerDataValidChanged(): Nullptr at SimpleMissionItem!"); return; } SimpleMissionItem *visualItemCopy = new SimpleMissionItem(*visualItem, true, this); _missionItems.append(visualItemCopy); } updateWaypointPath(); _missionController->removeAll(); if (areaCounter == numAreas) _localPlanDataValid = true; } else { _localPlanDataValid = false; _visualItems.clear(); _missionItems.clear(); } emit visualItemsChanged(); emit missionItemsChanged(); #ifdef QT_DEBUG //qWarning("Mission Items count: "); //qWarning() << _missionItems.count(); #endif } void WimaController::updateCurrentMissionItems() { int numberWaypoints = 30; // the number of waypoints currentMissionItems must not exceed QList geoCoordinateList; // list with potential waypoints (from _missionItems), for _currentMissionItems if (!extractCoordinateList(_missionItems, geoCoordinateList, _firstWaypointIndex, std::min(_firstWaypointIndex + numberWaypoints, _missionItems.count()-2))) // -2 -> last item is land item { qWarning("WimaController::updateCurrentMissionItems(): error on waypoint extraction."); return; } } void WimaController::updateWaypointPath() { _waypointPath.clear(); extractCoordinateList(_missionItems, _waypointPath, 1, _missionItems.count()-1); emit waypointPathChanged(); } void WimaController::updateCurrentPath() { _currentWaypointPath.clear(); extractCoordinateList(_currentMissionItems, _currentWaypointPath, 1, _currentMissionItems.count()-1); emit currentWaypointPathChanged(); }