QGCVehicleConfig.cc 24.7 KB
Newer Older
Bryant's avatar
Bryant committed
1 2 3 4 5 6
// 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
7
#include <limits.h>
Bryant's avatar
Bryant committed
8
#endif
9 10

#include <QTimer>
11
#include <QDir>
12

13
#include "QGCVehicleConfig.h"
14
#include "UASManager.h"
15
#include "QGC.h"
16
#include "QGCToolWidget.h"
17 18 19 20
#include "ui_QGCVehicleConfig.h"

QGCVehicleConfig::QGCVehicleConfig(QWidget *parent) :
    QWidget(parent),
21
    mav(NULL),
22
    chanCount(0),
23 24 25 26 27 28 29 30
    rcRoll(0.0f),
    rcPitch(0.0f),
    rcYaw(0.0f),
    rcThrottle(0.0f),
    rcMode(0.0f),
    rcAux1(0.0f),
    rcAux2(0.0f),
    rcAux3(0.0f),
31 32
    changed(true),
    rc_mode(RC_MODE_2),
33
    calibrationEnabled(false),
34 35
    ui(new Ui::QGCVehicleConfig)
{
36
    setObjectName("QGC_VEHICLECONFIG");
37
    ui->setupUi(this);
38 39 40 41

    requestCalibrationRC();
    if (mav) mav->requestParameter(0, "RC_TYPE");

42 43
    ui->rcModeComboBox->setCurrentIndex((int)rc_mode - 1);

44
    ui->rcCalibrationButton->setCheckable(true);
45 46
    connect(ui->rcCalibrationButton, SIGNAL(clicked(bool)), this, SLOT(toggleCalibrationRC(bool)));
    connect(ui->storeButton, SIGNAL(clicked()), this, SLOT(writeParameters()));
47
    connect(ui->rcModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setRCModeIndex(int)));
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    connect(ui->setTrimButton, SIGNAL(clicked()), this, SLOT(setTrimPositions()));

    /* Connect RC mapping assignments */
    connect(ui->rollSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setRollChan(int)));
    connect(ui->pitchSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setPitchChan(int)));
    connect(ui->yawSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setYawChan(int)));
    connect(ui->throttleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setThrottleChan(int)));
    connect(ui->modeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setModeChan(int)));
    connect(ui->aux1SpinBox, SIGNAL(valueChanged(int)), this, SLOT(setAux1Chan(int)));
    connect(ui->aux2SpinBox, SIGNAL(valueChanged(int)), this, SLOT(setAux2Chan(int)));
    connect(ui->aux3SpinBox, SIGNAL(valueChanged(int)), this, SLOT(setAux3Chan(int)));

    // Connect RC reverse assignments
    connect(ui->invertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setRollInverted(bool)));
    connect(ui->invertCheckBox_2, SIGNAL(clicked(bool)), this, SLOT(setPitchInverted(bool)));
    connect(ui->invertCheckBox_3, SIGNAL(clicked(bool)), this, SLOT(setYawInverted(bool)));
    connect(ui->invertCheckBox_4, SIGNAL(clicked(bool)), this, SLOT(setThrottleInverted(bool)));
    connect(ui->invertCheckBox_5, SIGNAL(clicked(bool)), this, SLOT(setModeInverted(bool)));
    connect(ui->invertCheckBox_6, SIGNAL(clicked(bool)), this, SLOT(setAux1Inverted(bool)));
    connect(ui->invertCheckBox_7, SIGNAL(clicked(bool)), this, SLOT(setAux2Inverted(bool)));
    connect(ui->invertCheckBox_8, SIGNAL(clicked(bool)), this, SLOT(setAux3Inverted(bool)));
69 70 71 72 73

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

    setActiveUAS(UASManager::instance()->getActiveUAS());

74
    for (unsigned int i = 0; i < chanMax; i++)
75
    {
76
        rcValue[i] = UINT16_MAX;
77
        rcMapping[i] = i;
78 79 80 81 82
    }

    updateTimer.setInterval(150);
    connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateView()));
    updateTimer.start();
83 84 85 86 87 88
}

QGCVehicleConfig::~QGCVehicleConfig()
{
    delete ui;
}
89

90 91 92 93 94 95 96 97
void QGCVehicleConfig::setRCModeIndex(int newRcMode)
{
    if (newRcMode > 0 && newRcMode < 5)
    {
        rc_mode = (enum RC_MODE) (newRcMode+1);
        changed = true;
    }
}
98 99 100 101 102 103 104 105 106 107 108 109 110

void QGCVehicleConfig::toggleCalibrationRC(bool enabled)
{
    if (enabled)
    {
        startCalibrationRC();
    }
    else
    {
        stopCalibrationRC();
    }
}

111 112 113
void QGCVehicleConfig::setTrimPositions()
{
    // Set trim for roll, pitch, yaw, throttle
114 115 116
    rcTrim[rcMapping[0]] = rcValue[rcMapping[0]]; // roll
    rcTrim[rcMapping[1]] = rcValue[rcMapping[1]]; // pitch
    rcTrim[rcMapping[2]] = rcValue[rcMapping[2]]; // yaw
Lorenz Meier's avatar
Lorenz Meier committed
117 118 119 120 121 122 123 124 125 126
    // Set trim to min if stick is close to min
    if (abs(rcValue[rcMapping[3]] - rcMin[rcMapping[3]]) < 100)
    {
        rcTrim[rcMapping[3]] = rcMin[rcMapping[3]];   // throttle
    }
    // Set trim to max if stick is close to max
    if (abs(rcValue[rcMapping[3]] - rcMax[rcMapping[3]]) < 100)
    {
        rcTrim[rcMapping[3]] = rcMax[rcMapping[3]];   // throttle
    }
127 128 129 130
    rcTrim[rcMapping[4]] = ((rcMax[rcMapping[4]] - rcMin[rcMapping[4]]) / 2.0f) + rcMin[rcMapping[4]];   // mode sw
    rcTrim[rcMapping[5]] = ((rcMax[rcMapping[5]] - rcMin[rcMapping[5]]) / 2.0f) + rcMin[rcMapping[5]];   // aux 1
    rcTrim[rcMapping[6]] = ((rcMax[rcMapping[6]] - rcMin[rcMapping[6]]) / 2.0f) + rcMin[rcMapping[6]];   // aux 2
    rcTrim[rcMapping[7]] = ((rcMax[rcMapping[7]] - rcMin[rcMapping[7]]) / 2.0f) + rcMin[rcMapping[7]];   // aux 3
131 132 133 134 135 136 137
}

void QGCVehicleConfig::detectChannelInversion()
{

}

138 139 140
void QGCVehicleConfig::startCalibrationRC()
{
    ui->rcTypeComboBox->setEnabled(false);
141
    ui->rcCalibrationButton->setText(tr("Stop RC Calibration"));
142
    resetCalibrationRC();
143
    calibrationEnabled = true;
144 145 146 147
}

void QGCVehicleConfig::stopCalibrationRC()
{
148
    calibrationEnabled = false;
149
    ui->rcTypeComboBox->setEnabled(true);
150
    ui->rcCalibrationButton->setText(tr("Start RC Calibration"));
151 152 153 154 155 156 157 158 159 160 161 162 163 164
}

void QGCVehicleConfig::setActiveUAS(UASInterface* active)
{
    // Do nothing if system is the same or NULL
    if ((active == NULL) || mav == active) return;

    if (mav)
    {
        // Disconnect old system
        disconnect(mav, SIGNAL(remoteControlChannelRawChanged(int,float)), this,
                   SLOT(remoteControlChannelRawChanged(int,float)));
        disconnect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
                   SLOT(parameterChanged(int,int,QString,QVariant)));
165 166 167 168 169

        foreach (QGCToolWidget* tool, toolWidgets)
        {
            delete tool;
        }
170
        toolWidgets.clear();
171 172
    }

173 174 175
    // Reset current state
    resetCalibrationRC();

176 177
    chanCount = 0;

178 179
    // Connect new system
    mav = active;
180 181 182 183
    connect(active, SIGNAL(remoteControlChannelRawChanged(int,float)), this,
               SLOT(remoteControlChannelRawChanged(int,float)));
    connect(active, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
               SLOT(parameterChanged(int,int,QString,QVariant)));
184 185 186 187

    mav->requestParameters();

    QString defaultsDir = qApp->applicationDirPath() + "/files/" + mav->getAutopilotTypeName().toLower() + "/widgets/";
188
    qDebug() << "CALIBRATION!! System Type Name:" << mav->getSystemTypeName();
189 190 191

    QGCToolWidget* tool;

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
    QDir autopilotdir(qApp->applicationDirPath() + "/files/" + mav->getAutopilotTypeName().toLower());
    QDir generaldir = QDir(autopilotdir.absolutePath() + "/general/widgets");
    QDir vehicledir = QDir(autopilotdir.absolutePath() + "/" + mav->getSystemTypeName().toLower() + "/widgets");
    if (!autopilotdir.exists("general"))
    {
     //TODO: Throw some kind of error here. There is no general configuration directory
        qDebug() << "invalid general dir";
    }
    if (!autopilotdir.exists(mav->getAutopilotTypeName().toLower()))
    {
        //TODO: Throw an error here too, no autopilot specific configuration
        qDebug() << "invalid vehicle dir";
    }
    qDebug() << autopilotdir.absolutePath();
    qDebug() << generaldir.absolutePath();
    qDebug() << vehicledir.absolutePath();
208
    int left = true;
209 210 211 212 213 214 215 216 217 218 219 220
    foreach (QString file,generaldir.entryList(QDir::Files | QDir::NoDotAndDotDot))
    {
        if (file.toLower().endsWith(".qgw")) {
            tool = new QGCToolWidget("", this);
            if (tool->loadSettings(generaldir.absoluteFilePath(file), false))
            {
                toolWidgets.append(tool);
                //ui->sensorLayout->addWidget(tool);
                QGroupBox *box = new QGroupBox(this);
                box->setTitle(tool->objectName());
                box->setLayout(new QVBoxLayout());
                box->layout()->addWidget(tool);
221 222 223 224 225 226 227 228 229 230
                if (left)
                {
                    left = false;
                    ui->leftGeneralLayout->addWidget(box);
                }
                else
                {
                    left = true;
                    ui->rightGeneralLayout->addWidget(box);
                }
231 232 233 234 235
            } else {
                delete tool;
            }
        }
    }
236
    left = true;
237 238 239 240 241 242 243 244 245 246 247 248
    foreach (QString file,vehicledir.entryList(QDir::Files | QDir::NoDotAndDotDot))
    {
        if (file.toLower().endsWith(".qgw")) {
            tool = new QGCToolWidget("", this);
            if (tool->loadSettings(vehicledir.absoluteFilePath(file), false))
            {
                toolWidgets.append(tool);
                //ui->sensorLayout->addWidget(tool);
                QGroupBox *box = new QGroupBox(this);
                box->setTitle(tool->objectName());
                box->setLayout(new QVBoxLayout());
                box->layout()->addWidget(tool);
249 250 251 252 253 254 255 256 257 258 259
                if (left)
                {
                    left = false;
                    ui->leftHWSpecificLayout->addWidget(box);
                }
                else
                {
                    left = true;
                    ui->rightHWSpecificLayout->addWidget(box);
                }

260 261 262 263 264 265 266 267
            } else {
                delete tool;
            }
        }
    }



268 269
    // Load calibration
    tool = new QGCToolWidget("", this);
270
    if (tool->loadSettings(autopilotdir.absolutePath() + "/" + mav->getSystemTypeName().toLower() + "/calibration.qgw", false))
271 272 273
    {
        toolWidgets.append(tool);
        ui->sensorLayout->addWidget(tool);
274 275
    } else {
        delete tool;
276
    }
277

278
    // Load multirotor attitude pid
279
    /*
280 281 282 283
    tool = new QGCToolWidget("", this);
    if (tool->loadSettings(defaultsDir + "px4_mc_attitude_pid_params.qgw", false))
    {
        toolWidgets.append(tool);
284 285 286 287 288 289
	QGroupBox *box = new QGroupBox(this);
	box->setTitle(tool->objectName());
	box->setLayout(new QVBoxLayout());
	box->layout()->addWidget(tool);
	ui->multiRotorAttitudeLayout->addWidget(box);
	//ui->multiRotorAttitudeLayout->addWidget(tool);
290 291
    } else {
        delete tool;
292 293 294 295 296 297 298
    }

    // Load multirotor position pid
    tool = new QGCToolWidget("", this);
    if (tool->loadSettings(defaultsDir + "px4_mc_position_pid_params.qgw", false))
    {
        toolWidgets.append(tool);
299 300 301 302 303 304
	QGroupBox *box = new QGroupBox(this);
	box->setTitle(tool->objectName());
	box->setLayout(new QVBoxLayout());
	box->layout()->addWidget(tool);
	ui->multiRotorAttitudeLayout->addWidget(box);
	//ui->multiRotorPositionLayout->addWidget(tool);
305 306
    } else {
        delete tool;
307 308 309 310 311 312 313
    }

    // Load fixed wing attitude pid
    tool = new QGCToolWidget("", this);
    if (tool->loadSettings(defaultsDir + "px4_fw_attitude_pid_params.qgw", false))
    {
        toolWidgets.append(tool);
314 315 316 317 318 319
	QGroupBox *box = new QGroupBox(this);
	box->setTitle(tool->objectName());
	box->setLayout(new QVBoxLayout());
	box->layout()->addWidget(tool);
	ui->multiRotorAttitudeLayout->addWidget(box);
	//ui->fixedWingAttitudeLayout->addWidget(tool);
320 321
    } else {
        delete tool;
322 323 324 325 326 327 328
    }

    // Load fixed wing position pid
    tool = new QGCToolWidget("", this);
    if (tool->loadSettings(defaultsDir + "px4_fw_position_pid_params.qgw", false))
    {
        toolWidgets.append(tool);
329 330 331 332 333 334
	QGroupBox *box = new QGroupBox(this);
	box->setTitle(tool->objectName());
	box->setLayout(new QVBoxLayout());
	box->layout()->addWidget(tool);
	ui->multiRotorAttitudeLayout->addWidget(box);
	//ui->fixedWingPositionLayout->addWidget(tool);
335 336
    } else {
        delete tool;
337
    }*/
338 339

    updateStatus(QString("Reading from system %1").arg(mav->getUASName()));
340 341 342 343 344 345
}

void QGCVehicleConfig::resetCalibrationRC()
{
    for (unsigned int i = 0; i < chanMax; ++i)
    {
346 347
        rcMin[i] = 1200;
        rcMax[i] = 1800;
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
    }
}

/**
 * Sends the RC calibration to the vehicle and stores it in EEPROM
 */
void QGCVehicleConfig::writeCalibrationRC()
{
    if (!mav) return;

    QString minTpl("RC%1_MIN");
    QString maxTpl("RC%1_MAX");
    QString trimTpl("RC%1_TRIM");
    QString revTpl("RC%1_REV");

    // Do not write the RC type, as these values depend on this
    // active onboard parameter

366
    for (unsigned int i = 0; i < chanCount; ++i)
367
    {
368
        //qDebug() << "SENDING" << minTpl.arg(i+1) << rcMin[i];
Lorenz Meier's avatar
Lorenz Meier committed
369
        mav->setParameter(0, minTpl.arg(i+1), rcMin[i]);
370
        QGC::SLEEP::usleep(50000);
Lorenz Meier's avatar
Lorenz Meier committed
371
        mav->setParameter(0, trimTpl.arg(i+1), rcTrim[i]);
372
        QGC::SLEEP::usleep(50000);
Lorenz Meier's avatar
Lorenz Meier committed
373
        mav->setParameter(0, maxTpl.arg(i+1), rcMax[i]);
374 375 376
        QGC::SLEEP::usleep(50000);
        mav->setParameter(0, revTpl.arg(i+1), (rcRev[i]) ? -1.0f : 1.0f);
        QGC::SLEEP::usleep(50000);
377 378 379
    }

    // Write mappings
380 381 382 383
    mav->setParameter(0, "RC_MAP_ROLL", (int32_t)(rcMapping[0]+1));
    QGC::SLEEP::usleep(50000);
    mav->setParameter(0, "RC_MAP_PITCH", (int32_t)(rcMapping[1]+1));
    QGC::SLEEP::usleep(50000);
384
    mav->setParameter(0, "RC_MAP_YAW", (int32_t)(rcMapping[2]+1));
385
    QGC::SLEEP::usleep(50000);
386
    mav->setParameter(0, "RC_MAP_THROTTLE", (int32_t)(rcMapping[3]+1));
387 388 389 390 391 392 393 394 395
    QGC::SLEEP::usleep(50000);
    mav->setParameter(0, "RC_MAP_MODE_SW", (int32_t)(rcMapping[4]+1));
    QGC::SLEEP::usleep(50000);
    mav->setParameter(0, "RC_MAP_AUX1", (int32_t)(rcMapping[5]+1));
    QGC::SLEEP::usleep(50000);
    mav->setParameter(0, "RC_MAP_AUX2", (int32_t)(rcMapping[6]+1));
    QGC::SLEEP::usleep(50000);
    mav->setParameter(0, "RC_MAP_AUX3", (int32_t)(rcMapping[7]+1));
    QGC::SLEEP::usleep(50000);
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
}

void QGCVehicleConfig::requestCalibrationRC()
{
    if (!mav) return;

    QString minTpl("RC%1_MIN");
    QString maxTpl("RC%1_MAX");
    QString trimTpl("RC%1_TRIM");
    QString revTpl("RC%1_REV");

    // Do not request the RC type, as these values depend on this
    // active onboard parameter

    for (unsigned int i = 0; i < chanMax; ++i)
    {
Lorenz Meier's avatar
Lorenz Meier committed
412
        mav->requestParameter(0, minTpl.arg(i+1));
Lorenz Meier's avatar
Lorenz Meier committed
413
        QGC::SLEEP::usleep(5000);
Lorenz Meier's avatar
Lorenz Meier committed
414
        mav->requestParameter(0, trimTpl.arg(i+1));
Lorenz Meier's avatar
Lorenz Meier committed
415
        QGC::SLEEP::usleep(5000);
Lorenz Meier's avatar
Lorenz Meier committed
416
        mav->requestParameter(0, maxTpl.arg(i+1));
Lorenz Meier's avatar
Lorenz Meier committed
417
        QGC::SLEEP::usleep(5000);
Lorenz Meier's avatar
Lorenz Meier committed
418
        mav->requestParameter(0, revTpl.arg(i+1));
Lorenz Meier's avatar
Lorenz Meier committed
419
        QGC::SLEEP::usleep(5000);
420 421 422 423 424 425 426
    }
}

void QGCVehicleConfig::writeParameters()
{
    updateStatus(tr("Writing all onboard parameters."));
    writeCalibrationRC();
427
    mav->writeParametersToStorage();
428 429 430 431
}

void QGCVehicleConfig::remoteControlChannelRawChanged(int chan, float val)
{
432 433
    // Check if index and values are sane
    if (chan < 0 || static_cast<unsigned int>(chan) >= chanMax || val < 500 || val > 2500)
434 435
        return;

Bryant's avatar
Bryant committed
436
    if (chan + 1 > (int)chanCount) {
437 438 439 440 441 442 443 444 445 446 447 448 449 450
        chanCount = chan+1;
    }

    // Update calibration data
    if (calibrationEnabled) {
        if (val < rcMin[chan])
        {
            rcMin[chan] = val;
        }

        if (val > rcMax[chan])
        {
            rcMax[chan] = val;
        }
451 452
    }

453 454 455
    // Raw value
    rcValue[chan] = val;

456 457 458 459
    // Normalized value
    float normalized;

    if (val >= rcTrim[chan])
460
    {
461
        normalized = (val - rcTrim[chan])/(rcMax[chan] - rcTrim[chan]);
462
    }
463 464 465 466 467 468 469 470 471
    else
    {
        normalized = -(rcTrim[chan] - val)/(rcTrim[chan] - rcMin[chan]);
    }

    // Bound
    normalized = qBound(-1.0f, normalized, 1.0f);
    // Invert
    normalized = (rcRev[chan]) ? -1.0f*normalized : normalized;
472

473 474 475
    if (chan == rcMapping[0])
    {
        // ROLL
476
        rcRoll = normalized;
477
    }
478
    if (chan == rcMapping[1])
479 480
    {
        // PITCH
481
        rcPitch = normalized;
482
    }
483
    if (chan == rcMapping[2])
484
    {
485
        rcYaw = normalized;
486
    }
487
    if (chan == rcMapping[3])
488 489
    {
        // THROTTLE
490 491 492 493
        if (rcRev[chan]) {
            rcThrottle = 1.0f + normalized;
        } else {
            rcThrottle = normalized;
494
        }
495 496

        rcThrottle = qBound(0.0f, rcThrottle, 1.0f);
497
    }
498
    if (chan == rcMapping[4])
499 500
    {
        // MODE SWITCH
501
        rcMode = normalized;
502
    }
503
    if (chan == rcMapping[5])
504 505
    {
        // AUX1
506
        rcAux1 = normalized;
507
    }
508
    if (chan == rcMapping[6])
509 510
    {
        // AUX2
511
        rcAux2 = normalized;
512
    }
513
    if (chan == rcMapping[7])
514 515
    {
        // AUX3
516
        rcAux3 = normalized;
517 518 519 520
    }

    changed = true;

521
    //qDebug() << "RC CHAN:" << chan << "PPM:" << val << "NORMALIZED:" << normalized;
522 523
}

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
void QGCVehicleConfig::updateInvertedCheckboxes(int index)
{
    unsigned int mapindex = rcMapping[index];

    switch (mapindex)
    {
    case 0:
        ui->invertCheckBox->setChecked(rcRev[index]);
        break;
    case 1:
        ui->invertCheckBox_2->setChecked(rcRev[index]);
        break;
    case 2:
        ui->invertCheckBox_3->setChecked(rcRev[index]);
        break;
    case 3:
        ui->invertCheckBox_4->setChecked(rcRev[index]);
        break;
    case 4:
        ui->invertCheckBox_5->setChecked(rcRev[index]);
        break;
    case 5:
        ui->invertCheckBox_6->setChecked(rcRev[index]);
        break;
    case 6:
        ui->invertCheckBox_7->setChecked(rcRev[index]);
        break;
    case 7:
        ui->invertCheckBox_8->setChecked(rcRev[index]);
        break;
    }
}

557 558 559 560
void QGCVehicleConfig::parameterChanged(int uas, int component, QString parameterName, QVariant value)
{
    Q_UNUSED(uas);
    Q_UNUSED(component);
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576

    // Channel calibration values
    QRegExp minTpl("RC?_MIN");
    minTpl.setPatternSyntax(QRegExp::Wildcard);
    QRegExp maxTpl("RC?_MAX");
    maxTpl.setPatternSyntax(QRegExp::Wildcard);
    QRegExp trimTpl("RC?_TRIM");
    trimTpl.setPatternSyntax(QRegExp::Wildcard);
    QRegExp revTpl("RC?_REV");
    revTpl.setPatternSyntax(QRegExp::Wildcard);

    // Do not write the RC type, as these values depend on this
    // active onboard parameter

    if (minTpl.exactMatch(parameterName)) {
        bool ok;
Lorenz Meier's avatar
Lorenz Meier committed
577
        int index = parameterName.mid(2, 1).toInt(&ok) - 1;
578
        //qDebug() << "PARAM:" << parameterName << "index:" << index;
579
        if (ok && (index >= 0) && (index < chanMax))
580 581 582 583 584 585 586
        {
            rcMin[index] = value.toInt();
        }
    }

    if (maxTpl.exactMatch(parameterName)) {
        bool ok;
Lorenz Meier's avatar
Lorenz Meier committed
587
        int index = parameterName.mid(2, 1).toInt(&ok) - 1;
588
        if (ok && (index >= 0) && (index < chanMax))
589 590 591 592 593 594 595
        {
            rcMax[index] = value.toInt();
        }
    }

    if (trimTpl.exactMatch(parameterName)) {
        bool ok;
Lorenz Meier's avatar
Lorenz Meier committed
596
        int index = parameterName.mid(2, 1).toInt(&ok) - 1;
597
        if (ok && (index >= 0) && (index < chanMax))
598 599 600 601 602 603 604
        {
            rcTrim[index] = value.toInt();
        }
    }

    if (revTpl.exactMatch(parameterName)) {
        bool ok;
Lorenz Meier's avatar
Lorenz Meier committed
605
        int index = parameterName.mid(2, 1).toInt(&ok) - 1;
606
        if (ok && (index >= 0) && (index < chanMax))
607 608
        {
            rcRev[index] = (value.toInt() == -1) ? true : false;
609
            updateInvertedCheckboxes(index);
610 611 612 613 614 615 616 617
        }
    }

//        mav->setParameter(0, trimTpl.arg(i), rcTrim[i]);
//        mav->setParameter(0, maxTpl.arg(i), rcMax[i]);
//        mav->setParameter(0, revTpl.arg(i), (rcRev[i]) ? -1 : 1);
//    }

618 619 620 621 622 623 624 625
    if (rcTypeUpdateRequested > 0 && parameterName == QString("RC_TYPE"))
    {
        rcTypeUpdateRequested = 0;
        updateStatus(tr("Received RC type update, setting parameters based on model."));
        rcType = value.toInt();
        // Request all other parameters as well
        requestCalibrationRC();
    }
626 627 628 629

    // Order is: roll, pitch, yaw, throttle, mode sw, aux 1-3

    if (parameterName.contains("RC_MAP_ROLL")) {
630 631
        rcMapping[0] = value.toInt() - 1;
        ui->rollSpinBox->setValue(rcMapping[0]+1);
632 633 634
    }

    if (parameterName.contains("RC_MAP_PITCH")) {
635 636
        rcMapping[1] = value.toInt() - 1;
        ui->pitchSpinBox->setValue(rcMapping[1]+1);
637 638 639
    }

    if (parameterName.contains("RC_MAP_YAW")) {
640 641
        rcMapping[2] = value.toInt() - 1;
        ui->yawSpinBox->setValue(rcMapping[2]+1);
642 643 644
    }

    if (parameterName.contains("RC_MAP_THROTTLE")) {
645 646
        rcMapping[3] = value.toInt() - 1;
        ui->throttleSpinBox->setValue(rcMapping[3]+1);
647 648 649
    }

    if (parameterName.contains("RC_MAP_MODE_SW")) {
650 651
        rcMapping[4] = value.toInt() - 1;
        ui->modeSpinBox->setValue(rcMapping[4]+1);
652 653 654
    }

    if (parameterName.contains("RC_MAP_AUX1")) {
655 656
        rcMapping[5] = value.toInt() - 1;
        ui->aux1SpinBox->setValue(rcMapping[5]+1);
657 658 659
    }

    if (parameterName.contains("RC_MAP_AUX2")) {
660
        rcMapping[6] = value.toInt() - 1;
661
        ui->aux2SpinBox->setValue(rcMapping[6]+1);
662 663 664
    }

    if (parameterName.contains("RC_MAP_AUX3")) {
665
        rcMapping[7] = value.toInt() - 1;
666
        ui->aux3SpinBox->setValue(rcMapping[7]+1);
667 668 669 670 671
    }

    // Scaling

    if (parameterName.contains("RC_SCALE_ROLL")) {
672
        rcScaling[0] = value.toFloat();
673 674 675
    }

    if (parameterName.contains("RC_SCALE_PITCH")) {
676
        rcScaling[1] = value.toFloat();
677 678 679
    }

    if (parameterName.contains("RC_SCALE_YAW")) {
680
        rcScaling[2] = value.toFloat();
681 682 683
    }

    if (parameterName.contains("RC_SCALE_THROTTLE")) {
684
        rcScaling[3] = value.toFloat();
685 686 687
    }

    if (parameterName.contains("RC_SCALE_MODE_SW")) {
688
        rcScaling[4] = value.toFloat();
689 690 691
    }

    if (parameterName.contains("RC_SCALE_AUX1")) {
692
        rcScaling[5] = value.toFloat();
693 694 695
    }

    if (parameterName.contains("RC_SCALE_AUX2")) {
696
        rcScaling[6] = value.toFloat();
697 698 699
    }

    if (parameterName.contains("RC_SCALE_AUX3")) {
700
        rcScaling[7] = value.toFloat();
701
    }
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
}

void QGCVehicleConfig::updateStatus(const QString& str)
{
    ui->statusLabel->setText(str);
    ui->statusLabel->setStyleSheet("");
}

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

void QGCVehicleConfig::setRCType(int type)
{
    if (!mav) return;

    // XXX TODO Add handling of RC_TYPE vs non-RC_TYPE here

    mav->setParameter(0, "RC_TYPE", type);
    rcTypeUpdateRequested = QGC::groundTimeMilliseconds();
    QTimer::singleShot(rcTypeTimeout+100, this, SLOT(checktimeOuts()));
}

void QGCVehicleConfig::checktimeOuts()
{
    if (rcTypeUpdateRequested > 0)
    {
        if (QGC::groundTimeMilliseconds() - rcTypeUpdateRequested > rcTypeTimeout)
        {
            updateError(tr("Setting remote control timed out - is the system connected?"));
        }
    }
}

void QGCVehicleConfig::updateView()
{
    if (changed)
    {
742 743
        if (rc_mode == RC_MODE_1)
        {
744 745 746 747
            ui->rollSlider->setValue(rcRoll * 50 + 50);
            ui->pitchSlider->setValue(rcThrottle * 100);
            ui->yawSlider->setValue(rcYaw * 50 + 50);
            ui->throttleSlider->setValue(rcPitch * 50 + 50);
748 749 750
        }
        else if (rc_mode == RC_MODE_2)
        {
751 752 753 754
            ui->rollSlider->setValue(rcRoll * 50 + 50);
            ui->pitchSlider->setValue(rcPitch * 50 + 50);
            ui->yawSlider->setValue(rcYaw * 50 + 50);
            ui->throttleSlider->setValue(rcThrottle * 100);
755 756 757
        }
        else if (rc_mode == RC_MODE_3)
        {
758 759 760 761
            ui->rollSlider->setValue(rcYaw * 50 + 50);
            ui->pitchSlider->setValue(rcThrottle * 100);
            ui->yawSlider->setValue(rcRoll * 50 + 50);
            ui->throttleSlider->setValue(rcPitch * 50 + 50);
762 763 764
        }
        else if (rc_mode == RC_MODE_4)
        {
765 766 767 768 769 770
            ui->rollSlider->setValue(rcYaw * 50 + 50);
            ui->pitchSlider->setValue(rcPitch * 50 + 50);
            ui->yawSlider->setValue(rcRoll * 50 + 50);
            ui->throttleSlider->setValue(rcThrottle * 100);
        }

771 772 773 774
        ui->chanLabel->setText(QString("%1/%2").arg(rcValue[rcMapping[0]]).arg(rcRoll, 5, 'f', 2, QChar(' ')));
        ui->chanLabel_2->setText(QString("%1/%2").arg(rcValue[rcMapping[1]]).arg(rcPitch, 5, 'f', 2, QChar(' ')));
        ui->chanLabel_3->setText(QString("%1/%2").arg(rcValue[rcMapping[2]]).arg(rcYaw, 5, 'f', 2, QChar(' ')));
        ui->chanLabel_4->setText(QString("%1/%2").arg(rcValue[rcMapping[3]]).arg(rcThrottle, 5, 'f', 2, QChar(' ')));
775 776

        ui->modeSwitchSlider->setValue(rcMode * 50 + 50);
777
        ui->chanLabel_5->setText(QString("%1/%2").arg(rcValue[rcMapping[4]]).arg(rcMode, 5, 'f', 2, QChar(' ')));
778

779
        if (rcValue[rcMapping[5]] != UINT16_MAX) {
780
            ui->aux1Slider->setValue(rcAux1 * 50 + 50);
781
            ui->chanLabel_6->setText(QString("%1/%2").arg(rcValue[rcMapping[5]]).arg(rcAux1, 5, 'f', 2, QChar(' ')));
782 783 784 785
        } else {
            ui->chanLabel_6->setText(tr("---"));
        }

786
        if (rcValue[rcMapping[6]] != UINT16_MAX) {
787
            ui->aux2Slider->setValue(rcAux2 * 50 + 50);
788
            ui->chanLabel_7->setText(QString("%1/%2").arg(rcValue[rcMapping[6]]).arg(rcAux2, 5, 'f', 2, QChar(' ')));
789 790 791 792
        } else {
            ui->chanLabel_7->setText(tr("---"));
        }

793
        if (rcValue[rcMapping[7]] != UINT16_MAX) {
794
            ui->aux3Slider->setValue(rcAux3 * 50 + 50);
795
            ui->chanLabel_8->setText(QString("%1/%2").arg(rcValue[rcMapping[7]]).arg(rcAux3, 5, 'f', 2, QChar(' ')));
796 797
        } else {
            ui->chanLabel_8->setText(tr("---"));
798 799
        }

800 801 802
        changed = false;
    }
}