2 ******************************************************************************
4 * @file configinputwidget.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * @addtogroup GCSPlugins GCS Plugins
8 * @addtogroup ConfigPlugin Config Plugin
10 * @brief Servo input/output configuration panel for the config gadget
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "configinputwidget.h"
30 #include <extensionsystem/pluginmanager.h>
31 #include <coreplugin/generalsettings.h>
34 #include <QStringList>
37 #include <QVBoxLayout>
38 #include <QPushButton>
39 #include <QDesktopServices>
41 #include <QMessageBox>
42 #include <utils/stylehelper.h>
43 #include <QMessageBox>
45 #define ACCESS_MIN_MOVE -3
46 #define ACCESS_MAX_MOVE 3
47 #define STICK_MIN_MOVE -8
48 #define STICK_MAX_MOVE 8
50 #define CHANNEL_NUMBER_NONE 0
51 #define DEFAULT_FLIGHT_MODE_NUMBER 3
53 ConfigInputWidget::ConfigInputWidget(QWidget
*parent
) :
54 ConfigTaskWidget(parent
),
55 wizardStep(wizardNone
),
56 // not currently stored in the settings UAVO
57 transmitterMode(mode2
),
58 transmitterType(acro
),
64 nextDelayedLatestActivityTick(0),
65 accessoryDesiredObj0(NULL
),
66 accessoryDesiredObj1(NULL
),
67 accessoryDesiredObj2(NULL
)
69 manualCommandObj
= ManualControlCommand::GetInstance(getObjectManager());
70 manualSettingsObj
= ManualControlSettings::GetInstance(getObjectManager());
71 flightModeSettingsObj
= FlightModeSettings::GetInstance(getObjectManager());
72 flightStatusObj
= FlightStatus::GetInstance(getObjectManager());
73 receiverActivityObj
= ReceiverActivity::GetInstance(getObjectManager());
74 accessoryDesiredObj0
= AccessoryDesired::GetInstance(getObjectManager(), 0);
75 accessoryDesiredObj1
= AccessoryDesired::GetInstance(getObjectManager(), 1);
76 accessoryDesiredObj2
= AccessoryDesired::GetInstance(getObjectManager(), 2);
77 actuatorSettingsObj
= ActuatorSettings::GetInstance(getObjectManager());
78 systemSettingsObj
= SystemSettings::GetInstance(getObjectManager());
80 // Only instance 0 is present if the board is not connected.
81 // The other instances are populated lazily.
82 Q_ASSERT(accessoryDesiredObj0
);
84 ui
= new Ui_InputWidget();
87 wizardUi
= new Ui_InputWizardWidget();
88 wizardUi
->setupUi(ui
->wizard
);
90 addApplySaveButtons(ui
->saveRCInputToRAM
, ui
->saveRCInputToSD
);
92 ExtensionSystem::PluginManager
*pm
= ExtensionSystem::PluginManager::instance();
93 Core::Internal::GeneralSettings
*settings
= pm
->getObject
<Core::Internal::GeneralSettings
>();
94 if (!settings
->useExpertMode()) {
95 ui
->saveRCInputToRAM
->setVisible(false);
98 addApplySaveButtons(ui
->saveRCInputToRAM
, ui
->saveRCInputToSD
);
100 // Generate the rows of buttons in the input channel form GUI
101 unsigned int index
= 0;
102 unsigned int indexRT
= 0;
103 foreach(QString name
, manualSettingsObj
->getField("ChannelNumber")->getElementNames()) {
104 Q_ASSERT(index
< ManualControlSettings::CHANNELGROUPS_NUMELEM
);
105 InputChannelForm
*form
= new InputChannelForm(index
, this);
108 form
->moveTo(*(ui
->channelLayout
));
110 // The order of the following binding calls is important. Since the values will be populated
111 // in reverse order of the binding order otherwise the 'Reversed' logic will floor the neutral value
112 // to the max value ( which is smaller than the neutral value when reversed ) and the channel number
113 // will not be set correctly.
114 addWidgetBinding("ManualControlSettings", "ChannelNumber", form
->ui
->channelNumber
, index
);
115 addWidgetBinding("ManualControlSettings", "ChannelGroups", form
->ui
->channelGroup
, index
);
116 // Slider position based on real time Rcinput (allow monitoring)
117 addWidgetBinding("ManualControlCommand", "Channel", form
->ui
->channelNeutral
, index
);
118 // Neutral value stored on board (SpinBox)
119 addWidgetBinding("ManualControlSettings", "ChannelNeutral", form
->ui
->neutralValue
, index
);
120 addWidgetBinding("ManualControlSettings", "ChannelMax", form
->ui
->channelMax
, index
);
121 addWidgetBinding("ManualControlSettings", "ChannelMin", form
->ui
->channelMin
, index
);
122 addWidgetBinding("ManualControlSettings", "ChannelMax", form
->ui
->channelMax
, index
);
124 addWidget(form
->ui
->channelRev
);
126 // Reversing supported for some channels only
127 bool reversable
= ((index
== ManualControlSettings::CHANNELGROUPS_THROTTLE
) ||
128 (index
== ManualControlSettings::CHANNELGROUPS_ROLL
) ||
129 (index
== ManualControlSettings::CHANNELGROUPS_PITCH
) ||
130 (index
== ManualControlSettings::CHANNELGROUPS_YAW
));
131 form
->ui
->channelRev
->setVisible(reversable
);
133 // Input filter response time fields supported for some channels only
135 case ManualControlSettings::CHANNELGROUPS_ROLL
:
136 case ManualControlSettings::CHANNELGROUPS_PITCH
:
137 case ManualControlSettings::CHANNELGROUPS_YAW
:
138 case ManualControlSettings::CHANNELGROUPS_COLLECTIVE
:
139 case ManualControlSettings::CHANNELGROUPS_ACCESSORY0
:
140 case ManualControlSettings::CHANNELGROUPS_ACCESSORY1
:
141 case ManualControlSettings::CHANNELGROUPS_ACCESSORY2
:
142 addWidgetBinding("ManualControlSettings", "ResponseTime", form
->ui
->channelResponseTime
, indexRT
);
145 case ManualControlSettings::CHANNELGROUPS_THROTTLE
:
146 case ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
:
147 form
->ui
->channelResponseTime
->setVisible(false);
157 addWidgetBinding("ManualControlSettings", "Deadband", ui
->deadband
, 0, 0.01f
);
158 addWidgetBinding("ManualControlSettings", "DeadbandAssistedControl", ui
->assistedControlDeadband
, 0, 0.01f
);
160 connect(ui
->configurationWizard
, SIGNAL(clicked()), this, SLOT(goToWizard()));
161 connect(ui
->stackedWidget
, SIGNAL(currentChanged(int)), this, SLOT(disableWizardButton(int)));
162 connect(ui
->runCalibration
, SIGNAL(toggled(bool)), this, SLOT(simpleCalibration(bool)));
164 connect(wizardUi
->wzNext
, SIGNAL(clicked()), this, SLOT(wzNext()));
165 connect(wizardUi
->wzCancel
, SIGNAL(clicked()), this, SLOT(wzCancel()));
166 connect(wizardUi
->wzBack
, SIGNAL(clicked()), this, SLOT(wzBack()));
168 ui
->stackedWidget
->setCurrentIndex(0);
169 addWidgetBinding("FlightModeSettings", "FlightModePosition", ui
->fmsModePos1
, 0, 1, true);
170 addWidgetBinding("FlightModeSettings", "FlightModePosition", ui
->fmsModePos2
, 1, 1, true);
171 addWidgetBinding("FlightModeSettings", "FlightModePosition", ui
->fmsModePos3
, 2, 1, true);
172 addWidgetBinding("FlightModeSettings", "FlightModePosition", ui
->fmsModePos4
, 3, 1, true);
173 addWidgetBinding("FlightModeSettings", "FlightModePosition", ui
->fmsModePos5
, 4, 1, true);
174 addWidgetBinding("FlightModeSettings", "FlightModePosition", ui
->fmsModePos6
, 5, 1, true);
175 addWidgetBinding("ManualControlSettings", "FlightModeNumber", ui
->fmsPosNum
);
177 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Roll
, "Roll", 1, true);
178 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Roll
, "Roll", 1, true);
179 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Roll
, "Roll", 1, true);
180 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Roll
, "Roll", 1, true);
181 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Roll
, "Roll", 1, true);
182 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Roll
, "Roll", 1, true);
183 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Pitch
, "Pitch", 1, true);
184 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Pitch
, "Pitch", 1, true);
185 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Pitch
, "Pitch", 1, true);
186 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Pitch
, "Pitch", 1, true);
187 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Pitch
, "Pitch", 1, true);
188 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Pitch
, "Pitch", 1, true);
189 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Yaw
, "Yaw", 1, true);
190 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Yaw
, "Yaw", 1, true);
191 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Yaw
, "Yaw", 1, true);
192 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Yaw
, "Yaw", 1, true);
193 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Yaw
, "Yaw", 1, true);
194 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Yaw
, "Yaw", 1, true);
195 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Thrust
, "Thrust", 1, true);
196 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Thrust
, "Thrust", 1, true);
197 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Thrust
, "Thrust", 1, true);
198 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Thrust
, "Thrust", 1, true);
199 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Thrust
, "Thrust", 1, true);
200 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Thrust
, "Thrust", 1, true);
202 addWidgetBinding("FlightModeSettings", "Arming", ui
->armControl
);
203 addWidgetBinding("FlightModeSettings", "ArmedTimeout", ui
->armTimeout
, 0, 1000);
204 connect(ManualControlCommand::GetInstance(getObjectManager()), SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveFMSlider()));
205 connect(ManualControlSettings::GetInstance(getObjectManager()), SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(updatePositionSlider()));
207 addWidget(ui
->configurationWizard
);
208 addWidget(ui
->runCalibration
);
213 refreshWidgetsValues();
214 // Connect the help button
215 connect(ui
->inputHelp
, SIGNAL(clicked()), this, SLOT(openHelp()));
217 wizardUi
->graphicsView
->setScene(new QGraphicsScene(this));
218 wizardUi
->graphicsView
->setViewportUpdateMode(QGraphicsView::FullViewportUpdate
);
219 m_renderer
= new QSvgRenderer();
220 QGraphicsScene
*l_scene
= wizardUi
->graphicsView
->scene();
221 wizardUi
->graphicsView
->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor()));
222 if (QFile::exists(":/configgadget/images/TX2.svg") && m_renderer
->load(QString(":/configgadget/images/TX2.svg")) && m_renderer
->isValid()) {
223 l_scene
->clear(); // Deletes all items contained in the scene as well.
225 m_txBackground
= new QGraphicsSvgItem();
226 // All other items will be clipped to the shape of the background
227 m_txBackground
->setFlags(QGraphicsItem::ItemClipsChildrenToShape
|
228 QGraphicsItem::ItemClipsToShape
);
229 m_txBackground
->setSharedRenderer(m_renderer
);
230 m_txBackground
->setElementId("background");
231 l_scene
->addItem(m_txBackground
);
233 m_txMainBody
= new QGraphicsSvgItem();
234 m_txMainBody
->setParentItem(m_txBackground
);
235 m_txMainBody
->setSharedRenderer(m_renderer
);
236 m_txMainBody
->setElementId("body");
237 l_scene
->addItem(m_txMainBody
);
239 m_txLeftStick
= new QGraphicsSvgItem();
240 m_txLeftStick
->setParentItem(m_txBackground
);
241 m_txLeftStick
->setSharedRenderer(m_renderer
);
242 m_txLeftStick
->setElementId("ljoy");
244 m_txRightStick
= new QGraphicsSvgItem();
245 m_txRightStick
->setParentItem(m_txBackground
);
246 m_txRightStick
->setSharedRenderer(m_renderer
);
247 m_txRightStick
->setElementId("rjoy");
249 m_txAccess0
= new QGraphicsSvgItem();
250 m_txAccess0
->setParentItem(m_txBackground
);
251 m_txAccess0
->setSharedRenderer(m_renderer
);
252 m_txAccess0
->setElementId("access0");
254 m_txAccess1
= new QGraphicsSvgItem();
255 m_txAccess1
->setParentItem(m_txBackground
);
256 m_txAccess1
->setSharedRenderer(m_renderer
);
257 m_txAccess1
->setElementId("access1");
259 m_txAccess2
= new QGraphicsSvgItem();
260 m_txAccess2
->setParentItem(m_txBackground
);
261 m_txAccess2
->setSharedRenderer(m_renderer
);
262 m_txAccess2
->setElementId("access2");
264 m_txFlightMode
= new QGraphicsSvgItem();
265 m_txFlightMode
->setParentItem(m_txBackground
);
266 m_txFlightMode
->setSharedRenderer(m_renderer
);
267 m_txFlightMode
->setElementId("flightModeCenter");
268 m_txFlightMode
->setZValue(-10);
270 m_txArrows
= new QGraphicsSvgItem();
271 m_txArrows
->setParentItem(m_txBackground
);
272 m_txArrows
->setSharedRenderer(m_renderer
);
273 m_txArrows
->setElementId("arrows");
274 m_txArrows
->setVisible(false);
276 QRectF orig
= m_renderer
->boundsOnElement("ljoy");
277 QMatrix Matrix
= m_renderer
->matrixForElement("ljoy");
278 orig
= Matrix
.mapRect(orig
);
279 m_txLeftStickOrig
.translate(orig
.x(), orig
.y());
280 m_txLeftStick
->setTransform(m_txLeftStickOrig
, false);
282 orig
= m_renderer
->boundsOnElement("arrows");
283 Matrix
= m_renderer
->matrixForElement("arrows");
284 orig
= Matrix
.mapRect(orig
);
285 m_txArrowsOrig
.translate(orig
.x(), orig
.y());
286 m_txArrows
->setTransform(m_txArrowsOrig
, false);
288 orig
= m_renderer
->boundsOnElement("body");
289 Matrix
= m_renderer
->matrixForElement("body");
290 orig
= Matrix
.mapRect(orig
);
291 m_txMainBodyOrig
.translate(orig
.x(), orig
.y());
292 m_txMainBody
->setTransform(m_txMainBodyOrig
, false);
294 orig
= m_renderer
->boundsOnElement("flightModeCenter");
295 Matrix
= m_renderer
->matrixForElement("flightModeCenter");
296 orig
= Matrix
.mapRect(orig
);
297 m_txFlightModeCOrig
.translate(orig
.x(), orig
.y());
298 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
300 orig
= m_renderer
->boundsOnElement("flightModeLeft");
301 Matrix
= m_renderer
->matrixForElement("flightModeLeft");
302 orig
= Matrix
.mapRect(orig
);
303 m_txFlightModeLOrig
.translate(orig
.x(), orig
.y());
304 orig
= m_renderer
->boundsOnElement("flightModeRight");
305 Matrix
= m_renderer
->matrixForElement("flightModeRight");
306 orig
= Matrix
.mapRect(orig
);
307 m_txFlightModeROrig
.translate(orig
.x(), orig
.y());
309 orig
= m_renderer
->boundsOnElement("rjoy");
310 Matrix
= m_renderer
->matrixForElement("rjoy");
311 orig
= Matrix
.mapRect(orig
);
312 m_txRightStickOrig
.translate(orig
.x(), orig
.y());
313 m_txRightStick
->setTransform(m_txRightStickOrig
, false);
315 orig
= m_renderer
->boundsOnElement("access0");
316 Matrix
= m_renderer
->matrixForElement("access0");
317 orig
= Matrix
.mapRect(orig
);
318 m_txAccess0Orig
.translate(orig
.x(), orig
.y());
319 m_txAccess0
->setTransform(m_txAccess0Orig
, false);
321 orig
= m_renderer
->boundsOnElement("access1");
322 Matrix
= m_renderer
->matrixForElement("access1");
323 orig
= Matrix
.mapRect(orig
);
324 m_txAccess1Orig
.translate(orig
.x(), orig
.y());
325 m_txAccess1
->setTransform(m_txAccess1Orig
, false);
327 orig
= m_renderer
->boundsOnElement("access2");
328 Matrix
= m_renderer
->matrixForElement("access2");
329 orig
= Matrix
.mapRect(orig
);
330 m_txAccess2Orig
.translate(orig
.x(), orig
.y());
331 m_txAccess2
->setTransform(m_txAccess2Orig
, true);
333 wizardUi
->graphicsView
->fitInView(m_txMainBody
, Qt::KeepAspectRatio
);
334 animate
= new QTimer(this);
335 connect(animate
, SIGNAL(timeout()), this, SLOT(moveTxControls()));
337 heliChannelOrder
<< ManualControlSettings::CHANNELGROUPS_COLLECTIVE
<<
338 ManualControlSettings::CHANNELGROUPS_THROTTLE
<<
339 ManualControlSettings::CHANNELGROUPS_ROLL
<<
340 ManualControlSettings::CHANNELGROUPS_PITCH
<<
341 ManualControlSettings::CHANNELGROUPS_YAW
<<
342 ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
<<
343 ManualControlSettings::CHANNELGROUPS_ACCESSORY0
<<
344 ManualControlSettings::CHANNELGROUPS_ACCESSORY1
<<
345 ManualControlSettings::CHANNELGROUPS_ACCESSORY2
;
347 acroChannelOrder
<< ManualControlSettings::CHANNELGROUPS_THROTTLE
<<
348 ManualControlSettings::CHANNELGROUPS_ROLL
<<
349 ManualControlSettings::CHANNELGROUPS_PITCH
<<
350 ManualControlSettings::CHANNELGROUPS_YAW
<<
351 ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
<<
352 ManualControlSettings::CHANNELGROUPS_ACCESSORY0
<<
353 ManualControlSettings::CHANNELGROUPS_ACCESSORY1
<<
354 ManualControlSettings::CHANNELGROUPS_ACCESSORY2
;
356 groundChannelOrder
<< ManualControlSettings::CHANNELGROUPS_THROTTLE
<<
357 ManualControlSettings::CHANNELGROUPS_YAW
<<
358 ManualControlSettings::CHANNELGROUPS_ACCESSORY0
;
360 updateEnableControls();
363 void ConfigInputWidget::resetTxControls()
365 m_txLeftStick
->setTransform(m_txLeftStickOrig
, false);
366 m_txRightStick
->setTransform(m_txRightStickOrig
, false);
367 m_txAccess0
->setTransform(m_txAccess0Orig
, false);
368 m_txAccess1
->setTransform(m_txAccess1Orig
, false);
369 m_txAccess2
->setTransform(m_txAccess2Orig
, false);
370 m_txFlightMode
->setElementId("flightModeCenter");
371 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
372 m_txArrows
->setVisible(false);
375 ConfigInputWidget::~ConfigInputWidget()
378 void ConfigInputWidget::enableControls(bool enable
)
380 ConfigTaskWidget::enableControls(enable
);
383 updatePositionSlider();
387 void ConfigInputWidget::resizeEvent(QResizeEvent
*event
)
389 QWidget::resizeEvent(event
);
391 wizardUi
->graphicsView
->fitInView(m_txBackground
, Qt::KeepAspectRatio
);
394 void ConfigInputWidget::openHelp()
396 QDesktopServices::openUrl(QUrl(tr("http://wiki.openpilot.org/x/04Cf"), QUrl::StrictMode
));
399 void ConfigInputWidget::goToWizard()
403 msgBox
.setText(tr("Arming Settings are now set to 'Always Disarmed' for your safety."));
404 msgBox
.setDetailedText(tr("You will have to reconfigure the arming settings manually "
405 "when the wizard is finished. After the last step of the "
406 "wizard you will be taken to the Arming Settings screen."));
407 msgBox
.setStandardButtons(QMessageBox::Ok
);
408 msgBox
.setDefaultButton(QMessageBox::Ok
);
411 // Set correct tab visible before starting wizard.
412 if (ui
->tabWidget
->currentIndex() != 0) {
413 ui
->tabWidget
->setCurrentIndex(0);
416 // Stash current manual settings data in case the wizard is
417 // cancelled or the user proceeds far enough into the wizard such
418 // that the UAVO is changed, but then backs out to the start and
419 // chooses a different TX type (which could otherwise result in
420 // unexpected TX channels being enabled)
421 manualSettingsData
= manualSettingsObj
->getData();
422 memento
.manualSettingsData
= manualSettingsData
;
423 flightModeSettingsData
= flightModeSettingsObj
->getData();
424 memento
.flightModeSettingsData
= flightModeSettingsData
;
425 flightModeSettingsData
.Arming
= FlightModeSettings::ARMING_ALWAYSDISARMED
;
426 flightModeSettingsObj
->setData(flightModeSettingsData
);
427 // Stash actuatorSettings
428 actuatorSettingsData
= actuatorSettingsObj
->getData();
429 memento
.actuatorSettingsData
= actuatorSettingsData
;
431 // Stash systemSettings
432 systemSettingsData
= systemSettingsObj
->getData();
433 memento
.systemSettingsData
= systemSettingsData
;
435 // Now reset channel and actuator settings (disable outputs)
436 resetChannelSettings();
437 resetActuatorSettings();
439 // Use faster input update rate.
443 wizardSetUpStep(wizardWelcome
);
444 wizardUi
->graphicsView
->fitInView(m_txBackground
, Qt::KeepAspectRatio
);
447 void ConfigInputWidget::disableWizardButton(int value
)
450 ui
->groupBox_3
->setVisible(false);
452 ui
->groupBox_3
->setVisible(true);
456 void ConfigInputWidget::wzCancel()
458 dimOtherControls(false);
460 // Cancel any ongoing delayd next trigger.
461 wzNextDelayedCancel();
463 // Restore original input update rate.
466 ui
->stackedWidget
->setCurrentIndex(0);
468 if (wizardStep
!= wizardNone
) {
469 wizardTearDownStep(wizardStep
);
471 wizardStep
= wizardNone
;
472 ui
->stackedWidget
->setCurrentIndex(0);
474 // Load settings back from beginning of wizard
475 manualSettingsObj
->setData(memento
.manualSettingsData
);
476 flightModeSettingsObj
->setData(memento
.flightModeSettingsData
);
477 actuatorSettingsObj
->setData(memento
.actuatorSettingsData
);
478 systemSettingsObj
->setData(memento
.systemSettingsData
);
481 void ConfigInputWidget::registerControlActivity()
483 nextDelayedLatestActivityTick
= nextDelayedTick
;
486 void ConfigInputWidget::wzNextDelayed()
490 // Call next after the full 2500 ms timeout has been reached,
491 // or if no input activity has occurred the last 500 ms.
492 if (nextDelayedTick
== 25 ||
493 nextDelayedTick
- nextDelayedLatestActivityTick
>= 5) {
498 void ConfigInputWidget::wzNextDelayedStart()
500 // Call wzNextDelayed every 100 ms, to see if it's time to go to the next page.
501 connect(&nextDelayedTimer
, SIGNAL(timeout()), this, SLOT(wzNextDelayed()));
502 nextDelayedTimer
.start(100);
505 // Cancel the delayed next timer, if it's active.
506 void ConfigInputWidget::wzNextDelayedCancel()
509 nextDelayedLatestActivityTick
= 0;
510 if (nextDelayedTimer
.isActive()) {
511 nextDelayedTimer
.stop();
512 disconnect(&nextDelayedTimer
, SIGNAL(timeout()), this, SLOT(wzNextDelayed()));
516 void ConfigInputWidget::wzNext()
518 wzNextDelayedCancel();
520 // In identify sticks mode the next button can indicate
522 if (wizardStep
!= wizardNone
&&
523 wizardStep
!= wizardIdentifySticks
) {
524 wizardTearDownStep(wizardStep
);
527 // State transitions for next button
528 switch (wizardStep
) {
530 wizardSetUpStep(wizardChooseType
);
532 case wizardChooseType
:
533 wizardSetUpStep(wizardChooseMode
);
535 case wizardChooseMode
:
536 wizardSetUpStep(wizardIdentifySticks
);
538 case wizardIdentifySticks
:
540 if (currentChannelNum
== -1) { // Gone through all channels
541 wizardTearDownStep(wizardIdentifySticks
);
542 wizardSetUpStep(wizardIdentifyCenter
);
545 case wizardIdentifyCenter
:
546 wizardSetUpStep(wizardIdentifyLimits
);
548 case wizardIdentifyLimits
:
549 wizardSetUpStep(wizardIdentifyInverted
);
551 case wizardIdentifyInverted
:
552 wizardSetUpStep(wizardFinish
);
555 wizardStep
= wizardNone
;
557 // Restore original input update rate.
560 // Load actuator settings back from beginning of wizard
561 actuatorSettingsObj
->setData(memento
.actuatorSettingsData
);
563 // Force flight mode neutral to middle and Throttle neutral at 4%
564 adjustSpecialNeutrals();
565 throttleError
= false;
566 checkThrottleRange();
568 // Force flight mode number to be 1 if 2 CH ground vehicle was selected
569 if (transmitterType
== ground
) {
570 forceOneFlightMode();
573 manualSettingsObj
->setData(manualSettingsData
);
574 // move to Arming Settings tab
575 ui
->stackedWidget
->setCurrentIndex(0);
576 ui
->tabWidget
->setCurrentIndex(2);
583 void ConfigInputWidget::wzBack()
585 wzNextDelayedCancel();
587 if (wizardStep
!= wizardNone
&&
588 wizardStep
!= wizardIdentifySticks
) {
589 wizardTearDownStep(wizardStep
);
592 // State transitions for next button
593 switch (wizardStep
) {
594 case wizardChooseType
:
595 wizardSetUpStep(wizardWelcome
);
597 case wizardChooseMode
:
598 wizardSetUpStep(wizardChooseType
);
600 case wizardIdentifySticks
:
602 if (currentChannelNum
== -1) {
603 wizardTearDownStep(wizardIdentifySticks
);
604 wizardSetUpStep(wizardChooseMode
);
607 case wizardIdentifyCenter
:
608 wizardSetUpStep(wizardIdentifySticks
);
610 case wizardIdentifyLimits
:
611 wizardSetUpStep(wizardIdentifyCenter
);
613 case wizardIdentifyInverted
:
614 wizardSetUpStep(wizardIdentifyLimits
);
617 wizardSetUpStep(wizardIdentifyInverted
);
624 void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step
)
626 wizardUi
->wzNext
->setText(tr("Next"));
630 foreach(QPointer
<QWidget
> wd
, extraWidgets
) {
635 extraWidgets
.clear();
636 wizardUi
->graphicsView
->setVisible(false);
637 setTxMovement(nothing
);
638 wizardUi
->wzBack
->setEnabled(false);
639 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->welcomePage
);
640 ui
->stackedWidget
->setCurrentIndex(1);
642 case wizardChooseType
:
644 wizardUi
->graphicsView
->setVisible(true);
645 wizardUi
->graphicsView
->fitInView(m_txBackground
, Qt::KeepAspectRatio
);
646 setTxMovement(nothing
);
647 wizardUi
->wzBack
->setEnabled(true);
648 if (transmitterType
== heli
) {
649 wizardUi
->typeHeli
->setChecked(true);
650 } else if (transmitterType
== ground
) {
651 wizardUi
->typeGround
->setChecked(true);
653 wizardUi
->typeAcro
->setChecked(true);
655 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->chooseTypePage
);
658 case wizardChooseMode
:
660 wizardUi
->wzBack
->setEnabled(true);
661 QRadioButton
*modeButtons
[] = {
662 wizardUi
->mode1Button
,
663 wizardUi
->mode2Button
,
664 wizardUi
->mode3Button
,
665 wizardUi
->mode4Button
668 for (int i
= 0; i
<= mode4
; ++i
) {
670 txMode mode
= static_cast<txMode
>(i
);
671 if (transmitterType
== heli
) {
673 case mode1
: label
= tr("Mode 1: Fore/Aft Cyclic and Yaw on the left, Throttle/Collective and Left/Right Cyclic on the right"); break;
674 case mode2
: label
= tr("Mode 2: Throttle/Collective and Yaw on the left, Cyclic on the right"); break;
675 case mode3
: label
= tr("Mode 3: Cyclic on the left, Throttle/Collective and Yaw on the right"); break;
676 case mode4
: label
= tr("Mode 4: Throttle/Collective and Left/Right Cyclic on the left, Fore/Aft Cyclic and Yaw on the right"); break;
677 default: Q_ASSERT(0); break;
679 wizardUi
->typePageFooter
->setText(" ");
682 case mode1
: label
= tr("Mode 1: Elevator and Rudder on the left, Throttle and Ailerons on the right"); break;
683 case mode2
: label
= tr("Mode 2: Throttle and Rudder on the left, Elevator and Ailerons on the right"); break;
684 case mode3
: label
= tr("Mode 3: Elevator and Ailerons on the left, Throttle and Rudder on the right"); break;
685 case mode4
: label
= tr("Mode 4: Throttle and Ailerons on the left, Elevator and Rudder on the right"); break;
686 default: Q_ASSERT(0); break;
688 wizardUi
->typePageFooter
->setText(tr("For a Quad: Elevator is Pitch, Ailerons are Roll, and Rudder is Yaw."));
690 modeButtons
[i
]->setText(label
);
691 if (transmitterMode
== mode
) {
692 modeButtons
[i
]->setChecked(true);
695 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->chooseModePage
);
698 case wizardIdentifySticks
:
699 usedChannels
.clear();
700 currentChannelNum
= -1;
702 manualSettingsData
= manualSettingsObj
->getData();
703 connect(receiverActivityObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyControls()));
704 wizardUi
->wzNext
->setEnabled(false);
705 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifySticksPage
);
707 case wizardIdentifyCenter
:
708 setTxMovement(centerAll
);
709 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifyCenterPage
);
710 if (transmitterType
== ground
) {
711 wizardUi
->identifyCenterInstructions
->setText(QString(tr("Please center all controls and trims and press Next when ready.\n\n"
712 "For a ground vehicle, this center position will be used as neutral value of each channel.")));
715 case wizardIdentifyLimits
:
717 setTxMovement(nothing
);
718 manualSettingsData
= manualSettingsObj
->getData();
719 for (uint i
= 0; i
< ManualControlSettings::CHANNELMAX_NUMELEM
; ++i
) {
720 // Preserve the inverted status
721 if (manualSettingsData
.ChannelMin
[i
] <= manualSettingsData
.ChannelMax
[i
]) {
722 manualSettingsData
.ChannelMin
[i
] = manualSettingsData
.ChannelNeutral
[i
];
723 manualSettingsData
.ChannelMax
[i
] = manualSettingsData
.ChannelNeutral
[i
];
725 // Make this detect as still inverted
726 manualSettingsData
.ChannelMin
[i
] = manualSettingsData
.ChannelNeutral
[i
] + 1;
727 manualSettingsData
.ChannelMax
[i
] = manualSettingsData
.ChannelNeutral
[i
];
730 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyLimits()));
731 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
732 connect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
733 connect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
735 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifyLimitsPage
);
738 case wizardIdentifyInverted
:
739 dimOtherControls(true);
740 setTxMovement(nothing
);
741 extraWidgets
.clear();
742 for (int index
= 0; index
< manualSettingsObj
->getField("ChannelMax")->getElementNames().length(); index
++) {
743 QString name
= manualSettingsObj
->getField("ChannelMax")->getElementNames().at(index
);
744 if (!name
.contains("Access") && !name
.contains("Flight") &&
745 (!name
.contains("Collective") || transmitterType
== heli
)) {
746 QCheckBox
*cb
= new QCheckBox(name
, this);
747 // Make sure checked status matches current one
748 cb
->setChecked(manualSettingsData
.ChannelMax
[index
] < manualSettingsData
.ChannelMin
[index
]);
749 wizardUi
->checkBoxesLayout
->addWidget(cb
, extraWidgets
.size() / 4, extraWidgets
.size() % 4);
750 extraWidgets
.append(cb
);
751 connect(cb
, SIGNAL(toggled(bool)), this, SLOT(invertControls()));
754 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
755 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifyInvertedPage
);
758 dimOtherControls(false);
759 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
760 connect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
761 connect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
762 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->finishPage
);
770 void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step
)
772 Q_ASSERT(step
== wizardStep
);
776 case wizardChooseType
:
777 if (wizardUi
->typeAcro
->isChecked()) {
778 transmitterType
= acro
;
779 } else if (wizardUi
->typeGround
->isChecked()) {
780 transmitterType
= ground
;
781 /* Make sure to tell controller, this is really a ground vehicle. */
782 systemSettingsData
= systemSettingsObj
->getData();
783 systemSettingsData
.AirframeType
= SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR
;
784 systemSettingsObj
->setData(systemSettingsData
);
786 transmitterType
= heli
;
789 case wizardChooseMode
:
791 QRadioButton
*modeButtons
[] = {
792 wizardUi
->mode1Button
,
793 wizardUi
->mode2Button
,
794 wizardUi
->mode3Button
,
795 wizardUi
->mode4Button
797 for (int i
= mode1
; i
<= mode4
; ++i
) {
798 if (modeButtons
[i
]->isChecked()) {
799 transmitterMode
= static_cast<txMode
>(i
);
804 case wizardIdentifySticks
:
805 disconnect(receiverActivityObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyControls()));
806 wizardUi
->wzNext
->setEnabled(true);
807 setTxMovement(nothing
);
808 /* If flight mode stick isn't identified, force flight mode number to be 1 */
809 manualSettingsData
= manualSettingsObj
->getData();
810 if (manualSettingsData
.ChannelGroups
[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE
] ==
811 ManualControlSettings::CHANNELGROUPS_NONE
) {
812 forceOneFlightMode();
815 case wizardIdentifyCenter
:
816 manualCommandData
= manualCommandObj
->getData();
817 manualSettingsData
= manualSettingsObj
->getData();
818 for (unsigned int i
= 0; i
< ManualControlCommand::CHANNEL_NUMELEM
; ++i
) {
819 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
821 manualSettingsObj
->setData(manualSettingsData
);
822 setTxMovement(nothing
);
824 case wizardIdentifyLimits
:
825 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyLimits()));
826 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
827 disconnect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
828 disconnect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
829 manualSettingsObj
->setData(manualSettingsData
);
830 setTxMovement(nothing
);
832 case wizardIdentifyInverted
:
833 dimOtherControls(false);
834 foreach(QWidget
* wd
, extraWidgets
) {
835 QCheckBox
*cb
= qobject_cast
<QCheckBox
*>(wd
);
838 disconnect(cb
, SIGNAL(toggled(bool)), this, SLOT(invertControls()));
842 extraWidgets
.clear();
843 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
846 dimOtherControls(false);
847 setTxMovement(nothing
);
848 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
849 disconnect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
850 disconnect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
857 static void fastMdataSingle(UAVDataObject
*object
, UAVObject::Metadata
*savedMdata
)
859 *savedMdata
= object
->getMetadata();
860 UAVObject::Metadata mdata
= *savedMdata
;
861 UAVObject::SetFlightTelemetryUpdateMode(mdata
, UAVObject::UPDATEMODE_PERIODIC
);
862 mdata
.flightTelemetryUpdatePeriod
= 150;
863 object
->setMetadata(mdata
);
866 static void restoreMdataSingle(UAVDataObject
*object
, UAVObject::Metadata
*savedMdata
)
868 object
->setMetadata(*savedMdata
);
872 * Set manual control command to fast updates
874 void ConfigInputWidget::fastMdata()
876 fastMdataSingle(manualCommandObj
, &manualControlMdata
);
877 fastMdataSingle(accessoryDesiredObj0
, &accessoryDesiredMdata0
);
881 * Restore previous update settings for manual control data
883 void ConfigInputWidget::restoreMdata()
885 restoreMdataSingle(manualCommandObj
, &manualControlMdata
);
886 restoreMdataSingle(accessoryDesiredObj0
, &accessoryDesiredMdata0
);
890 * Set the display to indicate which channel the person should move
892 void ConfigInputWidget::setChannel(int newChan
)
894 bool canBeSkipped
= false;
896 if (newChan
== ManualControlSettings::CHANNELGROUPS_COLLECTIVE
) {
897 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please enable throttle hold mode.</p>"
898 "<p>Move the Collective Pitch stick.</p>")));
899 } else if (newChan
== ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
) {
900 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please toggle the Flight Mode switch.</p>"
901 "<p>For switches you may have to repeat this rapidly.</p>"
902 "<p>Alternatively, you can click Next to skip this channel, but you will get only <b>ONE</b> Flight Mode.</p>")));
904 } else if ((transmitterType
== heli
) && (newChan
== ManualControlSettings::CHANNELGROUPS_THROTTLE
)) {
905 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please disable throttle hold mode.</p>"
906 "<p>Move the Throttle stick.</p>")));
908 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please move each control one at a time according to the instructions and picture below.</p>"
909 "<p>Move the %1 stick.</p>")).arg(manualSettingsObj
->getField("ChannelGroups")->getElementNames().at(newChan
)));
912 if (manualSettingsObj
->getField("ChannelGroups")->getElementNames().at(newChan
).contains("Accessory")) {
913 wizardUi
->identifyStickInstructions
->setText(wizardUi
->identifyStickInstructions
->text() + tr("<p>Alternatively, click Next to skip this channel.</p>"));
918 wizardUi
->wzNext
->setEnabled(true);
919 wizardUi
->wzNext
->setText(tr("Next / Skip"));
921 wizardUi
->wzNext
->setEnabled(false);
924 setMoveFromCommand(newChan
);
925 currentChannelNum
= newChan
;
926 channelDetected
= false;
930 * Unfortunately order of channel should be different in different conditions. Selects
931 * next channel based on heli or acro mode
933 void ConfigInputWidget::nextChannel()
936 switch (transmitterType
) {
938 order
= heliChannelOrder
;
941 order
= groundChannelOrder
;
944 order
= acroChannelOrder
;
948 if (currentChannelNum
== -1) {
949 setChannel(order
[0]);
952 for (int i
= 0; i
< order
.length() - 1; i
++) {
953 if (order
[i
] == currentChannelNum
) {
954 setChannel(order
[i
+ 1]);
958 currentChannelNum
= -1; // hit end of list
962 * Unfortunately order of channel should be different in different conditions. Selects
963 * previous channel based on heli or acro mode
965 void ConfigInputWidget::prevChannel()
968 switch (transmitterType
) {
970 order
= heliChannelOrder
;
973 order
= groundChannelOrder
;
976 order
= acroChannelOrder
;
980 // No previous from unset channel or next state
981 if (currentChannelNum
== -1) {
985 for (int i
= 1; i
< order
.length(); i
++) {
986 if (order
[i
] == currentChannelNum
) {
987 if (!usedChannels
.isEmpty() &&
988 usedChannels
.back().channelIndex
== order
[i
- 1]) {
989 usedChannels
.removeLast();
991 setChannel(order
[i
- 1]);
995 currentChannelNum
= -1; // hit end of list
998 void ConfigInputWidget::identifyControls()
1000 static const int DEBOUNCE_COUNT
= 4;
1001 static int debounce
= 0;
1003 receiverActivityData
= receiverActivityObj
->getData();
1005 if (receiverActivityData
.ActiveChannel
== 255) {
1009 if (channelDetected
) {
1010 registerControlActivity();
1014 receiverActivityData
= receiverActivityObj
->getData();
1015 currentChannel
.group
= receiverActivityData
.ActiveGroup
;
1016 currentChannel
.number
= receiverActivityData
.ActiveChannel
;
1018 if (debounce
== 0) {
1019 // Register a channel to be debounced.
1020 lastChannel
.group
= currentChannel
.group
;
1021 lastChannel
.number
= currentChannel
.number
;
1022 lastChannel
.channelIndex
= currentChannelNum
;
1027 if (currentChannel
!= lastChannel
) {
1028 // A new channel was seen. Only register it if we count down to 0.
1033 if (debounce
< DEBOUNCE_COUNT
) {
1034 // We still haven't seen enough enough activity on this channel yet.
1039 // Channel has been debounced and it's enough record it.
1041 if (usedChannels
.contains(lastChannel
)) {
1042 // Channel is already recorded.
1046 // Record the channel.
1048 channelDetected
= true;
1050 usedChannels
.append(lastChannel
);
1051 manualSettingsData
= manualSettingsObj
->getData();
1052 manualSettingsData
.ChannelGroups
[currentChannelNum
] = currentChannel
.group
;
1053 manualSettingsData
.ChannelNumber
[currentChannelNum
] = currentChannel
.number
;
1054 manualSettingsObj
->setData(manualSettingsData
);
1056 // m_config->wzText->clear();
1057 setTxMovement(nothing
);
1059 wzNextDelayedStart();
1062 void ConfigInputWidget::identifyLimits()
1064 manualCommandData
= manualCommandObj
->getData();
1065 for (uint i
= 0; i
< ManualControlSettings::CHANNELMAX_NUMELEM
; ++i
) {
1066 if (manualSettingsData
.ChannelMin
[i
] <= manualSettingsData
.ChannelMax
[i
]) {
1067 // Non inverted channel
1068 if (manualSettingsData
.ChannelMin
[i
] > manualCommandData
.Channel
[i
]) {
1069 manualSettingsData
.ChannelMin
[i
] = manualCommandData
.Channel
[i
];
1071 if (manualSettingsData
.ChannelMax
[i
] < manualCommandData
.Channel
[i
]) {
1072 manualSettingsData
.ChannelMax
[i
] = manualCommandData
.Channel
[i
];
1076 if (manualSettingsData
.ChannelMax
[i
] > manualCommandData
.Channel
[i
]) {
1077 manualSettingsData
.ChannelMax
[i
] = manualCommandData
.Channel
[i
];
1079 if (manualSettingsData
.ChannelMin
[i
] < manualCommandData
.Channel
[i
]) {
1080 manualSettingsData
.ChannelMin
[i
] = manualCommandData
.Channel
[i
];
1084 manualSettingsObj
->setData(manualSettingsData
);
1087 void ConfigInputWidget::setMoveFromCommand(int command
)
1089 // ManualControlSettings::ChannelNumberElem:
1090 // CHANNELNUMBER_ROLL=0,
1091 // CHANNELNUMBER_PITCH=1,
1092 // CHANNELNUMBER_YAW=2,
1093 // CHANNELNUMBER_THROTTLE=3,
1094 // CHANNELNUMBER_FLIGHTMODE=4,
1095 // CHANNELNUMBER_ACCESSORY0=5,
1096 // CHANNELNUMBER_ACCESSORY1=6,
1097 // CHANNELNUMBER_ACCESSORY2=7
1099 txMovements movement
= moveLeftVerticalStick
;
1102 case ManualControlSettings::CHANNELNUMBER_ROLL
:
1103 movement
= ((transmitterMode
== mode3
|| transmitterMode
== mode4
) ?
1104 moveLeftHorizontalStick
: moveRightHorizontalStick
);
1106 case ManualControlSettings::CHANNELNUMBER_PITCH
:
1107 movement
= (transmitterMode
== mode1
|| transmitterMode
== mode3
) ?
1108 moveLeftVerticalStick
: moveRightVerticalStick
;
1110 case ManualControlSettings::CHANNELNUMBER_YAW
:
1111 movement
= ((transmitterMode
== mode1
|| transmitterMode
== mode2
) ?
1112 moveLeftHorizontalStick
: moveRightHorizontalStick
);
1114 case ManualControlSettings::CHANNELNUMBER_THROTTLE
:
1115 movement
= (transmitterMode
== mode2
|| transmitterMode
== mode4
) ?
1116 moveLeftVerticalStick
: moveRightVerticalStick
;
1118 case ManualControlSettings::CHANNELNUMBER_COLLECTIVE
:
1119 movement
= (transmitterMode
== mode2
|| transmitterMode
== mode4
) ?
1120 moveLeftVerticalStick
: moveRightVerticalStick
;
1122 case ManualControlSettings::CHANNELNUMBER_FLIGHTMODE
:
1123 movement
= moveFlightMode
;
1125 case ManualControlSettings::CHANNELNUMBER_ACCESSORY0
:
1126 movement
= moveAccess0
;
1128 case ManualControlSettings::CHANNELNUMBER_ACCESSORY1
:
1129 movement
= moveAccess1
;
1131 case ManualControlSettings::CHANNELNUMBER_ACCESSORY2
:
1132 movement
= moveAccess2
;
1138 setTxMovement(movement
);
1141 void ConfigInputWidget::setTxMovement(txMovements movement
)
1145 case moveLeftVerticalStick
:
1148 currentMovement
= moveLeftVerticalStick
;
1149 animate
->start(100);
1151 case moveRightVerticalStick
:
1154 currentMovement
= moveRightVerticalStick
;
1155 animate
->start(100);
1157 case moveLeftHorizontalStick
:
1160 currentMovement
= moveLeftHorizontalStick
;
1161 animate
->start(100);
1163 case moveRightHorizontalStick
:
1166 currentMovement
= moveRightHorizontalStick
;
1167 animate
->start(100);
1172 currentMovement
= moveAccess0
;
1173 animate
->start(100);
1178 currentMovement
= moveAccess1
;
1179 animate
->start(100);
1184 currentMovement
= moveAccess2
;
1185 animate
->start(100);
1187 case moveFlightMode
:
1190 currentMovement
= moveFlightMode
;
1191 animate
->start(1000);
1195 currentMovement
= centerAll
;
1196 animate
->start(1000);
1201 currentMovement
= moveAll
;
1214 void ConfigInputWidget::moveTxControls()
1217 QGraphicsItem
*item
= NULL
;
1218 txMovementType move
= vertical
;
1221 static bool auxFlag
= false;
1223 switch (currentMovement
) {
1224 case moveLeftVerticalStick
:
1225 item
= m_txLeftStick
;
1226 trans
= m_txLeftStickOrig
;
1227 limitMax
= STICK_MAX_MOVE
;
1228 limitMin
= STICK_MIN_MOVE
;
1231 case moveRightVerticalStick
:
1232 item
= m_txRightStick
;
1233 trans
= m_txRightStickOrig
;
1234 limitMax
= STICK_MAX_MOVE
;
1235 limitMin
= STICK_MIN_MOVE
;
1238 case moveLeftHorizontalStick
:
1239 item
= m_txLeftStick
;
1240 trans
= m_txLeftStickOrig
;
1241 limitMax
= STICK_MAX_MOVE
;
1242 limitMin
= STICK_MIN_MOVE
;
1245 case moveRightHorizontalStick
:
1246 item
= m_txRightStick
;
1247 trans
= m_txRightStickOrig
;
1248 limitMax
= STICK_MAX_MOVE
;
1249 limitMin
= STICK_MIN_MOVE
;
1254 trans
= m_txAccess0Orig
;
1255 limitMax
= ACCESS_MAX_MOVE
;
1256 limitMin
= ACCESS_MIN_MOVE
;
1261 trans
= m_txAccess1Orig
;
1262 limitMax
= ACCESS_MAX_MOVE
;
1263 limitMin
= ACCESS_MIN_MOVE
;
1268 trans
= m_txAccess2Orig
;
1269 limitMax
= ACCESS_MAX_MOVE
;
1270 limitMin
= ACCESS_MIN_MOVE
;
1273 case moveFlightMode
:
1274 item
= m_txFlightMode
;
1282 limitMax
= STICK_MAX_MOVE
;
1283 limitMin
= STICK_MIN_MOVE
;
1289 if (move
== vertical
) {
1290 item
->setTransform(trans
.translate(0, movePos
* 10), false);
1291 } else if (move
== horizontal
) {
1292 item
->setTransform(trans
.translate(movePos
* 10, 0), false);
1293 } else if (move
== jump
) {
1294 if (item
== m_txArrows
) {
1295 m_txArrows
->setVisible(!m_txArrows
->isVisible());
1296 } else if (item
== m_txFlightMode
) {
1297 QGraphicsSvgItem
*svg
;
1298 svg
= (QGraphicsSvgItem
*)item
;
1300 if (svg
->elementId() == "flightModeCenter") {
1302 svg
->setElementId("flightModeRight");
1303 m_txFlightMode
->setTransform(m_txFlightModeROrig
, false);
1305 svg
->setElementId("flightModeLeft");
1306 m_txFlightMode
->setTransform(m_txFlightModeLOrig
, false);
1308 } else if (svg
->elementId() == "flightModeRight") {
1310 svg
->setElementId("flightModeCenter");
1311 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1312 } else if (svg
->elementId() == "flightModeLeft") {
1314 svg
->setElementId("flightModeCenter");
1315 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1319 } else if (move
== mix
) {
1320 trans
= m_txAccess0Orig
;
1321 m_txAccess0
->setTransform(trans
.translate(movePos
* 10 * ACCESS_MAX_MOVE
/ STICK_MAX_MOVE
, 0), false);
1322 trans
= m_txAccess1Orig
;
1323 m_txAccess1
->setTransform(trans
.translate(movePos
* 10 * ACCESS_MAX_MOVE
/ STICK_MAX_MOVE
, 0), false);
1324 trans
= m_txAccess2Orig
;
1325 m_txAccess2
->setTransform(trans
.translate(movePos
* 10 * ACCESS_MAX_MOVE
/ STICK_MAX_MOVE
, 0), false);
1328 trans
= m_txLeftStickOrig
;
1329 m_txLeftStick
->setTransform(trans
.translate(0, movePos
* 10), false);
1330 trans
= m_txRightStickOrig
;
1331 m_txRightStick
->setTransform(trans
.translate(0, movePos
* 10), false);
1333 trans
= m_txLeftStickOrig
;
1334 m_txLeftStick
->setTransform(trans
.translate(movePos
* 10, 0), false);
1335 trans
= m_txRightStickOrig
;
1336 m_txRightStick
->setTransform(trans
.translate(movePos
* 10, 0), false);
1340 m_txFlightMode
->setElementId("flightModeCenter");
1341 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1342 } else if (movePos
== ACCESS_MAX_MOVE
/ 2) {
1343 m_txFlightMode
->setElementId("flightModeRight");
1344 m_txFlightMode
->setTransform(m_txFlightModeROrig
, false);
1345 } else if (movePos
== ACCESS_MIN_MOVE
/ 2) {
1346 m_txFlightMode
->setElementId("flightModeLeft");
1347 m_txFlightMode
->setTransform(m_txFlightModeLOrig
, false);
1350 if (move
== horizontal
|| move
== vertical
|| move
== mix
) {
1351 if (movePos
== 0 && growing
) {
1359 if (movePos
> limitMax
) {
1360 movePos
= movePos
- 2;
1363 if (movePos
< limitMin
) {
1364 movePos
= movePos
+ 2;
1370 AccessoryDesired
*ConfigInputWidget::getAccessoryDesiredInstance(int instance
)
1374 if (accessoryDesiredObj0
== NULL
) {
1375 accessoryDesiredObj0
= AccessoryDesired::GetInstance(getObjectManager(), 0);
1377 return accessoryDesiredObj0
;
1380 if (accessoryDesiredObj1
== NULL
) {
1381 accessoryDesiredObj1
= AccessoryDesired::GetInstance(getObjectManager(), 1);
1383 return accessoryDesiredObj1
;
1386 if (accessoryDesiredObj2
== NULL
) {
1387 accessoryDesiredObj2
= AccessoryDesired::GetInstance(getObjectManager(), 2);
1389 return accessoryDesiredObj2
;
1398 float ConfigInputWidget::getAccessoryDesiredValue(int instance
)
1400 AccessoryDesired
*accessoryDesiredObj
= getAccessoryDesiredInstance(instance
);
1402 if (accessoryDesiredObj
== NULL
) {
1407 AccessoryDesired::DataFields data
= accessoryDesiredObj
->getData();
1409 return data
.AccessoryVal
;
1412 void ConfigInputWidget::moveSticks()
1416 manualCommandData
= manualCommandObj
->getData();
1417 flightStatusData
= flightStatusObj
->getData();
1419 switch (transmitterMode
) {
1421 trans
= m_txLeftStickOrig
;
1422 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1423 trans
= m_txRightStickOrig
;
1424 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1427 trans
= m_txLeftStickOrig
;
1428 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1429 trans
= m_txRightStickOrig
;
1430 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1433 trans
= m_txLeftStickOrig
;
1434 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1435 trans
= m_txRightStickOrig
;
1436 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1439 trans
= m_txLeftStickOrig
;
1440 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1441 trans
= m_txRightStickOrig
;
1442 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1448 if (flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[0]) {
1449 m_txFlightMode
->setElementId("flightModeLeft");
1450 m_txFlightMode
->setTransform(m_txFlightModeLOrig
, false);
1451 } else if (flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[1]) {
1452 m_txFlightMode
->setElementId("flightModeCenter");
1453 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1454 } else if (flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[2]) {
1455 m_txFlightMode
->setElementId("flightModeRight");
1456 m_txFlightMode
->setTransform(m_txFlightModeROrig
, false);
1459 m_txAccess0
->setTransform(QTransform(m_txAccess0Orig
).translate(getAccessoryDesiredValue(0) * ACCESS_MAX_MOVE
* 10, 0), false);
1460 m_txAccess1
->setTransform(QTransform(m_txAccess1Orig
).translate(getAccessoryDesiredValue(1) * ACCESS_MAX_MOVE
* 10, 0), false);
1461 m_txAccess2
->setTransform(QTransform(m_txAccess2Orig
).translate(getAccessoryDesiredValue(2) * ACCESS_MAX_MOVE
* 10, 0), false);
1464 void ConfigInputWidget::dimOtherControls(bool value
)
1473 m_txAccess0
->setOpacity(opac
);
1474 m_txAccess1
->setOpacity(opac
);
1475 m_txAccess2
->setOpacity(opac
);
1476 m_txFlightMode
->setOpacity(opac
);
1479 void ConfigInputWidget::invertControls()
1481 manualSettingsData
= manualSettingsObj
->getData();
1482 foreach(QWidget
* wd
, extraWidgets
) {
1483 QCheckBox
*cb
= qobject_cast
<QCheckBox
*>(wd
);
1486 int index
= manualSettingsObj
->getField("ChannelNumber")->getElementNames().indexOf(cb
->text());
1487 if ((cb
->isChecked() && (manualSettingsData
.ChannelMax
[index
] > manualSettingsData
.ChannelMin
[index
])) ||
1488 (!cb
->isChecked() && (manualSettingsData
.ChannelMax
[index
] < manualSettingsData
.ChannelMin
[index
]))) {
1490 aux
= manualSettingsData
.ChannelMax
[index
];
1491 manualSettingsData
.ChannelMax
[index
] = manualSettingsData
.ChannelMin
[index
];
1492 manualSettingsData
.ChannelMin
[index
] = aux
;
1496 manualSettingsObj
->setData(manualSettingsData
);
1499 void ConfigInputWidget::moveFMSlider()
1501 ManualControlSettings::DataFields manualSettingsDataPriv
= manualSettingsObj
->getData();
1502 ManualControlCommand::DataFields manualCommandDataPriv
= manualCommandObj
->getData();
1505 int chMin
= manualSettingsDataPriv
.ChannelMin
[ManualControlSettings::CHANNELMIN_FLIGHTMODE
];
1506 int chMax
= manualSettingsDataPriv
.ChannelMax
[ManualControlSettings::CHANNELMAX_FLIGHTMODE
];
1507 int chNeutral
= manualSettingsDataPriv
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE
];
1509 int value
= manualCommandDataPriv
.Channel
[ManualControlSettings::CHANNELMIN_FLIGHTMODE
];
1511 if ((chMax
> chMin
&& value
>= chNeutral
) || (chMin
> chMax
&& value
<= chNeutral
)) {
1512 if (chMax
!= chNeutral
) {
1513 valueScaled
= (float)(value
- chNeutral
) / (float)(chMax
- chNeutral
);
1518 if (chMin
!= chNeutral
) {
1519 valueScaled
= (float)(value
- chNeutral
) / (float)(chNeutral
- chMin
);
1525 // Bound and scale FlightMode from [-1..+1] to [0..1] range
1526 if (valueScaled
< -1.0) {
1528 } else if (valueScaled
> 1.0) {
1532 // Convert flightMode value into the switch position in the range [0..N-1]
1533 // This uses the same optimized computation as flight code to be consistent
1534 uint8_t pos
= ((int16_t)(valueScaled
* 256) + 256) * manualSettingsDataPriv
.FlightModeNumber
>> 9;
1535 if (pos
>= manualSettingsDataPriv
.FlightModeNumber
) {
1536 pos
= manualSettingsDataPriv
.FlightModeNumber
- 1;
1538 ui
->fmsSlider
->setValue(pos
);
1541 void ConfigInputWidget::updatePositionSlider()
1543 ManualControlSettings::DataFields manualSettingsDataPriv
= manualSettingsObj
->getData();
1545 switch (manualSettingsDataPriv
.FlightModeNumber
) {
1548 ui
->fmsModePos6
->setEnabled(true);
1549 ui
->pidBankSs1_5
->setEnabled(true);
1550 ui
->assistControlPos6
->setEnabled(true);
1553 ui
->fmsModePos5
->setEnabled(true);
1554 ui
->pidBankSs1_4
->setEnabled(true);
1555 ui
->assistControlPos5
->setEnabled(true);
1558 ui
->fmsModePos4
->setEnabled(true);
1559 ui
->pidBankSs1_3
->setEnabled(true);
1560 ui
->assistControlPos4
->setEnabled(true);
1563 ui
->fmsModePos3
->setEnabled(true);
1564 ui
->pidBankSs1_2
->setEnabled(true);
1565 ui
->assistControlPos3
->setEnabled(true);
1568 ui
->fmsModePos2
->setEnabled(true);
1569 ui
->pidBankSs1_1
->setEnabled(true);
1570 ui
->assistControlPos2
->setEnabled(true);
1573 ui
->fmsModePos1
->setEnabled(true);
1574 ui
->pidBankSs1_0
->setEnabled(true);
1575 ui
->assistControlPos1
->setEnabled(true);
1581 switch (manualSettingsDataPriv
.FlightModeNumber
) {
1583 ui
->fmsModePos1
->setEnabled(false);
1584 ui
->pidBankSs1_0
->setEnabled(false);
1585 ui
->assistControlPos1
->setEnabled(false);
1588 ui
->fmsModePos2
->setEnabled(false);
1589 ui
->pidBankSs1_1
->setEnabled(false);
1590 ui
->assistControlPos2
->setEnabled(false);
1593 ui
->fmsModePos3
->setEnabled(false);
1594 ui
->pidBankSs1_2
->setEnabled(false);
1595 ui
->assistControlPos3
->setEnabled(false);
1598 ui
->fmsModePos4
->setEnabled(false);
1599 ui
->pidBankSs1_3
->setEnabled(false);
1600 ui
->assistControlPos4
->setEnabled(false);
1603 ui
->fmsModePos5
->setEnabled(false);
1604 ui
->pidBankSs1_4
->setEnabled(false);
1605 ui
->assistControlPos5
->setEnabled(false);
1608 ui
->fmsModePos6
->setEnabled(false);
1609 ui
->pidBankSs1_5
->setEnabled(false);
1610 ui
->assistControlPos6
->setEnabled(false);
1617 QString fmNumber
= QString().setNum(manualSettingsDataPriv
.FlightModeNumber
);
1619 foreach(QSlider
* sp
, findChildren
<QSlider
*>()) {
1620 // Find FlightMode slider and apply stylesheet
1621 if (sp
->objectName() == "channelNeutral") {
1624 "QSlider::groove:horizontal {border: 2px solid rgb(196, 196, 196); height: 12px; border-radius: 4px; "
1625 "border-image:url(:/configgadget/images/flightmode_bg" + fmNumber
+ ".png); }"
1626 "QSlider::add-page:horizontal { background: none; border: none; }"
1627 "QSlider::sub-page:horizontal { background: none; border: none; }"
1628 "QSlider::handle:horizontal { background: rgba(196, 196, 196, 255); width: 10px; height: 28px; "
1629 "margin: -3px -2px; border-radius: 3px; border: 1px solid #777; }");
1638 void ConfigInputWidget::updateCalibration()
1640 manualCommandData
= manualCommandObj
->getData();
1641 for (uint i
= 0; i
< ManualControlSettings::CHANNELMAX_NUMELEM
; ++i
) {
1642 if ((!reverse
[i
] && manualSettingsData
.ChannelMin
[i
] > manualCommandData
.Channel
[i
]) ||
1643 (reverse
[i
] && manualSettingsData
.ChannelMin
[i
] < manualCommandData
.Channel
[i
])) {
1644 manualSettingsData
.ChannelMin
[i
] = manualCommandData
.Channel
[i
];
1646 if ((!reverse
[i
] && manualSettingsData
.ChannelMax
[i
] < manualCommandData
.Channel
[i
]) ||
1647 (reverse
[i
] && manualSettingsData
.ChannelMax
[i
] > manualCommandData
.Channel
[i
])) {
1648 manualSettingsData
.ChannelMax
[i
] = manualCommandData
.Channel
[i
];
1650 if ((i
== ManualControlSettings::CHANNELNUMBER_FLIGHTMODE
) || (i
== ManualControlSettings::CHANNELNUMBER_THROTTLE
)) {
1651 adjustSpecialNeutrals();
1653 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
1657 manualSettingsObj
->setData(manualSettingsData
);
1658 manualSettingsObj
->updated();
1661 void ConfigInputWidget::simpleCalibration(bool enable
)
1664 ui
->configurationWizard
->setEnabled(false);
1665 ui
->saveRCInputToRAM
->setEnabled(false);
1666 ui
->saveRCInputToSD
->setEnabled(false);
1667 ui
->runCalibration
->setText(tr("Stop Manual Calibration"));
1668 throttleError
= false;
1671 msgBox
.setText(tr("<p>Arming Settings are now set to 'Always Disarmed' for your safety.</p>"
1672 "<p>Be sure your receiver is powered with an external source and Transmitter is on.</p>"
1673 "<p align='center'><b>Stop Manual Calibration</b> when done</p>"));
1674 msgBox
.setDetailedText(tr("You will have to reconfigure the arming settings manually when the manual calibration is finished."));
1675 msgBox
.setStandardButtons(QMessageBox::Ok
);
1676 msgBox
.setDefaultButton(QMessageBox::Ok
);
1679 manualCommandData
= manualCommandObj
->getData();
1681 manualSettingsData
= manualSettingsObj
->getData();
1682 flightModeSettingsData
= flightModeSettingsObj
->getData();
1683 flightModeSettingsData
.Arming
= FlightModeSettings::ARMING_ALWAYSDISARMED
;
1684 flightModeSettingsObj
->setData(flightModeSettingsData
);
1686 for (unsigned int i
= 0; i
< ManualControlCommand::CHANNEL_NUMELEM
; i
++) {
1687 reverse
[i
] = manualSettingsData
.ChannelMax
[i
] < manualSettingsData
.ChannelMin
[i
];
1688 manualSettingsData
.ChannelMin
[i
] = manualCommandData
.Channel
[i
];
1689 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
1690 manualSettingsData
.ChannelMax
[i
] = manualCommandData
.Channel
[i
];
1693 fastMdataSingle(manualCommandObj
, &manualControlMdata
);
1695 // Stash actuatorSettings
1696 actuatorSettingsData
= actuatorSettingsObj
->getData();
1697 memento
.actuatorSettingsData
= actuatorSettingsData
;
1699 // Disable all actuators
1700 resetActuatorSettings();
1702 connect(manualCommandObj
, SIGNAL(objectUnpacked(UAVObject
*)), this, SLOT(updateCalibration()));
1704 manualCommandData
= manualCommandObj
->getData();
1705 manualSettingsData
= manualSettingsObj
->getData();
1706 systemSettingsData
= systemSettingsObj
->getData();
1708 if (systemSettingsData
.AirframeType
== SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR
) {
1709 QMessageBox::warning(this, tr("Ground Vehicle"),
1710 tr("<p>Please <b>center</b> throttle control and press OK when ready.</p>"));
1712 transmitterType
= ground
;
1713 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_THROTTLE
] =
1714 manualCommandData
.Channel
[ManualControlSettings::CHANNELNUMBER_THROTTLE
];
1717 restoreMdataSingle(manualCommandObj
, &manualControlMdata
);
1719 // Force flight mode number to be 1 if 2 channel ground vehicle was confirmed
1720 if (transmitterType
== ground
) {
1721 forceOneFlightMode();
1724 for (unsigned int i
= 0; i
< ManualControlCommand::CHANNEL_NUMELEM
; i
++) {
1725 if ((i
== ManualControlSettings::CHANNELNUMBER_FLIGHTMODE
) || (i
== ManualControlSettings::CHANNELNUMBER_THROTTLE
)) {
1726 adjustSpecialNeutrals();
1727 checkThrottleRange();
1729 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
1732 manualSettingsObj
->setData(manualSettingsData
);
1734 // Load actuator settings back from beginning of manual calibration
1735 actuatorSettingsObj
->setData(memento
.actuatorSettingsData
);
1737 ui
->configurationWizard
->setEnabled(true);
1738 ui
->saveRCInputToRAM
->setEnabled(true);
1739 ui
->saveRCInputToSD
->setEnabled(true);
1740 ui
->runCalibration
->setText(tr("Start Manual Calibration"));
1742 disconnect(manualCommandObj
, SIGNAL(objectUnpacked(UAVObject
*)), this, SLOT(updateCalibration()));
1746 void ConfigInputWidget::adjustSpecialNeutrals()
1748 // FlightMode and Throttle need special neutral settings
1750 // Force flight mode neutral to middle
1751 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE
] =
1752 (manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_FLIGHTMODE
] +
1753 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_FLIGHTMODE
]) / 2;
1755 // A ground vehicle has a reversible motor, the center position of throttle is the neutral setting.
1756 // So do not have to set a special neutral value for it.
1757 if (transmitterType
== ground
) {
1761 // Force throttle to be near min, add 4% from total range to avoid arming issues
1762 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_THROTTLE
] =
1763 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_THROTTLE
] +
1764 ((manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_THROTTLE
] -
1765 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_THROTTLE
]) * 0.04);
1768 void ConfigInputWidget::checkThrottleRange()
1770 int throttleRange
= abs(manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_THROTTLE
] -
1771 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_THROTTLE
]);
1773 if (!throttleError
&& (throttleRange
< 300)) {
1774 throttleError
= true;
1775 QMessageBox::warning(this, tr("Warning"), tr("<p>There is something wrong with Throttle range. Please redo calibration and move <b>ALL sticks</b>, Throttle stick included.</p>"), QMessageBox::Ok
);
1777 // Set Throttle neutral to max value so Throttle can't be positive
1778 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_THROTTLE
] =
1779 manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_THROTTLE
];
1783 bool ConfigInputWidget::shouldObjectBeSaved(UAVObject
*object
)
1785 // ManualControlCommand no need to be saved
1786 return dynamic_cast<ManualControlCommand
*>(object
) == NULL
;
1789 void ConfigInputWidget::resetChannelSettings()
1791 manualSettingsData
= manualSettingsObj
->getData();
1792 // Clear all channel data : Channel Type (PPM,PWM..) and Number
1793 for (unsigned int channel
= 0; channel
< ManualControlSettings::CHANNELNUMBER_NUMELEM
; channel
++) {
1794 manualSettingsData
.ChannelGroups
[channel
] = ManualControlSettings::CHANNELGROUPS_NONE
;
1795 manualSettingsData
.ChannelNumber
[channel
] = CHANNEL_NUMBER_NONE
;
1796 manualSettingsData
.FlightModeNumber
= DEFAULT_FLIGHT_MODE_NUMBER
;
1797 manualSettingsObj
->setData(manualSettingsData
);
1801 void ConfigInputWidget::resetActuatorSettings()
1803 actuatorSettingsData
= actuatorSettingsObj
->getData();
1805 UAVDataObject
*mixer
= dynamic_cast<UAVDataObject
*>(getObjectManager()->getObject(QString("MixerSettings")));
1810 // Clear all output data : Min, max, neutral at same value
1811 // 1000 for motors and 1500 for all others (Reversable motor included)
1812 for (unsigned int output
= 0; output
< 12; output
++) {
1813 QString mixerNumType
= QString("Mixer%1Type").arg(output
+ 1);
1814 UAVObjectField
*field
= mixer
->getField(mixerNumType
);
1818 mixerType
= field
->getValue().toString();
1820 if ((mixerType
== "Motor") || (mixerType
== "Disabled")) {
1821 actuatorSettingsData
.ChannelMax
[output
] = 1000;
1822 actuatorSettingsData
.ChannelMin
[output
] = 1000;
1823 actuatorSettingsData
.ChannelNeutral
[output
] = 1000;
1825 actuatorSettingsData
.ChannelMax
[output
] = 1500;
1826 actuatorSettingsData
.ChannelMin
[output
] = 1500;
1827 actuatorSettingsData
.ChannelNeutral
[output
] = 1500;
1829 actuatorSettingsObj
->setData(actuatorSettingsData
);
1833 void ConfigInputWidget::forceOneFlightMode()
1835 manualSettingsData
= manualSettingsObj
->getData();
1836 manualSettingsData
.FlightModeNumber
= 1;
1837 manualSettingsObj
->setData(manualSettingsData
);