MissionItem.cc 24.2 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"

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

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
54 55 56 57
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
58
    { MAV_CMD_NAV_LOITER_TIME,      "Loiter (seconds)" },
Don Gagne's avatar
Don Gagne committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    { 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
76
                         int            command)
77
    : QObject(parent)
Don Gagne's avatar
Don Gagne committed
78
    , _sequenceNumber(sequenceNumber)
Don Gagne's avatar
Don Gagne committed
79
    , _command((MavlinkQmlSingleton::Qml_MAV_CMD)command)
80
    , _autocontinue(autocontinue)
Don Gagne's avatar
Don Gagne committed
81
    , _isCurrentItem(isCurrentItem)
82
    , _reachedTime(0)
Don Gagne's avatar
Don Gagne committed
83
    , _yawRadiansFact(NULL)
84
{
85 86 87 88 89 90 91 92
    _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
93

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

Don Gagne's avatar
Don Gagne committed
150 151
MissionItem::MissionItem(const MissionItem& other, QObject* parent)
    : QObject(parent)
152
{
153 154 155 156 157 158 159 160
    _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
161 162 163 164 165 166 167 168 169 170 171
    
    _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);

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

MissionItem::~MissionItem()
{    
}

const MissionItem& MissionItem::operator=(const MissionItem& other)
{
181 182 183 184 185 186 187
    _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
188
    
189 190 191
    *_latitudeFact              = *other._latitudeFact;
    *_longitudeFact             = *other._longitudeFact;
    *_altitudeFact              = *other._altitudeFact;
Don Gagne's avatar
Don Gagne committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205
    *_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;
    
206 207 208 209 210
    return *this;
}

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

void MissionItem::save(QTextStream &saveStream)
{
    QString position("%1\t%2\t%3");
Don Gagne's avatar
Don Gagne committed
217 218 219
    position = position.arg(x(), 0, 'g', 18);
    position = position.arg(y(), 0, 'g', 18);
    position = position.arg(z(), 0, 'g', 18);
220
    QString parameters("%1\t%2\t%3\t%4");
Don Gagne's avatar
Don Gagne committed
221
    parameters = parameters.arg(param2(), 0, 'g', 18).arg(param2(), 0, 'g', 18).arg(loiterOrbitRadius(), 0, 'g', 18).arg(yawRadians(), 0, 'g', 18);
222 223
    // 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
224
    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";
225 226 227 228 229 230
}

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


Don Gagne's avatar
Don Gagne committed
249
void MissionItem::setSequenceNumber(int sequenceNumber)
250
{
Don Gagne's avatar
Don Gagne committed
251 252
    _sequenceNumber = sequenceNumber;
    emit sequenceNumberChanged(_sequenceNumber);
253 254 255 256 257 258 259
    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
260
        setLatitude(x);
261 262 263 264 265 266 267
    }
}

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
268
        setLongitude(y);
269 270 271 272 273 274 275
    }
}

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
276
        setAltitude(z);
277 278 279 280 281
    }
}

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

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

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

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

        // Flick defaults according to WP type

Don Gagne's avatar
Don Gagne committed
318
        if (_command == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) {
319
            // We default to 15 degrees minimum takeoff pitch
Don Gagne's avatar
Don Gagne committed
320
            setParam1(15.0);
321 322 323 324
        }

        emit changed(this);
        emit commandNameChanged(commandName());
Don Gagne's avatar
Don Gagne committed
325
        emit commandChanged((MavlinkQmlSingleton::Qml_MAV_CMD)_command);
326 327 328 329 330
        emit valueLabelsChanged(valueLabels());
        emit valueStringsChanged(valueStrings());
    }
}

331 332 333 334 335 336 337 338 339
int MissionItem::frame(void) const
{
    if (_altitudeRelativeToHomeFact->value().toBool()) {
        return MAV_FRAME_GLOBAL_RELATIVE_ALT;
    } else {
        return _frame;
    }
}

340 341 342
void MissionItem::setFrame(int /*MAV_FRAME*/ frame)
{
    if (_frame != frame) {
343
        _altitudeRelativeToHomeFact->setValue(_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT);
344 345 346 347 348 349 350 351 352 353 354 355 356
        _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
357
void MissionItem::setIsCurrentItem(bool isCurrentItem)
358
{
Don Gagne's avatar
Don Gagne committed
359 360 361
    if (_isCurrentItem != isCurrentItem) {
        _isCurrentItem = isCurrentItem;
        emit isCurrentItemChanged(isCurrentItem);
362 363 364 365 366
    }
}

void MissionItem::setAcceptanceRadius(double radius)
{
Don Gagne's avatar
Don Gagne committed
367
    setParam2(radius);
368 369
}

Don Gagne's avatar
Don Gagne committed
370
void MissionItem::setParam1(double param)
371
{
Don Gagne's avatar
Don Gagne committed
372
    if (param1() != param)
373
    {
Don Gagne's avatar
Don Gagne committed
374
        _param1Fact->setValue(param);
375 376 377 378 379
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}

Don Gagne's avatar
Don Gagne committed
380
void MissionItem::setParam2(double param)
381
{
Don Gagne's avatar
Don Gagne committed
382
    if (param2() != param)
383
    {
Don Gagne's avatar
Don Gagne committed
384
        _param2Fact->setValue(param);
385 386 387 388 389 390 391
        emit valueStringsChanged(valueStrings());
        emit changed(this);
    }
}

void MissionItem::setParam3(double param3)
{
Don Gagne's avatar
Don Gagne committed
392
    setLoiterOrbitRadius(param3);
393 394 395 396
}

void MissionItem::setParam4(double param4)
{
Don Gagne's avatar
Don Gagne committed
397
    setYawRadians(param4);
398 399 400 401
}

void MissionItem::setParam5(double param5)
{
402
    setLatitude(param5);
403 404 405 406
}

void MissionItem::setParam6(double param6)
{
407
    setLongitude(param6);
408 409 410 411
}

void MissionItem::setParam7(double param7)
{
412
    setAltitude(param7);
413 414
}

Don Gagne's avatar
Don Gagne committed
415
void MissionItem::setLoiterOrbitRadius(double radius)
416
{
Don Gagne's avatar
Don Gagne committed
417 418
    if (loiterOrbitRadius() != radius) {
        _loiterOrbitRadiusFact->setValue(radius);
419 420 421 422 423 424 425
        emit valueStringsChanged(valueStrings());
        emit changed(this);
    }
}

void MissionItem::setHoldTime(int holdTime)
{
Don Gagne's avatar
Don Gagne committed
426
    setParam1(holdTime);
427 428 429 430
}

void MissionItem::setHoldTime(double holdTime)
{
Don Gagne's avatar
Don Gagne committed
431
    setParam1(holdTime);
432 433
}

Don Gagne's avatar
Don Gagne committed
434
bool MissionItem::specifiesCoordinate(void) const
435
{
Don Gagne's avatar
Don Gagne committed
436
    switch (_command) {
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
        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
453
    switch (_command) {
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
        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
478
            type = QString("Unknown (%1)").arg(_command);
479 480 481 482 483 484 485 486 487 488
            break;
    }
    
    return type;
}

QStringList MissionItem::valueLabels(void)
{
    QStringList labels;
    
Don Gagne's avatar
Don Gagne committed
489
    switch (_command) {
490
        case MAV_CMD_NAV_WAYPOINT:
Don Gagne's avatar
Don Gagne committed
491
            if (frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
                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
510
            if (frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
511 512 513 514 515 516 517
                labels << "Alt (rel):";
            } else {
                labels << "Alt:";
            }
            labels << "Heading:";
            break;
        case MAV_CMD_NAV_TAKEOFF:
Don Gagne's avatar
Don Gagne committed
518
            if (frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
                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
547
    switch (_command) {
548
        case MAV_CMD_NAV_WAYPOINT:
549
            list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawDegrees()) << _oneDecimalString(param2()) << _oneDecimalString(param1());
550 551
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
Don Gagne's avatar
Don Gagne committed
552
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius());
553 554
            break;
        case MAV_CMD_NAV_LOITER_TURNS:
Don Gagne's avatar
Don Gagne committed
555
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
556 557
            break;
        case MAV_CMD_NAV_LOITER_TIME:
Don Gagne's avatar
Don Gagne committed
558
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
559 560 561 562
            break;
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
            break;
        case MAV_CMD_NAV_LAND:
563
            list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI));
564 565
            break;
        case MAV_CMD_NAV_TAKEOFF:
566
            list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(param1());
567 568
            break;
        case MAV_CMD_CONDITION_DELAY:
Don Gagne's avatar
Don Gagne committed
569
            list << _oneDecimalString(param1());
570 571
            break;
        case MAV_CMD_DO_JUMP:
Don Gagne's avatar
Don Gagne committed
572
            list << _oneDecimalString(param1()) << _oneDecimalString(param2());
573 574 575 576 577 578
            break;
        default:
            break;
    }
    
    return list;
Don Gagne's avatar
Don Gagne committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
}

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
594
        if (_rgMavCmd2Name[i].command == (MAV_CMD)_command) {
Don Gagne's avatar
Don Gagne committed
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
            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
611

612
QmlObjectListModel* MissionItem::textFieldFacts(void)
Don Gagne's avatar
Don Gagne committed
613 614 615
{
    QmlObjectListModel* model = new QmlObjectListModel(this);
    
Don Gagne's avatar
Don Gagne committed
616
    switch ((MAV_CMD)_command) {
Don Gagne's avatar
Don Gagne committed
617 618 619 620 621
        case MAV_CMD_NAV_WAYPOINT:
            _param2Fact->_setName("Radius:");
            _param2Fact->setMetaData(_acceptanceRadiusMetaData);
            _param1Fact->_setName("Hold:");
            _param1Fact->setMetaData(_holdTimeMetaData);
622 623 624
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
625
            model->append(_yawRadiansFact);
Don Gagne's avatar
Don Gagne committed
626 627 628 629
            model->append(_param2Fact);
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
630 631 632
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
633 634
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
635 636 637 638
            break;
        case MAV_CMD_NAV_LOITER_TURNS:
            _param1Fact->_setName("Turns:");
            _param1Fact->setMetaData(_loiterTurnsMetaData);
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 648
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LOITER_TIME:
            _param1Fact->_setName("Seconds:");
            _param1Fact->setMetaData(_loiterSecondsMetaData);
649 650 651
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
652 653
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
654 655 656
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LAND:
657 658 659
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
660
            model->append(_yawRadiansFact);
Don Gagne's avatar
Don Gagne committed
661 662
            break;
        case MAV_CMD_NAV_TAKEOFF:
Don Gagne's avatar
Don Gagne committed
663 664
            _param1Fact->_setName("Pitch:");
            _param1Fact->setMetaData(_pitchMetaData);
665 666 667
            model->append(_latitudeFact);
            model->append(_longitudeFact);
            model->append(_altitudeFact);
Don Gagne's avatar
Don Gagne committed
668 669
            model->append(_yawRadiansFact);
            model->append(_param1Fact);
Don Gagne's avatar
Don Gagne committed
670 671 672 673 674 675 676 677 678 679 680 681 682 683
            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
684 685
        default:
            break;
Don Gagne's avatar
Don Gagne committed
686 687 688 689 690
    }
    
    return model;
}

691
QmlObjectListModel* MissionItem::checkboxFacts(void)
Don Gagne's avatar
Don Gagne committed
692
{
693 694
    QmlObjectListModel* model = new QmlObjectListModel(this);
    
Don Gagne's avatar
Don Gagne committed
695 696
    switch ((MAV_CMD)_command) {
        case MAV_CMD_NAV_WAYPOINT:
697 698
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
699
        case MAV_CMD_NAV_LOITER_UNLIM:
700 701
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
702
        case MAV_CMD_NAV_LOITER_TURNS:
703 704
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
705
        case MAV_CMD_NAV_LOITER_TIME:
706 707
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
708
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
709
            break;
Don Gagne's avatar
Don Gagne committed
710
        case MAV_CMD_NAV_LAND:
711 712
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
713
        case MAV_CMD_NAV_TAKEOFF:
714 715
            model->append(_altitudeRelativeToHomeFact);
            break;
Don Gagne's avatar
Don Gagne committed
716
        default:
717
            break;
Don Gagne's avatar
Don Gagne committed
718
    }
719 720
    
    return model;
Don Gagne's avatar
Don Gagne committed
721 722
}

Don Gagne's avatar
Don Gagne committed
723 724
double MissionItem::yawRadians(void) const
{
Don Gagne's avatar
Don Gagne committed
725
    return _yawRadiansFact->value().toDouble();
Don Gagne's avatar
Don Gagne committed
726 727 728 729
}

void MissionItem::setYawRadians(double yaw)
{
Don Gagne's avatar
Don Gagne committed
730
    if (yawRadians() != yaw)
Don Gagne's avatar
Don Gagne committed
731
    {
Don Gagne's avatar
Don Gagne committed
732
        _yawRadiansFact->setValue(yaw);
Don Gagne's avatar
Don Gagne committed
733 734 735 736 737 738 739 740 741
        emit yawChanged(yaw);
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}


double MissionItem::yawDegrees(void) const
{
Don Gagne's avatar
Don Gagne committed
742
    return yawRadians() * (180.0 / M_PI);
Don Gagne's avatar
Don Gagne committed
743 744 745 746 747 748 749
}

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

750 751 752 753 754 755 756 757 758 759 760
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());
}