FlightModesComponentController.cc 8 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
 (c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "FlightModesComponentController.h"
#include "QGCMAVLink.h"
#include "UASManager.h"
#include "AutoPilotPluginManager.h"

#include <QVariant>
#include <QQmlProperty>

Don Gagne's avatar
Don Gagne committed
35
FlightModesComponentController::FlightModesComponentController(void) :
Don Gagne's avatar
Don Gagne committed
36 37
    _liveRCValues(false),
    _validConfiguration(false),
Don Gagne's avatar
Don Gagne committed
38
    _channelCount(18)
Don Gagne's avatar
Don Gagne committed
39
{
Don Gagne's avatar
Don Gagne committed
40 41 42 43 44
    QStringList usedParams;
    usedParams << "RC_MAP_THROTTLE" << "RC_MAP_YAW" << "RC_MAP_PITCH" << "RC_MAP_ROLL" << "RC_MAP_FLAPS" << "RC_MAP_AUX1" << "RC_MAP_AUX2" << "RC_MAP_ACRO_SW";
    if (!_allParametersExists(FactSystem::defaultComponentId, usedParams)) {
        return;
    }
Don Gagne's avatar
Don Gagne committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
    
    _initRcValues();
    _validateConfiguration();
}

FlightModesComponentController::~FlightModesComponentController()
{
    setSendLiveRCSwitchRanges(false);
}


void FlightModesComponentController::_initRcValues(void)
{
    for (int i=0; i<_chanMax; i++) {
        _rcValues << 1.0;
    }
}

/// This will look for parameter settings which would cause the config to not run correctly.
/// It will set _validConfiguration and _configurationErrors as needed.
void FlightModesComponentController::_validateConfiguration(void)
{
    _validConfiguration = true;
    
Don Gagne's avatar
Don Gagne committed
69
    _channelCount = parameterExists(FactSystem::defaultComponentId, "RC_CHAN_CNT") ? getParameterFact(FactSystem::defaultComponentId, "RC_CHAN_CNT")->value().toInt() : _chanMax;
Don Gagne's avatar
Don Gagne committed
70 71 72 73
    if (_channelCount <= 0 || _channelCount > _chanMax) {
        // Parameter exists, but has not yet been set or is invalid. Use default
        _channelCount = _chanMax;
    }
Don Gagne's avatar
Don Gagne committed
74 75 76 77 78 79
    
    // Make sure switches are valid and within channel range
    
    QStringList switchParams, switchNames;
    QList<int> switchMappings;
    
Don Gagne's avatar
Don Gagne committed
80 81
    switchParams << "RC_MAP_MODE_SW" << "RC_MAP_RETURN_SW" << "RC_MAP_LOITER_SW" << "RC_MAP_POSCTL_SW" << "RC_MAP_OFFB_SW" << "RC_MAP_ACRO_SW";
    switchNames << "Mode Switch" << "Return Switch" << "Loiter Switch" << "PosCtl Switch" << "Offboard Switch" << "Acro Switch";
Don Gagne's avatar
Don Gagne committed
82 83
    
    for(int i=0; i<switchParams.count(); i++) {
Don Gagne's avatar
Don Gagne committed
84
        int map = getParameterFact(FactSystem::defaultComponentId, switchParams[i])->value().toInt();
Don Gagne's avatar
Don Gagne committed
85 86 87 88 89 90 91 92
        switchMappings << map;
        
        if (map < 0 || map > _channelCount) {
            _validConfiguration = false;
            _configurationErrors += QString("%1 is set to %2. Mapping must between 0 and %3 (inclusive).\n").arg(switchNames[i]).arg(map).arg(_channelCount);
        }
    }
    
93
    // Make sure switches are not double-mapped
Don Gagne's avatar
Don Gagne committed
94 95 96
    
    QStringList attitudeParams, attitudeNames;
    
97 98
    attitudeParams << "RC_MAP_THROTTLE" << "RC_MAP_YAW" << "RC_MAP_PITCH" << "RC_MAP_ROLL" << "RC_MAP_FLAPS" << "RC_MAP_AUX1" << "RC_MAP_AUX2";
    attitudeNames << "Throttle" << "Yaw" << "Pitch" << "Roll" << "Flaps" << "Aux1" << "Aux2";
Don Gagne's avatar
Don Gagne committed
99 100

    for (int i=0; i<attitudeParams.count(); i++) {
Don Gagne's avatar
Don Gagne committed
101
        int map = getParameterFact(FactSystem::defaultComponentId, attitudeParams[i])->value().toInt();
Don Gagne's avatar
Don Gagne committed
102 103 104 105 106 107 108 109

        for (int j=0; j<switchParams.count(); j++) {
            if (map != 0 && map == switchMappings[j]) {
                _validConfiguration = false;
                _configurationErrors += QString("%1 is set to same channel as %2.\n").arg(switchNames[j]).arg(attitudeNames[i]);
            }
        }
    }
110 111 112 113 114 115 116 117 118
    
    // Check for switches that must be on their own channel
    
    QStringList singleSwitchParams, singleSwitchNames;
    
    singleSwitchParams << "RC_MAP_RETURN_SW" << "RC_MAP_OFFB_SW";
    singleSwitchNames << "Return Switch" << "Offboard Switch";
    
    for (int i=0; i<singleSwitchParams.count(); i++) {
Don Gagne's avatar
Don Gagne committed
119
        int map = getParameterFact(FactSystem::defaultComponentId, singleSwitchParams[i])->value().toInt();
120 121 122 123 124 125 126 127
        
        for (int j=0; j<switchParams.count(); j++) {
            if (map != 0 && singleSwitchParams[i] != switchParams[j] && map == switchMappings[j]) {
                _validConfiguration = false;
                _configurationErrors += QString("%1 must be on seperate channel, but is set to same channel as %2.\n").arg(singleSwitchNames[i]).arg(switchParams[j]);
            }
        }
    }
Don Gagne's avatar
Don Gagne committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
}

void FlightModesComponentController::setSendLiveRCSwitchRanges(bool start)
{
    if (start) {
        
        // We need to know min and max for channel in order to calculate percentage range
        for (int i=0; i<_chanMax; i++) {
            QString rcMinParam, rcMaxParam, rcRevParam;
            
            rcMinParam = QString("RC%1_MIN").arg(i+1);
            rcMaxParam = QString("RC%1_MAX").arg(i+1);
            rcRevParam = QString("RC%1_REV").arg(i+1);
            
            QVariant value;
            
Don Gagne's avatar
Don Gagne committed
144 145
            _rgRCMin[i] = getParameterFact(FactSystem::defaultComponentId, rcMinParam)->value().toInt();
            _rgRCMax[i] = getParameterFact(FactSystem::defaultComponentId, rcMaxParam)->value().toInt();
Don Gagne's avatar
Don Gagne committed
146
            
Don Gagne's avatar
Don Gagne committed
147
            float floatReversed = getParameterFact(-1, rcRevParam)->value().toFloat();
Don Gagne's avatar
Don Gagne committed
148 149 150
            _rgRCReversed[i] = floatReversed == -1.0f;
        }
        
151
        _uas->startCalibration(UASInterface::StartCalibrationRadio);
Don Gagne's avatar
Don Gagne committed
152 153 154
        connect(_uas, &UASInterface::remoteControlChannelRawChanged, this, &FlightModesComponentController::_remoteControlChannelRawChanged);
    } else {
        disconnect(_uas, &UASInterface::remoteControlChannelRawChanged, this, &FlightModesComponentController::_remoteControlChannelRawChanged);
155
        _uas->stopCalibration();
Don Gagne's avatar
Don Gagne committed
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
        _initRcValues();
        emit switchLiveRangeChanged();
    }
}

/// @brief This routine is called whenever a raw value for an RC channel changes.
///     @param chan RC channel on which signal is coming from (0-based)
///     @param fval Current value for channel
void FlightModesComponentController::_remoteControlChannelRawChanged(int chan, float fval)
{
    Q_ASSERT(chan >= 0 && chan <= _chanMax);
    
    if (fval < _rgRCMin[chan]) {
        fval= _rgRCMin[chan];
    }
    if (fval > _rgRCMax[chan]) {
        fval= _rgRCMax[chan];
    }
    
    float percentRange = (fval - _rgRCMin[chan]) / (float)(_rgRCMax[chan] - _rgRCMin[chan]);
    if (_rgRCReversed[chan]) {
        percentRange = 1.0 - percentRange;
    }
    
    _rcValues[chan] = percentRange;
    emit switchLiveRangeChanged();
}

double FlightModesComponentController::_switchLiveRange(const QString& param)
{
    QVariant value;
    
Don Gagne's avatar
Don Gagne committed
188
    int channel = getParameterFact(-1, param)->value().toInt();
Don Gagne's avatar
Don Gagne committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
    if (channel == 0) {
        return 1.0;
    } else {
        return _rcValues[channel - 1];
    }
}

double FlightModesComponentController::modeSwitchLiveRange(void)
{
    return _switchLiveRange("RC_MAP_MODE_SW");
}

double FlightModesComponentController::returnSwitchLiveRange(void)
{
    return _switchLiveRange("RC_MAP_RETURN_SW");
}

206 207 208 209 210
double FlightModesComponentController::offboardSwitchLiveRange(void)
{
    return _switchLiveRange("RC_MAP_OFFB_SW");
}

Don Gagne's avatar
Don Gagne committed
211 212 213 214 215 216 217 218 219 220
double FlightModesComponentController::loiterSwitchLiveRange(void)
{
    return _switchLiveRange("RC_MAP_LOITER_SW");
}

double FlightModesComponentController::posCtlSwitchLiveRange(void)
{
    return _switchLiveRange("RC_MAP_POSCTL_SW");
}

Don Gagne's avatar
Don Gagne committed
221 222 223 224
double FlightModesComponentController::acroSwitchLiveRange(void)
{
    return _switchLiveRange("RC_MAP_ACRO_SW");
}