PX4RCCalibrationTest.cc 27.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
 (c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/

#include "PX4RCCalibrationTest.h"
#include "UASManager.h"
#include "MockQGCUASParamManager.h"

/// @file
Don Gagne's avatar
Don Gagne committed
29
///     @brief QPX4RCCalibration Widget unit test
30 31 32
///
///     @author Don Gagne <don@thegagnes.com>

Don Gagne's avatar
Don Gagne committed
33
UT_REGISTER_TEST(PX4RCCalibrationTest)
34
QGC_LOGGING_CATEGORY(PX4RCCalibrationTestLog, "PX4RCCalibrationTestLog")
Don Gagne's avatar
Don Gagne committed
35

36 37 38 39 40 41
// 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) \
{ \
    if (_nextButton->isEnabled() != !!((mask) & nextButtonMask) || \
        _skipButton->isEnabled() != !!((mask) & skipButtonMask) || \
Don Gagne's avatar
Don Gagne committed
42
        _cancelButton->isEnabled() != !!((mask) & cancelButtonMask) ) { \
43
        qCDebug(PX4RCCalibrationTestLog) << _statusLabel->text(); \
44 45 46 47 48 49 50 51 52 53
    } \
    QCOMPARE(_nextButton->isEnabled(), !!((mask) & nextButtonMask)); \
    QCOMPARE(_skipButton->isEnabled(), !!((mask) & skipButtonMask)); \
    QCOMPARE(_cancelButton->isEnabled(), !!((mask) & cancelButtonMask)); \
}

// 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
54
    if (mode == testModeStandalone && tryCancel ## cancelNum) { \
55 56 57 58 59 60 61 62 63
        QTest::mouseClick(_cancelButton, Qt::LeftButton); \
        QCOMPARE(_calWidget->_rcCalState, PX4RCCalibration::rcCalStateChannelWait); \
        tryCancel ## cancelNum = false; \
        goto StartOver; \
    } else { \
        QTest::mouseClick(_nextButton, Qt::LeftButton); \
    } \
}

Don Gagne's avatar
Don Gagne committed
64 65
const int PX4RCCalibrationTest::_stickSettleWait = PX4RCCalibration::_stickDetectSettleMSecs * 1.5;

Don Gagne's avatar
Don Gagne committed
66 67
const int PX4RCCalibrationTest::_testMinValue = PX4RCCalibration::_rcCalPWMDefaultMinValue + 10;
const int PX4RCCalibrationTest::_testMaxValue = PX4RCCalibration::_rcCalPWMDefaultMaxValue - 10;
Don Gagne's avatar
Don Gagne committed
68
const int PX4RCCalibrationTest::_testCenterValue = PX4RCCalibrationTest::_testMinValue + ((PX4RCCalibrationTest::_testMaxValue - PX4RCCalibrationTest::_testMinValue) / 2);
Don Gagne's avatar
Don Gagne committed
69

Don Gagne's avatar
Don Gagne committed
70 71
const struct PX4RCCalibrationTest::ChannelSettings PX4RCCalibrationTest::_rgChannelSettings[PX4RCCalibrationTest::_availableChannels] = {
	// Function										Min                 Max                 #  Reversed
72 73
	
	// Channel 0 : Not mapped to function, Simulate invalid Min/Max
Don Gagne's avatar
Don Gagne committed
74
	{ PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,	_testCenterValue,   0, false },
75
	
76
    // Channels 1-4: Mapped to attitude control function
Don Gagne's avatar
Don Gagne committed
77 78 79 80
    { PX4RCCalibration::rcCalFunctionRoll,			_testMinValue,      _testMaxValue,      0, true },
    { PX4RCCalibration::rcCalFunctionPitch,			_testMinValue,      _testMaxValue,      0, false },
    { PX4RCCalibration::rcCalFunctionYaw,			_testMinValue,      _testMaxValue,      0, true },
    { PX4RCCalibration::rcCalFunctionThrottle,		_testMinValue,      _testMaxValue,      0,  false },
81 82 83 84 85 86 87 88 89
    
    // Channels 5-8: Not mapped to function, Simulate invalid Min/Max, since available channel Min/Max is still shown.
    // These are here to skip over the flight mode functions
    { PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    
    // Channels 9-11: Remainder of non-flight mode switches
Don Gagne's avatar
Don Gagne committed
90 91 92
    { PX4RCCalibration::rcCalFunctionFlaps,			_testMinValue,      _testMaxValue,      0, false },
    { PX4RCCalibration::rcCalFunctionAux1,			_testMinValue,      _testMaxValue,      0, false },
    { PX4RCCalibration::rcCalFunctionAux2,			_testMinValue,      _testMaxValue,      0, false },
93 94
	
    // Channel 12 : Not mapped to function, Simulate invalid Min, valid Max
Don Gagne's avatar
Don Gagne committed
95
    { PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,	_testMaxValue,      0,  false },
96 97
    
	// Channel 13 : Not mapped to function, Simulate valid Min, invalid Max
Don Gagne's avatar
Don Gagne committed
98
	{ PX4RCCalibration::rcCalFunctionMax,           _testMinValue,      _testCenterValue,   0,	false },
99 100
	
    // Channels 14-17: Not mapped to function, Simulate invalid Min/Max, since available channel Min/Max is still shown
Don Gagne's avatar
Don Gagne committed
101 102 103 104
    { PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
    { PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
	{ PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
	{ PX4RCCalibration::rcCalFunctionMax,			_testCenterValue,   _testCenterValue,   0,	false },
Don Gagne's avatar
Don Gagne committed
105 106
};

Don Gagne's avatar
Don Gagne committed
107 108
const struct PX4RCCalibrationTest::ChannelSettings PX4RCCalibrationTest::_rgChannelSettingsValidate[PX4RCCalibration::_chanMax] = {
    // Function										Min Value									Max Value									Trim Value										Reversed
109
	
110
    // Channels 0: not mapped and should be set to defaults
Don Gagne's avatar
Don Gagne committed
111
	{ PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
112
	
113
    // Channels 1-4: Mapped to attitude control function
114 115 116 117
	{ PX4RCCalibration::rcCalFunctionRoll,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               true },
    { PX4RCCalibration::rcCalFunctionPitch,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               false },
    { PX4RCCalibration::rcCalFunctionYaw,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               true },
    { PX4RCCalibration::rcCalFunctionThrottle,		_testMinValue,                              _testMaxValue,                              _testMinValue,                                  false },
118 119 120 121 122 123 124 125
    
    // Channels 5-8: not mapped and should be set to defaults
    { PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
    { PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
    { PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
    { PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
    
    // Channels 9-11: Remainder of non-flight mode switches
126 127 128
    { PX4RCCalibration::rcCalFunctionFlaps,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               false },
    { PX4RCCalibration::rcCalFunctionAux1,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               false },
    { PX4RCCalibration::rcCalFunctionAux2,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               false },
129
	
Don Gagne's avatar
Don Gagne committed
130 131 132 133 134
	// Channels 12-17 are not mapped and should be set to defaults
	{ PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
	{ PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
	{ PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
	{ PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
135 136
    { PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
    { PX4RCCalibration::rcCalFunctionMax,			PX4RCCalibration::_rcCalPWMDefaultMinValue,	PX4RCCalibration::_rcCalPWMDefaultMaxValue,	PX4RCCalibration::_rcCalPWMCenterPoint,         false },
Don Gagne's avatar
Don Gagne committed
137 138
};

139 140 141 142
PX4RCCalibrationTest::PX4RCCalibrationTest(void) :
    _mockUASManager(NULL),
    _calWidget(NULL)
{
Don Gagne's avatar
Don Gagne committed
143 144
}

145 146
void PX4RCCalibrationTest::init(void)
{
Don Gagne's avatar
Don Gagne committed
147 148
    UnitTest::init();
    
149 150 151
    _mockUASManager = new MockUASManager();
    Q_ASSERT(_mockUASManager);
    
Don Gagne's avatar
Don Gagne committed
152
    UASManager::setMockInstance(_mockUASManager);
153 154 155 156
    
    _mockUAS = new MockUAS();
    Q_CHECK_PTR(_mockUAS);
    
157 158 159
    _mockUASManager->setMockActiveUAS(_mockUAS);
    
    // This will instatiate the widget with an active uas with ready parameters
160 161
    _calWidget = new PX4RCCalibration();
    Q_CHECK_PTR(_calWidget);
Don Gagne's avatar
Don Gagne committed
162
    _calWidget->_setUnitTestMode();    
163 164 165 166 167 168 169 170 171 172 173 174 175 176

    // Get pointers to the push buttons
    _cancelButton = _calWidget->findChild<QPushButton*>("rcCalCancel");
    _nextButton = _calWidget->findChild<QPushButton*>("rcCalNext");
    _skipButton = _calWidget->findChild<QPushButton*>("rcCalSkip");
    
    Q_ASSERT(_cancelButton);
    Q_ASSERT(_nextButton);
    Q_ASSERT(_skipButton);
    
    _statusLabel = _calWidget->findChild<QLabel*>("rcCalStatus");
    Q_ASSERT(_statusLabel);
 
    for (size_t i=0; i<PX4RCCalibration::_chanMax; i++) {
Don Gagne's avatar
Don Gagne committed
177 178 179
        QString radioWidgetName("channel%1Value");

        RCValueWidget* radioWidget = _calWidget->findChild<RCValueWidget*>(radioWidgetName.arg(i+1));
180 181
        Q_ASSERT(radioWidget);
        
Don Gagne's avatar
Don Gagne committed
182
        _rgValueWidget[i] = radioWidget;
183
    }
Don Gagne's avatar
Don Gagne committed
184 185 186 187 188 189 190
    
    _rgSignals[0] = SIGNAL(nextButtonMessageBoxDisplayed());
    _multiSpyNextButtonMessageBox = new MultiSignalSpy();
    Q_CHECK_PTR(_multiSpyNextButtonMessageBox);
    QCOMPARE(_multiSpyNextButtonMessageBox->init(_calWidget, _rgSignals, 1), true);
    
    QCOMPARE(_calWidget->_currentStep, -1);
191 192 193 194
}

void PX4RCCalibrationTest::cleanup(void)
{
Don Gagne's avatar
Don Gagne committed
195 196 197
    Q_ASSERT(_calWidget);
    delete _calWidget;
    
198 199 200
    Q_ASSERT(_mockUAS);
    delete _mockUAS;
    
Don Gagne's avatar
Don Gagne committed
201
    UASManager::setMockInstance(NULL);
Don Gagne's avatar
Don Gagne committed
202
    
203 204 205
    Q_ASSERT(_mockUASManager);
    delete _mockUASManager;
    
Don Gagne's avatar
Don Gagne committed
206
    UnitTest::cleanup();
207 208
}

Don Gagne's avatar
Don Gagne committed
209
/// @brief Test for correct behavior in determining minimum numbers of channels for flight.
210 211 212
void PX4RCCalibrationTest::_minRCChannels_test(void)
{
    // Next button won't be enabled until we see the minimum number of channels.
213 214
    for (int chan=0; chan<PX4RCCalibration::_chanMinimum; chan++) {
        _mockUAS->emitRemoteControlChannelRawChanged(chan, (float)PX4RCCalibration::_rcCalPWMCenterPoint);
Don Gagne's avatar
Don Gagne committed
215 216
        
        // We use _chanCount internally so we should validate it
217
        QCOMPARE(_calWidget->_chanCount, chan+1);
Don Gagne's avatar
Don Gagne committed
218 219
        
        // Validate Next button state
Don Gagne's avatar
Don Gagne committed
220 221
        QTest::mouseClick(_nextButton, Qt::LeftButton);
        bool signalFound = _multiSpyNextButtonMessageBox->waitForSignalByIndex(0, 200);
222
        if (chan == PX4RCCalibration::_chanMinimum - 1) {
Don Gagne's avatar
Don Gagne committed
223 224 225
            // Last channel should trigger Calibration available
            QCOMPARE(signalFound, false);
            QCOMPARE(_calWidget->_currentStep, 0);
226
        } else {
Don Gagne's avatar
Don Gagne committed
227 228 229
            // Still less than the minimum channels. Next button should show message box. Calibration should not start.
            QCOMPARE(signalFound, true);
            QCOMPARE(_calWidget->_currentStep, -1);
230
        }
Don Gagne's avatar
Don Gagne committed
231
        _multiSpyNextButtonMessageBox->clearAllSignals();
Don Gagne's avatar
Don Gagne committed
232

233 234 235
        // The following test code no longer works since view update doesn't happens until parameters are received.
        // Leaving code here because RC Cal could be restructured to handle this case at some point.
#if 0
Don Gagne's avatar
Don Gagne committed
236
        // Only available channels should have visible widget. A ui update cycle needs to have passed so we wait a little.
Don Gagne's avatar
Don Gagne committed
237 238
        QTest::qWait(PX4RCCalibration::_updateInterval * 2);
        for (int chanWidget=0; chanWidget<PX4RCCalibration::_chanMax; chanWidget++) {
239
            qCDebug(PX4RCCalibrationTestLog) << _rgValueWidget[chanWidget]->objectName() << chanWidget << chan;
Don Gagne's avatar
Don Gagne committed
240
            QCOMPARE(_rgValueWidget[chanWidget]->isVisible(), !!(chanWidget <= chan));
Don Gagne's avatar
Don Gagne committed
241
        }
242
#endif
243 244 245
    }
}

Don Gagne's avatar
Don Gagne committed
246
void PX4RCCalibrationTest::_beginCalibration(void)
247 248 249
{
    CHK_BUTTONS(nextButtonMask | cancelButtonMask);

Don Gagne's avatar
Don Gagne committed
250 251 252 253
    // We should already have enough channels to proceed with calibration. Click next to start the process.
    
    QTest::mouseClick(_nextButton, Qt::LeftButton);
    QCOMPARE(_calWidget->_currentStep, 1);
254 255 256
    CHK_BUTTONS(cancelButtonMask);
}

Don Gagne's avatar
Don Gagne committed
257
void PX4RCCalibrationTest::_stickMoveWaitForSettle(int channel, int value)
258
{
259
    qCDebug(PX4RCCalibrationTestLog) << "_stickMoveWaitForSettle channel:value" << channel << value;
Don Gagne's avatar
Don Gagne committed
260 261 262 263 264 265 266 267 268 269 270 271

    // Move the stick, this will initialized the settle checker
    _mockUAS->emitRemoteControlChannelRawChanged(channel, value);
    
    // Emit the signal again to start the settle timer
    _mockUAS->emitRemoteControlChannelRawChanged(channel, value);
    
    // Wait long enough for the settle timer to expire
    QTest::qWait(PX4RCCalibration::_stickDetectSettleMSecs * 1.5);
    
    // Emit the signal again so that we detect stick settle
    _mockUAS->emitRemoteControlChannelRawChanged(channel, value);
272 273
}

Don Gagne's avatar
Don Gagne committed
274
void PX4RCCalibrationTest::_stickMoveAutoStep(const char* functionStr, enum PX4RCCalibration::rcCalFunctions function, enum PX4RCCalibrationTest::MoveToDirection direction, bool identifyStep)
275
{
Don Gagne's avatar
Don Gagne committed
276
    Q_UNUSED(functionStr);
277
    qCDebug(PX4RCCalibrationTestLog) << "_stickMoveAutoStep function:direction:reversed:identifyStep" << functionStr << function << direction << identifyStep;
278
    
Don Gagne's avatar
Don Gagne committed
279 280 281 282 283 284
    CHK_BUTTONS(cancelButtonMask);
    
    int channel = _rgFunctionChannelMap[function];
    int saveStep = _calWidget->_currentStep;
    
    bool reversed = _rgChannelSettings[channel].reversed;
285
    
Don Gagne's avatar
Don Gagne committed
286 287
    if (!identifyStep && direction != moveToCenter) {
        // We have already identified the function channel mapping. Move other channels around to make sure there is no impact.
288
        
Don Gagne's avatar
Don Gagne committed
289 290 291
        int otherChannel = channel + 1;
        if (otherChannel >= PX4RCCalibration::_chanMax) {
            otherChannel = 0;
Don Gagne's avatar
Don Gagne committed
292 293
        }
        
Don Gagne's avatar
Don Gagne committed
294 295 296
        _stickMoveWaitForSettle(otherChannel, _testMinValue);
        QCOMPARE(_calWidget->_currentStep, saveStep);
        CHK_BUTTONS(cancelButtonMask);
297
        
Don Gagne's avatar
Don Gagne committed
298 299 300
        _stickMoveWaitForSettle(otherChannel, PX4RCCalibration::_rcCalPWMCenterPoint);
        QCOMPARE(_calWidget->_currentStep, saveStep);
        CHK_BUTTONS(cancelButtonMask);
301 302
    }
    
Don Gagne's avatar
Don Gagne committed
303 304 305 306 307 308 309 310 311 312 313
    // 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) {
        value = PX4RCCalibration::_rcCalPWMCenterPoint;
    } else {
        Q_ASSERT(false);
314
    }
Don Gagne's avatar
Don Gagne committed
315 316 317
    
    _stickMoveWaitForSettle(channel, value);
    QCOMPARE(_calWidget->_currentStep, saveStep + 1);
318 319
}

Don Gagne's avatar
Don Gagne committed
320
void PX4RCCalibrationTest::_switchMinMaxStep(void)
321
{
Don Gagne's avatar
Don Gagne committed
322
    CHK_BUTTONS(nextButtonMask | cancelButtonMask);
Don Gagne's avatar
Don Gagne committed
323 324 325 326
    
    // Try setting a min/max value that is below the threshold to make sure min/max doesn't go valid
    _mockUAS->emitRemoteControlChannelRawChanged(0, (float)(PX4RCCalibration::_rcCalPWMValidMinValue + 1));
    _mockUAS->emitRemoteControlChannelRawChanged(0, (float)(PX4RCCalibration::_rcCalPWMValidMaxValue - 1));
Don Gagne's avatar
Don Gagne committed
327 328 329 330
    QCOMPARE(_rgValueWidget[0]->isMinValid(), false);
    QCOMPARE(_rgValueWidget[0]->isMaxValid(), false);
    
    // Send min/max values switch channels
331
    for (int chan=0; chan<_availableChannels; chan++) {
Don Gagne's avatar
Don Gagne committed
332 333
        _mockUAS->emitRemoteControlChannelRawChanged(chan, _rgChannelSettings[chan].rcMin);
        _mockUAS->emitRemoteControlChannelRawChanged(chan, _rgChannelSettings[chan].rcMax);
334
    }
Don Gagne's avatar
Don Gagne committed
335
    
Don Gagne's avatar
Don Gagne committed
336
    _channelHomePosition();
337

Don Gagne's avatar
Don Gagne committed
338 339 340
    int saveStep = _calWidget->_currentStep;
    QTest::mouseClick(_nextButton, Qt::LeftButton);
    QCOMPARE(_calWidget->_currentStep, saveStep + 1);
341 342
}

Don Gagne's avatar
Don Gagne committed
343
void PX4RCCalibrationTest::_flapsDetectStep(void)
344
{
Don Gagne's avatar
Don Gagne committed
345
    int channel = _rgFunctionChannelMap[PX4RCCalibration::rcCalFunctionFlaps];
346
    
347
    qCDebug(PX4RCCalibrationTestLog) << "_flapsDetectStep channel" << channel;
348
    
Don Gagne's avatar
Don Gagne committed
349 350
    // Test code can't handle reversed flaps channel
    Q_ASSERT(!_rgChannelSettings[channel].reversed);
351
    
Don Gagne's avatar
Don Gagne committed
352 353 354
    CHK_BUTTONS(nextButtonMask | cancelButtonMask | skipButtonMask);
    
    int saveStep = _calWidget->_currentStep;
355

Don Gagne's avatar
Don Gagne committed
356 357 358
    // Wiggle channel to identify
    _stickMoveWaitForSettle(channel, _testMaxValue);
    _stickMoveWaitForSettle(channel, _testMinValue);
359
    
Don Gagne's avatar
Don Gagne committed
360 361
    // Leave channel on full flaps down
    _stickMoveWaitForSettle(channel, _testMaxValue);
362
    
Don Gagne's avatar
Don Gagne committed
363 364 365 366 367
    // User has to hit next at this step
    QCOMPARE(_calWidget->_currentStep, saveStep);
    CHK_BUTTONS(nextButtonMask | cancelButtonMask | skipButtonMask);
    QTest::mouseClick(_nextButton, Qt::LeftButton);
    QCOMPARE(_calWidget->_currentStep, saveStep + 1);
368 369
}

Don Gagne's avatar
Don Gagne committed
370
void PX4RCCalibrationTest::_switchSelectAutoStep(const char* functionStr, PX4RCCalibration::rcCalFunctions function)
371
{
Don Gagne's avatar
Don Gagne committed
372
    Q_UNUSED(functionStr);
373
    ////qCDebug(PX4RCCalibrationTestLog)() << "_switchSelectAutoStep" << functionStr << "function:" << function;
374
    
Don Gagne's avatar
Don Gagne committed
375 376 377
    int buttonMask = cancelButtonMask;
    if (function != PX4RCCalibration::rcCalFunctionModeSwitch) {
        buttonMask |= skipButtonMask;
Don Gagne's avatar
Don Gagne committed
378 379
    }
    
Don Gagne's avatar
Don Gagne committed
380
    CHK_BUTTONS(buttonMask);
Don Gagne's avatar
Don Gagne committed
381
    
Don Gagne's avatar
Don Gagne committed
382
    int saveStep = _calWidget->_currentStep;
383
    
Don Gagne's avatar
Don Gagne committed
384 385 386 387 388 389
    // Wiggle stick for channel
    int channel = _rgFunctionChannelMap[function];
    _mockUAS->emitRemoteControlChannelRawChanged(channel, _testMinValue);
    _mockUAS->emitRemoteControlChannelRawChanged(channel, _testMaxValue);
    
    QCOMPARE(_calWidget->_currentStep, saveStep + 1);
390 391
}

Don Gagne's avatar
Don Gagne committed
392
void PX4RCCalibrationTest::_fullCalibration_test(void)
393
{
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
    // IMPORTANT NOTE: We used channels 1-5 for attitude mapping in the test below.
    // MockLink.param file cannot have flight mode switches mapped to those channels.
    // If it does it will cause errors since the stick will not be detetected where

    MockQGCUASParamManager* paramMgr = _mockUAS->getMockQGCUASParamManager();
    MockQGCUASParamManager::ParamMap_t mapParamsSet = paramMgr->getMockSetParameters();

    /// _rgFunctionChannelMap maps from function index to channel index. For channels which are not part of
    /// rc cal set the mapping the the previous mapping.
    
    for (int function=0; function<PX4RCCalibration::rcCalFunctionMax; function++) {
        bool found = false;
        
        // If we are mapping this function during cal set it into _rgFunctionChannelMap
        for (int channel=0; channel<PX4RCCalibrationTest::_availableChannels; channel++) {
            if (_rgChannelSettings[channel].function == function) {
                
                // First 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";
                
                foreach (QString switchParam, switchList) {
                    Q_ASSERT(mapParamsSet[switchParam].toInt() != channel + 1);
                }
                
                _rgFunctionChannelMap[function] = channel;
                found = true;
                
                break;
            }
        }
        
        // If we aren't mapping this function during calibration, set it to the previous setting
        if (!found) {
            _rgFunctionChannelMap[function] = mapParamsSet[PX4RCCalibration::_rgFunctionInfo[function].parameterName].toInt();
            qCDebug(PX4RCCalibrationTestLog) << "Assigning switch" << function << mapParamsSet[PX4RCCalibration::_rgFunctionInfo[function].parameterName].toInt();
            if (_rgFunctionChannelMap[function] == 0) {
                _rgFunctionChannelMap[function] = -1;   // -1 signals no mapping
            } else {
                _rgFunctionChannelMap[function]--;   // parameter is 1-based, _rgFunctionChannelMap is not
            }
        }
    }
Don Gagne's avatar
Don Gagne committed
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
    
    _channelHomePosition();
    QTest::mouseClick(_nextButton, Qt::LeftButton);    
    _beginCalibration();
    _stickMoveAutoStep("Throttle", PX4RCCalibration::rcCalFunctionThrottle, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Throttle", PX4RCCalibration::rcCalFunctionThrottle, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Yaw", PX4RCCalibration::rcCalFunctionYaw, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Yaw", PX4RCCalibration::rcCalFunctionYaw, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Roll", PX4RCCalibration::rcCalFunctionRoll, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Roll", PX4RCCalibration::rcCalFunctionRoll, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Pitch", PX4RCCalibration::rcCalFunctionPitch, moveToMax, true /* identify step */);
    _stickMoveAutoStep("Pitch", PX4RCCalibration::rcCalFunctionPitch, moveToMin, false /* not identify step */);
    _stickMoveAutoStep("Pitch", PX4RCCalibration::rcCalFunctionPitch, moveToCenter, false /* not identify step */);
    _switchMinMaxStep();
    _flapsDetectStep();
    _stickMoveAutoStep("Flaps", PX4RCCalibration::rcCalFunctionFlaps, moveToMin, false /* not identify step */);
    _switchSelectAutoStep("Aux1", PX4RCCalibration::rcCalFunctionAux1);
    _switchSelectAutoStep("Aux2", PX4RCCalibration::rcCalFunctionAux2);
456 457 458

    // One more click and the parameters should get saved
    QTest::mouseClick(_nextButton, Qt::LeftButton);
Don Gagne's avatar
Don Gagne committed
459
    _validateParameters();
460 461
}

Don Gagne's avatar
Don Gagne committed
462 463
/// @brief Sets rc input to Throttle down home position. Centers all other channels.
void PX4RCCalibrationTest::_channelHomePosition(void)
464
{
Don Gagne's avatar
Don Gagne committed
465
    // Initialize available channels to center point.
Don Gagne's avatar
Don Gagne committed
466
    for (int i=0; i<_availableChannels; i++) {
467 468
        _mockUAS->emitRemoteControlChannelRawChanged(i, (float)PX4RCCalibration::_rcCalPWMCenterPoint);
    }
Don Gagne's avatar
Don Gagne committed
469
    
470 471 472
    // 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.
    _mockUAS->emitRemoteControlChannelRawChanged(_rgFunctionChannelMap[PX4RCCalibration::rcCalFunctionThrottle], _testMinValue - 1);
473 474
}

Don Gagne's avatar
Don Gagne committed
475
void PX4RCCalibrationTest::_validateParameters(void)
476 477 478 479 480 481 482 483 484
{
    MockQGCUASParamManager* paramMgr = _mockUAS->getMockQGCUASParamManager();
    MockQGCUASParamManager::ParamMap_t mapParamsSet = paramMgr->getMockSetParameters();

    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
485 486 487 488 489 490 491 492 493 494 495
    // Check mapping for all fuctions
    for (int chanFunction=0; chanFunction<PX4RCCalibration::rcCalFunctionMax; chanFunction++) {
        int chanIndex = _rgFunctionChannelMap[chanFunction];
        
        int expectedParameterValue;
        if (chanIndex == -1) {
            expectedParameterValue = 0;  // 0 signals no mapping
        } else {
            expectedParameterValue = chanIndex + 1; // 1-based parameter value
        }
        
496
        qCDebug(PX4RCCalibrationTestLog) << "Validate" << chanFunction << mapParamsSet[PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName].toInt();
Don Gagne's avatar
Don Gagne committed
497 498 499
        QCOMPARE(mapParamsSet.contains(PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName), true);
        QCOMPARE(mapParamsSet[PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName].toInt(), expectedParameterValue);
    }
Don Gagne's avatar
Don Gagne committed
500 501 502 503 504 505 506

    // Validate the channel settings. Note the channels are 1-based in parameter names.
    for (int chan = 0; chan<PX4RCCalibration::_chanMax; chan++) {
        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
507 508 509 510 511 512 513 514 515
		int rcMinExpected = _rgChannelSettingsValidate[chan].rcMin;
		int rcMaxExpected = _rgChannelSettingsValidate[chan].rcMax;
		int rcTrimExpected = _rgChannelSettingsValidate[chan].rcTrim;
        bool rcReversedExpected = _rgChannelSettingsValidate[chan].reversed;

        QCOMPARE(mapParamsSet.contains(minTpl.arg(oneBasedChannel)), true);
        QCOMPARE(mapParamsSet.contains(maxTpl.arg(oneBasedChannel)), true);
        QCOMPARE(mapParamsSet.contains(trimTpl.arg(oneBasedChannel)), true);
        QCOMPARE(mapParamsSet.contains(revTpl.arg(oneBasedChannel)), true);
Don Gagne's avatar
Don Gagne committed
516
        
Don Gagne's avatar
Don Gagne committed
517 518 519 520 521 522 523 524 525 526
        int rcMinActual = mapParamsSet[minTpl.arg(oneBasedChannel)].toInt(&convertOk);
        QCOMPARE(convertOk, true);
        int rcMaxActual = mapParamsSet[maxTpl.arg(oneBasedChannel)].toInt(&convertOk);
        QCOMPARE(convertOk, true);
        int rcTrimActual = mapParamsSet[trimTpl.arg(oneBasedChannel)].toInt(&convertOk);
        QCOMPARE(convertOk, true);
        float rcReversedFloat = mapParamsSet[revTpl.arg(oneBasedChannel)].toFloat(&convertOk);
        QCOMPARE(convertOk, true);
        bool rcReversedActual = (rcReversedFloat == -1.0f);
        
527 528
        qCDebug(PX4RCCalibrationTestLog) << "_validateParemeters expected channel:min:max:trim:rev" << chan << rcMinExpected << rcMaxExpected << rcTrimExpected << rcReversedExpected;
        qCDebug(PX4RCCalibrationTestLog) << "_validateParemeters actual channel:min:max:trim:rev" << chan << rcMinActual << rcMaxActual << rcTrimActual << rcReversedActual;
529

Don Gagne's avatar
Don Gagne committed
530 531 532 533
        QCOMPARE(rcMinExpected, rcMinActual);
        QCOMPARE(rcMaxExpected, rcMaxActual);
        QCOMPARE(rcTrimExpected, rcTrimActual);
        QCOMPARE(rcReversedExpected, rcReversedActual);
534 535
    }
    
Don Gagne's avatar
Don Gagne committed
536 537 538
    // Check mapping for all fuctions
    for (int chanFunction=0; chanFunction<PX4RCCalibration::rcCalFunctionMax; chanFunction++) {
        QCOMPARE(mapParamsSet.contains(PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName), true);
539

Don Gagne's avatar
Don Gagne committed
540 541 542 543 544
        int expectedValue;
        if (_rgFunctionChannelMap[chanFunction] == -1) {
            expectedValue = 0;  // 0 signals no mapping
        } else {
            expectedValue = _rgFunctionChannelMap[chanFunction] + 1; // 1-based
545
        }
546
        // qCDebug(PX4RCCalibrationTestLog) << chanFunction << expectedValue << mapParamsSet[PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName].toInt();
Don Gagne's avatar
Don Gagne committed
547
        QCOMPARE(mapParamsSet[PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName].toInt(), expectedValue);
548
    }
Don Gagne's avatar
Don Gagne committed
549
}