/*===================================================================== QGroundControl Open Source Ground Control Station (c) 2009 - 2014 QGROUNDCONTROL PROJECT 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 . ======================================================================*/ #include "PX4RCCalibrationTest.h" #include "UASManager.h" #include "AutoPilotPluginManager.h" /// @file /// @brief QPX4RCCalibration Widget unit test /// /// @author Don Gagne UT_REGISTER_TEST(PX4RCCalibrationTest) QGC_LOGGING_CATEGORY(PX4RCCalibrationTestLog, "PX4RCCalibrationTestLog") // 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) || \ _cancelButton->isEnabled() != !!((mask) & cancelButtonMask) ) { \ qCDebug(PX4RCCalibrationTestLog) << _statusLabel->text(); \ } \ 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) \ { \ if (mode == testModeStandalone && tryCancel ## cancelNum) { \ QTest::mouseClick(_cancelButton, Qt::LeftButton); \ QCOMPARE(_calWidget->_rcCalState, PX4RCCalibration::rcCalStateChannelWait); \ tryCancel ## cancelNum = false; \ goto StartOver; \ } else { \ QTest::mouseClick(_nextButton, Qt::LeftButton); \ } \ } const int PX4RCCalibrationTest::_stickSettleWait = PX4RCCalibration::_stickDetectSettleMSecs * 1.5; const int PX4RCCalibrationTest::_testMinValue = PX4RCCalibration::_rcCalPWMDefaultMinValue + 10; const int PX4RCCalibrationTest::_testMaxValue = PX4RCCalibration::_rcCalPWMDefaultMaxValue - 10; const int PX4RCCalibrationTest::_testCenterValue = PX4RCCalibrationTest::_testMinValue + ((PX4RCCalibrationTest::_testMaxValue - PX4RCCalibrationTest::_testMinValue) / 2); const struct PX4RCCalibrationTest::ChannelSettings PX4RCCalibrationTest::_rgChannelSettings[PX4RCCalibrationTest::_availableChannels] = { // Function Min Max # Reversed // Channel 0 : Not mapped to function, Simulate invalid Min/Max { PX4RCCalibration::rcCalFunctionMax, _testCenterValue, _testCenterValue, 0, false }, // Channels 1-4: Mapped to attitude control function { PX4RCCalibration::rcCalFunctionRoll, _testMinValue, _testMaxValue, 0, true }, { PX4RCCalibration::rcCalFunctionPitch, _testMinValue, _testMaxValue, 0, false }, { PX4RCCalibration::rcCalFunctionYaw, _testMinValue, _testMaxValue, 0, true }, { PX4RCCalibration::rcCalFunctionThrottle, _testMinValue, _testMaxValue, 0, false }, // 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 { PX4RCCalibration::rcCalFunctionFlaps, _testMinValue, _testMaxValue, 0, false }, { PX4RCCalibration::rcCalFunctionAux1, _testMinValue, _testMaxValue, 0, false }, { PX4RCCalibration::rcCalFunctionAux2, _testMinValue, _testMaxValue, 0, false }, // Channel 12 : Not mapped to function, Simulate invalid Min, valid Max { PX4RCCalibration::rcCalFunctionMax, _testCenterValue, _testMaxValue, 0, false }, // Channel 13 : Not mapped to function, Simulate valid Min, invalid Max { PX4RCCalibration::rcCalFunctionMax, _testMinValue, _testCenterValue, 0, false }, // Channels 14-17: Not mapped to function, Simulate invalid Min/Max, since available channel Min/Max is still shown { PX4RCCalibration::rcCalFunctionMax, _testCenterValue, _testCenterValue, 0, false }, { PX4RCCalibration::rcCalFunctionMax, _testCenterValue, _testCenterValue, 0, false }, { PX4RCCalibration::rcCalFunctionMax, _testCenterValue, _testCenterValue, 0, false }, { PX4RCCalibration::rcCalFunctionMax, _testCenterValue, _testCenterValue, 0, false }, }; const struct PX4RCCalibrationTest::ChannelSettings PX4RCCalibrationTest::_rgChannelSettingsValidate[PX4RCCalibration::_chanMax] = { // Function Min Value Max Value Trim Value Reversed // Channels 0: not mapped and should be set to defaults { PX4RCCalibration::rcCalFunctionMax, PX4RCCalibration::_rcCalPWMDefaultMinValue, PX4RCCalibration::_rcCalPWMDefaultMaxValue, PX4RCCalibration::_rcCalPWMCenterPoint, false }, // Channels 1-4: Mapped to attitude control function { PX4RCCalibration::rcCalFunctionRoll, _testMinValue, _testMaxValue, _testCenterValue, true }, { PX4RCCalibration::rcCalFunctionPitch, _testMinValue, _testMaxValue, _testCenterValue, false }, { PX4RCCalibration::rcCalFunctionYaw, _testMinValue, _testMaxValue, _testCenterValue, true }, { PX4RCCalibration::rcCalFunctionThrottle, _testMinValue, _testMaxValue, _testMinValue, false }, // 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 { PX4RCCalibration::rcCalFunctionFlaps, _testMinValue, _testMaxValue, _testCenterValue, false }, { PX4RCCalibration::rcCalFunctionAux1, _testMinValue, _testMaxValue, _testCenterValue, false }, { PX4RCCalibration::rcCalFunctionAux2, _testMinValue, _testMaxValue, _testCenterValue, false }, // 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 }, { PX4RCCalibration::rcCalFunctionMax, PX4RCCalibration::_rcCalPWMDefaultMinValue, PX4RCCalibration::_rcCalPWMDefaultMaxValue, PX4RCCalibration::_rcCalPWMCenterPoint, false }, { PX4RCCalibration::rcCalFunctionMax, PX4RCCalibration::_rcCalPWMDefaultMinValue, PX4RCCalibration::_rcCalPWMDefaultMaxValue, PX4RCCalibration::_rcCalPWMCenterPoint, false }, }; PX4RCCalibrationTest::PX4RCCalibrationTest(void) : _calWidget(NULL) { } void PX4RCCalibrationTest::init(void) { UnitTest::init(); _mockLink = new MockLink(); Q_CHECK_PTR(_mockLink); LinkManager::instance()->_addLink(_mockLink); LinkManager::instance()->connectLink(_mockLink); QTest::qWait(5000); // Give enough time for UI to settle and heartbeats to go through _autopilot = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(UASManager::instance()->getActiveUAS()); Q_ASSERT(_autopilot); QSignalSpy spyPlugin(_autopilot, SIGNAL(pluginReadyChanged(bool))); if (!_autopilot->pluginReady()) { QCOMPARE(spyPlugin.wait(60000), true); } Q_ASSERT(_autopilot->pluginReady()); // This will instatiate the widget with an active uas with ready parameters _calWidget = new PX4RCCalibration(); Q_CHECK_PTR(_calWidget); _calWidget->_setUnitTestMode(); // Get pointers to the push buttons _cancelButton = _calWidget->findChild("rcCalCancel"); _nextButton = _calWidget->findChild("rcCalNext"); _skipButton = _calWidget->findChild("rcCalSkip"); Q_ASSERT(_cancelButton); Q_ASSERT(_nextButton); Q_ASSERT(_skipButton); _statusLabel = _calWidget->findChild("rcCalStatus"); Q_ASSERT(_statusLabel); for (size_t i=0; ifindChild(radioWidgetName.arg(i+1)); Q_ASSERT(radioWidget); _rgValueWidget[i] = radioWidget; } _rgSignals[0] = SIGNAL(nextButtonMessageBoxDisplayed()); _multiSpyNextButtonMessageBox = new MultiSignalSpy(); Q_CHECK_PTR(_multiSpyNextButtonMessageBox); QCOMPARE(_multiSpyNextButtonMessageBox->init(_calWidget, _rgSignals, 1), true); QCOMPARE(_calWidget->_currentStep, -1); } void PX4RCCalibrationTest::cleanup(void) { Q_ASSERT(_calWidget); delete _calWidget; // Disconnecting the link will prompt for log file save setExpectedFileDialog(getSaveFileName, QStringList()); LinkManager::instance()->disconnectLink(_mockLink); UnitTest::cleanup(); } /// @brief Test for correct behavior in determining minimum numbers of channels for flight. void PX4RCCalibrationTest::_minRCChannels_test(void) { // Next button won't be enabled until we see the minimum number of channels. for (int chan=0; chanemitRemoteControlChannelRawChanged(chan, (float)PX4RCCalibration::_rcCalPWMCenterPoint); // We use _chanCount internally so we should validate it QCOMPARE(_calWidget->_chanCount, chan+1); // Validate Next button state QTest::mouseClick(_nextButton, Qt::LeftButton); bool signalFound = _multiSpyNextButtonMessageBox->waitForSignalByIndex(0, 200); if (chan == PX4RCCalibration::_chanMinimum - 1) { // Last channel should trigger Calibration available QCOMPARE(signalFound, false); QCOMPARE(_calWidget->_currentStep, 0); } else { // Still less than the minimum channels. Next button should show message box. Calibration should not start. QCOMPARE(signalFound, true); QCOMPARE(_calWidget->_currentStep, -1); } _multiSpyNextButtonMessageBox->clearAllSignals(); // 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 // Only available channels should have visible widget. A ui update cycle needs to have passed so we wait a little. QTest::qWait(PX4RCCalibration::_updateInterval * 2); for (int chanWidget=0; chanWidgetobjectName() << chanWidget << chan; QCOMPARE(_rgValueWidget[chanWidget]->isVisible(), !!(chanWidget <= chan)); } #endif } } void PX4RCCalibrationTest::_beginCalibration(void) { CHK_BUTTONS(nextButtonMask | cancelButtonMask); // 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); CHK_BUTTONS(cancelButtonMask); } void PX4RCCalibrationTest::_stickMoveWaitForSettle(int channel, int value) { qCDebug(PX4RCCalibrationTestLog) << "_stickMoveWaitForSettle channel:value" << channel << value; // Move the stick, this will initialized the settle checker _mockLink->emitRemoteControlChannelRawChanged(channel, value); // Emit the signal again to start the settle timer _mockLink->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 _mockLink->emitRemoteControlChannelRawChanged(channel, value); } void PX4RCCalibrationTest::_stickMoveAutoStep(const char* functionStr, enum PX4RCCalibration::rcCalFunctions function, enum PX4RCCalibrationTest::MoveToDirection direction, bool identifyStep) { Q_UNUSED(functionStr); qCDebug(PX4RCCalibrationTestLog) << "_stickMoveAutoStep function:direction:reversed:identifyStep" << functionStr << function << direction << identifyStep; CHK_BUTTONS(cancelButtonMask); int channel = _rgFunctionChannelMap[function]; int saveStep = _calWidget->_currentStep; bool reversed = _rgChannelSettings[channel].reversed; if (!identifyStep && direction != moveToCenter) { // We have already identified the function channel mapping. Move other channels around to make sure there is no impact. int otherChannel = channel + 1; if (otherChannel >= PX4RCCalibration::_chanMax) { otherChannel = 0; } _stickMoveWaitForSettle(otherChannel, _testMinValue); QCOMPARE(_calWidget->_currentStep, saveStep); CHK_BUTTONS(cancelButtonMask); _stickMoveWaitForSettle(otherChannel, PX4RCCalibration::_rcCalPWMCenterPoint); QCOMPARE(_calWidget->_currentStep, saveStep); CHK_BUTTONS(cancelButtonMask); } // 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); } _stickMoveWaitForSettle(channel, value); QCOMPARE(_calWidget->_currentStep, saveStep + 1); } void PX4RCCalibrationTest::_switchMinMaxStep(void) { CHK_BUTTONS(nextButtonMask | cancelButtonMask); // Try setting a min/max value that is below the threshold to make sure min/max doesn't go valid _mockLink->emitRemoteControlChannelRawChanged(0, (float)(PX4RCCalibration::_rcCalPWMValidMinValue + 1)); _mockLink->emitRemoteControlChannelRawChanged(0, (float)(PX4RCCalibration::_rcCalPWMValidMaxValue - 1)); QCOMPARE(_rgValueWidget[0]->isMinValid(), false); QCOMPARE(_rgValueWidget[0]->isMaxValid(), false); // Send min/max values switch channels for (int chan=0; chan<_availableChannels; chan++) { _mockLink->emitRemoteControlChannelRawChanged(chan, _rgChannelSettings[chan].rcMin); _mockLink->emitRemoteControlChannelRawChanged(chan, _rgChannelSettings[chan].rcMax); } _channelHomePosition(); int saveStep = _calWidget->_currentStep; QTest::mouseClick(_nextButton, Qt::LeftButton); QCOMPARE(_calWidget->_currentStep, saveStep + 1); } void PX4RCCalibrationTest::_flapsDetectStep(void) { int channel = _rgFunctionChannelMap[PX4RCCalibration::rcCalFunctionFlaps]; qCDebug(PX4RCCalibrationTestLog) << "_flapsDetectStep channel" << channel; // Test code can't handle reversed flaps channel Q_ASSERT(!_rgChannelSettings[channel].reversed); CHK_BUTTONS(nextButtonMask | cancelButtonMask | skipButtonMask); int saveStep = _calWidget->_currentStep; // Wiggle channel to identify _stickMoveWaitForSettle(channel, _testMaxValue); _stickMoveWaitForSettle(channel, _testMinValue); // Leave channel on full flaps down _stickMoveWaitForSettle(channel, _testMaxValue); // 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); } void PX4RCCalibrationTest::_switchSelectAutoStep(const char* functionStr, PX4RCCalibration::rcCalFunctions function) { Q_UNUSED(functionStr); ////qCDebug(PX4RCCalibrationTestLog)() << "_switchSelectAutoStep" << functionStr << "function:" << function; int buttonMask = cancelButtonMask; if (function != PX4RCCalibration::rcCalFunctionModeSwitch) { buttonMask |= skipButtonMask; } CHK_BUTTONS(buttonMask); int saveStep = _calWidget->_currentStep; // Wiggle stick for channel int channel = _rgFunctionChannelMap[function]; _mockLink->emitRemoteControlChannelRawChanged(channel, _testMinValue); _mockLink->emitRemoteControlChannelRawChanged(channel, _testMaxValue); QCOMPARE(_calWidget->_currentStep, saveStep + 1); } void PX4RCCalibrationTest::_fullCalibration_test(void) { // IMPORTANT NOTE: We used channels 1-5 for attitude mapping in the test below. // MockLink.params 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 /// _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; functiongetParameterFact(switchParam)->value().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] = _autopilot->getParameterFact(PX4RCCalibration::_rgFunctionInfo[function].parameterName)->value().toInt(); qCDebug(PX4RCCalibrationTestLog) << "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 } } } _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); // One more click and the parameters should get saved QTest::mouseClick(_nextButton, Qt::LeftButton); _validateParameters(); } /// @brief Sets rc input to Throttle down home position. Centers all other channels. void PX4RCCalibrationTest::_channelHomePosition(void) { // Initialize available channels to center point. for (int i=0; i<_availableChannels; i++) { _mockLink->emitRemoteControlChannelRawChanged(i, (float)PX4RCCalibration::_rcCalPWMCenterPoint); } // 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. _mockLink->emitRemoteControlChannelRawChanged(_rgFunctionChannelMap[PX4RCCalibration::rcCalFunctionThrottle], _testMinValue - 1); } void PX4RCCalibrationTest::_validateParameters(void) { QString minTpl("RC%1_MIN"); QString maxTpl("RC%1_MAX"); QString trimTpl("RC%1_TRIM"); QString revTpl("RC%1_REV"); // Check mapping for all fuctions for (int chanFunction=0; chanFunctiongetParameterFact(PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName)->value().toInt(); QCOMPARE(_autopilot->getParameterFact(PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName)->value().toInt(), expectedParameterValue); } // Validate the channel settings. Note the channels are 1-based in parameter names. for (int chan = 0; changetParameterFact(minTpl.arg(oneBasedChannel))->value().toInt(&convertOk); QCOMPARE(convertOk, true); int rcMaxActual = _autopilot->getParameterFact(maxTpl.arg(oneBasedChannel))->value().toInt(&convertOk); QCOMPARE(convertOk, true); int rcTrimActual = _autopilot->getParameterFact(trimTpl.arg(oneBasedChannel))->value().toInt(&convertOk); QCOMPARE(convertOk, true); float rcReversedFloat = _autopilot->getParameterFact(revTpl.arg(oneBasedChannel))->value().toFloat(&convertOk); QCOMPARE(convertOk, true); bool rcReversedActual = (rcReversedFloat == -1.0f); 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; QCOMPARE(rcMinExpected, rcMinActual); QCOMPARE(rcMaxExpected, rcMaxActual); QCOMPARE(rcTrimExpected, rcTrimActual); QCOMPARE(rcReversedExpected, rcReversedActual); } // Check mapping for all fuctions for (int chanFunction=0; chanFunctiongetParameterFact(PX4RCCalibration::_rgFunctionInfo[chanFunction].parameterName)->value().toInt(), expectedValue); } }