ComplexMissionItem.cc 21.6 KB
Newer Older
1 2 3 4 5 6 7 8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
9 10 11


#include "ComplexMissionItem.h"
12 13
#include "JsonHelper.h"
#include "MissionController.h"
14
#include "QGCGeo.h"
15

Don Gagne's avatar
Don Gagne committed
16 17
#include <QPolygonF>

Don Gagne's avatar
Don Gagne committed
18 19 20 21 22 23 24 25 26 27 28
QGC_LOGGING_CATEGORY(ComplexMissionItemLog, "ComplexMissionItemLog")

const char* ComplexMissionItem::_jsonVersionKey =               "version";
const char* ComplexMissionItem::_jsonTypeKey =                  "type";
const char* ComplexMissionItem::_jsonPolygonKey =               "polygon";
const char* ComplexMissionItem::_jsonIdKey =                    "id";
const char* ComplexMissionItem::_jsonGridAltitudeKey =          "gridAltitude";
const char* ComplexMissionItem::_jsonGridAltitudeRelativeKey =  "gridAltitudeRelative";
const char* ComplexMissionItem::_jsonGridAngleKey =             "gridAngle";
const char* ComplexMissionItem::_jsonGridSpacingKey =           "gridSpacing";
const char* ComplexMissionItem::_jsonCameraTriggerKey =         "cameraTrigger";
Don Gagne's avatar
Don Gagne committed
29
const char* ComplexMissionItem::_jsonCameraTriggerDistanceKey = "cameraTriggerDistance";
30 31

const char* ComplexMissionItem::_complexType = "survey";
32 33

ComplexMissionItem::ComplexMissionItem(Vehicle* vehicle, QObject* parent)
34
    : VisualMissionItem(vehicle, parent)
35
    , _sequenceNumber(0)
36
    , _dirty(false)
Don Gagne's avatar
Don Gagne committed
37
    , _cameraTrigger(false)
Don Gagne's avatar
Don Gagne committed
38
    , _gridAltitudeRelative(true)
39 40
    , _cameraShots(0)
    , _coveredArea(0.0)
41 42 43
    , _gridAltitudeFact (0, "Altitude:",        FactMetaData::valueTypeDouble)
    , _gridAngleFact    (0, "Grid angle:",      FactMetaData::valueTypeDouble)
    , _gridSpacingFact  (0, "Grid spacing:",    FactMetaData::valueTypeDouble)
Don Gagne's avatar
Don Gagne committed
44
    , _cameraTriggerDistanceFact(0, "Camera trigger distance", FactMetaData::valueTypeDouble)
45
{
46
    _gridAltitudeFact.setRawValue(25);
Don Gagne's avatar
Don Gagne committed
47 48
    _gridSpacingFact.setRawValue(10);
    _cameraTriggerDistanceFact.setRawValue(25);
49

50 51
    connect(&_gridSpacingFact,  &Fact::valueChanged, this, &ComplexMissionItem::_generateGrid);
    connect(&_gridAngleFact,    &Fact::valueChanged, this, &ComplexMissionItem::_generateGrid);
52
    connect(&_cameraTriggerDistanceFact,    &Fact::valueChanged, this, &ComplexMissionItem::_generateGrid);
53 54

    connect(this, &ComplexMissionItem::cameraTriggerChanged, this, &ComplexMissionItem::_cameraTriggerChanged);
55 56
}

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
const ComplexMissionItem& ComplexMissionItem::operator=(const ComplexMissionItem& other)
{
    _vehicle = other._vehicle;

    setIsCurrentItem(other._isCurrentItem);
    setDirty(other._dirty);
    setAltDifference(other._altDifference);
    setAltPercent(other._altPercent);
    setAzimuth(other._azimuth);
    setDistance(other._distance);
    setCameraShots(other._cameraShots);
    setCoveredArea(other._coveredArea);

    return *this;
}

void ComplexMissionItem::setCameraShots(int cameraShots)
{
    if (_cameraShots != cameraShots) {
        _cameraShots = cameraShots;
        emit cameraShotsChanged(_cameraShots);
    }
}

void ComplexMissionItem::setCoveredArea(double coveredArea)
{
    if (!qFuzzyCompare(_coveredArea, coveredArea)) {
        _coveredArea = coveredArea;
        emit coveredAreaChanged(_coveredArea);
    }
}


90 91
void ComplexMissionItem::clearPolygon(void)
{
92 93 94 95
    // Bug workaround, see below
    while (_polygonPath.count() > 1) {
        _polygonPath.takeLast();
    }
96
    emit polygonPathChanged();
97 98 99

    // Although this code should remove the polygon from the map it doesn't. There appears
    // to be a bug in MapPolygon which causes it to not be redrawn if the list is empty. So
100
    // we work around it by using the code above to remove all but the last point which in turn
101 102
    // will cause the polygon to go away.
    _polygonPath.clear();
103 104

    _clearGrid();
105
    setDirty(true);
106

107
    emit specifiesCoordinateChanged();
108
    emit lastSequenceNumberChanged(lastSequenceNumber());
109 110 111 112 113 114
}

void ComplexMissionItem::addPolygonCoordinate(const QGeoCoordinate coordinate)
{
    _polygonPath << QVariant::fromValue(coordinate);
    emit polygonPathChanged();
115

116
    int pointCount = _polygonPath.count();
117 118 119 120 121
    if (pointCount >= 3) {
        if (pointCount == 3) {
            emit specifiesCoordinateChanged();
        }
        _generateGrid();
122
    }
123
    setDirty(true);
124
}
125

126 127 128 129 130 131 132 133
void ComplexMissionItem::adjustPolygonCoordinate(int vertexIndex, const QGeoCoordinate coordinate)
{
    _polygonPath[vertexIndex] = QVariant::fromValue(coordinate);
    emit polygonPathChanged();
    _generateGrid();
    setDirty(true);
}

134
int ComplexMissionItem::lastSequenceNumber(void) const
135
{
136 137 138 139
    int lastSeq = _sequenceNumber;

    if (_gridPoints.count()) {
        lastSeq += _gridPoints.count() - 1;
140 141 142 143
        if (_cameraTrigger) {
            // Account for two trigger messages
            lastSeq += 2;
        }
Don Gagne's avatar
Don Gagne committed
144 145
    }

146
    return lastSeq;
147 148 149 150 151 152 153 154 155 156 157 158
}

void ComplexMissionItem::setCoordinate(const QGeoCoordinate& coordinate)
{
    if (_coordinate != coordinate) {
        _coordinate = coordinate;
        emit coordinateChanged(_coordinate);
    }
}

void ComplexMissionItem::setDirty(bool dirty)
{
159 160 161 162
    if (_dirty != dirty) {
        _dirty = dirty;
        emit dirtyChanged(_dirty);
    }
163 164
}

165 166
void ComplexMissionItem::save(QJsonObject& saveObject) const
{
Don Gagne's avatar
Don Gagne committed
167 168 169 170 171 172 173 174
    saveObject[_jsonVersionKey] =               1;
    saveObject[_jsonTypeKey] =                  _complexType;
    saveObject[_jsonIdKey] =                    sequenceNumber();
    saveObject[_jsonGridAltitudeKey] =          _gridAltitudeFact.rawValue().toDouble();
    saveObject[_jsonGridAltitudeRelativeKey] =  _gridAltitudeRelative;
    saveObject[_jsonGridAngleKey] =             _gridAngleFact.rawValue().toDouble();
    saveObject[_jsonGridSpacingKey] =           _gridSpacingFact.rawValue().toDouble();
    saveObject[_jsonCameraTriggerKey] =         _cameraTrigger;
Don Gagne's avatar
Don Gagne committed
175
    saveObject[_jsonCameraTriggerDistanceKey] = _cameraTriggerDistanceFact.rawValue().toDouble();
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

    // Polygon shape

    QJsonArray polygonArray;

    for (int i=0; i<_polygonPath.count(); i++) {
        const QVariant& polyVar = _polygonPath[i];

        QJsonValue jsonValue;
        JsonHelper::writeQGeoCoordinate(jsonValue, polyVar.value<QGeoCoordinate>(), false /* writeAltitude */);
        polygonArray += jsonValue;
    }

    saveObject[_jsonPolygonKey] = polygonArray;
}

void ComplexMissionItem::setSequenceNumber(int sequenceNumber)
{
194 195 196
    if (_sequenceNumber != sequenceNumber) {
        _sequenceNumber = sequenceNumber;
        emit sequenceNumberChanged(sequenceNumber);
197
        emit lastSequenceNumberChanged(lastSequenceNumber());
198 199 200 201
    }
}

void ComplexMissionItem::_clear(void)
202
{
203 204
    clearPolygon();
    _clearGrid();
205 206 207 208 209 210 211 212 213
}


bool ComplexMissionItem::load(const QJsonObject& complexObject, QString& errorString)
{
    _clear();

    // Validate requires keys
    QStringList requiredKeys;
Don Gagne's avatar
Don Gagne committed
214
    requiredKeys << _jsonVersionKey << _jsonTypeKey << _jsonIdKey << _jsonPolygonKey << _jsonGridAltitudeKey << _jsonGridAngleKey << _jsonGridSpacingKey <<
Don Gagne's avatar
Don Gagne committed
215
                    _jsonCameraTriggerKey << _jsonCameraTriggerDistanceKey << _jsonGridAltitudeRelativeKey;
216 217 218 219 220 221 222 223
    if (!JsonHelper::validateRequiredKeys(complexObject, requiredKeys, errorString)) {
        _clear();
        return false;
    }

    // Validate types
    QStringList keyList;
    QList<QJsonValue::Type> typeList;
Don Gagne's avatar
Don Gagne committed
224
    keyList << _jsonVersionKey << _jsonTypeKey << _jsonIdKey << _jsonPolygonKey << _jsonGridAltitudeKey << _jsonGridAngleKey << _jsonGridSpacingKey <<
Don Gagne's avatar
Don Gagne committed
225
               _jsonCameraTriggerKey << _jsonCameraTriggerDistanceKey << _jsonGridAltitudeRelativeKey;
Don Gagne's avatar
Don Gagne committed
226
    typeList << QJsonValue::Double << QJsonValue::String << QJsonValue::Double << QJsonValue::Array << QJsonValue::Double << QJsonValue::Double<< QJsonValue::Double <<
Don Gagne's avatar
Don Gagne committed
227
                QJsonValue::Bool << QJsonValue::Double << QJsonValue::Bool;
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    if (!JsonHelper::validateKeyTypes(complexObject, keyList, typeList, errorString)) {
        _clear();
        return false;
    }

    // Version check
    if (complexObject[_jsonVersionKey].toInt() != 1) {
        errorString = tr("QGroundControl does not support this version of survey items");
        _clear();
        return false;
    }
    QString complexType = complexObject[_jsonTypeKey].toString();
    if (complexType != _complexType) {
        errorString = tr("QGroundControl does not support loading this complex mission item type: %1").arg(complexType);
        _clear();
        return false;
    }

    setSequenceNumber(complexObject[_jsonIdKey].toInt());
Don Gagne's avatar
Don Gagne committed
247 248 249 250 251 252 253 254

    _cameraTrigger =        complexObject[_jsonCameraTriggerKey].toBool();
    _gridAltitudeRelative = complexObject[_jsonGridAltitudeRelativeKey].toBool();

    _gridAltitudeFact.setRawValue           (complexObject[_jsonGridAltitudeKey].toDouble());
    _gridAngleFact.setRawValue              (complexObject[_jsonGridAngleKey].toDouble());
    _gridSpacingFact.setRawValue            (complexObject[_jsonGridSpacingKey].toDouble());
    _cameraTriggerDistanceFact.setRawValue  (complexObject[_jsonCameraTriggerDistanceKey].toDouble());
255 256 257 258 259 260 261 262 263 264 265 266 267 268

    // Polygon shape
    QJsonArray polygonArray(complexObject[_jsonPolygonKey].toArray());
    for (int i=0; i<polygonArray.count(); i++) {
        const QJsonValue& pointValue = polygonArray[i];

        QGeoCoordinate pointCoord;
        if (!JsonHelper::toQGeoCoordinate(pointValue, pointCoord, false /* altitudeRequired */, errorString)) {
            _clear();
            return false;
        }
        _polygonPath << QVariant::fromValue(pointCoord);
    }

269
    _generateGrid();
270

271 272
    return true;
}
273

274 275 276 277 278
void ComplexMissionItem::_setExitCoordinate(const QGeoCoordinate& coordinate)
{
    if (_exitCoordinate != coordinate) {
        _exitCoordinate = coordinate;
        emit exitCoordinateChanged(coordinate);
279
    }
280
}
281

282 283 284 285 286 287 288 289 290 291
bool ComplexMissionItem::specifiesCoordinate(void) const
{
    return _polygonPath.count() > 2;
}

void ComplexMissionItem::_clearGrid(void)
{
    // Bug workaround
    while (_gridPoints.count() > 1) {
        _gridPoints.takeLast();
292
    }
293 294 295 296 297 298 299 300 301 302 303 304 305
    emit gridPointsChanged();
    _gridPoints.clear();
}

void ComplexMissionItem::_generateGrid(void)
{
    if (_polygonPath.count() < 3) {
        _clearGrid();
        return;
    }

    _gridPoints.clear();

Don Gagne's avatar
Don Gagne committed
306 307
    QList<QPointF> polygonPoints;
    QList<QPointF> gridPoints;
308

Don Gagne's avatar
Don Gagne committed
309
    // Convert polygon to Qt coordinate system (y positive is down)
Don Gagne's avatar
Don Gagne committed
310
    qCDebug(ComplexMissionItemLog) << "Convert polygon";
311 312
    QGeoCoordinate tangentOrigin = _polygonPath[0].value<QGeoCoordinate>();
    for (int i=0; i<_polygonPath.count(); i++) {
Don Gagne's avatar
Don Gagne committed
313 314 315
        double y, x, down;
        convertGeoToNed(_polygonPath[i].value<QGeoCoordinate>(), tangentOrigin, &y, &x, &down);
        polygonPoints += QPointF(x, -y);
Don Gagne's avatar
Don Gagne committed
316
        qCDebug(ComplexMissionItemLog) << _polygonPath[i].value<QGeoCoordinate>() << polygonPoints.last().x() << polygonPoints.last().y();
317 318
    }

319 320 321 322 323 324 325 326 327 328
    double coveredArea = 0.0;
    for (int i=0; i<polygonPoints.count(); i++) {
        if (i != 0) {
            coveredArea += polygonPoints[i - 1].x() * polygonPoints[i].y() - polygonPoints[i].x() * polygonPoints[i -1].y();
        } else {
            coveredArea += polygonPoints.last().x() * polygonPoints[i].y() - polygonPoints[i].x() * polygonPoints.last().y();
        }
    }
    setCoveredArea(0.5 * fabs(coveredArea));

329 330 331
    // Generate grid
    _gridGenerator(polygonPoints, gridPoints);

332
    double surveyDistance = 0.0;
333 334
    // Convert to Geo and set altitude
    for (int i=0; i<gridPoints.count(); i++) {
Don Gagne's avatar
Don Gagne committed
335
        QPointF& point = gridPoints[i];
336

337 338 339 340
        if (i != 0) {
            surveyDistance += sqrt(pow((gridPoints[i] - gridPoints[i - 1]).x(),2.0) + pow((gridPoints[i] - gridPoints[i - 1]).y(),2.0));
        }

341
        QGeoCoordinate geoCoord;
Don Gagne's avatar
Don Gagne committed
342
        convertNedToGeo(-point.y(), point.x(), 0, tangentOrigin, &geoCoord);
343 344
        _gridPoints += QVariant::fromValue(geoCoord);
    }
345 346
    setCameraShots((int)floor(surveyDistance / _cameraTriggerDistanceFact.rawValue().toDouble()));

347 348 349 350 351 352 353
    emit gridPointsChanged();
    emit lastSequenceNumberChanged(lastSequenceNumber());

    if (_gridPoints.count()) {
        setCoordinate(_gridPoints.first().value<QGeoCoordinate>());
        _setExitCoordinate(_gridPoints.last().value<QGeoCoordinate>());
    }
Don Gagne's avatar
Don Gagne committed
354 355 356 357 358 359
}

QPointF ComplexMissionItem::_rotatePoint(const QPointF& point, const QPointF& origin, double angle)
{
    QPointF rotated;
    double radians = (M_PI / 180.0) * angle;
360

Don Gagne's avatar
Don Gagne committed
361 362 363 364
    rotated.setX(((point.x() - origin.x()) * cos(radians)) - ((point.y() - origin.y()) * sin(radians)) + origin.x());
    rotated.setY(((point.x() - origin.x()) * sin(radians)) + ((point.y() - origin.y()) * cos(radians)) + origin.y());

    return rotated;
365 366
}

Don Gagne's avatar
Don Gagne committed
367
void ComplexMissionItem::_intersectLinesWithRect(const QList<QLineF>& lineList, const QRectF& boundRect, QList<QLineF>& resultLines)
368
{
Don Gagne's avatar
Don Gagne committed
369 370 371 372
    QLineF topLine      (boundRect.topLeft(),       boundRect.topRight());
    QLineF bottomLine   (boundRect.bottomLeft(),    boundRect.bottomRight());
    QLineF leftLine     (boundRect.topLeft(),       boundRect.bottomLeft());
    QLineF rightLine    (boundRect.topRight(),      boundRect.bottomRight());
373

Don Gagne's avatar
Don Gagne committed
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
    for (int i=0; i<lineList.count(); i++) {
        QPointF intersectPoint;
        QLineF intersectLine;
        const QLineF& line = lineList[i];

        int foundCount = 0;
        if (line.intersect(topLine, &intersectPoint) == QLineF::BoundedIntersection) {
            intersectLine.setP1(intersectPoint);
            foundCount++;
        }
        if (line.intersect(rightLine, &intersectPoint) == QLineF::BoundedIntersection) {
            if (foundCount == 0) {
                intersectLine.setP1(intersectPoint);
            } else {
                if (foundCount != 1) {
                    qWarning() << "Found more than two intersecting points";
                }
                intersectLine.setP2(intersectPoint);
            }
            foundCount++;
        }
        if (line.intersect(bottomLine, &intersectPoint) == QLineF::BoundedIntersection) {
            if (foundCount == 0) {
                intersectLine.setP1(intersectPoint);
            } else {
                if (foundCount != 1) {
                    qWarning() << "Found more than two intersecting points";
                }
                intersectLine.setP2(intersectPoint);
            }
            foundCount++;
        }
        if (line.intersect(leftLine, &intersectPoint) == QLineF::BoundedIntersection) {
            if (foundCount == 0) {
                intersectLine.setP1(intersectPoint);
            } else {
                if (foundCount != 1) {
                    qWarning() << "Found more than two intersecting points";
                }
                intersectLine.setP2(intersectPoint);
            }
            foundCount++;
        }
417

Don Gagne's avatar
Don Gagne committed
418 419 420 421 422
        if (foundCount == 2) {
            resultLines += intersectLine;
        }
    }
}
423

Don Gagne's avatar
Don Gagne committed
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
void ComplexMissionItem::_intersectLinesWithPolygon(const QList<QLineF>& lineList, const QPolygonF& polygon, QList<QLineF>& resultLines)
{
    for (int i=0; i<lineList.count(); i++) {
        int foundCount = 0;
        QLineF intersectLine;
        const QLineF& line = lineList[i];

        for (int j=0; j<polygon.count()-1; j++) {
            QPointF intersectPoint;
            QLineF polygonLine = QLineF(polygon[j], polygon[j+1]);
            if (line.intersect(polygonLine, &intersectPoint) == QLineF::BoundedIntersection) {
                if (foundCount == 0) {
                    foundCount++;
                    intersectLine.setP1(intersectPoint);
                } else {
                    foundCount++;
                    intersectLine.setP2(intersectPoint);
                    break;
                }
            }
        }
445

Don Gagne's avatar
Don Gagne committed
446 447 448
        if (foundCount == 2) {
            resultLines += intersectLine;
        }
449
    }
Don Gagne's avatar
Don Gagne committed
450
}
451

Don Gagne's avatar
Don Gagne committed
452 453 454
void ComplexMissionItem::_gridGenerator(const QList<QPointF>& polygonPoints,  QList<QPointF>& gridPoints)
{
    double gridAngle = _gridAngleFact.rawValue().toDouble();
455

Don Gagne's avatar
Don Gagne committed
456
    gridPoints.clear();
457

Don Gagne's avatar
Don Gagne committed
458
    // Convert polygon to bounding rect
459

Don Gagne's avatar
Don Gagne committed
460
    qCDebug(ComplexMissionItemLog) << "Polygon";
Don Gagne's avatar
Don Gagne committed
461 462
    QPolygonF polygon;
    for (int i=0; i<polygonPoints.count(); i++) {
Don Gagne's avatar
Don Gagne committed
463
        qCDebug(ComplexMissionItemLog) << polygonPoints[i];
Don Gagne's avatar
Don Gagne committed
464 465 466 467 468
        polygon << polygonPoints[i];
    }
    polygon << polygonPoints[0];
    QRectF smallBoundRect = polygon.boundingRect();
    QPointF center = smallBoundRect.center();
Don Gagne's avatar
Don Gagne committed
469
    qCDebug(ComplexMissionItemLog) << "Bounding rect" << smallBoundRect.topLeft().x() << smallBoundRect.topLeft().y() << smallBoundRect.bottomRight().x() << smallBoundRect.bottomRight().y();
Don Gagne's avatar
Don Gagne committed
470 471 472 473 474 475 476 477 478

    // Rotate the bounding rect around it's center to generate the larger bounding rect
    QPolygonF boundPolygon;
    boundPolygon << _rotatePoint(smallBoundRect.topLeft(),       center, gridAngle);
    boundPolygon << _rotatePoint(smallBoundRect.topRight(),      center, gridAngle);
    boundPolygon << _rotatePoint(smallBoundRect.bottomRight(),   center, gridAngle);
    boundPolygon << _rotatePoint(smallBoundRect.bottomLeft(),    center, gridAngle);
    boundPolygon << boundPolygon[0];
    QRectF largeBoundRect = boundPolygon.boundingRect();
Don Gagne's avatar
Don Gagne committed
479
    qCDebug(ComplexMissionItemLog) << "Rotated bounding rect" << largeBoundRect.topLeft().x() << largeBoundRect.topLeft().y() << largeBoundRect.bottomRight().x() << largeBoundRect.bottomRight().y();
Don Gagne's avatar
Don Gagne committed
480 481 482 483 484 485 486 487 488 489 490

    // Create set of rotated parallel lines within the expanded bounding rect. Make the lines larger than the
    // bounding box to guarantee intersection.
    QList<QLineF> lineList;
    float x = largeBoundRect.topLeft().x();
    float gridSpacing = _gridSpacingFact.rawValue().toDouble();
    while (x < largeBoundRect.bottomRight().x()) {
        float yTop =    largeBoundRect.topLeft().y() - 100.0;
        float yBottom = largeBoundRect.bottomRight().y() + 100.0;

        lineList += QLineF(_rotatePoint(QPointF(x, yTop), center, gridAngle), _rotatePoint(QPointF(x, yBottom), center, gridAngle));
Don Gagne's avatar
Don Gagne committed
491
        qCDebug(ComplexMissionItemLog) << "line" << lineList.last().x1() << lineList.last().y1() << lineList.last().x2() << lineList.last().y2();
492 493 494 495

        x += gridSpacing;
    }

Don Gagne's avatar
Don Gagne committed
496 497 498 499
    // Now intesect the lines with the smaller bounding rect
    QList<QLineF> resultLines;
    //_intersectLinesWithRect(lineList, smallBoundRect, resultLines);
    _intersectLinesWithPolygon(lineList, polygon, resultLines);
500

Don Gagne's avatar
Don Gagne committed
501 502 503
    // Turn into a path
    for (int i=0; i<resultLines.count(); i++) {
        const QLineF& line = resultLines[i];
504 505

        if (i & 1) {
Don Gagne's avatar
Don Gagne committed
506
            gridPoints << line.p2() << line.p1();
507
        } else {
Don Gagne's avatar
Don Gagne committed
508
            gridPoints << line.p1() << line.p2();
509 510
        }
    }
511
}
512

Don Gagne's avatar
Don Gagne committed
513
QmlObjectListModel* ComplexMissionItem::getMissionItems(void) const
514
{
515 516 517 518 519 520 521 522 523
    QmlObjectListModel* pMissionItems = new QmlObjectListModel;

    int seqNum = _sequenceNumber;
    for (int i=0; i<_gridPoints.count(); i++) {
        QGeoCoordinate coord = _gridPoints[i].value<QGeoCoordinate>();
        double altitude = _gridAltitudeFact.rawValue().toDouble();

        MissionItem* item = new MissionItem(seqNum++,                       // sequence number
                                            MAV_CMD_NAV_WAYPOINT,           // MAV_CMD
Don Gagne's avatar
Don Gagne committed
524
                                            _gridAltitudeRelative ? MAV_FRAME_GLOBAL_RELATIVE_ALT : MAV_FRAME_GLOBAL,  // MAV_FRAME
525 526 527 528 529 530 531 532
                                            0.0, 0.0, 0.0, 0.0,             // param 1-4
                                            coord.latitude(),
                                            coord.longitude(),
                                            altitude,
                                            true,                           // autoContinue
                                            false,                          // isCurrentItem
                                            pMissionItems);                 // parent - allow delete on pMissionItems to delete everthing
        pMissionItems->append(item);
Don Gagne's avatar
Don Gagne committed
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

        if (_cameraTrigger && i == 0) {
            MissionItem* item = new MissionItem(seqNum++,                       // sequence number
                                                MAV_CMD_DO_SET_CAM_TRIGG_DIST,  // MAV_CMD
                                                MAV_FRAME_MISSION,              // MAV_FRAME
                                                _cameraTriggerDistanceFact.rawValue().toDouble(),   // trigger distance
                                                0.0, 0.0, 0.0, 0.0, 0.0, 0.0,   // param 2-7
                                                true,                           // autoContinue
                                                false,                          // isCurrentItem
                                                pMissionItems);                 // parent - allow delete on pMissionItems to delete everthing
            pMissionItems->append(item);
        }
    }

    if (_cameraTrigger) {
        MissionItem* item = new MissionItem(seqNum++,                       // sequence number
                                            MAV_CMD_DO_SET_CAM_TRIGG_DIST,  // MAV_CMD
                                            MAV_FRAME_MISSION,              // MAV_FRAME
                                            0.0,                            // trigger distance
                                            0.0, 0.0, 0.0, 0.0, 0.0, 0.0,   // param 2-7
                                            true,                           // autoContinue
                                            false,                          // isCurrentItem
                                            pMissionItems);                 // parent - allow delete on pMissionItems to delete everthing
        pMissionItems->append(item);
557 558 559
    }

    return pMissionItems;
560
}
Don Gagne's avatar
Don Gagne committed
561

562
void ComplexMissionItem::_cameraTriggerChanged(void)
Don Gagne's avatar
Don Gagne committed
563
{
564 565 566 567 568
    setDirty(true);
    if (_gridPoints.count()) {
        // If we have grid turn on/off camera trigger will add/remove two camera trigger mission items
        emit lastSequenceNumberChanged(lastSequenceNumber());
    }
Don Gagne's avatar
Don Gagne committed
569
}