Utils.cpp 6.56 KB
Newer Older
1 2
#include "Utils.h"
#include "MissionSettingsItem.h"
3 4
#include "PlanMasterController.h"

5 6 7
#include <iostream>

#include <QGeoCoordinate>
8 9 10 11 12


bool WaypointManager::Utils::insertMissionItem(const QGeoCoordinate &coordinate,
                                               long index,
                                               QmlObjectListModel &list,
13
                                               PlanMasterController* masterController,
14 15 16 17 18 19 20 21 22 23 24
                                               bool flyView,
                                               QObject *parent,
                                               bool doUpdates)
{
    using namespace WaypointManager::Utils;

    if ( !coordinate.isValid() ){
        return false;
    } else {
        if (parent == nullptr)
            parent = &list;
25
        auto *newItem = new SimpleMissionItem(masterController, flyView, MissionItem(), parent);
26 27 28 29 30 31 32 33

        int sequenceNumber = detail::nextSequenceNumber(list);
        newItem->setSequenceNumber(sequenceNumber);
        newItem->setCoordinate(coordinate);
        newItem->setCommand(MAV_CMD_NAV_WAYPOINT);

        // Set altitude and altitude mode from previous item.
        if (newItem->specifiesAltitude()) {
34 35
            double  altitude = 10;
            int     altitudeMode = QGroundControlQmlGlobal::AltitudeModeRelative;
36

37
            if (detail::previousAltitude(list, index-1, altitude, altitudeMode)) {
38 39 40 41 42 43 44 45 46 47
                newItem->altitude()->setRawValue(altitude);
                newItem->setAltitudeMode(
                            static_cast<QGroundControlQmlGlobal::AltitudeMode>(
                                altitudeMode) );
            }
        }

        list.insert(index, newItem);

        if ( doUpdates ) {
48 49 50
            updateSequenceNumbers(list);
            updateHirarchy(list);
            updateHomePosition(list);
51 52 53 54 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 90 91 92
        }
    }
    return true;
}

size_t WaypointManager::Utils::detail::nextSequenceNumber(QmlObjectListModel &list)
{
    if (list.count() >= 1) {
        VisualMissionItem* lastItem = list.value<VisualMissionItem*>(list.count() - 1);
        return lastItem->lastSequenceNumber() + 1;
    }
    return 0;
}

bool WaypointManager::Utils::detail::previousAltitude(QmlObjectListModel &list,
                                                      size_t index,
                                                      double &altitude,
                                                      int &altitudeMode)
{
    if (index >= size_t(list.count())) {
        return false;
    }

    for (long i = index; i >= 0; --i) {
        VisualMissionItem* visualItem = list.value<VisualMissionItem*>(i);

        if ( visualItem->specifiesCoordinate()
                 && !visualItem->isStandaloneCoordinate() ) {
            if ( visualItem->isSimpleItem() ) {
                SimpleMissionItem* simpleItem = qobject_cast<SimpleMissionItem*>(visualItem);
                if (simpleItem->specifiesAltitude()) {
                    altitude = simpleItem->altitude()->rawValue().toDouble();
                    altitudeMode = simpleItem->altitudeMode();
                    return true;
                }
            }
        }
    }

    return false;
}

93
bool WaypointManager::Utils::updateSequenceNumbers(QmlObjectListModel &list, size_t firstSeqNumber)
94 95 96
{
    using namespace WaypointManager::Utils;

97
    if ( list.count() < 1)
98 99 100
        return false;

    // Setup ascending sequence numbers for all visual items.
101 102 103 104 105 106 107 108
    VisualMissionItem* startItem = list.value<VisualMissionItem*>(0);
    assert(startItem != nullptr); // list empty?
    startItem->setSequenceNumber(firstSeqNumber);
    int sequenceNumber = startItem->lastSequenceNumber() + 1;
    for (int i=1; i < list.count(); ++i) {
        VisualMissionItem* item = list.value<VisualMissionItem*>(i);
        item->setSequenceNumber(sequenceNumber);
        sequenceNumber = item->lastSequenceNumber() + 1;
109 110 111 112
    }
    return true;
}

113
bool WaypointManager::Utils::updateHirarchy(QmlObjectListModel &list)
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
{
    if ( list.count() < 1)
        return false;

    VisualMissionItem* currentParentItem = list.value<VisualMissionItem*>(0);

    currentParentItem->childItems()->clear();

    for (size_t i = 1; i < size_t( list.count() ); ++i) {
        VisualMissionItem* item = list.value<VisualMissionItem*>(i);

        if (item->specifiesCoordinate()) {
            item->childItems()->clear();
            currentParentItem = item;
        } else if (item->isSimpleItem()) {
            currentParentItem->childItems()->append(item);
        }
    }

    return true;
}

136
bool WaypointManager::Utils::updateHomePosition(QmlObjectListModel &list)
137 138
{
    MissionSettingsItem *settingsItem = list.value<MissionSettingsItem *>(0);
139
    assert(settingsItem); // list not initialized?
140

141
    // Set the home position to be a delta from first coordinate.
142 143
    for (int i = 1; i < list.count(); ++i) {
        VisualMissionItem* item = list.value<VisualMissionItem*>(i);
144
        assert(item);
145 146

        if (item->specifiesCoordinate() && item->coordinate().isValid()) {
147
            QGeoCoordinate c = item->coordinate().atDistanceAndAzimuth(3, 0);
148 149 150 151 152 153 154 155 156 157
            c.setAltitude(0);
            settingsItem->setCoordinate(c);
            return true;
        }
    }

    return false;
}

void WaypointManager::Utils::initialize(QmlObjectListModel &list,
158
                                        PlanMasterController *masterController,
159 160
                                        bool flyView)
{
161
    MissionSettingsItem* settingsItem = new MissionSettingsItem(masterController, flyView, &list);
162 163 164
    list.insert(0, settingsItem);
}

165
bool WaypointManager::Utils::updateList(QmlObjectListModel &list)
166 167 168
{
    using namespace WaypointManager::Utils;

169 170 171
    bool ret = updateSequenceNumbers(list);
    ret = updateHirarchy(list) == false ? false : ret;
    (void)updateHomePosition(list);
172 173 174

    return ret;
}
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

void WaypointManager::Utils::printList(QmlObjectListModel &list)
{
    for (int i = 0; i < list.count(); ++i) {
        auto item = list.value<VisualMissionItem*>(i);
        qWarning() << "list index: " << i << "\n"
                   << "coordinate: " << item->coordinate() << "\n"
                   << "seq: " << item->sequenceNumber() << "\n"
                   << "last seq: " << item->lastSequenceNumber() << "\n"
                   << "is simple item: " << item->isSimpleItem() << "\n\n";
    }
}

void WaypointManager::Utils::makeSpeedCmd(SimpleMissionItem *item, double speed)
{
    assert(speed > 0);
    auto c = item->coordinate();
    item->setCommand(MAV_CMD_DO_CHANGE_SPEED);
    // Set coordinate must be after setCommand (setCommand sets coordinate to zero).
    item->setCoordinate(c);
    item->missionItem().setParam2(speed);
}