2 ******************************************************************************
4 * @file configinputwidget.cpp
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015-2016.
6 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
7 * @addtogroup GCSPlugins GCS Plugins
9 * @addtogroup ConfigPlugin Config Plugin
11 * @brief Servo input configuration panel for the config gadget
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "configinputwidget.h"
32 #include "ui_input_wizard.h"
34 #include "inputchannelform.h"
35 #include "ui_inputchannelform.h"
37 #include "failsafechannelform.h"
38 #include "ui_failsafechannelform.h"
40 #include <uavobjectmanager.h>
41 #include <uavobjecthelper.h>
42 #include <utils/stylehelper.h>
44 #include <systemalarms.h>
48 #include <QMessageBox>
49 #include <QGraphicsSvgItem>
50 #include <QSvgRenderer>
52 #define ACCESS_MIN_MOVE -3
53 #define ACCESS_MAX_MOVE 3
54 #define STICK_MIN_MOVE -8
55 #define STICK_MAX_MOVE 8
57 #define MIN_INPUT_US 100
58 #define MAX_INPUT_US 2500
60 #define CHANNEL_NUMBER_NONE 0
61 #define DEFAULT_FLIGHT_MODE_NUMBER 1
63 ConfigInputWidget::ConfigInputWidget(QWidget
*parent
) :
64 ConfigTaskWidget(parent
),
65 wizardStep(wizardNone
),
66 // not currently stored in the settings UAVO
67 transmitterMode(mode2
),
68 transmitterType(acro
),
74 nextDelayedLatestActivityTick(0),
75 accessoryDesiredObj0(NULL
),
76 accessoryDesiredObj1(NULL
),
77 accessoryDesiredObj2(NULL
),
78 accessoryDesiredObj3(NULL
),
81 ui
= new Ui_InputWidget();
84 // must be done before auto binding !
85 setWikiURL("Input+Configuration");
89 connect(this, SIGNAL(enableControlsChanged(bool)), this, SLOT(enableControlsChanged(bool)));
91 manualCommandObj
= ManualControlCommand::GetInstance(getObjectManager());
92 manualSettingsObj
= ManualControlSettings::GetInstance(getObjectManager());
93 flightModeSettingsObj
= FlightModeSettings::GetInstance(getObjectManager());
94 flightStatusObj
= FlightStatus::GetInstance(getObjectManager());
95 receiverActivityObj
= ReceiverActivity::GetInstance(getObjectManager());
96 accessoryDesiredObj0
= AccessoryDesired::GetInstance(getObjectManager(), 0);
97 accessoryDesiredObj1
= AccessoryDesired::GetInstance(getObjectManager(), 1);
98 accessoryDesiredObj2
= AccessoryDesired::GetInstance(getObjectManager(), 2);
99 accessoryDesiredObj3
= AccessoryDesired::GetInstance(getObjectManager(), 3);
100 rssiDesiredObj4
= AccessoryDesired::GetInstance(getObjectManager(), 4);
101 actuatorSettingsObj
= ActuatorSettings::GetInstance(getObjectManager());
102 systemSettingsObj
= SystemSettings::GetInstance(getObjectManager());
103 hwSettingsObj
= HwSettings::GetInstance(getObjectManager());
104 // Only instance 0 is present if the board is not connected.
105 // The other instances are populated lazily.
106 Q_ASSERT(accessoryDesiredObj0
);
108 // Generate the rows of buttons in the input channel form GUI
111 foreach(QString name
, manualSettingsObj
->getField("ChannelNumber")->getElementNames()) {
112 Q_ASSERT(index
< ManualControlSettings::CHANNELGROUPS_NUMELEM
);
114 // Input channel setup
115 InputChannelForm
*inputChannelForm
= new InputChannelForm(index
, this);
116 inputChannelForm
->setName(name
);
118 inputChannelForm
->moveTo(*(ui
->channelLayout
));
120 // The order of the following binding calls is important. Since the values will be populated
121 // in reverse order of the binding order otherwise the 'Reversed' logic will floor the neutral value
122 // to the max value ( which is smaller than the neutral value when reversed ) and the channel number
123 // will not be set correctly.
124 addWidgetBinding("ManualControlSettings", "ChannelNumber", inputChannelForm
->ui
->channelNumber
, index
);
125 addWidgetBinding("ManualControlSettings", "ChannelGroups", inputChannelForm
->ui
->channelGroup
, index
);
126 // Slider position based on real time Rcinput (allow monitoring)
127 addWidgetBinding("ManualControlCommand", "Channel", inputChannelForm
->ui
->channelNeutral
, index
);
128 // Neutral value stored on board (SpinBox)
129 // Rssi neutral is always set to min
130 if (index
== ManualControlSettings::CHANNELGROUPS_RSSI
) {
131 addWidgetBinding("ManualControlSettings", "ChannelMin", inputChannelForm
->ui
->neutralValue
, index
);
133 addWidgetBinding("ManualControlSettings", "ChannelNeutral", inputChannelForm
->ui
->neutralValue
, index
);
135 addWidgetBinding("ManualControlSettings", "ChannelMax", inputChannelForm
->ui
->channelMax
, index
);
136 addWidgetBinding("ManualControlSettings", "ChannelMin", inputChannelForm
->ui
->channelMin
, index
);
137 addWidgetBinding("ManualControlSettings", "ChannelMax", inputChannelForm
->ui
->channelMax
, index
);
139 addWidget(inputChannelForm
->ui
->channelRev
);
141 // Reversing supported for some channels only
142 bool reversable
= ((index
== ManualControlSettings::CHANNELGROUPS_THROTTLE
) ||
143 (index
== ManualControlSettings::CHANNELGROUPS_ROLL
) ||
144 (index
== ManualControlSettings::CHANNELGROUPS_PITCH
) ||
145 (index
== ManualControlSettings::CHANNELGROUPS_YAW
));
146 inputChannelForm
->ui
->channelRev
->setVisible(reversable
);
148 // Input filter response time fields supported for some channels only
149 // Set Neutral field to readonly for Rssi
151 case ManualControlSettings::CHANNELGROUPS_RSSI
:
152 inputChannelForm
->ui
->neutralValue
->setReadOnly(true);
153 case ManualControlSettings::CHANNELGROUPS_ROLL
:
154 case ManualControlSettings::CHANNELGROUPS_PITCH
:
155 case ManualControlSettings::CHANNELGROUPS_YAW
:
156 case ManualControlSettings::CHANNELGROUPS_COLLECTIVE
:
157 case ManualControlSettings::CHANNELGROUPS_ACCESSORY0
:
158 case ManualControlSettings::CHANNELGROUPS_ACCESSORY1
:
159 case ManualControlSettings::CHANNELGROUPS_ACCESSORY2
:
160 case ManualControlSettings::CHANNELGROUPS_ACCESSORY3
:
161 addWidgetBinding("ManualControlSettings", "ResponseTime", inputChannelForm
->ui
->channelResponseTime
, indexRT
);
164 case ManualControlSettings::CHANNELGROUPS_THROTTLE
:
165 case ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
:
166 inputChannelForm
->ui
->channelResponseTime
->setVisible(false);
175 QList
<int> failsafeReloadGroup
;
176 failsafeReloadGroup
.append(555);
178 addWidgetBinding("ManualControlSettings", "FailsafeFlightModeSwitchPosition", ui
->failsafeFlightMode
, 0, 1, true, new QList
<int>(failsafeReloadGroup
));
180 addWidgetBinding("FlightModeSettings", "BatteryFailsafeSwitchPositions", ui
->failsafeBatteryWarningFlightMode
, 0, 1, true, new QList
<int>(failsafeReloadGroup
));
181 addWidgetBinding("FlightModeSettings", "BatteryFailsafeSwitchPositions", ui
->failsafeBatteryCriticalFlightMode
, 1, 1, true, new QList
<int>(failsafeReloadGroup
));
183 // Generate the rows for the failsafe channel form GUI
185 foreach(QString name
, manualSettingsObj
->getField("FailsafeChannel")->getElementNames()) {
186 Q_ASSERT(index
< ManualControlSettings::FAILSAFECHANNEL_NUMELEM
);
188 // Failsafe channels setup
189 FailsafeChannelForm
*failsafeChannelForm
= new FailsafeChannelForm(index
, this);
190 addWidget(failsafeChannelForm
->ui
->channelValueSpinner
);
191 failsafeChannelForm
->setName(name
);
192 failsafeChannelForm
->moveTo(*(ui
->failsafeChannelsLayout
));
193 addWidgetBinding("ManualControlSettings", "FailsafeChannel", failsafeChannelForm
->ui
->channelValue
, index
, 0.01, true, new QList
<int>(failsafeReloadGroup
));
196 addWidget(ui
->failsafeDefault
);
198 addWidgetBinding("ManualControlSettings", "Deadband", ui
->deadband
, 0, 1);
199 addWidgetBinding("ManualControlSettings", "DeadbandAssistedControl", ui
->assistedControlDeadband
, 0, 1);
201 connect(ui
->configurationWizard
, SIGNAL(clicked()), this, SLOT(goToWizard()));
202 connect(ui
->stackedWidget
, SIGNAL(currentChanged(int)), this, SLOT(disableWizardButton(int)));
203 connect(ui
->runCalibration
, SIGNAL(toggled(bool)), this, SLOT(simpleCalibration(bool)));
205 connect(ReceiverActivity::GetInstance(getObjectManager()), SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(updateReceiverActivityStatus()));
206 connect(FlightStatus::GetInstance(getObjectManager()), SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(updateReceiverActivityStatus()));
208 ui
->receiverActivityStatus
->setStyleSheet("QLabel { background-color: darkGreen; color: rgb(255, 255, 255); \
209 border: 1px solid grey; border-radius: 5; margin:1px; font:bold;}");
211 ui
->stackedWidget
->setCurrentIndex(0);
212 QList
<QWidget
*> widgets
= QList
<QWidget
*>() << ui
->fmsModePos1
<< ui
->fmsModePos2
<< ui
->fmsModePos3
<<
213 ui
->fmsModePos4
<< ui
->fmsModePos5
<< ui
->fmsModePos6
;
215 foreach(QWidget
* widget
, widgets
) {
216 addWidgetBinding("FlightModeSettings", "FlightModePosition", widget
, index
++, 1, true);
219 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Roll
, "Roll", 1, true);
220 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Roll
, "Roll", 1, true);
221 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Roll
, "Roll", 1, true);
222 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Roll
, "Roll", 1, true);
223 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Roll
, "Roll", 1, true);
224 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Roll
, "Roll", 1, true);
226 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Pitch
, "Pitch", 1, true);
227 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Pitch
, "Pitch", 1, true);
228 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Pitch
, "Pitch", 1, true);
229 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Pitch
, "Pitch", 1, true);
230 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Pitch
, "Pitch", 1, true);
231 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Pitch
, "Pitch", 1, true);
233 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Yaw
, "Yaw", 1, true);
234 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Yaw
, "Yaw", 1, true);
235 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Yaw
, "Yaw", 1, true);
236 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Yaw
, "Yaw", 1, true);
237 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Yaw
, "Yaw", 1, true);
238 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Yaw
, "Yaw", 1, true);
240 addWidgetBinding("FlightModeSettings", "Stabilization1Settings", ui
->fmsSsPos1Thrust
, "Thrust", 1, true);
241 addWidgetBinding("FlightModeSettings", "Stabilization2Settings", ui
->fmsSsPos2Thrust
, "Thrust", 1, true);
242 addWidgetBinding("FlightModeSettings", "Stabilization3Settings", ui
->fmsSsPos3Thrust
, "Thrust", 1, true);
243 addWidgetBinding("FlightModeSettings", "Stabilization4Settings", ui
->fmsSsPos4Thrust
, "Thrust", 1, true);
244 addWidgetBinding("FlightModeSettings", "Stabilization5Settings", ui
->fmsSsPos5Thrust
, "Thrust", 1, true);
245 addWidgetBinding("FlightModeSettings", "Stabilization6Settings", ui
->fmsSsPos6Thrust
, "Thrust", 1, true);
247 addWidgetBinding("ManualControlSettings", "FlightModeNumber", ui
->fmsPosNum
);
249 addWidgetBinding("FlightModeSettings", "Arming", ui
->armControl
);
250 addWidgetBinding("FlightModeSettings", "ArmedTimeout", ui
->armTimeout
, 0, 1000);
251 connect(ManualControlCommand::GetInstance(getObjectManager()), SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveFMSlider()));
252 connect(ManualControlSettings::GetInstance(getObjectManager()), SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(updatePositionSlider()));
253 connect(SystemAlarms::GetInstance(getObjectManager()), SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(updateConfigAlarmStatus()));
255 connect(ui
->failsafeFlightMode
, SIGNAL(currentIndexChanged(int)), this, SLOT(failsafeFlightModeChanged(int)));
256 connect(ui
->failsafeFlightModeCb
, SIGNAL(toggled(bool)), this, SLOT(failsafeFlightModeCbToggled(bool)));
258 connect(ui
->failsafeBatteryWarningFlightMode
, SIGNAL(currentIndexChanged(int)), this, SLOT(failsafeBatteryWarningFlightModeChanged(int)));
259 connect(ui
->failsafeBatteryWarningFlightModeCb
, SIGNAL(toggled(bool)), this, SLOT(failsafeBatteryWarningFlightModeCbToggled(bool)));
261 connect(ui
->failsafeBatteryCriticalFlightMode
, SIGNAL(currentIndexChanged(int)), this, SLOT(failsafeBatteryCriticalFlightModeChanged(int)));
262 connect(ui
->failsafeBatteryCriticalFlightModeCb
, SIGNAL(toggled(bool)), this, SLOT(failsafeBatteryCriticalFlightModeCbToggled(bool)));
265 addWidget(ui
->configurationWizard
);
266 addWidget(ui
->runCalibration
);
267 addWidget(ui
->failsafeFlightModeCb
);
268 addWidget(ui
->failsafeBatteryWarningFlightModeCb
);
269 addWidget(ui
->failsafeBatteryCriticalFlightModeCb
);
272 wizardUi
= new Ui_InputWizardWidget();
273 wizardUi
->setupUi(ui
->wizard
);
275 connect(wizardUi
->wzNext
, SIGNAL(clicked()), this, SLOT(wzNext()));
276 connect(wizardUi
->wzCancel
, SIGNAL(clicked()), this, SLOT(wzCancel()));
277 connect(wizardUi
->wzBack
, SIGNAL(clicked()), this, SLOT(wzBack()));
279 wizardUi
->graphicsView
->setScene(new QGraphicsScene(this));
280 wizardUi
->graphicsView
->setViewportUpdateMode(QGraphicsView::FullViewportUpdate
);
281 m_renderer
= new QSvgRenderer();
282 QGraphicsScene
*l_scene
= wizardUi
->graphicsView
->scene();
283 wizardUi
->graphicsView
->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor()));
284 if (QFile::exists(":/configgadget/images/TX2.svg") && m_renderer
->load(QString(":/configgadget/images/TX2.svg")) && m_renderer
->isValid()) {
285 l_scene
->clear(); // Deletes all items contained in the scene as well.
287 m_txBackground
= new QGraphicsSvgItem();
288 // All other items will be clipped to the shape of the background
289 m_txBackground
->setFlags(QGraphicsItem::ItemClipsChildrenToShape
|
290 QGraphicsItem::ItemClipsToShape
);
291 m_txBackground
->setSharedRenderer(m_renderer
);
292 m_txBackground
->setElementId("background");
293 l_scene
->addItem(m_txBackground
);
295 m_txMainBody
= new QGraphicsSvgItem();
296 m_txMainBody
->setParentItem(m_txBackground
);
297 m_txMainBody
->setSharedRenderer(m_renderer
);
298 m_txMainBody
->setElementId("body");
299 l_scene
->addItem(m_txMainBody
);
301 m_txLeftStick
= new QGraphicsSvgItem();
302 m_txLeftStick
->setParentItem(m_txBackground
);
303 m_txLeftStick
->setSharedRenderer(m_renderer
);
304 m_txLeftStick
->setElementId("ljoy");
306 m_txRightStick
= new QGraphicsSvgItem();
307 m_txRightStick
->setParentItem(m_txBackground
);
308 m_txRightStick
->setSharedRenderer(m_renderer
);
309 m_txRightStick
->setElementId("rjoy");
311 m_txAccess0
= new QGraphicsSvgItem();
312 m_txAccess0
->setParentItem(m_txBackground
);
313 m_txAccess0
->setSharedRenderer(m_renderer
);
314 m_txAccess0
->setElementId("access0");
316 m_txAccess1
= new QGraphicsSvgItem();
317 m_txAccess1
->setParentItem(m_txBackground
);
318 m_txAccess1
->setSharedRenderer(m_renderer
);
319 m_txAccess1
->setElementId("access1");
321 m_txAccess2
= new QGraphicsSvgItem();
322 m_txAccess2
->setParentItem(m_txBackground
);
323 m_txAccess2
->setSharedRenderer(m_renderer
);
324 m_txAccess2
->setElementId("access2");
326 m_txAccess3
= new QGraphicsSvgItem();
327 m_txAccess3
->setParentItem(m_txBackground
);
328 m_txAccess3
->setSharedRenderer(m_renderer
);
329 m_txAccess3
->setElementId("access3");
331 m_txFlightMode
= new QGraphicsSvgItem();
332 m_txFlightMode
->setParentItem(m_txBackground
);
333 m_txFlightMode
->setSharedRenderer(m_renderer
);
334 m_txFlightMode
->setElementId("flightModeCenter");
335 m_txFlightMode
->setZValue(-10);
337 m_txFlightModeCountBG
= new QGraphicsSvgItem();
338 m_txFlightModeCountBG
->setParentItem(m_txBackground
);
339 m_txFlightModeCountBG
->setSharedRenderer(m_renderer
);
340 m_txFlightModeCountBG
->setElementId("fm_count_bg");
341 l_scene
->addItem(m_txFlightModeCountBG
);
343 m_txFlightModeCountText
= new QGraphicsSimpleTextItem("?", m_txFlightModeCountBG
);
344 m_txFlightModeCountText
->setBrush(QColor(40, 40, 40));
345 m_txFlightModeCountText
->setFont(QFont("Arial Bold"));
347 m_txArrows
= new QGraphicsSvgItem();
348 m_txArrows
->setParentItem(m_txBackground
);
349 m_txArrows
->setSharedRenderer(m_renderer
);
350 m_txArrows
->setElementId("arrows");
351 m_txArrows
->setVisible(false);
353 QRectF orig
= m_renderer
->boundsOnElement("ljoy");
354 QMatrix Matrix
= m_renderer
->matrixForElement("ljoy");
355 orig
= Matrix
.mapRect(orig
);
356 m_txLeftStickOrig
.translate(orig
.x(), orig
.y());
357 m_txLeftStick
->setTransform(m_txLeftStickOrig
, false);
359 orig
= m_renderer
->boundsOnElement("arrows");
360 Matrix
= m_renderer
->matrixForElement("arrows");
361 orig
= Matrix
.mapRect(orig
);
362 m_txArrowsOrig
.translate(orig
.x(), orig
.y());
363 m_txArrows
->setTransform(m_txArrowsOrig
, false);
365 orig
= m_renderer
->boundsOnElement("body");
366 Matrix
= m_renderer
->matrixForElement("body");
367 orig
= Matrix
.mapRect(orig
);
368 m_txMainBodyOrig
.translate(orig
.x(), orig
.y());
369 m_txMainBody
->setTransform(m_txMainBodyOrig
, false);
371 orig
= m_renderer
->boundsOnElement("flightModeCenter");
372 Matrix
= m_renderer
->matrixForElement("flightModeCenter");
373 orig
= Matrix
.mapRect(orig
);
374 m_txFlightModeCOrig
.translate(orig
.x(), orig
.y());
375 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
377 orig
= m_renderer
->boundsOnElement("flightModeLeft");
378 Matrix
= m_renderer
->matrixForElement("flightModeLeft");
379 orig
= Matrix
.mapRect(orig
);
380 m_txFlightModeLOrig
.translate(orig
.x(), orig
.y());
381 orig
= m_renderer
->boundsOnElement("flightModeRight");
382 Matrix
= m_renderer
->matrixForElement("flightModeRight");
383 orig
= Matrix
.mapRect(orig
);
384 m_txFlightModeROrig
.translate(orig
.x(), orig
.y());
386 orig
= m_renderer
->boundsOnElement("fm_count_bg");
387 Matrix
= m_renderer
->matrixForElement("fm_count_bg");
388 orig
= Matrix
.mapRect(orig
);
389 m_txFlightModeCountBGOrig
.translate(orig
.x(), orig
.y());
390 m_txFlightModeCountBG
->setTransform(m_txFlightModeCountBGOrig
, false);
392 QRectF flightModeBGRect
= m_txFlightModeCountBG
->boundingRect();
393 QRectF flightModeTextRect
= m_txFlightModeCountText
->boundingRect();
395 m_txFlightModeCountTextOrig
.translate(flightModeBGRect
.width() - (flightModeBGRect
.height() / 2), flightModeBGRect
.height() / 2);
396 m_txFlightModeCountTextOrig
.scale(scale
, scale
);
397 m_txFlightModeCountTextOrig
.translate(-flightModeTextRect
.width() / 2, -flightModeTextRect
.height() / 2);
398 m_txFlightModeCountText
->setTransform(m_txFlightModeCountTextOrig
, false);
400 orig
= m_renderer
->boundsOnElement("rjoy");
401 Matrix
= m_renderer
->matrixForElement("rjoy");
402 orig
= Matrix
.mapRect(orig
);
403 m_txRightStickOrig
.translate(orig
.x(), orig
.y());
404 m_txRightStick
->setTransform(m_txRightStickOrig
, false);
406 orig
= m_renderer
->boundsOnElement("access0");
407 Matrix
= m_renderer
->matrixForElement("access0");
408 orig
= Matrix
.mapRect(orig
);
409 m_txAccess0Orig
.translate(orig
.x(), orig
.y());
410 m_txAccess0
->setTransform(m_txAccess0Orig
, false);
412 orig
= m_renderer
->boundsOnElement("access1");
413 Matrix
= m_renderer
->matrixForElement("access1");
414 orig
= Matrix
.mapRect(orig
);
415 m_txAccess1Orig
.translate(orig
.x(), orig
.y());
416 m_txAccess1
->setTransform(m_txAccess1Orig
, false);
418 orig
= m_renderer
->boundsOnElement("access2");
419 Matrix
= m_renderer
->matrixForElement("access2");
420 orig
= Matrix
.mapRect(orig
);
421 m_txAccess2Orig
.translate(orig
.x(), orig
.y());
422 m_txAccess2
->setTransform(m_txAccess2Orig
, true);
424 orig
= m_renderer
->boundsOnElement("access3");
425 Matrix
= m_renderer
->matrixForElement("access3");
426 orig
= Matrix
.mapRect(orig
);
427 m_txAccess3Orig
.translate(orig
.x(), orig
.y());
428 m_txAccess3
->setTransform(m_txAccess3Orig
, true);
430 wizardUi
->graphicsView
->fitInView(m_txMainBody
, Qt::KeepAspectRatio
);
431 animate
= new QTimer(this);
432 connect(animate
, SIGNAL(timeout()), this, SLOT(moveTxControls()));
434 heliChannelOrder
<< ManualControlSettings::CHANNELGROUPS_COLLECTIVE
<<
435 ManualControlSettings::CHANNELGROUPS_THROTTLE
<<
436 ManualControlSettings::CHANNELGROUPS_ROLL
<<
437 ManualControlSettings::CHANNELGROUPS_PITCH
<<
438 ManualControlSettings::CHANNELGROUPS_YAW
<<
439 ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
<<
440 ManualControlSettings::CHANNELGROUPS_ACCESSORY0
<<
441 ManualControlSettings::CHANNELGROUPS_ACCESSORY1
<<
442 ManualControlSettings::CHANNELGROUPS_ACCESSORY2
<<
443 ManualControlSettings::CHANNELGROUPS_ACCESSORY3
;
445 acroChannelOrder
<< ManualControlSettings::CHANNELGROUPS_THROTTLE
<<
446 ManualControlSettings::CHANNELGROUPS_ROLL
<<
447 ManualControlSettings::CHANNELGROUPS_PITCH
<<
448 ManualControlSettings::CHANNELGROUPS_YAW
<<
449 ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
<<
450 ManualControlSettings::CHANNELGROUPS_ACCESSORY0
<<
451 ManualControlSettings::CHANNELGROUPS_ACCESSORY1
<<
452 ManualControlSettings::CHANNELGROUPS_ACCESSORY2
<<
453 ManualControlSettings::CHANNELGROUPS_ACCESSORY3
;
455 groundChannelOrder
<< ManualControlSettings::CHANNELGROUPS_THROTTLE
<<
456 ManualControlSettings::CHANNELGROUPS_YAW
<<
457 ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
<<
458 ManualControlSettings::CHANNELGROUPS_ACCESSORY0
;
461 void ConfigInputWidget::buildOptionComboBox(QComboBox
*combo
, UAVObjectField
*field
, int index
, bool applyLimits
)
463 if (combo
== ui
->failsafeFlightMode
|| combo
== ui
->failsafeBatteryCriticalFlightMode
|| combo
== ui
->failsafeBatteryWarningFlightMode
) {
464 for (quint32 i
= 0; i
< FlightModeSettings::FLIGHTMODEPOSITION_NUMELEM
; i
++) {
465 combo
->addItem(QString("Position %1").arg(i
+ 1), QVariant(i
));
468 ConfigTaskWidget::buildOptionComboBox(combo
, field
, index
, applyLimits
);
472 void ConfigInputWidget::resetTxControls()
474 m_txLeftStick
->setTransform(m_txLeftStickOrig
, false);
475 m_txRightStick
->setTransform(m_txRightStickOrig
, false);
476 m_txAccess0
->setTransform(m_txAccess0Orig
, false);
477 m_txAccess1
->setTransform(m_txAccess1Orig
, false);
478 m_txAccess2
->setTransform(m_txAccess2Orig
, false);
479 m_txAccess3
->setTransform(m_txAccess3Orig
, false);
480 m_txFlightMode
->setElementId("flightModeCenter");
481 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
482 m_txArrows
->setVisible(false);
483 m_txFlightModeCountText
->setText("?");
484 m_txFlightModeCountText
->setVisible(false);
485 m_txFlightModeCountBG
->setVisible(false);
488 ConfigInputWidget::~ConfigInputWidget()
491 void ConfigInputWidget::enableControls(bool enable
)
493 ConfigTaskWidget::enableControls(enable
);
496 updatePositionSlider();
498 // Hide configAlarmStatus when disconnected
499 ui
->configAlarmStatus
->setVisible(false);
500 if (wizardStep
!= wizardNone
) {
501 // Close input wizard
504 if (ui
->runCalibration
->isChecked()) {
505 // Close manual calibration
506 ui
->runCalibration
->setChecked(false);
507 ui
->runCalibration
->setText(tr("Start Manual Calibration"));
508 emit
inputCalibrationStateChanged(false);
513 void ConfigInputWidget::resizeEvent(QResizeEvent
*event
)
515 QWidget::resizeEvent(event
);
517 wizardUi
->graphicsView
->fitInView(m_txBackground
, Qt::KeepAspectRatio
);
520 void ConfigInputWidget::goToWizard()
522 if (!outputConfigIsSafe
) {
523 QMessageBox::warning(this, tr("Warning"), tr("There is something wrong in <b>Output</b> tab."
524 "<p>Please fix the issue before starting the Transmitter wizard.</p>"), QMessageBox::Ok
);
530 msgBox
.setText(tr("Arming Settings are now set to 'Always Disarmed' for your safety."));
531 msgBox
.setDetailedText(tr("You will have to reconfigure the arming settings manually "
532 "when the wizard is finished. After the last step of the "
533 "wizard you will be taken to the Arming Settings screen."));
534 msgBox
.setStandardButtons(QMessageBox::Ok
);
535 msgBox
.setDefaultButton(QMessageBox::Ok
);
538 // Tell Output tab we freeze actuators soon
539 emit
inputCalibrationStateChanged(true);
541 // Set correct tab visible before starting wizard.
542 if (ui
->tabWidget
->currentIndex() != 0) {
543 ui
->tabWidget
->setCurrentIndex(0);
546 // Stash current manual settings data in case the wizard is
547 // cancelled or the user proceeds far enough into the wizard such
548 // that the UAVO is changed, but then backs out to the start and
549 // chooses a different TX type (which could otherwise result in
550 // unexpected TX channels being enabled)
551 manualSettingsData
= manualSettingsObj
->getData();
552 memento
.manualSettingsData
= manualSettingsData
;
553 flightModeSettingsData
= flightModeSettingsObj
->getData();
554 memento
.flightModeSettingsData
= flightModeSettingsData
;
555 flightModeSettingsData
.Arming
= FlightModeSettings::ARMING_ALWAYSDISARMED
;
556 flightModeSettingsObj
->setData(flightModeSettingsData
);
557 // Stash actuatorSettings
558 actuatorSettingsData
= actuatorSettingsObj
->getData();
559 memento
.actuatorSettingsData
= actuatorSettingsData
;
561 // Stash systemSettings
562 systemSettingsData
= systemSettingsObj
->getData();
563 memento
.systemSettingsData
= systemSettingsData
;
565 // Now reset channel and actuator settings (disable outputs)
566 resetChannelSettings();
567 resetActuatorSettings();
569 // Use faster input update rate.
573 wizardSetUpStep(wizardWelcome
);
574 wizardUi
->graphicsView
->fitInView(m_txBackground
, Qt::KeepAspectRatio
);
577 void ConfigInputWidget::disableWizardButton(int value
)
580 ui
->groupBox_3
->setVisible(false);
582 ui
->groupBox_3
->setVisible(true);
586 void ConfigInputWidget::wzCancel()
588 dimOtherControls(false);
590 // Cancel any ongoing delayd next trigger.
591 wzNextDelayedCancel();
593 // Restore original input update rate.
596 ui
->stackedWidget
->setCurrentIndex(0);
598 if (wizardStep
!= wizardNone
) {
599 wizardTearDownStep(wizardStep
);
601 wizardStep
= wizardNone
;
602 ui
->stackedWidget
->setCurrentIndex(0);
604 // Load settings back from beginning of wizard
605 manualSettingsObj
->setData(memento
.manualSettingsData
);
606 flightModeSettingsObj
->setData(memento
.flightModeSettingsData
);
607 actuatorSettingsObj
->setData(memento
.actuatorSettingsData
);
608 systemSettingsObj
->setData(memento
.systemSettingsData
);
610 // Tell Output tab the calibration is ended
611 emit
inputCalibrationStateChanged(false);
614 void ConfigInputWidget::registerControlActivity()
616 nextDelayedLatestActivityTick
= nextDelayedTick
;
619 void ConfigInputWidget::wzNextDelayed()
623 // Call next after the full 2500 ms timeout has been reached,
624 // or if no input activity has occurred the last 500 ms.
625 if (nextDelayedTick
== 25 ||
626 nextDelayedTick
- nextDelayedLatestActivityTick
>= 5) {
631 void ConfigInputWidget::wzNextDelayedStart()
633 // Call wzNextDelayed every 100 ms, to see if it's time to go to the next page.
634 connect(&nextDelayedTimer
, SIGNAL(timeout()), this, SLOT(wzNextDelayed()));
635 nextDelayedTimer
.start(100);
638 // Cancel the delayed next timer, if it's active.
639 void ConfigInputWidget::wzNextDelayedCancel()
642 nextDelayedLatestActivityTick
= 0;
643 if (nextDelayedTimer
.isActive()) {
644 nextDelayedTimer
.stop();
645 disconnect(&nextDelayedTimer
, SIGNAL(timeout()), this, SLOT(wzNextDelayed()));
649 void ConfigInputWidget::wzNext()
651 wzNextDelayedCancel();
653 // In identify sticks mode the next button can indicate
655 if (wizardStep
!= wizardNone
&&
656 wizardStep
!= wizardIdentifySticks
) {
657 wizardTearDownStep(wizardStep
);
660 // State transitions for next button
661 switch (wizardStep
) {
663 wizardSetUpStep(wizardChooseType
);
665 case wizardChooseType
:
666 wizardSetUpStep(wizardChooseMode
);
668 case wizardChooseMode
:
669 wizardSetUpStep(wizardIdentifySticks
);
671 case wizardIdentifySticks
:
673 if (currentChannelNum
== -1) { // Gone through all channels
674 wizardTearDownStep(wizardIdentifySticks
);
675 wizardSetUpStep(wizardIdentifyCenter
);
678 case wizardIdentifyCenter
:
679 resetFlightModeSettings();
680 wizardSetUpStep(wizardIdentifyLimits
);
682 case wizardIdentifyLimits
:
683 wizardSetUpStep(wizardIdentifyInverted
);
685 case wizardIdentifyInverted
:
686 wizardSetUpStep(wizardFinish
);
689 wizardStep
= wizardNone
;
691 // Restore original input update rate.
694 // Load actuator settings back from beginning of wizard
695 actuatorSettingsObj
->setData(memento
.actuatorSettingsData
);
697 // Force flight mode neutral to middle and Throttle neutral at 4%
698 adjustSpecialNeutrals();
699 throttleError
= false;
700 checkThrottleRange();
702 manualSettingsObj
->setData(manualSettingsData
);
704 // move to Arming Settings tab
705 ui
->stackedWidget
->setCurrentIndex(0);
706 ui
->tabWidget
->setCurrentIndex(3);
708 // Tell Output tab the calibration is ended
709 emit
inputCalibrationStateChanged(false);
716 void ConfigInputWidget::wzBack()
718 wzNextDelayedCancel();
720 if (wizardStep
!= wizardNone
&&
721 wizardStep
!= wizardIdentifySticks
) {
722 wizardTearDownStep(wizardStep
);
725 // State transitions for back button
726 switch (wizardStep
) {
727 case wizardChooseType
:
728 wizardSetUpStep(wizardWelcome
);
730 case wizardChooseMode
:
731 wizardSetUpStep(wizardChooseType
);
733 case wizardIdentifySticks
:
735 if (currentChannelNum
== -1) {
736 wizardTearDownStep(wizardIdentifySticks
);
737 wizardSetUpStep(wizardChooseMode
);
740 case wizardIdentifyCenter
:
741 wizardSetUpStep(wizardIdentifySticks
);
743 case wizardIdentifyLimits
:
744 wizardSetUpStep(wizardIdentifyCenter
);
746 case wizardIdentifyInverted
:
747 resetFlightModeSettings();
748 wizardSetUpStep(wizardIdentifyLimits
);
751 wizardSetUpStep(wizardIdentifyInverted
);
758 void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step
)
760 wizardUi
->wzNext
->setText(tr("Next"));
764 foreach(QPointer
<QWidget
> wd
, extraWidgets
) {
769 extraWidgets
.clear();
770 wizardUi
->graphicsView
->setVisible(false);
771 setTxMovement(nothing
);
772 wizardUi
->wzBack
->setEnabled(false);
773 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->welcomePage
);
774 ui
->stackedWidget
->setCurrentIndex(1);
776 case wizardChooseType
:
778 wizardUi
->graphicsView
->setVisible(true);
779 wizardUi
->graphicsView
->fitInView(m_txBackground
, Qt::KeepAspectRatio
);
780 setTxMovement(nothing
);
781 wizardUi
->wzBack
->setEnabled(true);
782 if (transmitterType
== heli
) {
783 wizardUi
->typeHeli
->setChecked(true);
784 } else if (transmitterType
== ground
) {
785 wizardUi
->typeGround
->setChecked(true);
787 wizardUi
->typeAcro
->setChecked(true);
789 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->chooseTypePage
);
792 case wizardChooseMode
:
794 wizardUi
->wzBack
->setEnabled(true);
795 QRadioButton
*modeButtons
[] = {
796 wizardUi
->mode1Button
,
797 wizardUi
->mode2Button
,
798 wizardUi
->mode3Button
,
799 wizardUi
->mode4Button
802 for (int i
= 0; i
<= mode4
; ++i
) {
804 txMode mode
= static_cast<txMode
>(i
);
805 if (transmitterType
== heli
) {
807 case mode1
: label
= tr("Mode 1: Fore/Aft Cyclic and Yaw on the left, Throttle/Collective and Left/Right Cyclic on the right"); break;
808 case mode2
: label
= tr("Mode 2: Throttle/Collective and Yaw on the left, Cyclic on the right"); break;
809 case mode3
: label
= tr("Mode 3: Cyclic on the left, Throttle/Collective and Yaw on the right"); break;
810 case mode4
: label
= tr("Mode 4: Throttle/Collective and Left/Right Cyclic on the left, Fore/Aft Cyclic and Yaw on the right"); break;
811 default: Q_ASSERT(0); break;
813 wizardUi
->typePageFooter
->setText(" ");
816 case mode1
: label
= tr("Mode 1: Elevator and Rudder on the left, Throttle and Ailerons on the right"); break;
817 case mode2
: label
= tr("Mode 2: Throttle and Rudder on the left, Elevator and Ailerons on the right"); break;
818 case mode3
: label
= tr("Mode 3: Elevator and Ailerons on the left, Throttle and Rudder on the right"); break;
819 case mode4
: label
= tr("Mode 4: Throttle and Ailerons on the left, Elevator and Rudder on the right"); break;
820 default: Q_ASSERT(0); break;
822 wizardUi
->typePageFooter
->setText(tr("For a Quad: Elevator is Pitch, Ailerons are Roll, and Rudder is Yaw."));
824 modeButtons
[i
]->setText(label
);
825 if (transmitterMode
== mode
) {
826 modeButtons
[i
]->setChecked(true);
829 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->chooseModePage
);
832 case wizardIdentifySticks
:
833 usedChannels
.clear();
834 currentChannelNum
= -1;
836 manualSettingsData
= manualSettingsObj
->getData();
837 connect(receiverActivityObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyControls()));
838 wizardUi
->wzNext
->setEnabled(false);
839 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifySticksPage
);
841 case wizardIdentifyCenter
:
842 setTxMovement(centerAll
);
843 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifyCenterPage
);
844 if (transmitterType
== ground
) {
845 wizardUi
->identifyCenterInstructions
->setText(QString(tr("Please center all controls and trims and press Next when ready.\n\n"
846 "For a ground vehicle, this center position will be used as neutral value of each channel.")));
849 case wizardIdentifyLimits
:
851 setTxMovement(nothing
);
852 manualSettingsData
= manualSettingsObj
->getData();
853 for (uint i
= 0; i
< ManualControlSettings::CHANNELNUMBER_RSSI
; ++i
) {
854 // Preserve the inverted status
855 if (manualSettingsData
.ChannelMin
[i
] <= manualSettingsData
.ChannelMax
[i
]) {
856 manualSettingsData
.ChannelMin
[i
] = manualSettingsData
.ChannelNeutral
[i
];
857 manualSettingsData
.ChannelMax
[i
] = manualSettingsData
.ChannelNeutral
[i
];
859 // Make this detect as still inverted
860 manualSettingsData
.ChannelMin
[i
] = manualSettingsData
.ChannelNeutral
[i
] + 1;
861 manualSettingsData
.ChannelMax
[i
] = manualSettingsData
.ChannelNeutral
[i
];
864 UAVObjectUpdaterHelper updateHelper
;
865 manualSettingsObj
->setData(manualSettingsData
, false);
866 updateHelper
.doObjectAndWait(manualSettingsObj
);
868 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyLimits()));
869 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
870 connect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
871 connect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
873 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifyLimitsPage
);
876 case wizardIdentifyInverted
:
877 dimOtherControls(true);
878 setTxMovement(nothing
);
879 extraWidgets
.clear();
880 for (int index
= 0; index
< manualSettingsObj
->getField("ChannelMax")->getElementNames().length(); index
++) {
881 QString name
= manualSettingsObj
->getField("ChannelMax")->getElementNames().at(index
);
882 if (!name
.contains("Access") && !name
.contains("Flight") && !name
.contains("Rssi") &&
883 (!name
.contains("Collective") || transmitterType
== heli
)) {
884 QCheckBox
*cb
= new QCheckBox(name
, this);
885 // Make sure checked status matches current one
886 cb
->setChecked(manualSettingsData
.ChannelMax
[index
] < manualSettingsData
.ChannelMin
[index
]);
887 wizardUi
->checkBoxesLayout
->addWidget(cb
, extraWidgets
.size() / 5, extraWidgets
.size() % 5);
888 extraWidgets
.append(cb
);
889 connect(cb
, SIGNAL(toggled(bool)), this, SLOT(invertControls()));
892 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
893 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->identifyInvertedPage
);
896 dimOtherControls(false);
897 connect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
898 connect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
899 connect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
900 wizardUi
->pagesStack
->setCurrentWidget(wizardUi
->finishPage
);
908 void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step
)
910 UAVObjectUpdaterHelper updateHelper
;
912 Q_ASSERT(step
== wizardStep
);
916 case wizardChooseType
:
917 if (wizardUi
->typeAcro
->isChecked()) {
918 transmitterType
= acro
;
919 } else if (wizardUi
->typeGround
->isChecked()) {
920 transmitterType
= ground
;
922 systemSettingsData
= systemSettingsObj
->getData();
923 /* Make sure to tell controller, this is really a ground vehicle. */
924 if ((systemSettingsData
.AirframeType
!= SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR
) ||
925 (systemSettingsData
.AirframeType
!= SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL
) ||
926 (systemSettingsData
.AirframeType
!= SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE
) ||
927 (systemSettingsData
.AirframeType
!= SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEBOAT
) ||
928 (systemSettingsData
.AirframeType
!= SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIALBOAT
)) {
929 // Apply default ground vehicle airframe
930 systemSettingsData
.AirframeType
= SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR
;
931 systemSettingsObj
->setData(systemSettingsData
);
934 transmitterType
= heli
;
937 case wizardChooseMode
:
939 QRadioButton
*modeButtons
[] = {
940 wizardUi
->mode1Button
,
941 wizardUi
->mode2Button
,
942 wizardUi
->mode3Button
,
943 wizardUi
->mode4Button
945 for (int i
= mode1
; i
<= mode4
; ++i
) {
946 if (modeButtons
[i
]->isChecked()) {
947 transmitterMode
= static_cast<txMode
>(i
);
952 case wizardIdentifySticks
:
953 disconnect(receiverActivityObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyControls()));
954 wizardUi
->wzNext
->setEnabled(true);
955 setTxMovement(nothing
);
957 case wizardIdentifyCenter
:
958 manualCommandData
= manualCommandObj
->getData();
959 manualSettingsData
= manualSettingsObj
->getData();
960 // Ignore last Rssi channel
961 for (unsigned int i
= 0; i
< ManualControlSettings::CHANNELNUMBER_RSSI
; ++i
) {
962 // Set Accessory neutral to middle range
963 if (i
>= ManualControlSettings::CHANNELNUMBER_ACCESSORY0
) {
964 manualSettingsData
.ChannelNeutral
[i
] = manualSettingsData
.ChannelMin
[i
] + ((manualSettingsData
.ChannelMax
[i
] - manualSettingsData
.ChannelMin
[i
]) / 2);
966 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
969 manualSettingsObj
->setData(manualSettingsData
, false);
970 updateHelper
.doObjectAndWait(manualSettingsObj
);
971 setTxMovement(nothing
);
973 case wizardIdentifyLimits
:
974 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(identifyLimits()));
975 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
976 disconnect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
977 disconnect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
978 manualSettingsObj
->setData(manualSettingsData
, false);
979 updateHelper
.doObjectAndWait(manualSettingsObj
);
980 setTxMovement(nothing
);
982 case wizardIdentifyInverted
:
983 dimOtherControls(false);
984 foreach(QWidget
* wd
, extraWidgets
) {
985 QCheckBox
*cb
= qobject_cast
<QCheckBox
*>(wd
);
988 disconnect(cb
, SIGNAL(toggled(bool)), this, SLOT(invertControls()));
992 extraWidgets
.clear();
993 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
996 dimOtherControls(false);
997 setTxMovement(nothing
);
998 disconnect(manualCommandObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
999 disconnect(flightStatusObj
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
1000 disconnect(accessoryDesiredObj0
, SIGNAL(objectUpdated(UAVObject
*)), this, SLOT(moveSticks()));
1007 static void fastMdataSingle(UAVDataObject
*object
, UAVObject::Metadata
*savedMdata
)
1009 *savedMdata
= object
->getMetadata();
1010 UAVObject::Metadata mdata
= *savedMdata
;
1011 UAVObject::SetFlightTelemetryUpdateMode(mdata
, UAVObject::UPDATEMODE_PERIODIC
);
1012 mdata
.flightTelemetryUpdatePeriod
= 150;
1013 object
->setMetadata(mdata
);
1016 static void restoreMdataSingle(UAVDataObject
*object
, UAVObject::Metadata
*savedMdata
)
1018 object
->setMetadata(*savedMdata
);
1022 * Set manual control command to fast updates
1024 void ConfigInputWidget::fastMdata()
1026 fastMdataSingle(manualCommandObj
, &manualControlMdata
);
1027 fastMdataSingle(accessoryDesiredObj0
, &accessoryDesiredMdata0
);
1031 * Restore previous update settings for manual control data
1033 void ConfigInputWidget::restoreMdata()
1035 restoreMdataSingle(manualCommandObj
, &manualControlMdata
);
1036 restoreMdataSingle(accessoryDesiredObj0
, &accessoryDesiredMdata0
);
1040 * Set the display to indicate which channel the person should move
1042 void ConfigInputWidget::setChannel(int newChan
)
1044 bool canBeSkipped
= false;
1046 if (newChan
== ManualControlSettings::CHANNELGROUPS_COLLECTIVE
) {
1047 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please enable throttle hold mode.</p>"
1048 "<p>Move the Collective Pitch stick.</p>")));
1049 } else if (newChan
== ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
) {
1050 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please toggle the Flight Mode switch.</p>"
1051 "<p>For switches you may have to repeat this rapidly.</p>"
1052 "<p>Alternatively, you can click Next to skip this channel, but you will get only <b>ONE</b> Flight Mode.</p>")));
1053 canBeSkipped
= true;
1054 } else if ((transmitterType
== heli
) && (newChan
== ManualControlSettings::CHANNELGROUPS_THROTTLE
)) {
1055 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please disable throttle hold mode.</p>"
1056 "<p>Move the Throttle stick.</p>")));
1058 wizardUi
->identifyStickInstructions
->setText(QString(tr("<p>Please move each control one at a time according to the instructions and picture below.</p>"
1059 "<p>Move the %1 stick.</p>")).arg(manualSettingsObj
->getField("ChannelGroups")->getElementNames().at(newChan
)));
1062 if (manualSettingsObj
->getField("ChannelGroups")->getElementNames().at(newChan
).contains("Accessory")) {
1063 wizardUi
->identifyStickInstructions
->setText(wizardUi
->identifyStickInstructions
->text() + tr("<p>Alternatively, click Next to skip this channel.</p>"));
1064 canBeSkipped
= true;
1068 wizardUi
->wzNext
->setEnabled(true);
1069 wizardUi
->wzNext
->setText(tr("Next / Skip"));
1071 wizardUi
->wzNext
->setEnabled(false);
1074 setMoveFromCommand(newChan
);
1075 currentChannelNum
= newChan
;
1076 channelDetected
= false;
1080 * Unfortunately order of channel should be different in different conditions. Selects
1081 * next channel based on heli or acro mode
1083 void ConfigInputWidget::nextChannel()
1086 switch (transmitterType
) {
1088 order
= heliChannelOrder
;
1091 order
= groundChannelOrder
;
1094 order
= acroChannelOrder
;
1098 if (currentChannelNum
== -1) {
1099 setChannel(order
[0]);
1102 for (int i
= 0; i
< order
.length() - 1; i
++) {
1103 if (order
[i
] == currentChannelNum
) {
1104 setChannel(order
[i
+ 1]);
1108 currentChannelNum
= -1; // hit end of list
1112 * Unfortunately order of channel should be different in different conditions. Selects
1113 * previous channel based on heli or acro mode
1115 void ConfigInputWidget::prevChannel()
1118 switch (transmitterType
) {
1120 order
= heliChannelOrder
;
1123 order
= groundChannelOrder
;
1126 order
= acroChannelOrder
;
1130 // No previous from unset channel or next state
1131 if (currentChannelNum
== -1) {
1135 for (int i
= 1; i
< order
.length(); i
++) {
1136 if (order
[i
] == currentChannelNum
) {
1137 if (!usedChannels
.isEmpty() &&
1138 usedChannels
.back().channelIndex
== order
[i
- 1]) {
1139 usedChannels
.removeLast();
1141 setChannel(order
[i
- 1]);
1145 currentChannelNum
= -1; // hit end of list
1148 void ConfigInputWidget::identifyControls()
1150 static const int DEBOUNCE_COUNT
= 4;
1151 static int debounce
= 0;
1153 receiverActivityData
= receiverActivityObj
->getData();
1155 if (receiverActivityData
.ActiveChannel
== 255) {
1159 if (channelDetected
) {
1160 registerControlActivity();
1164 receiverActivityData
= receiverActivityObj
->getData();
1165 currentChannel
.group
= receiverActivityData
.ActiveGroup
;
1166 currentChannel
.number
= receiverActivityData
.ActiveChannel
;
1168 if (debounce
== 0) {
1169 // Register a channel to be debounced.
1170 lastChannel
.group
= currentChannel
.group
;
1171 lastChannel
.number
= currentChannel
.number
;
1172 lastChannel
.channelIndex
= currentChannelNum
;
1177 if (currentChannel
!= lastChannel
) {
1178 // A new channel was seen. Only register it if we count down to 0.
1183 if (debounce
< DEBOUNCE_COUNT
) {
1184 // We still haven't seen enough enough activity on this channel yet.
1189 // Channel has been debounced and it's enough record it.
1191 if (usedChannels
.contains(lastChannel
)) {
1192 // Channel is already recorded.
1196 // Record the channel.
1198 channelDetected
= true;
1200 usedChannels
.append(lastChannel
);
1201 manualSettingsData
= manualSettingsObj
->getData();
1202 manualSettingsData
.ChannelGroups
[currentChannelNum
] = currentChannel
.group
;
1203 manualSettingsData
.ChannelNumber
[currentChannelNum
] = currentChannel
.number
;
1204 manualSettingsObj
->setData(manualSettingsData
);
1206 // m_config->wzText->clear();
1207 setTxMovement(nothing
);
1209 wzNextDelayedStart();
1212 void ConfigInputWidget::identifyLimits()
1214 uint16_t inputValue
;
1215 static uint16_t previousInputFMValue
;
1216 bool newLimitValue
= false;
1217 bool newFlightModeValue
= false;
1219 manualCommandData
= manualCommandObj
->getData();
1220 for (uint i
= 0; i
< ManualControlSettings::CHANNELNUMBER_RSSI
; ++i
) {
1221 inputValue
= manualCommandData
.Channel
[i
];
1222 // Check if channel is already detected and prevent glitches
1223 if ((manualSettingsData
.ChannelNumber
[i
] != CHANNEL_NUMBER_NONE
) &&
1224 (inputValue
> MIN_INPUT_US
) && (inputValue
< MAX_INPUT_US
)) {
1225 if (manualSettingsData
.ChannelMin
[i
] <= manualSettingsData
.ChannelMax
[i
]) {
1226 // Non inverted channel
1227 if (manualSettingsData
.ChannelMin
[i
] > inputValue
) {
1228 manualSettingsData
.ChannelMin
[i
] = inputValue
;
1229 newLimitValue
= true;
1231 if (manualSettingsData
.ChannelMax
[i
] < inputValue
) {
1232 manualSettingsData
.ChannelMax
[i
] = inputValue
;
1233 newLimitValue
= true;
1237 if (manualSettingsData
.ChannelMax
[i
] > inputValue
) {
1238 manualSettingsData
.ChannelMax
[i
] = inputValue
;
1239 newLimitValue
= true;
1241 if (manualSettingsData
.ChannelMin
[i
] < inputValue
) {
1242 manualSettingsData
.ChannelMin
[i
] = inputValue
;
1243 newLimitValue
= true;
1246 // Flightmode channel
1247 if (i
== ManualControlSettings::CHANNELGROUPS_FLIGHTMODE
) {
1248 int deltaInput
= abs(previousInputFMValue
- inputValue
);
1249 previousInputFMValue
= inputValue
;
1250 // Expecting two consecutive readings within a close value
1251 if (deltaInput
< 5) {
1252 // Avoid duplicate values too close and error due to RcTx drift
1253 int minSpacing
= 100; // 100µs
1254 for (int pos
= 0; pos
< manualSettingsData
.FlightModeNumber
+ 1; ++pos
) {
1255 if (flightModeSignalValue
[pos
] == 0) {
1256 newFlightModeValue
= true;
1257 // A new flightmode value can be set now
1258 for (int checkpos
= 0; checkpos
< manualSettingsData
.FlightModeNumber
+ 1; ++checkpos
) {
1259 // Check if value is already used, MinSpacing needed between values.
1260 if ((flightModeSignalValue
[checkpos
] < inputValue
+ minSpacing
) &&
1261 (flightModeSignalValue
[checkpos
] > inputValue
- minSpacing
)) {
1262 newFlightModeValue
= false;
1265 // Be sure FlightModeNumber is < FlightModeSettings::FLIGHTMODEPOSITION_NUMELEM (6)
1266 if ((manualSettingsData
.FlightModeNumber
< FlightModeSettings::FLIGHTMODEPOSITION_NUMELEM
) && newFlightModeValue
) {
1267 // Start from 0, erase previous count
1269 manualSettingsData
.FlightModeNumber
= 0;
1271 // Store new value and increase FlightModeNumber
1272 flightModeSignalValue
[pos
] = inputValue
;
1273 manualSettingsData
.FlightModeNumber
++;
1274 // Show flight mode number
1275 m_txFlightModeCountText
->setText(QString().number(manualSettingsData
.FlightModeNumber
));
1276 m_txFlightModeCountText
->setVisible(true);
1277 m_txFlightModeCountBG
->setVisible(true);
1285 // Save only if something changed
1286 if (newLimitValue
|| newFlightModeValue
) {
1287 UAVObjectUpdaterHelper updateHelper
;
1288 manualSettingsObj
->setData(manualSettingsData
, false);
1289 updateHelper
.doObjectAndWait(manualSettingsObj
);
1293 void ConfigInputWidget::setMoveFromCommand(int command
)
1295 // ManualControlSettings::ChannelNumberElem:
1296 // CHANNELNUMBER_ROLL=0,
1297 // CHANNELNUMBER_PITCH=1,
1298 // CHANNELNUMBER_YAW=2,
1299 // CHANNELNUMBER_THROTTLE=3,
1300 // CHANNELNUMBER_FLIGHTMODE=4,
1301 // CHANNELNUMBER_ACCESSORY0=5,
1302 // CHANNELNUMBER_ACCESSORY1=6,
1303 // CHANNELNUMBER_ACCESSORY2=7
1305 txMovements movement
= moveLeftVerticalStick
;
1308 case ManualControlSettings::CHANNELNUMBER_ROLL
:
1309 movement
= ((transmitterMode
== mode3
|| transmitterMode
== mode4
) ?
1310 moveLeftHorizontalStick
: moveRightHorizontalStick
);
1312 case ManualControlSettings::CHANNELNUMBER_PITCH
:
1313 movement
= (transmitterMode
== mode1
|| transmitterMode
== mode3
) ?
1314 moveLeftVerticalStick
: moveRightVerticalStick
;
1316 case ManualControlSettings::CHANNELNUMBER_YAW
:
1317 movement
= ((transmitterMode
== mode1
|| transmitterMode
== mode2
) ?
1318 moveLeftHorizontalStick
: moveRightHorizontalStick
);
1320 case ManualControlSettings::CHANNELNUMBER_THROTTLE
:
1321 movement
= (transmitterMode
== mode2
|| transmitterMode
== mode4
) ?
1322 moveLeftVerticalStick
: moveRightVerticalStick
;
1324 case ManualControlSettings::CHANNELNUMBER_COLLECTIVE
:
1325 movement
= (transmitterMode
== mode2
|| transmitterMode
== mode4
) ?
1326 moveLeftVerticalStick
: moveRightVerticalStick
;
1328 case ManualControlSettings::CHANNELNUMBER_FLIGHTMODE
:
1329 movement
= moveFlightMode
;
1331 case ManualControlSettings::CHANNELNUMBER_ACCESSORY0
:
1332 movement
= moveAccess0
;
1334 case ManualControlSettings::CHANNELNUMBER_ACCESSORY1
:
1335 movement
= moveAccess1
;
1337 case ManualControlSettings::CHANNELNUMBER_ACCESSORY2
:
1338 movement
= moveAccess2
;
1340 case ManualControlSettings::CHANNELNUMBER_ACCESSORY3
:
1341 movement
= moveAccess3
;
1347 setTxMovement(movement
);
1350 void ConfigInputWidget::setTxMovement(txMovements movement
)
1354 case moveLeftVerticalStick
:
1357 currentMovement
= moveLeftVerticalStick
;
1358 animate
->start(100);
1360 case moveRightVerticalStick
:
1363 currentMovement
= moveRightVerticalStick
;
1364 animate
->start(100);
1366 case moveLeftHorizontalStick
:
1369 currentMovement
= moveLeftHorizontalStick
;
1370 animate
->start(100);
1372 case moveRightHorizontalStick
:
1375 currentMovement
= moveRightHorizontalStick
;
1376 animate
->start(100);
1381 currentMovement
= moveAccess0
;
1382 animate
->start(100);
1387 currentMovement
= moveAccess1
;
1388 animate
->start(100);
1393 currentMovement
= moveAccess2
;
1394 animate
->start(100);
1399 currentMovement
= moveAccess3
;
1400 animate
->start(100);
1402 case moveFlightMode
:
1405 currentMovement
= moveFlightMode
;
1406 animate
->start(1000);
1410 currentMovement
= centerAll
;
1411 animate
->start(1000);
1416 currentMovement
= moveAll
;
1429 void ConfigInputWidget::moveTxControls()
1432 QGraphicsItem
*item
= NULL
;
1433 txMovementType move
= vertical
;
1436 static bool auxFlag
= false;
1438 switch (currentMovement
) {
1439 case moveLeftVerticalStick
:
1440 item
= m_txLeftStick
;
1441 trans
= m_txLeftStickOrig
;
1442 limitMax
= STICK_MAX_MOVE
;
1443 limitMin
= STICK_MIN_MOVE
;
1446 case moveRightVerticalStick
:
1447 item
= m_txRightStick
;
1448 trans
= m_txRightStickOrig
;
1449 limitMax
= STICK_MAX_MOVE
;
1450 limitMin
= STICK_MIN_MOVE
;
1453 case moveLeftHorizontalStick
:
1454 item
= m_txLeftStick
;
1455 trans
= m_txLeftStickOrig
;
1456 limitMax
= STICK_MAX_MOVE
;
1457 limitMin
= STICK_MIN_MOVE
;
1460 case moveRightHorizontalStick
:
1461 item
= m_txRightStick
;
1462 trans
= m_txRightStickOrig
;
1463 limitMax
= STICK_MAX_MOVE
;
1464 limitMin
= STICK_MIN_MOVE
;
1469 trans
= m_txAccess0Orig
;
1470 limitMax
= ACCESS_MAX_MOVE
;
1471 limitMin
= ACCESS_MIN_MOVE
;
1476 trans
= m_txAccess1Orig
;
1477 limitMax
= ACCESS_MAX_MOVE
;
1478 limitMin
= ACCESS_MIN_MOVE
;
1483 trans
= m_txAccess2Orig
;
1484 limitMax
= ACCESS_MAX_MOVE
;
1485 limitMin
= ACCESS_MIN_MOVE
;
1490 trans
= m_txAccess3Orig
;
1491 limitMax
= ACCESS_MAX_MOVE
;
1492 limitMin
= ACCESS_MIN_MOVE
;
1495 case moveFlightMode
:
1496 item
= m_txFlightMode
;
1504 limitMax
= STICK_MAX_MOVE
;
1505 limitMin
= STICK_MIN_MOVE
;
1511 if (move
== vertical
) {
1512 item
->setTransform(trans
.translate(0, movePos
* 10), false);
1513 } else if (move
== horizontal
) {
1514 item
->setTransform(trans
.translate(movePos
* 10, 0), false);
1515 } else if (move
== jump
) {
1516 if (item
== m_txArrows
) {
1517 m_txArrows
->setVisible(!m_txArrows
->isVisible());
1518 } else if (item
== m_txFlightMode
) {
1519 QGraphicsSvgItem
*svg
;
1520 svg
= (QGraphicsSvgItem
*)item
;
1522 if (svg
->elementId() == "flightModeCenter") {
1524 svg
->setElementId("flightModeRight");
1525 m_txFlightMode
->setTransform(m_txFlightModeROrig
, false);
1527 svg
->setElementId("flightModeLeft");
1528 m_txFlightMode
->setTransform(m_txFlightModeLOrig
, false);
1530 } else if (svg
->elementId() == "flightModeRight") {
1532 svg
->setElementId("flightModeCenter");
1533 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1534 } else if (svg
->elementId() == "flightModeLeft") {
1536 svg
->setElementId("flightModeCenter");
1537 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1541 } else if (move
== mix
) {
1542 trans
= m_txAccess0Orig
;
1543 m_txAccess0
->setTransform(trans
.translate(movePos
* 10 * ACCESS_MAX_MOVE
/ STICK_MAX_MOVE
, 0), false);
1544 trans
= m_txAccess1Orig
;
1545 m_txAccess1
->setTransform(trans
.translate(movePos
* 10 * ACCESS_MAX_MOVE
/ STICK_MAX_MOVE
, 0), false);
1546 trans
= m_txAccess2Orig
;
1547 m_txAccess2
->setTransform(trans
.translate(movePos
* 10 * ACCESS_MAX_MOVE
/ STICK_MAX_MOVE
, 0), false);
1548 trans
= m_txAccess3Orig
;
1549 m_txAccess3
->setTransform(trans
.translate(movePos
* 10 * ACCESS_MAX_MOVE
/ STICK_MAX_MOVE
, 0), false);
1552 trans
= m_txLeftStickOrig
;
1553 m_txLeftStick
->setTransform(trans
.translate(0, movePos
* 10), false);
1554 trans
= m_txRightStickOrig
;
1555 m_txRightStick
->setTransform(trans
.translate(0, movePos
* 10), false);
1557 trans
= m_txLeftStickOrig
;
1558 m_txLeftStick
->setTransform(trans
.translate(movePos
* 10, 0), false);
1559 trans
= m_txRightStickOrig
;
1560 m_txRightStick
->setTransform(trans
.translate(movePos
* 10, 0), false);
1564 m_txFlightMode
->setElementId("flightModeCenter");
1565 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1566 } else if (movePos
== ACCESS_MAX_MOVE
/ 2) {
1567 m_txFlightMode
->setElementId("flightModeRight");
1568 m_txFlightMode
->setTransform(m_txFlightModeROrig
, false);
1569 } else if (movePos
== ACCESS_MIN_MOVE
/ 2) {
1570 m_txFlightMode
->setElementId("flightModeLeft");
1571 m_txFlightMode
->setTransform(m_txFlightModeLOrig
, false);
1574 if (move
== horizontal
|| move
== vertical
|| move
== mix
) {
1575 if (movePos
== 0 && growing
) {
1583 if (movePos
> limitMax
) {
1584 movePos
= movePos
- 2;
1587 if (movePos
< limitMin
) {
1588 movePos
= movePos
+ 2;
1594 AccessoryDesired
*ConfigInputWidget::getAccessoryDesiredInstance(int instance
)
1598 if (accessoryDesiredObj0
== NULL
) {
1599 accessoryDesiredObj0
= AccessoryDesired::GetInstance(getObjectManager(), 0);
1601 return accessoryDesiredObj0
;
1604 if (accessoryDesiredObj1
== NULL
) {
1605 accessoryDesiredObj1
= AccessoryDesired::GetInstance(getObjectManager(), 1);
1607 return accessoryDesiredObj1
;
1610 if (accessoryDesiredObj2
== NULL
) {
1611 accessoryDesiredObj2
= AccessoryDesired::GetInstance(getObjectManager(), 2);
1613 return accessoryDesiredObj2
;
1616 if (accessoryDesiredObj3
== NULL
) {
1617 accessoryDesiredObj3
= AccessoryDesired::GetInstance(getObjectManager(), 3);
1619 return accessoryDesiredObj3
;
1628 float ConfigInputWidget::getAccessoryDesiredValue(int instance
)
1630 AccessoryDesired
*accessoryDesiredObj
= getAccessoryDesiredInstance(instance
);
1632 if (accessoryDesiredObj
== NULL
) {
1637 AccessoryDesired::DataFields data
= accessoryDesiredObj
->getData();
1639 return data
.AccessoryVal
;
1642 void ConfigInputWidget::moveSticks()
1646 manualCommandData
= manualCommandObj
->getData();
1647 flightStatusData
= flightStatusObj
->getData();
1649 switch (transmitterMode
) {
1651 trans
= m_txLeftStickOrig
;
1652 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1653 trans
= m_txRightStickOrig
;
1654 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1657 trans
= m_txLeftStickOrig
;
1658 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1659 trans
= m_txRightStickOrig
;
1660 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1663 trans
= m_txLeftStickOrig
;
1664 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1665 trans
= m_txRightStickOrig
;
1666 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1669 trans
= m_txLeftStickOrig
;
1670 m_txLeftStick
->setTransform(trans
.translate(manualCommandData
.Roll
* STICK_MAX_MOVE
* 10, -manualCommandData
.Throttle
* STICK_MAX_MOVE
* 10), false);
1671 trans
= m_txRightStickOrig
;
1672 m_txRightStick
->setTransform(trans
.translate(manualCommandData
.Yaw
* STICK_MAX_MOVE
* 10, manualCommandData
.Pitch
* STICK_MAX_MOVE
* 10), false);
1678 if ((flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[0]) ||
1679 (flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[5])) {
1680 m_txFlightMode
->setElementId("flightModeLeft");
1681 m_txFlightMode
->setTransform(m_txFlightModeLOrig
, false);
1682 } else if ((flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[1]) ||
1683 (flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[4])) {
1684 m_txFlightMode
->setElementId("flightModeCenter");
1685 m_txFlightMode
->setTransform(m_txFlightModeCOrig
, false);
1686 } else if ((flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[2]) ||
1687 (flightStatusData
.FlightMode
== flightModeSettingsData
.FlightModePosition
[3])) {
1688 m_txFlightMode
->setElementId("flightModeRight");
1689 m_txFlightMode
->setTransform(m_txFlightModeROrig
, false);
1692 m_txAccess0
->setTransform(QTransform(m_txAccess0Orig
).translate(getAccessoryDesiredValue(0) * ACCESS_MAX_MOVE
* 10, 0), false);
1693 m_txAccess1
->setTransform(QTransform(m_txAccess1Orig
).translate(getAccessoryDesiredValue(1) * ACCESS_MAX_MOVE
* 10, 0), false);
1694 m_txAccess2
->setTransform(QTransform(m_txAccess2Orig
).translate(getAccessoryDesiredValue(2) * ACCESS_MAX_MOVE
* 10, 0), false);
1695 m_txAccess3
->setTransform(QTransform(m_txAccess3Orig
).translate(getAccessoryDesiredValue(3) * ACCESS_MAX_MOVE
* 10, 0), false);
1698 void ConfigInputWidget::dimOtherControls(bool value
)
1707 m_txAccess0
->setOpacity(opac
);
1708 m_txAccess1
->setOpacity(opac
);
1709 m_txAccess2
->setOpacity(opac
);
1710 m_txAccess3
->setOpacity(opac
);
1711 m_txFlightMode
->setOpacity(opac
);
1714 void ConfigInputWidget::invertControls()
1716 manualSettingsData
= manualSettingsObj
->getData();
1717 foreach(QWidget
* wd
, extraWidgets
) {
1718 QCheckBox
*cb
= qobject_cast
<QCheckBox
*>(wd
);
1721 int index
= manualSettingsObj
->getField("ChannelNumber")->getElementNames().indexOf(cb
->text());
1722 if ((cb
->isChecked() && (manualSettingsData
.ChannelMax
[index
] > manualSettingsData
.ChannelMin
[index
])) ||
1723 (!cb
->isChecked() && (manualSettingsData
.ChannelMax
[index
] < manualSettingsData
.ChannelMin
[index
]))) {
1725 aux
= manualSettingsData
.ChannelMax
[index
];
1726 manualSettingsData
.ChannelMax
[index
] = manualSettingsData
.ChannelMin
[index
];
1727 manualSettingsData
.ChannelMin
[index
] = aux
;
1731 UAVObjectUpdaterHelper updateHelper
;
1732 manualSettingsObj
->setData(manualSettingsData
, false);
1733 updateHelper
.doObjectAndWait(manualSettingsObj
);
1736 void ConfigInputWidget::moveFMSlider()
1738 ManualControlSettings::DataFields manualSettingsDataPriv
= manualSettingsObj
->getData();
1739 ManualControlCommand::DataFields manualCommandDataPriv
= manualCommandObj
->getData();
1742 int chMin
= manualSettingsDataPriv
.ChannelMin
[ManualControlSettings::CHANNELMIN_FLIGHTMODE
];
1743 int chMax
= manualSettingsDataPriv
.ChannelMax
[ManualControlSettings::CHANNELMAX_FLIGHTMODE
];
1744 int chNeutral
= manualSettingsDataPriv
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE
];
1746 int value
= manualCommandDataPriv
.Channel
[ManualControlSettings::CHANNELMIN_FLIGHTMODE
];
1748 if ((chMax
> chMin
&& value
>= chNeutral
) || (chMin
> chMax
&& value
<= chNeutral
)) {
1749 if (chMax
!= chNeutral
) {
1750 valueScaled
= (float)(value
- chNeutral
) / (float)(chMax
- chNeutral
);
1755 if (chMin
!= chNeutral
) {
1756 valueScaled
= (float)(value
- chNeutral
) / (float)(chNeutral
- chMin
);
1762 // Bound and scale FlightMode from [-1..+1] to [0..1] range
1763 if (valueScaled
< -1.0) {
1765 } else if (valueScaled
> 1.0) {
1769 // Convert flightMode value into the switch position in the range [0..N-1]
1770 // This uses the same optimized computation as flight code to be consistent
1771 uint8_t pos
= ((int16_t)(valueScaled
* 256) + 256) * manualSettingsDataPriv
.FlightModeNumber
>> 9;
1772 if (pos
>= manualSettingsDataPriv
.FlightModeNumber
) {
1773 pos
= manualSettingsDataPriv
.FlightModeNumber
- 1;
1775 ui
->fmsSlider
->setValue(pos
);
1776 highlightStabilizationMode(pos
);
1779 void ConfigInputWidget::highlightStabilizationMode(int pos
)
1781 QComboBox
*comboboxFm
= this->findChild
<QComboBox
*>("fmsModePos" + QString::number(pos
+ 1));
1782 QString customStyleSheet
= "QComboBox:editable:!on{background: #feb103;}";
1785 QString flightModeText
= comboboxFm
->currentText();
1786 comboboxFm
->setStyleSheet("");
1787 for (uint8_t i
= 0; i
< FlightModeSettings::FLIGHTMODEPOSITION_NUMELEM
; i
++) {
1788 QLabel
*label
= this->findChild
<QLabel
*>("stab" + QString::number(i
+ 1) + "_label");
1789 QComboBox
*comboRoll
= this->findChild
<QComboBox
*>("fmsSsPos" + QString::number(i
+ 1) + "Roll");
1790 QComboBox
*comboPitch
= this->findChild
<QComboBox
*>("fmsSsPos" + QString::number(i
+ 1) + "Pitch");
1791 QComboBox
*comboYaw
= this->findChild
<QComboBox
*>("fmsSsPos" + QString::number(i
+ 1) + "Yaw");
1792 QComboBox
*comboThrust
= this->findChild
<QComboBox
*>("fmsSsPos" + QString::number(i
+ 1) + "Thrust");
1793 QComboBox
*comboboxFm2
= this->findChild
<QComboBox
*>("fmsModePos" + QString::number(i
+ 1));
1794 comboboxFm2
->setStyleSheet("");
1796 // Highlight current stabilization mode if any.
1797 if ((flightModeText
.contains("Stabilized", Qt::CaseInsensitive
)) && (flightModeText
.contains(QString::number(i
+ 1), Qt::CaseInsensitive
))) {
1798 label
->setStyleSheet("border-radius: 4px; border:3px solid #feb103;");
1799 comboRoll
->setStyleSheet(customStyleSheet
);
1800 comboPitch
->setStyleSheet(customStyleSheet
);
1801 comboYaw
->setStyleSheet(customStyleSheet
);
1802 comboThrust
->setStyleSheet(customStyleSheet
);
1804 label
->setStyleSheet("");
1805 comboRoll
->setStyleSheet("");
1806 comboPitch
->setStyleSheet("");
1807 comboYaw
->setStyleSheet("");
1808 comboThrust
->setStyleSheet("");
1809 if (!flightModeText
.contains("Stabilized", Qt::CaseInsensitive
)) {
1810 // Highlight PosHold, Return to Base, ... flightmodes
1811 comboboxFm
->setStyleSheet(customStyleSheet
);
1818 void setComboBoxItemEnabled(QComboBox
*combo
, int index
, bool enabled
= true)
1820 combo
->setItemData(index
, enabled
? QVariant(1 | 32) : QVariant(0), Qt::UserRole
- 1);
1823 void ConfigInputWidget::updatePositionSlider()
1825 ManualControlSettings::DataFields manualSettingsDataPriv
= manualSettingsObj
->getData();
1827 QWidget
*fmsModes
[] = {
1835 QWidget
*pidBanks
[] = {
1843 QWidget
*assistControls
[] = {
1844 ui
->assistControlPos1
,
1845 ui
->assistControlPos2
,
1846 ui
->assistControlPos3
,
1847 ui
->assistControlPos4
,
1848 ui
->assistControlPos5
,
1849 ui
->assistControlPos6
1852 for (quint32 i
= 0; i
< FlightModeSettings::FLIGHTMODEPOSITION_NUMELEM
; i
++) {
1853 bool enabled
= i
< manualSettingsDataPriv
.FlightModeNumber
;
1855 fmsModes
[i
]->setEnabled(enabled
);
1856 pidBanks
[i
]->setEnabled(enabled
);
1857 assistControls
[i
]->setEnabled(enabled
);
1858 setComboBoxItemEnabled(ui
->failsafeFlightMode
, i
, enabled
);
1859 setComboBoxItemEnabled(ui
->failsafeBatteryCriticalFlightMode
, i
, enabled
);
1860 setComboBoxItemEnabled(ui
->failsafeBatteryWarningFlightMode
, i
, enabled
);
1863 QString fmNumber
= QString().setNum(manualSettingsDataPriv
.FlightModeNumber
);
1865 foreach(QSlider
* sp
, findChildren
<QSlider
*>()) {
1866 // Find FlightMode slider and apply stylesheet
1867 if (sp
->objectName() == "channelNeutral") {
1870 "QSlider::groove:horizontal {border: 2px solid rgb(196, 196, 196); margin: 0px 23px 0px 23px; height: 12px; border-radius: 5px; "
1871 "border-image:url(:/configgadget/images/flightmode_bg" + fmNumber
+ ".png); }"
1872 "QSlider::add-page:horizontal { background: none; border: none; }"
1873 "QSlider::sub-page:horizontal { background: none; border: none; }"
1874 "QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, "
1875 "stop: 0 rgba(196, 196, 196, 180), stop: 0.45 rgba(196, 196, 196, 180), "
1876 "stop: 0.46 rgba(255,0,0,100), stop: 0.54 rgba(255,0,0,100), "
1877 "stop: 0.55 rgba(196, 196, 196, 180), stop: 1 rgba(196, 196, 196, 180)); "
1878 "width: 46px; height: 28px; margin: -6px -23px -6px -23px; border-radius: 5px; border: 1px solid #777; }");
1887 void ConfigInputWidget::updateConfigAlarmStatus()
1889 SystemAlarms
*systemAlarmsObj
= SystemAlarms::GetInstance(getObjectManager());
1890 SystemAlarms::DataFields systemAlarms
= systemAlarmsObj
->getData();
1892 QString message
= tr("Config OK");
1893 QString tooltipMessage
= tr("All fine, no config alarm!");
1894 QString bgColor
= "green";
1896 if (systemAlarms
.Alarm
[SystemAlarms::ALARM_SYSTEMCONFIGURATION
] > SystemAlarms::ALARM_WARNING
) {
1897 switch (systemAlarms
.ExtendedAlarmStatus
[SystemAlarms::EXTENDEDALARMSTATUS_SYSTEMCONFIGURATION
]) {
1898 case SystemAlarms::EXTENDEDALARMSTATUS_FLIGHTMODE
:
1899 message
= tr("Config error");
1900 tooltipMessage
= tr("There is something wrong in the current config,\nusually a Thrust mode or Assisted mode not supported.\n\n"
1901 "Tip: Reduce the Flight Mode Count to find the culprit.");
1905 ui
->configAlarmStatus
->setVisible(true);
1906 ui
->configAlarmStatus
->setStyleSheet(
1907 "QLabel { background-color: " + bgColor
+ ";"
1908 "color: rgb(255, 255, 255); border-radius: 5; margin:1px; font:bold; }");
1909 ui
->configAlarmStatus
->setText(message
);
1910 ui
->configAlarmStatus
->setToolTip(tooltipMessage
);
1913 void ConfigInputWidget::updateCalibration()
1915 manualCommandData
= manualCommandObj
->getData();
1916 for (uint i
= 0; i
< ManualControlSettings::CHANNELNUMBER_RSSI
; ++i
) {
1917 if ((!reverse
[i
] && manualSettingsData
.ChannelMin
[i
] > manualCommandData
.Channel
[i
]) ||
1918 (reverse
[i
] && manualSettingsData
.ChannelMin
[i
] < manualCommandData
.Channel
[i
])) {
1919 manualSettingsData
.ChannelMin
[i
] = manualCommandData
.Channel
[i
];
1921 if ((!reverse
[i
] && manualSettingsData
.ChannelMax
[i
] < manualCommandData
.Channel
[i
]) ||
1922 (reverse
[i
] && manualSettingsData
.ChannelMax
[i
] > manualCommandData
.Channel
[i
])) {
1923 manualSettingsData
.ChannelMax
[i
] = manualCommandData
.Channel
[i
];
1925 if ((i
== ManualControlSettings::CHANNELNUMBER_FLIGHTMODE
) || (i
== ManualControlSettings::CHANNELNUMBER_THROTTLE
)) {
1926 adjustSpecialNeutrals();
1928 // Set Accessory neutral to middle range
1929 if (i
>= ManualControlSettings::CHANNELNUMBER_ACCESSORY0
) {
1930 manualSettingsData
.ChannelNeutral
[i
] = manualSettingsData
.ChannelMin
[i
] + ((manualSettingsData
.ChannelMax
[i
] - manualSettingsData
.ChannelMin
[i
]) / 2);
1932 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
1936 UAVObjectUpdaterHelper updateHelper
;
1937 manualSettingsObj
->setData(manualSettingsData
, false);
1938 updateHelper
.doObjectAndWait(manualSettingsObj
);
1939 manualSettingsObj
->updated();
1942 void ConfigInputWidget::simpleCalibration(bool enable
)
1944 if (!isConnected()) {
1948 if (!outputConfigIsSafe
) {
1950 QMessageBox::warning(this, tr("Warning"), tr("There is something wrong in <b>Output</b> tab."
1951 "<p>Please fix the issue before starting the Manual Calibration.</p>"), QMessageBox::Ok
);
1952 ui
->runCalibration
->setChecked(false);
1958 ui
->configurationWizard
->setEnabled(false);
1959 ui
->applyButton
->setEnabled(false);
1960 ui
->saveButton
->setEnabled(false);
1961 ui
->runCalibration
->setText(tr("Stop Manual Calibration"));
1962 throttleError
= false;
1965 msgBox
.setText(tr("<p>Arming Settings are now set to 'Always Disarmed' for your safety.</p>"
1966 "<p>Be sure your receiver is powered with an external source and Transmitter is on.</p>"
1967 "<p align='center'><b>Stop Manual Calibration</b> when done</p>"));
1968 msgBox
.setDetailedText(tr("You will have to reconfigure the arming settings manually when the manual calibration is finished."));
1969 msgBox
.setStandardButtons(QMessageBox::Ok
);
1970 msgBox
.setDefaultButton(QMessageBox::Ok
);
1973 // Tell Output tab we freeze actuators soon
1974 emit
inputCalibrationStateChanged(true);
1976 manualCommandData
= manualCommandObj
->getData();
1978 manualSettingsData
= manualSettingsObj
->getData();
1979 flightModeSettingsData
= flightModeSettingsObj
->getData();
1980 flightModeSettingsData
.Arming
= FlightModeSettings::ARMING_ALWAYSDISARMED
;
1981 flightModeSettingsObj
->setData(flightModeSettingsData
);
1982 // Ignore last Rssi channel
1983 for (unsigned int i
= 0; i
< ManualControlSettings::CHANNELNUMBER_RSSI
; i
++) {
1984 reverse
[i
] = manualSettingsData
.ChannelMax
[i
] < manualSettingsData
.ChannelMin
[i
];
1985 manualSettingsData
.ChannelMin
[i
] = manualCommandData
.Channel
[i
];
1986 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
1987 manualSettingsData
.ChannelMax
[i
] = manualCommandData
.Channel
[i
];
1990 fastMdataSingle(manualCommandObj
, &manualControlMdata
);
1992 // Stash actuatorSettings
1993 actuatorSettingsData
= actuatorSettingsObj
->getData();
1994 memento
.actuatorSettingsData
= actuatorSettingsData
;
1996 // Disable all actuators
1997 resetActuatorSettings();
1999 connect(manualCommandObj
, SIGNAL(objectUnpacked(UAVObject
*)), this, SLOT(updateCalibration()));
2001 manualCommandData
= manualCommandObj
->getData();
2002 manualSettingsData
= manualSettingsObj
->getData();
2003 systemSettingsData
= systemSettingsObj
->getData();
2005 if ((systemSettingsData
.AirframeType
== SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR
) ||
2006 (systemSettingsData
.AirframeType
== SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL
) ||
2007 (systemSettingsData
.AirframeType
== SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE
) ||
2008 (systemSettingsData
.AirframeType
== SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEBOAT
) ||
2009 (systemSettingsData
.AirframeType
== SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIALBOAT
)) {
2010 QMessageBox::warning(this, tr("Ground Vehicle"),
2011 tr("<p>Please <b>center</b> throttle control and press OK when ready.</p>"));
2013 transmitterType
= ground
;
2014 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_THROTTLE
] =
2015 manualCommandData
.Channel
[ManualControlSettings::CHANNELNUMBER_THROTTLE
];
2018 restoreMdataSingle(manualCommandObj
, &manualControlMdata
);
2020 for (unsigned int i
= 0; i
< ManualControlSettings::CHANNELNUMBER_RSSI
; i
++) {
2021 if ((i
== ManualControlSettings::CHANNELNUMBER_FLIGHTMODE
) || (i
== ManualControlSettings::CHANNELNUMBER_THROTTLE
)) {
2022 adjustSpecialNeutrals();
2023 checkThrottleRange();
2025 // Set Accessory neutral to middle range
2026 if (i
>= ManualControlSettings::CHANNELNUMBER_ACCESSORY0
) {
2027 manualSettingsData
.ChannelNeutral
[i
] = manualSettingsData
.ChannelMin
[i
] + ((manualSettingsData
.ChannelMax
[i
] - manualSettingsData
.ChannelMin
[i
]) / 2);
2029 manualSettingsData
.ChannelNeutral
[i
] = manualCommandData
.Channel
[i
];
2033 manualSettingsObj
->setData(manualSettingsData
);
2035 // Load actuator settings back from beginning of manual calibration
2036 actuatorSettingsObj
->setData(memento
.actuatorSettingsData
);
2038 ui
->configurationWizard
->setEnabled(true);
2039 ui
->applyButton
->setEnabled(true);
2040 ui
->saveButton
->setEnabled(true);
2041 ui
->runCalibration
->setText(tr("Start Manual Calibration"));
2043 // Tell Output tab the calibration is ended
2044 emit
inputCalibrationStateChanged(false);
2046 disconnect(manualCommandObj
, SIGNAL(objectUnpacked(UAVObject
*)), this, SLOT(updateCalibration()));
2050 void ConfigInputWidget::adjustSpecialNeutrals()
2052 // FlightMode and Throttle need special neutral settings
2054 // Force flight mode neutral to middle
2055 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE
] =
2056 (manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_FLIGHTMODE
] +
2057 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_FLIGHTMODE
]) / 2;
2059 // A ground vehicle has a reversible motor, the center position of throttle is the neutral setting.
2060 // So do not have to set a special neutral value for it.
2061 if (transmitterType
== ground
) {
2065 // Force throttle to be near min, add 4% from total range to avoid arming issues
2066 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_THROTTLE
] =
2067 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_THROTTLE
] +
2068 ((manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_THROTTLE
] -
2069 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_THROTTLE
]) * 0.04);
2072 void ConfigInputWidget::checkThrottleRange()
2074 int throttleRange
= abs(manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_THROTTLE
] -
2075 manualSettingsData
.ChannelMin
[ManualControlSettings::CHANNELMIN_THROTTLE
]);
2077 if (!throttleError
&& (throttleRange
< 300)) {
2078 throttleError
= true;
2079 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
);
2081 // Set Throttle neutral to max value so Throttle can't be positive
2082 manualSettingsData
.ChannelNeutral
[ManualControlSettings::CHANNELNEUTRAL_THROTTLE
] =
2083 manualSettingsData
.ChannelMax
[ManualControlSettings::CHANNELMAX_THROTTLE
];
2087 bool ConfigInputWidget::shouldObjectBeSaved(UAVObject
*object
)
2089 // ManualControlCommand no need to be saved
2090 return dynamic_cast<ManualControlCommand
*>(object
) == NULL
;
2093 void ConfigInputWidget::resetChannelSettings()
2095 manualSettingsData
= manualSettingsObj
->getData();
2096 // Clear all channel data : Channel Type (PPM,PWM..) and Number, except for Rssi
2097 for (unsigned int channel
= 0; channel
< ManualControlSettings::CHANNELNUMBER_RSSI
; channel
++) {
2098 manualSettingsData
.ChannelGroups
[channel
] = ManualControlSettings::CHANNELGROUPS_NONE
;
2099 manualSettingsData
.ChannelNumber
[channel
] = CHANNEL_NUMBER_NONE
;
2100 UAVObjectUpdaterHelper updateHelper
;
2101 manualSettingsObj
->setData(manualSettingsData
, false);
2102 updateHelper
.doObjectAndWait(manualSettingsObj
);
2104 resetFlightModeSettings();
2107 void ConfigInputWidget::resetFlightModeSettings()
2109 // Reset FlightMode settings
2110 manualSettingsData
.FlightModeNumber
= DEFAULT_FLIGHT_MODE_NUMBER
;
2111 UAVObjectUpdaterHelper updateHelper
;
2112 manualSettingsObj
->setData(manualSettingsData
, false);
2113 updateHelper
.doObjectAndWait(manualSettingsObj
);
2114 for (uint8_t pos
= 0; pos
< FlightModeSettings::FLIGHTMODEPOSITION_NUMELEM
; pos
++) {
2115 flightModeSignalValue
[pos
] = 0;
2119 void ConfigInputWidget::resetActuatorSettings()
2121 actuatorSettingsData
= actuatorSettingsObj
->getData();
2123 UAVDataObject
*mixer
= dynamic_cast<UAVDataObject
*>(getObjectManager()->getObject(QString("MixerSettings")));
2128 // Clear all output data : Min, max, neutral at same value
2129 // min value for motors and neutral for all others (Reversable motor, servo)
2130 for (unsigned int output
= 0; output
< ActuatorSettings::CHANNELMAX_NUMELEM
; output
++) {
2131 QString mixerNumType
= QString("Mixer%1Type").arg(output
+ 1);
2132 UAVObjectField
*field
= mixer
->getField(mixerNumType
);
2136 mixerType
= field
->getValue().toString();
2138 if ((mixerType
== "Motor") || (mixerType
== "Disabled")) {
2139 // Apply current min setting to neutral/max values
2140 actuatorSettingsData
.ChannelMax
[output
] = actuatorSettingsData
.ChannelMin
[output
];
2141 actuatorSettingsData
.ChannelNeutral
[output
] = actuatorSettingsData
.ChannelMin
[output
];
2143 // Apply current neutral setting to min/max values
2144 actuatorSettingsData
.ChannelMax
[output
] = actuatorSettingsData
.ChannelNeutral
[output
];
2145 actuatorSettingsData
.ChannelMin
[output
] = actuatorSettingsData
.ChannelNeutral
[output
];
2147 UAVObjectUpdaterHelper updateHelper
;
2148 actuatorSettingsObj
->setData(actuatorSettingsData
, false);
2149 updateHelper
.doObjectAndWait(actuatorSettingsObj
);
2153 void ConfigInputWidget::updateReceiverActivityStatus()
2155 ReceiverActivity
*receiverActivity
= ReceiverActivity::GetInstance(getObjectManager());
2157 Q_ASSERT(receiverActivity
);
2159 FlightStatus
*flightStatus
= FlightStatus::GetInstance(getObjectManager());
2161 Q_ASSERT(flightStatus
);
2163 UAVObjectField
*activeGroup
= receiverActivity
->getField(QString("ActiveGroup"));
2164 Q_ASSERT(activeGroup
);
2166 UAVObjectField
*activeChannel
= receiverActivity
->getField(QString("ActiveChannel"));
2167 Q_ASSERT(activeChannel
);
2169 QString activeGroupText
= activeGroup
->getValue().toString();
2170 QString activeChannelText
= activeChannel
->getValue().toString();
2173 if (activeGroupText
!= "None") {
2174 ui
->receiverActivityStatus
->setText(tr("%1 input - Channel %2").arg(activeGroupText
).arg(activeChannelText
));
2175 ui
->receiverActivityStatus
->setStyleSheet("QLabel { background-color: green; color: rgb(255, 255, 255); \
2176 border: 1px solid grey; border-radius: 5; margin:1px; font:bold;}");
2178 bool armed
= (flightStatus
->getArmed() == FlightStatus::ARMED_ARMED
);
2179 QString receiverActivityText
= armed
? tr("Disabled (Armed)") : tr("No activity");
2180 ui
->receiverActivityStatus
->setText(receiverActivityText
);
2181 ui
->receiverActivityStatus
->setStyleSheet("QLabel { background-color: darkGreen; color: rgb(255, 255, 255); \
2182 border: 1px solid grey; border-radius: 5; margin:1px; font:bold;}");
2186 void ConfigInputWidget::failsafeBatteryWarningFlightModeChanged(int index
)
2188 HwSettings::DataFields hwSettingsData
= hwSettingsObj
->getData();
2189 bool batteryModuleEnabled
= (hwSettingsData
.OptionalModules
[HwSettings::OPTIONALMODULES_BATTERY
] == HwSettings::OPTIONALMODULES_ENABLED
);
2191 ui
->failsafeBatteryWarningFlightMode
->setEnabled(batteryModuleEnabled
&& index
!= -1);
2192 ui
->failsafeBatteryWarningFlightModeCb
->setChecked(index
!= -1);
2195 void ConfigInputWidget::failsafeBatteryCriticalFlightModeChanged(int index
)
2197 HwSettings::DataFields hwSettingsData
= hwSettingsObj
->getData();
2198 bool batteryModuleEnabled
= (hwSettingsData
.OptionalModules
[HwSettings::OPTIONALMODULES_BATTERY
] == HwSettings::OPTIONALMODULES_ENABLED
);
2200 ui
->failsafeBatteryCriticalFlightMode
->setEnabled(batteryModuleEnabled
&& index
!= -1);
2201 ui
->failsafeBatteryCriticalFlightModeCb
->setChecked(index
!= -1);
2204 void ConfigInputWidget::failsafeFlightModeChanged(int index
)
2206 ui
->failsafeFlightMode
->setEnabled(index
!= -1);
2207 ui
->failsafeFlightModeCb
->setChecked(index
!= -1);
2210 void ConfigInputWidget::failsafeFlightModeCbToggled(bool checked
)
2212 ui
->failsafeFlightMode
->setCurrentIndex(checked
? 0 : -1);
2215 void ConfigInputWidget::failsafeBatteryWarningFlightModeCbToggled(bool checked
)
2217 ui
->failsafeBatteryWarningFlightMode
->setCurrentIndex(checked
? 0 : -1);
2220 void ConfigInputWidget::failsafeBatteryCriticalFlightModeCbToggled(bool checked
)
2222 ui
->failsafeBatteryCriticalFlightMode
->setCurrentIndex(checked
? 0 : -1);
2225 void ConfigInputWidget::enableControlsChanged(bool enabled
)
2227 ui
->failsafeFlightMode
->setEnabled(enabled
&& ui
->failsafeFlightMode
->currentIndex() != -1);
2229 HwSettings::DataFields hwSettingsData
= hwSettingsObj
->getData();
2230 bool batteryModuleEnabled
= (hwSettingsData
.OptionalModules
[HwSettings::OPTIONALMODULES_BATTERY
] == HwSettings::OPTIONALMODULES_ENABLED
);
2231 ui
->failsafeBatteryWarningFlightMode
->setEnabled(batteryModuleEnabled
&& enabled
&& ui
->failsafeBatteryWarningFlightMode
->currentIndex() != -1);
2232 ui
->failsafeBatteryCriticalFlightMode
->setEnabled(batteryModuleEnabled
&& enabled
&& ui
->failsafeBatteryCriticalFlightMode
->currentIndex() != -1);
2233 ui
->failsafeBatteryWarningFlightModeCb
->setEnabled(enabled
&& batteryModuleEnabled
);
2234 ui
->failsafeBatteryCriticalFlightModeCb
->setEnabled(enabled
&& batteryModuleEnabled
);
2237 void ConfigInputWidget::setOutputConfigSafe(bool status
)
2239 outputConfigIsSafe
= status
;