RadioConfigTest.cc 30.6 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
/*=====================================================================
 
 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/>.
 
 ======================================================================*/

Don Gagne's avatar
Don Gagne committed
24
#include "RadioConfigTest.h"
25
#include "RadioComponentController.h"
26
#include "MultiVehicleManager.h"
27
#include "QGCApplication.h"
28 29

/// @file
30
///     @brief QRadioComponentController Widget unit test
31 32 33
///
///     @author Don Gagne <don@thegagnes.com>

34
QGC_LOGGING_CATEGORY(RadioConfigTestLog, "RadioConfigTestLog")
Don Gagne's avatar
Don Gagne committed
35

36 37 38 39
// 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) \
{ \
40 41 42 43
    if (_controller->_nextButton->isEnabled() != !!((mask) & nextButtonMask) || \
        _controller->_skipButton->isEnabled() != !!((mask) & skipButtonMask) || \
        _controller->_cancelButton->isEnabled() != !!((mask) & cancelButtonMask) ) { \
        qCDebug(RadioConfigTestLog) << _controller->_statusText->property("text"); \
44
    } \
45 46 47
    QCOMPARE(_controller->_nextButton->isEnabled(), !!((mask) & nextButtonMask)); \
    QCOMPARE(_controller->_skipButton->isEnabled(), !!((mask) & skipButtonMask)); \
    QCOMPARE(_controller->_cancelButton->isEnabled(), !!((mask) & cancelButtonMask)); \
48 49 50 51 52 53
}

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

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

66 67 68
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
69

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

Don Gagne's avatar
Don Gagne committed
105
// Note the: 1500/*RadioComponentController::_rcCalPWMCenterPoint*/ entries. For some reason I couldn't get the compiler to do the
106
// 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
107
const struct RadioConfigTest::ChannelSettings RadioConfigTest::_rgChannelSettingsValidatePX4[RadioComponentController::_chanMaxPX4] = {
Don Gagne's avatar
Don Gagne committed
108
    // Function										Min Value									Max Value									Trim Value										Reversed
109
	
110
    // Channels 0: not mapped and should be set to defaults
111
	{ RadioComponentController::rcCalFunctionMax,			RadioComponentController::_rcCalPWMDefaultMinValue,	RadioComponentController::_rcCalPWMDefaultMaxValue,	1500/*RadioComponentController::_rcCalPWMCenterPoint*/,         false },
112
	
113
    // Channels 1-4: Mapped to attitude control function
114 115 116 117
	{ RadioComponentController::rcCalFunctionRoll,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               true },
    { RadioComponentController::rcCalFunctionPitch,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               false },
    { RadioComponentController::rcCalFunctionYaw,			_testMinValue,                              _testMaxValue,                              _testCenterValue,                               true },
    { RadioComponentController::rcCalFunctionThrottle,		_testMinValue,                              _testMaxValue,                              _testMinValue,                                  false },
118
    
119 120 121 122
    // 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 },
123 124 125 126
    { 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 },
127
	
Don Gagne's avatar
Don Gagne committed
128
	// Channels 12-17 are not mapped and should be set to defaults
129 130 131 132 133 134
	{ 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
135 136
};

Don Gagne's avatar
Don Gagne committed
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 162 163 164 165 166 167 168 169 170 171 172 173 174
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 },
175
    { RadioComponentController::rcCalFunctionPitch,			_testMinValue, _testMaxValue, _testCenterValue, true },
Don Gagne's avatar
Don Gagne committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    { 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 },
};

193 194 195
RadioConfigTest::RadioConfigTest(void) :
    _calWidget(NULL),
    _controller(NULL)
196
{
197
    
Don Gagne's avatar
Don Gagne committed
198 199
}

Don Gagne's avatar
Don Gagne committed
200
void RadioConfigTest::_init(MAV_AUTOPILOT firmwareType)
201
{
Don Gagne's avatar
Don Gagne committed
202
    _connectMockLink(firmwareType);
203
    
204
    _autopilot = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()->autopilotPlugin();
205
    Q_ASSERT(_autopilot);
206 207
    
    // This will instatiate the widget with an active uas with ready parameters
208
    _calWidget = new QGCQmlWidgetHolder(QString(), NULL);
209
    _calWidget->resize(600, 600);
210
    Q_CHECK_PTR(_calWidget);
211 212
    _calWidget->setAutoPilot(_autopilot);
    _calWidget->setSource(QUrl::fromUserInput("qrc:/qml/RadioComponent.qml"));
213
    
214 215 216
    // Nasty hack to get to controller
    _controller = RadioComponentController::_unitTestController;
    Q_ASSERT(_controller);
Don Gagne's avatar
Don Gagne committed
217

218
    _controller->_setUnitTestMode();
Don Gagne's avatar
Don Gagne committed
219 220 221 222
    
    _rgSignals[0] = SIGNAL(nextButtonMessageBoxDisplayed());
    _multiSpyNextButtonMessageBox = new MultiSignalSpy();
    Q_CHECK_PTR(_multiSpyNextButtonMessageBox);
223
    QCOMPARE(_multiSpyNextButtonMessageBox->init(_controller, _rgSignals, 1), true);
Don Gagne's avatar
Don Gagne committed
224
    
225
    QCOMPARE(_controller->_currentStep, -1);
226 227
}

228
void RadioConfigTest::cleanup(void)
229
{
Don Gagne's avatar
Don Gagne committed
230 231 232
    Q_ASSERT(_calWidget);
    delete _calWidget;
    
233 234
    // Disconnecting the link will prompt for log file save
    setExpectedFileDialog(getSaveFileName, QStringList());
235
    
Don Gagne's avatar
Don Gagne committed
236
    UnitTest::cleanup();
237 238
}

239
void RadioConfigTest::_beginCalibration(void)
240 241 242
{
    CHK_BUTTONS(nextButtonMask | cancelButtonMask);

Don Gagne's avatar
Don Gagne committed
243 244
    // We should already have enough channels to proceed with calibration. Click next to start the process.
    
245 246
    _controller->nextButtonClicked();
    QCOMPARE(_controller->_currentStep, 1);
247 248 249
    CHK_BUTTONS(cancelButtonMask);
}

250
void RadioConfigTest::_stickMoveWaitForSettle(int channel, int value)
251
{
252
    qCDebug(RadioConfigTestLog) << "_stickMoveWaitForSettle channel:value" << channel << value;
Don Gagne's avatar
Don Gagne committed
253 254

    // Move the stick, this will initialized the settle checker
255
    _mockLink->emitRemoteControlChannelRawChanged(channel, value);
Don Gagne's avatar
Don Gagne committed
256 257
    
    // Emit the signal again to start the settle timer
258
    _mockLink->emitRemoteControlChannelRawChanged(channel, value);
Don Gagne's avatar
Don Gagne committed
259 260
    
    // Wait long enough for the settle timer to expire
261
    QTest::qWait(RadioComponentController::_stickDetectSettleMSecs * 1.5);
Don Gagne's avatar
Don Gagne committed
262 263
    
    // Emit the signal again so that we detect stick settle
264
    _mockLink->emitRemoteControlChannelRawChanged(channel, value);
265 266
}

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

313
void RadioConfigTest::_switchMinMaxStep(void)
314
{
Don Gagne's avatar
Don Gagne committed
315
    CHK_BUTTONS(nextButtonMask | cancelButtonMask);
Don Gagne's avatar
Don Gagne committed
316 317
    
    // Try setting a min/max value that is below the threshold to make sure min/max doesn't go valid
318 319
    _mockLink->emitRemoteControlChannelRawChanged(0, (float)(RadioComponentController::_rcCalPWMValidMinValue + 1));
    _mockLink->emitRemoteControlChannelRawChanged(0, (float)(RadioComponentController::_rcCalPWMValidMaxValue - 1));
Don Gagne's avatar
Don Gagne committed
320 321
    
    // Send min/max values switch channels
Don Gagne's avatar
Don Gagne committed
322 323 324
    for (int chan=0; chan<_chanMax(); chan++) {
        _mockLink->emitRemoteControlChannelRawChanged(chan, _channelSettings()[chan].rcMin);
        _mockLink->emitRemoteControlChannelRawChanged(chan, _channelSettings()[chan].rcMax);
325
    }
Don Gagne's avatar
Don Gagne committed
326
    
Don Gagne's avatar
Don Gagne committed
327
    _channelHomePosition();
328

329 330 331
    int saveStep = _controller->_currentStep;
    _controller->nextButtonClicked();
    QCOMPARE(_controller->_currentStep, saveStep + 1);
332 333
}

334
void RadioConfigTest::_switchSelectAutoStep(const char* functionStr, RadioComponentController::rcCalFunctions function)
335
{
Don Gagne's avatar
Don Gagne committed
336
    Q_UNUSED(functionStr);
337
    ////qCDebug(RadioConfigTestLog)() << "_switchSelectAutoStep" << functionStr << "function:" << function;
338
    
Don Gagne's avatar
Don Gagne committed
339
    int buttonMask = cancelButtonMask;
340
    if (function != RadioComponentController::rcCalFunctionModeSwitch) {
Don Gagne's avatar
Don Gagne committed
341
        buttonMask |= skipButtonMask;
Don Gagne's avatar
Don Gagne committed
342 343
    }
    
Don Gagne's avatar
Don Gagne committed
344
    CHK_BUTTONS(buttonMask);
Don Gagne's avatar
Don Gagne committed
345
    
346
    int saveStep = _controller->_currentStep;
347
    
Don Gagne's avatar
Don Gagne committed
348 349
    // Wiggle stick for channel
    int channel = _rgFunctionChannelMap[function];
350 351
    _mockLink->emitRemoteControlChannelRawChanged(channel, _testMinValue);
    _mockLink->emitRemoteControlChannelRawChanged(channel, _testMaxValue);
Don Gagne's avatar
Don Gagne committed
352
    
353
    QCOMPARE(_controller->_currentStep, saveStep + 1);
354 355
}

Don Gagne's avatar
Don Gagne committed
356
void RadioConfigTest::_fullCalibrationWorker(MAV_AUTOPILOT firmwareType)
357
{
Don Gagne's avatar
Don Gagne committed
358 359
    _init(firmwareType);

360
    // IMPORTANT NOTE: We used channels 1-5 for attitude mapping in the test below.
361
    // MockLink.params file cannot have flight mode switches mapped to those channels.
362 363 364 365 366
    // 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.
    
367
    for (int function=0; function<RadioComponentController::rcCalFunctionMax; function++) {
368 369 370
        bool found = false;
        
        // If we are mapping this function during cal set it into _rgFunctionChannelMap
Don Gagne's avatar
Don Gagne committed
371 372
        for (int channel=0; channel<_chanMax(); channel++) {
            if (_channelSettings()[channel].function == function) {
373
                
Don Gagne's avatar
Don Gagne committed
374 375 376 377 378
                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";

379
                    foreach (const QString &switchParam, switchList) {
Don Gagne's avatar
Don Gagne committed
380 381
                        Q_ASSERT(_autopilot->getParameterFact(FactSystem::defaultComponentId, switchParam)->rawValue().toInt() != channel + 1);
                    }
382 383 384 385 386 387 388 389 390 391 392
                }
                
                _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
393 394 395 396 397 398 399 400 401
            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
                }
402
            } else {
Don Gagne's avatar
Don Gagne committed
403
                _rgFunctionChannelMap[function] = -1;   // -1 signals no mapping
404 405 406
            }
        }
    }
Don Gagne's avatar
Don Gagne committed
407 408
    
    _channelHomePosition();
409
    _controller->nextButtonClicked();
Don Gagne's avatar
Don Gagne committed
410
    _beginCalibration();
411 412 413 414 415 416 417 418 419
    _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
420
    _switchMinMaxStep();
421 422

    // One more click and the parameters should get saved
423
    _controller->nextButtonClicked();
Don Gagne's avatar
Don Gagne committed
424
    _validateParameters();
425 426
}

Don Gagne's avatar
Don Gagne committed
427 428 429 430 431 432 433 434 435 436 437
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
438
/// @brief Sets rc input to Throttle down home position. Centers all other channels.
439
void RadioConfigTest::_channelHomePosition(void)
440
{
Don Gagne's avatar
Don Gagne committed
441
    // Initialize available channels to center point.
Don Gagne's avatar
Don Gagne committed
442
    for (int i=0; i<_chanMax(); i++) {
443
        _mockLink->emitRemoteControlChannelRawChanged(i, (float)RadioComponentController::_rcCalPWMCenterPoint);
444
    }
Don Gagne's avatar
Don Gagne committed
445
    
446 447
    // 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.
448
    _mockLink->emitRemoteControlChannelRawChanged(_rgFunctionChannelMap[RadioComponentController::rcCalFunctionThrottle], _testMinValue - 1);
449 450
}

451
void RadioConfigTest::_validateParameters(void)
452 453 454 455 456 457
{
    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
458
    // Check mapping for all fuctions
459
    for (int chanFunction=0; chanFunction<RadioComponentController::rcCalFunctionMax; chanFunction++) {
Don Gagne's avatar
Don Gagne committed
460 461 462 463 464 465 466 467 468
        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
469 470 471 472 473
        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
474
    }
Don Gagne's avatar
Don Gagne committed
475 476

    // Validate the channel settings. Note the channels are 1-based in parameter names.
Don Gagne's avatar
Don Gagne committed
477
    for (int chan = 0; chan<_chanMax(); chan++) {
Don Gagne's avatar
Don Gagne committed
478 479 480 481
        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
482 483 484 485
        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
486

Don Gagne's avatar
Don Gagne committed
487
        int rcMinActual = _autopilot->getParameterFact(FactSystem::defaultComponentId, minTpl.arg(oneBasedChannel))->rawValue().toInt(&convertOk);
Don Gagne's avatar
Don Gagne committed
488
        QCOMPARE(convertOk, true);
Don Gagne's avatar
Don Gagne committed
489
        int rcMaxActual = _autopilot->getParameterFact(FactSystem::defaultComponentId, maxTpl.arg(oneBasedChannel))->rawValue().toInt(&convertOk);
Don Gagne's avatar
Don Gagne committed
490
        QCOMPARE(convertOk, true);
Don Gagne's avatar
Don Gagne committed
491
        int rcTrimActual = _autopilot->getParameterFact(FactSystem::defaultComponentId, trimTpl.arg(oneBasedChannel))->rawValue().toInt(&convertOk);
Don Gagne's avatar
Don Gagne committed
492
        QCOMPARE(convertOk, true);
Don Gagne's avatar
Don Gagne committed
493
        float rcReversedFloat = _autopilot->getParameterFact(FactSystem::defaultComponentId, revTpl.arg(oneBasedChannel))->rawValue().toFloat(&convertOk);
Don Gagne's avatar
Don Gagne committed
494 495 496
        QCOMPARE(convertOk, true);
        bool rcReversedActual = (rcReversedFloat == -1.0f);
        
Lorenz Meier's avatar
Lorenz Meier committed
497 498
        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;
499

Don Gagne's avatar
Don Gagne committed
500 501 502 503
        QCOMPARE(rcMinExpected, rcMinActual);
        QCOMPARE(rcMaxExpected, rcMaxActual);
        QCOMPARE(rcTrimExpected, rcTrimActual);
        QCOMPARE(rcReversedExpected, rcReversedActual);
504 505
    }
    
Don Gagne's avatar
Don Gagne committed
506
    // Check mapping for all fuctions
507
    for (int chanFunction=0; chanFunction<RadioComponentController::rcCalFunctionMax; chanFunction++) {
Don Gagne's avatar
Don Gagne committed
508 509 510 511 512
        int expectedValue;
        if (_rgFunctionChannelMap[chanFunction] == -1) {
            expectedValue = 0;  // 0 signals no mapping
        } else {
            expectedValue = _rgFunctionChannelMap[chanFunction] + 1; // 1-based
513
        }
Don Gagne's avatar
Don Gagne committed
514 515 516 517 518
        const char* paramName = _functionInfo()[chanFunction].parameterName;
        if (paramName) {
            // qCDebug(RadioConfigTestLog) << chanFunction << expectedValue << mapParamsSet[paramName].toInt();
            QCOMPARE(_autopilot->getParameterFact(FactSystem::defaultComponentId, paramName)->rawValue().toInt(), expectedValue);
        }
519
    }
Don Gagne's avatar
Don Gagne committed
520
}
Don Gagne's avatar
Don Gagne committed
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545

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;
}