dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
configvehicletypewidget.cpp
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  */
29 
30 #include <QDebug>
31 #include <QStringList>
32 #include <QTimer>
33 #include <QWidget>
34 #include <QTextEdit>
35 #include <QVBoxLayout>
36 #include <QPushButton>
37 #include <math.h>
38 #include <QDesktopServices>
39 #include <QUrl>
40 #include <QEventLoop>
41 #include <QMessageBox>
42 
43 #include "systemsettings.h"
44 #include "mixersettings.h"
45 #include "actuatorcommand.h"
46 #include "actuatorsettings.h"
47 #include "vehicletrim.h"
48 
54  : QItemDelegate(parent)
55 {
56 }
57 
58 QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /* option */,
59  const QModelIndex & /* index */) const
60 {
61  QSpinBox *editor = new QSpinBox(parent);
62  editor->setMinimum(-VehicleConfig::mixerRange);
63  editor->setMaximum(VehicleConfig::mixerRange);
64 
65  return editor;
66 }
67 
68 void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
69 {
70  int value = index.model()->data(index, Qt::EditRole).toInt();
71 
72  QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
73  spinBox->setValue(value);
74 }
75 
76 void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
77  const QModelIndex &index) const
78 {
79  QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
80  spinBox->interpretText();
81  int value = spinBox->value();
82 
83  model->setData(index, value, Qt::EditRole);
84 }
85 
86 void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
87  const QModelIndex & /* index */) const
88 {
89  editor->setGeometry(option.rect);
90 }
91 
92 /**********************************************************************************/
93 
98  : ConfigTaskWidget(parent)
99 {
100  m_aircraft = new Ui_AircraftWidget();
101  m_aircraft->setupUi(this);
102 
103  addUAVObject("SystemSettings");
104  addUAVObject("MixerSettings");
105 
106  addUAVObjectToWidgetRelation("MixerSettings", "Curve2Source",
107  m_aircraft->customThrottle2Curve->getCBCurveSource());
108 
109  // Generate lists of mixerTypeNames, mixerVectorNames, channelNames
110  channelNames << "None";
111  for (int i = 0; i < (int)ActuatorSettings::CHANNELMIN_NUMELEM; i++) {
112 
113  mixerTypes << QString("Mixer%1Type").arg(i + 1);
114  mixerVectors << QString("Mixer%1Vector").arg(i + 1);
115  channelNames << QString("Channel%1").arg(i + 1);
116  }
117 
118  // Set up vehicle type combobox
119  m_aircraft->aircraftType->addItem("Fixed Wing", AIRFRAME_FIXED_WING);
120  m_aircraft->aircraftType->addItem("Multirotor", AIRFRAME_MULTIROTOR);
121  m_aircraft->aircraftType->addItem("Helicopter", AIRFRAME_HELICOPTER);
122  m_aircraft->aircraftType->addItem("Ground", AIRFRAME_GROUND);
123  m_aircraft->aircraftType->addItem("Custom", AIRFRAME_CUSTOM);
124 
125  m_aircraft->aircraftType->setCurrentIndex(1); // Set default vehicle to MultiRotor
126  m_aircraft->airframesWidget->setCurrentIndex(1); // Force the tab index to match
127 
128  // Setup fixed-wing combobox
129  m_aircraft->fixedWingType->addItem("Elevator aileron rudder",
130  SystemSettings::AIRFRAMETYPE_FIXEDWING);
131  m_aircraft->fixedWingType->addItem("Elevon", SystemSettings::AIRFRAMETYPE_FIXEDWINGELEVON);
132  m_aircraft->fixedWingType->addItem("Vtail", SystemSettings::AIRFRAMETYPE_FIXEDWINGVTAIL);
133  m_aircraft->fixedWingType->setCurrentIndex(0); // Set default model to "Elevator aileron rudder"
134 
135  // Setup ground vehicle combobox
136  m_aircraft->groundVehicleType->addItem("Turnable (car)",
137  SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR);
138  m_aircraft->groundVehicleType->addItem("Differential (tank)",
139  SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL);
140  m_aircraft->groundVehicleType->addItem("Motorcycle",
141  SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE);
142  m_aircraft->groundVehicleType->setCurrentIndex(0); // Set default model to "Turnable (car)"
143 
144  // Setup multirotor combobox
145  m_aircraft->multirotorFrameType->addItem("Tricopter Y", SystemSettings::AIRFRAMETYPE_TRI);
146  m_aircraft->multirotorFrameType->addItem("Quad X", SystemSettings::AIRFRAMETYPE_QUADX);
147  m_aircraft->multirotorFrameType->addItem("Quad +", SystemSettings::AIRFRAMETYPE_QUADP);
148  m_aircraft->multirotorFrameType->addItem("Hexacopter", SystemSettings::AIRFRAMETYPE_HEXA);
149  m_aircraft->multirotorFrameType->addItem("Hexacopter X", SystemSettings::AIRFRAMETYPE_HEXAX);
150  m_aircraft->multirotorFrameType->addItem("Hexacopter Y6",
151  SystemSettings::AIRFRAMETYPE_HEXACOAX);
152  m_aircraft->multirotorFrameType->addItem("Octocopter", SystemSettings::AIRFRAMETYPE_OCTO);
153  m_aircraft->multirotorFrameType->addItem("Octocopter V", SystemSettings::AIRFRAMETYPE_OCTOV);
154  m_aircraft->multirotorFrameType->addItem("Octocopter Coax +",
155  SystemSettings::AIRFRAMETYPE_OCTOCOAXP);
156  m_aircraft->multirotorFrameType->addItem("Octocopter Coax X",
157  SystemSettings::AIRFRAMETYPE_OCTOCOAXX);
158  m_aircraft->multirotorFrameType->setCurrentIndex(2); // Set default model to "Quad X"
159 
160  // NEW STYLE: Loop through the widgets looking for all widgets that have "ChannelBox" in their
161  // name
162  // The upshot of this is that ALL new ComboBox widgets for selecting the output channel must
163  // have "ChannelBox" in their name
164  foreach (QComboBox *combobox,
165  this->findChildren<QComboBox *>(QRegExp("\\S+ChannelBo\\S+"))) // FOR WHATEVER REASON,
166  // THIS DOES NOT WORK
167  // WITH ChannelBox.
168  // ChannelBo is
169  // sufficiently accurate
170  {
171  combobox->addItems(channelNames);
172  }
173 
174  // Setup the Multirotor picture in the Quad settings interface
175  m_aircraft->quadShape->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
176  m_aircraft->quadShape->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
177  QSvgRenderer *renderer = new QSvgRenderer();
178  renderer->load(QString(":/configgadget/images/multirotor-shapes.svg"));
179  quad = new QGraphicsSvgItem();
180  quad->setSharedRenderer(renderer);
181  quad->setElementId("quad-x");
182  QGraphicsScene *scene = new QGraphicsScene(this);
183  scene->addItem(quad);
184  scene->setSceneRect(quad->boundingRect());
185  m_aircraft->quadShape->setScene(scene);
186 
187  // Put combo boxes in line one of the custom mixer table:
188  UAVDataObject *obj =
189  dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
190  UAVObjectField *field = obj->getField(QString("Mixer1Type"));
191  QStringList list = field->getOptions();
192  for (int i = 0; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++) {
193  QComboBox *qb = new QComboBox(m_aircraft->customMixerTable);
194  qb->addItems(list);
195  m_aircraft->customMixerTable->setCellWidget(0, i, qb);
196  }
197 
198  SpinBoxDelegate *sbd = new SpinBoxDelegate();
199  for (int i = 1; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++) {
200  m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
201  }
202 
203  // create and setup a MultiRotor config widget
204  m_multirotor = new ConfigMultiRotorWidget(m_aircraft);
205  m_multirotor->quad = quad;
206  m_multirotor->uiowner = this;
207  m_multirotor->setupUI(SystemSettings::AIRFRAMETYPE_QUADX);
208 
209  // create and setup a GroundVehicle config widget
210  m_groundvehicle = new ConfigGroundVehicleWidget(m_aircraft);
211  m_groundvehicle->setupUI(SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR);
212 
213  // create and setup a FixedWing config widget
214  m_fixedwing = new ConfigFixedWingWidget(m_aircraft);
215  m_fixedwing->setupUI(SystemSettings::AIRFRAMETYPE_FIXEDWING);
216 
217  // create and setup a Helicopter config widget
218  m_heli = m_aircraft->helicopterLayout;
219  m_heli->setupUI(SystemSettings::AIRFRAMETYPE_HELICP);
220 
221  // Connect aircraft type selection dropbox to callback function
222  connect(m_aircraft->aircraftType, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
223  &ConfigVehicleTypeWidget::switchAirframeType);
224 
225  // Connect airframe selection dropbox to callback functions
226  connect(m_aircraft->fixedWingType, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
227  &ConfigVehicleTypeWidget::doSetupAirframeUI);
228  connect(m_aircraft->multirotorFrameType, QOverload<int>::of(&QComboBox::currentIndexChanged),
229  this, &ConfigVehicleTypeWidget::doSetupAirframeUI);
230  connect(m_aircraft->groundVehicleType, QOverload<int>::of(&QComboBox::currentIndexChanged),
231  this, &ConfigVehicleTypeWidget::doSetupAirframeUI);
232  // connect(m_heli->m_ccpm->ccpmType, QOverload<const QString
233  // &>::of(&QComboBox::currentIndexChanged),
234  // this, &ConfigCcpmWidget::setupAirframeUI);
235 
236  // Connect the multirotor motor reverse checkbox
237  connect(m_aircraft->MultirotorRevMixercheckBox, &QAbstractButton::clicked, this,
238  &ConfigVehicleTypeWidget::reverseMultirotorMotor);
239 
240  // Connect actuator and level bias buttons to slots
241  connect(m_aircraft->bnLevelTrim, &QAbstractButton::clicked, this,
242  &ConfigVehicleTypeWidget::bnLevelTrim_clicked);
243  connect(m_aircraft->bnServoTrim, &QAbstractButton::clicked, this,
244  &ConfigVehicleTypeWidget::bnServoTrim_clicked);
245 
246  autoLoadWidgets();
247  enableControls(false);
248  refreshWidgetsValues();
249  addToDirtyMonitor();
250 
252  m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
253 }
254 
259 {
260  // Do nothing
261 }
262 
269 {
270  int i;
271  QStringList channelDesc;
272 
273  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
274  UAVObjectManager *objMngr = pm->getObject<UAVObjectManager>();
275  Q_ASSERT(objMngr);
276 
277  // get an instance of systemsettings
278  SystemSettings *systemSettings = SystemSettings::GetInstance(objMngr);
279  Q_ASSERT(systemSettings);
280  SystemSettings::DataFields systemSettingsData = systemSettings->getData();
281 
282  switch (systemSettingsData.AirframeType) {
283  // fixed wing
284  case SystemSettings::AIRFRAMETYPE_FIXEDWING:
285  case SystemSettings::AIRFRAMETYPE_FIXEDWINGELEVON:
286  case SystemSettings::AIRFRAMETYPE_FIXEDWINGVTAIL: {
287  channelDesc = ConfigFixedWingWidget::getChannelDescriptions();
288  } break;
289 
290  // helicp
291  case SystemSettings::AIRFRAMETYPE_HELICP: {
292  channelDesc = ConfigCcpmWidget::getChannelDescriptions();
293  } break;
294 
295  // multirotor
296  case SystemSettings::AIRFRAMETYPE_VTOL:
297  case SystemSettings::AIRFRAMETYPE_TRI:
298  case SystemSettings::AIRFRAMETYPE_QUADX:
299  case SystemSettings::AIRFRAMETYPE_QUADP:
300  case SystemSettings::AIRFRAMETYPE_OCTOV:
301  case SystemSettings::AIRFRAMETYPE_OCTOCOAXX:
302  case SystemSettings::AIRFRAMETYPE_OCTOCOAXP:
303  case SystemSettings::AIRFRAMETYPE_OCTO:
304  case SystemSettings::AIRFRAMETYPE_HEXAX:
305  case SystemSettings::AIRFRAMETYPE_HEXACOAX:
306  case SystemSettings::AIRFRAMETYPE_HEXA: {
307  channelDesc = ConfigMultiRotorWidget::getChannelDescriptions();
308  } break;
309 
310  // ground
311  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR:
312  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL:
313  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE: {
314  channelDesc = ConfigGroundVehicleWidget::getChannelDescriptions();
315  } break;
316 
317  default: {
318  for (i = 0; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++)
319  channelDesc.append(QString("-"));
320  } break;
321  }
322 
323  return channelDesc;
324 }
325 
331 void ConfigVehicleTypeWidget::switchAirframeType(int index)
332 {
333  m_aircraft->airframesWidget->setCurrentIndex(index);
334  m_aircraft->quadShape->setSceneRect(quad->boundingRect());
335  m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
336  switch (m_aircraft->aircraftType->itemData(index).toInt()) {
337  case AIRFRAME_FIXED_WING:
338  m_aircraft->bnServoTrim->setEnabled(true);
339  break;
340  case AIRFRAME_CUSTOM:
341  m_aircraft->customMixerTable->resizeColumnsToContents();
342  for (int i = 0; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++) {
343  m_aircraft->customMixerTable->setColumnWidth(
344  i,
345  (m_aircraft->customMixerTable->width()
346  - m_aircraft->customMixerTable->verticalHeader()->width())
347  / 10);
348  }
349  Q_FALLTHROUGH();
350  case AIRFRAME_MULTIROTOR:
351  case AIRFRAME_HELICOPTER:
352  case AIRFRAME_GROUND:
353  m_aircraft->bnServoTrim->setEnabled(false);
354  break;
355  }
356 }
357 
361 void ConfigVehicleTypeWidget::showEvent(QShowEvent *event)
362 {
363  Q_UNUSED(event)
364  // Thit fitInView method should only be called now, once the
365  // widget is shown, otherwise it cannot compute its values and
366  // the result is usually a ahrsbargraph that is way too small.
367  m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
368  m_aircraft->customMixerTable->resizeColumnsToContents();
369  for (int i = 0; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++) {
370  m_aircraft->customMixerTable->setColumnWidth(
371  i,
372  (m_aircraft->customMixerTable->width()
373  - m_aircraft->customMixerTable->verticalHeader()->width())
374  / 10);
375  }
376 }
377 
381 void ConfigVehicleTypeWidget::resizeEvent(QResizeEvent *event)
382 {
383  Q_UNUSED(event);
384  m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
385  // Make the custom table columns autostretch:
386  m_aircraft->customMixerTable->resizeColumnsToContents();
387  for (int i = 0; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++) {
388  m_aircraft->customMixerTable->setColumnWidth(
389  i,
390  (m_aircraft->customMixerTable->width()
391  - m_aircraft->customMixerTable->verticalHeader()->width())
392  / 10);
393  }
394 }
395 
396 void ConfigVehicleTypeWidget::toggleAileron2(int index)
397 {
398  if (index) {
399  m_aircraft->fwAileron2ChannelBox->setEnabled(true);
400  m_aircraft->fwAileron2Label->setEnabled(true);
401  } else {
402  m_aircraft->fwAileron2ChannelBox->setEnabled(false);
403  m_aircraft->fwAileron2Label->setEnabled(false);
404  }
405 }
406 
407 void ConfigVehicleTypeWidget::toggleElevator2(int index)
408 {
409  if (index) {
410  m_aircraft->fwElevator2ChannelBox->setEnabled(true);
411  m_aircraft->fwElevator2Label->setEnabled(true);
412  } else {
413  m_aircraft->fwElevator2ChannelBox->setEnabled(false);
414  m_aircraft->fwElevator2Label->setEnabled(false);
415  }
416 }
417 
418 void ConfigVehicleTypeWidget::toggleRudder2(int index)
419 {
420  if (index) {
421  m_aircraft->fwRudder2ChannelBox->setEnabled(true);
422  m_aircraft->fwRudder2Label->setEnabled(true);
423  } else {
424  m_aircraft->fwRudder2ChannelBox->setEnabled(false);
425  m_aircraft->fwRudder2Label->setEnabled(false);
426  }
427 }
428 
429 /**************************
430  * Aircraft settings
431  **************************/
435 void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject *obj)
436 {
437 
439 
440  if (!allObjectsUpdated())
441  return;
442 
443  bool dirty = isDirty();
444 
445  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
446  Q_ASSERT(mixerSettings);
447 
448  SystemSettings *systemSettings = SystemSettings::GetInstance(getObjectManager());
449  Q_ASSERT(systemSettings);
450  SystemSettings::DataFields systemSettingsData = systemSettings->getData();
451 
452  // Get the Airframe type from the system settings:
453  // At this stage, we will need to have some hardcoded settings in this code, this
454  // is not ideal, but there you go.
455  frameType = (SystemSettings::AirframeTypeOptions)systemSettingsData.AirframeType;
456  setupAirframeUI(frameType);
457 
458  QPointer<VehicleConfig> vconfig = new VehicleConfig();
459 
460  QList<double> curveValues;
461 
462  // Setup all Throttle2 curves for all types of airframe
463  vconfig->getThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE2,
464  &curveValues);
465 
466  if (!vconfig->isValidThrottleCurve(&curveValues)) {
467  for (int i = 0; i < curveValues.count(); i++) {
468  curveValues[i] = 1.0 * ((double)i / curveValues.count());
469  }
470 
471  vconfig->setThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE2,
472  curveValues);
473  }
474 
475  // Load the Settings for vehicle frames:
476  switch (frameType) {
477  case SystemSettings::AIRFRAMETYPE_FIXEDWING:
478  case SystemSettings::AIRFRAMETYPE_FIXEDWINGELEVON:
479  case SystemSettings::AIRFRAMETYPE_FIXEDWINGVTAIL:
480  // Retrieve fixed wing settings
481  m_fixedwing->refreshAirframeWidgetsValues(frameType);
482  break;
483  case SystemSettings::AIRFRAMETYPE_TRI:
484  case SystemSettings::AIRFRAMETYPE_QUADX:
485  case SystemSettings::AIRFRAMETYPE_QUADP:
486  case SystemSettings::AIRFRAMETYPE_HEXA:
487  case SystemSettings::AIRFRAMETYPE_HEXAX:
488  case SystemSettings::AIRFRAMETYPE_HEXACOAX:
489  case SystemSettings::AIRFRAMETYPE_OCTO:
490  case SystemSettings::AIRFRAMETYPE_OCTOV:
491  case SystemSettings::AIRFRAMETYPE_OCTOCOAXP:
492  case SystemSettings::AIRFRAMETYPE_OCTOCOAXX:
493  // Retrieve multirotor settings
494  m_multirotor->refreshAirframeWidgetsValues(frameType);
495  break;
496  case SystemSettings::AIRFRAMETYPE_HELICP:
497  // Retrieve helicopter settings
498  setComboCurrentIndex(m_aircraft->aircraftType,
499  m_aircraft->aircraftType->findText("Helicopter"));
500  m_heli->refreshAirframeWidgetsValues(frameType);
501  break;
502  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR:
503  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL:
504  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE:
505  // Retrieve ground vehicle settings
506  m_groundvehicle->refreshAirframeWidgetsValues(frameType);
507  break;
508  default:
509  // Retrieve custom settings
510  setComboCurrentIndex(m_aircraft->aircraftType,
511  m_aircraft->aircraftType->findText("Custom"));
512  break;
513  }
514 
515  updateCustomAirframeUI();
516 
517  // Tell UI is has unsaved changes
518  setDirty(dirty);
519 }
520 
526 void ConfigVehicleTypeWidget::doSetupAirframeUI(int comboboxIndex)
527 {
528  // Check which tab page is currently selected, and get the item data from the appropriate
529  // combobox
530  if (m_aircraft->aircraftType->currentText() == "Multirotor") {
531  frameType = (SystemSettings::AirframeTypeOptions)m_aircraft->multirotorFrameType
532  ->itemData(comboboxIndex)
533  .toUInt();
534  } else if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
535  frameType =
536  (SystemSettings::AirframeTypeOptions)m_aircraft->fixedWingType->itemData(comboboxIndex)
537  .toUInt();
538  } else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
539  frameType = SystemSettings::AIRFRAMETYPE_HELICP;
540  } else if (m_aircraft->aircraftType->currentText() == "Ground") {
541  frameType = (SystemSettings::AirframeTypeOptions)m_aircraft->groundVehicleType
542  ->itemData(comboboxIndex)
543  .toUInt();
544  } else if (m_aircraft->aircraftType->currentText() == "Custom") {
545  frameType = SystemSettings::AIRFRAMETYPE_CUSTOM;
546  }
547 
548  // Setup the
549  setupAirframeUI(frameType);
550 }
551 
556 void ConfigVehicleTypeWidget::setupAirframeUI(SystemSettings::AirframeTypeOptions frameType)
557 {
558  bool dirty = isDirty();
559 
560  switch (frameType) {
561  case SystemSettings::AIRFRAMETYPE_FIXEDWING:
562  case SystemSettings::AIRFRAMETYPE_FIXEDWINGELEVON:
563  case SystemSettings::AIRFRAMETYPE_FIXEDWINGVTAIL:
564  // Call fixed-wing setup UI
565  m_fixedwing->setupUI(frameType);
566  break;
567  case SystemSettings::AIRFRAMETYPE_TRI:
568  case SystemSettings::AIRFRAMETYPE_QUADX:
569  case SystemSettings::AIRFRAMETYPE_QUADP:
570  case SystemSettings::AIRFRAMETYPE_HEXA:
571  case SystemSettings::AIRFRAMETYPE_HEXAX:
572  case SystemSettings::AIRFRAMETYPE_HEXACOAX:
573  case SystemSettings::AIRFRAMETYPE_OCTO:
574  case SystemSettings::AIRFRAMETYPE_OCTOV:
575  case SystemSettings::AIRFRAMETYPE_OCTOCOAXP:
576  case SystemSettings::AIRFRAMETYPE_OCTOCOAXX:
577  // Call multi-rotor setup UI
578  m_multirotor->setupUI(frameType);
579  break;
580  case SystemSettings::AIRFRAMETYPE_HELICP:
581  // Call helicopter setup UI
582  m_heli->setupUI(frameType);
583  break;
584  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR:
585  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL:
586  case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE:
587  // Call ground vehicle setup UI
588  m_groundvehicle->setupUI(frameType);
589  break;
590  default:
591  break;
592  }
593 
594  // SHOULDN'T THIS BE DONE ONLY IN QUAD SETUP, AND NOT ALL THE REST???
595  m_aircraft->quadShape->setSceneRect(quad->boundingRect());
596  m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
597 
598  setDirty(dirty);
599 }
600 
604 void ConfigVehicleTypeWidget::resetField(UAVObjectField *field)
605 {
606  for (auto i = 0; i < field->getNumElements(); i++)
607  field->setValue(0, i);
608 }
609 
615 void ConfigVehicleTypeWidget::updateCustomAirframeUI()
616 {
617  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
618  Q_ASSERT(mixerSettings);
619 
620  QPointer<VehicleConfig> vconfig = new VehicleConfig();
621 
622  QList<double> curveValues;
623 
624  MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();
625  if (mixerSettingsData.Curve2Source == MixerSettings::CURVE2SOURCE_THROTTLE)
626  m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_THROTTLE, false);
627  else {
628  m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_OTHER, false);
629  }
630 
631  // Setup all Throttle2 curves for all types of airframes
632  vconfig->getThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE2,
633  &curveValues);
634 
635  if (vconfig->isValidThrottleCurve(&curveValues)) {
636  m_aircraft->customThrottle2Curve->initCurve(&curveValues);
637  } else {
638  m_aircraft->customThrottle2Curve->initLinearCurve(
639  curveValues.count(), 1.0, m_aircraft->customThrottle2Curve->getMin());
640  }
641 
642  // Update the mixer table:
643  for (int channel = 0; channel < (int)(ActuatorCommand::CHANNEL_NUMELEM); channel++) {
644  UAVObjectField *field = mixerSettings->getField(mixerTypes.at(channel));
645  if (field) {
646  QComboBox *q =
647  static_cast<QComboBox *>(m_aircraft->customMixerTable->cellWidget(0, channel));
648  if (q) {
649  QString s = field->getValue().toString();
650  setComboCurrentIndex(q, q->findText(s));
651  }
652 
653  m_aircraft->customMixerTable->item(1, channel)
654  ->setText(QString::number(vconfig->getMixerVectorValue(
655  mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE1)));
656  m_aircraft->customMixerTable->item(2, channel)
657  ->setText(QString::number(vconfig->getMixerVectorValue(
658  mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE2)));
659  m_aircraft->customMixerTable->item(3, channel)
660  ->setText(QString::number(vconfig->getMixerVectorValue(
661  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL)));
662  m_aircraft->customMixerTable->item(4, channel)
663  ->setText(QString::number(vconfig->getMixerVectorValue(
664  mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH)));
665  m_aircraft->customMixerTable->item(5, channel)
666  ->setText(QString::number(vconfig->getMixerVectorValue(
667  mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW)));
668  m_aircraft->customMixerTable->item(6, channel)
669  ->setText(QString::number(vconfig->getMixerVectorValue(
670  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ACCESSORY0)));
671  m_aircraft->customMixerTable->item(7, channel)
672  ->setText(QString::number(vconfig->getMixerVectorValue(
673  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ACCESSORY1)));
674  m_aircraft->customMixerTable->item(8, channel)
675  ->setText(QString::number(vconfig->getMixerVectorValue(
676  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ACCESSORY2)));
677  }
678  }
679 }
680 
688 void ConfigVehicleTypeWidget::updateObjectsFromWidgets()
689 {
690  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
691  Q_ASSERT(mixerSettings);
692 
693  QPointer<VehicleConfig> vconfig = new VehicleConfig();
694 
695  frameType = SystemSettings::AIRFRAMETYPE_CUSTOM; // Set airframe type default to "Custom"
696 
697  if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
698  frameType = m_fixedwing->updateConfigObjectsFromWidgets();
699  } else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
700  frameType = m_multirotor->updateConfigObjectsFromWidgets();
701  } else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
702  frameType = m_heli->updateConfigObjectsFromWidgets();
703  } else if (m_aircraft->aircraftType->currentText() == "Ground") {
704  frameType = m_groundvehicle->updateConfigObjectsFromWidgets();
705  } else {
706  // Update the table:
707  for (int channel = 0; channel < (int)(ActuatorCommand::CHANNEL_NUMELEM); channel++) {
708  QComboBox *q =
709  static_cast<QComboBox *>(m_aircraft->customMixerTable->cellWidget(0, channel));
710  if (q->currentText() == "Disabled")
711  vconfig->setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_DISABLED);
712  else if (q->currentText() == "Motor")
713  vconfig->setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_MOTOR);
714  else if (q->currentText() == "Servo")
715  vconfig->setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_SERVO);
716  else if (q->currentText() == "CameraRoll")
717  vconfig->setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_CAMERAROLL);
718  else if (q->currentText() == "CameraPitch")
719  vconfig->setMixerType(mixerSettings, channel,
720  MixerSettings::MIXER1TYPE_CAMERAPITCH);
721  else if (q->currentText() == "CameraYaw")
722  vconfig->setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_CAMERAYAW);
723 
724  vconfig->setMixerVectorValue(
725  mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE1,
726  m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
727  vconfig->setMixerVectorValue(
728  mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE2,
729  m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
730  vconfig->setMixerVectorValue(
731  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL,
732  m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
733  vconfig->setMixerVectorValue(
734  mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH,
735  m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
736  vconfig->setMixerVectorValue(
737  mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW,
738  m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
739  vconfig->setMixerVectorValue(
740  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ACCESSORY0,
741  m_aircraft->customMixerTable->item(6, channel)->text().toDouble());
742  vconfig->setMixerVectorValue(
743  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ACCESSORY1,
744  m_aircraft->customMixerTable->item(7, channel)->text().toDouble());
745  vconfig->setMixerVectorValue(
746  mixerSettings, channel, MixerSettings::MIXER1VECTOR_ACCESSORY2,
747  m_aircraft->customMixerTable->item(8, channel)->text().toDouble());
748  }
749 
750  // set the airframe type
751  SystemSettings *systemSettings = SystemSettings::GetInstance(getObjectManager());
752  Q_ASSERT(systemSettings);
753  SystemSettings::DataFields systemSettingsData = systemSettings->getData();
754 
755  systemSettingsData.AirframeType = frameType;
756 
757  systemSettings->setData(systemSettingsData);
758  }
759 
760  /* Call the superclass fairly late here, because it wants to save things
761  * we're still touching.
762  */
764 
765  updateCustomAirframeUI();
766 }
767 
773 void ConfigVehicleTypeWidget::setComboCurrentIndex(QComboBox *box, int index)
774 {
775  if (index >= 0 && index < box->count())
776  box->setCurrentIndex(index);
777 }
778 
779 void ConfigVehicleTypeWidget::reverseMultirotorMotor()
780 {
781  m_multirotor->drawAirframe(frameType);
782 }
783 
788 void ConfigVehicleTypeWidget::bnLevelTrim_clicked()
789 {
790  QMessageBox msgBox(QMessageBox::Question, tr("Trim level"),
791  tr("Use the transmitter trim to set the autopilot for straight and level "
792  "flight? (Please see the tooltip for more information.)"),
793  QMessageBox::Yes | QMessageBox::No, this);
794  int userChoice = msgBox.exec();
795 
796  // If the user cancels, stop here.
797  if (userChoice != QMessageBox::Yes)
798  return;
799 
800  // Call bias set function
801  VehicleTrim vehicleTrim;
803  ret = vehicleTrim.setAutopilotBias();
804 
805  // Process return state
806  switch (ret) {
808  QMessageBox msgBox(QMessageBox::Critical, tr("No receiver detected"),
809  tr("Transmitter and receiver must be powered on."), QMessageBox::Ok,
810  this);
811  msgBox.exec();
812  break;
813  }
815  QMessageBox msgBox(QMessageBox::Critical, tr("Vehicle armed"),
816  tr("The autopilot must be disarmed first."), QMessageBox::Ok, this);
817  msgBox.exec();
818  break;
819  }
821  QMessageBox msgBox(
822  QMessageBox::Critical, tr("Vehicle not in Stabilized mode"),
823  tr("The autopilot must be in Leveling, Stabilized1, Stabilized2, or Stabilized3 mode."),
824  QMessageBox::Ok, this);
825  msgBox.exec();
826  break;
827  }
829  QMessageBox msgBox(QMessageBox::Critical,
830  tr("Incorrect roll and pitch stabilization modes."),
831  tr("Both roll and pitch must be in Attitude stabilization mode."),
832  QMessageBox::Ok, this);
833  msgBox.exec();
834  break;
835  }
837  QMessageBox msgBox(
838  QMessageBox::Information, tr("Trim updated"),
839  tr("Trim successfully updated, please reset the transmitter's trim to zero and be sure "
840  "to configure stabilization settings to use Attitude mode."),
841  QMessageBox::Ok, this);
842  msgBox.exec();
843 
844  // Set tab as dirty (i.e. having unsaved changes).
845  setDirty(true);
846 
847  break;
848  }
849 }
850 
855 void ConfigVehicleTypeWidget::bnServoTrim_clicked()
856 {
857  QMessageBox msgBox(QMessageBox::Question, tr("Trim servos"),
858  "Use the transmitter trim to set servos for wings-level, constant-speed "
859  "flight? (Please see the tooltip for more information.)",
860  QMessageBox::Ok | QMessageBox::Cancel, this);
861  int cancelAction = msgBox.exec();
862 
863  // If the user cancels, stop here.
864  if (cancelAction != QMessageBox::Ok)
865  return;
866 
867  // Call servo trim function
868  VehicleTrim vehicleTrim;
870  ret = vehicleTrim.setTrimActuators();
871 
872  // Process return state
873  switch (ret) {
875  QMessageBox msgBox(QMessageBox::Critical, tr("No receiver detected"),
876  "Transmitter and receiver must be powered on.", QMessageBox::Ok, this);
877  msgBox.exec();
878  break;
879  }
881  QMessageBox msgBox(QMessageBox::Critical, tr("Vehicle not in manual mode"),
882  "The autopilot must be in manual flight mode.", QMessageBox::Ok, this);
883  msgBox.exec();
884  break;
885  }
887  QMessageBox msgBox(
888  QMessageBox::Information, tr("Trim updated"),
889  "Servo trim successfully updated, please reset the transmitter's trim before flying.",
890  QMessageBox::Ok, this);
891  msgBox.exec();
892 
893  // Set tab as dirty (i.e. having unsaved changes).
894  setDirty(true);
895 
896  break;
897  }
898 }
899 
904 void ConfigVehicleTypeWidget::addToDirtyMonitor()
905 {
906  addWidget(m_aircraft->customMixerTable);
907  addWidget(m_aircraft->fixedWingType);
908  addWidget(m_aircraft->groundVehicleType);
909  addWidget(m_aircraft->multirotorFrameType);
910  addWidget(m_aircraft->multiMotorChannelBox1);
911  addWidget(m_aircraft->multiMotorChannelBox2);
912  addWidget(m_aircraft->multiMotorChannelBox3);
913  addWidget(m_aircraft->multiMotorChannelBox4);
914  addWidget(m_aircraft->multiMotorChannelBox5);
915  addWidget(m_aircraft->multiMotorChannelBox6);
916  addWidget(m_aircraft->multiMotorChannelBox7);
917  addWidget(m_aircraft->multiMotorChannelBox8);
918  addWidget(m_aircraft->mrPitchMixLevel);
919  addWidget(m_aircraft->mrRollMixLevel);
920  addWidget(m_aircraft->mrYawMixLevel);
921  addWidget(m_aircraft->triYawChannelBox);
922  addWidget(m_aircraft->aircraftType);
923  addWidget(m_aircraft->fwEngineChannelBox);
924  addWidget(m_aircraft->fwAileron1ChannelBox);
925  addWidget(m_aircraft->fwAileron2ChannelBox);
926  addWidget(m_aircraft->fwElevator1ChannelBox);
927  addWidget(m_aircraft->fwElevator2ChannelBox);
928  addWidget(m_aircraft->fwRudder1ChannelBox);
929  addWidget(m_aircraft->fwRudder2ChannelBox);
930  addWidget(m_aircraft->elevonSlider1);
931  addWidget(m_aircraft->elevonSlider2);
932  addWidget(m_heli->m_ccpm->ccpmType);
933  addWidget(m_heli->m_ccpm->ccpmTailChannel);
934  addWidget(m_heli->m_ccpm->ccpmEngineChannel);
935  addWidget(m_heli->m_ccpm->ccpmServoWChannel);
936  addWidget(m_heli->m_ccpm->ccpmServoXChannel);
937  addWidget(m_heli->m_ccpm->ccpmServoYChannel);
938  addWidget(m_heli->m_ccpm->ccpmSingleServo);
939  addWidget(m_heli->m_ccpm->ccpmServoZChannel);
940  addWidget(m_heli->m_ccpm->ccpmAngleW);
941  addWidget(m_heli->m_ccpm->ccpmAngleX);
942  addWidget(m_heli->m_ccpm->ccpmCorrectionAngle);
943  addWidget(m_heli->m_ccpm->ccpmAngleZ);
944  addWidget(m_heli->m_ccpm->ccpmAngleY);
945  addWidget(m_heli->m_ccpm->ccpmCollectivePassthrough);
946  addWidget(m_heli->m_ccpm->ccpmLinkRoll);
947  addWidget(m_heli->m_ccpm->ccpmLinkCyclic);
948  addWidget(m_heli->m_ccpm->ccpmRevoSlider);
949  addWidget(m_heli->m_ccpm->ccpmREVOspinBox);
950  addWidget(m_heli->m_ccpm->ccpmCollectiveSlider);
951  addWidget(m_heli->m_ccpm->ccpmCollectivespinBox);
952  addWidget(m_heli->m_ccpm->ccpmCollectiveScale);
953  addWidget(m_heli->m_ccpm->ccpmCollectiveScaleBox);
954  addWidget(m_heli->m_ccpm->ccpmCyclicScale);
955  addWidget(m_heli->m_ccpm->ccpmPitchScale);
956  addWidget(m_heli->m_ccpm->ccpmPitchScaleBox);
957  addWidget(m_heli->m_ccpm->ccpmRollScale);
958  addWidget(m_heli->m_ccpm->ccpmRollScaleBox);
959  addWidget(m_heli->m_ccpm->SwashLvlPositionSlider);
960  addWidget(m_heli->m_ccpm->SwashLvlPositionSpinBox);
961  addWidget(m_heli->m_ccpm->PitchCurve->getCurveWidget());
962  addWidget(m_heli->m_ccpm->ccpmAdvancedSettingsTable);
963 }
void setDirty(bool value)
void addUAVObjectToWidgetRelation(QString object, QString field, QWidget *widget, int index=0, double scale=1, bool isLimited=false, bool useUnits=false, QList< int > *defaultReloadGroups=nullptr, quint32 instID=0, bool oneWayBind=false)
Add an UAVObject field to widget relation to the management system Note: This is the instance called ...
Gui-less support class for vehicle trimming.
ConfigVehicleTypeWidget(QWidget *parent=nullptr)
void addWidget(QWidget *widget)
autopilotLevelBiasMessages
Definition: vehicletrim.h:53
Core plugin system that manages the plugins, their life cycle and their registered objects...
Definition: pluginmanager.h:53
static const double mixerRange
QVariant getValue(int index=0) const
autopilotLevelBiasMessages setAutopilotBias()
VehicleTrim::setFixedWingTrimAutopilotBias Takes the desired roll and pitch, and sets that as the aut...
Definition: vehicletrim.cpp:54
int getNumElements() const
for i
Definition: OPPlots.m:140
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
QStringList getOptions() const
void setValue(const QVariant &data, int index=0)
UAVObjectField * getField(const QString &name)
Definition: uavobject.cpp:236
The VehicleTrim class is a UI free algorithm that can be connected to any interfaces. As such it only communicates with the UI via signals and slots, but has no direct handles to any particular controls or widgets.
Definition: vehicletrim.h:39
void addUAVObject(QString objectName, QList< int > *reloadGroups=NULL)
actuatorTrimMessages setTrimActuators()
VehicleTrim::setFixedWingTrimActuators Reads the servo inputs from the transmitter, and sets these values as the neutral points.
SpinBoxDelegate(QObject *parent=nullptr)
virtual void enableControls(bool enable)
virtual void updateObjectsFromWidgets()
virtual void refreshWidgetsValues(UAVObject *obj=NULL)
void showEvent(QShowEvent *event)
UAVObject * getObject(const QString &name, quint32 instId=0)
void setEditorData(QWidget *editor, const QModelIndex &index) const
UAVObjectManager * getObjectManager()
ConfigTaskWidget::getObjectManager Utility function to get a pointer to the object manager...
void resizeEvent(QResizeEvent *event)
static QStringList getChannelDescriptions()
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const