Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / ground / gcs / src / plugins / setupwizard / setupwizard.cpp
blob5a8f467288daf805a5c8c47f1975dc2e25e4b516
1 /**
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
8 * @{
9 * @addtogroup Setup Wizard Plugin
10 * @{
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
22 * for more details.
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);
72 resize(780, 560);
73 createPages();
76 SetupWizard::~SetupWizard()
78 if (m_vehicleTemplate != NULL) {
79 delete m_vehicleTemplate;
80 m_vehicleTemplate = NULL;
84 int SetupWizard::nextId() const
86 switch (currentId()) {
87 case PAGE_START:
88 if (canAutoUpdate()) {
89 return PAGE_UPDATE;
90 } else {
91 return PAGE_CONTROLLER;
93 case PAGE_UPDATE:
94 return PAGE_CONTROLLER;
96 case PAGE_CONTROLLER:
98 switch (getControllerType()) {
99 case CONTROLLER_CC:
100 case CONTROLLER_CC3D:
101 case CONTROLLER_REVO:
102 case CONTROLLER_SPARKY2:
103 case CONTROLLER_DISCOVERYF4:
104 return PAGE_INPUT;
106 case CONTROLLER_NANO:
107 if (isRestartNeeded()) {
108 reboot();
110 return PAGE_INPUT;
112 case CONTROLLER_OPLINK:
113 default:
114 return PAGE_NOTYETIMPLEMENTED;
117 case PAGE_VEHICLES:
119 switch (getVehicleType()) {
120 case VEHICLE_MULTI:
121 return PAGE_MULTI;
123 case VEHICLE_FIXEDWING:
124 return PAGE_FIXEDWING;
126 case VEHICLE_HELI:
127 return PAGE_HELI;
129 case VEHICLE_SURFACE:
130 return PAGE_SURFACE;
132 default:
133 return PAGE_NOTYETIMPLEMENTED;
136 case PAGE_MULTI:
137 return PAGE_ESC;
139 case PAGE_FIXEDWING:
140 case PAGE_SURFACE:
141 if ((getVehicleSubType() == GROUNDVEHICLE_DIFFERENTIAL) ||
142 (getVehicleSubType() == GROUNDVEHICLE_DIFFERENTIAL_BOAT)) {
143 return PAGE_ESC;
144 } else {
145 return PAGE_SERVO;
148 case PAGE_INPUT:
149 if (isRestartNeeded()) {
150 saveHardwareSettings();
151 reboot();
153 return PAGE_VEHICLES;
155 case PAGE_ESC:
156 if (getVehicleSubType() == MULTI_ROTOR_TRI_Y) {
157 return PAGE_SERVO;
158 } else {
159 switch (getControllerType()) {
160 case CONTROLLER_REVO:
161 case CONTROLLER_NANO:
162 case CONTROLLER_SPARKY2:
163 return PAGE_GPS;
165 default:
166 return PAGE_SUMMARY;
170 case PAGE_SERVO:
172 switch (getControllerType()) {
173 case CONTROLLER_REVO:
174 case CONTROLLER_NANO:
175 case CONTROLLER_SPARKY2:
176 return PAGE_GPS;
178 default:
179 return PAGE_SUMMARY;
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;
189 } else {
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:
200 return PAGE_SAVE;
202 case PAGE_GPS:
203 switch (getVehicleType()) {
204 case VEHICLE_FIXEDWING:
205 if (getGpsType() != GPS_DISABLED) {
206 return PAGE_AIRSPEED;
207 } else {
208 return PAGE_SUMMARY;
210 default:
211 return PAGE_SUMMARY;
214 case PAGE_AIRSPEED:
215 return PAGE_SUMMARY;
217 case PAGE_SUMMARY:
219 switch (getControllerType()) {
220 case CONTROLLER_CC:
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;
230 default:
231 return PAGE_BIAS_CALIBRATION;
233 default:
234 return PAGE_NOTYETIMPLEMENTED;
237 case PAGE_SAVE:
238 return PAGE_END;
240 case PAGE_NOTYETIMPLEMENTED:
241 return PAGE_END;
243 default:
244 return -1;
248 QString SetupWizard::getSummaryText()
250 QString summary = "";
252 summary.append("<b>").append(tr("Controller type: ")).append("</b>");
253 switch (getControllerType()) {
254 case CONTROLLER_CC:
255 summary.append(tr("OpenPilot CopterControl"));
256 break;
257 case CONTROLLER_CC3D:
258 summary.append(tr("OpenPilot CopterControl 3D"));
259 break;
260 case CONTROLLER_REVO:
261 summary.append(tr("OpenPilot Revolution"));
262 break;
263 case CONTROLLER_NANO:
264 summary.append(tr("OpenPilot Nano"));
265 break;
266 case CONTROLLER_SPARKY2:
267 summary.append(tr("TauLabs Sparky 2.0"));
268 break;
269 case CONTROLLER_OPLINK:
270 summary.append(tr("OpenPilot OPLink Radio Modem"));
271 break;
272 case CONTROLLER_DISCOVERYF4:
273 summary.append(tr("OpenPilot DiscoveryF4 Development Board"));
274 break;
275 default:
276 summary.append(tr("Unknown"));
277 break;
280 summary.append("<br>");
281 summary.append("<b>").append(tr("Vehicle type: ")).append("</b>");
282 switch (getVehicleType()) {
283 case VEHICLE_MULTI:
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"));
291 break;
292 case SetupWizard::MULTI_ROTOR_QUAD_X:
293 summary.append(tr("Quadcopter X"));
294 break;
295 case SetupWizard::MULTI_ROTOR_QUAD_PLUS:
296 summary.append(tr("Quadcopter +"));
297 break;
298 case SetupWizard::MULTI_ROTOR_HEXA:
299 summary.append(tr("Hexacopter"));
300 break;
301 case SetupWizard::MULTI_ROTOR_HEXA_COAX_Y:
302 summary.append(tr("Hexacopter Coax (Y6)"));
303 break;
304 case SetupWizard::MULTI_ROTOR_HEXA_H:
305 summary.append(tr("Hexacopter H"));
306 break;
307 case SetupWizard::MULTI_ROTOR_HEXA_X:
308 summary.append(tr("Hexacopter X"));
309 break;
310 case SetupWizard::MULTI_ROTOR_OCTO:
311 summary.append(tr("Octocopter"));
312 break;
313 case SetupWizard::MULTI_ROTOR_OCTO_COAX_X:
314 summary.append(tr("Octocopter Coax X"));
315 break;
316 case SetupWizard::MULTI_ROTOR_OCTO_COAX_PLUS:
317 summary.append(tr("Octocopter Coax +"));
318 break;
319 case SetupWizard::MULTI_ROTOR_OCTO_V:
320 summary.append(tr("Octocopter V"));
321 break;
322 default:
323 summary.append(tr("Unknown"));
324 break;
327 break;
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"));
336 break;
337 case SetupWizard::FIXED_WING_AILERON:
338 summary.append(tr("Aileron"));
339 break;
340 case SetupWizard::FIXED_WING_ELEVON:
341 summary.append(tr("Elevon"));
342 break;
343 default:
344 summary.append(tr("Unknown"));
345 break;
348 break;
349 case VEHICLE_HELI:
350 summary.append(tr("Helicopter"));
351 break;
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"));
360 break;
361 case SetupWizard::GROUNDVEHICLE_DIFFERENTIAL:
362 summary.append(tr("Tank"));
363 break;
364 case SetupWizard::GROUNDVEHICLE_MOTORCYCLE:
365 summary.append(tr("Motorcycle"));
366 break;
367 case SetupWizard::GROUNDVEHICLE_BOAT:
368 summary.append(tr("Boat"));
369 break;
370 case SetupWizard::GROUNDVEHICLE_DIFFERENTIAL_BOAT:
371 summary.append(tr("Boat differential"));
372 break;
373 default:
374 summary.append(tr("Unknown"));
375 break;
378 break;
379 default:
380 summary.append(tr("Unknown"));
383 summary.append("<br>");
384 summary.append("<b>").append(tr("Input type: ")).append("</b>");
385 switch (getInputType()) {
386 case INPUT_PWM:
387 summary.append(tr("PWM (One cable per channel)"));
388 break;
389 case INPUT_PPM:
390 summary.append(tr("PPM (One cable for all channels)"));
391 break;
392 case INPUT_SBUS:
393 summary.append(tr("Futaba S.Bus"));
394 break;
395 case INPUT_DSM:
396 summary.append(tr("Spektrum Satellite"));
397 break;
398 case INPUT_SRXL:
399 summary.append(tr("Multiplex SRXL"));
400 break;
401 case INPUT_HOTT_SUMD:
402 summary.append(tr("Graupner HoTT"));
403 break;
404 case INPUT_EXBUS:
405 summary.append(tr("Jeti EX.Bus"));
406 break;
407 case INPUT_IBUS:
408 summary.append(tr("FlySky IBus"));
409 break;
410 default:
411 summary.append(tr("Unknown"));
414 summary.append("<br>");
415 summary.append("<b>").append(tr("Speed Controller (ESC) type: ")).append("</b>");
416 switch (getEscType()) {
417 case ESC_STANDARD:
418 summary.append(tr("Standard ESC (%1 Hz)").arg(VehicleConfigurationHelper::LEGACY_ESC_FREQUENCY));
419 break;
420 case ESC_STANDARD300:
421 summary.append(tr("Standard ESC (%1 Hz)").arg(VehicleConfigurationHelper::LEGACY_MULTI_ESC_FREQUENCY));
422 break;
423 case ESC_RAPID:
424 summary.append(tr("Rapid ESC (%1 Hz)").arg(VehicleConfigurationHelper::RAPID_ESC_FREQUENCY));
425 break;
426 case ESC_SYNCHED:
427 summary.append(tr("Synched ESC"));
428 break;
429 case ESC_ONESHOT125:
430 summary.append(tr("Oneshot125 ESC"));
431 break;
432 case ESC_ONESHOT42:
433 summary.append(tr("Oneshot42 ESC"));
434 break;
435 case ESC_MULTISHOT:
436 summary.append(tr("Multishot ESC"));
437 break;
438 case ESC_DSHOT150:
439 summary.append(tr("Dshot150 ESC"));
440 break;
441 case ESC_DSHOT600:
442 summary.append(tr("Dshot600 ESC"));
443 break;
444 case ESC_DSHOT1200:
445 summary.append(tr("Dshot1200 ESC"));
446 break;
447 default:
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()) {
458 case SERVO_ANALOG:
459 summary.append(tr("Analog Servos (50 Hz)"));
460 break;
461 case SERVO_DIGITAL:
462 summary.append(tr("Digital Servos (333 Hz)"));
463 break;
464 default:
465 summary.append(tr("Unknown"));
469 // Show GPS Type
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()) {
474 case GPS_PLATINUM:
475 summary.append(tr("OpenPilot Platinum"));
476 break;
477 case GPS_NAZA:
478 summary.append(tr("Naza GPS"));
479 break;
480 case GPS_UBX_FLEXI_I2CMAG:
481 summary.append(tr("Generic UBLOX + I2C Magnetometer"));
482 break;
483 case GPS_UBX:
484 summary.append(tr("OpenPilot v8 or Generic UBLOX GPS"));
485 break;
486 case GPS_NMEA:
487 summary.append(tr("Generic NMEA GPS"));
488 break;
489 default:
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"));
502 break;
503 case AIRSPEED_EAGLETREE:
504 summary.append(tr("EagleTree on Flexi-Port"));
505 break;
506 case AIRSPEED_MS4525:
507 summary.append(tr("MS4525 based on Flexi-Port"));
508 break;
509 default:
510 summary.append(tr("Unknown"));
513 return summary;
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();
554 } else {
555 back();
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();
575 Q_ASSERT(pm);
576 UploaderGadgetFactory *uploader = pm->getObject<UploaderGadgetFactory>();
577 Q_ASSERT(uploader);
578 uploader->reboot();
580 wiz->setRestartNeeded(false);
581 wiz->setWindowFlags(wiz->windowFlags() | Qt::WindowStaysOnTopHint);
582 wiz->show();
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();
596 Q_ASSERT(pm);
597 UploaderGadgetFactory *uploader = pm->getObject<UploaderGadgetFactory>();
598 Q_ASSERT(uploader);
599 return uploader->isAutoUpdateCapable();