dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
configmultirotorwidget.cpp
Go to the documentation of this file.
1 
12 /*
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  * for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with this program; if not, see <http://www.gnu.org/licenses/>
25  */
26 #include "configmultirotorwidget.h"
27 
28 #include <QDebug>
29 #include <QStringList>
30 #include <QWidget>
31 #include <QTextEdit>
32 #include <QVBoxLayout>
33 #include <QPushButton>
34 #include <QComboBox>
35 #include <QBrush>
36 #include <math.h>
37 
38 #include "actuatorcommand.h"
39 #include "mixersettings.h"
40 
41 const QString ConfigMultiRotorWidget::CHANNELBOXNAME = QString("multiMotorChannelBox");
42 const QString ConfigMultiRotorWidget::CHANNELLABELNAME = QString("MotorOutputLabel");
43 
47 ConfigMultiRotorWidget::ConfigMultiRotorWidget(Ui_AircraftWidget *aircraft, QWidget *parent)
48  : VehicleConfig(parent)
49  , invertMotors(1)
50 {
51  m_aircraft = aircraft;
52 }
53 
58 {
59  // Do nothing
60 }
61 
62 void ConfigMultiRotorWidget::setupUI(SystemSettings::AirframeTypeOptions frameType)
63 {
64  Q_ASSERT(m_aircraft);
65  Q_ASSERT(uiowner);
66  Q_ASSERT(quad);
67 
68  int i;
69  // motor labels
70  QStringList labels;
71  int numMotors = 0;
72 
73  // set aircraftType to Multirotor, disable triyaw channel
74  setComboCurrentIndex(m_aircraft->aircraftType,
75  m_aircraft->aircraftType->findText("Multirotor"));
76  m_aircraft->triYawChannelBox->setEnabled(false);
77 
78  // disable all motor channel boxes
79  for (i = 1; i <= 8; i++) {
80  // do it manually so we can turn off any error decorations
81  QComboBox *combobox =
82  uiowner->findChild<QComboBox *>("multiMotorChannelBox" + QString::number(i));
83  if (combobox) {
84  combobox->setEnabled(false);
85  combobox->setItemData(0, 0, Qt::DecorationRole);
86  }
87  }
88 
89  switch (frameType) {
90  case SystemSettings::AIRFRAMETYPE_TRI:
92  m_aircraft->multirotorFrameType,
93  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_TRI));
94 
95  m_aircraft->mrRollMixLevel->setValue(100);
96  m_aircraft->mrPitchMixLevel->setValue(100);
97  setYawMixLevel(50);
98 
99  m_aircraft->triYawChannelBox->setEnabled(true);
100 
101  // set motor boxes
102  numMotors = 3;
103  labels << "NW"
104  << "NE"
105  << "S";
106  break;
107  case SystemSettings::AIRFRAMETYPE_QUADX:
109  m_aircraft->multirotorFrameType,
110  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_QUADX));
111 
112  // Enable all necessary motor channel boxes...
113  enableComboBoxes(uiowner, CHANNELBOXNAME, 4, true);
114 
115  // init mixer levels
116  m_aircraft->mrRollMixLevel->setValue(50);
117  m_aircraft->mrPitchMixLevel->setValue(50);
118  setYawMixLevel(50);
119 
120  // set motor boxes
121  numMotors = 4;
122  labels << "NW"
123  << "NE"
124  << "SE"
125  << "SW";
126  break;
127  case SystemSettings::AIRFRAMETYPE_QUADP:
129  m_aircraft->multirotorFrameType,
130  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_QUADP));
131 
132  // Enable all necessary motor channel boxes...
133  enableComboBoxes(uiowner, CHANNELBOXNAME, 4, true);
134 
135  m_aircraft->mrRollMixLevel->setValue(100);
136  m_aircraft->mrPitchMixLevel->setValue(100);
137  setYawMixLevel(50);
138 
139  // set motor boxes
140  numMotors = 4;
141  labels << "N"
142  << "E"
143  << "S"
144  << "W";
145  break;
146  case SystemSettings::AIRFRAMETYPE_HEXA:
148  m_aircraft->multirotorFrameType,
149  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_HEXA));
150 
151  m_aircraft->mrRollMixLevel->setValue(50);
152  m_aircraft->mrPitchMixLevel->setValue(33);
153  setYawMixLevel(33);
154 
155  // set motor boxes
156  numMotors = 6;
157  break;
158  case SystemSettings::AIRFRAMETYPE_HEXAX:
160  m_aircraft->multirotorFrameType,
161  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_HEXAX));
162 
163  m_aircraft->mrRollMixLevel->setValue(33);
164  m_aircraft->mrPitchMixLevel->setValue(50);
165  setYawMixLevel(33);
166 
167  // set motor boxes
168  numMotors = 6;
169  break;
170  case SystemSettings::AIRFRAMETYPE_HEXACOAX:
172  m_aircraft->multirotorFrameType,
173  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_HEXACOAX));
174 
175  m_aircraft->mrRollMixLevel->setValue(100);
176  m_aircraft->mrPitchMixLevel->setValue(50);
177  setYawMixLevel(66);
178 
179  // set motor boxes
180  numMotors = 6;
181  break;
182  case SystemSettings::AIRFRAMETYPE_OCTO:
184  m_aircraft->multirotorFrameType,
185  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_OCTO));
186 
187  m_aircraft->mrRollMixLevel->setValue(33);
188  m_aircraft->mrPitchMixLevel->setValue(33);
189  setYawMixLevel(25);
190 
191  // set motor boxes
192  numMotors = 8;
193  break;
194  case SystemSettings::AIRFRAMETYPE_OCTOV:
196  m_aircraft->multirotorFrameType,
197  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_OCTOV));
198 
199  m_aircraft->mrRollMixLevel->setValue(25);
200  m_aircraft->mrPitchMixLevel->setValue(25);
201  setYawMixLevel(25);
202 
203  // set motor boxes
204  numMotors = 8;
205  break;
206  case SystemSettings::AIRFRAMETYPE_OCTOCOAXP:
208  m_aircraft->multirotorFrameType,
209  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_OCTOCOAXP));
210 
211  m_aircraft->mrRollMixLevel->setValue(100);
212  m_aircraft->mrPitchMixLevel->setValue(100);
213  setYawMixLevel(50);
214 
215  // set motor boxes
216  numMotors = 8;
217  break;
218  case SystemSettings::AIRFRAMETYPE_OCTOCOAXX:
220  m_aircraft->multirotorFrameType,
221  m_aircraft->multirotorFrameType->findData(SystemSettings::AIRFRAMETYPE_OCTOCOAXX));
222 
223  m_aircraft->mrRollMixLevel->setValue(50);
224  m_aircraft->mrPitchMixLevel->setValue(50);
225  setYawMixLevel(50);
226 
227  // set motor boxes
228  numMotors = 8;
229  break;
230  default:
231  Q_ASSERT(0);
232  break;
233  }
234 
235  // set labels on motor boxes, use default labels when not specified by vehicle type above
236  for (int i = labels.length() + 1; i <= numMotors; i++)
237  labels << QString::number(i);
238  setLabelText(uiowner, CHANNELLABELNAME, labels);
239  // enable necessary motor boxes
240  enableComboBoxes(uiowner, CHANNELBOXNAME, numMotors, true);
241 
242  // Draw the appropriate airframe
243  drawAirframe(frameType);
244 }
245 
246 void ConfigMultiRotorWidget::drawAirframe(SystemSettings::AirframeTypeOptions frameType)
247 {
248 
249  invertMotors = m_aircraft->MultirotorRevMixercheckBox->isChecked() ? -1 : 1;
250 
251  switch (frameType) {
252  case SystemSettings::AIRFRAMETYPE_TRI:
253  if (invertMotors > 0)
254  quad->setElementId("tri");
255  else
256  quad->setElementId("tri_reverse");
257  break;
258  case SystemSettings::AIRFRAMETYPE_QUADX:
259  if (invertMotors > 0)
260  quad->setElementId("quad-x");
261  else
262  quad->setElementId("quad-x_reverse");
263  break;
264  case SystemSettings::AIRFRAMETYPE_QUADP:
265  if (invertMotors > 0)
266  quad->setElementId("quad-plus");
267  else
268  quad->setElementId("quad-plus_reverse");
269  break;
270  case SystemSettings::AIRFRAMETYPE_HEXA:
271  if (invertMotors > 0)
272  quad->setElementId("quad-hexa");
273  else
274  quad->setElementId("quad-hexa_reverse");
275  break;
276  case SystemSettings::AIRFRAMETYPE_HEXAX:
277  if (invertMotors > 0)
278  quad->setElementId("quad-hexa-H");
279  else
280  quad->setElementId("quad-hexa-H_reverse");
281  break;
282  case SystemSettings::AIRFRAMETYPE_HEXACOAX:
283  if (invertMotors > 0)
284  quad->setElementId("hexa-coax");
285  else
286  quad->setElementId("hexa-coax_reverse");
287  break;
288  case SystemSettings::AIRFRAMETYPE_OCTO:
289  if (invertMotors > 0)
290  quad->setElementId("quad-octo");
291  else
292  quad->setElementId("quad-octo_reverse");
293  break;
294  case SystemSettings::AIRFRAMETYPE_OCTOV:
295  if (invertMotors > 0)
296  quad->setElementId("quad-octo-v");
297  else
298  quad->setElementId("quad-octo-v_reverse");
299  break;
300  case SystemSettings::AIRFRAMETYPE_OCTOCOAXP:
301  if (invertMotors > 0)
302  quad->setElementId("octo-coax-P");
303  else
304  quad->setElementId("octo-coax-P_reverse");
305  break;
306  case SystemSettings::AIRFRAMETYPE_OCTOCOAXX:
307  if (invertMotors > 0)
308  quad->setElementId("octo-coax-X");
309  else
310  quad->setElementId("octo-coax-X_reverse");
311  break;
312  default:
313  Q_ASSERT(0);
314  break;
315  }
316 }
317 
318 void ConfigMultiRotorWidget::ResetActuators(GUIConfigDataUnion *configData)
319 {
320  configData->multi.VTOLMotorN = 0;
321  configData->multi.VTOLMotorNE = 0;
322  configData->multi.VTOLMotorE = 0;
323  configData->multi.VTOLMotorSE = 0;
324  configData->multi.VTOLMotorS = 0;
325  configData->multi.VTOLMotorSW = 0;
326  configData->multi.VTOLMotorW = 0;
327  configData->multi.VTOLMotorNW = 0;
328  configData->multi.TRIYaw = 0;
329 }
330 
331 QStringList ConfigMultiRotorWidget::getChannelDescriptions()
332 {
333  QStringList channelDesc;
334 
335  // init a channel_numelem list of channel desc defaults
336  for (int i = 0; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++) {
337  channelDesc.append(QString("-"));
338  }
339 
340  // get the gui config data
341  GUIConfigDataUnion configData = GetConfigData();
342  multiGUISettingsStruct multi = configData.multi;
343 
344  if (multi.VTOLMotorN > 0 && multi.VTOLMotorN <= ActuatorCommand::CHANNEL_NUMELEM)
345  channelDesc[multi.VTOLMotorN - 1] = QString("VTOLMotorN");
346  if (multi.VTOLMotorNE > 0 && multi.VTOLMotorNE <= ActuatorCommand::CHANNEL_NUMELEM)
347  channelDesc[multi.VTOLMotorNE - 1] = QString("VTOLMotorNE");
348  if (multi.VTOLMotorNW > 0 && multi.VTOLMotorNW <= ActuatorCommand::CHANNEL_NUMELEM)
349  channelDesc[multi.VTOLMotorNW - 1] = QString("VTOLMotorNW");
350  if (multi.VTOLMotorS > 0 && multi.VTOLMotorS <= ActuatorCommand::CHANNEL_NUMELEM)
351  channelDesc[multi.VTOLMotorS - 1] = QString("VTOLMotorS");
352  if (multi.VTOLMotorSE > 0 && multi.VTOLMotorSE <= ActuatorCommand::CHANNEL_NUMELEM)
353  channelDesc[multi.VTOLMotorSE - 1] = QString("VTOLMotorSE");
354  if (multi.VTOLMotorSW > 0 && multi.VTOLMotorSW <= ActuatorCommand::CHANNEL_NUMELEM)
355  channelDesc[multi.VTOLMotorSW - 1] = QString("VTOLMotorSW");
356  if (multi.VTOLMotorW > 0 && multi.VTOLMotorW <= ActuatorCommand::CHANNEL_NUMELEM)
357  channelDesc[multi.VTOLMotorW - 1] = QString("VTOLMotorW");
358  if (multi.VTOLMotorE > 0 && multi.VTOLMotorE <= ActuatorCommand::CHANNEL_NUMELEM)
359  channelDesc[multi.VTOLMotorE - 1] = QString("VTOLMotorE");
360  if (multi.TRIYaw > 0 && multi.TRIYaw <= ActuatorCommand::CHANNEL_NUMELEM)
361  channelDesc[multi.TRIYaw - 1] = QString("Tri-Yaw");
362 
363  return channelDesc;
364 }
365 
366 void ConfigMultiRotorWidget::setYawMixLevel(int value)
367 {
368  if (value < 0) {
369  m_aircraft->mrYawMixLevel->setValue((-1) * value);
370  m_aircraft->MultirotorRevMixercheckBox->setChecked(true);
371  } else {
372  m_aircraft->mrYawMixLevel->setValue(value);
373  m_aircraft->MultirotorRevMixercheckBox->setChecked(false);
374  }
375 }
376 
380 SystemSettings::AirframeTypeOptions ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
381 {
382  SystemSettings::AirframeTypeOptions airframeType = SystemSettings::AIRFRAMETYPE_FIXEDWING;
383  QList<QString> motorList;
384 
385  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
386  Q_ASSERT(mixerSettings);
387 
388  if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex())
389  == SystemSettings::AIRFRAMETYPE_QUADP) {
390  airframeType = SystemSettings::AIRFRAMETYPE_QUADP;
391  setupQuad(true);
392  } else if (m_aircraft->multirotorFrameType->itemData(
393  m_aircraft->multirotorFrameType->currentIndex())
394  == SystemSettings::AIRFRAMETYPE_QUADX) {
395  airframeType = SystemSettings::AIRFRAMETYPE_QUADX;
396  setupQuad(false);
397  } else if (m_aircraft->multirotorFrameType->itemData(
398  m_aircraft->multirotorFrameType->currentIndex())
399  == SystemSettings::AIRFRAMETYPE_HEXA) {
400  airframeType = SystemSettings::AIRFRAMETYPE_HEXA;
401  setupHexa(true);
402  } else if (m_aircraft->multirotorFrameType->itemData(
403  m_aircraft->multirotorFrameType->currentIndex())
404  == SystemSettings::AIRFRAMETYPE_HEXAX) {
405  airframeType = SystemSettings::AIRFRAMETYPE_HEXAX;
406  setupHexa(false);
407  } else if (m_aircraft->multirotorFrameType->itemData(
408  m_aircraft->multirotorFrameType->currentIndex())
409  == SystemSettings::AIRFRAMETYPE_HEXACOAX) {
410  airframeType = SystemSettings::AIRFRAMETYPE_HEXACOAX;
411 
412  // Show any config errors in GUI
413  if (throwConfigError(6)) {
414  return airframeType;
415  }
416  motorList << "VTOLMotorNW"
417  << "VTOLMotorW"
418  << "VTOLMotorNE"
419  << "VTOLMotorE"
420  << "VTOLMotorS"
421  << "VTOLMotorSE";
422  setupMotors(motorList, airframeType);
423 
424  // Motor 1 to 6, Y6 Layout:
425  // pitch roll yaw
426  double mixer[8][3] = { { 0.5, 1, -1 }, { 0.5, 1, 1 }, { 0.5, -1, -1 }, { 0.5, -1, 1 },
427  { -1, 0, -1 }, { -1, 0, 1 }, { 0, 0, 0 }, { 0, 0, 0 } };
428  setupMultiRotorMixer(mixer);
429  m_aircraft->mrStatusLabel->setText("Configuration OK");
430 
431  } else if (m_aircraft->multirotorFrameType->itemData(
432  m_aircraft->multirotorFrameType->currentIndex())
433  == SystemSettings::AIRFRAMETYPE_OCTO) {
434  airframeType = SystemSettings::AIRFRAMETYPE_OCTO;
435 
436  // Show any config errors in GUI
437  if (throwConfigError(8)) {
438  return airframeType;
439  }
440  motorList << "VTOLMotorN"
441  << "VTOLMotorNE"
442  << "VTOLMotorE"
443  << "VTOLMotorSE"
444  << "VTOLMotorS"
445  << "VTOLMotorSW"
446  << "VTOLMotorW"
447  << "VTOLMotorNW";
448  setupMotors(motorList, airframeType);
449  // Motor 1 to 8:
450  // pitch roll yaw
451  double mixer[8][3] = { { 1, 0, -1 }, { 1, -1, 1 }, { 0, -1, -1 }, { -1, -1, 1 },
452  { -1, 0, -1 }, { -1, 1, 1 }, { 0, 1, -1 }, { 1, 1, 1 } };
453  setupMultiRotorMixer(mixer);
454  m_aircraft->mrStatusLabel->setText("Configuration OK");
455 
456  } else if (m_aircraft->multirotorFrameType->itemData(
457  m_aircraft->multirotorFrameType->currentIndex())
458  == SystemSettings::AIRFRAMETYPE_OCTOV) {
459  airframeType = SystemSettings::AIRFRAMETYPE_OCTOV;
460 
461  // Show any config errors in GUI
462  if (throwConfigError(8)) {
463  return airframeType;
464  }
465  motorList << "VTOLMotorN"
466  << "VTOLMotorNE"
467  << "VTOLMotorE"
468  << "VTOLMotorSE"
469  << "VTOLMotorS"
470  << "VTOLMotorSW"
471  << "VTOLMotorW"
472  << "VTOLMotorNW";
473  setupMotors(motorList, airframeType);
474  // Motor 1 to 8:
475  // IMPORTANT: Assumes evenly spaced engines
476  // pitch roll yaw
477  double mixer[8][3] = { { 0.33, -1, -1 }, { 1, -1, 1 }, { -1, -1, -1 }, { -0.33, -1, 1 },
478  { -0.33, 1, -1 }, { -1, 1, 1 }, { 1, 1, -1 }, { 0.33, 1, 1 } };
479  setupMultiRotorMixer(mixer);
480  m_aircraft->mrStatusLabel->setText("Configuration OK");
481 
482  } else if (m_aircraft->multirotorFrameType->itemData(
483  m_aircraft->multirotorFrameType->currentIndex())
484  == SystemSettings::AIRFRAMETYPE_OCTOCOAXP) {
485  airframeType = SystemSettings::AIRFRAMETYPE_OCTOCOAXP;
486 
487  // Show any config errors in GUI
488  if (throwConfigError(8)) {
489  return airframeType;
490  }
491  motorList << "VTOLMotorN"
492  << "VTOLMotorNE"
493  << "VTOLMotorE"
494  << "VTOLMotorSE"
495  << "VTOLMotorS"
496  << "VTOLMotorSW"
497  << "VTOLMotorW"
498  << "VTOLMotorNW";
499  setupMotors(motorList, airframeType);
500  // Motor 1 to 8:
501  // pitch roll yaw
502  double mixer[8][3] = { { 1, 0, -1 }, { 1, 0, 1 }, { 0, -1, -1 }, { 0, -1, 1 },
503  { -1, 0, -1 }, { -1, 0, 1 }, { 0, 1, -1 }, { 0, 1, 1 } };
504  setupMultiRotorMixer(mixer);
505  m_aircraft->mrStatusLabel->setText("Configuration OK");
506 
507  } else if (m_aircraft->multirotorFrameType->itemData(
508  m_aircraft->multirotorFrameType->currentIndex())
509  == SystemSettings::AIRFRAMETYPE_OCTOCOAXX) {
510  airframeType = SystemSettings::AIRFRAMETYPE_OCTOCOAXX;
511 
512  // Show any config errors in GUI
513  if (throwConfigError(8)) {
514  return airframeType;
515  }
516  motorList << "VTOLMotorNW"
517  << "VTOLMotorN"
518  << "VTOLMotorNE"
519  << "VTOLMotorE"
520  << "VTOLMotorSE"
521  << "VTOLMotorS"
522  << "VTOLMotorSW"
523  << "VTOLMotorW";
524  setupMotors(motorList, airframeType);
525  // Motor 1 to 8:
526  // pitch roll yaw
527  double mixer[8][3] = { { 1, 1, -1 }, { 1, 1, 1 }, { 1, -1, -1 }, { 1, -1, 1 },
528  { -1, -1, -1 }, { -1, -1, 1 }, { -1, 1, -1 }, { -1, 1, 1 } };
529  setupMultiRotorMixer(mixer);
530  m_aircraft->mrStatusLabel->setText("Configuration OK");
531 
532  } else if (m_aircraft->multirotorFrameType->itemData(
533  m_aircraft->multirotorFrameType->currentIndex())
534  == SystemSettings::AIRFRAMETYPE_TRI) {
535  airframeType = SystemSettings::AIRFRAMETYPE_TRI;
536 
537  // Show any config errors in GUI
538  if (throwConfigError(3)) {
539  return airframeType;
540  }
541  if (m_aircraft->triYawChannelBox->currentText() == "None") {
542  m_aircraft->mrStatusLabel->setText(
543  "<font color='red'>Error: Assign a Yaw channel</font>");
544  return airframeType;
545  }
546  motorList << "VTOLMotorNW"
547  << "VTOLMotorNE"
548  << "VTOLMotorS";
549  setupMotors(motorList, airframeType);
550 
551  // Motor 1 to 6, Y6 Layout:
552  // pitch roll yaw
553  double mixer[8][3] = { { 0.5, 1, 0 }, { 0.5, -1, 0 }, { -1, 0, 0 }, { 0, 0, 0 },
554  { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
555  setupMultiRotorMixer(mixer);
556 
557  // tell the mixer about tricopter yaw channel
558 
559  int channel = m_aircraft->triYawChannelBox->currentIndex() - 1;
560  if (channel > -1) {
561  setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_SERVO);
562  setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW,
563  mixerScale);
564  }
565 
566  m_aircraft->mrStatusLabel->setText(tr("Configuration OK"));
567  }
568 
569  return airframeType;
570 }
571 
575 void ConfigMultiRotorWidget::refreshAirframeWidgetsValues(
576  SystemSettings::AirframeTypeOptions frameType)
577 {
578  int channel;
579  double value;
580 
582  multiGUISettingsStruct multi = config.multi;
583 
584  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
585  Q_ASSERT(mixerSettings);
586 
587  if (frameType == SystemSettings::AIRFRAMETYPE_QUADP) {
588  // Motors 1/2/3/4 are: N / E / S / W
589  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorN);
590  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorE);
591  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorS);
592  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorW);
593 
594  // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
595  // This assumes that all vectors are identical - if not, the user should use the
596  // "custom" setting.
597 
598  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
599  if (channel > -1) {
600  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
601  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
602 
603  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
604  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
605 
606  channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
607  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
608  m_aircraft->mrRollMixLevel->setValue(-qRound(value / (mixerScale / 100.0)));
609  }
610  } else if (frameType == SystemSettings::AIRFRAMETYPE_QUADX) {
611  // Motors 1/2/3/4 are: NW / NE / SE / SW
612  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
613  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
614  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE);
615  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSW);
616 
617  // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
618  // This assumes that all vectors are identical - if not, the user should use the
619  // "custom" setting.
620  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
621  if (channel > -1) {
622  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
623  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
624 
625  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
626  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
627 
628  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
629  m_aircraft->mrRollMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
630  }
631 
632  } else if (frameType == SystemSettings::AIRFRAMETYPE_HEXA) {
633  // Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
634 
635  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorN);
636  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
637  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE);
638  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorS);
639  setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorSW);
640  setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorNW);
641 
642  // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
643  // This assumes that all vectors are identical - if not, the user should use the
644  // "custom" setting.
645 
646  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
647  if (channel > -1) {
648  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
649  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
650 
651  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
652  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
653 
654  // change channels
655  channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
656  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
657  m_aircraft->mrRollMixLevel->setValue(-qRound(value / (mixerScale / 100.0)));
658  }
659 
660  } else if (frameType == SystemSettings::AIRFRAMETYPE_HEXAX) {
661  // Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
662 
663  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNE);
664  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorE);
665  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE);
666  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSW);
667  setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorW);
668  setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorNW);
669 
670  // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
671  // This assumes that all vectors are identical - if not, the user should use the
672  // "custom" setting.
673 
674  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
675  if (channel > -1) {
676  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
677  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
678 
679  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
680  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
681 
682  channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
683  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
684  m_aircraft->mrRollMixLevel->setValue(-qRound(value / (mixerScale / 100.0)));
685  }
686  } else if (frameType == SystemSettings::AIRFRAMETYPE_HEXACOAX) {
687  // Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
688 
689  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
690  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorW);
691  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorNE);
692  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorE);
693  setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorS);
694  setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorSE);
695 
696  // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
697  // This assumes that all vectors are identical - if not, the user should use the
698  // "custom" setting.
699  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
700  if (channel > -1) {
701  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
702  m_aircraft->mrPitchMixLevel->setValue(qRound(2 * value / (mixerScale / 100.0)));
703 
704  channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
705  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
706  setYawMixLevel(qRound(value / (mixerScale / 100.0)));
707 
708  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
709  m_aircraft->mrRollMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
710  }
711  } else if (frameType == SystemSettings::AIRFRAMETYPE_OCTO
712  || frameType == SystemSettings::AIRFRAMETYPE_OCTOV
713  || frameType == SystemSettings::AIRFRAMETYPE_OCTOCOAXP) {
714  // Motors 1 to 8 are N / NE / E / etc
715 
716  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorN);
717  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
718  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorE);
719  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSE);
720  setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorS);
721  setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorSW);
722  setComboCurrentIndex(m_aircraft->multiMotorChannelBox7, multi.VTOLMotorW);
723  setComboCurrentIndex(m_aircraft->multiMotorChannelBox8, multi.VTOLMotorNW);
724 
725  // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
726  // This assumes that all vectors are identical - if not, the user should use the
727  // "custom" setting.
728  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
729  if (channel > -1) {
730  if (frameType == SystemSettings::AIRFRAMETYPE_OCTO) {
731  value =
732  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
733  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
734 
735  value =
736  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
737  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
738 
739  // change channels
740  channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
741  value =
742  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
743  m_aircraft->mrRollMixLevel->setValue(-qRound(value / (mixerScale / 100.0)));
744  } else if (frameType == SystemSettings::AIRFRAMETYPE_OCTOV) {
745  value =
746  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
747  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
748 
749  value =
750  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
751  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
752 
753  // change channels
754  channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
755  value =
756  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
757  m_aircraft->mrRollMixLevel->setValue(-qRound(value / (mixerScale / 100.0)));
758  } else if (frameType == SystemSettings::AIRFRAMETYPE_OCTOCOAXP) {
759  value =
760  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
761  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
762 
763  value =
764  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
765  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
766 
767  // change channels
768  channel = m_aircraft->multiMotorChannelBox3->currentIndex() - 1;
769  value =
770  getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
771  m_aircraft->mrRollMixLevel->setValue(-qRound(value / (mixerScale / 100.0)));
772  }
773  }
774  } else if (frameType == SystemSettings::AIRFRAMETYPE_OCTOCOAXX) {
775  // Motors 1 to 8 are N / NE / E / etc
776 
777  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
778  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorN);
779  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorNE);
780  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorE);
781  setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorSE);
782  setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorS);
783  setComboCurrentIndex(m_aircraft->multiMotorChannelBox7, multi.VTOLMotorSW);
784  setComboCurrentIndex(m_aircraft->multiMotorChannelBox8, multi.VTOLMotorW);
785 
786  // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
787  // This assumes that all vectors are identical - if not, the user should use the
788  // "custom" setting.
789  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
790  if (channel > -1) {
791  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
792  m_aircraft->mrPitchMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
793 
794  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW);
795  setYawMixLevel(-qRound(value / (mixerScale / 100.0)));
796 
797  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
798  m_aircraft->mrRollMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
799  }
800  } else if (frameType == SystemSettings::AIRFRAMETYPE_TRI) {
801  // Motors 1 to 8 are N / NE / E / etc
802 
803  setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
804  setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
805  setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorS);
806  setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorS);
807  setComboCurrentIndex(m_aircraft->triYawChannelBox, multi.TRIYaw);
808 
809  channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
810  if (channel > -1) {
811  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH);
812  m_aircraft->mrPitchMixLevel->setValue(qRound(2 * value / (mixerScale / 100.0)));
813 
814  value = getMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL);
815  m_aircraft->mrRollMixLevel->setValue(qRound(value / (mixerScale / 100.0)));
816  }
817  }
818 
819  drawAirframe(frameType);
820 }
821 
825 void ConfigMultiRotorWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
826 {
827  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
828  Q_ASSERT(mixerSettings);
829 
830  setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_MOTOR);
831 
832  setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE1,
833  mixerScale);
834  setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE2, 0);
835  setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL,
836  qRound(roll * mixerScale));
837  setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH,
838  qRound(pitch * mixerScale));
839  setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW,
840  qRound(yaw * mixerScale));
841 }
842 
846 void ConfigMultiRotorWidget::setupMotors(QList<QString> motorList,
847  SystemSettings::AirframeTypeOptions vehicle)
848 {
849  QList<QComboBox *> mmList;
850  mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2
851  << m_aircraft->multiMotorChannelBox3 << m_aircraft->multiMotorChannelBox4
852  << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
853  << m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
854 
855  GUIConfigDataUnion configData = GetConfigData();
856  ResetActuators(&configData);
857 
858  int index;
859  foreach (QString motor, motorList) {
860 
861  index = mmList.takeFirst()->currentIndex();
862 
863  if (motor == QString("VTOLMotorN"))
864  configData.multi.VTOLMotorN = index;
865  else if (motor == QString("VTOLMotorNE"))
866  configData.multi.VTOLMotorNE = index;
867  else if (motor == QString("VTOLMotorE"))
868  configData.multi.VTOLMotorE = index;
869  else if (motor == QString("VTOLMotorSE"))
870  configData.multi.VTOLMotorSE = index;
871  else if (motor == QString("VTOLMotorS"))
872  configData.multi.VTOLMotorS = index;
873  else if (motor == QString("VTOLMotorSW"))
874  configData.multi.VTOLMotorSW = index;
875  else if (motor == QString("VTOLMotorW"))
876  configData.multi.VTOLMotorW = index;
877  else if (motor == QString("VTOLMotorNW"))
878  configData.multi.VTOLMotorNW = index;
879  }
880 
881  if (vehicle == SystemSettings::AIRFRAMETYPE_TRI) {
882  configData.multi.TRIYaw = m_aircraft->triYawChannelBox->currentIndex();
883  }
884 
885  SetConfigData(configData, vehicle);
886 }
887 
891 bool ConfigMultiRotorWidget::setupQuad(bool pLayout)
892 {
893  // Check coherence:
894 
895  // Show any config errors in GUI
896  if (throwConfigError(4)) {
897  return false;
898  }
899 
900  QList<QString> motorList;
901  if (pLayout) {
902  motorList << "VTOLMotorN"
903  << "VTOLMotorE"
904  << "VTOLMotorS"
905  << "VTOLMotorW";
906  } else {
907  motorList << "VTOLMotorNW"
908  << "VTOLMotorNE"
909  << "VTOLMotorSE"
910  << "VTOLMotorSW";
911  }
912  setupMotors(motorList,
913  pLayout ? SystemSettings::AIRFRAMETYPE_QUADP : SystemSettings::AIRFRAMETYPE_QUADX);
914 
915  // Now, setup the mixer:
916  // Motor 1 to 4, X Layout:
917  // pitch roll yaw
918  // {0.5 ,0.5 ,-0.5 //Front left motor (CW)
919  // {0.5 ,-0.5 ,0.5 //Front right motor(CCW)
920  // {-0.5 ,-0.5 ,-0.5 //rear right motor (CW)
921  // {-0.5 ,0.5 ,0.5 //Rear left motor (CCW)
922  double xMixer[8][3] = { { 1, 1, -1 }, { 1, -1, 1 }, { -1, -1, -1 }, { -1, 1, 1 },
923  { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
924  //
925  // Motor 1 to 4, P Layout:
926  // pitch roll yaw
927  // {1 ,0 ,-0.5 //Front motor (CW)
928  // {0 ,-1 ,0.5 //Right motor(CCW)
929  // {-1 ,0 ,-0.5 //Rear motor (CW)
930  // {0 ,1 ,0.5 //Left motor (CCW)
931  double pMixer[8][3] = { { 1, 0, -1 }, { 0, -1, 1 }, { -1, 0, -1 }, { 0, 1, 1 },
932  { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
933 
934  if (pLayout) {
935  setupMultiRotorMixer(pMixer);
936  } else {
937  setupMultiRotorMixer(xMixer);
938  }
939  m_aircraft->mrStatusLabel->setText(tr("Configuration OK"));
940  return true;
941 }
942 
946 bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
947 {
948  // Check coherence:
949  // Show any config errors in GUI
950  if (throwConfigError(6))
951  return false;
952 
953  QList<QString> motorList;
954  if (pLayout) {
955  motorList << "VTOLMotorN"
956  << "VTOLMotorNE"
957  << "VTOLMotorSE"
958  << "VTOLMotorS"
959  << "VTOLMotorSW"
960  << "VTOLMotorNW";
961  } else {
962  motorList << "VTOLMotorNE"
963  << "VTOLMotorE"
964  << "VTOLMotorSE"
965  << "VTOLMotorSW"
966  << "VTOLMotorW"
967  << "VTOLMotorNW";
968  }
969  setupMotors(motorList,
970  pLayout ? SystemSettings::AIRFRAMETYPE_HEXA : SystemSettings::AIRFRAMETYPE_HEXAX);
971 
972  // and set only the relevant channels:
973 
974  // Motor 1 to 6, P Layout:
975  // pitch roll yaw
976  // 1 { 0.3 , 0 ,-0.3 // N CW
977  // 2 { 0.3 ,-0.5 , 0.3 // NE CCW
978  // 3 {-0.3 ,-0.5 ,-0.3 // SE CW
979  // 4 {-0.3 , 0 , 0.3 // S CCW
980  // 5 {-0.3 , 0.5 ,-0.3 // SW CW
981  // 6 { 0.3 , 0.5 , 0.3 // NW CCW
982 
983  double pMixer[8][3] = { { 1, 0, -1 }, { 1, -1, 1 }, { -1, -1, -1 }, { -1, 0, 1 },
984  { -1, 1, -1 }, { 1, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } };
985 
986  //
987  // Motor 1 to 6, X Layout:
988  // 1 [ 0.5, -0.3, -0.3 ] NE
989  // 2 [ 0 , -0.3, 0.3 ] E
990  // 3 [ -0.5, -0.3, -0.3 ] SE
991  // 4 [ -0.5, 0.3, 0.3 ] SW
992  // 5 [ 0 , 0.3, -0.3 ] W
993  // 6 [ 0.5, 0.3, 0.3 ] NW
994  double xMixer[8][3] = { { 1, -1, -1 }, { 0, -1, 1 }, { -1, -1, -1 }, { -1, 1, 1 },
995  { 0, 1, -1 }, { 1, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } };
996 
997  if (pLayout) {
998  setupMultiRotorMixer(pMixer);
999  } else {
1000  setupMultiRotorMixer(xMixer);
1001  }
1002  m_aircraft->mrStatusLabel->setText("Configuration OK");
1003  return true;
1004 }
1005 
1009 bool ConfigMultiRotorWidget::setupMultiRotorMixer(double mixerFactors[8][3])
1010 {
1011  QList<QComboBox *> mmList;
1012  mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2
1013  << m_aircraft->multiMotorChannelBox3 << m_aircraft->multiMotorChannelBox4
1014  << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
1015  << m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
1016 
1017  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
1018  Q_ASSERT(mixerSettings);
1019  resetMixers(mixerSettings);
1020 
1021  // and enable only the relevant channels:
1022  double pFactor = (double)m_aircraft->mrPitchMixLevel->value() / 100;
1023  double rFactor = (double)m_aircraft->mrRollMixLevel->value() / 100;
1024  invertMotors = m_aircraft->MultirotorRevMixercheckBox->isChecked() ? -1 : 1;
1025  double yFactor = invertMotors * (double)m_aircraft->mrYawMixLevel->value() / 100;
1026  for (int i = 0; i < 8; i++) {
1027  if (mmList.at(i)->isEnabled()) {
1028  int channel = mmList.at(i)->currentIndex() - 1;
1029  if (channel > -1)
1030  setupQuadMotor(channel, mixerFactors[i][0] * pFactor, rFactor * mixerFactors[i][1],
1031  yFactor * mixerFactors[i][2]);
1032  }
1033  }
1034  return true;
1035 }
1036 
1041 bool ConfigMultiRotorWidget::throwConfigError(int numMotors)
1042 {
1043  // Initialize configuration error flag
1044  bool error = false;
1045 
1046  // Iterate through all instances of multiMotorChannelBox
1047  for (int i = 0; i < numMotors; i++) {
1048  // Find widgets with text "multiMotorChannelBox.x", where x is an integer
1049  QComboBox *combobox =
1050  uiowner->findChild<QComboBox *>("multiMotorChannelBox" + QString::number(i + 1));
1051  if (combobox) {
1052  if (combobox->currentText() == "None") {
1053  int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize);
1054  QPixmap pixmap(size, size);
1055  pixmap.fill(QColor("red"));
1056  combobox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
1057  error = true;
1058  } else {
1059  combobox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
1060  }
1061  }
1062  }
1063 
1064  if (error) {
1065  m_aircraft->mrStatusLabel->setText(
1066  QString("<font color='red'>ERROR: Assign all %1 motor channels</font>").arg(numMotors));
1067  }
1068  return error;
1069 }
static void SetConfigData(GUIConfigDataUnion configData, SystemSettings::AirframeTypeOptions vehicle)
static GUIConfigDataUnion GetConfigData()
for i
Definition: OPPlots.m:140
double getMixerVectorValue(UAVDataObject *mixer, int channel, MixerSettings::Mixer1VectorElem elementName)
void resetMixers(UAVDataObject *mixer)
void setMixerType(UAVDataObject *mixer, int channel, MixerSettings::Mixer1TypeOptions mixerType)
multiGUISettingsStruct multi
void setMixerVectorValue(UAVDataObject *mixer, int channel, MixerSettings::Mixer1VectorElem elementName, double value)
ConfigMultiRotorWidget(Ui_AircraftWidget *aircraft=nullptr, QWidget *parent=nullptr)
static void enableComboBoxes(QWidget *owner, QString boxName, int boxCount, bool enable)
else error('Your technical computing program does not support file choosers.Please input the file name in the argument. ') end elseif nargin >0 logfile
void setLabelText(QWidget *owner, const QString &boxName, const QStringList &labels)
UAVObjectManager * getObjectManager()
ConfigTaskWidget::getObjectManager Utility function to get a pointer to the object manager...
static const double mixerScale
static void setComboCurrentIndex(QComboBox *box, int index)