Skip to content
WimaController.cc 10.7 KiB
Newer Older
Valentin Platzgummer's avatar
Valentin Platzgummer committed
#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)
    , _firstWaypointIndex   (2) // starts with 2, 0 is home position, 1 is takeoff
QmlObjectListModel* WimaController::visualItems()
    return &_visualItems;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
QStringList WimaController::loadNameFilters() const
{
    QStringList filters;

    filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension) <<
Valentin Platzgummer's avatar
Valentin Platzgummer committed
               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()
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()
{
void WimaController::saveToCurrent()
void WimaController::saveToFile(const QString& filename)
{
    QString file = filename;
bool WimaController::loadFromCurrent()
}

bool WimaController::loadFromFile(const QString &filename)
{
    QString file = filename;
QJsonDocument WimaController::saveToJson(FileType fileType)
bool WimaController::calcShortestPath(const QGeoCoordinate &start, const QGeoCoordinate &destination, QList<QGeoCoordinate> &path)
{
    using namespace GeoUtilities;
    using namespace PolygonCalculus;
    QList<QPointF> 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<QGeoCoordinate> &coordinateList)
{
    return extractCoordinateList(missionItems, coordinateList, 0, missionItems.count()-1);
}

bool WimaController::extractCoordinateList(const QmlObjectListModel &missionItems, QList<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++) {
                const MissionItem *mItem = qobject_cast<MissionItem*>(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<QGeoCoordinate> 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<const WimaAreaData*> 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<const WimaServiceAreaData*>(areaData);
                _visualItems.append(&_serviceArea);
            if (areaData->type() == WimaMeasurementAreaData::typeString) { // is it a measurement area?
                _measurementArea =  *qobject_cast<const WimaMeasurementAreaData*>(areaData);
                _visualItems.append(&_measurementArea);
            if (areaData->type() == WimaCorridorData::typeString) { // is it a corridor?
                _corridor =  *qobject_cast<const WimaCorridorData*>(areaData);
                //_visualItems.append(&_corridor); // not needed
            if (areaData->type() == WimaJoinedAreaData::typeString) { // is it a corridor?
                _joinedArea =  *qobject_cast<const WimaJoinedAreaData*>(areaData);
                _visualItems.append(&_joinedArea);
#ifdef QT_DEBUG
        //qWarning("containerDataValidChanged(): count:");
        //qWarning() << planData.missionItems().count();
#endif

        QList<const MissionItem*> tempMissionItems = planData.missionItems();

        _missionController->removeAll();
        QmlObjectListModel* missionControllerVisualItems = _missionController->visualItems();
        for ( auto missionItem : tempMissionItems) {
            _missionController->insertSimpleMissionItem(*missionItem, missionControllerVisualItems->count());

        MissionSettingsItem *settingsItem     = qobject_cast<MissionSettingsItem *>((*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<SimpleMissionItem *>((*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;
        _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<QGeoCoordinate> 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();
}