APMAirframeComponentController.cc 9 KB
Newer Older
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.
 *
 ****************************************************************************/

10 11 12 13
#include "APMAirframeComponentController.h"
#include "QGCMAVLink.h"
#include "MultiVehicleManager.h"
#include "QGCApplication.h"
Don Gagne's avatar
Don Gagne committed
14
#include "QGCFileDownload.h"
15
#include "ParameterManager.h"
16 17 18

#include <QVariant>
#include <QQmlProperty>
Don Gagne's avatar
Don Gagne committed
19
#include <QStandardPaths>
Don Gagne's avatar
Don Gagne committed
20
#include <QDir>
Don Gagne's avatar
Don Gagne committed
21 22
#include <QJsonParseError>
#include <QJsonObject>
23

24

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 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
// These should match the FRAME_CLASS parameter enum meta data
#define FRAME_CLASS_UNDEFINED       0
#define FRAME_CLASS_QUAD            1
#define FRAME_CLASS_HEX             2
#define FRAME_CLASS_OCTA            3
#define FRAME_CLASS_OCTAQUAD        4
#define FRAME_CLASS_Y6              5
#define FRAME_CLASS_HELI            6
#define FRAME_CLASS_TRI             7
#define FRAME_CLASS_SINGLECOPTER    8
#define FRAME_CLASS_COAXCOPTER      9
#define FRAME_CLASS_BICOPTER        10
#define FRAME_CLASS_HELI_DUAL       11
#define FRAME_CLASS_DODECAHEXA      12
#define FRAME_CLASS_HELIQUAD        13

// These should match the FRAME_TYPE parameter enum meta data
#define FRAME_TYPE_PLUS         0
#define FRAME_TYPE_X            1
#define FRAME_TYPE_V            2
#define FRAME_TYPE_H            3
#define FRAME_TYPE_V_TAIL       4
#define FRAME_TYPE_A_TAIL       5
#define FRAME_TYPE_Y6B          10
#define FRAME_TYPE_Y6F          11
#define FRAME_TYPE_BETAFLIGHTX  12
#define FRAME_TYPE_DJIX         13
#define FRAME_TYPE_CLOCKWISEX   14

typedef struct {
    int         frameClass;
    int         frameType;
    const char* imageResource;
} FrameToImageInfo_t;

static const FrameToImageInfo_t s_rgFrameToImage[] = {
    { FRAME_CLASS_QUAD,     FRAME_TYPE_PLUS,    "QuadRotorPlus" },
    { FRAME_CLASS_QUAD,     FRAME_TYPE_X,       "QuadRotorX" },
    { FRAME_CLASS_QUAD,     FRAME_TYPE_V,       "QuadRotorWide" },
    { FRAME_CLASS_QUAD,     FRAME_TYPE_H,       "QuadRotorH" },
    { FRAME_CLASS_QUAD,     FRAME_TYPE_V_TAIL,  "QuadRotorVTail" },
    { FRAME_CLASS_QUAD,     FRAME_TYPE_A_TAIL,  "QuadRotorATail" },
    { FRAME_CLASS_HEX,      FRAME_TYPE_PLUS,    "HexaRotorPlus" },
    { FRAME_CLASS_HEX,      FRAME_TYPE_X,       "HexaRotorX" },
    { FRAME_CLASS_OCTA,     FRAME_TYPE_PLUS,    "OctoRotorPlus" },
    { FRAME_CLASS_OCTA,     FRAME_TYPE_X,       "OctoRotorX" },
    { FRAME_CLASS_OCTAQUAD, FRAME_TYPE_PLUS,    "OctoRotorPlusCoaxial" },
    { FRAME_CLASS_OCTAQUAD, FRAME_TYPE_X,       "OctoRotorXCoaxial" },
    { FRAME_CLASS_Y6,       FRAME_TYPE_Y6B,     "Y6B" },
    { FRAME_CLASS_Y6,       FRAME_TYPE_Y6F,     "AirframeUnknown" },
    { FRAME_CLASS_Y6,       -1,                 "Y6A" },
    { FRAME_CLASS_HELI,     -1,                 "Helicopter" },
    { FRAME_CLASS_TRI,      -1,                 "YPlus" },
};

static QString s_findImageResource(int frameClass, int frameType)
{
    for (size_t i=0; i<sizeof(s_rgFrameToImage)/sizeof(s_rgFrameToImage[0]); i++) {
        const FrameToImageInfo_t* pFrameToImageInfo = &s_rgFrameToImage[i];

        if (pFrameToImageInfo->frameClass == frameClass && pFrameToImageInfo->frameType == frameType) {
            return pFrameToImageInfo->imageResource;
        } else if (pFrameToImageInfo->frameClass == frameClass && pFrameToImageInfo->frameType == -1) {
            return pFrameToImageInfo->imageResource;
        }
90
    }
91

92
    return QStringLiteral("AirframeUnknown");
93 94
}

95 96 97 98
APMAirframeComponentController::APMAirframeComponentController(void)
    : _frameClassFact   (getParameterFact(FactSystem::defaultComponentId, QStringLiteral("FRAME_CLASS")))
    , _frameTypeFact    (getParameterFact(FactSystem::defaultComponentId, QStringLiteral("FRAME_TYPE")))
    , _frameClassModel  (new QmlObjectListModel(this))
99
{
100
    _fillFrameClasses();
101 102
}

103
APMAirframeComponentController::~APMAirframeComponentController()
104
{
105

106 107
}

108
void APMAirframeComponentController::_fillFrameClasses()
109
{
110
    QList<int> frameTypeNotSupported;
111

112 113 114 115 116 117
    frameTypeNotSupported << FRAME_CLASS_HELI
                          << FRAME_CLASS_SINGLECOPTER
                          << FRAME_CLASS_COAXCOPTER
                          << FRAME_CLASS_BICOPTER
                          << FRAME_CLASS_HELI_DUAL
                          << FRAME_CLASS_HELIQUAD;
118

119 120 121 122
    for (int i=1; i<_frameClassFact->enumStrings().count(); i++) {
        QString frameClassName =    _frameClassFact->enumStrings()[i];
        int     frameClass =        _frameClassFact->enumValues()[i].toInt();
        int     defaultFrameType;
123

124 125 126 127
        if (frameTypeNotSupported.contains(frameClass)) {
            defaultFrameType = -1;
        } else {
            defaultFrameType = FRAME_TYPE_X;
128
        }
129
        _frameClassModel->append(new APMFrameClass(frameClassName, frameClass, _frameTypeFact, defaultFrameType, _frameClassModel));
130 131 132
    }
}

Don Gagne's avatar
Don Gagne committed
133 134 135 136 137 138 139 140
void APMAirframeComponentController::_loadParametersFromDownloadFile(const QString& downloadedParamFile)
{
    QFile parametersFile(downloadedParamFile);
    if (!parametersFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "Unable to open downloaded parameter file" << downloadedParamFile << parametersFile.errorString();
        qgcApp()->restoreOverrideCursor();
        return;
    }
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

    QTextStream reader(&parametersFile);

    while (!reader.atEnd()) {
        QString line = reader.readLine().trimmed();
        if (line.isEmpty() || line.at(0) == QChar('#')) {
            continue;
        }

        QStringList aux = line.split(',');
        if (parameterExists(-1, aux.at(0))) {
            Fact *param = getParameterFact(-1, aux.at(0));
            param->setRawValue(QVariant::fromValue(aux.at(1)));
        }
    }
Don Gagne's avatar
Don Gagne committed
156
    qgcApp()->restoreOverrideCursor();
157
    _vehicle->parameterManager()->refreshAllParameters();
158 159
}

Don Gagne's avatar
Don Gagne committed
160
void APMAirframeComponentController::loadParameters(const QString& paramFile)
161 162
{
    qgcApp()->setOverrideCursor(Qt::WaitCursor);
Don Gagne's avatar
Don Gagne committed
163 164 165 166 167 168 169

    QString paramFileUrl = QStringLiteral("https://api.github.com/repos/ArduPilot/ardupilot/contents/Tools/Frame_params/%1?ref=master");

    QGCFileDownload* downloader = new QGCFileDownload(this);
    connect(downloader, &QGCFileDownload::downloadFinished, this, &APMAirframeComponentController::_githubJsonDownloadFinished);
    connect(downloader, &QGCFileDownload::error, this, &APMAirframeComponentController::_githubJsonDownloadError);
    downloader->download(paramFileUrl.arg(paramFile));
170 171
}

Don Gagne's avatar
Don Gagne committed
172
void APMAirframeComponentController::_githubJsonDownloadFinished(QString remoteFile, QString localFile)
173
{
Don Gagne's avatar
Don Gagne committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    Q_UNUSED(remoteFile);

    QFile jsonFile(localFile);
    if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "Unable to open github json file" << localFile << jsonFile.errorString();
        qgcApp()->restoreOverrideCursor();
        return;
    }
    QByteArray bytes = jsonFile.readAll();
    jsonFile.close();

    QJsonParseError jsonParseError;
    QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError);
    if (jsonParseError.error != QJsonParseError::NoError) {
        qWarning() <<  "Unable to open json document" << localFile << jsonParseError.errorString();
        qgcApp()->restoreOverrideCursor();
        return;
    }
    QJsonObject json = doc.object();

    QGCFileDownload* downloader = new QGCFileDownload(this);
    connect(downloader, &QGCFileDownload::downloadFinished, this, &APMAirframeComponentController::_paramFileDownloadFinished);
    connect(downloader, &QGCFileDownload::error, this, &APMAirframeComponentController::_paramFileDownloadError);
Don Gagne's avatar
Don Gagne committed
197
    downloader->download(json[QLatin1Literal("download_url")].toString());
Don Gagne's avatar
Don Gagne committed
198 199 200 201
}

void APMAirframeComponentController::_githubJsonDownloadError(QString errorMsg)
{
202
    qgcApp()->showMessage(tr("Param file github json download failed: %1").arg(errorMsg));
Don Gagne's avatar
Don Gagne committed
203
    qgcApp()->restoreOverrideCursor();
204 205
}

Don Gagne's avatar
Don Gagne committed
206 207 208 209 210 211 212 213 214
void APMAirframeComponentController::_paramFileDownloadFinished(QString remoteFile, QString localFile)
{
    Q_UNUSED(remoteFile);

    _loadParametersFromDownloadFile(localFile);
}

void APMAirframeComponentController::_paramFileDownloadError(QString errorMsg)
{
Don Gagne's avatar
Don Gagne committed
215
    qgcApp()->showMessage(tr("Param file download failed: %1").arg(errorMsg));
Don Gagne's avatar
Don Gagne committed
216 217
    qgcApp()->restoreOverrideCursor();
}
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

APMFrameClass::APMFrameClass(const QString& name, int frameClass, Fact* frameTypeFact, int defaultFrameType, QObject* parent)
    : QObject               (parent)
    , _name                 (name)
    , _frameClass           (frameClass)
    , _defaultFrameType     (defaultFrameType)
    , _frameTypeSupported   (defaultFrameType != -1)
    , _frameTypeFact        (frameTypeFact)
{
    connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::imageResourceChanged);
    connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::frameTypeChanged);
}

APMFrameClass::~APMFrameClass()
{

}

QString APMFrameClass::imageResource(void)
{
    return QStringLiteral("/qmlimages/Airframe/%1").arg(s_findImageResource(_frameClass, _frameTypeFact->rawValue().toInt()));
}