Skip to content
MissionItem.cc 20.4 KiB
Newer Older
Don Gagne's avatar
Don Gagne committed
/*===================================================================
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
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
    { MAV_CMD_NAV_LOITER_TIME,      "Loiter (seconds)" },
Don Gagne's avatar
Don Gagne committed
    { 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,
                         int            action)
Don Gagne's avatar
Don Gagne committed
    : QObject(parent)
Don Gagne's avatar
Don Gagne committed
    , _sequenceNumber(sequenceNumber)
    , _coordinate(coordinate)
Don Gagne's avatar
Don Gagne committed
    , _frame(frame)
    , _action(action)
    , _autocontinue(autocontinue)
Don Gagne's avatar
Don Gagne committed
    , _isCurrentItem(isCurrentItem)
Don Gagne's avatar
Don Gagne committed
    , _reachedTime(0)
Don Gagne's avatar
Don Gagne committed
    , _yawRadiansFact(NULL)
Don Gagne's avatar
Don Gagne committed
    _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);
    
    setParam1(param1);
    setParam2(param2);
    setYawRadians(param4);
    setLoiterOrbitRadius(param3);
Don Gagne's avatar
Don Gagne committed
    
    // FIXME: Need to fill out more meta data
    
Don Gagne's avatar
Don Gagne committed
    FactMetaData* yawMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    yawMetaData->setUnits("degrees");
Don Gagne's avatar
Don Gagne committed
    
    _pitchMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    _pitchMetaData->setUnits("degrees");
    
    _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
    FactMetaData* loiterOrbitRadiusMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
    loiterOrbitRadiusMetaData->setUnits("meters");
Don Gagne's avatar
Don Gagne committed
    
    _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");
    
Don Gagne's avatar
Don Gagne committed
    _yawRadiansFact->setMetaData(yawMetaData);
    _loiterOrbitRadiusFact->setMetaData(loiterOrbitRadiusMetaData);
Don Gagne's avatar
Don Gagne committed
MissionItem::MissionItem(const MissionItem& other, QObject* parent)
    : QObject(parent)
Don Gagne's avatar
Don Gagne committed
    _yawRadiansFact         = new Fact(this);
    _loiterOrbitRadiusFact  = new Fact(this);
    _param1Fact             = new Fact(this);
    _param2Fact             = new Fact(this);
    
    _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);

Don Gagne's avatar
Don Gagne committed
    *this = other;
}

MissionItem::~MissionItem()
{    
}

const MissionItem& MissionItem::operator=(const MissionItem& other)
{
Don Gagne's avatar
Don Gagne committed
    _sequenceNumber = other._sequenceNumber;
    _isCurrentItem  = other._isCurrentItem;
    _coordinate     = other._coordinate;
    _frame          = other._frame;
    _action         = other._action;
    _autocontinue   = other._autocontinue;
    _reachedTime    = other._reachedTime;
    
Don Gagne's avatar
Don Gagne committed
    *_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;
    
Don Gagne's avatar
Don Gagne committed
    return *this;
}

bool MissionItem::isNavigationType()
{
    return (_action < MAV_CMD_NAV_LAST);
}

void MissionItem::save(QTextStream &saveStream)
{
    QString position("%1\t%2\t%3");
Don Gagne's avatar
Don Gagne committed
    position = position.arg(x(), 0, 'g', 18);
    position = position.arg(y(), 0, 'g', 18);
    position = position.arg(z(), 0, 'g', 18);
Don Gagne's avatar
Don Gagne committed
    QString parameters("%1\t%2\t%3\t%4");
Don Gagne's avatar
Don Gagne committed
    parameters = parameters.arg(getParam2(), 0, 'g', 18).arg(getParam2(), 0, 'g', 18).arg(loiterOrbitRadius(), 0, 'g', 18).arg(yawRadians(), 0, 'g', 18);
Don Gagne's avatar
Don Gagne committed
    // 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
    saveStream << this->sequenceNumber() << "\t" << this->isCurrentItem() << "\t" << this->getFrame() << "\t" << this->getAction() << "\t"  << parameters << "\t" << position  << "\t" << this->getAutoContinue() << "\r\n"; //"\t" << this->getDescription() << "\r\n";
Don Gagne's avatar
Don Gagne committed
}

bool MissionItem::load(QTextStream &loadStream)
{
    const QStringList &wpParams = loadStream.readLine().split("\t");
    if (wpParams.size() == 12) {
Don Gagne's avatar
Don Gagne committed
        setSequenceNumber(wpParams[0].toInt());
        setIsCurrentItem(wpParams[1].toInt() == 1 ? true : false);
Don Gagne's avatar
Don Gagne committed
        _frame = (MAV_FRAME) wpParams[2].toInt();
        _action = (MAV_CMD) wpParams[3].toInt();
Don Gagne's avatar
Don Gagne committed
        setParam1(wpParams[4].toDouble());
        setParam2(wpParams[5].toDouble());
        setLoiterOrbitRadius(wpParams[6].toDouble());
Don Gagne's avatar
Don Gagne committed
        setYawRadians(wpParams[7].toDouble());
Don Gagne's avatar
Don Gagne committed
        setLatitude(wpParams[8].toDouble());
        setLongitude(wpParams[9].toDouble());
        setAltitude(wpParams[10].toDouble());
Don Gagne's avatar
Don Gagne committed
        _autocontinue = (wpParams[11].toInt() == 1 ? true : false);
        return true;
    }
    return false;
}


Don Gagne's avatar
Don Gagne committed
void MissionItem::setSequenceNumber(int sequenceNumber)
Don Gagne's avatar
Don Gagne committed
    _sequenceNumber = sequenceNumber;
    emit sequenceNumberChanged(_sequenceNumber);
Don Gagne's avatar
Don Gagne committed
    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
        setLatitude(x);
Don Gagne's avatar
Don Gagne committed
    }
}

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
        setLongitude(y);
Don Gagne's avatar
Don Gagne committed
    }
}

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
        setAltitude(z);
Don Gagne's avatar
Don Gagne committed
    }
}

void MissionItem::setLatitude(double lat)
{
Don Gagne's avatar
Don Gagne committed
    if (_coordinate.latitude() != lat && ((_frame == MAV_FRAME_GLOBAL) || (_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT)))
Don Gagne's avatar
Don Gagne committed
        _coordinate.setLatitude(lat);
Don Gagne's avatar
Don Gagne committed
        emit changed(this);
Don Gagne's avatar
Don Gagne committed
        emit coordinateChanged(coordinate());
Don Gagne's avatar
Don Gagne committed
    }
}

void MissionItem::setLongitude(double lon)
{
Don Gagne's avatar
Don Gagne committed
    if (_coordinate.longitude() != lon && ((_frame == MAV_FRAME_GLOBAL) || (_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT)))
Don Gagne's avatar
Don Gagne committed
        _coordinate.setLongitude(lon);
Don Gagne's avatar
Don Gagne committed
        emit changed(this);
Don Gagne's avatar
Don Gagne committed
        emit coordinateChanged(coordinate());
Don Gagne's avatar
Don Gagne committed
    }
}

void MissionItem::setAltitude(double altitude)
{
Don Gagne's avatar
Don Gagne committed
    if (_coordinate.altitude() != altitude && ((_frame == MAV_FRAME_GLOBAL) || (_frame == MAV_FRAME_GLOBAL_RELATIVE_ALT)))
Don Gagne's avatar
Don Gagne committed
        _coordinate.setAltitude(altitude);
Don Gagne's avatar
Don Gagne committed
        emit changed(this);
        emit valueStringsChanged(valueStrings());
Don Gagne's avatar
Don Gagne committed
        emit coordinateChanged(coordinate());
Don Gagne's avatar
Don Gagne committed
    }
}

void MissionItem::setAction(int /*MAV_CMD*/ action)
{
    if (_action != action) {
        _action = action;

        // Flick defaults according to WP type

        if (_action == MAV_CMD_NAV_TAKEOFF) {
            // We default to 15 degrees minimum takeoff pitch
Don Gagne's avatar
Don Gagne committed
            setParam1(15.0);
Don Gagne's avatar
Don Gagne committed
        }

        emit changed(this);
        emit commandNameChanged(commandName());
        emit commandChanged((MavlinkQmlSingleton::Qml_MAV_CMD)_action);
Don Gagne's avatar
Don Gagne committed
        emit specifiesCoordinateChanged(specifiesCoordinate());
Don Gagne's avatar
Don Gagne committed
        emit valueLabelsChanged(valueLabels());
        emit valueStringsChanged(valueStrings());
    }
}

void MissionItem::setFrame(int /*MAV_FRAME*/ frame)
{
    if (_frame != frame) {
        _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
void MissionItem::setIsCurrentItem(bool isCurrentItem)
Don Gagne's avatar
Don Gagne committed
    if (_isCurrentItem != isCurrentItem) {
        _isCurrentItem = isCurrentItem;
        emit isCurrentItemChanged(isCurrentItem);
Don Gagne's avatar
Don Gagne committed
    }
}

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

void MissionItem::setParam1(double param1)
{
Don Gagne's avatar
Don Gagne committed
    if (getParam1() != param1)
Don Gagne's avatar
Don Gagne committed
        _param1Fact->setValue(param1);
Don Gagne's avatar
Don Gagne committed
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}

void MissionItem::setParam2(double param2)
{
Don Gagne's avatar
Don Gagne committed
    if (getParam2() != param2)
Don Gagne's avatar
Don Gagne committed
        _param2Fact->setValue(param2);
Don Gagne's avatar
Don Gagne committed
        emit valueStringsChanged(valueStrings());
        emit changed(this);
    }
}

void MissionItem::setParam3(double param3)
{
Don Gagne's avatar
Don Gagne committed
    setLoiterOrbitRadius(param3);
Don Gagne's avatar
Don Gagne committed
}

void MissionItem::setParam4(double param4)
{
Don Gagne's avatar
Don Gagne committed
    setYawRadians(param4);
Don Gagne's avatar
Don Gagne committed
}

void MissionItem::setParam5(double param5)
{
Don Gagne's avatar
Don Gagne committed
    if (_coordinate.latitude() != param5) {
        _coordinate.setLatitude(param5);
Don Gagne's avatar
Don Gagne committed
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}

void MissionItem::setParam6(double param6)
{
Don Gagne's avatar
Don Gagne committed
    if (_coordinate.longitude() != param6) {
        _coordinate.setLongitude(param6);
Don Gagne's avatar
Don Gagne committed
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}

void MissionItem::setParam7(double param7)
{
Don Gagne's avatar
Don Gagne committed
    if (_coordinate.altitude() != param7) {
        _coordinate.setAltitude(param7);
Don Gagne's avatar
Don Gagne committed
        emit valueStringsChanged(valueStrings());
        emit changed(this);
    }
}

Don Gagne's avatar
Don Gagne committed
void MissionItem::setLoiterOrbitRadius(double radius)
Don Gagne's avatar
Don Gagne committed
    if (loiterOrbitRadius() != radius) {
        _loiterOrbitRadiusFact->setValue(radius);
Don Gagne's avatar
Don Gagne committed
        emit valueStringsChanged(valueStrings());
        emit changed(this);
    }
}

void MissionItem::setHoldTime(int holdTime)
{
Don Gagne's avatar
Don Gagne committed
    setParam1(holdTime);
Don Gagne's avatar
Don Gagne committed
}

void MissionItem::setHoldTime(double holdTime)
{
Don Gagne's avatar
Don Gagne committed
    setParam1(holdTime);
Don Gagne's avatar
Don Gagne committed
bool MissionItem::specifiesCoordinate(void) const
Don Gagne's avatar
Don Gagne committed
{
    switch (_action) {
        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;
    
    switch (_action) {
        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:
            type = QString("Unknown (%1)").arg(_action);
            break;
    }
    
    return type;
}

QStringList MissionItem::valueLabels(void)
{
    QStringList labels;
    
    switch (_action) {
        case MAV_CMD_NAV_WAYPOINT:
            if (getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
                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:
            if (getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
                labels << "Alt (rel):";
            } else {
                labels << "Alt:";
            }
            labels << "Heading:";
            break;
        case MAV_CMD_NAV_TAKEOFF:
            if (getFrame() == MAV_FRAME_GLOBAL_RELATIVE_ALT) {
                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;
    
    switch (_action) {
        case MAV_CMD_NAV_WAYPOINT:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(_coordinate.altitude()) << _oneDecimalString(yawDegrees()) << _oneDecimalString(getParam2()) << _oneDecimalString(getParam1());
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius());
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_NAV_LOITER_TURNS:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(getParam1());
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_NAV_LOITER_TIME:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(getParam1());
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
            break;
        case MAV_CMD_NAV_LAND:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(_coordinate.altitude()) << _oneDecimalString(yawRadians() * (180.0 / M_PI));
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_NAV_TAKEOFF:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(_coordinate.altitude()) << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(getParam1());
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_CONDITION_DELAY:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(getParam1());
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_DO_JUMP:
Don Gagne's avatar
Don Gagne committed
            list << _oneDecimalString(getParam1()) << _oneDecimalString(getParam2());
Don Gagne's avatar
Don Gagne committed
            break;
        default:
            break;
    }
    
    return list;
Don Gagne's avatar
Don Gagne committed
}

void MissionItem::setCoordinate(const QGeoCoordinate& coordinate)
{
    _coordinate = coordinate;
    emit coordinateChanged(coordinate);
    emit changed(this);
}

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++) {
        if (_rgMavCmd2Name[i].command == _action) {
            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

QmlObjectListModel* MissionItem::facts(void)
{
    QmlObjectListModel* model = new QmlObjectListModel(this);
    
    switch (_action) {
        case MAV_CMD_NAV_WAYPOINT:
            _param2Fact->_setName("Radius:");
            _param2Fact->setMetaData(_acceptanceRadiusMetaData);
            _param1Fact->_setName("Hold:");
            _param1Fact->setMetaData(_holdTimeMetaData);
Don Gagne's avatar
Don Gagne committed
            model->append(_yawRadiansFact);
Don Gagne's avatar
Don Gagne committed
            model->append(_param2Fact);
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LOITER_UNLIM:
Don Gagne's avatar
Don Gagne committed
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_NAV_LOITER_TURNS:
            _param1Fact->_setName("Turns:");
            _param1Fact->setMetaData(_loiterTurnsMetaData);
Don Gagne's avatar
Don Gagne committed
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_LOITER_TIME:
            _param1Fact->_setName("Seconds:");
            _param1Fact->setMetaData(_loiterSecondsMetaData);
Don Gagne's avatar
Don Gagne committed
            model->append(_yawRadiansFact);
            model->append(_loiterOrbitRadiusFact);
Don Gagne's avatar
Don Gagne committed
            model->append(_param1Fact);
            break;
        case MAV_CMD_NAV_RETURN_TO_LAUNCH:
            break;
        case MAV_CMD_NAV_LAND:
Don Gagne's avatar
Don Gagne committed
            model->append(_yawRadiansFact);
Don Gagne's avatar
Don Gagne committed
            break;
        case MAV_CMD_NAV_TAKEOFF:
Don Gagne's avatar
Don Gagne committed
            _param1Fact->_setName("Pitch:");
            _param1Fact->setMetaData(_pitchMetaData);
            model->append(_yawRadiansFact);
            model->append(_param1Fact);
Don Gagne's avatar
Don Gagne committed
            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;
    }
    
    return model;
}

double MissionItem::yawRadians(void) const
{
Don Gagne's avatar
Don Gagne committed
    return _yawRadiansFact->value().toDouble();
Don Gagne's avatar
Don Gagne committed
}

void MissionItem::setYawRadians(double yaw)
{
Don Gagne's avatar
Don Gagne committed
    if (yawRadians() != yaw)
Don Gagne's avatar
Don Gagne committed
    {
Don Gagne's avatar
Don Gagne committed
        _yawRadiansFact->setValue(yaw);
Don Gagne's avatar
Don Gagne committed
        emit yawChanged(yaw);
        emit changed(this);
        emit valueStringsChanged(valueStrings());
    }
}


double MissionItem::yawDegrees(void) const
{
Don Gagne's avatar
Don Gagne committed
    return yawRadians() * (180.0 / M_PI);
Don Gagne's avatar
Don Gagne committed
}

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