dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
gcscontrolgadget.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 "gcscontrol.h"
27 #include "gcscontrolgadget.h"
28 #include "gcscontrolgadgetwidget.h"
32 #include "uavobjects/uavobject.h"
33 #include <QDebug>
34 
35 #define JOYSTICK_UPDATE_RATE 50
36 
37 GCSControlGadget::GCSControlGadget(QString classId, GCSControlGadgetWidget *widget, QWidget *parent,
38  QObject *plugin)
39  : IUAVGadget(classId, parent)
40  , m_widget(widget)
41  , controlsMode(0)
42 {
43  connect(getManualControlCommand(), &UAVObject::objectUpdated, this,
45  connect(widget, &GCSControlGadgetWidget::sticksChanged, this,
47  connect(widget, &GCSControlGadgetWidget::controlEnabled, this,
49  connect(this, &GCSControlGadget::sticksChangedRemotely, widget,
53 
54  manualControlCommandUpdated(getManualControlCommand());
55 
56  joystickTime.start();
57 
58 #if defined(USE_SDL)
59  GCSControl *pl = dynamic_cast<GCSControl *>(plugin);
60  connect(pl->sdlGamepad, SIGNAL(gamepads(quint8)), this, SLOT(gamepads(quint8)));
61  connect(pl->sdlGamepad, SIGNAL(buttonState(ButtonNumber, bool)), this,
62  SLOT(buttonState(ButtonNumber, bool)));
63  connect(pl->sdlGamepad, SIGNAL(axesValues(QListInt16)), this, SLOT(axesValues(QListInt16)));
64 #else
65  Q_UNUSED(plugin)
66 #endif
67 }
68 
70 {
71  delete m_widget;
72 }
73 
74 void GCSControlGadget::loadConfiguration(IUAVGadgetConfiguration *config)
75 {
76  GCSControlGadgetConfiguration *GCSControlConfig =
77  qobject_cast<GCSControlGadgetConfiguration *>(config);
78 
79  QList<int> ql = GCSControlConfig->getChannelsMapping();
80  rollChannel = ql.at(0);
81  pitchChannel = ql.at(1);
82  yawChannel = ql.at(2);
83  throttleChannel = ql.at(3);
84 
85  controlsMode = GCSControlConfig->getControlsMode();
86  gcsReceiverMode = GCSControlConfig->getGcsReceiverMode();
87  m_widget->allowGcsControl(gcsReceiverMode);
88 
89  for (unsigned int i = 0; i < 8; i++) {
90  buttonSettings[i].ActionID = GCSControlConfig->getbuttonSettings(i).ActionID;
91  buttonSettings[i].FunctionID = GCSControlConfig->getbuttonSettings(i).FunctionID;
92  buttonSettings[i].Amount = GCSControlConfig->getbuttonSettings(i).Amount;
93  buttonSettings[i].Amount = GCSControlConfig->getbuttonSettings(i).Amount;
94  channelReverse[i] = GCSControlConfig->getChannelsReverse().at(i);
95  }
96 }
97 
104 {
105  enableSending = enable;
106  if (enableSending)
107  getGcsControl()->beginGCSControl();
108  else
109  getGcsControl()->endGCSControl();
110 }
111 
112 ManualControlCommand *GCSControlGadget::getManualControlCommand()
113 {
114  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
115  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
116  return dynamic_cast<ManualControlCommand *>(
117  objManager->getObject(QString("ManualControlCommand")));
118 }
119 
120 GCSControl *GCSControlGadget::getGcsControl()
121 {
122  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
123  GCSControl *gcsControl = pm->getObject<GCSControl>();
124  Q_ASSERT(gcsControl);
125  return gcsControl;
126 }
127 
129 {
130 
131  // Show updates from transmitter when we're not sending.
132  if (enableSending)
133  return;
134 
135  double roll = obj->getField("Roll")->getDouble();
136  double pitch = obj->getField("Pitch")->getDouble();
137  double yaw = obj->getField("Yaw")->getDouble();
138  double throttle = obj->getField("Throttle")->getDouble();
139  // Remap RPYT to left X/Y and right X/Y depending on mode
140  switch (controlsMode) {
141  case 1:
142  // Mode 1: LeftX = Yaw, LeftY = Pitch, RightX = Roll, RightY = Throttle
143  emit sticksChangedRemotely(yaw, -pitch, roll, throttle);
144  break;
145  case 2:
146  // Mode 2: LeftX = Yaw, LeftY = Throttle, RightX = Roll, RightY = Pitch
147  emit sticksChangedRemotely(yaw, throttle, roll, -pitch);
148  break;
149  case 3:
150  // Mode 3: LeftX = Roll, LeftY = Pitch, RightX = Yaw, RightY = Throttle
151  emit sticksChangedRemotely(roll, -pitch, yaw, throttle);
152  break;
153  case 4:
154  // Mode 4: LeftX = Roll, LeftY = Throttle, RightX = Yaw, RightY = Pitch;
155  emit sticksChangedRemotely(roll, throttle, yaw, -pitch);
156  break;
157  }
158 }
159 
163 void GCSControlGadget::sticksChangedLocally(double leftX, double leftY, double rightX,
164  double rightY, double arming)
165 {
166  if (enableSending)
167  setGcsReceiver(leftX, leftY, rightX, rightY, arming);
168 }
169 
171 void GCSControlGadget::setGcsReceiver(double leftX, double leftY, double rightX, double rightY,
172  double arming)
173 {
174  GCSControl *ctr = getGcsControl();
175  Q_ASSERT(ctr);
176  if (ctr == NULL)
177  return;
178 
179  double newRoll = 0;
180  double newPitch = 0;
181  double newYaw = 0;
182  double newThrottle = 0;
183 
184  // Remap left X/Y and right X/Y to RPYT depending on mode
185  switch (controlsMode) {
186  case 1:
187  // Mode 1: LeftX = Yaw, LeftY = Pitch, RightX = Roll, RightY = Throttle
188  newRoll = rightX;
189  newPitch = -leftY;
190  newYaw = leftX;
191  newThrottle = rightY;
192  break;
193  case 2:
194  // Mode 2: LeftX = Yaw, LeftY = Throttle, RightX = Roll, RightY = Pitch
195  newRoll = rightX;
196  newPitch = -rightY;
197  newYaw = leftX;
198  newThrottle = leftY;
199  break;
200  case 3:
201  // Mode 3: LeftX = Roll, LeftY = Pitch, RightX = Yaw, RightY = Throttle
202  newRoll = leftX;
203  newPitch = -leftY;
204  newYaw = rightX;
205  newThrottle = rightY;
206  break;
207  case 4:
208  // Mode 4: LeftX = Roll, LeftY = Throttle, RightX = Yaw, RightY = Pitch;
209  newRoll = leftX;
210  newPitch = -rightY;
211  newYaw = rightX;
212  newThrottle = leftY;
213  break;
214  }
215 
216  ctr->setThrottle(newThrottle);
217  ctr->setRoll(newRoll);
218  ctr->setPitch(newPitch);
219  ctr->setYaw(newYaw);
220  ctr->setArming(arming);
221 
222  switch (controlsMode) {
223  case 1:
224  // Mode 1: LeftX = Yaw, LeftY = Pitch, RightX = Roll, RightY = Throttle
225  emit sticksChangedRemotely(newYaw, -newPitch, newRoll, newThrottle);
226  break;
227  case 2:
228  // Mode 2: LeftX = Yaw, LeftY = Throttle, RightX = Roll, RightY = Pitch
229  emit sticksChangedRemotely(newYaw, newThrottle, newRoll, -newPitch);
230  break;
231  case 3:
232  // Mode 3: LeftX = Roll, LeftY = Pitch, RightX = Yaw, RightY = Throttle
233  emit sticksChangedRemotely(newRoll, -newPitch, newYaw, newThrottle);
234  break;
235  case 4:
236  // Mode 4: LeftX = Roll, LeftY = Throttle, RightX = Yaw, RightY = Pitch;
237  emit sticksChangedRemotely(newRoll, newThrottle, newYaw, -newPitch);
238  break;
239  }
240 }
241 
242 void GCSControlGadget::flightModeChanged(ManualControlSettings::FlightModePositionOptions mode)
243 {
244  if (enableSending)
245  getGcsControl()->setFlightMode(mode);
246 }
247 
248 void GCSControlGadget::gamepads(quint8 count)
249 {
250  Q_UNUSED(count);
251 }
252 
253 double GCSControlGadget::constrain(double value)
254 {
255  if (value < -1)
256  return -1;
257  if (value > 1)
258  return 1;
259  return value;
260 }
261 
262 #if defined(USE_SDL)
263 void GCSControlGadget::buttonState(ButtonNumber number, bool pressed)
264 {
265  if ((buttonSettings[number].ActionID > 0) && (buttonSettings[number].FunctionID > 0)
266  && (pressed)) { // this button is configured
267  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
268  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
269  UAVDataObject *obj =
270  dynamic_cast<UAVDataObject *>(objManager->getObject(QString("ManualControlCommand")));
271  bool currentCGSControl =
272  (dynamic_cast<GCSControlGadgetWidget *>(m_widget))->getGCSControl();
273 
274  switch (buttonSettings[number].ActionID) {
275  case 1: // increase
276  if (currentCGSControl) {
277  switch (buttonSettings[number].FunctionID) {
278  case 1: // Roll
279  obj->getField("Roll")->setValue(
280  bound(obj->getField("Roll")->getValue().toDouble()
281  + buttonSettings[number].Amount));
282  break;
283  case 2: // Pitch
284  obj->getField("Pitch")->setValue(
285  bound(obj->getField("Pitch")->getValue().toDouble()
286  + buttonSettings[number].Amount));
287  break;
288  case 3: // Yaw
289  obj->getField("Yaw")->setValue(wrap(obj->getField("Yaw")->getValue().toDouble()
290  + buttonSettings[number].Amount));
291  break;
292  case 4: // Throttle
293  obj->getField("Throttle")
294  ->setValue(bound(obj->getField("Throttle")->getValue().toDouble()
295  + buttonSettings[number].Amount));
296  break;
297  }
298  }
299  break;
300  case 2: // decrease
301  if (currentCGSControl) {
302  switch (buttonSettings[number].FunctionID) {
303  case 1: // Roll
304  obj->getField("Roll")->setValue(
305  bound(obj->getField("Roll")->getValue().toDouble()
306  - buttonSettings[number].Amount));
307  break;
308  case 2: // Pitch
309  obj->getField("Pitch")->setValue(
310  bound(obj->getField("Pitch")->getValue().toDouble()
311  - buttonSettings[number].Amount));
312  break;
313  case 3: // Yaw
314  obj->getField("Yaw")->setValue(wrap(obj->getField("Yaw")->getValue().toDouble()
315  - buttonSettings[number].Amount));
316  break;
317  case 4: // Throttle
318  obj->getField("Throttle")
319  ->setValue(bound(obj->getField("Throttle")->getValue().toDouble()
320  - buttonSettings[number].Amount));
321  break;
322  }
323  }
324  break;
325  case 3: // toggle
326  switch (buttonSettings[number].FunctionID) {
327  case 1: // Armed
328  if (currentCGSControl) {
329  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
330  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
331  UAVDataObject *obj = dynamic_cast<UAVDataObject *>(
332  objManager->getObject(QString("FlightStatus")));
333 
334  if (obj->getField("Armed")->getValue().toString().compare("Armed") == 0) {
335  obj->getField("Armed")->setValue("Disarmed");
336  } else {
337  obj->getField("Armed")->setValue("Armed");
338  }
339  }
340  break;
341  case 2: // GCS Control
342  // Toggle the GCS Control checkbox, its built in signalling will handle the update
343  // to OP
344  (dynamic_cast<GCSControlGadgetWidget *>(m_widget))
345  ->setGCSControl(!currentCGSControl);
346 
347  break;
348  }
349 
350  break;
351  }
352 
353  obj->updated();
354  }
355  // buttonSettings[number].ActionID NIDT
356  // buttonSettings[number].FunctionID -RPYTAC
357  // buttonSettings[number].Amount
358 }
359 
360 void GCSControlGadget::axesValues(QListInt16 values)
361 {
362  int chMax = values.length();
363  if (rollChannel >= chMax || pitchChannel >= chMax || yawChannel >= chMax
364  || throttleChannel >= chMax) {
365  qDebug()
366  << "GCSControl: configuration is inconsistent with current joystick! Aborting update.";
367  return;
368  }
369 
370  double rValue = (rollChannel > -1) ? values[rollChannel] : 0;
371  double pValue = (pitchChannel > -1) ? values[pitchChannel] : 0;
372  double yValue = (yawChannel > -1) ? values[yawChannel] : 0;
373  double tValue = (throttleChannel > -1) ? values[throttleChannel] : 0;
374  double max = 32767;
375 
376  /* TODO: need to appropriately plumb */
377  double arming = -1;
378 
379  if (rollChannel > -1)
380  if (channelReverse[rollChannel] == true)
381  rValue = -rValue;
382  if (pitchChannel > -1)
383  if (channelReverse[pitchChannel] == true)
384  pValue = -pValue;
385  if (yawChannel > -1)
386  if (channelReverse[yawChannel] == true)
387  yValue = -yValue;
388  if (throttleChannel > -1)
389  if (channelReverse[throttleChannel] == true)
390  tValue = -tValue;
391 
392  if (joystickTime.elapsed() > JOYSTICK_UPDATE_RATE) {
393  joystickTime.restart();
394  // Remap RPYT to left X/Y and right X/Y depending on mode
395  // Mode 1: LeftX = Yaw, LeftY = Pitch, RightX = Roll, RightY = Throttle
396  // Mode 2: LeftX = Yaw, LeftY = THrottle, RightX = Roll, RightY = Pitch
397  // Mode 3: LeftX = Roll, LeftY = Pitch, RightX = Yaw, RightY = Throttle
398  // Mode 4: LeftX = Roll, LeftY = Throttle, RightX = Yaw, RightY = Pitch;
399  switch (controlsMode) {
400  case 1:
401  sticksChangedLocally(yValue / max, -pValue / max, rValue / max, -tValue / max, arming);
402  break;
403  case 2:
404  sticksChangedLocally(yValue / max, -tValue / max, rValue / max, -pValue / max, arming);
405  break;
406  case 3:
407  sticksChangedLocally(rValue / max, -pValue / max, yValue / max, -tValue / max, arming);
408  break;
409  case 4:
410  sticksChangedLocally(rValue / max, -tValue / max, yValue / max, -pValue / max, arming);
411  break;
412  }
413  }
414 }
415 #endif
416 
417 double GCSControlGadget::bound(double input)
418 {
419  if (input > 1.0)
420  return 1.0;
421  if (input < -1.0)
422  return -1.0;
423  return input;
424 }
425 
426 double GCSControlGadget::wrap(double input)
427 {
428  while (input > 1.0)
429  input -= 2.0;
430  while (input < -1.0)
431  input += 2.0;
432  return input;
433 }
void loadConfiguration(IUAVGadgetConfiguration *config)
buttonSettingsStruct getbuttonSettings(int i)
void updateSticks(double leftX, double leftY, double rightX, double rightY)
Signals from parent gadget indicating change from the remote system.
bool setYaw(float value)
Definition: gcscontrol.cpp:203
void allowGcsControl(bool allow)
Allow the GCS to take over control of UAV.
GCSControlGadget(QString classId, GCSControlGadgetWidget *widget, QWidget *parent=nullptr, QObject *plugin=nullptr)
void sticksChangedLocally(double leftX, double leftY, double rightX, double rightY, double arming)
double getDouble(int index=0) const
Core plugin system that manages the plugins, their life cycle and their registered objects...
Definition: pluginmanager.h:53
bool setRoll(float value)
Definition: gcscontrol.cpp:193
void manualControlCommandUpdated(UAVObject *)
bool setThrottle(float value)
Definition: gcscontrol.cpp:188
for i
Definition: OPPlots.m:140
bool setFlightMode(ManualControlSettings::FlightModePositionOptions flightMode)
Definition: gcscontrol.cpp:177
void sticksChangedRemotely(double leftX, double leftY, double rightX, double rightY)
void objectUpdated(UAVObject *obj)
Signal sent whenever any field of the object is updated.
void sticksChanged(double leftX, double leftY, double rightX, double rightY, double arming)
Emitted whenever the UI is clicked on to indicate the new stick positions.
bool beginGCSControl()
GCSControl::beginGCSControl Configure the FC to use the GCSReceiver control for manual control (cache...
Definition: gcscontrol.cpp:99
void gamepads(quint8 count)
void setValue(const QVariant &data, int index=0)
bool setPitch(float value)
Definition: gcscontrol.cpp:198
void axesValues(QListInt16 values)
UAVObjectField * getField(const QString &name)
Definition: uavobject.cpp:236
void enableControl(bool enable)
Enable or disable sending data.
void flightModeChangedLocally(ManualControlSettings::FlightModePositionOptions)
bool endGCSControl()
GCSControl::endGCSControl restores the cached ManualControlSettings.
Definition: gcscontrol.cpp:163
void buttonState(ButtonNumber number, bool pressed)
UAVObject * getObject(const QString &name, quint32 instId=0)
bool setArming(float value)
Definition: gcscontrol.cpp:208
void flightModeChanged(ManualControlSettings::FlightModePositionOptions mode)