MissionItem.cc 25.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*===================================================================
QGroundControl Open Source Ground Control Station

(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief MissionItem class
 *
 *   @author Benjamin Knecht <mavteam@student.ethz.ch>
 *   @author Petri Tanskanen <mavteam@student.ethz.ch>
 *
 */

#include <QStringList>
#include <QDebug>

#include "MissionItem.h"

Don Gagne's avatar
Don Gagne committed
37
QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog")
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

QDebug operator<<(QDebug dbg, const MissionItem& missionItem)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace() << "MissionItem(" << missionItem.coordinate() << ")";
    
    return dbg;
}

QDebug operator<<(QDebug dbg, const MissionItem* missionItem)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace() << "MissionItem(" << missionItem->coordinate() << ")";
    
    return dbg;
}

Don Gagne's avatar
Don Gagne committed
55 56 57 58
const MissionItem::MavCmd2Name_t  MissionItem::_rgMavCmd2Name[_cMavCmd2Name] = {
    { MAV_CMD_NAV_WAYPOINT,         "Waypoint" },
    { MAV_CMD_NAV_LOITER_UNLIM,     "Loiter" },
    { MAV_CMD_NAV_LOITER_TURNS,     "Loiter (turns)" },
Don Gagne's avatar
Don Gagne committed
59
    { MAV_CMD_NAV_LOITER_TIME,      "Loiter (seconds)" },
Don Gagne's avatar
Don Gagne committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    { MAV_CMD_NAV_RETURN_TO_LAUNCH, "Return Home" },
    { MAV_CMD_NAV_LAND,             "Land" },
    { MAV_CMD_NAV_TAKEOFF,          "Takeoff" },
    { MAV_CMD_CONDITION_DELAY,      "Delay" },
    { MAV_CMD_DO_JUMP,              "Jump To Command" },
};

MissionItem::MissionItem(QObject*       parent,
                         int            sequenceNumber,
                         QGeoCoordinate coordinate,
                         double         param1,
                         double         param2,
                         double         param3,
                         double         param4,
                         bool           autocontinue,
                         bool           isCurrentItem,
                         int            frame,
Don Gagne's avatar
Don Gagne committed
77
                         int            command)
78
    : QObject(parent)
Don Gagne's avatar
Don Gagne committed
79
    , _sequenceNumber(sequenceNumber)
Don Gagne's avatar
Don Gagne committed
80
    , _command((MavlinkQmlSingleton::Qml_MAV_CMD)command)
81
    , _autocontinue(autocontinue)
Don Gagne's avatar
Don Gagne committed
82
    , _isCurrentItem(isCurrentItem)
83
    , _reachedTime(0)
Don Gagne's avatar
Don Gagne committed
84
    , _yawRadiansFact(NULL)
85
{
86 87 88 89 90 91 92 93
    _latitudeFact                   = new Fact(0, "Latitude:",                      FactMetaData::valueTypeDouble, this);
    _longitudeFact                  = new Fact(0, "Longitude:",                     FactMetaData::valueTypeDouble, this);
    _altitudeFact                   = new Fact(0, "Altitude:",                      FactMetaData::valueTypeDouble, this);
    _yawRadiansFact                 = new Fact(0, "Heading:",                       FactMetaData::valueTypeDouble, this);
    _loiterOrbitRadiusFact          = new Fact(0, "Radius:",                        FactMetaData::valueTypeDouble, this);
    _param1Fact                     = new Fact(0, QString(),                        FactMetaData::valueTypeDouble, this);
    _param2Fact                     = new Fact(0, QString(),                        FactMetaData::valueTypeDouble, this);
    _altitudeRelativeToHomeFact     = new Fact(0, "Altitude is relative to home",   FactMetaData::valueTypeDouble, this);
Don Gagne's avatar
Don Gagne committed
94

95
    setFrame(frame);
Don Gagne's avatar
Don Gagne committed
96
    
97
    setCoordinate(coordinate);
Don Gagne's avatar
Don Gagne committed
98 99 100 101
    setParam1(param1);
    setParam2(param2);
    setYawRadians(param4);
    setLoiterOrbitRadius(param3);
Don Gagne's avatar
Don Gagne committed
102 103 104
    
    // FIXME: Need to fill out more meta data
    
105 106 107 108 109 110 111 112 113 114 115
    FactMetaData* latitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _latitudeFact);
    latitudeMetaData->setUnits("deg");
    
    FactMetaData* longitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _longitudeFact);
    longitudeMetaData->setUnits("deg");
    
    FactMetaData* altitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _altitudeFact);
    altitudeMetaData->setUnits("meters");
    
    FactMetaData* yawMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _yawRadiansFact);
    yawMetaData->setUnits("deg");
Don Gagne's avatar
Don Gagne committed
116 117
    
    _pitchMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
118
    _pitchMetaData->setUnits("deg");
Don Gagne's avatar
Don Gagne committed
119 120 121 122 123 124 125
    
    _acceptanceRadiusMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    _acceptanceRadiusMetaData->setUnits("meters");
    
    _holdTimeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    _holdTimeMetaData->setUnits("seconds");
    
Don Gagne's avatar
Don Gagne committed
126 127
    FactMetaData* loiterOrbitRadiusMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    loiterOrbitRadiusMetaData->setUnits("meters");
Don Gagne's avatar
Don Gagne committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    
    _loiterTurnsMetaData = new FactMetaData(FactMetaData::valueTypeInt32, this);
    _loiterTurnsMetaData->setUnits("count");
    
    _loiterSecondsMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    _loiterSecondsMetaData->setUnits("seconds");
    
    _delaySecondsMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    _delaySecondsMetaData->setUnits("seconds");
    
    _jumpSequenceMetaData = new FactMetaData(FactMetaData::valueTypeInt32, this);
    _jumpSequenceMetaData->setUnits("#");
    
    _jumpRepeatMetaData = new FactMetaData(FactMetaData::valueTypeInt32, this);
    _jumpRepeatMetaData->setUnits("count");
    
144 145 146
    _latitudeFact->setMetaData(latitudeMetaData);
    _longitudeFact->setMetaData(longitudeMetaData);
    _altitudeFact->setMetaData(altitudeMetaData);
Don Gagne's avatar
Don Gagne committed
147 148
    _yawRadiansFact->setMetaData(yawMetaData);
    _loiterOrbitRadiusFact->setMetaData(loiterOrbitRadiusMetaData);
149 150
}

Don Gagne's avatar
Don Gagne committed
151 152
MissionItem::MissionItem(const MissionItem& other, QObject* parent)
    : QObject(parent)
153
{
154 155 156 157 158 159 160 161
    _latitudeFact               = new Fact(this);
    _longitudeFact              = new Fact(this);
    _altitudeFact               = new Fact(this);
    _yawRadiansFact             = new Fact(this);
    _loiterOrbitRadiusFact      = new Fact(this);
    _param1Fact                 = new Fact(this);
    _param2Fact                 = new Fact(this);
    _altitudeRelativeToHomeFact = new Fact(this);
Don Gagne's avatar
Don Gagne committed
162 163 164 165 166 167 168 169 170 171 172
    
    _pitchMetaData = new FactMetaData(this);
    
    _acceptanceRadiusMetaData = new FactMetaData(this);
    _holdTimeMetaData = new FactMetaData(this);
    _loiterTurnsMetaData = new FactMetaData(this);
    _loiterSecondsMetaData = new FactMetaData(this);
    _delaySecondsMetaData = new FactMetaData(this);
    _jumpSequenceMetaData = new FactMetaData(this);
    _jumpRepeatMetaData = new FactMetaData(this);

173 174 175 176 177 178 179 180 181
    *this = other;
}

MissionItem::~MissionItem()
{    
}

const MissionItem& MissionItem::operator=(const MissionItem& other)
{
182 183 184 185 186 187 188
    _sequenceNumber             = other._sequenceNumber;
    _isCurrentItem              = other._isCurrentItem;
    _frame                      = other._frame;
    _command                    = other._command;
    _autocontinue               = other._autocontinue;
    _reachedTime                = other._reachedTime;
    _altitudeRelativeToHomeFact = other._altitudeRelativeToHomeFact;
Don Gagne's avatar
Don Gagne committed
189
    
190 191 192
    *_latitudeFact              = *other._latitudeFact;
    *_longitudeFact             = *other._longitudeFact;
    *_altitudeFact              = *other._altitudeFact;
Don Gagne's avatar
Don Gagne committed
193 194 195 196 197 198 199 200 201 202 203 204 205 206
    *_yawRadiansFact            = *other._yawRadiansFact;
    *_loiterOrbitRadiusFact     = *other._loiterOrbitRadiusFact;
    *_param1Fact                = *other._param1Fact;
    *_param2Fact                = *other._param2Fact;
    
    *_pitchMetaData             = *other._pitchMetaData;
    *_acceptanceRadiusMetaData  = *other._acceptanceRadiusMetaData;
    *_holdTimeMetaData          = *other._holdTimeMetaData;
    *_loiterTurnsMetaData       = *other._loiterTurnsMetaData;
    *_loiterSecondsMetaData     = *other._loiterSecondsMetaData;
    *_delaySecondsMetaData      = *other._delaySecondsMetaData;
    *_jumpSequenceMetaData      = *other._jumpSequenceMetaData;
    *_jumpRepeatMetaData        = *other._jumpRepeatMetaData;
    
207 208 209 210 211
    return *this;
}

bool MissionItem::isNavigationType()
{
Don Gagne's avatar
Don Gagne committed
212
    return (_command < MavlinkQmlSingleton::MAV_CMD_NAV_LAST);
213 214 215 216 217
}

void MissionItem::save(QTextStream &saveStream)
{
    QString position("%1\t%2\t%3");
Don Gagne's avatar
Don Gagne committed
218 219 220
    position = position.arg(x(), 0, 'g', 18);
    position = position.arg(y(), 0, 'g', 18);
    position = position.arg(z(), 0, 'g', 18);
221
    QString parameters("%1\t%2\t%3\t%4");
Don Gagne's avatar
Don Gagne committed
222
    parameters = parameters.arg(param2(), 0, 'g', 18).arg(param2(), 0, 'g', 18).arg(loiterOrbitRadius(), 0, 'g', 18).arg(yawRadians(), 0, 'g', 18);
223 224
    // FORMAT: <INDEX> <CURRENT WP> <COORD FRAME> <COMMAND> <PARAM1> <PARAM2> <PARAM3> <PARAM4> <PARAM5/X/LONGITUDE> <PARAM6/Y/LATITUDE> <PARAM7/Z/ALTITUDE> <AUTOCONTINUE> <DESCRIPTION>
    // as documented here: http://qgroundcontrol.org/waypoint_protocol
Don Gagne's avatar
Don Gagne committed
225
    saveStream << this->sequenceNumber() << "\t" << this->isCurrentItem() << "\t" << this->frame() << "\t" << this->command() << "\t"  << parameters << "\t" << position  << "\t" << this->autoContinue() << "\r\n"; //"\t" << this->getDescription() << "\r\n";
226 227 228 229 230 231
}

bool MissionItem::load(QTextStream &loadStream)
{
    const QStringList &wpParams = loadStream.readLine().split("\t");
    if (wpParams.size() == 12) {
Don Gagne's avatar
Don Gagne committed
232 233
        setSequenceNumber(wpParams[0].toInt());
        setIsCurrentItem(wpParams[1].toInt() == 1 ? true : false);
234
        setFrame(wpParams[2].toInt());
Don Gagne's avatar
Don Gagne committed
235
        setAction(wpParams[3].toInt());
Don Gagne's avatar
Don Gagne committed
236 237 238
        setParam1(wpParams[4].toDouble());
        setParam2(wpParams[5].toDouble());
        setLoiterOrbitRadius(wpParams[6].toDouble());
Don Gagne's avatar
Don Gagne committed
239
        setYawRadians(wpParams[7].toDouble());
Don Gagne's avatar
Don Gagne committed
240 241 242
        setLatitude(wpParams[8].toDouble());
        setLongitude(wpParams[9].toDouble());
        setAltitude(wpParams[10].toDouble());
243 244 245 246 247 248 249
        _autocontinue = (wpParams[11].toInt() == 1 ? true : false);
        return true;
    }
    return false;
}


Don Gagne's avatar
Don Gagne committed
250
void MissionItem::setSequenceNumber(int sequenceNumber)
251
{
Don Gagne's avatar
Don Gagne committed
252 253
    _sequenceNumber = sequenceNumber;
    emit sequenceNumberChanged(_sequenceNumber);
254 255 256 257 258 259 260
    emit changed(this);
}

void MissionItem::setX(double x)
{
    if (!isinf(x) && !isnan(x) && ((_frame == MAV_FRAME_LOCAL_NED) || (_frame == MAV_FRAME_LOCAL_ENU)))
    {
Don Gagne's avatar
Don Gagne committed
261
        setLatitude(x);
262 263 264 265 266 267 268
    }
}

void MissionItem::setY(double y)
{
    if (!isinf(y) && !isnan(y) && ((_frame == MAV_FRAME_LOCAL_NED) || (_frame == MAV_FRAME_LOCAL_ENU)))
    {
Don Gagne's avatar
Don Gagne committed
269
        setLongitude(y);
270 271 272 273 274 275 276
    }
}

void MissionItem::setZ(double z)
{
    if (!isinf(z) && !isnan(z) && ((_frame == MAV_FRAME_LOCAL_NED) || (_frame == MAV_FRAME_LOCAL_ENU)))
    {
Don Gagne's avatar
Don Gagne committed
277
        setAltitude(z);
278 279 280 281 282
    }
}

void MissionItem::setLatitude(double lat)
{
283
    if (_latitudeFact->value().toDouble() != lat && ((_frame == MAV_FRAME_GLOBAL) || (_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT)))
284
    {
285
        _latitudeFact->setValue(lat);
286
        emit changed(this);
Don Gagne's avatar
Don Gagne committed
287
        emit coordinateChanged(coordinate());
288 289 290 291 292
    }
}

void MissionItem::setLongitude(double lon)
{
293
    if (_longitudeFact->value().toDouble() != lon && ((_frame == MAV_FRAME_GLOBAL) || (_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT)))
294
    {
295
        _longitudeFact->setValue(lon);
296
        emit changed(this);
Don Gagne's avatar
Don Gagne committed
297
        emit coordinateChanged(coordinate());
298 299 300 301 302
    }
}

void MissionItem::setAltitude(double altitude)
{
303
    if (_altitudeFact->value().toDouble() != altitude && ((_frame == MAV_FRAME_GLOBAL) || (_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT)))
304
    {
305
        _altitudeFact->setValue(altitude);
306 307
        emit changed(this);
        emit valueStringsChanged(valueStrings());
Don Gagne's avatar
Don Gagne committed
308
        emit coordinateChanged(coordinate());
309 310 311 312 313
    }
}

void MissionItem::setAction(int /*MAV_CMD*/ action)
{
Don Gagne's avatar
Don Gagne committed
314 315
    if (_command != action) {
        _command = (MavlinkQmlSingleton::Qml_MAV_CMD)action;
316

Don Gagne's avatar
Don Gagne committed
317
        // Fix defaults according to WP type
318

Don Gagne's avatar
Don Gagne committed
319
        if (_command == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) {
320
            // We default to 15 degrees minimum takeoff pitch
Don Gagne's avatar
Don Gagne committed
321
            setParam1(15.0);
322
        }
Don Gagne's avatar
Don Gagne committed
323 324 325 326 327 328 329 330
        
        if (specifiesCoordinate()) {
            if (_frame != MAV_FRAME_GLOBAL && _frame != MAV_FRAME_GLOBAL_RELATIVE_ALT) {
                setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
            }
        } else {
            setFrame(MAV_FRAME_MISSION);
        }
331 332 333

        emit changed(this);
        emit commandNameChanged(commandName());
Don Gagne's avatar
Don Gagne committed
334
        emit commandChanged((MavlinkQmlSingleton::Qml_MAV_CMD)_command);
335 336 337 338 339
        emit valueLabelsChanged(valueLabels());
        emit valueStringsChanged(valueStrings());
    }
}

340 341 342 343 344 345 346 347 348
int MissionItem::frame(void) const
{
    if (_altitudeRelativeToHomeFact->value().toBool()) {
        return MAV_FRAME_GLOBAL_RELATIVE_ALT;
    } else {
        return _frame;
    }
}

349 350 351
void MissionItem::setFrame(int /*MAV_FRAME*/ frame)
{
    if (_frame != frame) {
352
        _altitudeRelativeToHomeFact->setValue(_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT);
353 354 355 356 357 358 359 360 361 362 363 364 365
        _frame = frame;
        emit changed(this);
    }
}

void MissionItem::setAutocontinue(bool autoContinue)
{
    if (_autocontinue != autoContinue) {
        _autocontinue = autoContinue;
        emit changed(this);
    }
}

Don Gagne's avatar
Don Gagne committed
366
void MissionItem::setIsCurrentItem(bool isCurrentItem)
367
{
Don Gagne's avatar
Don Gagne committed
368 369 370
    if (_isCurrentItem != isCurrentItem) {
        _isCurrentItem = isCurrentItem;
        emit isCurrentItemChanged(isCurrentItem);
371 372 373 374 375
    }
}

void MissionItem::setAcceptanceRadius(double radius)
{
Don Gagne's avatar
Don Gagne committed
376
    setParam2(radius);
377 378
}

Don Gagne's avatar
Don Gagne committed
379
void MissionItem::setParam1(double param)
380
{
Don Gagne's avatar
Don Gagne committed
381
    if (param1() != param)
382
    {
Don Gagne's avatar
Don Gagne committed
383
        _param1Fact->setValue(param);
384 385 386 387 388
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}

Don Gagne's avatar
Don Gagne committed
389
void MissionItem::setParam2(double param)
390
{
Don Gagne's avatar
Don Gagne committed
391
    if (param2() != param)
392
    {
Don Gagne's avatar
Don Gagne committed
393
        _param2Fact->setValue(param);
394 395 396 397 398 399 400
        emit valueStringsChanged(valueStrings());
        emit changed(this);
    }
}

void MissionItem::setParam3(double param3)
{
Don Gagne's avatar
Don Gagne committed
401
    setLoiterOrbitRadius(param3);
402 403 404 405
}

void MissionItem::setParam4(double param4)
{
Don Gagne's avatar
Don Gagne committed
406
    setYawRadians(param4);
407 408 409 410
}

void MissionItem::setParam5(double param5)
{
411
    setLatitude(param5);
412 413 414 415
}

void MissionItem::setParam6(double param6)
{
416
    setLongitude(param6);
417 418 419 420
}

void MissionItem::setParam7(double param7)
{
421
    setAltitude(param7);
422 423
}

Don Gagne's avatar
Don Gagne committed
424
void MissionItem::setLoiterOrbitRadius(double radius)
425
{
Don Gagne's avatar
Don Gagne committed
426 427
    if (loiterOrbitRadius() != radius) {
        _loiterOrbitRadiusFact->setValue(radius);
428 429 430 431 432 433 434
        emit valueStringsChanged(valueStrings());
        emit changed(this);
    }
}

void MissionItem::setHoldTime(int holdTime)
{
Don Gagne's avatar
Don Gagne committed
435
    setParam1(holdTime);
436 437 438 439
}

void MissionItem::setHoldTime(double holdTime)
{
Don Gagne's avatar
Don Gagne committed
440
    setParam1(holdTime);
441 442
}

Don Gagne's avatar
Don Gagne committed
443
bool MissionItem::specifiesCoordinate(void) const
444
{
Don Gagne's avatar
Don Gagne committed
445
    switch (_command) {
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
        case MAV_CMD_NAV_WAYPOINT:
        case MAV_CMD_NAV_LOITER_UNLIM:
        case MAV_CMD_NAV_LOITER_TURNS:
        case MAV_CMD_NAV_LOITER_TIME:
        case MAV_CMD_NAV_LAND:
        case MAV_CMD_NAV_TAKEOFF:
            return true;
        default:
            return false;
    }
}

QString MissionItem::commandName(void)
{
    QString type;
    
Don Gagne's avatar
Don Gagne committed
462
    switch (_command) {
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
        case MAV_CMD_NAV_WAYPOINT:
            type = "Waypoint";
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
        case MAV_CMD_NAV_LOITER_TURNS:
        case MAV_CMD_NAV_LOITER_TIME:
            type = "Loiter";
            break;
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
            type = "Return Home";
            break;
        case MAV_CMD_NAV_LAND:
            type = "Land";
            break;
        case MAV_CMD_NAV_TAKEOFF:
            type = "Takeoff";
            break;
        case MAV_CMD_CONDITION_DELAY:
            type = "Delay";
            break;
        case MAV_CMD_DO_JUMP:
            type = "Jump To Command";
            break;
        default:
Don Gagne's avatar
Don Gagne committed
487
            type = QString("Unknown (%1)").arg(_command);
488 489 490 491 492 493 494 495 496 497
            break;
    }
    
    return type;
}

QStringList MissionItem::valueLabels(void)
{
    QStringList labels;
    
Don Gagne's avatar
Don Gagne committed
498
    switch (_command) {
499
        case MAV_CMD_NAV_WAYPOINT:
Don Gagne's avatar
Don Gagne committed
500
            if (frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
                labels << "Alt (rel):";
            } else {
                labels << "Alt:";
            }
            labels << "Heading:" << "Radius:" << "Hold:";
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
            labels << "Heading:" << "Radius:";
            break;
        case MAV_CMD_NAV_LOITER_TURNS:
            labels << "Heading:"  << "Radius:"<< "Turns:";
            break;
        case MAV_CMD_NAV_LOITER_TIME:
            labels << "Heading:" << "Radius:" << "Seconds:";
            break;
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
            break;
        case MAV_CMD_NAV_LAND:
Don Gagne's avatar
Don Gagne committed
519
            if (frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
520 521 522 523 524 525 526
                labels << "Alt (rel):";
            } else {
                labels << "Alt:";
            }
            labels << "Heading:";
            break;
        case MAV_CMD_NAV_TAKEOFF:
Don Gagne's avatar
Don Gagne committed
527
            if (frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
                labels << "Alt (rel):";
            } else {
                labels << "Alt:";
            }
            labels << "Heading:" << "Pitch:";
            break;
        case MAV_CMD_CONDITION_DELAY:
            labels << "Seconds:";
            break;
        case MAV_CMD_DO_JUMP:
            labels << "Jump to:" << "Repeat:";
            break;
        default:
            break;
    }
    
    return labels;
}

QString MissionItem::_oneDecimalString(double value)
{
    return QString("%1").arg(value, 0 /* min field width */, 'f' /* format */, 1 /* precision */);
}

QStringList MissionItem::valueStrings(void)
{
    QStringList list;
    
Don Gagne's avatar
Don Gagne committed
556
    switch (_command) {
557
        case MAV_CMD_NAV_WAYPOINT:
558
            list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawDegrees()) << _oneDecimalString(param2()) << _oneDecimalString(param1());
559 560
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
Don Gagne's avatar
Don Gagne committed
561
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius());
562 563
            break;
        case MAV_CMD_NAV_LOITER_TURNS:
Don Gagne's avatar
Don Gagne committed
564
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
565 566
            break;
        case MAV_CMD_NAV_LOITER_TIME:
Don Gagne's avatar
Don Gagne committed
567
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
568 569 570 571
            break;
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
            break;
        case MAV_CMD_NAV_LAND:
572
            list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI));
573 574
            break;
        case MAV_CMD_NAV_TAKEOFF:
575
            list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(param1());
576 577
            break;
        case MAV_CMD_CONDITION_DELAY:
Don Gagne's avatar
Don Gagne committed
578
            list << _oneDecimalString(param1());
579 580
            break;
        case MAV_CMD_DO_JUMP:
Don Gagne's avatar
Don Gagne committed
581
            list << _oneDecimalString(param1()) << _oneDecimalString(param2());
582 583 584 585 586 587
            break;
        default:
            break;
    }
    
    return list;
Don Gagne's avatar
Don Gagne committed
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
}

QStringList MissionItem::commandNames(void) {
    QStringList list;
    
    for (int i=0; i<_cMavCmd2Name; i++) {
        list += _rgMavCmd2Name[i].name;
    }
    
    return list;
}

int MissionItem::commandByIndex(void)
{
    for (int i=0; i<_cMavCmd2Name; i++) {
Don Gagne's avatar
Don Gagne committed
603
        if (_rgMavCmd2Name[i].command == (MAV_CMD)_command) {
Don Gagne's avatar
Don Gagne committed
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
            return i;
        }
    }
    
    return -1;
}

void MissionItem::setCommandByIndex(int index)
{
    if (index < 0 || index >= _cMavCmd2Name) {
        qWarning() << "Invalid index" << index;
        return;
    }
    
    setCommand((MavlinkQmlSingleton::Qml_MAV_CMD)_rgMavCmd2Name[index].command);
}
Don Gagne's avatar
Don Gagne committed
620

621
QmlObjectListModel* MissionItem::textFieldFacts(void)
Don Gagne's avatar
Don Gagne committed
622 623 624
{
    QmlObjectListModel* model = new QmlObjectListModel(this);
    
Don Gagne's avatar
Don Gagne committed
625
    switch ((MAV_CMD)_command) {
Don Gagne's avatar
Don Gagne committed
626 627 628 629 630
        case MAV_CMD_NAV_WAYPOINT:
            _param2Fact->_setName("Radius:");
            _param2Fact->setMetaData(_acceptanceRadiusMetaData);
            _param1Fact->_setName("Hold:");
            _param1Fact->setMetaData(_holdTimeMetaData);
631 632 633
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
634
            model->append(_yawRadiansFact);
Don Gagne's avatar
Don Gagne committed
635 636 637 638
            model->append(_param2Fact);
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
639 640 641
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
642 643
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
644 645 646 647
            break;
        case MAV_CMD_NAV_LOITER_TURNS:
            _param1Fact->_setName("Turns:");
            _param1Fact->setMetaData(_loiterTurnsMetaData);
648 649 650
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
651 652
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
653 654 655 656 657
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LOITER_TIME:
            _param1Fact->_setName("Seconds:");
            _param1Fact->setMetaData(_loiterSecondsMetaData);
658 659 660
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
661 662
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
663 664 665
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LAND:
666 667 668
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
669
            model->append(_yawRadiansFact);
Don Gagne's avatar
Don Gagne committed
670 671
            break;
        case MAV_CMD_NAV_TAKEOFF:
Don Gagne's avatar
Don Gagne committed
672 673
            _param1Fact->_setName("Pitch:");
            _param1Fact->setMetaData(_pitchMetaData);
674 675 676
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
677 678
            model->append(_yawRadiansFact);
            model->append(_param1Fact);
Don Gagne's avatar
Don Gagne committed
679 680 681 682 683 684 685 686 687 688 689 690 691 692
            break;
        case MAV_CMD_CONDITION_DELAY:
            _param1Fact->_setName("Seconds:");
            _param1Fact->setMetaData(_delaySecondsMetaData);
            model->append(_param1Fact);
            break;
        case MAV_CMD_DO_JUMP:
            _param1Fact->_setName("Seq #:");
            _param1Fact->setMetaData(_jumpSequenceMetaData);
            _param2Fact->_setName("Repeat:");
            _param2Fact->setMetaData(_jumpRepeatMetaData);
            model->append(_param1Fact);
            model->append(_param2Fact);
            break;
Don Gagne's avatar
Don Gagne committed
693 694
        default:
            break;
Don Gagne's avatar
Don Gagne committed
695 696 697 698 699
    }
    
    return model;
}

700
QmlObjectListModel* MissionItem::checkboxFacts(void)
Don Gagne's avatar
Don Gagne committed
701
{
702 703
    QmlObjectListModel* model = new QmlObjectListModel(this);
    
Don Gagne's avatar
Don Gagne committed
704 705
    switch ((MAV_CMD)_command) {
        case MAV_CMD_NAV_WAYPOINT:
706 707
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
708
        case MAV_CMD_NAV_LOITER_UNLIM:
709 710
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
711
        case MAV_CMD_NAV_LOITER_TURNS:
712 713
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
714
        case MAV_CMD_NAV_LOITER_TIME:
715 716
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
717
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
718
            break;
Don Gagne's avatar
Don Gagne committed
719
        case MAV_CMD_NAV_LAND:
720 721
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
722
        case MAV_CMD_NAV_TAKEOFF:
723 724
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
725
        default:
726
            break;
Don Gagne's avatar
Don Gagne committed
727
    }
728 729
    
    return model;
Don Gagne's avatar
Don Gagne committed
730 731
}

Don Gagne's avatar
Don Gagne committed
732 733
double MissionItem::yawRadians(void) const
{
Don Gagne's avatar
Don Gagne committed
734
    return _yawRadiansFact->value().toDouble();
Don Gagne's avatar
Don Gagne committed
735 736 737 738
}

void MissionItem::setYawRadians(double yaw)
{
Don Gagne's avatar
Don Gagne committed
739
    if (yawRadians() != yaw)
Don Gagne's avatar
Don Gagne committed
740
    {
Don Gagne's avatar
Don Gagne committed
741
        _yawRadiansFact->setValue(yaw);
Don Gagne's avatar
Don Gagne committed
742 743 744 745 746 747 748 749 750
        emit yawChanged(yaw);
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}


double MissionItem::yawDegrees(void) const
{
Don Gagne's avatar
Don Gagne committed
751
    return yawRadians() * (180.0 / M_PI);
Don Gagne's avatar
Don Gagne committed
752 753 754 755 756 757 758
}

void MissionItem::setYawDegrees(double yaw)
{
    setYawRadians(yaw * (M_PI / 180.0));
}

759 760 761 762 763 764 765 766 767 768 769
QGeoCoordinate MissionItem::coordinate(void) const
{
    return QGeoCoordinate(latitude(), longitude(), altitude());
}

void MissionItem::setCoordinate(const QGeoCoordinate& coordinate)
{
    setLatitude(coordinate.latitude());
    setLongitude(coordinate.longitude());
    setAltitude(coordinate.altitude());
}
Don Gagne's avatar
Don Gagne committed
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798

bool MissionItem::canEdit(void)
{
    bool found = false;
    
    for (int i=0; i<_cMavCmd2Name; i++) {
        if (_rgMavCmd2Name[i].command == (MAV_CMD)_command) {
            found = true;
            break;
        }
    }
    
    if (found) {
        if (!_autocontinue) {
            qCDebug(MissionItemLog) << "canEdit false due to _autocontinue != true";
            return false;
        }
        
        if (_frame != MAV_FRAME_GLOBAL && _frame != MAV_FRAME_GLOBAL_RELATIVE_ALT && _frame != MAV_FRAME_MISSION) {
            qCDebug(MissionItemLog) << "canEdit false due unsupported frame type:" << _frame;
            return false;
        }
        
        return true;
    } else {
        qCDebug(MissionItemLog) << "canEdit false due unsupported command:" << _command;
        return false;
    }
}