AirMapAdvisoryManager.cc 5.95 KB
Newer Older
Gus Grubba's avatar
Gus Grubba committed
1 2 3 4 5 6 7 8 9
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

Gus Grubba's avatar
Gus Grubba committed
10
#include "AirMapAdvisoryManager.h"
11
#include "AirspaceRestriction.h"
Gus Grubba's avatar
Gus Grubba committed
12
#include "AirMapRulesetsManager.h"
Gus Grubba's avatar
Gus Grubba committed
13
#include "AirMapManager.h"
Gus Grubba's avatar
Gus Grubba committed
14
#include "QGCApplication.h"
Gus Grubba's avatar
Gus Grubba committed
15

16
#include <cmath>
17
#include <QTimer>
Gus Grubba's avatar
Gus Grubba committed
18
#include <QDateTime>
19 20

#include "airmap/airspaces.h"
Gus Grubba's avatar
Gus Grubba committed
21
#include "airmap/advisory.h"
22

Gus Grubba's avatar
Gus Grubba committed
23 24 25 26
#define ADVISORY_UPDATE_DISTANCE    500     //-- 500m threshold for updates

using namespace airmap;

Gus Grubba's avatar
Gus Grubba committed
27 28 29 30 31 32 33
//-----------------------------------------------------------------------------
AirMapAdvisory::AirMapAdvisory(QObject* parent)
    : AirspaceAdvisory(parent)
{
}

//-----------------------------------------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
34
AirMapAdvisoryManager::AirMapAdvisoryManager(AirMapSharedState& shared, QObject *parent)
Gus Grubba's avatar
Gus Grubba committed
35 36 37 38 39 40
    : AirspaceAdvisoryProvider(parent)
    , _valid(false)
    , _shared(shared)
{
}

Gus Grubba's avatar
Gus Grubba committed
41
//-----------------------------------------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
42
void
43
AirMapAdvisoryManager::setROI(const QGCGeoBoundingCube& roi, bool reset)
Gus Grubba's avatar
Gus Grubba committed
44 45
{
    //-- If first time or we've moved more than ADVISORY_UPDATE_DISTANCE, ask for updates.
46
    if(reset || (!_lastROI.isValid() || _lastROI.pointNW.distanceTo(roi.pointNW) > ADVISORY_UPDATE_DISTANCE || _lastROI.pointSE.distanceTo(roi.pointSE) > ADVISORY_UPDATE_DISTANCE)) {
47
        _lastROI = roi;
48
        _requestAdvisories();
Gus Grubba's avatar
Gus Grubba committed
49 50 51
    }
}

Gus Grubba's avatar
Gus Grubba committed
52 53 54 55 56 57 58
//-----------------------------------------------------------------------------
static bool
adv_sort(QObject* a, QObject* b)
{
    AirMapAdvisory* aa = qobject_cast<AirMapAdvisory*>(a);
    AirMapAdvisory* bb = qobject_cast<AirMapAdvisory*>(b);
    if(!aa || !bb) return false;
59
    return static_cast<int>(aa->color()) > static_cast<int>(bb->color());
Gus Grubba's avatar
Gus Grubba committed
60 61 62
}

//-----------------------------------------------------------------------------
Gus Grubba's avatar
Gus Grubba committed
63
void
64
AirMapAdvisoryManager::_requestAdvisories()
Gus Grubba's avatar
Gus Grubba committed
65
{
66
    qCDebug(AirMapManagerLog) << "Advisories Request (ROI Changed)";
Gus Grubba's avatar
Gus Grubba committed
67 68 69 70 71 72 73
    if (!_shared.client()) {
        qCDebug(AirMapManagerLog) << "No AirMap client instance. Not updating Advisories";
        _valid = false;
        emit advisoryChanged();
        return;
    }
    _valid = false;
74
    _advisories.clearAndDeleteContents();
Gus Grubba's avatar
Gus Grubba committed
75 76 77
    Advisory::Search::Parameters params;
    //-- Geometry
    Geometry::Polygon polygon;
78 79
    //-- Get ROI bounding box, clipping to max area of interest
    for (const auto& qcoord : _lastROI.polygon2D(qgcApp()->toolbox()->airspaceManager()->maxAreaOfInterest())) {
Gus Grubba's avatar
Gus Grubba committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
        Geometry::Coordinate coord;
        coord.latitude  = qcoord.latitude();
        coord.longitude = qcoord.longitude();
        polygon.outer_ring.coordinates.push_back(coord);
    }
    params.geometry = Geometry(polygon);
    //-- Rulesets
    AirMapRulesetsManager* pRulesMgr = dynamic_cast<AirMapRulesetsManager*>(qgcApp()->toolbox()->airspaceManager()->ruleSets());
    QString ruleIDs;
    if(pRulesMgr) {
        for(int rs = 0; rs < pRulesMgr->ruleSets()->count(); rs++) {
            AirMapRuleSet* ruleSet = qobject_cast<AirMapRuleSet*>(pRulesMgr->ruleSets()->get(rs));
            //-- If this ruleset is selected
            if(ruleSet && ruleSet->selected()) {
                ruleIDs = ruleIDs + ruleSet->id();
                //-- Separate rules with commas
                if(rs < pRulesMgr->ruleSets()->count() - 1) {
                    ruleIDs = ruleIDs + ",";
                }
            }
        }
    }
102 103 104 105 106 107
    if(ruleIDs.isEmpty()) {
        qCDebug(AirMapManagerLog) << "No rules defined. Not updating Advisories";
        _valid = false;
        emit advisoryChanged();
        return;
    }
Gus Grubba's avatar
Gus Grubba committed
108 109 110 111 112 113
    params.rulesets = ruleIDs.toStdString();
    //-- Time
    quint64 start   = static_cast<quint64>(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch());
    quint64 end     = start + 60 * 30 * 1000;
    params.start    = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast<qint64>(start)));
    params.end      = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast<qint64>(end)));
114
    std::weak_ptr<LifetimeChecker> isAlive(_instance);
Gus Grubba's avatar
Gus Grubba committed
115
    _shared.client()->advisory().search(params, [this, isAlive](const Advisory::Search::Result& result) {
116
        if (!isAlive.lock()) return;
Gus Grubba's avatar
Gus Grubba committed
117
        if (result) {
Gus Grubba's avatar
Gus Grubba committed
118 119 120
            qCDebug(AirMapManagerLog) << "Successful advisory search. Items:" << result.value().size();
            _airspaceColor = AirspaceAdvisoryProvider::Green;
            for (const auto& advisory : result.value()) {
Gus Grubba's avatar
Gus Grubba committed
121
                AirMapAdvisory* pAdvisory = new AirMapAdvisory(this);
Gus Grubba's avatar
Gus Grubba committed
122 123 124 125 126 127 128
                pAdvisory->_id          = QString::fromStdString(advisory.advisory.airspace.id());
                pAdvisory->_name        = QString::fromStdString(advisory.advisory.airspace.name());
                pAdvisory->_type        = static_cast<AirspaceAdvisory::AdvisoryType>(advisory.advisory.airspace.type());
                pAdvisory->_color       = static_cast<AirspaceAdvisoryProvider::AdvisoryColor>(advisory.color);
                if(pAdvisory->_color > _airspaceColor) {
                    _airspaceColor = pAdvisory->_color;
                }
129
                _advisories.append(pAdvisory);
Gus Grubba's avatar
Gus Grubba committed
130
                qCDebug(AirMapManagerLog) << "Adding advisory" << pAdvisory->name();
Gus Grubba's avatar
Gus Grubba committed
131
            }
Gus Grubba's avatar
Gus Grubba committed
132
            //-- Sort in order of color (priority)
133 134 135
            _advisories.beginReset();
            std::sort(_advisories.objectList()->begin(), _advisories.objectList()->end(), adv_sort);
            _advisories.endReset();
Gus Grubba's avatar
Gus Grubba committed
136
            _valid = true;
Gus Grubba's avatar
Gus Grubba committed
137
        } else {
138 139
            QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
            qCDebug(AirMapManagerLog) << "Advisories Request Failed" << QString::fromStdString(result.error().message()) << description;
Gus Grubba's avatar
Gus Grubba committed
140 141 142 143
        }
        emit advisoryChanged();
    });
}