WimaController.cc 10.7 KB
Newer Older
Valentin Platzgummer's avatar
Valentin Platzgummer committed
1
#include "WimaController.h"
2

3 4 5
const char* WimaController::wimaFileExtension   = "wima";
const char* WimaController::areaItemsName       = "AreaItems";
const char* WimaController::missionItemsName    = "MissionItems";
6

7 8 9 10
WimaController::WimaController(QObject *parent)
    : QObject               (parent)
    , _container            (nullptr)
    , _joinedArea           (this)
11 12
    , _measurementArea      (this)
    , _serviceArea          (this)
13
    , _corridor             (this)
14
    , _localPlanDataValid   (false)
15
    , _firstWaypointIndex   (2) // starts with 2, 0 is home position, 1 is takeoff
16
{
17

18 19
}

20
QmlObjectListModel* WimaController::visualItems()
21
{
22
    return &_visualItems;
23 24
}

Valentin Platzgummer's avatar
Valentin Platzgummer committed
25 26 27 28
QStringList WimaController::loadNameFilters() const
{
    QStringList filters;

29
    filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension) <<
Valentin Platzgummer's avatar
Valentin Platzgummer committed
30 31
               tr("All Files (*.*)");
    return filters;
32 33 34 35 36
}

QStringList WimaController::saveNameFilters() const
{
    QStringList filters;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
37

38 39
    filters << tr("Supported types (*.%1 *.%2)").arg(wimaFileExtension).arg(AppSettings::planFileExtension);
    return filters;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
40 41
}

42
WimaDataContainer *WimaController::dataContainer()
43
{
44
    return _container;
45 46
}

47 48 49 50 51
QmlObjectListModel *WimaController::missionItems()
{
    return &_missionItems;
}

52 53 54 55 56
QVariantList WimaController::waypointPath()
{
    return  _waypointPath;
}

57 58 59 60 61 62 63 64 65 66 67 68
void WimaController::setMasterController(PlanMasterController *masterC)
{
    _masterController = masterC;
    emit masterControllerChanged();
}

void WimaController::setMissionController(MissionController *missionC)
{
    _missionController = missionC;
    emit missionControllerChanged();
}

69 70 71 72 73 74
/*!
 * \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
 */
75 76
void WimaController::setDataContainer(WimaDataContainer *container)
{
77 78 79 80 81
    if (container != nullptr) {
        if (_container != nullptr) {
           disconnect(_container, &WimaDataContainer::dataValidChanged, this, &WimaController::containerDataValidChanged);
        }

82
        _container = container;
83
        connect(_container, &WimaDataContainer::dataValidChanged, this, &WimaController::containerDataValidChanged);
84 85 86 87 88

        emit dataContainerChanged();
    }
}

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
void WimaController::startMission()
{

}

void WimaController::abortMission()
{

}

void WimaController::pauseMission()
{

}

void WimaController::resumeMission()
{

}

109 110
bool WimaController::updateMission()
{
111
    return true;
112 113
}

114
void WimaController::saveToCurrent()
115 116 117
{
}

118 119
void WimaController::saveToFile(const QString& filename)
{
120
    QString file = filename;
121 122
}

123
bool WimaController::loadFromCurrent()
124
{
125
    return true;
126 127 128 129
}

bool WimaController::loadFromFile(const QString &filename)
{
130
    QString file = filename;
131
    return true;
132 133 134
}


135

136
QJsonDocument WimaController::saveToJson(FileType fileType)
137
{
138 139 140 141
    if(fileType)
    {

    }
142
    return QJsonDocument();
143 144
}

145 146 147 148 149 150 151 152 153 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 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
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;
}

213 214 215 216 217 218 219 220
/*!
 * \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)
221
{
222 223 224 225 226
    if ( valid ) {
        if (_container == nullptr) {
            qWarning("WimaController::containerDataValidChanged(): No container assigned!");
        }
        _localPlanDataValid = false;
227
        _visualItems.clear();
228
        _missionItems.clear();
229 230 231 232 233 234 235 236 237 238 239
        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?
240
                _serviceArea = *qobject_cast<const WimaServiceAreaData*>(areaData);
241
                areaCounter++;
242
                _visualItems.append(&_serviceArea);
243 244 245 246

                continue;
            }

247 248
            if (areaData->type() == WimaMeasurementAreaData::typeString) { // is it a measurement area?
                _measurementArea =  *qobject_cast<const WimaMeasurementAreaData*>(areaData);
249
                areaCounter++;
250
                _visualItems.append(&_measurementArea);
251 252 253 254

                continue;
            }

255 256
            if (areaData->type() == WimaCorridorData::typeString) { // is it a corridor?
                _corridor =  *qobject_cast<const WimaCorridorData*>(areaData);
257
                areaCounter++;
258
                //_visualItems.append(&_corridor); // not needed
259 260 261 262

                continue;
            }

263 264
            if (areaData->type() == WimaJoinedAreaData::typeString) { // is it a corridor?
                _joinedArea =  *qobject_cast<const WimaJoinedAreaData*>(areaData);
265
                areaCounter++;
266
                _visualItems.append(&_joinedArea);
267 268

                continue;
269
            }
270 271 272 273 274

            if (areaCounter >= numAreas)
                break;
        }

275 276 277 278 279
#ifdef QT_DEBUG
        //qWarning("containerDataValidChanged(): count:");
        //qWarning() << planData.missionItems().count();
#endif

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

282
        _missionController->removeAll();
283
        QmlObjectListModel* missionControllerVisualItems = _missionController->visualItems();
284
        for ( auto missionItem : tempMissionItems) {
285
            _missionController->insertSimpleMissionItem(*missionItem, missionControllerVisualItems->count());
286
        }
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304

        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);
        }

305
        updateWaypointPath();
306
        _missionController->removeAll();
307

308 309
        if (areaCounter == numAreas)
            _localPlanDataValid = true;
310

311 312
    } else {
        _localPlanDataValid = false;
313 314
        _visualItems.clear();
        _missionItems.clear();
315
    }
316 317

    emit visualItemsChanged();
318
    emit missionItemsChanged();
319 320 321 322 323

#ifdef QT_DEBUG
    //qWarning("Mission Items count: ");
    //qWarning() << _missionItems.count();
#endif
324 325
}

326
void WimaController::updateCurrentMissionItems()
327
{
328
    int numberWaypoints = 30; // the number of waypoints currentMissionItems must not exceed
329

330 331 332 333 334 335
    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;
336 337 338
    }


339
}
340

341 342 343 344
void WimaController::updateWaypointPath()
{
    _waypointPath.clear();
    extractCoordinateList(_missionItems, _waypointPath, 1, _missionItems.count()-1);
345

346 347 348 349 350 351
    emit waypointPathChanged();
}
void WimaController::updateCurrentPath()
{
    _currentWaypointPath.clear();
    extractCoordinateList(_currentMissionItems, _currentWaypointPath, 1, _currentMissionItems.count()-1);
352

353 354
    emit currentWaypointPathChanged();
}
355

356 357