Joystick.cc 28 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
const char* Joystick::_frequencySettingsKey =           "Frequency";
30 31 32 33 34 35
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";
36

37 38 39 40 41
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");

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

49 50
int Joystick::_transmitterMode = 2;

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

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

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

87 88
    _updateTXModeSettingsKey(_multiVehicleManager->activeVehicle());

89
    _loadSettings();
90 91

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

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

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

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
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;

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

128
    _exponential = 0;
129 130
    _accumulator = false;
    _deadband = false;
131
    _circleCorrection = false;
132
    _frequency = 25.0f;
133 134 135 136 137 138
    _throttleMode = ThrottleModeCenterZero;
    _calibrated = true;

    _saveSettings();
}

139
void Joystick::_updateTXModeSettingsKey(Vehicle* activeVehicle)
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
{
    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;
        }
157 158 159 160
    } else {
        _txModeSettingsKey = NULL;
    }
}
161

162 163 164 165 166
void Joystick::_activeVehicleChanged(Vehicle* activeVehicle)
{
    _updateTXModeSettingsKey(activeVehicle);

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

        setTXMode(mode);
    }
}

175 176 177
void Joystick::_loadSettings(void)
{
    QSettings   settings;
178

179
    settings.beginGroup(_settingsGroup);
180

181 182 183 184
    Vehicle* activeVehicle = _multiVehicleManager->activeVehicle();

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

186
    settings.beginGroup(_name);
187

188 189
    bool badSettings = false;
    bool convertOk;
190

191
    qCDebug(JoystickLog) << "_loadSettings " << _name;
192

193
    _calibrated = settings.value(_calibratedSettingsKey, false).toBool();
194
    _exponential = settings.value(_exponentialSettingsKey, 0).toFloat();
195
    _accumulator = settings.value(_accumulatorSettingsKey, false).toBool();
Gregory Dymarek's avatar
Gregory Dymarek committed
196
    _deadband = settings.value(_deadbandSettingsKey, false).toBool();
197
    _circleCorrection = settings.value(_circleCorrectionSettingsKey, false).toBool();
198
    _frequency = settings.value(_frequencySettingsKey, 25.0f).toFloat();
199

200 201
    _throttleMode = (ThrottleMode_t)settings.value(_throttleModeSettingsKey, ThrottleModeCenterZero).toInt(&convertOk);
    badSettings |= !convertOk;
202

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

205 206 207 208
    QString minTpl  ("Axis%1Min");
    QString maxTpl  ("Axis%1Max");
    QString trimTpl ("Axis%1Trim");
    QString revTpl  ("Axis%1Rev");
209
    QString deadbndTpl  ("Axis%1Deadbnd");
210

211
    for (int axis=0; axis<_axisCount; axis++) {
212
        Calibration_t* calibration = &_rgCalibration[axis];
213

214 215
        calibration->center = settings.value(trimTpl.arg(axis), 0).toInt(&convertOk);
        badSettings |= !convertOk;
216

217 218
        calibration->min = settings.value(minTpl.arg(axis), -32768).toInt(&convertOk);
        badSettings |= !convertOk;
219

220
        calibration->max = settings.value(maxTpl.arg(axis), 32767).toInt(&convertOk);
221
        badSettings |= !convertOk;
222

223 224 225
        calibration->deadband = settings.value(deadbndTpl.arg(axis), 0).toInt(&convertOk);
        badSettings |= !convertOk;

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

228

229
        qCDebug(JoystickLog) << "_loadSettings axis:min:max:trim:reversed:deadband:badsettings" << axis << calibration->min << calibration->max << calibration->center << calibration->reversed << calibration->deadband << badSettings;
230
    }
231

232 233
    for (int function=0; function<maxFunction; function++) {
        int functionAxis;
234

235 236
        functionAxis = settings.value(_rgFunctionSettingsKey[function], -1).toInt(&convertOk);
        badSettings |= !convertOk || (functionAxis == -1);
237

238
        _rgFunctionAxis[function] = functionAxis;
239

240 241
        qCDebug(JoystickLog) << "_loadSettings function:axis:badsettings" << function << functionAxis << badSettings;
    }
242

243 244 245 246
    // 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
247
    for (int button=0; button<_totalButtonCount; button++) {
248
        _rgButtonActions << settings.value(QString(_buttonActionSettingsKey).arg(button), QString()).toString();
Don Gagne's avatar
Don Gagne committed
249
        qCDebug(JoystickLog) << "_loadSettings button:action" << button << _rgButtonActions[button];
250
    }
251

252 253 254 255 256 257 258 259 260
    if (badSettings) {
        _calibrated = false;
        settings.setValue(_calibratedSettingsKey, false);
    }
}

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

262
    settings.beginGroup(_settingsGroup);
263 264 265

    // Transmitter mode is static
    // Save the mode we are using
266 267
    if(_txModeSettingsKey)
        settings.setValue(_txModeSettingsKey, _transmitterMode);
268

269
    settings.beginGroup(_name);
270

271
    settings.setValue(_calibratedSettingsKey, _calibrated);
272
    settings.setValue(_exponentialSettingsKey, _exponential);
273
    settings.setValue(_accumulatorSettingsKey, _accumulator);
Gregory Dymarek's avatar
Gregory Dymarek committed
274
    settings.setValue(_deadbandSettingsKey, _deadband);
275
    settings.setValue(_circleCorrectionSettingsKey, _circleCorrection);
276
    settings.setValue(_frequencySettingsKey, _frequency);
277
    settings.setValue(_throttleModeSettingsKey, _throttleMode);
278

279
    qCDebug(JoystickLog) << "_saveSettings calibrated:throttlemode:deadband:txmode" << _calibrated << _throttleMode << _deadband << _circleCorrection << _transmitterMode;
280 281 282 283 284

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

287
    for (int axis=0; axis<_axisCount; axis++) {
288
        Calibration_t* calibration = &_rgCalibration[axis];
289

290 291 292 293
        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);
294
        settings.setValue(deadbndTpl.arg(axis), calibration->deadband);
295

296
        qCDebug(JoystickLog) << "_saveSettings name:axis:min:max:trim:reversed:deadband"
297 298 299 300 301
                                << _name
                                << axis
                                << calibration->min
                                << calibration->max
                                << calibration->center
302 303
                                << calibration->reversed
                                << calibration->deadband;
304
    }
305

306 307 308 309 310
    // 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);

311
    for (int function=0; function<maxFunction; function++) {
312
        settings.setValue(_rgFunctionSettingsKey[function], temp[function]);
313 314
        qCDebug(JoystickLog) << "_saveSettings name:function:axis" << _name << function << _rgFunctionSettingsKey[function];
    }
315

Don Gagne's avatar
Don Gagne committed
316
    for (int button=0; button<_totalButtonCount; button++) {
317 318 319 320 321
        settings.setValue(QString(_buttonActionSettingsKey).arg(button), _rgButtonActions[button]);
        qCDebug(JoystickLog) << "_saveSettings button:action" << button << _rgButtonActions[button];
    }
}

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 353 354 355 356 357
// 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;
    }
}

358
/// Adjust the raw axis value to the -1:1 range given calibration information
359
float Joystick::_adjustRange(int value, Calibration_t calibration, bool withDeadbands)
360 361 362 363
{
    float valueNormalized;
    float axisLength;
    float axisBasis;
364

365 366 367 368 369 370 371 372 373
    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;
    }
374

375 376
    float axisPercent;

377
    if (withDeadbands) {
378 379 380 381 382 383 384
        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;
        }
385 386 387
    }
    else {
        axisPercent = valueNormalized / axisLength;
388
    }
389

390
    float correctedValue = axisBasis * axisPercent;
391

392 393 394
    if (calibration.reversed) {
        correctedValue *= -1.0f;
    }
395

396
#if 0
397
    qCDebug(JoystickLog) << "_adjustRange corrected:value:min:max:center:reversed:deadband:basis:normalized:length"
398 399 400 401 402
                            << correctedValue
                            << value
                            << calibration.min
                            << calibration.max
                            << calibration.center
403
                            << calibration.reversed
404
                            << calibration.deadband
405 406 407 408 409
                            << axisBasis
                            << valueNormalized
                            << axisLength;
#endif

410
    return std::max(-1.0f, std::min(correctedValue, 1.0f));
411 412 413 414 415
}


void Joystick::run(void)
{
Gregory Dymarek's avatar
Gregory Dymarek committed
416
    _open();
417

418
    while (!_exitThread) {
Gregory Dymarek's avatar
Gregory Dymarek committed
419
    _update();
420 421 422

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

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

        // 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);
                }
            }
        }
452

453
        if (_activeVehicle->joystickEnabled() && !_calibrationMode && _calibrated) {
454
            int     axis = _rgFunctionAxis[rollFunction];
455
            float   roll = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _deadband);
456

457
                    axis = _rgFunctionAxis[pitchFunction];
458
            float   pitch = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _deadband);
459

460
                    axis = _rgFunctionAxis[yawFunction];
461
            float   yaw = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis],_deadband);
462

463
                    axis = _rgFunctionAxis[throttleFunction];
464
            float   throttle = _adjustRange(_rgAxisValues[axis], _rgCalibration[axis], _throttleMode==ThrottleModeDownZero?false:_deadband);
465

466 467 468 469 470 471 472 473 474
            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;
            }

475 476 477 478 479 480 481 482 483 484 485 486 487
            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));
            }

488
            if ( _exponential != 0 ) {
489
                // Exponential (0% to -50% range like most RC radios)
nanthony21's avatar
nanthony21 committed
490
                //_exponential is set by a slider in joystickConfig.qml
491 492

                // Calculate new RPY with exponential applied
493 494 495
                roll =      -_exponential*powf(roll,3) + (1+_exponential)*roll;
                pitch =     -_exponential*powf(pitch,3) + (1+_exponential)*pitch;
                yaw =       -_exponential*powf(yaw,3) + (1+_exponential)*yaw;
496
            }
497

498
            // Adjust throttle to 0:1 range
499
            if (_throttleMode == ThrottleModeCenterZero && _activeVehicle->supportsThrottleModeCenterZero()) {
500
                if (!_activeVehicle->supportsNegativeThrust() || !_negativeThrust) {
501 502
                    throttle = std::max(0.0f, throttle);
                }
503
            } else {
504 505
                throttle = (throttle + 1.0f) / 2.0f;
            }
506

507
            // Set up button pressed information
508

509
            // We only send the buttons the firmwware has reserved
510
            int reservedButtonCount = _activeVehicle->manualControlReservedButtonCount();
511
            if (reservedButtonCount == -1) {
512
                reservedButtonCount = _totalButtonCount;
513
            }
514

515 516
            quint16 newButtonBits = 0;      // New set of button which are down
            quint16 buttonPressedBits = 0;  // Buttons pressed for manualControl signal
517

518
            for (int buttonIndex=0; buttonIndex<_totalButtonCount; buttonIndex++) {
519
                quint16 buttonBit = 1 << buttonIndex;
520

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

529 530
                        if (buttonIndex >= reservedButtonCount) {
                            // Button is above firmware reserved set
Don Gagne's avatar
Don Gagne committed
531 532 533
                            QString buttonAction =_rgButtonActions[buttonIndex];
                            if (!buttonAction.isEmpty()) {
                                _buttonAction(buttonAction);
534 535 536
                            }
                        }
                    }
537 538

                    // Mark the button as pressed as long as its pressed
539
                    buttonPressedBits |= buttonBit;
540 541
                }
            }
542

543
            _lastButtonBits = newButtonBits;
544

545
            qCDebug(JoystickValuesLog) << "name:roll:pitch:yaw:throttle" << name() << roll << -pitch << yaw << throttle;
546

547
            emit manualControl(roll, -pitch, yaw, throttle, buttonPressedBits, _activeVehicle->joystickMode());
548
        }
549

550 551 552
        // Sleep. Update rate of joystick is by default 25 Hz
        int mswait = (int)(1000.0f / _frequency);
        QGC::SLEEP::msleep(mswait);
553
    }
554

Gregory Dymarek's avatar
Gregory Dymarek committed
555
    _close();
556 557
}

558
void Joystick::startPolling(Vehicle* vehicle)
559
{
560 561 562 563 564 565
    if (vehicle) {

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

        // Always set up the new vehicle
569
        _activeVehicle = vehicle;
570

571 572 573 574 575
        // If joystick is not calibrated, disable it
        if ( !_calibrated ) {
            vehicle->setJoystickEnabled(false);
        }

Jacob Walser's avatar
Jacob Walser committed
576 577 578
        // Update qml in case of joystick transition
        emit calibratedChanged(_calibrated);

579 580 581 582 583 584 585 586 587 588 589 590 591
        // 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()) {
592 593
        _exitThread = false;
        start();
594 595 596 597 598
    }
}

void Joystick::stopPolling(void)
{
599
    if (isRunning()) {
600 601 602

        if (_activeVehicle && _activeVehicle->joystickEnabled()) {
            UAS* uas = _activeVehicle->uas();
Jacob Walser's avatar
Jacob Walser committed
603 604
            // Neutral attitude controls
            // emit manualControl(0, 0, 0, 0.5, 0, _activeVehicle->joystickMode());
605 606
            disconnect(this, &Joystick::manualControl,          uas, &UAS::setExternalControlSetpoint);
        }
Don Gagne's avatar
Don Gagne committed
607 608
        // FIXME: ****
        //disconnect(this, &Joystick::buttonActionTriggered,  uas, &UAS::triggerAction);
609

610
        _exitThread = true;
Jacob Walser's avatar
Jacob Walser committed
611
    }
612 613 614 615
}

void Joystick::setCalibration(int axis, Calibration_t& calibration)
{
616
    if (!_validAxis(axis)) {
617 618 619
        qCWarning(JoystickLog) << "Invalid axis index" << axis;
        return;
    }
620

621 622 623 624 625 626 627 628
    _calibrated = true;
    _rgCalibration[axis] = calibration;
    _saveSettings();
    emit calibratedChanged(_calibrated);
}

Joystick::Calibration_t Joystick::getCalibration(int axis)
{
629
    if (!_validAxis(axis)) {
630 631
        qCWarning(JoystickLog) << "Invalid axis index" << axis;
    }
632

633 634 635 636 637
    return _rgCalibration[axis];
}

void Joystick::setFunctionAxis(AxisFunction_t function, int axis)
{
638
    if (!_validAxis(axis)) {
639 640 641 642 643 644
        qCWarning(JoystickLog) << "Invalid axis index" << axis;
        return;
    }

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

646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
    _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
662

663
    list << _buttonActionArm << _buttonActionDisarm;
664 665 666 667

    if (_activeVehicle) {
        list << _activeVehicle->flightModes();
    }
668
    list << _buttonActionVTOLFixedWing << _buttonActionVTOLMultiRotor;
669

670 671 672
    return list;
}

Don Gagne's avatar
Don Gagne committed
673
void Joystick::setButtonAction(int button, const QString& action)
674
{
675
    if (!_validButton(button)) {
676 677 678
        qCWarning(JoystickLog) << "Invalid button index" << button;
        return;
    }
679

Don Gagne's avatar
Don Gagne committed
680
    qDebug() << "setButtonAction" << action;
681

682 683 684 685 686
    _rgButtonActions[button] = action;
    _saveSettings();
    emit buttonActionsChanged(buttonActions());
}

Don Gagne's avatar
Don Gagne committed
687
QString Joystick::getButtonAction(int button)
688
{
689
    if (!_validButton(button)) {
690 691
        qCWarning(JoystickLog) << "Invalid button index" << button;
    }
692

693 694 695 696 697 698
    return _rgButtonActions[button];
}

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

Don Gagne's avatar
Don Gagne committed
700
    for (int button=0; button<_totalButtonCount; button++) {
701 702
        list += QVariant::fromValue(_rgButtonActions[button]);
    }
703

704 705 706 707 708 709 710 711 712 713 714 715 716 717
    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;
    }
718

719
    _throttleMode = (ThrottleMode_t)mode;
720 721 722 723 724

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

725 726 727 728
    _saveSettings();
    emit throttleModeChanged(_throttleMode);
}

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
bool Joystick::negativeThrust(void)
{
    return _negativeThrust;
}

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

    _saveSettings();
    emit negativeThrustChanged(_negativeThrust);
}

745
float Joystick::exponential(void)
746 747 748 749
{
    return _exponential;
}

750
void Joystick::setExponential(float expo)
751 752 753 754 755 756 757
{
    _exponential = expo;

    _saveSettings();
    emit exponentialChanged(_exponential);
}

758 759 760 761 762 763 764 765 766 767 768 769 770
bool Joystick::accumulator(void)
{
    return _accumulator;
}

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

    _saveSettings();
    emit accumulatorChanged(_accumulator);
}

Gregory Dymarek's avatar
Gregory Dymarek committed
771 772 773 774 775 776 777 778 779 780 781 782
bool Joystick::deadband(void)
{
    return _deadband;
}

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

    _saveSettings();
}

783 784 785 786 787 788 789 790 791 792 793 794 795
bool Joystick::circleCorrection(void)
{
    return _circleCorrection;
}

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

    _saveSettings();
    emit circleCorrectionChanged(_circleCorrection);
}

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
float Joystick::frequency()
{
    return _frequency;
}

void Joystick::setFrequency(float val)
{
    //-- Arbitrary limits
    if(val < 0.25f)  val = 0.25f;
    if(val > 100.0f) val = 100.0f;
    _frequency = val;
    _saveSettings();
    emit frequencyChanged();
}

811
void Joystick::setCalibrationMode(bool calibrating)
812
{
813
    _calibrationMode = calibrating;
814

815
    if (calibrating && !isRunning()) {
816
        _pollingStartedForCalibration = true;
817
        startPolling(_multiVehicleManager->activeVehicle());
818
    }
819 820
    else if (_pollingStartedForCalibration) {
        stopPolling();
Don Gagne's avatar
Don Gagne committed
821
    }
822 823
}

824

Don Gagne's avatar
Don Gagne committed
825 826
void Joystick::_buttonAction(const QString& action)
{
827 828 829 830
    if (!_activeVehicle || !_activeVehicle->joystickEnabled()) {
        return;
    }

831
    if (action == _buttonActionArm) {
Don Gagne's avatar
Don Gagne committed
832
        _activeVehicle->setArmed(true);
833
    } else if (action == _buttonActionDisarm) {
Don Gagne's avatar
Don Gagne committed
834
        _activeVehicle->setArmed(false);
835 836 837 838
    } else if (action == _buttonActionVTOLFixedWing) {
        _activeVehicle->setVtolInFwdFlight(true);
    } else if (action == _buttonActionVTOLMultiRotor) {
        _activeVehicle->setVtolInFwdFlight(false);
839 840
    } else if (_activeVehicle->flightModes().contains(action)) {
        _activeVehicle->setFlightMode(action);
Don Gagne's avatar
Don Gagne committed
841 842 843 844 845
    } else {
        qCDebug(JoystickLog) << "_buttonAction unknown action:" << action;
    }
}

846 847 848 849 850 851 852
bool Joystick::_validAxis(int axis)
{
    return axis >= 0 && axis < _axisCount;
}

bool Joystick::_validButton(int button)
{
853
    return button >= 0 && button < _totalButtonCount;
854 855
}