dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
configccpmwidget.cpp
Go to the documentation of this file.
1 
13 /*
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.
18  *
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.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  */
27 #include "configccpmwidget.h"
28 #include "physical_constants.h"
29 
30 #include <QDebug>
31 #include <QStringList>
32 #include <QWidget>
33 #include <QTextEdit>
34 #include <QVBoxLayout>
35 #include <QPushButton>
36 #include <QBrush>
37 #include <math.h>
38 #include <QMessageBox>
39 
40 #include "actuatorcommand.h"
41 #include "mixersettings.h"
42 
44  : VehicleConfig(parent)
45 {
46  int i;
47  SwashLvlConfigurationInProgress = 0;
48  SwashLvlState = 0;
49  SwashLvlServoInterlock = 0;
50  updatingFromHardware = false;
51  updatingToHardware = false;
52 
53  m_ccpm = new Ui_CcpmWidget();
54  m_ccpm->setupUi(this);
55 
56  // Initialization of the swashplaye widget
57  m_ccpm->SwashplateImage->setScene(new QGraphicsScene(this));
58 
59  m_ccpm->SwashLvlSwashplateImage->setScene(m_ccpm->SwashplateImage->scene());
60  m_ccpm->SwashLvlSwashplateImage->setSceneRect(-50, -50, 500, 500);
61  // m_ccpm->SwashLvlSwashplateImage->scale(.85,.85);
62 
63  // m_ccpm->SwashplateImage->setSceneRect(SwashplateImg->boundingRect());
64  m_ccpm->SwashplateImage->setSceneRect(-50, -30, 500, 500);
65  // m_ccpm->SwashplateImage->scale(.85,.85);
66 
67  QSvgRenderer *renderer = new QSvgRenderer();
68  renderer->load(QString(":/configgadget/images/ccpm_setup.svg"));
69 
70  SwashplateImg = new QGraphicsSvgItem();
71  SwashplateImg->setSharedRenderer(renderer);
72  SwashplateImg->setElementId("Swashplate");
73  SwashplateImg->setObjectName("Swashplate");
74  // SwashplateImg->setScale(0.75);
75  m_ccpm->SwashplateImage->scene()->addItem(SwashplateImg);
76 
77  QFont serifFont("Times", 24, QFont::Bold);
78  QPen pen; // creates a default pen
79 
80  pen.setStyle(Qt::DotLine);
81  pen.setWidth(2);
82  pen.setBrush(Qt::gray);
83  pen.setCapStyle(Qt::RoundCap);
84  pen.setJoinStyle(Qt::RoundJoin);
85 
86  QBrush brush(Qt::darkBlue);
87  QPen pen2; // creates a default pen
88 
89  // pen2.setStyle(Qt::DotLine);
90  pen2.setWidth(1);
91  pen2.setBrush(Qt::blue);
92  // pen2.setCapStyle(Qt::RoundCap);
93  // pen2.setJoinStyle(Qt::RoundJoin);
94 
95  // brush.setStyle(Qt::RadialGradientPattern);
96 
97  QList<QString> ServoNames;
98  ServoNames << "ServoW"
99  << "ServoX"
100  << "ServoY"
101  << "ServoZ";
102 
103  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
104  ServoLines[i] =
105  m_ccpm->SwashLvlSwashplateImage->scene()->addLine(0, 0, 100 * i, i * i * 100, pen);
106 
107  Servos[i] = new QGraphicsSvgItem();
108  Servos[i]->setSharedRenderer(renderer);
109  Servos[i]->setElementId(ServoNames.at(i));
110  m_ccpm->SwashplateImage->scene()->addItem(Servos[i]);
111 
112  ServosText[i] = new QGraphicsTextItem();
113  ServosText[i]->setDefaultTextColor(Qt::yellow);
114  ServosText[i]->setPlainText(QString("-"));
115  ServosText[i]->setFont(serifFont);
116 
117  ServosTextCircles[i] = new QGraphicsEllipseItem(1, 1, 30, 30);
118  ServosTextCircles[i]->setBrush(brush);
119  ServosTextCircles[i]->setPen(pen2);
120  m_ccpm->SwashplateImage->scene()->addItem(ServosTextCircles[i]);
121  m_ccpm->SwashplateImage->scene()->addItem(ServosText[i]);
122 
123  SwashLvlSpinBoxes[i] = new QSpinBox;
124  m_ccpm->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
125  SwashLvlSpinBoxes[i]->setMaximum(10000);
126  SwashLvlSpinBoxes[i]->setMinimum(0);
127  SwashLvlSpinBoxes[i]->setValue(0);
128  }
129 
130  // initialize our throttle mixer curve
131 
132  // initialize channel names
133  m_ccpm->ccpmEngineChannel->addItems(channelNames);
134  m_ccpm->ccpmEngineChannel->setCurrentIndex(0);
135  m_ccpm->ccpmTailChannel->addItems(channelNames);
136  m_ccpm->ccpmTailChannel->setCurrentIndex(0);
137  m_ccpm->ccpmServoWChannel->addItems(channelNames);
138  m_ccpm->ccpmServoWChannel->setCurrentIndex(0);
139  m_ccpm->ccpmServoXChannel->addItems(channelNames);
140  m_ccpm->ccpmServoXChannel->setCurrentIndex(0);
141  m_ccpm->ccpmServoYChannel->addItems(channelNames);
142  m_ccpm->ccpmServoYChannel->setCurrentIndex(0);
143  m_ccpm->ccpmServoZChannel->addItems(channelNames);
144  m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
145 
146  QStringList Types;
147  Types << QString::fromUtf8("CCPM 2 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 90º")
148  << QString::fromUtf8("CCPM 4 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 120º")
149  << QString::fromUtf8("CCPM 3 Servo 140º") << QString::fromUtf8("FP 2 Servo 90º")
150  << QString::fromUtf8("Coax 2 Servo 90º") << QString::fromUtf8("Custom - User Angles")
151  << QString::fromUtf8("Custom - Advanced Settings");
152  m_ccpm->ccpmType->addItems(Types);
153 
154  // set default swashplate config to CCPM 3 Servo 120 degrees
155  // need to set the index for the dropdown list and update the UI config using that index
156  m_ccpm->ccpmType->setCurrentIndex(
157  m_ccpm->ccpmType->findText(QString::fromUtf8("CCPM 3 Servo 120º")));
158 
159  // It is wrong to do these before the type is selected to be heli
160  // GUIConfigDataUnion config = GetConfigData();
161  // config.heli.SwashplateType = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
162  // SetConfigData(config, SystemSettings::AIRFRAMETYPE_HELICP);
163 
164  refreshAirframeWidgetsValues(SystemSettings::AIRFRAMETYPE_HELICP);
165 
166  // initialize our collective mixer curve
167  // refreshAirframeWidgetsValues triggers a whole cascade of curve-related calls
168  // need set the collective curve info after this point to make it stick
169  // tell mixercurve this is a pitch curve
170  m_ccpm->PitchCurve->setMixerType(MixerCurve::MIXERCURVE_OTHER, false);
171  m_ccpm->PitchCurve->initLinearCurve(5, 1.0, -1.0);
172 
173  UpdateType();
174 
175  connect(m_ccpm->ccpmAngleW, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
176  connect(m_ccpm->ccpmAngleX, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
177  connect(m_ccpm->ccpmAngleY, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
178  connect(m_ccpm->ccpmAngleZ, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
179  connect(m_ccpm->ccpmCorrectionAngle, SIGNAL(valueChanged(double)), this,
180  SLOT(ccpmSwashplateUpdate()));
181  connect(m_ccpm->ccpmServoWChannel, SIGNAL(currentIndexChanged(int)), this,
182  SLOT(ccpmSwashplateUpdate()));
183  connect(m_ccpm->ccpmServoXChannel, SIGNAL(currentIndexChanged(int)), this,
184  SLOT(ccpmSwashplateUpdate()));
185  connect(m_ccpm->ccpmServoYChannel, SIGNAL(currentIndexChanged(int)), this,
186  SLOT(ccpmSwashplateUpdate()));
187  connect(m_ccpm->ccpmServoZChannel, SIGNAL(currentIndexChanged(int)), this,
188  SLOT(ccpmSwashplateUpdate()));
189  connect(m_ccpm->ccpmEngineChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
190  connect(m_ccpm->ccpmTailChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
191  connect(m_ccpm->ccpmRevoSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
192  connect(m_ccpm->ccpmREVOspinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
193  connect(m_ccpm->ccpmCollectiveSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
194  connect(m_ccpm->ccpmCollectivespinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
195  connect(m_ccpm->ccpmType, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
196  connect(m_ccpm->ccpmSingleServo, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
197 
198  connect(m_ccpm->SwashLvlStartButton, SIGNAL(clicked()), this,
199  SLOT(SwashLvlStartButtonPressed()));
200  connect(m_ccpm->SwashLvlNextButton, SIGNAL(clicked()), this, SLOT(SwashLvlNextButtonPressed()));
201  connect(m_ccpm->SwashLvlCancelButton, SIGNAL(clicked()), this,
202  SLOT(SwashLvlCancelButtonPressed()));
203  connect(m_ccpm->SwashLvlFinishButton, SIGNAL(clicked()), this,
204  SLOT(SwashLvlFinishButtonPressed()));
205 
206  connect(m_ccpm->ccpmCollectivePassthrough, SIGNAL(clicked()), this,
207  SLOT(SetUIComponentVisibilities()));
208  connect(m_ccpm->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
209  connect(m_ccpm->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
210 
211  ccpmSwashplateRedraw();
212 }
213 
215 {
216  // Do nothing
217 }
218 
219 void ConfigCcpmWidget::setupUI(SystemSettings::AirframeTypeOptions frameType)
220 {
221  Q_UNUSED(frameType);
222 }
223 
224 void ConfigCcpmWidget::ResetActuators(GUIConfigDataUnion *configData)
225 {
226  configData->heli.Throttle = 0;
227  configData->heli.Tail = 0;
228  configData->heli.ServoIndexW = 0;
229  configData->heli.ServoIndexX = 0;
230  configData->heli.ServoIndexY = 0;
231  configData->heli.ServoIndexZ = 0;
232 }
233 
234 QStringList ConfigCcpmWidget::getChannelDescriptions()
235 {
236  int i;
237  QStringList channelDesc;
238 
239  // init a channel_numelem list of channel desc defaults
240  for (i = 0; i < (int)(ActuatorCommand::CHANNEL_NUMELEM); i++) {
241  channelDesc.append(QString("-"));
242  }
243 
244  // get the gui config data
245  GUIConfigDataUnion configData = GetConfigData();
246  heliGUISettingsStruct heli = configData.heli;
247 
248  if (heli.Throttle > 0)
249  channelDesc[heli.Throttle - 1] = QString("Throttle");
250  if (heli.Tail > 0)
251  channelDesc[heli.Tail - 1] = QString("Tail");
252 
253  switch (heli.FirstServoIndex) {
254  case 0: // front
255  if (heli.ServoIndexW > 0)
256  channelDesc[heli.ServoIndexW - 1] = QString("Elevator");
257  if (heli.ServoIndexX > 0)
258  channelDesc[heli.ServoIndexX - 1] = QString("Roll1");
259  if (heli.ServoIndexY > 0)
260  channelDesc[heli.ServoIndexY - 1] = QString("Roll2");
261  break;
262 
263  case 1: // right
264  if (heli.ServoIndexW > 0)
265  channelDesc[heli.ServoIndexW - 1] = QString("ServoW");
266  if (heli.ServoIndexX > 0)
267  channelDesc[heli.ServoIndexX - 1] = QString("ServoX");
268  if (heli.ServoIndexY > 0)
269  channelDesc[heli.ServoIndexY - 1] = QString("ServoY");
270  break;
271 
272  case 2: // rear
273  if (heli.ServoIndexW > 0)
274  channelDesc[heli.ServoIndexW - 1] = QString("Elevator");
275  if (heli.ServoIndexX > 0)
276  channelDesc[heli.ServoIndexX - 1] = QString("Roll1");
277  if (heli.ServoIndexY > 0)
278  channelDesc[heli.ServoIndexY - 1] = QString("Roll2");
279  break;
280 
281  case 3: // left
282  if (heli.ServoIndexW > 0)
283  channelDesc[heli.ServoIndexW - 1] = QString("ServoW");
284  if (heli.ServoIndexX > 0)
285  channelDesc[heli.ServoIndexX - 1] = QString("ServoX");
286  if (heli.ServoIndexY > 0)
287  channelDesc[heli.ServoIndexY - 1] = QString("ServoY");
288  break;
289  }
290  if (heli.ServoIndexZ > 0)
291  channelDesc[heli.ServoIndexZ - 1] = QString("ServoZ");
292 
293  return channelDesc;
294 }
295 
296 void ConfigCcpmWidget::UpdateType()
297 {
298  int TypeInt, SingleServoIndex, NumServosDefined;
299  double AdjustmentAngle = 0;
300 
301  SetUIComponentVisibilities();
302 
303  TypeInt = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex() - 1;
304  TypeText = m_ccpm->ccpmType->currentText();
305  SingleServoIndex = m_ccpm->ccpmSingleServo->currentIndex();
306 
307  // set visibility of user settings
308  m_ccpm->ccpmAdvancedSettingsTable->setEnabled(TypeInt == 0);
309  m_ccpm->ccpmAdvancedSettingsTable->clearFocus();
310  ;
311 
312  m_ccpm->ccpmAngleW->setEnabled(TypeInt == 1);
313  m_ccpm->ccpmAngleX->setEnabled(TypeInt == 1);
314  m_ccpm->ccpmAngleY->setEnabled(TypeInt == 1);
315  m_ccpm->ccpmAngleZ->setEnabled(TypeInt == 1);
316  m_ccpm->ccpmCorrectionAngle->setEnabled(TypeInt != 0);
317 
318  m_ccpm->ccpmServoWChannel->setEnabled(TypeInt > 0);
319  m_ccpm->ccpmServoXChannel->setEnabled(TypeInt > 0);
320  m_ccpm->ccpmServoYChannel->setEnabled(TypeInt > 0);
321  m_ccpm->ccpmServoZChannel->setEnabled(TypeInt > 0);
322  m_ccpm->ccpmSingleServo->setEnabled(TypeInt > 1);
323 
324  m_ccpm->ccpmEngineChannel->setEnabled(TypeInt > 0);
325  m_ccpm->ccpmTailChannel->setEnabled(TypeInt > 0);
326  m_ccpm->ccpmCollectiveSlider->setEnabled(TypeInt > 0);
327  m_ccpm->ccpmCollectivespinBox->setEnabled(TypeInt > 0);
328  m_ccpm->ccpmRevoSlider->setEnabled(TypeInt > 0);
329  m_ccpm->ccpmREVOspinBox->setEnabled(TypeInt > 0);
330 
331  AdjustmentAngle = SingleServoIndex * 90;
332 
333  m_ccpm->PitchCurve->setVisible(1);
334 
335  NumServosDefined = 4;
336  // set values for pre defined heli types
337  if (TypeText.compare(QString::fromUtf8("CCPM 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
338  m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
339  m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
340  m_ccpm->ccpmAngleY->setValue(0);
341  m_ccpm->ccpmAngleZ->setValue(0);
342  m_ccpm->ccpmAngleY->setEnabled(0);
343  m_ccpm->ccpmAngleZ->setEnabled(0);
344  m_ccpm->ccpmServoYChannel->setCurrentIndex(0);
345  m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
346  m_ccpm->ccpmServoYChannel->setEnabled(0);
347  m_ccpm->ccpmServoZChannel->setEnabled(0);
348  NumServosDefined = 2;
349 
350  } else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 90º"), Qt::CaseInsensitive) == 0) {
351  m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
352  m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
353  m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 180, 360));
354  m_ccpm->ccpmAngleZ->setValue(0);
355  m_ccpm->ccpmAngleZ->setEnabled(0);
356  m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
357  m_ccpm->ccpmServoZChannel->setEnabled(0);
358  NumServosDefined = 3;
359 
360  } else if (TypeText.compare(QString::fromUtf8("CCPM 4 Servo 90º"), Qt::CaseInsensitive) == 0) {
361  m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
362  m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
363  m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 180, 360));
364  m_ccpm->ccpmAngleZ->setValue(fmod(AdjustmentAngle + 270, 360));
365  m_ccpm->ccpmSingleServo->setEnabled(0);
366  m_ccpm->ccpmSingleServo->setCurrentIndex(0);
367  NumServosDefined = 4;
368 
369  } else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 120º"), Qt::CaseInsensitive) == 0) {
370  m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
371  m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 120, 360));
372  m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 240, 360));
373  m_ccpm->ccpmAngleZ->setValue(0);
374  m_ccpm->ccpmAngleZ->setEnabled(0);
375  m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
376  m_ccpm->ccpmServoZChannel->setEnabled(0);
377  NumServosDefined = 3;
378 
379  } else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 140º"), Qt::CaseInsensitive) == 0) {
380  m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
381  m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 140, 360));
382  m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 220, 360));
383  m_ccpm->ccpmAngleZ->setValue(0);
384  m_ccpm->ccpmAngleZ->setEnabled(0);
385  m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
386  m_ccpm->ccpmServoZChannel->setEnabled(0);
387  NumServosDefined = 3;
388 
389  } else if (TypeText.compare(QString::fromUtf8("FP 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
390  m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
391  m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
392  m_ccpm->ccpmAngleY->setValue(0);
393  m_ccpm->ccpmAngleZ->setValue(0);
394  m_ccpm->ccpmAngleY->setEnabled(0);
395  m_ccpm->ccpmAngleZ->setEnabled(0);
396  m_ccpm->ccpmServoYChannel->setCurrentIndex(0);
397  m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
398  m_ccpm->ccpmServoYChannel->setEnabled(0);
399  m_ccpm->ccpmServoZChannel->setEnabled(0);
400 
401  m_ccpm->ccpmCollectivespinBox->setEnabled(0);
402  m_ccpm->ccpmCollectiveSlider->setEnabled(0);
403  m_ccpm->ccpmCollectivespinBox->setValue(0);
404  m_ccpm->ccpmCollectiveSlider->setValue(0);
405  m_ccpm->PitchCurve->setVisible(0);
406  NumServosDefined = 2;
407  } else if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
408  m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
409  m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
410  m_ccpm->ccpmAngleY->setValue(0);
411  m_ccpm->ccpmAngleZ->setValue(0);
412  m_ccpm->ccpmAngleY->setEnabled(0);
413  m_ccpm->ccpmAngleZ->setEnabled(0);
414  m_ccpm->ccpmServoYChannel->setCurrentIndex(0);
415  m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
416  m_ccpm->ccpmServoYChannel->setEnabled(0);
417  m_ccpm->ccpmServoZChannel->setEnabled(0);
418 
419  m_ccpm->ccpmCollectivespinBox->setEnabled(0);
420  m_ccpm->ccpmCollectiveSlider->setEnabled(0);
421  m_ccpm->ccpmCollectivespinBox->setValue(0);
422  m_ccpm->ccpmCollectiveSlider->setValue(0);
423  m_ccpm->PitchCurve->setVisible(0);
424  NumServosDefined = 2;
425  }
426 
427  // Set the text of the motor boxes
428  if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
429  m_ccpm->ccpmEngineLabel->setText("CW motor");
430  m_ccpm->ccpmTailLabel->setText("CCW motor");
431  } else {
432  m_ccpm->ccpmEngineLabel->setText("Engine");
433  m_ccpm->ccpmTailLabel->setText("Tail rotor");
434  }
435 
436  // set the visibility of the swashplate servo selection boxes
437  m_ccpm->ccpmServoWLabel->setVisible(NumServosDefined >= 1);
438  m_ccpm->ccpmServoXLabel->setVisible(NumServosDefined >= 2);
439  m_ccpm->ccpmServoYLabel->setVisible(NumServosDefined >= 3);
440  m_ccpm->ccpmServoZLabel->setVisible(NumServosDefined >= 4);
441  m_ccpm->ccpmServoWChannel->setVisible(NumServosDefined >= 1);
442  m_ccpm->ccpmServoXChannel->setVisible(NumServosDefined >= 2);
443  m_ccpm->ccpmServoYChannel->setVisible(NumServosDefined >= 3);
444  m_ccpm->ccpmServoZChannel->setVisible(NumServosDefined >= 4);
445 
446  // set the visibility of the swashplate angle selection boxes
447  m_ccpm->ccpmServoWLabel_2->setVisible(NumServosDefined >= 1);
448  m_ccpm->ccpmServoXLabel_2->setVisible(NumServosDefined >= 2);
449  m_ccpm->ccpmServoYLabel_2->setVisible(NumServosDefined >= 3);
450  m_ccpm->ccpmServoZLabel_2->setVisible(NumServosDefined >= 4);
451  m_ccpm->ccpmAngleW->setVisible(NumServosDefined >= 1);
452  m_ccpm->ccpmAngleX->setVisible(NumServosDefined >= 2);
453  m_ccpm->ccpmAngleY->setVisible(NumServosDefined >= 3);
454  m_ccpm->ccpmAngleZ->setVisible(NumServosDefined >= 4);
455 
456  m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents();
457  for (int i = 0; i < 6; i++) {
458  m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(
459  i,
460  (m_ccpm->ccpmAdvancedSettingsTable->width()
461  - m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())
462  / 6);
463  }
464 
465  // update UI
466  ccpmSwashplateUpdate();
467 }
468 
469 void ConfigCcpmWidget::ccpmSwashplateRedraw()
470 {
471  double angle[CCPM_MAX_SWASH_SERVOS], CorrectionAngle, x, y, w, h, radius, CenterX, CenterY;
472  int used[CCPM_MAX_SWASH_SERVOS], defined[CCPM_MAX_SWASH_SERVOS], i;
473  QRectF bounds;
474  QRect size;
475  double scale, xscale, yscale;
476 
477  size = m_ccpm->SwashplateImage->rect();
478  xscale = size.width();
479  yscale = size.height();
480  scale = xscale;
481  if (yscale < scale)
482  scale = yscale;
483  scale /= 460.00;
484  m_ccpm->SwashplateImage->resetTransform();
485  m_ccpm->SwashplateImage->scale(scale, scale);
486 
487  size = m_ccpm->SwashLvlSwashplateImage->rect();
488  xscale = size.width();
489  yscale = size.height();
490  scale = xscale;
491  if (yscale < scale)
492  scale = yscale;
493  scale /= 590.00;
494  m_ccpm->SwashLvlSwashplateImage->resetTransform();
495  m_ccpm->SwashLvlSwashplateImage->scale(scale, scale);
496 
497  CorrectionAngle = m_ccpm->ccpmCorrectionAngle->value();
498 
499  CenterX = 200;
500  CenterY = 200;
501 
502  bounds = SwashplateImg->boundingRect();
503 
504  SwashplateImg->setPos(CenterX - bounds.width() / 2, CenterY - bounds.height() / 2);
505 
506  defined[0] = (m_ccpm->ccpmServoWChannel->isEnabled());
507  defined[1] = (m_ccpm->ccpmServoXChannel->isEnabled());
508  defined[2] = (m_ccpm->ccpmServoYChannel->isEnabled());
509  defined[3] = (m_ccpm->ccpmServoZChannel->isEnabled());
510  used[0] = ((m_ccpm->ccpmServoWChannel->currentIndex() > 0)
511  && (m_ccpm->ccpmServoWChannel->isEnabled()));
512  used[1] = ((m_ccpm->ccpmServoXChannel->currentIndex() > 0)
513  && (m_ccpm->ccpmServoXChannel->isEnabled()));
514  used[2] = ((m_ccpm->ccpmServoYChannel->currentIndex() > 0)
515  && (m_ccpm->ccpmServoYChannel->isEnabled()));
516  used[3] = ((m_ccpm->ccpmServoZChannel->currentIndex() > 0)
517  && (m_ccpm->ccpmServoZChannel->isEnabled()));
518  angle[0] = (CorrectionAngle + 180 + m_ccpm->ccpmAngleW->value()) * DEG2RAD;
519  angle[1] = (CorrectionAngle + 180 + m_ccpm->ccpmAngleX->value()) * DEG2RAD;
520  angle[2] = (CorrectionAngle + 180 + m_ccpm->ccpmAngleY->value()) * DEG2RAD;
521  angle[3] = (CorrectionAngle + 180 + m_ccpm->ccpmAngleZ->value()) * DEG2RAD;
522 
523  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
524  radius = 210;
525  x = CenterX - (radius * sin(angle[i])) - 10.00;
526  y = CenterY + (radius * cos(angle[i])) - 10.00;
527  Servos[i]->setPos(x, y);
528  Servos[i]->setVisible(used[i] != 0);
529 
530  radius = 150;
531  bounds = ServosText[i]->boundingRect();
532  x = CenterX - (radius * sin(angle[i])) - bounds.width() / 2;
533  y = CenterY + (radius * cos(angle[i])) - bounds.height() / 2;
534 
535  ServosText[i]->setPos(x, y);
536  ServosText[i]->setVisible(used[i] != 0);
537 
538  if (bounds.width() > bounds.height()) {
539  bounds.setHeight(bounds.width());
540  } else {
541  bounds.setWidth(bounds.height());
542  }
543  x = CenterX - (radius * sin(angle[i])) - bounds.width() / 2;
544  y = CenterY + (radius * cos(angle[i])) - bounds.height() / 2;
545 
546  ServosTextCircles[i]->setRect(bounds);
547  ServosTextCircles[i]->setPos(x, y);
548  ServosTextCircles[i]->setVisible(used[i] != 0);
549 
550  w = SwashLvlSpinBoxes[i]->width() / 2;
551  h = SwashLvlSpinBoxes[i]->height() / 2;
552  radius = (215.00 + w + h);
553  x = CenterX - (radius * sin(angle[i])) - w;
554  y = CenterY + (radius * cos(angle[i])) - h;
555  SwashLvlSpinBoxes[i]->move(m_ccpm->SwashLvlSwashplateImage->mapFromScene(x, y));
556  SwashLvlSpinBoxes[i]->setVisible(used[i] != 0);
557 
558  radius = 220;
559  x = CenterX - (radius * sin(angle[i]));
560  y = CenterY + (radius * cos(angle[i]));
561  ServoLines[i]->setLine(CenterX, CenterY, x, y);
562  ServoLines[i]->setVisible(defined[i] != 0);
563  }
564 
565  // m_ccpm->SwashplateImage->centerOn (CenterX, CenterY);
566 
567  // m_ccpm->SwashplateImage->fitInView(SwashplateImg, Qt::KeepAspectRatio);
568 }
569 
570 void ConfigCcpmWidget::ccpmSwashplateUpdate()
571 {
572  ccpmSwashplateRedraw();
573  SetUIComponentVisibilities();
574  UpdateMixer();
575 }
576 
577 void ConfigCcpmWidget::UpdateMixer()
578 {
579  bool useCCPM;
580  bool useCyclic;
581  int i, j, ThisEnable[6];
582  float CollectiveConstant, PitchConstant, RollConstant, ThisAngle[6];
583  QString Channel;
584 
585  if (throwConfigError(SystemSettings::AIRFRAMETYPE_HELICP))
586  return;
587 
589 
590  useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState);
591  useCyclic = config.heli.ccpmLinkRollState;
592 
593  CollectiveConstant = (float)config.heli.SliderValue0 / 100.00;
594 
595  if (useCCPM) { // cyclic = 1 - collective
596  PitchConstant = 1 - CollectiveConstant;
597  RollConstant = PitchConstant;
598  } else {
599  PitchConstant = (float)config.heli.SliderValue1 / 100.00;
600  ;
601  if (useCyclic) {
602  RollConstant = PitchConstant;
603  } else {
604  RollConstant = (float)config.heli.SliderValue2 / 100.00;
605  ;
606  }
607  }
608 
609  if (config.heli.SwashplateType > 0) { // not advanced settings
610  // get the channel data from the ui
611  MixerChannelData[0] = m_ccpm->ccpmEngineChannel->currentIndex();
612  MixerChannelData[1] = m_ccpm->ccpmTailChannel->currentIndex();
613  MixerChannelData[2] = m_ccpm->ccpmServoWChannel->currentIndex();
614  MixerChannelData[3] = m_ccpm->ccpmServoXChannel->currentIndex();
615  MixerChannelData[4] = m_ccpm->ccpmServoYChannel->currentIndex();
616  MixerChannelData[5] = m_ccpm->ccpmServoZChannel->currentIndex();
617 
618  // get the angle data from the ui
619  ThisAngle[2] = m_ccpm->ccpmAngleW->value();
620  ThisAngle[3] = m_ccpm->ccpmAngleX->value();
621  ThisAngle[4] = m_ccpm->ccpmAngleY->value();
622  ThisAngle[5] = m_ccpm->ccpmAngleZ->value();
623 
624  // get the angle data from the ui
625  ThisEnable[2] = m_ccpm->ccpmServoWChannel->isEnabled();
626  ThisEnable[3] = m_ccpm->ccpmServoXChannel->isEnabled();
627  ThisEnable[4] = m_ccpm->ccpmServoYChannel->isEnabled();
628  ThisEnable[5] = m_ccpm->ccpmServoZChannel->isEnabled();
629 
630  ServosText[0]->setPlainText(QString("%1").arg(MixerChannelData[2]));
631  ServosText[1]->setPlainText(QString("%1").arg(MixerChannelData[3]));
632  ServosText[2]->setPlainText(QString("%1").arg(MixerChannelData[4]));
633  ServosText[3]->setPlainText(QString("%1").arg(MixerChannelData[5]));
634 
635  // go through the user data and update the mixer matrix
636  for (i = 0; i < 6; i++) {
637  if ((MixerChannelData[i] > 0) && ((ThisEnable[i]) || (i < 2))) {
638  m_ccpm->ccpmAdvancedSettingsTable->item(i, 0)->setText(
639  QString("%1").arg(MixerChannelData[i]));
640 
641  // Generate the mixer vector
642  if (i == 0) { // main motor-engine
643  m_ccpm->ccpmAdvancedSettingsTable->item(i, 1)->setText(
644  QString("%1").arg(mixerScale)); // Thrust
645  m_ccpm->ccpmAdvancedSettingsTable->item(i, 2)->setText(
646  QString("%1").arg(0)); // ThrottleCurve2
647  m_ccpm->ccpmAdvancedSettingsTable->item(i, 3)->setText(
648  QString("%1").arg(0)); // Roll
649  m_ccpm->ccpmAdvancedSettingsTable->item(i, 4)->setText(
650  QString("%1").arg(0)); // Pitch
651 
652  if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)
653  == 0)
654  m_ccpm->ccpmAdvancedSettingsTable->item(i, 5)->setText(
655  QString("%1").arg(-mixerScale)); // Yaw
656  else
657  m_ccpm->ccpmAdvancedSettingsTable->item(i, 5)->setText(
658  QString("%1").arg(0)); // Yaw
659  }
660  if (i == 1) { // tailrotor --or-- counter-clockwise motor
661  if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)
662  == 0) {
663  m_ccpm->ccpmAdvancedSettingsTable->item(i, 1)->setText(
664  QString("%1").arg(mixerScale)); // Thrust
665  m_ccpm->ccpmAdvancedSettingsTable->item(i, 5)->setText(
666  QString("%1").arg(mixerScale)); // Yaw
667  } else {
668  m_ccpm->ccpmAdvancedSettingsTable->item(i, 1)->setText(
669  QString("%1").arg(0)); // ThrottleCurve1
670  m_ccpm->ccpmAdvancedSettingsTable->item(i, 5)->setText(
671  QString("%1").arg(mixerScale)); // Yaw
672  }
673 
674  m_ccpm->ccpmAdvancedSettingsTable->item(i, 2)->setText(
675  QString("%1").arg(0)); // ThrottleCurve2
676  m_ccpm->ccpmAdvancedSettingsTable->item(i, 3)->setText(
677  QString("%1").arg(0)); // Roll
678  m_ccpm->ccpmAdvancedSettingsTable->item(i, 4)->setText(
679  QString("%1").arg(0)); // Pitch
680  }
681  if (i > 1) { // Swashplate
682  m_ccpm->ccpmAdvancedSettingsTable->item(i, 1)->setText(
683  QString("%1").arg(0)); // Thrust
684  m_ccpm->ccpmAdvancedSettingsTable->item(i, 2)->setText(QString("%1").arg(
685  (int)(mixerScale * CollectiveConstant))); // ThrottleCurve2
686  m_ccpm->ccpmAdvancedSettingsTable->item(i, 3)->setText(QString("%1").arg(
687  (int)(mixerScale * RollConstant
688  * sin((180 + config.heli.CorrectionAngle + ThisAngle[i])
689  * DEG2RAD)))); // Roll
690  m_ccpm->ccpmAdvancedSettingsTable->item(i, 4)->setText(
691  QString("%1").arg((int)(mixerScale * PitchConstant
692  * cos((config.heli.CorrectionAngle + ThisAngle[i])
693  * DEG2RAD)))); // Pitch
694  m_ccpm->ccpmAdvancedSettingsTable->item(i, 5)->setText(
695  QString("%1").arg(0)); // Yaw
696  }
697  } else {
698  for (j = 0; j < 6; j++)
699  m_ccpm->ccpmAdvancedSettingsTable->item(i, j)->setText(QString("-"));
700  }
701  }
702  } else { // advanced settings
703  for (i = 0; i < 6; i++) {
704  Channel = m_ccpm->ccpmAdvancedSettingsTable->item(i, 0)->text();
705  if (Channel == "-")
706  Channel = QString("9");
707  MixerChannelData[i] = Channel.toInt();
708  }
709  }
710 }
711 
712 SystemSettings::AirframeTypeOptions ConfigCcpmWidget::updateConfigObjects()
713 {
714  SystemSettings::AirframeTypeOptions airframeType = SystemSettings::AIRFRAMETYPE_HELICP;
715 
716  bool useCCPM;
717  bool useCyclic;
718 
719  if (updatingFromHardware == true)
720  return airframeType;
721 
722  updatingFromHardware = true;
723 
724  // get the user options
726 
727  // swashplate config
728  config.heli.SwashplateType = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex() - 1;
729  config.heli.FirstServoIndex = m_ccpm->ccpmSingleServo->currentIndex();
730 
731  // ccpm mixing options
732  config.heli.ccpmCollectivePassthroughState = m_ccpm->ccpmCollectivePassthrough->isChecked();
733  config.heli.ccpmLinkCyclicState = m_ccpm->ccpmLinkCyclic->isChecked();
734  config.heli.ccpmLinkRollState = m_ccpm->ccpmLinkRoll->isChecked();
735  useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState);
736  useCyclic = config.heli.ccpmLinkRollState;
737 
738  // correction angle
739  config.heli.CorrectionAngle = m_ccpm->ccpmCorrectionAngle->value();
740 
741  // update sliders
742  if (useCCPM) {
743  config.heli.SliderValue0 = m_ccpm->ccpmCollectiveSlider->value();
744  } else {
745  config.heli.SliderValue0 = m_ccpm->ccpmCollectiveScale->value();
746  }
747  if (useCyclic) {
748  config.heli.SliderValue1 = m_ccpm->ccpmCyclicScale->value();
749  } else {
750  config.heli.SliderValue1 = m_ccpm->ccpmPitchScale->value();
751  }
752  config.heli.SliderValue2 = m_ccpm->ccpmRollScale->value();
753 
754  // servo assignments
755  config.heli.ServoIndexW = m_ccpm->ccpmServoWChannel->currentIndex();
756  config.heli.ServoIndexX = m_ccpm->ccpmServoXChannel->currentIndex();
757  config.heli.ServoIndexY = m_ccpm->ccpmServoYChannel->currentIndex();
758  config.heli.ServoIndexZ = m_ccpm->ccpmServoZChannel->currentIndex();
759 
760  // throttle
761  config.heli.Throttle = m_ccpm->ccpmEngineChannel->currentIndex();
762  // tail
763  config.heli.Tail = m_ccpm->ccpmTailChannel->currentIndex();
764 
765  SetConfigData(config, SystemSettings::AIRFRAMETYPE_HELICP);
766 
767  updatingFromHardware = false;
768  return airframeType;
769 }
770 
771 SystemSettings::AirframeTypeOptions
772 ConfigCcpmWidget::updateConfigObjectsFromWidgets() // UpdateCCPMOptionsFromUI()
773 {
774  SystemSettings::AirframeTypeOptions airframeType = updateConfigObjects();
775 
776  setMixer();
777 
778  return airframeType;
779 }
780 
781 void ConfigCcpmWidget::refreshAirframeWidgetsValues(
782  SystemSettings::AirframeTypeOptions frameType) // UpdateCCPMUIFromOptions()
783 {
784  Q_UNUSED(frameType);
785 
787 
788  // swashplate config
789  setComboCurrentIndex(m_ccpm->ccpmType,
790  m_ccpm->ccpmType->count() - (config.heli.SwashplateType + 1));
791  setComboCurrentIndex(m_ccpm->ccpmSingleServo, config.heli.FirstServoIndex);
792 
793  // ccpm mixing options
794  m_ccpm->ccpmCollectivePassthrough->setChecked(config.heli.ccpmCollectivePassthroughState);
795  m_ccpm->ccpmLinkCyclic->setChecked(config.heli.ccpmLinkCyclicState);
796  m_ccpm->ccpmLinkRoll->setChecked(config.heli.ccpmLinkRollState);
797 
798  // correction angle
799  m_ccpm->ccpmCorrectionAngle->setValue(config.heli.CorrectionAngle);
800 
801  // update sliders
802  m_ccpm->ccpmCollectiveScale->setValue(config.heli.SliderValue0);
803  m_ccpm->ccpmCollectiveScaleBox->setValue(config.heli.SliderValue0);
804  m_ccpm->ccpmCyclicScale->setValue(config.heli.SliderValue1);
805  m_ccpm->ccpmCyclicScaleBox->setValue(config.heli.SliderValue1);
806  m_ccpm->ccpmPitchScale->setValue(config.heli.SliderValue1);
807  m_ccpm->ccpmPitchScaleBox->setValue(config.heli.SliderValue1);
808  m_ccpm->ccpmRollScale->setValue(config.heli.SliderValue2);
809  m_ccpm->ccpmRollScaleBox->setValue(config.heli.SliderValue2);
810  m_ccpm->ccpmCollectiveSlider->setValue(config.heli.SliderValue0);
811  m_ccpm->ccpmCollectivespinBox->setValue(config.heli.SliderValue0);
812 
813  // servo assignments
814  setComboCurrentIndex(m_ccpm->ccpmServoWChannel, config.heli.ServoIndexW);
815  setComboCurrentIndex(m_ccpm->ccpmServoXChannel, config.heli.ServoIndexX);
816  setComboCurrentIndex(m_ccpm->ccpmServoYChannel, config.heli.ServoIndexY);
817  setComboCurrentIndex(m_ccpm->ccpmServoZChannel, config.heli.ServoIndexZ);
818 
819  // throttle
820  setComboCurrentIndex(m_ccpm->ccpmEngineChannel, config.heli.Throttle);
821  // tail
822  setComboCurrentIndex(m_ccpm->ccpmTailChannel, config.heli.Tail);
823 
824  getMixer();
825 }
826 
827 void ConfigCcpmWidget::SetUIComponentVisibilities()
828 {
829  m_ccpm->ccpmRevoMixingBox->setVisible(0);
830 
831  m_ccpm->ccpmPitchMixingBox->setVisible(!m_ccpm->ccpmCollectivePassthrough->isChecked()
832  && m_ccpm->ccpmLinkCyclic->isChecked());
833 
834  m_ccpm->ccpmCollectiveScalingBox->setVisible(m_ccpm->ccpmCollectivePassthrough->isChecked()
835  || !m_ccpm->ccpmLinkCyclic->isChecked());
836 
837  m_ccpm->ccpmLinkCyclic->setVisible(!m_ccpm->ccpmCollectivePassthrough->isChecked());
838 
839  m_ccpm->ccpmCyclicScalingBox->setVisible(
840  (m_ccpm->ccpmCollectivePassthrough->isChecked() || !m_ccpm->ccpmLinkCyclic->isChecked())
841  && m_ccpm->ccpmLinkRoll->isChecked());
842 
843  if (!m_ccpm->ccpmCollectivePassthrough->checkState() && m_ccpm->ccpmLinkCyclic->isChecked()) {
844  m_ccpm->ccpmPitchScalingBox->setVisible(0);
845  m_ccpm->ccpmRollScalingBox->setVisible(0);
846  m_ccpm->ccpmLinkRoll->setVisible(0);
847 
848  } else {
849  m_ccpm->ccpmPitchScalingBox->setVisible(!m_ccpm->ccpmLinkRoll->isChecked());
850  m_ccpm->ccpmRollScalingBox->setVisible(!m_ccpm->ccpmLinkRoll->isChecked());
851  m_ccpm->ccpmLinkRoll->setVisible(1);
852  }
853 }
858 {
859  if (SwashLvlConfigurationInProgress)
860  return;
861  if (updatingToHardware)
862  return;
863 
864  updatingFromHardware = true;
865 
866  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
867  Q_ASSERT(mixerSettings);
868 
869  // set the airframe type
870  QPointer<VehicleConfig> vconfig = new VehicleConfig();
871  QList<double> curveValues;
872 
873  vconfig->getThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE2,
874  &curveValues);
875  // is at least one of the curve values != 0?
876  if (vconfig->isValidThrottleCurve(&curveValues)) {
877  m_ccpm->PitchCurve->setCurve(&curveValues);
878  } else {
879  m_ccpm->PitchCurve->ResetCurve();
880  }
881 
882  updatingFromHardware = false;
883 
884  ccpmSwashplateUpdate();
885 }
886 
891 {
892  int i, j;
893 
894  if (SwashLvlConfigurationInProgress)
895  return;
896  if (updatingToHardware == true)
897  return;
898 
899  updatingToHardware = true;
900 
901  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
902  Q_ASSERT(mixerSettings);
903  MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();
904 
905  UpdateMixer();
906 
907  // Set up some helper pointers
908  decltype(&mixerSettingsData.Mixer1Vector[0]) mixers[] = {
909  mixerSettingsData.Mixer1Vector, mixerSettingsData.Mixer2Vector,
910  mixerSettingsData.Mixer3Vector, mixerSettingsData.Mixer4Vector,
911  mixerSettingsData.Mixer5Vector, mixerSettingsData.Mixer6Vector,
912  mixerSettingsData.Mixer7Vector, mixerSettingsData.Mixer8Vector,
913  mixerSettingsData.Mixer9Vector, mixerSettingsData.Mixer10Vector
914  };
915 
916  decltype(&mixerSettingsData.Mixer1Type) mixerTypes[] = {
917  &mixerSettingsData.Mixer1Type, &mixerSettingsData.Mixer2Type, &mixerSettingsData.Mixer3Type,
918  &mixerSettingsData.Mixer4Type, &mixerSettingsData.Mixer5Type, &mixerSettingsData.Mixer6Type,
919  &mixerSettingsData.Mixer7Type, &mixerSettingsData.Mixer8Type, &mixerSettingsData.Mixer9Type,
920  &mixerSettingsData.Mixer10Type
921  };
922 
923  // reset all to Disabled
924  for (i = 0; i < 8; i++)
925  *(mixerTypes[i]) = 0;
926 
927  // go through the user data and update the mixer matrix
928  for (i = 0; i < 6; i++) {
929  if (MixerChannelData[i] > 0
930  && (uint)MixerChannelData[i] < sizeof(mixerTypes) / sizeof(mixerTypes[0])) {
931  // Set the mixer type. If Coax, then first two are motors. Otherwise, only first is
932  // motor
933  if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
934  *(mixerTypes[MixerChannelData[i] - 1]) =
935  i > 1 ? MixerSettings::MIXER1TYPE_SERVO : MixerSettings::MIXER1TYPE_MOTOR;
936  } else {
937  *(mixerTypes[MixerChannelData[i] - 1]) =
938  i > 0 ? MixerSettings::MIXER1TYPE_SERVO : MixerSettings::MIXER1TYPE_MOTOR;
939  }
940 
941  // Configure the vector
942  for (j = 0; j < 5; j++)
943  mixers[MixerChannelData[i] - 1][j] =
944  m_ccpm->ccpmAdvancedSettingsTable->item(i, j + 1)
945  ->text()
946  .toInt(); // TODO: Fix crash here
947  }
948  }
949 
950  // get the user data for the curve into the mixer settings
951  QList<double> curve2 = m_ccpm->PitchCurve->getCurve();
952  for (i = 0; i < 5; i++) {
953  mixerSettingsData.ThrottleCurve2[i] = curve2.at(i);
954  }
955 
956  // mapping of collective input to curve 2...
957  // MixerSettings.Curve2Source =
958  // Throttle,Roll,Pitch,Yaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5
959  // check if we are using throttle or directly from a channel...
960  if (m_ccpm->ccpmCollectivePassthrough->isChecked())
961  mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_COLLECTIVE;
962  else
963  mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_THROTTLE;
964 
965  mixerSettings->setData(mixerSettingsData);
966  mixerSettings->updated();
967  updatingToHardware = false;
968 }
969 
974 {
975  if (SwashLvlConfigurationInProgress)
976  return;
977  ShowDisclaimer(0);
978  // Send update so that the latest value is saved
979  // sendccpmUpdate();
980  setMixer();
981 
982  MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
983  Q_ASSERT(mixerSettings);
984 
985  saveObjectToSD(mixerSettings);
986 }
987 
988 void ConfigCcpmWidget::resizeEvent(QResizeEvent *event)
989 {
990  Q_UNUSED(event);
991  // Make the custom table columns autostretch:
992  m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents();
993  for (int i = 0; i < 6; i++) {
994  m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(
995  i,
996  (m_ccpm->ccpmAdvancedSettingsTable->width()
997  - m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())
998  / 6);
999  }
1000  ccpmSwashplateRedraw();
1001 }
1002 void ConfigCcpmWidget::showEvent(QShowEvent *event)
1003 {
1004  Q_UNUSED(event)
1005  m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents();
1006  for (int i = 0; i < 6; i++) {
1007  m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(
1008  i,
1009  (m_ccpm->ccpmAdvancedSettingsTable->width()
1010  - m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())
1011  / 6);
1012  }
1013  ccpmSwashplateRedraw();
1014 }
1015 
1016 void ConfigCcpmWidget::SwashLvlStartButtonPressed()
1017 {
1018  QMessageBox msgBox(QMessageBox::Information, tr("Swashplate Leveling Routine"),
1019  tr("<b>You are about to start the Swashplate levelling routine.</b><p>This process will start "
1020  "by downloading the current configuration from the GCS to the OP hardware and will adjust "
1021  "your configuration at various stages.<p>The final state of your system should match the "
1022  "current configuration in the GCS config gadget.<p>Please ensure all ccpm settings in the "
1023  "GCS are correct before continuing.<p>If this process is interrupted, then the state of "
1024  "your OP board may not match the GCS configuration.<p><i>After completing this process, "
1025  "please check all settings before attempting to fly.</i><p><font color=red><b>Please "
1026  "disconnect your motor to ensure it will not spin up.</b></font><p><hr><i>Do you wish to "
1027  "proceed?</i>"), QMessageBox::Yes | QMessageBox::Cancel, this);
1028 
1029  msgBox.setDefaultButton(QMessageBox::Cancel);
1030  int ret = msgBox.exec();
1031 
1032  UAVObjectField *MinField;
1033  UAVObjectField *NeutralField;
1034  UAVObjectField *MaxField;
1035  UAVDataObject *obj;
1037  UAVObjectManager *objManager;
1038 
1039  switch (ret) {
1040  case QMessageBox::Yes:
1041  // Yes was clicked
1042  SwashLvlState = 0;
1043  // remove Flight control of ActuatorCommand
1044  enableSwashplateLevellingControl(true);
1045 
1046  m_ccpm->SwashLvlStartButton->setEnabled(false);
1047  m_ccpm->SwashLvlNextButton->setEnabled(true);
1048  m_ccpm->SwashLvlCancelButton->setEnabled(true);
1049  m_ccpm->SwashLvlFinishButton->setEnabled(false);
1050  // clear status check boxes
1051  m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
1052  m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
1053  m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
1054  m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
1055 
1056  // download the current settings to the OP hw
1057  // sendccpmUpdate();
1058  setMixer();
1059 
1060  // change control mode to gcs control / disarmed
1061  // set throttle to 0
1062 
1063  // save off the old ActuatorSettings for the swashplate servos
1064  pm = ExtensionSystem::PluginManager::instance();
1065  objManager = pm->getObject<UAVObjectManager>();
1066 
1067  // Get the channel assignements:
1068  obj = dynamic_cast<UAVDataObject *>(objManager->getObject(QString("ActuatorSettings")));
1069  Q_ASSERT(obj);
1070  // obj->requestUpdate();
1071  MinField = obj->getField(QString("ChannelMin"));
1072  NeutralField = obj->getField(QString("ChannelNeutral"));
1073  MaxField = obj->getField(QString("ChannelMax"));
1074 
1075  // channel assignments
1076  oldSwashLvlConfiguration.ServoChannels[0] = m_ccpm->ccpmServoWChannel->currentIndex();
1077  oldSwashLvlConfiguration.ServoChannels[1] = m_ccpm->ccpmServoXChannel->currentIndex();
1078  oldSwashLvlConfiguration.ServoChannels[2] = m_ccpm->ccpmServoYChannel->currentIndex();
1079  oldSwashLvlConfiguration.ServoChannels[3] = m_ccpm->ccpmServoZChannel->currentIndex();
1080 
1081  // if servos are used
1082  oldSwashLvlConfiguration.Used[0] = (m_ccpm->ccpmServoWChannel->currentIndex() > 0);
1083  oldSwashLvlConfiguration.Used[1] = (m_ccpm->ccpmServoXChannel->currentIndex() > 0);
1084  oldSwashLvlConfiguration.Used[2] = (m_ccpm->ccpmServoYChannel->currentIndex() > 0);
1085  oldSwashLvlConfiguration.Used[3] = (m_ccpm->ccpmServoZChannel->currentIndex() > 0);
1086 
1087  // all the channel spinboxes have "None" as index zero; thus, all channels will be off by 1
1088  for (uint8_t i = 0; i < CCPM_MAX_SWASH_SERVOS; ++i) {
1089  // if a channel is selected, shift its value into the correct range [0,N-1] instead of
1090  // [1,N]
1091  if (oldSwashLvlConfiguration.ServoChannels[i] > 0)
1092  oldSwashLvlConfiguration.ServoChannels[i]--;
1093  }
1094 
1095  // min,neutral,max values for the servos
1096  for (uint8_t i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1097  oldSwashLvlConfiguration.Min[i] =
1098  MinField->getValue(oldSwashLvlConfiguration.ServoChannels[i]).toInt();
1099  oldSwashLvlConfiguration.Neutral[i] =
1100  NeutralField->getValue(oldSwashLvlConfiguration.ServoChannels[i]).toInt();
1101  oldSwashLvlConfiguration.Max[i] =
1102  MaxField->getValue(oldSwashLvlConfiguration.ServoChannels[i]).toInt();
1103  }
1104 
1105  // copy to new Actuator settings.
1106  memcpy(&newSwashLvlConfiguration, &oldSwashLvlConfiguration,
1108 
1109  // goto the first step
1110  SwashLvlNextButtonPressed();
1111  break;
1112  case QMessageBox::Cancel:
1113  // Cancel was clicked
1114  SwashLvlState = 0;
1115  // restore Flight control of ActuatorCommand
1116  enableSwashplateLevellingControl(false);
1117 
1118  m_ccpm->SwashLvlStartButton->setEnabled(true);
1119  m_ccpm->SwashLvlNextButton->setEnabled(false);
1120  m_ccpm->SwashLvlCancelButton->setEnabled(false);
1121  m_ccpm->SwashLvlFinishButton->setEnabled(false);
1122  break;
1123  default:
1124  // should never be reached
1125  break;
1126  }
1127 }
1128 void ConfigCcpmWidget::SwashLvlNextButtonPressed()
1129 {
1130  // ShowDisclaimer(2);
1131  SwashLvlState++;
1132  int i;
1133 
1134  switch (SwashLvlState) {
1135  case 0:
1136  break;
1137  case 1: // Neutral levelling
1138  m_ccpm->SwashLvlStepList->setCurrentRow(0);
1139  // set spin boxes and swashplate servos to Neutral values
1140  setSwashplateLevel(50);
1141  // disable position slider
1142  m_ccpm->SwashLvlPositionSlider->setEnabled(false);
1143  m_ccpm->SwashLvlPositionSpinBox->setEnabled(false);
1144  // set position slider to 50%
1145  m_ccpm->SwashLvlPositionSlider->setValue(50);
1146  m_ccpm->SwashLvlPositionSpinBox->setValue(50);
1147  // connect spinbox signals to slots and ebnable them
1148  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1149  connect(SwashLvlSpinBoxes[i], SIGNAL(valueChanged(int)), this,
1150  SLOT(SwashLvlSpinBoxChanged(int)));
1151  SwashLvlSpinBoxes[i]->setEnabled(true);
1152  }
1153  // issue user instructions
1154  m_ccpm->SwashLvlStepInstruction->setHtml(
1155  "<h2>Neutral levelling</h2><p>Using adjustment of:<ul><li>servo horns<li>link lengths "
1156  "and<li>Neutral timing spinboxes to the right</ul><br>ensure that the swashplate is in "
1157  "the center of desired travel range and is level.");
1158  break;
1159  case 2: // Max levelling
1160  // check Neutral status as complete
1161  m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Checked);
1162  m_ccpm->SwashLvlStepList->setCurrentRow(1);
1163  // set spin boxes and swashplate servos to Max values
1164  setSwashplateLevel(100);
1165  // set position slider to 100%
1166  m_ccpm->SwashLvlPositionSlider->setValue(100);
1167  m_ccpm->SwashLvlPositionSpinBox->setValue(100);
1168  // issue user instructions
1169  m_ccpm->SwashLvlStepInstruction->setText("<h2>Max levelling</h2><p>Using adjustment "
1170  "of:<ul><li>Max timing spinboxes to the right "
1171  "ONLY</ul><br>ensure that the swashplate is at "
1172  "the top of desired travel range and is level.");
1173  break;
1174  case 3: // Min levelling
1175  // check Max status as complete
1176  m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Checked);
1177  m_ccpm->SwashLvlStepList->setCurrentRow(2);
1178  // set spin boxes and swashplate servos to Min values
1179  setSwashplateLevel(0);
1180  // set position slider to 0%
1181  m_ccpm->SwashLvlPositionSlider->setValue(0);
1182  m_ccpm->SwashLvlPositionSpinBox->setValue(0);
1183  // issue user instructions
1184  m_ccpm->SwashLvlStepInstruction->setText(
1185  "<h2>Min levelling</h2><p>Using adjustment of:<ul><li>Min timing spinboxes to the "
1186  "right ONLY</ul><br>ensure that the swashplate is at the bottom of desired travel "
1187  "range and is level.");
1188  break;
1189  case 4: // levelling verification
1190  // check Min status as complete
1191  m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Checked);
1192  m_ccpm->SwashLvlStepList->setCurrentRow(3);
1193  // enable position slider
1194  m_ccpm->SwashLvlPositionSlider->setEnabled(true);
1195  m_ccpm->SwashLvlPositionSpinBox->setEnabled(true);
1196  // make heli respond to slider movement
1197  connect(m_ccpm->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this,
1198  SLOT(setSwashplateLevel(int)));
1199  // disable spin boxes
1200  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1201  SwashLvlSpinBoxes[i]->setEnabled(false);
1202  }
1203 
1204  // issue user instructions
1205  m_ccpm->SwashLvlStepInstruction->setText("<h2>levelling verification</h2><p>Adjust the "
1206  "slider to the right over it's full range and "
1207  "observe the swashplate motion. It should remain "
1208  "level over the entire range of travel.");
1209  break;
1210  case 5: // levelling complete
1211  // check verify status as complete
1212  m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Checked);
1213  // issue user instructions
1214  m_ccpm->SwashLvlStepInstruction->setText(
1215  "<h2>levelling complete</h2><p>Press the Finish button to save these settings to the "
1216  "SD card<p>Press the cancel button to return to the pre-levelling settings");
1217  // disable position slider
1218  m_ccpm->SwashLvlPositionSlider->setEnabled(false);
1219  m_ccpm->SwashLvlPositionSpinBox->setEnabled(false);
1220  // disconnect levelling slots from signals
1221  disconnect(m_ccpm->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this,
1222  SLOT(setSwashplateLevel(int)));
1223  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1224  disconnect(SwashLvlSpinBoxes[i], SIGNAL(valueChanged(int)), this,
1225  SLOT(SwashLvlSpinBoxChanged(int)));
1226  }
1227 
1228  m_ccpm->SwashLvlStartButton->setEnabled(false);
1229  m_ccpm->SwashLvlNextButton->setEnabled(false);
1230  m_ccpm->SwashLvlCancelButton->setEnabled(true);
1231  m_ccpm->SwashLvlFinishButton->setEnabled(true);
1232 
1233  default:
1234  // restore collective/cyclic setting
1235  // restore pitch curve
1236  // clear spin boxes
1237  // change control mode to gcs control (OFF) / disarmed
1238  // issue user confirmation
1239  break;
1240  }
1241 }
1242 void ConfigCcpmWidget::SwashLvlCancelButtonPressed()
1243 {
1244  int i;
1245  SwashLvlState = 0;
1246 
1247  UAVObjectField *MinField;
1248  UAVObjectField *NeutralField;
1249  UAVObjectField *MaxField;
1250 
1251  m_ccpm->SwashLvlStartButton->setEnabled(true);
1252  m_ccpm->SwashLvlNextButton->setEnabled(false);
1253  m_ccpm->SwashLvlCancelButton->setEnabled(false);
1254  m_ccpm->SwashLvlFinishButton->setEnabled(false);
1255 
1256  m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
1257  m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
1258  m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
1259  m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
1260 
1261  // restore old Actuator Settings
1262  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1263  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
1264  UAVDataObject *obj =
1265  dynamic_cast<UAVDataObject *>(objManager->getObject(QString("ActuatorSettings")));
1266  Q_ASSERT(obj);
1267  // update settings to match our changes.
1268  MinField = obj->getField(QString("ChannelMin"));
1269  NeutralField = obj->getField(QString("ChannelNeutral"));
1270  MaxField = obj->getField(QString("ChannelMax"));
1271 
1272  // min,neutral,max values for the servos
1273  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1274  MinField->setValue(oldSwashLvlConfiguration.Min[i],
1275  oldSwashLvlConfiguration.ServoChannels[i]);
1276  NeutralField->setValue(oldSwashLvlConfiguration.Neutral[i],
1277  oldSwashLvlConfiguration.ServoChannels[i]);
1278  MaxField->setValue(oldSwashLvlConfiguration.Max[i],
1279  oldSwashLvlConfiguration.ServoChannels[i]);
1280  }
1281 
1282  obj->updated();
1283 
1284  // restore Flight control of ActuatorCommand
1285  enableSwashplateLevellingControl(false);
1286 
1287  m_ccpm->SwashLvlStepInstruction->setText(
1288  "<h2>Levelling Cancelled</h2><p>Previous settings have been restored.");
1289 }
1290 
1291 void ConfigCcpmWidget::SwashLvlFinishButtonPressed()
1292 {
1293  int i;
1294 
1295  UAVObjectField *MinField;
1296  UAVObjectField *NeutralField;
1297  UAVObjectField *MaxField;
1298 
1299  m_ccpm->SwashLvlStartButton->setEnabled(true);
1300  m_ccpm->SwashLvlNextButton->setEnabled(false);
1301  m_ccpm->SwashLvlCancelButton->setEnabled(false);
1302  m_ccpm->SwashLvlFinishButton->setEnabled(false);
1303 
1304  // save new Actuator Settings to memory and SD card
1305  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1306  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
1307  UAVDataObject *obj =
1308  dynamic_cast<UAVDataObject *>(objManager->getObject(QString("ActuatorSettings")));
1309  Q_ASSERT(obj);
1310  // update settings to match our changes.
1311  MinField = obj->getField(QString("ChannelMin"));
1312  NeutralField = obj->getField(QString("ChannelNeutral"));
1313  MaxField = obj->getField(QString("ChannelMax"));
1314 
1315  // min,neutral,max values for the servos
1316  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1317  MinField->setValue(newSwashLvlConfiguration.Min[i],
1318  newSwashLvlConfiguration.ServoChannels[i]);
1319  NeutralField->setValue(newSwashLvlConfiguration.Neutral[i],
1320  newSwashLvlConfiguration.ServoChannels[i]);
1321  MaxField->setValue(newSwashLvlConfiguration.Max[i],
1322  newSwashLvlConfiguration.ServoChannels[i]);
1323  }
1324 
1325  obj->updated();
1326  saveObjectToSD(obj);
1327 
1328  // restore Flight control of ActuatorCommand
1329  enableSwashplateLevellingControl(false);
1330 
1331  m_ccpm->SwashLvlStepInstruction->setText(
1332  "<h2>Levelling Completed</h2><p>New settings have been saved to the SD card");
1333 
1334  ShowDisclaimer(0);
1335  // ShowDisclaimer(2);
1336 }
1337 
1338 int ConfigCcpmWidget::ShowDisclaimer(int messageID)
1339 {
1340  QMessageBox msgBox;
1341  msgBox.setText("<font color=red><h1>Warning!!!</h2></font>");
1342  int ret;
1343  switch (messageID) {
1344  case 0:
1345  // Basic disclaimer
1346  msgBox.setInformativeText("<h2>This code has many configurations.</h2><p>Please double "
1347  "check all settings before attempting flight!");
1348  msgBox.setStandardButtons(QMessageBox::Ok);
1349  msgBox.setDefaultButton(QMessageBox::Ok);
1350  msgBox.setIcon(QMessageBox::Information);
1351  ret = msgBox.exec();
1352  return 0;
1353  break;
1354  case 1:
1355  // Not Tested disclaimer
1356  msgBox.setInformativeText("<h2>The CCPM mixer code needs more testing!</h2><p><font "
1357  "color=red>Use it at your own risk!</font><p>Do you wish to "
1358  "continue?");
1359  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
1360  msgBox.setDefaultButton(QMessageBox::Cancel);
1361  msgBox.setIcon(QMessageBox::Warning);
1362  ret = msgBox.exec();
1363  switch (ret) {
1364  case QMessageBox::Cancel:
1365  return -1;
1366  case QMessageBox::Yes:
1367  return 0;
1368  }
1369  break;
1370  case 2:
1371  // DO NOT use
1372  msgBox.setInformativeText("<h2>The CCPM swashplate levelling code is NOT "
1373  "complete!</h2><p><font color=red>DO NOT use it for "
1374  "flight!</font>");
1375  msgBox.setStandardButtons(QMessageBox::Ok);
1376  msgBox.setDefaultButton(QMessageBox::Ok);
1377  msgBox.setIcon(QMessageBox::Critical);
1378  ret = msgBox.exec();
1379  return 0;
1380  break;
1381  default:
1382  // should never be reached
1383  break;
1384  }
1385  return -1;
1386 }
1387 
1392 void ConfigCcpmWidget::enableSwashplateLevellingControl(bool state)
1393 {
1394  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
1395  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
1396 
1397  UAVDataObject *obj =
1398  dynamic_cast<UAVDataObject *>(objManager->getObject(QString("ActuatorCommand")));
1399  UAVObject::Metadata mdata = obj->getMetadata();
1400  if (state) {
1401  SwashLvlaccInitialData = mdata;
1404  UAVObject::SetGcsTelemetryAcked(mdata, false);
1406  mdata.gcsTelemetryUpdatePeriod = 100;
1407  SwashLvlConfigurationInProgress = 1;
1408  m_ccpm->TabObject->setTabEnabled(0, 0);
1409  m_ccpm->TabObject->setTabEnabled(2, 0);
1410  m_ccpm->TabObject->setTabEnabled(3, 0);
1411  m_ccpm->ccpmType->setEnabled(0);
1412  } else {
1413  mdata = SwashLvlaccInitialData; // Restore metadata
1414  SwashLvlConfigurationInProgress = 0;
1415 
1416  m_ccpm->TabObject->setTabEnabled(0, 1);
1417  m_ccpm->TabObject->setTabEnabled(2, 1);
1418  m_ccpm->TabObject->setTabEnabled(3, 1);
1419  m_ccpm->ccpmType->setEnabled(1);
1420  }
1421  obj->setMetadata(mdata);
1422 }
1423 
1429 void ConfigCcpmWidget::setSwashplateLevel(int percent)
1430 {
1431  if (percent < 0)
1432  return; // -1;
1433  if (percent > 100)
1434  return; // -1;
1435  if (SwashLvlConfigurationInProgress != 1)
1436  return; // -1;
1437  int i;
1438  double value = 0;
1439  double level = ((double)percent / 50.00) - 1.00;
1440 
1441  SwashLvlServoInterlock = 1;
1442 
1443  ActuatorCommand *actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
1444  ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
1445 
1446  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1447  // don't do anything for unused channels (set to "None")
1448  if (newSwashLvlConfiguration.Used[i] == 0)
1449  continue;
1450 
1451  if (level == 0)
1452  value = newSwashLvlConfiguration.Neutral[i];
1453  else if (level > 0)
1454  value = (newSwashLvlConfiguration.Max[i] - newSwashLvlConfiguration.Neutral[i]) * level
1455  + newSwashLvlConfiguration.Neutral[i];
1456  else if (level < 0)
1457  value = (newSwashLvlConfiguration.Neutral[i] - newSwashLvlConfiguration.Min[i]) * level
1458  + newSwashLvlConfiguration.Neutral[i];
1459 
1460  actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
1461  SwashLvlSpinBoxes[i]->setValue(value);
1462  }
1463 
1464  actuatorCommand->setData(actuatorCommandData);
1465  actuatorCommand->updated();
1466 
1467  SwashLvlServoInterlock = 0;
1468 
1469  return;
1470 }
1471 
1472 void ConfigCcpmWidget::SwashLvlSpinBoxChanged(int value)
1473 {
1474  Q_UNUSED(value);
1475  int i;
1476  if (SwashLvlServoInterlock == 1)
1477  return;
1478 
1479  ActuatorCommand *actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
1480  ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
1481 
1482  for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
1483  // don't do anything for unused channels (set to "None")
1484  if (newSwashLvlConfiguration.Used[i] == 0)
1485  continue;
1486 
1487  value = SwashLvlSpinBoxes[i]->value();
1488 
1489  switch (SwashLvlState) {
1490  case 1: // Neutral levelling
1491  newSwashLvlConfiguration.Neutral[i] = value;
1492  break;
1493  case 2: // Max levelling
1494  newSwashLvlConfiguration.Max[i] = value;
1495  break;
1496  case 3: // Min levelling
1497  newSwashLvlConfiguration.Min[i] = value;
1498  break;
1499  case 4: // levelling verification
1500  break;
1501  case 5: // levelling complete
1502  break;
1503  default:
1504  break;
1505  }
1506 
1507  actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
1508  }
1509 
1510  actuatorCommand->setData(actuatorCommandData);
1511  actuatorCommand->updated();
1512 
1513  return;
1514 }
1515 
1520 bool ConfigCcpmWidget::throwConfigError(SystemSettings::AirframeTypeOptions airframeType)
1521 {
1522  Q_UNUSED(airframeType);
1523 
1524  bool error = false;
1525 
1526  if ((m_ccpm->ccpmServoWChannel->currentIndex() == 0)
1527  && (m_ccpm->ccpmServoWChannel->isEnabled())) {
1528  m_ccpm->ccpmServoWLabel->setText("<font color=red>" + m_ccpm->ccpmServoWLabel->text()
1529  + "</font>");
1530  error = true;
1531  } else {
1532  m_ccpm->ccpmServoWLabel->setText(QTextEdit(m_ccpm->ccpmServoWLabel->text()).toPlainText());
1533  }
1534 
1535  if ((m_ccpm->ccpmServoXChannel->currentIndex() == 0)
1536  && (m_ccpm->ccpmServoXChannel->isEnabled())) {
1537  m_ccpm->ccpmServoXLabel->setText("<font color=red>" + m_ccpm->ccpmServoXLabel->text()
1538  + "</font>");
1539  error = true;
1540  } else {
1541  m_ccpm->ccpmServoXLabel->setText(QTextEdit(m_ccpm->ccpmServoXLabel->text()).toPlainText());
1542  }
1543 
1544  if ((m_ccpm->ccpmServoYChannel->currentIndex() == 0)
1545  && (m_ccpm->ccpmServoYChannel->isEnabled())) {
1546  m_ccpm->ccpmServoYLabel->setText("<font color=red>" + m_ccpm->ccpmServoYLabel->text()
1547  + "</font>");
1548  error = true;
1549  } else {
1550  m_ccpm->ccpmServoYLabel->setText(QTextEdit(m_ccpm->ccpmServoYLabel->text()).toPlainText());
1551  }
1552 
1553  if ((m_ccpm->ccpmServoZChannel->currentIndex() == 0)
1554  && (m_ccpm->ccpmServoZChannel->isEnabled())) {
1555  m_ccpm->ccpmServoZLabel->setText("<font color=red>" + m_ccpm->ccpmServoZLabel->text()
1556  + "</font>");
1557  error = true;
1558  } else {
1559  m_ccpm->ccpmServoZLabel->setText(QTextEdit(m_ccpm->ccpmServoZLabel->text()).toPlainText());
1560  }
1561 
1562  if ((m_ccpm->ccpmEngineChannel->currentIndex() == 0)
1563  && (m_ccpm->ccpmEngineChannel->isEnabled())) {
1564  m_ccpm->ccpmEngineLabel->setText("<font color=red>" + m_ccpm->ccpmEngineLabel->text()
1565  + "</font>");
1566  } else {
1567  m_ccpm->ccpmEngineLabel->setText(QTextEdit(m_ccpm->ccpmEngineLabel->text()).toPlainText());
1568  }
1569 
1570  if ((m_ccpm->ccpmTailChannel->currentIndex() == 0) && (m_ccpm->ccpmTailChannel->isEnabled())) {
1571  m_ccpm->ccpmTailLabel->setText("<font color=red>" + m_ccpm->ccpmTailLabel->text()
1572  + "</font>");
1573  error = true;
1574  } else {
1575  m_ccpm->ccpmTailLabel->setText(QTextEdit(m_ccpm->ccpmTailLabel->text()).toPlainText());
1576  }
1577 
1578  return error;
1579 }
VehicleConfig(QWidget *parent=nullptr)
int Max[CCPM_MAX_SWASH_SERVOS]
int Used[CCPM_MAX_SWASH_SERVOS]
QStringList mixerTypes
int Neutral[CCPM_MAX_SWASH_SERVOS]
ConfigCcpmWidget(QWidget *parent=nullptr)
DEG2RAD
Definition: OPPlots.m:107
static void SetFlightAccess(Metadata &meta, AccessMode mode)
Definition: uavobject.cpp:387
static void SetConfigData(GUIConfigDataUnion configData, SystemSettings::AirframeTypeOptions vehicle)
static GUIConfigDataUnion GetConfigData()
int ServoChannels[CCPM_MAX_SWASH_SERVOS]
Core plugin system that manages the plugins, their life cycle and their registered objects...
Definition: pluginmanager.h:53
QVariant getValue(int index=0) const
static void SetGcsTelemetryAcked(Metadata &meta, quint8 val)
Definition: uavobject.cpp:447
for i
Definition: OPPlots.m:140
void showEvent(QShowEvent *event)
static void SetFlightTelemetryUpdateMode(Metadata &meta, UpdateMode val)
Definition: uavobject.cpp:468
void setValue(const QVariant &data, int index=0)
void resizeEvent(QResizeEvent *event)
QStringList channelNames
void saveObjectToSD(UAVObject *obj)
heliGUISettingsStruct heli
Metadata getMetadata()
else error('Your technical computing program does not support file choosers.Please input the file name in the argument. ') end elseif nargin >0 logfile
x
Definition: OPPlots.m:100
static void SetGcsTelemetryUpdateMode(Metadata &meta, UpdateMode val)
Definition: uavobject.cpp:490
int Min[CCPM_MAX_SWASH_SERVOS]
UAVObject * getObject(const QString &name, quint32 instId=0)
UAVObjectField * getField(const QString &objName, const QString &fieldName, quint32 instId=0)
getField Get a UAV Object field Success is asserted so there is no need to do this again in the calle...
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)
y
Definition: OPPlots.m:101