Joystick.cc 27.7 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.
 *
 ****************************************************************************/

10 11 12 13 14 15 16 17 18

#include "Joystick.h"
#include "QGC.h"
#include "AutoPilotPlugin.h"
#include "UAS.h"

#include <QSettings>

QGC_LOGGING_CATEGORY(JoystickLog, "JoystickLog")
19
QGC_LOGGING_CATEGORY(JoystickValuesLog, "JoystickValuesLog")
20

21
const char* Joystick::_settingsGroup =                  "Joysticks";
22
const char* Joystick::_calibratedSettingsKey =          "Calibrated2"; // Increment number to force recalibration
23 24 25 26 27
const char* Joystick::_buttonActionSettingsKey =        "ButtonActionName%1";
const char* Joystick::_throttleModeSettingsKey =        "ThrottleMode";
const char* Joystick::_exponentialSettingsKey =         "Exponential";
const char* Joystick::_accumulatorSettingsKey =         "Accumulator";
const char* Joystick::_deadbandSettingsKey =            "Deadband";
28
const char* Joystick::_circleCorrectionSettingsKey =    "Circle_Correction";
29 30 31 32 33 34
const char* Joystick::_txModeSettingsKey =              NULL;
const char* Joystick::_fixedWingTXModeSettingsKey =     "TXMode_FixedWing";
const char* Joystick::_multiRotorTXModeSettingsKey =    "TXMode_MultiRotor";
const char* Joystick::_roverTXModeSettingsKey =         "TXMode_Rover";
const char* Joystick::_vtolTXModeSettingsKey =          "TXMode_VTOL";
const char* Joystick::_submarineTXModeSettingsKey =     "TXMode_Submarine";
35

36 37 38 39 40
const char* Joystick::_buttonActionArm =                QT_TR_NOOP("Arm");
const char* Joystick::_buttonActionDisarm =             QT_TR_NOOP("Disarm");
const char* Joystick::_buttonActionVTOLFixedWing =      QT_TR_NOOP("VTOL: Fixed Wing");
const char* Joystick::_buttonActionVTOLMultiRotor =     QT_TR_NOOP("VTOL: Multi-Rotor");

41 42 43 44 45 46 47
const char* Joystick::_rgFunctionSettingsKey[Joystick::maxFunction] = {
    "RollAxis",
    "PitchAxis",
    "YawAxis",
    "ThrottleAxis"
};

48 49
int Joystick::_transmitterMode = 2;

50
Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatCount, MultiVehicleManager* multiVehicleManager)
Gregory Dymarek's avatar
Gregory Dymarek committed
51
    : _exitThread(false)
52 53 54
    , _name(name)
    , _axisCount(axisCount)
    , _buttonCount(buttonCount)
55 56 57
    , _hatCount(hatCount)
    , _hatButtonCount(4*hatCount)
    , _totalButtonCount(_buttonCount+_hatButtonCount)
58
    , _calibrationMode(false)
59 60 61
    , _rgAxisValues(NULL)
    , _rgCalibration(NULL)
    , _rgButtonValues(NULL)
62 63
    , _lastButtonBits(0)
    , _throttleMode(ThrottleModeCenterZero)
64
    , _negativeThrust(false)
65
    , _exponential(0)
66
    , _accumulator(false)
Gregory Dymarek's avatar
Gregory Dymarek committed
67
    , _deadband(false)
68
    , _circleCorrection(false)
69 70
    , _activeVehicle(NULL)
    , _pollingStartedForCalibration(false)
71
    , _multiVehicleManager(multiVehicleManager)
72
{
73

74 75
    _rgAxisValues = new int[_axisCount];
    _rgCalibration = new Calibration_t[_axisCount];
76
    _rgButtonValues = new bool[_totalButtonCount];
77 78

    for (int i=0; i<_axisCount; i++) {
79 80
        _rgAxisValues[i] = 0;
    }
81
    for (int i=0; i<_totalButtonCount; i++) {
82 83
        _rgButtonValues[i] = false;
    }
84

85 86
    _updateTXModeSettingsKey(_multiVehicleManager->activeVehicle());

87
    _loadSettings();
88 89

    connect(_multiVehicleManager, &MultiVehicleManager::activeVehicleChanged, this, &Joystick::_activeVehicleChanged);
90 91 92 93
}

Joystick::~Joystick()
{
94 95 96 97
    // Crash out of the thread if it is still running
    terminate();
    wait();

Jacob Walser's avatar
Jacob Walser committed
98 99 100
    delete[] _rgAxisValues;
    delete[] _rgCalibration;
    delete[] _rgButtonValues;
101 102
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
void Joystick::_setDefaultCalibration(void) {
    QSettings   settings;
    settings.beginGroup(_settingsGroup);
    settings.beginGroup(_name);
    _calibrated = settings.value(_calibratedSettingsKey, false).toBool();

    // Only set default calibrations if we do not have a calibration for this gamecontroller
    if(_calibrated) return;

    for(int axis = 0; axis < _axisCount; axis++) {
        Joystick::Calibration_t calibration;
        _rgCalibration[axis] = calibration;
    }

    _rgCalibration[1].reversed = true;
    _rgCalibration[3].reversed = true;

120 121 122 123 124
    // Default TX Mode 2 axis assignments for gamecontrollers
    _rgFunctionAxis[rollFunction]       = 2;
    _rgFunctionAxis[pitchFunction]      = 3;
    _rgFunctionAxis[yawFunction]        = 0;
    _rgFunctionAxis[throttleFunction]   = 1;
125

126
    _exponential = 0;
127 128
    _accumulator = false;
    _deadband = false;
129
    _circleCorrection = false;
130 131 132 133 134 135
    _throttleMode = ThrottleModeCenterZero;
    _calibrated = true;

    _saveSettings();
}

136
void Joystick::_updateTXModeSettingsKey(Vehicle* activeVehicle)
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
{
    if(activeVehicle) {
        if(activeVehicle->fixedWing()) {
            _txModeSettingsKey = _fixedWingTXModeSettingsKey;
        } else if(activeVehicle->multiRotor()) {
            _txModeSettingsKey = _multiRotorTXModeSettingsKey;
        } else if(activeVehicle->rover()) {
            _txModeSettingsKey = _roverTXModeSettingsKey;
        } else if(activeVehicle->vtol()) {
            _txModeSettingsKey = _vtolTXModeSettingsKey;
        } else if(activeVehicle->sub()) {
            _txModeSettingsKey = _submarineTXModeSettingsKey;
        } else {
            _txModeSettingsKey = NULL;
            qWarning() << "No valid joystick TXmode settings key for selected vehicle";
            return;
        }
154 155 156 157
    } else {
        _txModeSettingsKey = NULL;
    }
}
158

159 160 161 162 163
void Joystick::_activeVehicleChanged(Vehicle* activeVehicle)
{
    _updateTXModeSettingsKey(activeVehicle);

    if(activeVehicle) {
164 165 166 167 168 169 170 171
        QSettings settings;
        settings.beginGroup(_settingsGroup);
        int mode = settings.value(_txModeSettingsKey, activeVehicle->firmwarePlugin()->defaultJoystickTXMode()).toInt();

        setTXMode(mode);
    }
}

172 173 174
void Joystick::_loadSettings(void)
{
    QSettings   settings;
175

176
    settings.beginGroup(_settingsGroup);
177

178 179 180 181
    Vehicle* activeVehicle = _multiVehicleManager->activeVehicle();

    if(_txModeSettingsKey && activeVehicle)
        _transmitterMode = settings.value(_txModeSettingsKey, activeVehicle->firmwarePlugin()->defaultJoystickTXMode()).toInt();
182

183
    settings.beginGroup(_name);
184

185 186
    bool badSettings = false;
    bool convertOk;
187

188
    qCDebug(JoystickLog) << "_loadSettings " << _name;
189

190
    _calibrated = settings.value(_calibratedSettingsKey, false).toBool();
191
    _exponential = settings.value(_exponentialSettingsKey, 0).toFloat();
192
    _accumulator = settings.value(_accumulatorSettingsKey, false).toBool();
Gregory Dymarek's avatar
Gregory Dymarek committed
193
    _deadband = settings.value(_deadbandSettingsKey, false).toBool();
194
    _circleCorrection = settings.value(_circleCorrectionSettingsKey, false).toBool();
195

196 197
    _throttleMode = (ThrottleMode_t)settings.value(_throttleModeSettingsKey, ThrottleModeCenterZero).toInt(&convertOk);
    badSettings |= !convertOk;
198

199
    qCDebug(JoystickLog) << "_loadSettings calibrated:txmode:throttlemode:exponential:deadband:badsettings" << _calibrated << _transmitterMode << _throttleMode << _exponential << _deadband << badSettings;
200

201 202 203 204
    QString minTpl  ("Axis%1Min");
    QString maxTpl  ("Axis%1Max");
    QString trimTpl ("Axis%1Trim");
    QString revTpl  ("Axis%1Rev");
205
    QString deadbndTpl  ("Axis%1Deadbnd");
206

207
    for (int axis=0; axis<_axisCount; axis++) {
208
        Calibration_t* calibration = &_rgCalibration[axis];
209

210 211
        calibration->center = settings.value(trimTpl.arg(axis), 0).toInt(&convertOk);
        badSettings |= !convertOk;
212

213 214
        calibration->min = settings.value(minTpl.arg(axis), -32768).toInt(&convertOk);
        badSettings |= !convertOk;
215

216
        calibration->max = settings.value(maxTpl.arg(axis), 32767).toInt(&convertOk);
217
        badSettings |= !convertOk;
218

219 220 221
        calibration->deadband = settings.value(deadbndTpl.arg(axis), 0).toInt(&convertOk);
        badSettings |= !convertOk;

222
        calibration->reversed = settings.value(revTpl.arg(axis), false).toBool();
223

224

225
        qCDebug(JoystickLog) << "_loadSettings axis:min:max:trim:reversed:deadband:badsettings" << axis << calibration->min << calibration->max << calibration->center << calibration->reversed << calibration->deadband << badSettings;
226
    }
227

228 229
    for (int function=0; function<maxFunction; function++) {
        int functionAxis;
230

231 232
        functionAxis = settings.value(_rgFunctionSettingsKey[function], -1).toInt(&convertOk);
        badSettings |= !convertOk || (functionAxis == -1);
233

234
        _rgFunctionAxis[function] = functionAxis;
235

236 237
        qCDebug(JoystickLog) << "_loadSettings function:axis:badsettings" << function << functionAxis << badSettings;
    }
238

239 240 241 242
    // FunctionAxis mappings are always stored in TX mode 2
    // Remap to stored TX mode in settings
    _remapAxes(2, _transmitterMode, _rgFunctionAxis);

Don Gagne's avatar
Don Gagne committed
243
    for (int button=0; button<_totalButtonCount; button++) {
244
        _rgButtonActions << settings.value(QString(_buttonActionSettingsKey).arg(button), QString()).toString();
Don Gagne's avatar
Don Gagne committed
245
        qCDebug(JoystickLog) << "_loadSettings button:action" << button << _rgButtonActions[button];
246
    }
247

248 249 250 251 252 253 254 255 256
    if (badSettings) {
        _calibrated = false;
        settings.setValue(_calibratedSettingsKey, false);
    }
}

void Joystick::_saveSettings(void)
{
    QSettings settings;
257

258
    settings.beginGroup(_settingsGroup);
259 260 261

    // Transmitter mode is static
    // Save the mode we are using
262 263
    if(_txModeSettingsKey)
        settings.setValue(_txModeSettingsKey, _transmitterMode);
264

265
    settings.beginGroup(_name);
266

267
    settings.setValue(_calibratedSettingsKey, _calibrated);
268
    settings.setValue(_exponentialSettingsKey, _exponential);
269
    settings.setValue(_accumulatorSettingsKey, _accumulator);
Gregory Dymarek's avatar
Gregory Dymarek committed
270
    settings.setValue(_deadbandSettingsKey, _deadband);
271
    settings.setValue(_circleCorrectionSettingsKey, _circleCorrection);
272
    settings.setValue(_throttleModeSettingsKey, _throttleMode);
273

274
    qCDebug(JoystickLog) << "_saveSettings calibrated:throttlemode:deadband:txmode" << _calibrated << _throttleMode << _deadband << _circleCorrection << _transmitterMode;
275 276 277 278 279

    QString minTpl  ("Axis%1Min");
    QString maxTpl  ("Axis%1Max");
    QString trimTpl ("Axis%1Trim");
    QString revTpl  ("Axis%1Rev");
280
    QString deadbndTpl  ("Axis%1Deadbnd");
281

282
    for (int axis=0; axis<_axisCount; axis++) {
283
        Calibration_t* calibration = &_rgCalibration[axis];
284

285 286 287 288
        settings.setValue(trimTpl.arg(axis), calibration->center);
        settings.setValue(minTpl.arg(axis), calibration->min);
        settings.setValue(maxTpl.arg(axis), calibration->max);
        settings.setValue(revTpl.arg(axis), calibration->reversed);
289
        settings.setValue(deadbndTpl.arg(axis), calibration->deadband);
290

291
        qCDebug(JoystickLog) << "_saveSettings name:axis:min:max:trim:reversed:deadband"
292 293 294 295 296
                                << _name
                                << axis
                                << calibration->min
                                << calibration->max
                                << calibration->center
297 298
                                << calibration->reversed
                                << calibration->deadband;
299
    }
300

301 302 303 304 305
    // Always save function Axis mappings in TX Mode 2
    // Write mode 2 mappings without changing mapping currently in use
    int temp[maxFunction];
    _remapAxes(_transmitterMode, 2, temp);

306
    for (int function=0; function<maxFunction; function++) {
307
        settings.setValue(_rgFunctionSettingsKey[function], temp[function]);
308 309
        qCDebug(JoystickLog) << "_saveSettings name:function:axis" << _name << function << _rgFunctionSettingsKey[function];
    }
310

Don Gagne's avatar
Don Gagne committed
311
    for (int button=0; button<_totalButtonCount; button++) {
312 313 314 315 316
        settings.setValue(QString(_buttonActionSettingsKey).arg(button), _rgButtonActions[button]);
        qCDebug(JoystickLog) << "_saveSettings button:action" << button << _rgButtonActions[button];
    }
}

317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
// Relative mappings of axis functions between different TX modes
int Joystick::_mapFunctionMode(int mode, int function) {

    static const int mapping[][4] = {
        { 2, 1, 0, 3 },
        { 2, 3, 0, 1 },
        { 0, 1, 2, 3 },
        { 0, 3, 2, 1 }};

    return mapping[mode-1][function];
}

// Remap current axis functions from current TX mode to new TX mode
void Joystick::_remapAxes(int currentMode, int newMode, int (&newMapping)[maxFunction]) {
    int temp[maxFunction];

    for(int function = 0; function < maxFunction; function++) {
        temp[_mapFunctionMode(newMode, function)] = _rgFunctionAxis[_mapFunctionMode(currentMode, function)];
    }

    for(int function = 0; function < maxFunction; function++) {
        newMapping[function] = temp[function];
    }

}

void Joystick::setTXMode(int mode) {
    if(mode > 0 && mode <= 4) {
        _remapAxes(_transmitterMode, mode, _rgFunctionAxis);
        _transmitterMode = mode;
        _saveSettings();
    } else {
        qCWarning(JoystickLog) << "Invalid mode:" << mode;
    }
}

353
/// Adjust the raw axis value to the -1:1 range given calibration information
354
float Joystick::_adjustRange(int value, Calibration_t calibration, bool withDeadbands)
355 356 357 358
{
    float valueNormalized;
    float axisLength;
    float axisBasis;
359

360 361 362 363 364 365 366 367 368
    if (value > calibration.center) {
        axisBasis = 1.0f;
        valueNormalized = value - calibration.center;
        axisLength =  calibration.max - calibration.center;
    } else {
        axisBasis = -1.0f;
        valueNormalized = calibration.center - value;
        axisLength =  calibration.center - calibration.min;
    }
369

370 371
    float axisPercent;

372
    if (withDeadbands) {
373 374 375 376 377 378 379
        if (valueNormalized>calibration.deadband) {
            axisPercent = (valueNormalized - calibration.deadband) / (axisLength - calibration.deadband);
        } else if (valueNormalized<-calibration.deadband) {
            axisPercent = (valueNormalized + calibration.deadband) / (axisLength - calibration.deadband);
        } else {
            axisPercent = 0.f;
        }
380 381 382
    }
    else {
        axisPercent = valueNormalized / axisLength;
383
    }
384

385
    float correctedValue = axisBasis * axisPercent;
386

387 388 389
    if (calibration.reversed) {
        correctedValue *= -1.0f;
    }
390

391
#if 0
392
    qCDebug(JoystickLog) << "_adjustRange corrected:value:min:max:center:reversed:deadband:basis:normalized:length"
393 394 395 396 397
                            << correctedValue
                            << value
                            << calibration.min
                            << calibration.max
                            << calibration.center
398
                            << calibration.reversed
399
                            << calibration.deadband
400 401 402 403 404
                            << axisBasis
                            << valueNormalized
                            << axisLength;
#endif

405
    return std::max(-1.0f, std::min(correctedValue, 1.0f));
406 407 408 409 410
}


void Joystick::run(void)
{
Gregory Dymarek's avatar
Gregory Dymarek committed
411
    _open();
412

413
    while (!_exitThread) {
Gregory Dymarek's avatar
Gregory Dymarek committed
414
    _update();
415 416 417

        // Update axes
        for (int axisIndex=0; axisIndex<_axisCount; axisIndex++) {
Gregory Dymarek's avatar
Gregory Dymarek committed
418
            int newAxisValue = _getAxis(axisIndex);
419 420 421 422
            // Calibration code requires signal to be emitted even if value hasn't changed
            _rgAxisValues[axisIndex] = newAxisValue;
            emit rawAxisValueChanged(axisIndex, newAxisValue);
        }
423

424 425
        // Update buttons
        for (int buttonIndex=0; buttonIndex<_buttonCount; buttonIndex++) {
Gregory Dymarek's avatar
Gregory Dymarek committed
426
            bool newButtonValue = _getButton(buttonIndex);
427 428 429 430 431
            if (newButtonValue != _rgButtonValues[buttonIndex]) {
                _rgButtonValues[buttonIndex] = newButtonValue;
                emit rawButtonPressedChanged(buttonIndex, newButtonValue);
            }
        }
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446

        // Update hat - append hat buttons to the end of the normal button list
        int numHatButtons = 4;
        for (int hatIndex=0; hatIndex<_hatCount; hatIndex++) {
            for (int hatButtonIndex=0; hatButtonIndex<numHatButtons; hatButtonIndex++) {
                // Create new index value that includes the normal button list
                int rgButtonValueIndex = hatIndex*numHatButtons + hatButtonIndex + _buttonCount;
                // Get hat value from joystick
                bool newButtonValue = _getHat(hatIndex,hatButtonIndex);
                if (newButtonValue != _rgButtonValues[rgButtonValueIndex]) {
                    _rgButtonValues[rgButtonValueIndex] = newButtonValue;
                    emit rawButtonPressedChanged(rgButtonValueIndex, newButtonValue);
                }
            }
        }
447

448
        if (_outputEnabled && _calibrated) {
449
            int     axis = _rgFunctionAxis[rollFunction];
450
            float   roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _deadband);
451

452
                    axis = _rgFunctionAxis[pitchFunction];
453
            float   pitch = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _deadband);
454

455
                    axis = _rgFunctionAxis[yawFunction];
456
            float   yaw = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis],_deadband);
457

458
                    axis = _rgFunctionAxis[throttleFunction];
459
            float   throttle = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _throttleMode==ThrottleModeDownZero?false:_deadband);
460

461 462 463 464 465 466 467 468 469
            if ( _accumulator ) {
                static float throttle_accu = 0.f;

                throttle_accu += throttle*(40/1000.f); //for throttle to change from min to max it will take 1000ms (40ms is a loop time)

                throttle_accu = std::max(static_cast<float>(-1.f), std::min(throttle_accu, static_cast<float>(1.f)));
                throttle = throttle_accu;
            }

470 471 472 473 474 475 476 477 478 479 480 481 482
            if ( _circleCorrection ) {
                float roll_limited = std::max(static_cast<float>(-M_PI_4), std::min(roll, static_cast<float>(M_PI_4)));
                float pitch_limited = std::max(static_cast<float>(-M_PI_4), std::min(pitch, static_cast<float>(M_PI_4)));
                float yaw_limited = std::max(static_cast<float>(-M_PI_4), std::min(yaw, static_cast<float>(M_PI_4)));
                float throttle_limited = std::max(static_cast<float>(-M_PI_4), std::min(throttle, static_cast<float>(M_PI_4)));

                // Map from unit circle to linear range and limit
                roll =      std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f));
                pitch =     std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f));
                yaw =       std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f));
                throttle =  std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f));
            }

483
            if ( _exponential != 0 ) {
484
                // Exponential (0% to -50% range like most RC radios)
nanthony21's avatar
nanthony21 committed
485
                //_exponential is set by a slider in joystickConfig.qml
486 487

                // Calculate new RPY with exponential applied
488 489 490
                roll =      -_exponential*powf(roll,3) + (1+_exponential)*roll;
                pitch =     -_exponential*powf(pitch,3) + (1+_exponential)*pitch;
                yaw =       -_exponential*powf(yaw,3) + (1+_exponential)*yaw;
491
            }
492

493
            // Adjust throttle to 0:1 range
494
            if (_throttleMode == ThrottleModeCenterZero && _activeVehicle->supportsThrottleModeCenterZero()) {
495
                if (!_activeVehicle->supportsNegativeThrust() || !_negativeThrust) {
496 497
                    throttle = std::max(0.0f, throttle);
                }
498
            } else {
499 500
                throttle = (throttle + 1.0f) / 2.0f;
            }
501

502
            // Set up button pressed information
503

504
            // We only send the buttons the firmwware has reserved
505
            int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount();
506
            if (reservedButtonCount == -1) {
507
                reservedButtonCount = _totalButtonCount;
508
            }
509

510 511
            quint16 newButtonBits = 0;      // New set of button which are down
            quint16 buttonPressedBits = 0;  // Buttons pressed for manualControl signal
512

513
            for (int buttonIndex=0; buttonIndex<_totalButtonCount; buttonIndex++) {
514
                quint16 buttonBit = 1 << buttonIndex;
515

516 517
                if (!_rgButtonValues[buttonIndex]) {
                    // Button up, just record it
518 519 520
                    newButtonBits |= buttonBit;
                } else {
                    if (_lastButtonBits & buttonBit) {
521
                        // Button was up last time through, but is now down which indicates a button press
522
                        qCDebug(JoystickLog) << "button triggered" << buttonIndex;
523

524 525
                        if (buttonIndex >= reservedButtonCount) {
                            // Button is above firmware reserved set
Don Gagne's avatar
Don Gagne committed
526 527 528
                            QString buttonAction =_rgButtonActions[buttonIndex];
                            if (!buttonAction.isEmpty()) {
                                _buttonAction(buttonAction);
529 530 531
                            }
                        }
                    }
532 533

                    // Mark the button as pressed as long as its pressed
534
                    buttonPressedBits |= buttonBit;
535 536
                }
            }
537

538
            _lastButtonBits = newButtonBits;
539

540
            qCDebug(JoystickValuesLog) << "name:roll:pitch:yaw:throttle" << name() << roll << -pitch << yaw << throttle;
541

542
            emit manualControl(roll, -pitch, yaw, throttle, buttonPressedBits, _activeVehicle->joystickMode());
543
        }
544

545 546 547
        // Sleep, update rate of joystick is approx. 25 Hz (1000 ms / 25 = 40 ms)
        QGC::SLEEP::msleep(40);
    }
548

Gregory Dymarek's avatar
Gregory Dymarek committed
549
    _close();
550 551
}

552
void Joystick::startPolling(Vehicle* vehicle)
553
{
554 555 556 557 558 559
    if (vehicle) {

        // If a vehicle is connected, disconnect it
        if (_activeVehicle) {
            UAS* uas = _activeVehicle->uas();
            disconnect(this, &Joystick::manualControl, uas, &UAS::setExternalControlSetpoint);
560
        }
561 562

        // Always set up the new vehicle
563
        _activeVehicle = vehicle;
564

565 566 567 568 569
        // If joystick is not calibrated, disable it
        if ( !_calibrated ) {
            vehicle->setJoystickEnabled(false);
        }

Jacob Walser's avatar
Jacob Walser committed
570 571 572
        // Update qml in case of joystick transition
        emit calibratedChanged(_calibrated);

573 574 575 576 577 578 579 580 581 582 583 584 585
        // Only connect the new vehicle if it wants joystick data
        if (vehicle->joystickEnabled()) {
            _pollingStartedForCalibration = false;

            UAS* uas = _activeVehicle->uas();
            connect(this, &Joystick::manualControl, uas, &UAS::setExternalControlSetpoint);
            // FIXME: ****
            //connect(this, &Joystick::buttonActionTriggered, uas, &UAS::triggerAction);
        }
    }


    if (!isRunning()) {
586 587
        _exitThread = false;
        start();
588 589 590 591 592
    }
}

void Joystick::stopPolling(void)
{
593
    if (isRunning()) {
594 595 596

        if (_activeVehicle && _activeVehicle->joystickEnabled()) {
            UAS* uas = _activeVehicle->uas();
Jacob Walser's avatar
Jacob Walser committed
597 598
            // Neutral attitude controls
            // emit manualControl(0, 0, 0, 0.5, 0, _activeVehicle->joystickMode());
599 600
            disconnect(this, &Joystick::manualControl,          uas, &UAS::setExternalControlSetpoint);
        }
Don Gagne's avatar
Don Gagne committed
601 602
        // FIXME: ****
        //disconnect(this, &Joystick::buttonActionTriggered,  uas, &UAS::triggerAction);
603

604
        _exitThread = true;
Jacob Walser's avatar
Jacob Walser committed
605
    }
606 607 608 609
}

void Joystick::setCalibration(int axis, Calibration_t& calibration)
{
610
    if (!_validAxis(axis)) {
611 612 613
        qCWarning(JoystickLog) << "Invalid axis index" << axis;
        return;
    }
614

615 616 617 618 619 620 621 622
    _calibrated = true;
    _rgCalibration[axis] = calibration;
    _saveSettings();
    emit calibratedChanged(_calibrated);
}

Joystick::Calibration_t Joystick::getCalibration(int axis)
{
623
    if (!_validAxis(axis)) {
624 625
        qCWarning(JoystickLog) << "Invalid axis index" << axis;
    }
626

627 628 629 630 631
    return _rgCalibration[axis];
}

void Joystick::setFunctionAxis(AxisFunction_t function, int axis)
{
632
    if (!_validAxis(axis)) {
633 634 635 636 637 638
        qCWarning(JoystickLog) << "Invalid axis index" << axis;
        return;
    }

    _calibrated = true;
    _rgFunctionAxis[function] = axis;
639

640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
    _saveSettings();
    emit calibratedChanged(_calibrated);
}

int Joystick::getFunctionAxis(AxisFunction_t function)
{
    if (function < 0 || function >= maxFunction) {
        qCWarning(JoystickLog) << "Invalid function" << function;
    }

    return _rgFunctionAxis[function];
}

QStringList Joystick::actions(void)
{
    QStringList list;
Don Gagne's avatar
Don Gagne committed
656

657
    list << _buttonActionArm << _buttonActionDisarm;
658 659 660 661

    if (_activeVehicle) {
        list << _activeVehicle->flightModes();
    }
662
    list << _buttonActionVTOLFixedWing << _buttonActionVTOLMultiRotor;
663

664 665 666
    return list;
}

Don Gagne's avatar
Don Gagne committed
667
void Joystick::setButtonAction(int button, const QString& action)
668
{
669
    if (!_validButton(button)) {
670 671 672
        qCWarning(JoystickLog) << "Invalid button index" << button;
        return;
    }
673

Don Gagne's avatar
Don Gagne committed
674
    qDebug() << "setButtonAction" << action;
675

676 677 678 679 680
    _rgButtonActions[button] = action;
    _saveSettings();
    emit buttonActionsChanged(buttonActions());
}

Don Gagne's avatar
Don Gagne committed
681
QString Joystick::getButtonAction(int button)
682
{
683
    if (!_validButton(button)) {
684 685
        qCWarning(JoystickLog) << "Invalid button index" << button;
    }
686

687 688 689 690 691 692
    return _rgButtonActions[button];
}

QVariantList Joystick::buttonActions(void)
{
    QVariantList list;
693

Don Gagne's avatar
Don Gagne committed
694
    for (int button=0; button<_totalButtonCount; button++) {
695 696
        list += QVariant::fromValue(_rgButtonActions[button]);
    }
697

698 699 700 701 702 703 704 705 706 707 708 709 710 711
    return list;
}

int Joystick::throttleMode(void)
{
    return _throttleMode;
}

void Joystick::setThrottleMode(int mode)
{
    if (mode < 0 || mode >= ThrottleModeMax) {
        qCWarning(JoystickLog) << "Invalid throttle mode" << mode;
        return;
    }
712

713
    _throttleMode = (ThrottleMode_t)mode;
714 715 716 717 718

    if (_throttleMode == ThrottleModeDownZero) {
        setAccumulator(false);
    }

719 720 721 722
    _saveSettings();
    emit throttleModeChanged(_throttleMode);
}

723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
bool Joystick::negativeThrust(void)
{
    return _negativeThrust;
}

void Joystick::setNegativeThrust(bool allowNegative)
{
    if (_negativeThrust == allowNegative) {
        return;
    }
    _negativeThrust = allowNegative;

    _saveSettings();
    emit negativeThrustChanged(_negativeThrust);
}

739
float Joystick::exponential(void)
740 741 742 743
{
    return _exponential;
}

744
void Joystick::setExponential(float expo)
745 746 747 748 749 750 751
{
    _exponential = expo;

    _saveSettings();
    emit exponentialChanged(_exponential);
}

752 753 754 755 756 757 758 759 760 761 762 763 764
bool Joystick::accumulator(void)
{
    return _accumulator;
}

void Joystick::setAccumulator(bool accu)
{
    _accumulator = accu;

    _saveSettings();
    emit accumulatorChanged(_accumulator);
}

Gregory Dymarek's avatar
Gregory Dymarek committed
765 766 767 768 769 770 771 772 773 774 775 776
bool Joystick::deadband(void)
{
    return _deadband;
}

void Joystick::setDeadband(bool deadband)
{
    _deadband = deadband;

    _saveSettings();
}

777 778 779 780 781 782 783 784 785 786 787 788 789
bool Joystick::circleCorrection(void)
{
    return _circleCorrection;
}

void Joystick::setCircleCorrection(bool circleCorrection)
{
    _circleCorrection = circleCorrection;

    _saveSettings();
    emit circleCorrectionChanged(_circleCorrection);
}

790
void Joystick::setCalibrationMode(bool calibrating)
791
{
792
    _calibrationMode = calibrating;
793

794
    if (calibrating && !isRunning()) {
795
        _pollingStartedForCalibration = true;
796
        startPolling(_multiVehicleManager->activeVehicle());
797
    }
798 799
    else if (_pollingStartedForCalibration) {
        stopPolling();
Don Gagne's avatar
Don Gagne committed
800
    }
801 802
    if (calibrating){
        setOutputEnabled(false); //Disable the joystick output before calibrating
803
    }
804 805 806 807 808 809 810 811
    else if (!calibrating && _calibrated){
        setOutputEnabled(true); //Enable joystick output after calibration
    }
}

void Joystick::setOutputEnabled(bool enabled){
    _outputEnabled = enabled;
    emit outputEnabledChanged(_outputEnabled);
812
}
813

Don Gagne's avatar
Don Gagne committed
814 815
void Joystick::_buttonAction(const QString& action)
{
816 817 818 819
    if (!_activeVehicle || !_activeVehicle->joystickEnabled()) {
        return;
    }

820
    if (action == _buttonActionArm) {
Don Gagne's avatar
Don Gagne committed
821
        _activeVehicle->setArmed(true);
822
    } else if (action == _buttonActionDisarm) {
Don Gagne's avatar
Don Gagne committed
823
        _activeVehicle->setArmed(false);
824 825 826 827
    } else if (action == _buttonActionVTOLFixedWing) {
        _activeVehicle->setVtolInFwdFlight(true);
    } else if (action == _buttonActionVTOLMultiRotor) {
        _activeVehicle->setVtolInFwdFlight(false);
828 829
    } else if (_activeVehicle->flightModes().contains(action)) {
        _activeVehicle->setFlightMode(action);
Don Gagne's avatar
Don Gagne committed
830 831 832 833 834
    } else {
        qCDebug(JoystickLog) << "_buttonAction unknown action:" << action;
    }
}

835 836 837 838 839 840 841
bool Joystick::_validAxis(int axis)
{
    return axis >= 0 && axis < _axisCount;
}

bool Joystick::_validButton(int button)
{
842
    return button >= 0 && button < _totalButtonCount;
843 844
}