RadioConfigTest.cc 30 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

Don Gagne's avatar
Don Gagne committed
11
#include "RadioConfigTest.h"
12
#include "RadioComponentController.h"
13
#include "MultiVehicleManager.h"
14
#include "QGCApplication.h"
15 16

/// @file
17
///     @brief QRadioComponentController Widget unit test
18 19 20
///
///     @author Don Gagne <don@thegagnes.com>

21
QGC_LOGGING_CATEGORY(RadioConfigTestLog, "RadioConfigTestLog")
Don Gagne's avatar
Don Gagne committed
22

23 24 25 26
// This will check for the wizard buttons being enabled of disabled according to the mask you pass in.
// We use a macro instead of a method so that we get better line number reporting on failure.
#define CHK_BUTTONS(mask) \
{ \
27 28 29 30
    if (_controller->_nextButton->isEnabled() != !!((mask) & nextButtonMask) || \
        _controller->_skipButton->isEnabled() != !!((mask) & skipButtonMask) || \
        _controller->_cancelButton->isEnabled() != !!((mask) & cancelButtonMask) ) { \
        qCDebug(RadioConfigTestLog) << _controller->_statusText->property("text"); \
31
    } \
32 33 34
    QCOMPARE(_controller->_nextButton->isEnabled(), !!((mask) & nextButtonMask)); \
    QCOMPARE(_controller->_skipButton->isEnabled(), !!((mask) & skipButtonMask)); \
    QCOMPARE(_controller->_cancelButton->isEnabled(), !!((mask) & cancelButtonMask)); \
35 36 37 38 39 40
}

// This allows you to write unit tests which will click the Cancel button the first time through, followed
// by the Next button on the second iteration.
#define NEXT_OR_CANCEL(cancelNum) \
{ \
Don Gagne's avatar
Don Gagne committed
41
    if (mode == testModeStandalone && tryCancel ## cancelNum) { \
42
        QTest::mouseClick(_cancelButton, Qt::LeftButton); \
43
        QCOMPARE(_controller->_rcCalState, RadioComponentController::rcCalStateChannelWait); \
44 45 46 47 48 49 50
        tryCancel ## cancelNum = false; \
        goto StartOver; \
    } else { \
        QTest::mouseClick(_nextButton, Qt::LeftButton); \
    } \
}

51
const int RadioConfigTest::_stickSettleWait = RadioComponentController::_stickDetectSettleMSecs * 1.5;
Don Gagne's avatar
Don Gagne committed
52

53 54 55
const int RadioConfigTest::_testMinValue = RadioComponentController::_rcCalPWMDefaultMinValue + 10;
const int RadioConfigTest::_testMaxValue = RadioComponentController::_rcCalPWMDefaultMaxValue - 10;
const int RadioConfigTest::_testCenterValue = RadioConfigTest::_testMinValue + ((RadioConfigTest::_testMaxValue - RadioConfigTest::_testMinValue) / 2);
Don Gagne's avatar
Don Gagne committed
56

Don Gagne's avatar
Don Gagne committed
57
const struct RadioConfigTest::ChannelSettings RadioConfigTest::_rgChannelSettingsPX4[RadioComponentController::_chanMaxPX4] = {
Don Gagne's avatar
Don Gagne committed
58
	// Function										Min                 Max                 #  Reversed
59 60
	
	// Channel 0 : Not mapped to function, Simulate invalid Min/Max
61
	{ RadioComponentController::rcCalFunctionMax,			_testCenterValue,	_testCenterValue,   0, false },
62
	
63
    // Channels 1-4: Mapped to attitude control function
64 65 66 67
    { RadioComponentController::rcCalFunctionRoll,			_testMinValue,      _testMaxValue,      0, true },
    { RadioComponentController::rcCalFunctionPitch,			_testMinValue,      _testMaxValue,      0, false },
    { RadioComponentController::rcCalFunctionYaw,			_testMinValue,      _testMaxValue,      0, true },
    { RadioComponentController::rcCalFunctionThrottle,		_testMinValue,      _testMaxValue,      0,  false },
68
    
69
    // Channels 5-11: Not mapped to function, Simulate invalid Min/Max, since available channel Min/Max is still shown.
70
    // These are here to skip over the flight mode functions
71 72 73 74
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
75 76 77
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
78 79
	
    // Channel 12 : Not mapped to function, Simulate invalid Min, valid Max
80
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,	_testMaxValue,      0,  false },
81 82
    
	// Channel 13 : Not mapped to function, Simulate valid Min, invalid Max
83
	{ RadioComponentController::rcCalFunctionMax,           _testMinValue,      _testCenterValue,   0,	false },
84 85
	
    // Channels 14-17: Not mapped to function, Simulate invalid Min/Max, since available channel Min/Max is still shown
86 87 88 89
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
	{ RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
	{ RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
Don Gagne's avatar
Don Gagne committed
90 91
};

Don Gagne's avatar
Don Gagne committed
92
// Note the: 1500/*RadioComponentController::_rcCalPWMCenterPoint*/ entries. For some reason I couldn't get the compiler to do the
93
// right thing with the constant. So I just hacked inthe real value instead of fighting with it any longer.
Don Gagne's avatar
Don Gagne committed
94
const struct RadioConfigTest::ChannelSettings RadioConfigTest::_rgChannelSettingsValidatePX4[RadioComponentController::_chanMaxPX4] = {
Don Gagne's avatar
Don Gagne committed
95
    // Function										Min Value									Max Value									Trim Value										Reversed
96
	
97
    // Channels 0: not mapped and should be set to defaults
98
	{ RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
99
	
100
    // Channels 1-4: Mapped to attitude control function
101 102 103 104
	{ RadioComponentController::rcCalFunctionRoll,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               true },
    { RadioComponentController::rcCalFunctionPitch,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               false },
    { RadioComponentController::rcCalFunctionYaw,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               true },
    { RadioComponentController::rcCalFunctionThrottle,		_testMinValue,                              _testMaxValue,                              _testMinValue,                                  false },
105
    
106 107 108 109
    // Channels 5-11: not mapped and should be set to defaults
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
110 111 112 113
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
114
	
Don Gagne's avatar
Don Gagne committed
115
	// Channels 12-17 are not mapped and should be set to defaults
116 117 118 119 120 121
	{ RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
	{ RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
	{ RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
	{ RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
Don Gagne's avatar
Don Gagne committed
122 123
};

Don Gagne's avatar
Don Gagne committed
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
const struct RadioConfigTest::ChannelSettings RadioConfigTest::_rgChannelSettingsAPM[RadioComponentController::_chanMaxAPM] = {
    // Function										Min                 Max                 #  Reversed

    // Channel 0 : Not mapped to function, Simulate invalid Min/Max
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,	_testCenterValue,   0, false },

    // Channels 1-4: Mapped to attitude control function
    { RadioComponentController::rcCalFunctionRoll,			_testMinValue,      _testMaxValue,      0, true },
    { RadioComponentController::rcCalFunctionPitch,			_testMinValue,      _testMaxValue,      0, false },
    { RadioComponentController::rcCalFunctionYaw,			_testMinValue,      _testMaxValue,      0, true },
    { RadioComponentController::rcCalFunctionThrottle,		_testMinValue,      _testMaxValue,      0,  false },

    // Channels 5-11: Not mapped to function, Simulate invalid Min/Max, since available channel Min/Max is still shown.
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },

    // Channel 12 : Not mapped to function, Simulate invalid Min, valid Max
    { RadioComponentController::rcCalFunctionMax,			_testCenterValue,	_testMaxValue,      0,  false },

    // Channel 13 : Not mapped to function, Simulate valid Min, invalid Max
    { RadioComponentController::rcCalFunctionMax,           _testMinValue,      _testCenterValue,   0,	false },
};

// Note the: 1500/*RadioComponentController::_rcCalPWMCenterPoint*/ entries. For some reason I couldn't get the compiler to do the
// right thing with the constant. So I just hacked inthe real value instead of fighting with it any longer.
const struct RadioConfigTest::ChannelSettings RadioConfigTest::_rgChannelSettingsValidateAPM[RadioComponentController::_chanMaxAPM] = {
    // Function										Min Value									Max Value									Trim Value										Reversed

    // Channels 0: not mapped and should be set to defaults
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },

    // Channels 1-4: Mapped to attitude control function
    { RadioComponentController::rcCalFunctionRoll,			_testMinValue, _testMaxValue, _testCenterValue, true },
162
    { RadioComponentController::rcCalFunctionPitch,			_testMinValue, _testMaxValue, _testCenterValue, true },
Don Gagne's avatar
Don Gagne committed
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    { RadioComponentController::rcCalFunctionYaw,			_testMinValue, _testMaxValue, _testCenterValue, true },
    { RadioComponentController::rcCalFunctionThrottle,		_testMinValue, _testMaxValue, _testMinValue,    false },

    // Channels 5-11: not mapped and should be set to defaults
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },

    // Channels 12-13 are not mapped and should be set to defaults
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
    { RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
};

180 181 182
RadioConfigTest::RadioConfigTest(void) :
    _calWidget(NULL),
    _controller(NULL)
183
{
184
    
Don Gagne's avatar
Don Gagne committed
185 186
}

Don Gagne's avatar
Don Gagne committed
187
void RadioConfigTest::_init(MAV_AUTOPILOT firmwareType)
188
{
Don Gagne's avatar
Don Gagne committed
189
    _connectMockLink(firmwareType);
190
    
191
    _autopilot = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()->autopilotPlugin();
192
    Q_ASSERT(_autopilot);
193 194
    
    // This will instatiate the widget with an active uas with ready parameters
195
    _calWidget = new QGCQmlWidgetHolder(QString(), NULL);
196
    _calWidget->resize(600, 600);
197
    Q_CHECK_PTR(_calWidget);
198 199
    _calWidget->setAutoPilot(_autopilot);
    _calWidget->setSource(QUrl::fromUserInput("qrc:/qml/RadioComponent.qml"));
200
    
201 202 203
    // Nasty hack to get to controller
    _controller = RadioComponentController::_unitTestController;
    Q_ASSERT(_controller);
Don Gagne's avatar
Don Gagne committed
204

205
    _controller->_setUnitTestMode();
Don Gagne's avatar
Don Gagne committed
206 207 208 209
    
    _rgSignals[0] = SIGNAL(nextButtonMessageBoxDisplayed());
    _multiSpyNextButtonMessageBox = new MultiSignalSpy();
    Q_CHECK_PTR(_multiSpyNextButtonMessageBox);
210
    QCOMPARE(_multiSpyNextButtonMessageBox->init(_controller, _rgSignals, 1), true);
Don Gagne's avatar
Don Gagne committed
211
    
212
    QCOMPARE(_controller->_currentStep, -1);
213 214
}

215
void RadioConfigTest::cleanup(void)
216
{
Don Gagne's avatar
Don Gagne committed
217 218 219
    Q_ASSERT(_calWidget);
    delete _calWidget;
    
220 221
    // Disconnecting the link will prompt for log file save
    setExpectedFileDialog(getSaveFileName, QStringList());
222
    
Don Gagne's avatar
Don Gagne committed
223
    UnitTest::cleanup();
224 225
}

226
void RadioConfigTest::_beginCalibration(void)
227 228 229
{
    CHK_BUTTONS(nextButtonMask | cancelButtonMask);

Don Gagne's avatar
Don Gagne committed
230 231
    // We should already have enough channels to proceed with calibration. Click next to start the process.
    
232 233
    _controller->nextButtonClicked();
    QCOMPARE(_controller->_currentStep, 1);
234 235 236
    CHK_BUTTONS(cancelButtonMask);
}

237
void RadioConfigTest::_stickMoveWaitForSettle(int channel, int value)
238
{
239
    qCDebug(RadioConfigTestLog) << "_stickMoveWaitForSettle channel:value" << channel << value;
Don Gagne's avatar
Don Gagne committed
240 241

    // Move the stick, this will initialized the settle checker
242
    _mockLink->emitRemoteControlChannelRawChanged(channel, value);
Don Gagne's avatar
Don Gagne committed
243 244
    
    // Emit the signal again to start the settle timer
245
    _mockLink->emitRemoteControlChannelRawChanged(channel, value);
Don Gagne's avatar
Don Gagne committed
246 247
    
    // Wait long enough for the settle timer to expire
248
    QTest::qWait(RadioComponentController::_stickDetectSettleMSecs * 1.5);
Don Gagne's avatar
Don Gagne committed
249 250
    
    // Emit the signal again so that we detect stick settle
251
    _mockLink->emitRemoteControlChannelRawChanged(channel, value);
252 253
}

254
void RadioConfigTest::_stickMoveAutoStep(const char* functionStr, enum RadioComponentController::rcCalFunctions function, enum RadioConfigTest::MoveToDirection direction, bool identifyStep)
255
{
Don Gagne's avatar
Don Gagne committed
256
    Q_UNUSED(functionStr);
257
    qCDebug(RadioConfigTestLog) << "_stickMoveAutoStep function:direction:reversed:identifyStep" << functionStr << function << direction << identifyStep;
258
    
Don Gagne's avatar
Don Gagne committed
259 260 261
    CHK_BUTTONS(cancelButtonMask);
    
    int channel = _rgFunctionChannelMap[function];
262
    int saveStep = _controller->_currentStep;
Don Gagne's avatar
Don Gagne committed
263
    
Don Gagne's avatar
Don Gagne committed
264
    bool reversed = _channelSettings()[channel].reversed;
265
    
Don Gagne's avatar
Don Gagne committed
266 267
    if (!identifyStep && direction != moveToCenter) {
        // We have already identified the function channel mapping. Move other channels around to make sure there is no impact.
268
        
Don Gagne's avatar
Don Gagne committed
269
        int otherChannel = channel + 1;
Don Gagne's avatar
Don Gagne committed
270
        if (otherChannel >= _chanMax()) {
Don Gagne's avatar
Don Gagne committed
271
            otherChannel = 0;
Don Gagne's avatar
Don Gagne committed
272 273
        }
        
Don Gagne's avatar
Don Gagne committed
274
        _stickMoveWaitForSettle(otherChannel, _testMinValue);
275
        QCOMPARE(_controller->_currentStep, saveStep);
Don Gagne's avatar
Don Gagne committed
276
        CHK_BUTTONS(cancelButtonMask);
277
        
278 279
        _stickMoveWaitForSettle(otherChannel, RadioComponentController::_rcCalPWMCenterPoint);
        QCOMPARE(_controller->_currentStep, saveStep);
Don Gagne's avatar
Don Gagne committed
280
        CHK_BUTTONS(cancelButtonMask);
281 282
    }
    
Don Gagne's avatar
Don Gagne committed
283 284 285 286 287 288 289 290
    // Move channel to specified position to trigger next step
    
    int value;
    if (direction == moveToMin) {
        value = reversed ? _testMaxValue : _testMinValue;
    } else if (direction == moveToMax) {
        value = reversed ? _testMinValue : _testMaxValue;
    } else if (direction == moveToCenter) {
291
        value = RadioComponentController::_rcCalPWMCenterPoint;
Don Gagne's avatar
Don Gagne committed
292 293
    } else {
        Q_ASSERT(false);
294
    }
Don Gagne's avatar
Don Gagne committed
295 296
    
    _stickMoveWaitForSettle(channel, value);
297
    QCOMPARE(_controller->_currentStep, saveStep + 1);
298 299
}

300
void RadioConfigTest::_switchMinMaxStep(void)
301
{
Don Gagne's avatar
Don Gagne committed
302
    CHK_BUTTONS(nextButtonMask | cancelButtonMask);
Don Gagne's avatar
Don Gagne committed
303 304
    
    // Try setting a min/max value that is below the threshold to make sure min/max doesn't go valid
305 306
    _mockLink->emitRemoteControlChannelRawChanged(0, (float)(RadioComponentController::_rcCalPWMValidMinValue + 1));
    _mockLink->emitRemoteControlChannelRawChanged(0, (float)(RadioComponentController::_rcCalPWMValidMaxValue - 1));
Don Gagne's avatar
Don Gagne committed
307 308
    
    // Send min/max values switch channels
Don Gagne's avatar
Don Gagne committed
309 310 311
    for (int chan=0; chan<_chanMax(); chan++) {
        _mockLink->emitRemoteControlChannelRawChanged(chan, _channelSettings()[chan].rcMin);
        _mockLink->emitRemoteControlChannelRawChanged(chan, _channelSettings()[chan].rcMax);
312
    }
Don Gagne's avatar
Don Gagne committed
313
    
Don Gagne's avatar
Don Gagne committed
314
    _channelHomePosition();
315

316 317 318
    int saveStep = _controller->_currentStep;
    _controller->nextButtonClicked();
    QCOMPARE(_controller->_currentStep, saveStep + 1);
319 320
}

321
void RadioConfigTest::_switchSelectAutoStep(const char* functionStr, RadioComponentController::rcCalFunctions function)
322
{
Don Gagne's avatar
Don Gagne committed
323
    Q_UNUSED(functionStr);
324
    ////qCDebug(RadioConfigTestLog)() << "_switchSelectAutoStep" << functionStr << "function:" << function;
325
    
Don Gagne's avatar
Don Gagne committed
326
    int buttonMask = cancelButtonMask;
327
    if (function != RadioComponentController::rcCalFunctionModeSwitch) {
Don Gagne's avatar
Don Gagne committed
328
        buttonMask |= skipButtonMask;
Don Gagne's avatar
Don Gagne committed
329 330
    }
    
Don Gagne's avatar
Don Gagne committed
331
    CHK_BUTTONS(buttonMask);
Don Gagne's avatar
Don Gagne committed
332
    
333
    int saveStep = _controller->_currentStep;
334
    
Don Gagne's avatar
Don Gagne committed
335 336
    // Wiggle stick for channel
    int channel = _rgFunctionChannelMap[function];
337 338
    _mockLink->emitRemoteControlChannelRawChanged(channel, _testMinValue);
    _mockLink->emitRemoteControlChannelRawChanged(channel, _testMaxValue);
Don Gagne's avatar
Don Gagne committed
339
    
340
    QCOMPARE(_controller->_currentStep, saveStep + 1);
341 342
}

Don Gagne's avatar
Don Gagne committed
343
void RadioConfigTest::_fullCalibrationWorker(MAV_AUTOPILOT firmwareType)
344
{
Don Gagne's avatar
Don Gagne committed
345 346
    _init(firmwareType);

347
    // IMPORTANT NOTE: We used channels 1-5 for attitude mapping in the test below.
348
    // MockLink.params file cannot have flight mode switches mapped to those channels.
349 350 351 352 353
    // If it does it will cause errors since the stick will not be detetected where

    /// _rgFunctionChannelMap maps from function index to channel index. For channels which are not part of
    /// rc cal set the mapping the the previous mapping.
    
354
    for (int function=0; function<RadioComponentController::rcCalFunctionMax; function++) {
355 356 357
        bool found = false;
        
        // If we are mapping this function during cal set it into _rgFunctionChannelMap
Don Gagne's avatar
Don Gagne committed
358 359
        for (int channel=0; channel<_chanMax(); channel++) {
            if (_channelSettings()[channel].function == function) {
360
                
Don Gagne's avatar
Don Gagne committed
361 362 363 364 365
                if (_px4Vehicle()) {
                    // Make sure this function isn't being use for a switch
                    QStringList switchList;
                    switchList << "RC_MAP_MODE_SW" << "RC_MAP_LOITER_SW" << "RC_MAP_RETURN_SW" << "RC_MAP_POSCTL_SW" << "RC_MAP_ACRO_SW";

366
                    foreach (const QString &switchParam, switchList) {
Don Gagne's avatar
Don Gagne committed
367 368
                        Q_ASSERT(_autopilot->getParameterFact(FactSystem::defaultComponentId, switchParam)->rawValue().toInt() != channel + 1);
                    }
369 370 371 372 373 374 375 376 377 378 379
                }
                
                _rgFunctionChannelMap[function] = channel;
                found = true;
                
                break;
            }
        }
        
        // If we aren't mapping this function during calibration, set it to the previous setting
        if (!found) {
Don Gagne's avatar
Don Gagne committed
380 381 382 383 384 385 386 387 388
            const char* paramName = _functionInfo()[function].parameterName;
            if (paramName) {
                _rgFunctionChannelMap[function] = _autopilot->getParameterFact(FactSystem::defaultComponentId, paramName)->rawValue().toInt();
                qCDebug(RadioConfigTestLog) << "Assigning switch" << function << _rgFunctionChannelMap[function];
                if (_rgFunctionChannelMap[function] == 0) {
                    _rgFunctionChannelMap[function] = -1;   // -1 signals no mapping
                } else {
                    _rgFunctionChannelMap[function]--;   // parameter is 1-based, _rgFunctionChannelMap is not
                }
389
            } else {
Don Gagne's avatar
Don Gagne committed
390
                _rgFunctionChannelMap[function] = -1;   // -1 signals no mapping
391 392 393
            }
        }
    }
Don Gagne's avatar
Don Gagne committed
394 395
    
    _channelHomePosition();
396
    _controller->nextButtonClicked();
Don Gagne's avatar
Don Gagne committed
397
    _beginCalibration();
398 399 400 401 402 403 404 405 406
    _stickMoveAutoStep("Throttle", RadioComponentController::rcCalFunctionThrottle, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Throttle", RadioComponentController::rcCalFunctionThrottle, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Yaw", RadioComponentController::rcCalFunctionYaw, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Yaw", RadioComponentController::rcCalFunctionYaw, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Roll", RadioComponentController::rcCalFunctionRoll, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Roll", RadioComponentController::rcCalFunctionRoll, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Pitch", RadioComponentController::rcCalFunctionPitch, moveToCenter, false /* not identify step */);
Don Gagne's avatar
Don Gagne committed
407
    _switchMinMaxStep();
408 409

    // One more click and the parameters should get saved
410
    _controller->nextButtonClicked();
Don Gagne's avatar
Don Gagne committed
411
    _validateParameters();
412 413
}

Don Gagne's avatar
Don Gagne committed
414 415 416 417 418 419 420 421 422 423 424
void RadioConfigTest::_fullCalibration_px4_test(void)
{
    _fullCalibrationWorker(MAV_AUTOPILOT_PX4);
}


void RadioConfigTest::_fullCalibration_apm_test(void)
{
    _fullCalibrationWorker(MAV_AUTOPILOT_ARDUPILOTMEGA);
}

Don Gagne's avatar
Don Gagne committed
425
/// @brief Sets rc input to Throttle down home position. Centers all other channels.
426
void RadioConfigTest::_channelHomePosition(void)
427
{
Don Gagne's avatar
Don Gagne committed
428
    // Initialize available channels to center point.
Don Gagne's avatar
Don Gagne committed
429
    for (int i=0; i<_chanMax(); i++) {
430
        _mockLink->emitRemoteControlChannelRawChanged(i, (float)RadioComponentController::_rcCalPWMCenterPoint);
431
    }
Don Gagne's avatar
Don Gagne committed
432
    
433 434
    // Throttle to min - 1 (throttle is not reversed). We do this so that the trim value is below the min value. This should end up
    // being validated and raised to min value. If not, something is wrong with RC Cal code.
435
    _mockLink->emitRemoteControlChannelRawChanged(_rgFunctionChannelMap[RadioComponentController::rcCalFunctionThrottle], _testMinValue - 1);
436 437
}

438
void RadioConfigTest::_validateParameters(void)
439 440 441 442 443 444
{
    QString minTpl("RC%1_MIN");
    QString maxTpl("RC%1_MAX");
    QString trimTpl("RC%1_TRIM");
    QString revTpl("RC%1_REV");
    
Don Gagne's avatar
Don Gagne committed
445
    // Check mapping for all fuctions
446
    for (int chanFunction=0; chanFunction<RadioComponentController::rcCalFunctionMax; chanFunction++) {
Don Gagne's avatar
Don Gagne committed
447 448 449 450 451 452 453 454 455
        int chanIndex = _rgFunctionChannelMap[chanFunction];
        
        int expectedParameterValue;
        if (chanIndex == -1) {
            expectedParameterValue = 0;  // 0 signals no mapping
        } else {
            expectedParameterValue = chanIndex + 1; // 1-based parameter value
        }
        
Don Gagne's avatar
Don Gagne committed
456 457 458 459 460
        const char* paramName = _functionInfo()[chanFunction].parameterName;
        if (paramName) {
            qCDebug(RadioConfigTestLog) << "Validate" << chanFunction << _autopilot->getParameterFact(FactSystem::defaultComponentId, paramName)->rawValue().toInt();
            QCOMPARE(_autopilot->getParameterFact(FactSystem::defaultComponentId, paramName)->rawValue().toInt(), expectedParameterValue);
        }
Don Gagne's avatar
Don Gagne committed
461
    }
Don Gagne's avatar
Don Gagne committed
462 463

    // Validate the channel settings. Note the channels are 1-based in parameter names.
Don Gagne's avatar
Don Gagne committed
464
    for (int chan = 0; chan<_chanMax(); chan++) {
Don Gagne's avatar
Don Gagne committed
465 466 467 468
        int oneBasedChannel = chan + 1;
        bool convertOk;
        
        // Required channels have min/max set on them. Remaining channels are left to default.
Don Gagne's avatar
Don Gagne committed
469 470 471 472
        int rcMinExpected = _channelSettingsValidate()[chan].rcMin;
        int rcMaxExpected = _channelSettingsValidate()[chan].rcMax;
        int rcTrimExpected = _channelSettingsValidate()[chan].rcTrim;
        bool rcReversedExpected = _channelSettingsValidate()[chan].reversed;
Don Gagne's avatar
Don Gagne committed
473

Don Gagne's avatar
Don Gagne committed
474
        int rcMinActual = _autopilot->getParameterFact(FactSystem::defaultComponentId, minTpl.arg(oneBasedChannel))->rawValue().toInt(&convertOk);
Don Gagne's avatar
Don Gagne committed
475
        QCOMPARE(convertOk, true);
Don Gagne's avatar
Don Gagne committed
476
        int rcMaxActual = _autopilot->getParameterFact(FactSystem::defaultComponentId, maxTpl.arg(oneBasedChannel))->rawValue().toInt(&convertOk);
Don Gagne's avatar
Don Gagne committed
477
        QCOMPARE(convertOk, true);
Don Gagne's avatar
Don Gagne committed
478
        int rcTrimActual = _autopilot->getParameterFact(FactSystem::defaultComponentId, trimTpl.arg(oneBasedChannel))->rawValue().toInt(&convertOk);
Don Gagne's avatar
Don Gagne committed
479
        QCOMPARE(convertOk, true);
Don Gagne's avatar
Don Gagne committed
480
        float rcReversedFloat = _autopilot->getParameterFact(FactSystem::defaultComponentId, revTpl.arg(oneBasedChannel))->rawValue().toFloat(&convertOk);
Don Gagne's avatar
Don Gagne committed
481 482 483
        QCOMPARE(convertOk, true);
        bool rcReversedActual = (rcReversedFloat == -1.0f);
        
Lorenz Meier's avatar
Lorenz Meier committed
484 485
        qCDebug(RadioConfigTestLog) << "_validateParameters expected channel:min:max:trim:rev" << chan << rcMinExpected << rcMaxExpected << rcTrimExpected << rcReversedExpected;
        qCDebug(RadioConfigTestLog) << "_validateParameters actual channel:min:max:trim:rev" << chan << rcMinActual << rcMaxActual << rcTrimActual << rcReversedActual;
486

Don Gagne's avatar
Don Gagne committed
487 488 489 490
        QCOMPARE(rcMinExpected, rcMinActual);
        QCOMPARE(rcMaxExpected, rcMaxActual);
        QCOMPARE(rcTrimExpected, rcTrimActual);
        QCOMPARE(rcReversedExpected, rcReversedActual);
491 492
    }
    
Don Gagne's avatar
Don Gagne committed
493
    // Check mapping for all fuctions
494
    for (int chanFunction=0; chanFunction<RadioComponentController::rcCalFunctionMax; chanFunction++) {
Don Gagne's avatar
Don Gagne committed
495 496 497 498 499
        int expectedValue;
        if (_rgFunctionChannelMap[chanFunction] == -1) {
            expectedValue = 0;  // 0 signals no mapping
        } else {
            expectedValue = _rgFunctionChannelMap[chanFunction] + 1; // 1-based
500
        }
Don Gagne's avatar
Don Gagne committed
501 502 503 504 505
        const char* paramName = _functionInfo()[chanFunction].parameterName;
        if (paramName) {
            // qCDebug(RadioConfigTestLog) << chanFunction << expectedValue << mapParamsSet[paramName].toInt();
            QCOMPARE(_autopilot->getParameterFact(FactSystem::defaultComponentId, paramName)->rawValue().toInt(), expectedValue);
        }
506
    }
Don Gagne's avatar
Don Gagne committed
507
}
Don Gagne's avatar
Don Gagne committed
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532

bool RadioConfigTest::_px4Vehicle(void) const
{
    return _vehicle->firmwareType() == MAV_AUTOPILOT_PX4;
}

const struct RadioConfigTest::ChannelSettings* RadioConfigTest::_channelSettings(void) const
{
    return _px4Vehicle() ? _rgChannelSettingsPX4 : _rgChannelSettingsAPM;
}

const struct RadioConfigTest::ChannelSettings* RadioConfigTest::_channelSettingsValidate(void) const
{
    return _px4Vehicle() ? _rgChannelSettingsValidatePX4 : _rgChannelSettingsValidateAPM;
}

const struct RadioComponentController::FunctionInfo* RadioConfigTest::_functionInfo(void) const
{
    return _px4Vehicle() ? RadioComponentController::_rgFunctionInfoPX4 : RadioComponentController::_rgFunctionInfoAPM;
}

int RadioConfigTest::_chanMax(void) const
{
    return _px4Vehicle() ? RadioComponentController::_chanMaxPX4 : RadioComponentController::_chanMaxAPM;
}