You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
7.9 KiB
225 lines
7.9 KiB
/*===================================================================== |
|
|
|
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> |
|
|
|
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<int> 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; i<switchParams.count(); i++) { |
|
int map = _autoPilotPlugin->getParameterFact(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; i<attitudeParams.count(); i++) { |
|
int map = _autoPilotPlugin->getParameterFact(attitudeParams[i])->value().toInt(); |
|
|
|
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]); |
|
} |
|
} |
|
} |
|
|
|
// 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++) { |
|
int map = _autoPilotPlugin->getParameterFact(singleSwitchParams[i])->value().toInt(); |
|
|
|
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]); |
|
} |
|
} |
|
} |
|
} |
|
|
|
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; |
|
|
|
_rgRCMin[i] = _autoPilotPlugin->getParameterFact(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"); |
|
} |
|
|
|
|