Skip to content
Snippets Groups Projects
QGCVehicleConfig.cc 17.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <limits.h>
    
    #include <QTimer>
    
    
    #include "ui_QGCVehicleConfig.h"
    
    QGCVehicleConfig::QGCVehicleConfig(QWidget *parent) :
        QWidget(parent),
    
        rc_mode(RC_MODE_2),
        rcRoll(0.0f),
        rcPitch(0.0f),
        rcYaw(0.0f),
        rcThrottle(0.0f),
        rcMode(0.0f),
        rcAux1(0.0f),
        rcAux2(0.0f),
        rcAux3(0.0f),
    
        setObjectName("QGC_VEHICLECONFIG");
    
    
        requestCalibrationRC();
        if (mav) mav->requestParameter(0, "RC_TYPE");
    
    
        ui->rcModeComboBox->setCurrentIndex((int)rc_mode - 1);
    
    
        connect(ui->rcCalibrationButton, SIGNAL(clicked(bool)), this, SLOT(toggleCalibrationRC(bool)));
        connect(ui->storeButton, SIGNAL(clicked()), this, SLOT(writeParameters()));
    
        connect(ui->rcModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setRCModeIndex(int)));
    
    
        connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
    
        setActiveUAS(UASManager::instance()->getActiveUAS());
    
    
        for (unsigned int i = 0; i < chanMax; i++)
    
        {
            rcValue[i] = 1500;
        }
    
        updateTimer.setInterval(150);
        connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateView()));
        updateTimer.start();
    
    void QGCVehicleConfig::setRCModeIndex(int newRcMode)
    {
        if (newRcMode > 0 && newRcMode < 5)
        {
            rc_mode = (enum RC_MODE) (newRcMode+1);
            changed = true;
        }
    }
    
    
    void QGCVehicleConfig::toggleCalibrationRC(bool enabled)
    {
        if (enabled)
        {
            startCalibrationRC();
        }
        else
        {
            stopCalibrationRC();
        }
    }
    
    void QGCVehicleConfig::startCalibrationRC()
    {
        ui->rcTypeComboBox->setEnabled(false);
    
        ui->rcCalibrationButton->setText(tr("Stop RC Calibration"));
    
        resetCalibrationRC();
    }
    
    void QGCVehicleConfig::stopCalibrationRC()
    {
        ui->rcTypeComboBox->setEnabled(true);
    
        ui->rcCalibrationButton->setText(tr("Start RC Calibration"));
    
    }
    
    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)));
    
            toolWidgets.clear();
    
        // Connect new system
        mav = active;
    
        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)));
    
    
        mav->requestParameters();
    
        QString defaultsDir = qApp->applicationDirPath() + "/files/" + mav->getAutopilotTypeName().toLower() + "/widgets/";
    
        QGCToolWidget* tool;
    
        // Load calibration
        tool = new QGCToolWidget("", this);
        if (tool->loadSettings(defaultsDir + "px4_calibration.qgw", false))
        {
            toolWidgets.append(tool);
            ui->sensorLayout->addWidget(tool);
        }
        // Load multirotor attitude pid
        tool = new QGCToolWidget("", this);
        if (tool->loadSettings(defaultsDir + "px4_mc_attitude_pid_params.qgw", false))
        {
            toolWidgets.append(tool);
            ui->multiRotorAttitudeLayout->addWidget(tool);
        }
    
        // Load multirotor position pid
        tool = new QGCToolWidget("", this);
        if (tool->loadSettings(defaultsDir + "px4_mc_position_pid_params.qgw", false))
        {
            toolWidgets.append(tool);
            ui->multiRotorPositionLayout->addWidget(tool);
        }
    
        // Load fixed wing attitude pid
        tool = new QGCToolWidget("", this);
        if (tool->loadSettings(defaultsDir + "px4_fw_attitude_pid_params.qgw", false))
        {
            toolWidgets.append(tool);
            ui->fixedWingAttitudeLayout->addWidget(tool);
        }
    
        // Load fixed wing position pid
        tool = new QGCToolWidget("", this);
        if (tool->loadSettings(defaultsDir + "px4_fw_position_pid_params.qgw", false))
        {
            toolWidgets.append(tool);
            ui->fixedWingPositionLayout->addWidget(tool);
        }
    
        updateStatus(QString("Reading from system %1").arg(mav->getUASName()));
    
    }
    
    void QGCVehicleConfig::resetCalibrationRC()
    {
        for (unsigned int i = 0; i < chanMax; ++i)
        {
            rcMin[i] = INT_MAX;
            rcMax[i] = INT_MIN;
        }
    }
    
    /**
     * 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
    
        for (unsigned int i = 0; i < chanMax; ++i)
        {
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            mav->setParameter(0, minTpl.arg(i+1), rcMin[i]);
            mav->setParameter(0, trimTpl.arg(i+1), rcTrim[i]);
            mav->setParameter(0, maxTpl.arg(i+1), rcMax[i]);
            mav->setParameter(0, revTpl.arg(i+1), (rcRev[i]) ? -1 : 1);
    
        }
    
        // Write mappings
        mav->setParameter(0, "RC_MAP_ROLL", rcMapping[0]);
        mav->setParameter(0, "RC_MAP_PITCH", rcMapping[1]);
        mav->setParameter(0, "RC_MAP_THROTTLE", rcMapping[2]);
        mav->setParameter(0, "RC_MAP_YAW", rcMapping[3]);
        mav->setParameter(0, "RC_MAP_MODE_SW", rcMapping[4]);
        mav->setParameter(0, "RC_MAP_AUX1", rcMapping[5]);
        mav->setParameter(0, "RC_MAP_AUX2", rcMapping[6]);
        mav->setParameter(0, "RC_MAP_AUX3", rcMapping[7]);
    }
    
    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
            mav->requestParameter(0, minTpl.arg(i+1));
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            QGC::SLEEP::usleep(5000);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            mav->requestParameter(0, trimTpl.arg(i+1));
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            QGC::SLEEP::usleep(5000);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            mav->requestParameter(0, maxTpl.arg(i+1));
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            QGC::SLEEP::usleep(5000);
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            mav->requestParameter(0, revTpl.arg(i+1));
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            QGC::SLEEP::usleep(5000);
    
        }
    }
    
    void QGCVehicleConfig::writeParameters()
    {
        updateStatus(tr("Writing all onboard parameters."));
        writeCalibrationRC();
    }
    
    void QGCVehicleConfig::remoteControlChannelRawChanged(int chan, float val)
    {
    
    Lorenz Meier's avatar
    Lorenz Meier committed
    //    /* scale around the mid point differently for lower and upper range */
    //            if (ppm_buffer[i] > _rc.chan[i].mid + _parameters.dz[i]) {
    //                _rc.chan[i].scaled = ((ppm_buffer[i] - _parameters.trim[i]) / (_parameters.max[i] - _parameters.trim[i]));
    //            } else if ((ppm_buffer[i] < _rc_chan[i].mid - _parameters.dz[i])) {
    //                _rc.chan[i].scaled = -1.0 + ((ppm_buffer[i] - _parameters.min[i]) / (_parameters.trim[i] - _parameters.min[i]));
    //            } else {
    //                /* in the configured dead zone, output zero */
    //                _rc.chan[i].scaled = 0.0f;
    //            }
    
    
        if (chan < 0 || static_cast<unsigned int>(chan) >= chanMax)
            return;
    
    
        if (val < rcMin[chan])
        {
            rcMin[chan] = val;
        }
    
        if (val > rcMax[chan])
        {
            rcMax[chan] = val;
        }
    
    
        if (chan == rcMapping[0])
        {
            // ROLL
    
            if (rcRoll >= rcTrim[chan])
    
            {
                rcRoll = (val - rcTrim[chan])/(rcMax[chan] - rcTrim[chan]);
            }
            else
            {
                rcRoll = (val - rcMin[chan])/(rcTrim[chan] - rcMin[chan]);
            }
    
    
            rcRoll = qBound(-1.0f, rcRoll, 1.0f);
        }
        else if (chan == rcMapping[1])
        {
            // PITCH
    
            if (rcPitch >= rcTrim[chan])
    
            {
                rcPitch = (val - rcTrim[chan])/(rcMax[chan] - rcTrim[chan]);
            }
            else
            {
                rcPitch = (val - rcMin[chan])/(rcTrim[chan] - rcMin[chan]);
            }
    
            rcPitch = qBound(-1.0f, rcPitch, 1.0f);
        }
        else if (chan == rcMapping[2])
        {
            // YAW
    
            if (rcYaw >= rcTrim[chan])
    
            {
                rcYaw = (val - rcTrim[chan])/(rcMax[chan] - rcTrim[chan]);
            }
            else
            {
                rcYaw = (val - rcMin[chan])/(rcTrim[chan] - rcMin[chan]);
            }
    
            rcYaw = qBound(-1.0f, rcYaw, 1.0f);
        }
        else if (chan == rcMapping[3])
        {
            // THROTTLE
    
            if (rcThrottle >= rcTrim[chan])
    
            {
                rcThrottle = (val - rcTrim[chan])/(rcMax[chan] - rcTrim[chan]);
            }
            else
            {
                rcThrottle = (val - rcMin[chan])/(rcTrim[chan] - rcMin[chan]);
            }
    
            rcThrottle = qBound(-1.0f, rcThrottle, 1.0f);
        }
        else if (chan == rcMapping[4])
        {
            // MODE SWITCH
    
            if (rcMode >= rcTrim[chan])
    
            {
                rcMode = (val - rcTrim[chan])/(rcMax[chan] - rcTrim[chan]);
            }
            else
            {
                rcMode = (val - rcMin[chan])/(rcTrim[chan] - rcMin[chan]);
            }
    
            rcMode = qBound(-1.0f, rcMode, 1.0f);
        }
        else if (chan == rcMapping[5])
        {
            // AUX1
            rcAux1 = val;
    
        }
        else if (chan == rcMapping[6])
        {
            // AUX2
            rcAux2 = val;
    
        }
        else if (chan == rcMapping[7])
        {
            // AUX3
            rcAux3 = val;
    
        //qDebug() << "RC CHAN:" << chan << "PPM:" << val;
    
    }
    
    void QGCVehicleConfig::parameterChanged(int uas, int component, QString parameterName, QVariant value)
    {
        Q_UNUSED(uas);
        Q_UNUSED(component);
    
    
        // 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
            unsigned int index = parameterName.mid(2, 1).toInt(&ok) - 1;
    
            if (ok && (index > 0) && (index < chanMax))
            {
                rcMin[index] = value.toInt();
            }
        }
    
        if (maxTpl.exactMatch(parameterName)) {
            bool ok;
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            unsigned int index = parameterName.mid(2, 1).toInt(&ok) - 1;
    
            if (ok && (index > 0) && (index < chanMax))
            {
                rcMax[index] = value.toInt();
            }
        }
    
        if (trimTpl.exactMatch(parameterName)) {
            bool ok;
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            unsigned int index = parameterName.mid(2, 1).toInt(&ok) - 1;
    
            if (ok && (index > 0) && (index < chanMax))
            {
                rcTrim[index] = value.toInt();
            }
        }
    
        if (revTpl.exactMatch(parameterName)) {
            bool ok;
    
    Lorenz Meier's avatar
    Lorenz Meier committed
            unsigned int index = parameterName.mid(2, 1).toInt(&ok) - 1;
    
            if (ok && (index > 0) && (index < chanMax))
            {
                rcRev[index] = (value.toInt() == -1) ? true : false;
    
                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;
                }
            }
        }
    
    //        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);
    //    }
    
    
        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();
        }
    
    
        // Order is: roll, pitch, yaw, throttle, mode sw, aux 1-3
    
        if (parameterName.contains("RC_MAP_ROLL")) {
            rcMapping[0] = value.toInt();
            ui->rollSpinBox->setValue(rcMapping[0]);
        }
    
        if (parameterName.contains("RC_MAP_PITCH")) {
            rcMapping[1] = value.toInt();
            ui->pitchSpinBox->setValue(rcMapping[1]);
        }
    
        if (parameterName.contains("RC_MAP_YAW")) {
            rcMapping[2] = value.toInt();
            ui->yawSpinBox->setValue(rcMapping[2]);
        }
    
        if (parameterName.contains("RC_MAP_THROTTLE")) {
            rcMapping[3] = value.toInt();
            ui->throttleSpinBox->setValue(rcMapping[3]);
        }
    
        if (parameterName.contains("RC_MAP_MODE_SW")) {
            rcMapping[4] = value.toInt();
            ui->modeSpinBox->setValue(rcMapping[4]);
        }
    
        if (parameterName.contains("RC_MAP_AUX1")) {
            rcMapping[5] = value.toInt();
            ui->aux1SpinBox->setValue(rcMapping[5]);
        }
    
        if (parameterName.contains("RC_MAP_AUX2")) {
            rcMapping[6] = value.toInt();
            ui->aux1SpinBox->setValue(rcMapping[6]);
        }
    
        if (parameterName.contains("RC_MAP_AUX3")) {
            rcMapping[7] = value.toInt();
            ui->aux1SpinBox->setValue(rcMapping[7]);
        }
    
        // Scaling
    
        if (parameterName.contains("RC_SCALE_ROLL")) {
            rcScaling[0] = value.toInt();
        }
    
        if (parameterName.contains("RC_SCALE_PITCH")) {
            rcScaling[1] = value.toInt();
        }
    
        if (parameterName.contains("RC_SCALE_YAW")) {
            rcScaling[2] = value.toInt();
        }
    
        if (parameterName.contains("RC_SCALE_THROTTLE")) {
            rcScaling[3] = value.toInt();
        }
    
        if (parameterName.contains("RC_SCALE_MODE_SW")) {
            rcScaling[4] = value.toInt();
        }
    
        if (parameterName.contains("RC_SCALE_AUX1")) {
            rcScaling[5] = value.toInt();
        }
    
        if (parameterName.contains("RC_SCALE_AUX2")) {
            rcScaling[6] = value.toInt();
        }
    
        if (parameterName.contains("RC_SCALE_AUX3")) {
            rcScaling[7] = value.toInt();
        }
    
    }
    
    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)
        {
    
            if (rc_mode == RC_MODE_1)
            {
                ui->rollSlider->setValue(rcRoll);
                ui->pitchSlider->setValue(rcThrottle);
                ui->yawSlider->setValue(rcYaw);
                ui->throttleSlider->setValue(rcPitch);
            }
            else if (rc_mode == RC_MODE_2)
            {
                ui->rollSlider->setValue(rcRoll);
                ui->pitchSlider->setValue(rcPitch);
                ui->yawSlider->setValue(rcYaw);
                ui->throttleSlider->setValue(rcThrottle);
            }
            else if (rc_mode == RC_MODE_3)
            {
                ui->rollSlider->setValue(rcYaw);
                ui->pitchSlider->setValue(rcThrottle);
                ui->yawSlider->setValue(rcRoll);
                ui->throttleSlider->setValue(rcPitch);
            }
            else if (rc_mode == RC_MODE_4)
            {
                ui->rollSlider->setValue(rcYaw);
                ui->pitchSlider->setValue(rcPitch);
                ui->yawSlider->setValue(rcRoll);
                ui->throttleSlider->setValue(rcThrottle);
            }
    
            ui->chanLabel->setText(QString("%1/%2").arg(rcValue[0]).arg(rcRoll));
            ui->chanLabel_2->setText(QString("%1/%2").arg(rcValue[1]).arg(rcPitch));
            ui->chanLabel_3->setText(QString("%1/%2").arg(rcValue[2]).arg(rcYaw));
            ui->chanLabel_4->setText(QString("%1/%2").arg(rcValue[3]).arg(rcThrottle));
            ui->modeSwitchSlider->setValue(rcMode);
            ui->chanLabel_5->setText(QString("%1/%2").arg(rcValue[4]).arg(rcMode));
            ui->aux1Slider->setValue(rcAux1);
            ui->chanLabel_6->setText(QString("%1/%2").arg(rcValue[5]).arg(rcAux1));
            ui->aux2Slider->setValue(rcAux2);
            ui->chanLabel_7->setText(QString("%1/%2").arg(rcValue[6]).arg(rcAux2));
            ui->aux3Slider->setValue(rcAux3);
            ui->chanLabel_8->setText(QString("%1/%2").arg(rcValue[7]).arg(rcAux3));