YARP
Yet Another Robot Platform
IJoypadController.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
7 #include <yarp/os/LogStream.h>
8 #include <cmath>
9 
10 using namespace yarp::dev;
11 using namespace yarp::os;
12 
13 namespace {
14 YARP_LOG_COMPONENT(IJOYPADCONTROLLER, "yarp.dev.IJoypadController")
15 }
16 
17 #define buttActionGroupName "BUTTON_EXECUTE"
18 
19 #define JoyData yarp::dev::IJoypadEvent::joyData
20 
22 
23 #ifndef YARP_NO_DEPRECATED // Since YARP 3.0.0
25 #endif
27  m_event(nullptr),
28  EventDrivenEnabled(false)
29 {
30 }
31 
32 
33 bool isEqual(const float& a, const float& b, const float& tolerance)
34 {
35  return fabs(a - b) < tolerance;
36 }
37 
38 bool isEqual(const double& a, const double& b, const double& tolerance)
39 {
40  return fabs(a - b) < tolerance;
41 }
42 
43 bool isEqual(const yarp::sig::Vector& a, const yarp::sig::Vector& b, const double& tolerance)
44 {
45  if (a.size() != b.size()) {
46  return false;
47  }
48 
49  for (size_t i = 0; i < a.size(); i++)
50  {
51  if (fabs(a[i] - b[i]) > tolerance)
52  {
53  return false;
54  }
55  }
56  return true;
57 }
58 
60 {
61  unsigned int count;
62  if(getRawButtonCount(count) && count)
63  {
64  float value = 0;
65  for(unsigned int i = 0; i < count; i++)
66  {
67  getRawButton(i, value);
68  old_buttons.push_back(value);
69  }
70  }
71 
72  if(getRawAxisCount(count) && count)
73  {
74  double value = 0;
75  for(unsigned int i = 0; i < count; i++)
76  {
77  getRawAxis(i, value);
78  old_axes.push_back(value);
79  }
80  }
81 
82  if(getRawHatCount(count) && count)
83  {
84  unsigned char value = 0;
85  for(unsigned int i = 0; i < count; i++)
86  {
87  getRawHat(i, value);
88  old_hats.push_back(value);
89  }
90  }
91 
92  if(getRawTrackballCount(count) && count)
93  {
94  yarp::sig::Vector value;
95  for(unsigned int i = 0; i < count; i++)
96  {
97  getRawTrackball(i, value);
98  old_trackballs.push_back(value);
99  }
100  }
101 
102  if(getRawStickCount(count) && count)
103  {
104  yarp::sig::Vector value;
105  for(unsigned int i = 0; i < count; i++)
106  {
107  getRawStick(i, value, IJoypadController::JypCtrlcoord_CARTESIAN);
108  old_sticks.push_back(value);
109 
110  }
111  }
112 
113  if(getRawTouchSurfaceCount(count) && count)
114  {
115  yarp::sig::Vector value;
116  for(unsigned int i = 0; i < count; i++)
117  {
118  getRawTouch(i, value);
119  old_touches.push_back(value);
120  }
121  }
122  return true;
123 }
124 
126 {
127  bool perform = false;
128  if(!m_event)
129  {
130  return;
131  }
132 
133  unsigned int count;
134  std::vector<JoyData<float> > buttons;
135  std::vector<JoyData<double> > axes;
136  std::vector<JoyData<unsigned char> > hats;
137  std::vector<JoyData<yarp::sig::Vector> > trackBalls;
138  std::vector<JoyData<yarp::sig::Vector> > sticks;
139  std::vector<JoyData<yarp::sig::Vector> > Touch;
140 
141  if(getRawButtonCount(count) && count)
142  {
143  float value = 0;
144  for(unsigned int i = 0; i < count; i++)
145  {
146  getRawButton(i, value);
147  if(!isEqual(value, old_buttons[i], 0.00001f))
148  {
149  perform = true;
150  buttons.emplace_back(i, value);
151  old_buttons[i] = value;
152  }
153  }
154  }
155 
156  if(getRawAxisCount(count) && count)
157  {
158  double value = 0;
159  for(unsigned int i = 0; i < count; i++)
160  {
161  getRawAxis(i, value);
162  if(!isEqual(value, old_axes[i], 0.00001))
163  {
164  perform = true;
165  axes.emplace_back(i, value);
166  old_axes[i] = value;
167  }
168  }
169  }
170 
171  if(getRawHatCount(count) && count)
172  {
173  unsigned char value = 0;
174  for(unsigned int i = 0; i < count; i++)
175  {
176  getRawHat(i, value);
177  if(value != old_hats[i])
178  {
179  perform = true;
180  hats.emplace_back(i, value);
181  old_hats[i] = value;
182  }
183  }
184  }
185 
186  if(getRawTrackballCount(count) && count)
187  {
188  yarp::sig::Vector value;
189  for(unsigned int i = 0; i < count; i++)
190  {
191  getRawTrackball(i, value);
192  if(!isEqual(value, old_trackballs[i], 0.00001))
193  {
194  perform = true;
195  trackBalls.emplace_back(i, value);
196  old_trackballs[i] = value;
197  }
198  }
199  }
200 
201  if(getRawStickCount(count) && count)
202  {
203  yarp::sig::Vector value;
204  for(unsigned int i = 0; i < count; i++)
205  {
206  getRawStick(i, value, IJoypadController::JypCtrlcoord_CARTESIAN);
207  if(!isEqual(value, old_sticks[i], 0.00001))
208  {
209  perform = true;
210  sticks.emplace_back(i, value);
211  old_sticks[i] = value;
212  }
213  }
214  }
215 
216  if(getRawTouchSurfaceCount(count) && count)
217  {
218  yarp::sig::Vector value;
219  for(unsigned int i = 0; i < count; i++)
220  {
221  getRawTouch(i, value);
222  if(!isEqual(value, old_touches[i], 0.00001))
223  {
224  perform = true;
225  Touch.emplace_back(i, value);
226  old_touches[i] = value;
227  }
228  }
229  }
230 
231  if(perform)
232  {
233  m_event->action(buttons, axes, hats, trackBalls, sticks, Touch);
234  }
235 }
236 
238 {
239  if (enable)
240  {
241  if (event)
242  {
243  if(isRunning())
244  {
245  stop();
246  }
247 
248  m_event = event;
249  EventDrivenEnabled = true;
250  start();
251 
252  return true;
253  }
254  else
255  {
256  if(isRunning())
257  {
258  yError() << "IJoypadController: event thread is already running";
259  return false;
260  }
261 
262  if (m_event)
263  {
264  EventDrivenEnabled = true;
265  start();
266  return true;
267  }
268  else
269  {
270  yError() << "IJoypadController: you must provide a valid event to start the event thread";
271  return false;
272  }
273  }
274  }
275 
276  if(isRunning())
277  {
278  stop();
279  EventDrivenEnabled = false;
280  return true;
281  }
282 
283  return false;
284 }
285 
286 bool yarp::dev::IJoypadEventDriven::getAxisCount(unsigned int& axis_count)
287 {
288  return getRawAxisCount(axis_count);
289 }
290 
291 bool yarp::dev::IJoypadEventDriven::getButtonCount(unsigned int& button_count)
292 {
293  return getRawButtonCount(button_count);
294 }
295 
296 bool yarp::dev::IJoypadEventDriven::getTrackballCount(unsigned int& Trackball_count)
297 {
298  return getRawTrackballCount(Trackball_count);
299 }
300 
301 bool yarp::dev::IJoypadEventDriven::getHatCount(unsigned int& Hat_count)
302 {
303  return getRawHatCount(Hat_count);
304 }
305 
307 {
308  return getRawTouchSurfaceCount(touch_count);
309 }
310 
311 bool yarp::dev::IJoypadEventDriven::getStickCount(unsigned int& stick_count)
312 {
313  return getRawStickCount(stick_count);
314 }
315 
316 bool yarp::dev::IJoypadEventDriven::getStickDoF(unsigned int stick_id, unsigned int& DoF)
317 {
318  if (EventDrivenEnabled)
319  {
320  yError() << "EventDriven is enable.. you can't poll the joypad state";
321  return false;
322  }
323  return getRawStickDoF(stick_id, DoF);
324 }
325 
326 bool yarp::dev::IJoypadEventDriven::getButton(unsigned int button_id, float& value)
327 {
328  if (EventDrivenEnabled)
329  {
330  yError() << "EventDriven is enable.. you can't poll the joypad state";
331  return false;
332  }
333  return getRawButton(button_id, value);
334 }
335 
336 bool yarp::dev::IJoypadEventDriven::getTrackball(unsigned int trackball_id, yarp::sig::Vector& value)
337 {
338  if (EventDrivenEnabled)
339  {
340  yError() << "EventDriven is enable.. you can't poll the joypad state";
341  return false;
342  }
343 
344  return getRawTrackball(trackball_id, value);
345 }
346 
347 bool yarp::dev::IJoypadEventDriven::getHat(unsigned int hat_id, unsigned char& value)
348 {
349  if (EventDrivenEnabled)
350  {
351  yError() << "EventDriven is enable.. you can't poll the joypad state";
352  return false;
353  }
354 
355  return getRawHat(hat_id, value);
356 }
357 
358 bool yarp::dev::IJoypadEventDriven::getAxis(unsigned int axis_id, double& value)
359 {
360  if (EventDrivenEnabled)
361  {
362  yError() << "EventDriven is enable.. you can't poll the joypad state";
363  return false;
364  }
365 
366  return getRawAxis(axis_id, value);
367 }
368 
369 bool yarp::dev::IJoypadEventDriven::getStick(unsigned int stick_id, yarp::sig::Vector& value, JoypadCtrl_coordinateMode coordinate_mode)
370 {
371  if (EventDrivenEnabled)
372  {
373  yError() << "EventDriven is enable.. you can't poll the joypad state";
374  return false;
375  }
376 
377  return getRawStick(stick_id, value, coordinate_mode);
378 }
379 
381 {
382  if (EventDrivenEnabled)
383  {
384  yError() << "EventDriven is enable.. you can't poll the joypad state";
385  return false;
386  }
387 
388  return getRawTouch(touch_id, value);
389 }
390 
392 {
393  if (m_actions.find(action_id) != m_actions.end())
394  {
395  yCInfo(IJOYPADCONTROLLER) << "executing script" << action_id << ":" << m_actions[action_id];
396  int ret = system(m_actions[action_id].c_str());
397  YARP_UNUSED(ret);
398  }
399  else
400  {
401  yCWarning(IJOYPADCONTROLLER) << "no scripts associated to button" << action_id;
402  return false;
403  }
404  return true;
405 }
406 
408 {
409  int dummy = 0;
410  size_t i;
411  int& actCount = count ? *count : dummy;
412  if(!cfg.check(buttActionGroupName))
413  {
414  yCInfo(IJOYPADCONTROLLER) << "no actions found in the configuration file (no" << buttActionGroupName << "group found)";
415  actCount = 0;
416  return true;
417  }
418  Bottle& actionsGroup = cfg.findGroup(buttActionGroupName);
419 
420  if(!actionsGroup.size())
421  {
422  yCError(IJOYPADCONTROLLER) << "no action found under" << buttActionGroupName << "group";
423  actCount = 0;
424  return false;
425  }
426 
427  for(i = 1; i < actionsGroup.size(); i++)
428  {
429  if(!actionsGroup.get(i).isList())
430  {
431  yDebug() << "error parsing cfg";
432  return false;
433  }
434 
435  Bottle& keyvalue = *actionsGroup.get(i).asList();
436  yDebug() << keyvalue.toString();
437  unsigned int buttonCount;
438  if(!this->getButtonCount(buttonCount))
439  {
440  yCError(IJOYPADCONTROLLER) << "unable to get button count while parsing the actions";
441  actCount = 0;
442  return false;
443  }
444  if(!keyvalue.get(0).isInt32() ||
445  keyvalue.get(0).asInt32() < 0 ||
446  (unsigned int) keyvalue.get(0).asInt32() > buttonCount-1 ||
447  !keyvalue.get(1).isString())
448  {
449  yCError(IJOYPADCONTROLLER) << "Button's actions parameters must be in the format 'unsigned int string' and the button id must be in range";
450  actCount = 0;
451  return false;
452  }
453  yCInfo(IJOYPADCONTROLLER) << "assigning actions" << keyvalue.get(1).asString() << "to button" << keyvalue.get(0).asInt32();
454  m_actions[keyvalue.get(0).asInt32()] = keyvalue.get(1).asString();
455  }
456 
457  actCount = i;
458  yCInfo(IJOYPADCONTROLLER) << actCount << "action parsed successfully";
459  return true;
460 }
461 
bool isEqual(const float &a, const float &b, const float &tolerance)
#define buttActionGroupName
bool ret
#define yError(...)
Definition: Log.h:279
#define yDebug(...)
Definition: Log.h:234
virtual bool executeAction(int action_id)
virtual bool parseActions(const yarp::os::Searchable &cfg, int *count=nullptr)
bool getTouch(unsigned int touch_id, yarp::sig::Vector &value) override final
Get the value of a touch if present, return false otherwise.
bool getStickDoF(unsigned int stick_id, unsigned int &DoF) override final
Get the Degree Of Freedom count for desired stick.
bool eventDriven(bool enable, yarp::dev::IJoypadEvent *event=nullptr) override
Activate event Driven mode.
bool getStickCount(unsigned int &stick_count) override final
Get the number of the sticks.
bool getButtonCount(unsigned int &button_count) override final
Get number of buttons.
bool getTrackball(unsigned int trackball_id, yarp::sig::Vector &value) override final
Get the axes change of a Trackball.
bool getHat(unsigned int hat_id, unsigned char &value) override final
Get the value of an Hat.
bool threadInit() override final
Initialization method.
bool getAxisCount(unsigned int &axis_count) override final
Get number of axes.
bool getTrackballCount(unsigned int &Trackball_count) override final
Get number of trackballs.
void run() override final
Loop function.
bool getButton(unsigned int button_id, float &value) override final
Get the value of a button.
bool getTouchSurfaceCount(unsigned int &touch_count) override final
Get the number of touch surface.
bool getHatCount(unsigned int &Hat_count) override final
Get number of hats.
bool getAxis(unsigned int axis_id, double &value) override final
Get the value of an axis if present, return false otherwise.
bool getStick(unsigned int stick_id, yarp::sig::Vector &value, JoypadCtrl_coordinateMode coordinate_mode) override final
Get the value of a stick if present, return false otherwise.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:211
An abstraction for a periodic thread.
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:156
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual bool isList() const
Checks if value is a list.
Definition: Value.cpp:162
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
virtual bool isInt32() const
Checks if value is a 32-bit integer.
Definition: Value.cpp:132
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
size_t size() const
Definition: Vector.h:323
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCWarning(component,...)
Definition: LogComponent.h:143
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
An interface for the device drivers.
An interface to the operating system, including Port based communication.
#define YARP_UNUSED(var)
Definition: api.h:162