QGCPX4VehicleConfig.cc 12.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// On Windows (for VS2010) stdint.h contains the limits normally contained in limits.h
// It also needs the __STDC_LIMIT_MACROS macro defined in order to include them (done
// in qgroundcontrol.pri).
#ifdef WIN32
#include <stdint.h>
#else
#include <limits.h>
#endif

#include <QTimer>
#include <QDir>
#include <QXmlStreamReader>
#include <QMessageBox>
14
#include <QLabel>
15 16

#include "QGCPX4VehicleConfig.h"
17

18 19
#include "QGC.h"
#include "QGCToolWidget.h"
20
#include "UASManager.h"
21
#include "LinkManager.h"
22
#include "UASParameterCommsMgr.h"
23
#include "ui_QGCPX4VehicleConfig.h"
24
#include "px4_configuration/QGCPX4AirframeConfig.h"
25
#include "px4_configuration/QGCPX4SensorCalibration.h"
26
#include "px4_configuration/PX4RCCalibration.h"
27

28
#ifdef QGC_QUPGRADE_ENABLED
29
#include <dialog_bare.h>
30
#endif
tstellanova's avatar
tstellanova committed
31

32 33 34 35 36 37
#define WIDGET_INDEX_FIRMWARE 0
#define WIDGET_INDEX_RC 1
#define WIDGET_INDEX_SENSOR_CAL 2
#define WIDGET_INDEX_AIRFRAME_CONFIG 3
#define WIDGET_INDEX_GENERAL_CONFIG 4
#define WIDGET_INDEX_ADV_CONFIG 5
38 39 40 41

#define MIN_PWM_VAL 800
#define MAX_PWM_VAL 2200

42 43 44
QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) :
    QWidget(parent),
    mav(NULL),
45
    px4AirframeConfig(NULL),
Lorenz Meier's avatar
Lorenz Meier committed
46 47
    planeBack(":/files/images/px4/rc/cessna_back.png"),
    planeSide(":/files/images/px4/rc/cessna_side.png"),
Lorenz Meier's avatar
Lorenz Meier committed
48
    px4SensorCalibration(NULL),
49 50 51 52 53 54 55
    ui(new Ui::QGCPX4VehicleConfig)
{
    doneLoadingConfig = false;

    setObjectName("QGC_VEHICLECONFIG");
    ui->setupUi(this);

56 57 58 59 60
    ui->advancedMenuButton->setEnabled(false);
    ui->airframeMenuButton->setEnabled(false);
    ui->sensorMenuButton->setEnabled(false);
    ui->rcMenuButton->setEnabled(false);

61 62 63
    px4AirframeConfig = new QGCPX4AirframeConfig(this);
    ui->airframeLayout->addWidget(px4AirframeConfig);

64 65 66
    px4SensorCalibration = new QGCPX4SensorCalibration(this);
    ui->sensorLayout->addWidget(px4SensorCalibration);

67 68 69
    px4RCCalibration = new PX4RCCalibration(this);
    ui->rcLayout->addWidget(px4RCCalibration);
    
70 71
#ifdef QGC_QUPGRADE_ENABLED
    DialogBare *firmwareDialog = new DialogBare(this);
72
    ui->firmwareLayout->addWidget(firmwareDialog);
73 74 75

    connect(firmwareDialog, SIGNAL(connectLinks()), LinkManager::instance(), SLOT(connectAll()));
    connect(firmwareDialog, SIGNAL(disconnectLinks()), LinkManager::instance(), SLOT(disconnectAll()));
76 77 78 79 80 81 82
#else

    QLabel* label = new QLabel(this);
    label->setText("THIS VERSION OF QGROUNDCONTROL WAS BUILT WITHOUT QUPGRADE. To enable firmware upload support, checkout QUpgrade WITHIN the QGroundControl folder");
    ui->firmwareLayout->addWidget(label);
#endif

83 84 85 86
    connect(ui->rcMenuButton,SIGNAL(clicked()),
            this,SLOT(rcMenuButtonClicked()));
    connect(ui->sensorMenuButton,SIGNAL(clicked()),
            this,SLOT(sensorMenuButtonClicked()));
87 88 89 90 91 92
    connect(ui->flightModeMenuButton, SIGNAL(clicked()),
            this, SLOT(flightModeMenuButtonClicked()));
    connect(ui->safetyConfigButton, SIGNAL(clicked()),
            this, SLOT(safetyConfigMenuButtonClicked()));
    connect(ui->tuningMenuButton,SIGNAL(clicked()),
            this,SLOT(tuningMenuButtonClicked()));
93 94 95 96 97 98
    connect(ui->advancedMenuButton,SIGNAL(clicked()),
            this,SLOT(advancedMenuButtonClicked()));
    connect(ui->airframeMenuButton, SIGNAL(clicked()),
            this, SLOT(airframeMenuButtonClicked()));
    connect(ui->firmwareMenuButton, SIGNAL(clicked()),
            this, SLOT(firmwareMenuButtonClicked()));
99

100
    //TODO connect buttons here to save/clear actions?
101 102 103
    UASInterface* tmpMav = UASManager::instance()->getActiveUAS();
    if (tmpMav) {
        ui->pendingCommitsWidget->initWithUAS(tmpMav);
tstellanova's avatar
tstellanova committed
104
        ui->pendingCommitsWidget->update();
105
        setActiveUAS(tmpMav);
tstellanova's avatar
tstellanova committed
106
    }
107

108 109 110
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
            this, SLOT(setActiveUAS(UASInterface*)));

111
    firmwareMenuButtonClicked();
112
}
113

114 115 116 117 118
QGCPX4VehicleConfig::~QGCPX4VehicleConfig()
{
    delete ui;
}

119 120
void QGCPX4VehicleConfig::rcMenuButtonClicked()
{
121
    ui->stackedWidget->setCurrentWidget(ui->rcTab);
Lorenz Meier's avatar
Lorenz Meier committed
122
    ui->tabTitleLabel->setText(tr("Radio Calibration"));
123 124 125 126
}

void QGCPX4VehicleConfig::sensorMenuButtonClicked()
{
127
    ui->stackedWidget->setCurrentWidget(ui->sensorTab);
Lorenz Meier's avatar
Lorenz Meier committed
128
    ui->tabTitleLabel->setText(tr("Sensor Calibration"));
129 130
}

131 132
void QGCPX4VehicleConfig::tuningMenuButtonClicked()
{
Lorenz Meier's avatar
Lorenz Meier committed
133
    ui->stackedWidget->setCurrentWidget(ui->tuningTab);
134 135 136 137 138 139 140 141 142 143
    ui->tabTitleLabel->setText(tr("Controller Tuning"));
}

void QGCPX4VehicleConfig::flightModeMenuButtonClicked()
{
    ui->stackedWidget->setCurrentWidget(ui->flightModeTab);
    ui->tabTitleLabel->setText(tr("Flight Mode Configuration"));
}

void QGCPX4VehicleConfig::safetyConfigMenuButtonClicked()
144
{
145 146
    ui->stackedWidget->setCurrentWidget(ui->safetyConfigTab);
    ui->tabTitleLabel->setText(tr("Safety Feature Configuration"));
147 148 149 150
}

void QGCPX4VehicleConfig::advancedMenuButtonClicked()
{
151
    ui->stackedWidget->setCurrentWidget(ui->advancedTab);
Lorenz Meier's avatar
Lorenz Meier committed
152
    ui->tabTitleLabel->setText(tr("Advanced Configuration Options"));
153 154
}

155 156
void QGCPX4VehicleConfig::airframeMenuButtonClicked()
{
157
    ui->stackedWidget->setCurrentWidget(ui->airframeTab);
Lorenz Meier's avatar
Lorenz Meier committed
158
    ui->tabTitleLabel->setText(tr("Airframe Configuration"));
159 160
}

161 162
void QGCPX4VehicleConfig::firmwareMenuButtonClicked()
{
163
    ui->stackedWidget->setCurrentWidget(ui->firmwareTab);
Lorenz Meier's avatar
Lorenz Meier committed
164
    ui->tabTitleLabel->setText(tr("Firmware Upgrade"));
165 166
}

167
#if 0
168 169
void QGCPX4VehicleConfig::toggleSpektrumPairing(bool enabled)
{
170 171
    Q_UNUSED(enabled);
    
172 173
    if (!ui->dsm2RadioButton->isChecked() && !ui->dsmxRadioButton->isChecked()
            && !ui->dsmx8RadioButton->isChecked()) {
Lorenz Meier's avatar
Lorenz Meier committed
174 175 176 177 178 179 180
        // Reject
        QMessageBox warnMsgBox;
        warnMsgBox.setText(tr("Please select a Spektrum Protocol Version"));
        warnMsgBox.setInformativeText(tr("Please select either DSM2 or DSM-X\ndirectly below the pair button,\nbased on the receiver type."));
        warnMsgBox.setStandardButtons(QMessageBox::Ok);
        warnMsgBox.setDefaultButton(QMessageBox::Ok);
        (void)warnMsgBox.exec();
181
        return;
Lorenz Meier's avatar
Lorenz Meier committed
182 183
    }

184
    UASInterface* mav = UASManager::instance()->getActiveUAS();
185 186 187 188 189 190 191 192 193 194
    if (mav) {
        int rxSubType;
        if (ui->dsm2RadioButton->isChecked())
            rxSubType = 0;
        else if (ui->dsmxRadioButton->isChecked())
            rxSubType = 1;
        else // if (ui->dsmx8RadioButton->isChecked())
            rxSubType = 2;
        mav->pairRX(0, rxSubType);
    }
195
}
196
#endif
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

void QGCPX4VehicleConfig::menuButtonClicked()
{
    QPushButton *button = qobject_cast<QPushButton*>(sender());
    if (!button)
    {
        return;
    }
    if (buttonToWidgetMap.contains(button))
    {
        ui->stackedWidget->setCurrentWidget(buttonToWidgetMap[button]);
    }

}

void QGCPX4VehicleConfig::setActiveUAS(UASInterface* active)
{
    // Hide items if NULL and abort
    if (!active) {
        return;
    }


tstellanova's avatar
tstellanova committed
220 221 222
    // Do nothing if UAS is already visible
    if (mav == active)
        return;
223 224 225

    if (mav)
    {
226

227
        //TODO use paramCommsMgr instead
228 229 230
        disconnect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
                   SLOT(parameterChanged(int,int,QString,QVariant)));

231 232 233 234 235
        foreach(QWidget* child, ui->airframeLayout->findChildren<QWidget*>())
        {
            child->deleteLater();
        }

236
        // And then delete any custom tabs
237
        foreach(QWidget* child, additionalTabs) {
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
            child->deleteLater();
        }
        additionalTabs.clear();

        toolWidgets.clear();
        paramToWidgetMap.clear();
        libParamToWidgetMap.clear();
        systemTypeToParamMap.clear();
        toolToBoxMap.clear();
        paramTooltips.clear();
    }

    // Connect new system
    mav = active;

253 254
    paramMgr = mav->getParamManager();

tstellanova's avatar
tstellanova committed
255
    ui->pendingCommitsWidget->setUAS(mav);
256
    ui->paramTreeWidget->setUAS(mav);
tstellanova's avatar
tstellanova committed
257

258
    //TODO eliminate the separate RC_TYPE call
259 260 261
    mav->requestParameter(0, "RC_TYPE");

    // Connect new system
262
    connect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
263
               SLOT(parameterChanged(int,int,QString,QVariant)));
264

265

266
    if (systemTypeToParamMap.contains(mav->getSystemTypeName())) {
267 268
        paramToWidgetMap = systemTypeToParamMap[mav->getSystemTypeName()];
    }
269
    else {
270 271 272 273 274
        //Indication that we have no meta data for this system type.
        qDebug() << "No parameters defined for system type:" << mav->getSystemTypeName();
        paramToWidgetMap = systemTypeToParamMap[mav->getSystemTypeName()];
    }

275
    if (!paramTooltips.isEmpty()) {
276
           mav->getParamManager()->setParamDescriptions(paramTooltips);
277 278 279 280 281 282 283 284 285 286 287
    }

    qDebug() << "CALIBRATION!! System Type Name:" << mav->getSystemTypeName();

    //Load configuration after 1ms. This allows it to go into the event loop, and prevents application hangups due to the
    //amount of time it actually takes to load the configuration windows.
    QTimer::singleShot(1,this,SLOT(loadConfig()));

    updateStatus(QString("Reading from system %1").arg(mav->getUASName()));

    // Since a system is now connected, enable the VehicleConfig UI.
288 289 290 291 292
    // Enable buttons
    ui->advancedMenuButton->setEnabled(true);
    ui->airframeMenuButton->setEnabled(true);
    ui->sensorMenuButton->setEnabled(true);
    ui->rcMenuButton->setEnabled(true);
293 294
}

295 296
void QGCPX4VehicleConfig::parameterChanged(int uas, int component, QString parameterName, QVariant value)
{
297
    if (!doneLoadingConfig) {
298 299 300 301 302
        //We do not want to attempt to generate any UI elements until loading of the config file is complete.
        //We should re-request params later if needed, that is not implemented yet.
        return;
    }

303
    if (paramToWidgetMap.contains(parameterName)) {
304 305
        //Main group of parameters of the selected airframe
        paramToWidgetMap.value(parameterName)->setParameterValue(uas,component,parameterName,value);
306
        if (toolToBoxMap.contains(paramToWidgetMap.value(parameterName))) {
307 308
            toolToBoxMap[paramToWidgetMap.value(parameterName)]->show();
        }
309
        else {
310 311 312
            qCritical() << "Widget with no box, possible memory corruption for param:" << parameterName;
        }
    }
313
    else if (libParamToWidgetMap.contains(parameterName)) {
314 315
        //All the library parameters
        libParamToWidgetMap.value(parameterName)->setParameterValue(uas,component,parameterName,value);
316
        if (toolToBoxMap.contains(libParamToWidgetMap.value(parameterName))) {
317 318
            toolToBoxMap[libParamToWidgetMap.value(parameterName)]->show();
        }
319
        else {
320 321 322
            qCritical() << "Widget with no box, possible memory corruption for param:" << parameterName;
        }
    }
323
    else {
324 325
        //Param recieved that we have no metadata for. Search to see if it belongs in a
        //group with some other params
326
        //bool found = false;
327 328
        for (int i=0;i<toolWidgets.size();i++) {
            if (parameterName.startsWith(toolWidgets[i]->objectName())) {
329 330 331
                //It should be grouped with this one, add it.
                toolWidgets[i]->addParam(uas,component,parameterName,value);
                libParamToWidgetMap.insert(parameterName,toolWidgets[i]);
332
                //found  = true;
333 334 335
                break;
            }
        }
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
//        if (!found) {
//            //New param type, create a QGroupBox for it.
//            QWidget* parent = ui->advanceColumnContents;

//            // Create the tool, attaching it to the QGroupBox
//            QGCToolWidget *tool = new QGCToolWidget("", parent);
//            QString tooltitle = parameterName;
//            if (parameterName.split("_").size() > 1) {
//                tooltitle = parameterName.split("_")[0] + "_";
//            }
//            tool->setTitle(tooltitle);
//            tool->setObjectName(tooltitle);
//            //tool->setSettings(set);
//            libParamToWidgetMap.insert(parameterName,tool);
//            toolWidgets.append(tool);
//            tool->addParam(uas, component, parameterName, value);
//            QGroupBox *box = new QGroupBox(parent);
//            box->setTitle(tool->objectName());
//            box->setLayout(new QVBoxLayout(box));
//            box->layout()->addWidget(tool);

//            libParamToWidgetMap.insert(parameterName,tool);
//            toolWidgets.append(tool);
//            ui->advancedColumnLayout->addWidget(box);

//            toolToBoxMap[tool] = box;
//        }
363 364 365 366 367 368
    }

}

void QGCPX4VehicleConfig::updateStatus(const QString& str)
{
369 370
    ui->advancedStatusLabel->setText(str);
    ui->advancedStatusLabel->setStyleSheet("");
371 372 373 374
}

void QGCPX4VehicleConfig::updateError(const QString& str)
{
375 376
    ui->advancedStatusLabel->setText(str);
    ui->advancedStatusLabel->setStyleSheet(QString("QLabel { margin: 0px 2px; font: 14px; color: %1; background-color: %2; }").arg(QGC::colorDarkWhite.name()).arg(QGC::colorMagenta.name()));
377
}