APMRadioComponent.cc 4.83 KB
Newer Older
1 2 3 4 5 6 7 8 9
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

Don Gagne's avatar
Don Gagne committed
10 11 12

#include "APMRadioComponent.h"
#include "APMAutoPilotPlugin.h"
13
#include "APMAirframeComponent.h"
Don Gagne's avatar
Don Gagne committed
14 15

APMRadioComponent::APMRadioComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) :
16
    VehicleComponent(vehicle, autopilot, parent),
Don Gagne's avatar
Don Gagne committed
17 18
    _name(tr("Radio"))
{
Don Gagne's avatar
Don Gagne committed
19 20 21
    _mapParams << QStringLiteral("RCMAP_ROLL") << QStringLiteral("RCMAP_PITCH") << QStringLiteral("RCMAP_YAW") << QStringLiteral("RCMAP_THROTTLE");

    foreach (const QString& mapParam, _mapParams) {
22
        Fact* fact = _vehicle->getParameterFact(-1, mapParam);
Don Gagne's avatar
Don Gagne committed
23 24 25 26
        connect(fact, &Fact::valueChanged, this, &APMRadioComponent::_triggerChanged);
    }

    _connectSetupTriggers();
Don Gagne's avatar
Don Gagne committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
}

QString APMRadioComponent::name(void) const
{
    return _name;
}

QString APMRadioComponent::description(void) const
{
    return tr("The Radio Component is used to setup which channels on your RC Transmitter you will use for each vehicle control such as Roll, Pitch, Yaw and Throttle. "
              "It also allows you to assign switches and dials to the various flight modes. "
              "Prior to flight you must also calibrate the extents for all of your channels.");
}

QString APMRadioComponent::iconResource(void) const
{
43
    return QStringLiteral("/qmlimages/RadioComponentIcon.png");
Don Gagne's avatar
Don Gagne committed
44 45 46 47 48 49 50 51 52 53
}

bool APMRadioComponent::requiresSetup(void) const
{
    return true;
}

bool APMRadioComponent::setupComplete(void) const
{
    // The best we can do to detect the need for a radio calibration is look for attitude
Don Gagne's avatar
Don Gagne committed
54 55 56 57 58
    // controls to be mapped as well as all attitude control rc min/max/trim still at defaults.
    QList<int> mapValues;

    // First check for all attitude controls mapped
    for (int i=0; i<_mapParams.count(); i++) {
59
        mapValues << _vehicle->getParameterFact(FactSystem::defaultComponentId, _mapParams[i])->rawValue().toInt();
Don Gagne's avatar
Don Gagne committed
60
        if (mapValues[i] <= 0) {
Don Gagne's avatar
Don Gagne committed
61 62 63
            return false;
        }
    }
Don Gagne's avatar
Don Gagne committed
64 65 66

    // Next check RC#_MIN/MAX/TRIM all at defaults
    foreach (const QString& mapParam, _mapParams) {
67 68
        int channel = _vehicle->getParameterFact(-1, mapParam)->rawValue().toInt();
        if (_vehicle->getParameterFact(-1, QString("RC%1_MIN").arg(channel))->rawValue().toInt() != 1100) {
Don Gagne's avatar
Don Gagne committed
69 70
            return true;
        }
71
        if (_vehicle->getParameterFact(-1, QString("RC%1_MAX").arg(channel))->rawValue().toInt() != 1900) {
Don Gagne's avatar
Don Gagne committed
72 73
            return true;
        }
74
        if (_vehicle->getParameterFact(-1, QString("RC%1_TRIM").arg(channel))->rawValue().toInt() != 1500) {
Don Gagne's avatar
Don Gagne committed
75 76 77
            return true;
        }
    }
Don Gagne's avatar
Don Gagne committed
78
    
Don Gagne's avatar
Don Gagne committed
79
    return false;
Don Gagne's avatar
Don Gagne committed
80 81 82 83
}

QStringList APMRadioComponent::setupCompleteChangedTriggerList(void) const
{
Don Gagne's avatar
Don Gagne committed
84 85
    // APMRadioComponent manages it's own triggers
    return QStringList();
Don Gagne's avatar
Don Gagne committed
86 87 88 89
}

QUrl APMRadioComponent::setupSource(void) const
{
90
    return QUrl::fromUserInput(QStringLiteral("qrc:/qml/RadioComponent.qml"));
Don Gagne's avatar
Don Gagne committed
91 92 93 94
}

QUrl APMRadioComponent::summaryQmlSource(void) const
{
95
    return QUrl::fromUserInput(QStringLiteral("qrc:/qml/APMRadioComponentSummary.qml"));
Don Gagne's avatar
Don Gagne committed
96 97 98 99 100 101 102 103 104 105 106 107
}

QString APMRadioComponent::prerequisiteSetup(void) const
{
    APMAutoPilotPlugin* plugin = dynamic_cast<APMAutoPilotPlugin*>(_autopilot);

    if (!plugin->airframeComponent()->setupComplete()) {
        return plugin->airframeComponent()->name();
    }
    
    return QString();
}
Don Gagne's avatar
Don Gagne committed
108 109 110 111 112 113 114 115 116 117 118

void APMRadioComponent::_connectSetupTriggers(void)
{
    // Disconnect previous triggers
    foreach(Fact* fact, _triggerFacts) {
        disconnect(fact, &Fact::valueChanged, this, &APMRadioComponent::_triggerChanged);
    }
    _triggerFacts.clear();

    // Get the channels for attitude controls and connect to those values for triggers
    foreach (const QString& mapParam, _mapParams) {
119
        int channel = _vehicle->getParameterFact(FactSystem::defaultComponentId, mapParam)->rawValue().toInt();
Don Gagne's avatar
Don Gagne committed
120

121
        Fact* fact = _vehicle->getParameterFact(-1, QString("RC%1_MIN").arg(channel));
Don Gagne's avatar
Don Gagne committed
122 123 124
        _triggerFacts << fact;
        connect(fact, &Fact::valueChanged, this, &APMRadioComponent::_triggerChanged);

125
        fact = _vehicle->getParameterFact(-1, QString("RC%1_MAX").arg(channel));
Don Gagne's avatar
Don Gagne committed
126 127 128
        _triggerFacts << fact;
        connect(fact, &Fact::valueChanged, this, &APMRadioComponent::_triggerChanged);

129
        fact = _vehicle->getParameterFact(-1, QString("RC%1_TRIM").arg(channel));
Don Gagne's avatar
Don Gagne committed
130 131 132 133 134 135 136 137 138 139 140 141
        _triggerFacts << fact;
        connect(fact, &Fact::valueChanged, this, &APMRadioComponent::_triggerChanged);
    }
}

void APMRadioComponent::_triggerChanged(void)
{
    emit setupCompleteChanged(setupComplete());

    // Control mapping may have changed so we need to reset triggers
    _connectSetupTriggers();
}