2 ******************************************************************************
4 * @file setupwizard.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 Setup Wizard Plugin
11 * @brief A Wizard to make the initial setup easy for everyone.
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 "setupwizard.h"
30 #include "pages/opstartpage.h"
31 #include "pages/opendpage.h"
32 #include "pages/controllerpage.h"
33 #include "pages/vehiclepage.h"
34 #include "pages/multipage.h"
35 #include "pages/fixedwingpage.h"
36 #include "pages/airspeedpage.h"
37 #include "pages/gpspage.h"
38 #include "pages/helipage.h"
39 #include "pages/surfacepage.h"
40 #include "pages/inputpage.h"
41 #include "pages/escpage.h"
42 #include "pages/servopage.h"
43 #include "pages/biascalibrationpage.h"
44 #include "pages/esccalibrationpage.h"
45 #include "pages/summarypage.h"
46 #include "pages/savepage.h"
47 #include "pages/notyetimplementedpage.h"
48 #include "pages/outputcalibrationpage.h"
49 #include "pages/revocalibrationpage.h"
50 #include "pages/airframeinitialtuningpage.h"
51 #include "extensionsystem/pluginmanager.h"
52 #include "vehicleconfigurationhelper.h"
53 #include "actuatorsettings.h"
54 #include "pages/autoupdatepage.h"
55 #include "uploader/uploadergadgetfactory.h"
57 SetupWizard::SetupWizard(QWidget
*parent
) : QWizard(parent
), VehicleConfigurationSource(),
58 m_controllerType(CONTROLLER_UNKNOWN
),
59 m_vehicleType(VEHICLE_UNKNOWN
), m_inputType(INPUT_UNKNOWN
),
60 m_escType(ESC_UNKNOWN
), m_servoType(SERVO_UNKNOWN
),
61 m_airspeedType(AIRSPEED_DISABLED
), m_gpsType(GPS_DISABLED
),
62 m_vehicleTemplate(NULL
), m_calibrationPerformed(false),
63 m_restartNeeded(false), m_connectionManager(NULL
)
65 setWindowTitle(tr("Setup Wizard"));
66 setOption(QWizard::IndependentPages
, false);
67 for (quint16 i
= 0; i
< ActuatorSettings::CHANNELMAX_NUMELEM
; i
++) {
68 m_actuatorSettings
<< actuatorChannelSettings();
70 setWizardStyle(QWizard::ModernStyle
);
71 setMinimumSize(780, 560);
76 SetupWizard::~SetupWizard()
78 if (m_vehicleTemplate
!= NULL
) {
79 delete m_vehicleTemplate
;
80 m_vehicleTemplate
= NULL
;
84 int SetupWizard::nextId() const
86 switch (currentId()) {
88 if (canAutoUpdate()) {
91 return PAGE_CONTROLLER
;
94 return PAGE_CONTROLLER
;
98 switch (getControllerType()) {
100 case CONTROLLER_CC3D
:
101 case CONTROLLER_REVO
:
102 case CONTROLLER_SPARKY2
:
103 case CONTROLLER_DISCOVERYF4
:
106 case CONTROLLER_NANO
:
107 if (isRestartNeeded()) {
112 case CONTROLLER_OPLINK
:
114 return PAGE_NOTYETIMPLEMENTED
;
119 switch (getVehicleType()) {
123 case VEHICLE_FIXEDWING
:
124 return PAGE_FIXEDWING
;
129 case VEHICLE_SURFACE
:
133 return PAGE_NOTYETIMPLEMENTED
;
141 if ((getVehicleSubType() == GROUNDVEHICLE_DIFFERENTIAL
) ||
142 (getVehicleSubType() == GROUNDVEHICLE_DIFFERENTIAL_BOAT
)) {
149 if (isRestartNeeded()) {
150 saveHardwareSettings();
153 return PAGE_VEHICLES
;
156 if (getVehicleSubType() == MULTI_ROTOR_TRI_Y
) {
159 switch (getControllerType()) {
160 case CONTROLLER_REVO
:
161 case CONTROLLER_NANO
:
162 case CONTROLLER_SPARKY2
:
172 switch (getControllerType()) {
173 case CONTROLLER_REVO
:
174 case CONTROLLER_NANO
:
175 case CONTROLLER_SPARKY2
:
183 case PAGE_BIAS_CALIBRATION
:
184 if ((getVehicleType() == VEHICLE_MULTI
) &&
185 (getEscType() != ESC_DSHOT150
) &&
186 (getEscType() != ESC_DSHOT600
) &&
187 (getEscType() != ESC_DSHOT1200
)) {
188 return PAGE_ESC_CALIBRATION
;
190 return PAGE_OUTPUT_CALIBRATION
;
193 case PAGE_ESC_CALIBRATION
:
194 return PAGE_OUTPUT_CALIBRATION
;
196 case PAGE_OUTPUT_CALIBRATION
:
197 return PAGE_AIRFRAME_INITIAL_TUNING
;
199 case PAGE_AIRFRAME_INITIAL_TUNING
:
203 switch (getVehicleType()) {
204 case VEHICLE_FIXEDWING
:
205 if (getGpsType() != GPS_DISABLED
) {
206 return PAGE_AIRSPEED
;
219 switch (getControllerType()) {
221 case CONTROLLER_CC3D
:
222 case CONTROLLER_REVO
:
223 case CONTROLLER_NANO
:
224 case CONTROLLER_SPARKY2
:
225 case CONTROLLER_DISCOVERYF4
:
226 switch (getVehicleType()) {
227 case VEHICLE_FIXEDWING
:
228 return PAGE_OUTPUT_CALIBRATION
;
231 return PAGE_BIAS_CALIBRATION
;
234 return PAGE_NOTYETIMPLEMENTED
;
240 case PAGE_NOTYETIMPLEMENTED
:
248 QString
SetupWizard::getSummaryText()
250 QString summary
= "";
252 summary
.append("<b>").append(tr("Controller type: ")).append("</b>");
253 switch (getControllerType()) {
255 summary
.append(tr("OpenPilot CopterControl"));
257 case CONTROLLER_CC3D
:
258 summary
.append(tr("OpenPilot CopterControl 3D"));
260 case CONTROLLER_REVO
:
261 summary
.append(tr("OpenPilot Revolution"));
263 case CONTROLLER_NANO
:
264 summary
.append(tr("OpenPilot Nano"));
266 case CONTROLLER_SPARKY2
:
267 summary
.append(tr("TauLabs Sparky 2.0"));
269 case CONTROLLER_OPLINK
:
270 summary
.append(tr("OpenPilot OPLink Radio Modem"));
272 case CONTROLLER_DISCOVERYF4
:
273 summary
.append(tr("OpenPilot DiscoveryF4 Development Board"));
276 summary
.append(tr("Unknown"));
280 summary
.append("<br>");
281 summary
.append("<b>").append(tr("Vehicle type: ")).append("</b>");
282 switch (getVehicleType()) {
284 summary
.append(tr("Multirotor"));
286 summary
.append("<br>");
287 summary
.append("<b>").append(tr("Vehicle sub type: ")).append("</b>");
288 switch (getVehicleSubType()) {
289 case SetupWizard::MULTI_ROTOR_TRI_Y
:
290 summary
.append(tr("Tricopter"));
292 case SetupWizard::MULTI_ROTOR_QUAD_X
:
293 summary
.append(tr("Quadcopter X"));
295 case SetupWizard::MULTI_ROTOR_QUAD_PLUS
:
296 summary
.append(tr("Quadcopter +"));
298 case SetupWizard::MULTI_ROTOR_HEXA
:
299 summary
.append(tr("Hexacopter"));
301 case SetupWizard::MULTI_ROTOR_HEXA_COAX_Y
:
302 summary
.append(tr("Hexacopter Coax (Y6)"));
304 case SetupWizard::MULTI_ROTOR_HEXA_H
:
305 summary
.append(tr("Hexacopter H"));
307 case SetupWizard::MULTI_ROTOR_HEXA_X
:
308 summary
.append(tr("Hexacopter X"));
310 case SetupWizard::MULTI_ROTOR_OCTO
:
311 summary
.append(tr("Octocopter"));
313 case SetupWizard::MULTI_ROTOR_OCTO_COAX_X
:
314 summary
.append(tr("Octocopter Coax X"));
316 case SetupWizard::MULTI_ROTOR_OCTO_COAX_PLUS
:
317 summary
.append(tr("Octocopter Coax +"));
319 case SetupWizard::MULTI_ROTOR_OCTO_V
:
320 summary
.append(tr("Octocopter V"));
323 summary
.append(tr("Unknown"));
328 case VEHICLE_FIXEDWING
:
329 summary
.append(tr("Fixed wing"));
331 summary
.append("<br>");
332 summary
.append("<b>").append(tr("Vehicle sub type: ")).append("</b>");
333 switch (getVehicleSubType()) {
334 case SetupWizard::FIXED_WING_DUAL_AILERON
:
335 summary
.append(tr("Dual Aileron"));
337 case SetupWizard::FIXED_WING_AILERON
:
338 summary
.append(tr("Aileron"));
340 case SetupWizard::FIXED_WING_ELEVON
:
341 summary
.append(tr("Elevon"));
344 summary
.append(tr("Unknown"));
350 summary
.append(tr("Helicopter"));
352 case VEHICLE_SURFACE
:
353 summary
.append(tr("Surface vehicle"));
355 summary
.append("<br>");
356 summary
.append("<b>").append(tr("Vehicle sub type: ")).append("</b>");
357 switch (getVehicleSubType()) {
358 case SetupWizard::GROUNDVEHICLE_CAR
:
359 summary
.append(tr("Car"));
361 case SetupWizard::GROUNDVEHICLE_DIFFERENTIAL
:
362 summary
.append(tr("Tank"));
364 case SetupWizard::GROUNDVEHICLE_MOTORCYCLE
:
365 summary
.append(tr("Motorcycle"));
367 case SetupWizard::GROUNDVEHICLE_BOAT
:
368 summary
.append(tr("Boat"));
370 case SetupWizard::GROUNDVEHICLE_DIFFERENTIAL_BOAT
:
371 summary
.append(tr("Boat differential"));
374 summary
.append(tr("Unknown"));
380 summary
.append(tr("Unknown"));
383 summary
.append("<br>");
384 summary
.append("<b>").append(tr("Input type: ")).append("</b>");
385 switch (getInputType()) {
387 summary
.append(tr("PWM (One cable per channel)"));
390 summary
.append(tr("PPM (One cable for all channels)"));
393 summary
.append(tr("Futaba S.Bus"));
396 summary
.append(tr("Spektrum Satellite"));
399 summary
.append(tr("Multiplex SRXL"));
401 case INPUT_HOTT_SUMD
:
402 summary
.append(tr("Graupner HoTT"));
405 summary
.append(tr("Jeti EX.Bus"));
408 summary
.append(tr("FlySky IBus"));
411 summary
.append(tr("Unknown"));
414 summary
.append("<br>");
415 summary
.append("<b>").append(tr("Speed Controller (ESC) type: ")).append("</b>");
416 switch (getEscType()) {
418 summary
.append(tr("Standard ESC (%1 Hz)").arg(VehicleConfigurationHelper::LEGACY_ESC_FREQUENCY
));
420 case ESC_STANDARD300
:
421 summary
.append(tr("Standard ESC (%1 Hz)").arg(VehicleConfigurationHelper::LEGACY_MULTI_ESC_FREQUENCY
));
424 summary
.append(tr("Rapid ESC (%1 Hz)").arg(VehicleConfigurationHelper::RAPID_ESC_FREQUENCY
));
427 summary
.append(tr("Synched ESC"));
430 summary
.append(tr("Oneshot125 ESC"));
433 summary
.append(tr("Oneshot42 ESC"));
436 summary
.append(tr("Multishot ESC"));
439 summary
.append(tr("Dshot150 ESC"));
442 summary
.append(tr("Dshot600 ESC"));
445 summary
.append(tr("Dshot1200 ESC"));
448 summary
.append(tr("Unknown"));
451 // If Tricopter show tail servo speed
452 if (getVehicleSubType() == MULTI_ROTOR_TRI_Y
|| getVehicleType() == VEHICLE_FIXEDWING
453 || getVehicleSubType() == GROUNDVEHICLE_MOTORCYCLE
|| getVehicleSubType() == GROUNDVEHICLE_CAR
454 || getVehicleSubType() == GROUNDVEHICLE_BOAT
) {
455 summary
.append("<br>");
456 summary
.append("<b>").append(tr("Servo type: ")).append("</b>");
457 switch (getServoType()) {
459 summary
.append(tr("Analog Servos (50 Hz)"));
462 summary
.append(tr("Digital Servos (333 Hz)"));
465 summary
.append(tr("Unknown"));
470 if (getControllerType() == CONTROLLER_REVO
|| getControllerType() == CONTROLLER_NANO
|| getControllerType() == CONTROLLER_SPARKY2
) {
471 summary
.append("<br>");
472 summary
.append("<b>").append(tr("GPS type: ")).append("</b>");
473 switch (getGpsType()) {
475 summary
.append(tr("OpenPilot Platinum"));
478 summary
.append(tr("Naza GPS"));
480 case GPS_UBX_FLEXI_I2CMAG
:
481 summary
.append(tr("Generic UBLOX + I2C Magnetometer"));
484 summary
.append(tr("OpenPilot v8 or Generic UBLOX GPS"));
487 summary
.append(tr("Generic NMEA GPS"));
490 summary
.append(tr("None"));
494 // Show Airspeed sensor type
495 if ((getControllerType() == CONTROLLER_REVO
|| getControllerType() == CONTROLLER_NANO
|| getControllerType() == CONTROLLER_SPARKY2
)
496 && getVehicleType() == VEHICLE_FIXEDWING
) {
497 summary
.append("<br>");
498 summary
.append("<b>").append(tr("Airspeed Sensor: ")).append("</b>");
499 switch (getAirspeedType()) {
500 case AIRSPEED_ESTIMATE
:
501 summary
.append(tr("Software Estimated"));
503 case AIRSPEED_EAGLETREE
:
504 summary
.append(tr("EagleTree on Flexi-Port"));
506 case AIRSPEED_MS4525
:
507 summary
.append(tr("MS4525 based on Flexi-Port"));
510 summary
.append(tr("Unknown"));
516 void SetupWizard::createPages()
518 setPage(PAGE_START
, new OPStartPage(this));
519 setPage(PAGE_UPDATE
, new AutoUpdatePage(this));
520 setPage(PAGE_CONTROLLER
, new ControllerPage(this));
521 setPage(PAGE_VEHICLES
, new VehiclePage(this));
522 setPage(PAGE_MULTI
, new MultiPage(this));
523 setPage(PAGE_FIXEDWING
, new FixedWingPage(this));
524 setPage(PAGE_AIRSPEED
, new AirSpeedPage(this));
525 setPage(PAGE_GPS
, new GpsPage(this));
526 setPage(PAGE_HELI
, new HeliPage(this));
527 setPage(PAGE_SURFACE
, new SurfacePage(this));
528 setPage(PAGE_INPUT
, new InputPage(this));
529 setPage(PAGE_ESC
, new EscPage(this));
530 setPage(PAGE_SERVO
, new ServoPage(this));
531 setPage(PAGE_BIAS_CALIBRATION
, new BiasCalibrationPage(this));
532 setPage(PAGE_ESC_CALIBRATION
, new EscCalibrationPage(this));
533 setPage(PAGE_OUTPUT_CALIBRATION
, new OutputCalibrationPage(this));
534 setPage(PAGE_SUMMARY
, new SummaryPage(this));
535 setPage(PAGE_SAVE
, new SavePage(this));
536 setPage(PAGE_NOTYETIMPLEMENTED
, new NotYetImplementedPage(this));
537 setPage(PAGE_AIRFRAME_INITIAL_TUNING
, new AirframeInitialTuningPage(this));
538 setPage(PAGE_END
, new OPEndPage(this));
540 setStartId(PAGE_START
);
542 connect(button(QWizard::CustomButton1
), SIGNAL(clicked()), this, SLOT(customBackClicked()));
543 setButtonText(QWizard::CustomButton1
, buttonText(QWizard::BackButton
));
544 QList
<QWizard::WizardButton
> button_layout
;
545 button_layout
<< QWizard::Stretch
<< QWizard::CustomButton1
<< QWizard::NextButton
<< QWizard::CancelButton
<< QWizard::FinishButton
;
546 setButtonLayout(button_layout
);
547 connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(pageChanged(int)));
550 void SetupWizard::customBackClicked()
552 if (currentId() == PAGE_OUTPUT_CALIBRATION
) {
553 static_cast<OutputCalibrationPage
*>(currentPage())->customBackClicked();
556 if (currentId() == PAGE_OUTPUT_CALIBRATION
) {
557 static_cast<OutputCalibrationPage
*>(currentPage())->customBackClicked();
562 void SetupWizard::pageChanged(int currId
)
564 button(QWizard::CustomButton1
)->setVisible(currId
!= PAGE_START
);
565 button(QWizard::CancelButton
)->setVisible(currId
!= PAGE_END
);
568 void SetupWizard::reboot() const
570 SetupWizard
*wiz
= const_cast<SetupWizard
*>(this);
572 wiz
->setWindowFlags(wiz
->windowFlags() & ~Qt::WindowStaysOnTopHint
);
574 ExtensionSystem::PluginManager
*pm
= ExtensionSystem::PluginManager::instance();
576 UploaderGadgetFactory
*uploader
= pm
->getObject
<UploaderGadgetFactory
>();
580 wiz
->setRestartNeeded(false);
581 wiz
->setWindowFlags(wiz
->windowFlags() | Qt::WindowStaysOnTopHint
);
585 bool SetupWizard::saveHardwareSettings() const
587 VehicleConfigurationHelper
helper(const_cast<SetupWizard
*>(this));
589 return helper
.setupHardwareSettings();
592 bool SetupWizard::canAutoUpdate() const
594 ExtensionSystem::PluginManager
*pm
= ExtensionSystem::PluginManager::instance();
597 UploaderGadgetFactory
*uploader
= pm
->getObject
<UploaderGadgetFactory
>();
599 return uploader
->isAutoUpdateCapable();