QGCPX4VehicleConfig.cc 11.8 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
#include "PX4FirmwareUpgrade.h"
tstellanova's avatar
tstellanova committed
29

30 31 32 33 34 35
#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
36 37 38 39

#define MIN_PWM_VAL 800
#define MAX_PWM_VAL 2200

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

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

54 55 56 57 58
    ui->advancedMenuButton->setEnabled(false);
    ui->airframeMenuButton->setEnabled(false);
    ui->sensorMenuButton->setEnabled(false);
    ui->rcMenuButton->setEnabled(false);

59 60 61
    px4AirframeConfig = new QGCPX4AirframeConfig(this);
    ui->airframeLayout->addWidget(px4AirframeConfig);

62 63 64
    px4SensorCalibration = new QGCPX4SensorCalibration(this);
    ui->sensorLayout->addWidget(px4SensorCalibration);

65 66 67
    px4RCCalibration = new PX4RCCalibration(this);
    ui->rcLayout->addWidget(px4RCCalibration);
    
68 69
    PX4FirmwareUpgrade* firmwareUpgrade = new PX4FirmwareUpgrade(this);
    ui->firmwareLayout->addWidget(firmwareUpgrade);
70

71 72 73 74
    connect(ui->rcMenuButton,SIGNAL(clicked()),
            this,SLOT(rcMenuButtonClicked()));
    connect(ui->sensorMenuButton,SIGNAL(clicked()),
            this,SLOT(sensorMenuButtonClicked()));
75 76 77 78 79 80
    connect(ui->flightModeMenuButton, SIGNAL(clicked()),
            this, SLOT(flightModeMenuButtonClicked()));
    connect(ui->safetyConfigButton, SIGNAL(clicked()),
            this, SLOT(safetyConfigMenuButtonClicked()));
    connect(ui->tuningMenuButton,SIGNAL(clicked()),
            this,SLOT(tuningMenuButtonClicked()));
81 82 83 84 85 86
    connect(ui->advancedMenuButton,SIGNAL(clicked()),
            this,SLOT(advancedMenuButtonClicked()));
    connect(ui->airframeMenuButton, SIGNAL(clicked()),
            this, SLOT(airframeMenuButtonClicked()));
    connect(ui->firmwareMenuButton, SIGNAL(clicked()),
            this, SLOT(firmwareMenuButtonClicked()));
87

88
    //TODO connect buttons here to save/clear actions?
89 90 91
    UASInterface* tmpMav = UASManager::instance()->getActiveUAS();
    if (tmpMav) {
        ui->pendingCommitsWidget->initWithUAS(tmpMav);
tstellanova's avatar
tstellanova committed
92
        ui->pendingCommitsWidget->update();
93
        setActiveUAS(tmpMav);
tstellanova's avatar
tstellanova committed
94
    }
95

96 97 98
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
            this, SLOT(setActiveUAS(UASInterface*)));

99
    firmwareMenuButtonClicked();
100
}
101

102 103 104 105 106
QGCPX4VehicleConfig::~QGCPX4VehicleConfig()
{
    delete ui;
}

107 108
void QGCPX4VehicleConfig::rcMenuButtonClicked()
{
109
    ui->stackedWidget->setCurrentWidget(ui->rcTab);
Lorenz Meier's avatar
Lorenz Meier committed
110
    ui->tabTitleLabel->setText(tr("Radio Calibration"));
111 112 113 114
}

void QGCPX4VehicleConfig::sensorMenuButtonClicked()
{
115
    ui->stackedWidget->setCurrentWidget(ui->sensorTab);
Lorenz Meier's avatar
Lorenz Meier committed
116
    ui->tabTitleLabel->setText(tr("Sensor Calibration"));
117 118
}

119 120
void QGCPX4VehicleConfig::tuningMenuButtonClicked()
{
Lorenz Meier's avatar
Lorenz Meier committed
121
    ui->stackedWidget->setCurrentWidget(ui->tuningTab);
122 123 124 125 126 127 128 129 130 131
    ui->tabTitleLabel->setText(tr("Controller Tuning"));
}

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

void QGCPX4VehicleConfig::safetyConfigMenuButtonClicked()
132
{
133 134
    ui->stackedWidget->setCurrentWidget(ui->safetyConfigTab);
    ui->tabTitleLabel->setText(tr("Safety Feature Configuration"));
135 136 137 138
}

void QGCPX4VehicleConfig::advancedMenuButtonClicked()
{
139
    ui->stackedWidget->setCurrentWidget(ui->advancedTab);
Lorenz Meier's avatar
Lorenz Meier committed
140
    ui->tabTitleLabel->setText(tr("Advanced Configuration Options"));
141 142
}

143 144
void QGCPX4VehicleConfig::airframeMenuButtonClicked()
{
145
    ui->stackedWidget->setCurrentWidget(ui->airframeTab);
Lorenz Meier's avatar
Lorenz Meier committed
146
    ui->tabTitleLabel->setText(tr("Airframe Configuration"));
147 148
}

149 150
void QGCPX4VehicleConfig::firmwareMenuButtonClicked()
{
151
    ui->stackedWidget->setCurrentWidget(ui->firmwareTab);
Lorenz Meier's avatar
Lorenz Meier committed
152
    ui->tabTitleLabel->setText(tr("Firmware Upgrade"));
153 154
}

155
#if 0
156 157
void QGCPX4VehicleConfig::toggleSpektrumPairing(bool enabled)
{
158 159
    Q_UNUSED(enabled);
    
160 161
    if (!ui->dsm2RadioButton->isChecked() && !ui->dsmxRadioButton->isChecked()
            && !ui->dsmx8RadioButton->isChecked()) {
Lorenz Meier's avatar
Lorenz Meier committed
162 163 164 165 166 167 168
        // 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();
169
        return;
Lorenz Meier's avatar
Lorenz Meier committed
170 171
    }

172
    UASInterface* mav = UASManager::instance()->getActiveUAS();
173 174 175 176 177 178 179 180 181 182
    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);
    }
183
}
184
#endif
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207

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
208 209 210
    // Do nothing if UAS is already visible
    if (mav == active)
        return;
211 212 213

    if (mav)
    {
214

215
        //TODO use paramCommsMgr instead
216 217 218
        disconnect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
                   SLOT(parameterChanged(int,int,QString,QVariant)));

219 220 221 222 223
        foreach(QWidget* child, ui->airframeLayout->findChildren<QWidget*>())
        {
            child->deleteLater();
        }

224
        // And then delete any custom tabs
225
        foreach(QWidget* child, additionalTabs) {
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
            child->deleteLater();
        }
        additionalTabs.clear();

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

    // Connect new system
    mav = active;

241 242
    paramMgr = mav->getParamManager();

tstellanova's avatar
tstellanova committed
243
    ui->pendingCommitsWidget->setUAS(mav);
244
    ui->paramTreeWidget->setUAS(mav);
tstellanova's avatar
tstellanova committed
245

246
    //TODO eliminate the separate RC_TYPE call
247 248 249
    mav->requestParameter(0, "RC_TYPE");

    // Connect new system
250
    connect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
251
               SLOT(parameterChanged(int,int,QString,QVariant)));
252

253

254
    if (systemTypeToParamMap.contains(mav->getSystemTypeName())) {
255 256
        paramToWidgetMap = systemTypeToParamMap[mav->getSystemTypeName()];
    }
257
    else {
258 259 260 261 262
        //Indication that we have no meta data for this system type.
        qDebug() << "No parameters defined for system type:" << mav->getSystemTypeName();
        paramToWidgetMap = systemTypeToParamMap[mav->getSystemTypeName()];
    }

263
    if (!paramTooltips.isEmpty()) {
264
           mav->getParamManager()->setParamDescriptions(paramTooltips);
265 266 267 268 269 270 271
    }

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

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

    // Since a system is now connected, enable the VehicleConfig UI.
272 273 274 275 276
    // Enable buttons
    ui->advancedMenuButton->setEnabled(true);
    ui->airframeMenuButton->setEnabled(true);
    ui->sensorMenuButton->setEnabled(true);
    ui->rcMenuButton->setEnabled(true);
277 278
}

279 280
void QGCPX4VehicleConfig::parameterChanged(int uas, int component, QString parameterName, QVariant value)
{
281
    if (!doneLoadingConfig) {
282 283 284 285 286
        //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;
    }

287
    if (paramToWidgetMap.contains(parameterName)) {
288 289
        //Main group of parameters of the selected airframe
        paramToWidgetMap.value(parameterName)->setParameterValue(uas,component,parameterName,value);
290
        if (toolToBoxMap.contains(paramToWidgetMap.value(parameterName))) {
291 292
            toolToBoxMap[paramToWidgetMap.value(parameterName)]->show();
        }
293
        else {
294 295 296
            qCritical() << "Widget with no box, possible memory corruption for param:" << parameterName;
        }
    }
297
    else if (libParamToWidgetMap.contains(parameterName)) {
298 299
        //All the library parameters
        libParamToWidgetMap.value(parameterName)->setParameterValue(uas,component,parameterName,value);
300
        if (toolToBoxMap.contains(libParamToWidgetMap.value(parameterName))) {
301 302
            toolToBoxMap[libParamToWidgetMap.value(parameterName)]->show();
        }
303
        else {
304 305 306
            qCritical() << "Widget with no box, possible memory corruption for param:" << parameterName;
        }
    }
307
    else {
308 309
        //Param recieved that we have no metadata for. Search to see if it belongs in a
        //group with some other params
310
        //bool found = false;
311 312
        for (int i=0;i<toolWidgets.size();i++) {
            if (parameterName.startsWith(toolWidgets[i]->objectName())) {
313 314 315
                //It should be grouped with this one, add it.
                toolWidgets[i]->addParam(uas,component,parameterName,value);
                libParamToWidgetMap.insert(parameterName,toolWidgets[i]);
316
                //found  = true;
317 318 319
                break;
            }
        }
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
//        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;
//        }
347 348 349 350 351 352
    }

}

void QGCPX4VehicleConfig::updateStatus(const QString& str)
{
353 354
    ui->advancedStatusLabel->setText(str);
    ui->advancedStatusLabel->setStyleSheet("");
355 356 357 358
}

void QGCPX4VehicleConfig::updateError(const QString& str)
{
359 360
    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()));
361
}