/*===================================================================== QGroundControl Open Source Ground Control Station (c) 2009, 2015 QGROUNDCONTROL PROJECT 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 . ======================================================================*/ /// @file /// @author Don Gagne #include "FlightModesComponentController.h" #include "QGCMAVLink.h" #include "UASManager.h" #include "AutoPilotPluginManager.h" #include #include FlightModesComponentController::FlightModesComponentController(QObject* parent) : QObject(parent), _liveRCValues(false), _validConfiguration(false), _channelCount(18), _autoPilotPlugin(NULL) { _uas = UASManager::instance()->getActiveUAS(); Q_ASSERT(_uas); _autoPilotPlugin = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(_uas); Q_ASSERT(_autoPilotPlugin); Q_ASSERT(_autoPilotPlugin->pluginReady()); _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; _channelCount = _autoPilotPlugin->parameterExists("RC_CHAN_CNT") ? _autoPilotPlugin->getParameterFact("RC_CHAN_CNT")->value().toInt() : _chanMax; if (_channelCount <= 0 || _channelCount > _chanMax) { // Parameter exists, but has not yet been set or is invalid. Use default _channelCount = _chanMax; } // Make sure switches are valid and within channel range QStringList switchParams, switchNames; QList switchMappings; switchParams << "RC_MAP_MODE_SW" << "RC_MAP_RETURN_SW" << "RC_MAP_LOITER_SW" << "RC_MAP_POSCTL_SW" << "RC_MAP_OFFB_SW"; switchNames << "Mode Switch" << "Return Switch" << "Loiter Switch" << "PosCtl Switch" << "Offboard Switch"; for(int i=0; igetParameterFact(switchParams[i])->value().toInt(); 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); } } // Make sure switches are not double-mapped QStringList attitudeParams, attitudeNames; attitudeParams << "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"; attitudeNames << "Throttle" << "Yaw" << "Pitch" << "Roll" << "Flaps" << "Aux1" << "Aux2" << "Acro"; for (int i=0; igetParameterFact(attitudeParams[i])->value().toInt(); for (int j=0; jgetParameterFact(singleSwitchParams[i])->value().toInt(); for (int j=0; jgetParameterFact(rcMinParam)->value().toInt(); _rgRCMax[i] = _autoPilotPlugin->getParameterFact(rcMaxParam)->value().toInt(); float floatReversed = _autoPilotPlugin->getParameterFact(rcRevParam)->value().toFloat(); _rgRCReversed[i] = floatReversed == -1.0f; } _uas->startCalibration(UASInterface::StartCalibrationRadio); connect(_uas, &UASInterface::remoteControlChannelRawChanged, this, &FlightModesComponentController::_remoteControlChannelRawChanged); } else { disconnect(_uas, &UASInterface::remoteControlChannelRawChanged, this, &FlightModesComponentController::_remoteControlChannelRawChanged); _uas->stopCalibration(); _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; int channel = _autoPilotPlugin->getParameterFact(param)->value().toInt(); 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"); } double FlightModesComponentController::offboardSwitchLiveRange(void) { return _switchLiveRange("RC_MAP_OFFB_SW"); } double FlightModesComponentController::loiterSwitchLiveRange(void) { return _switchLiveRange("RC_MAP_LOITER_SW"); } double FlightModesComponentController::posCtlSwitchLiveRange(void) { return _switchLiveRange("RC_MAP_POSCTL_SW"); }