YARP
Yet Another Robot Platform
JoypadControlClient.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 
6 #include "JoypadControlClient.h"
7 #include <yarp/os/LogComponent.h>
8 #include <yarp/os/LogStream.h>
9 #include <tuple>
11 
12 using namespace yarp::dev;
13 using namespace yarp::sig;
14 using namespace yarp::os;
15 
16 namespace {
17 YARP_LOG_COMPONENT(JOYPADCONTROLCLIENT, "yarp.device.JoypadControlClient")
18 }
19 
21 {
22  m_ports.push_back(&m_buttonsPort );
23  m_ports.push_back(&m_axisPort );
24  m_ports.push_back(&m_stickPort );
25  m_ports.push_back(&m_trackballPort);
26  m_ports.push_back(&m_touchPort );
27  m_ports.push_back(&m_hatsPort );
28  watchdog.m_ports = m_ports;
29 }
30 
31 bool JoypadControlClient::getJoypadInfo()
32 {
33  unsigned int count;
34  bool temp;
35 
36  temp = m_rpc_only;
37  m_rpc_only = true;
38  std::vector<std::tuple<int, JoypadControl::LoopablePort*, std::string> > vocabs_ports;
39  vocabs_ports.emplace_back(VOCAB_BUTTON, &m_buttonsPort, "/buttons");
40  vocabs_ports.emplace_back(VOCAB_AXIS, &m_axisPort, "/axis");
41  vocabs_ports.emplace_back(VOCAB_STICK, &m_stickPort, "/stick");
42  vocabs_ports.emplace_back(VOCAB_TRACKBALL, &m_trackballPort, "/trackballs");
43  vocabs_ports.emplace_back(VOCAB_TOUCH, &m_touchPort, "/touch");
44  vocabs_ports.emplace_back(VOCAB_HAT, &m_hatsPort, "/hat");
45 
46  for(auto vocab_port : vocabs_ports)
47  {
48  if (!getCount(std::get<0>(vocab_port), count)) {
49  return false;
50  }
51  if(count)
52  {
53  std::string source;
54  std::string destination;
55  std::string portname = m_local + std::get<2>(vocab_port) + ":i";
56  std::get<1>(vocab_port)->valid = true;
57  std::get<1>(vocab_port)->count = count;
58 
59  if(std::get<0>(vocab_port) == VOCAB_STICK)
60  {
61  for(unsigned int i = 0; i < count; i++)
62  {
63  unsigned int dofCount;
64  if(!getStickDoF(i, dofCount))
65  {
66  yCError(JOYPADCONTROLCLIENT) << "Unable to get sticks DoF";
67  return false;
68  }
69  m_stickDof.push_back(dofCount);
70  }
71  }
72 
73  yCInfo(JOYPADCONTROLCLIENT) << "Opening" << portname;
74 
75  if(!std::get<1>(vocab_port)->contactable->open(portname))
76  {
77  yCError(JOYPADCONTROLCLIENT) << "Unable to open" << portname << "port";
78  return false;
79  }
80 
81  source = m_remote + std::get<2>(vocab_port) + ":o";
82  destination = m_local + std::get<2>(vocab_port) + ":i";
83  if(!yarp::os::NetworkBase::connect(source.c_str(), destination.c_str(), "udp"))
84  {
85  yCError(JOYPADCONTROLCLIENT) << "Unable to connect" << portname << "port";
86  return false;
87  }
88 
89  std::get<1>(vocab_port)->useCallback();
90  }
91  }
92  m_rpc_only = temp;
93  return true;
94 }
95 
97 {
98  if(config.check("help"))
99  {
100  yCInfo(JOYPADCONTROLCLIENT) << "Parameter:\n\n" <<
101  "local - prefix of the local port\n" <<
102  "remote - prefix of the port provided to and opened by JoypadControlServer\n";
103  }
104  if(!config.check("local"))
105  {
106  yCError(JOYPADCONTROLCLIENT) << "Unable to 'local' parameter. check configuration file";
107  return false;
108  }
109 
110  m_local = config.find("local").asString();
111 
112  if(!m_rpcPort.open(m_local + "/rpc:o"))
113  {
114  yCError(JOYPADCONTROLCLIENT) << "Unable to open rpc port.";
115  return false;
116  }
117 
118  yCInfo(JOYPADCONTROLCLIENT) << "rpc port opened. starting the handshake";
119 
120  if(!config.check("remote"))
121  {
122  yCError(JOYPADCONTROLCLIENT) << "Unable to find the 'remote' parameter. check configuration file";
123  return false;
124  }
125 
126  m_remote = config.find("remote").asString();
127 
128  if(!yarp::os::NetworkBase::connect(m_local + "/rpc:o", m_remote + "/rpc:i"))
129  {
130  yCError(JOYPADCONTROLCLIENT) << "Handshake failed. unable to connect to remote port" << m_remote + "/rpc:i";
131  return false;
132  }
133 
134  yCInfo(JOYPADCONTROLCLIENT) << "Handshake succeeded! retrieving info";
135 
136  if(!getJoypadInfo())
137  {
138  yCError(JOYPADCONTROLCLIENT) << "Unable to get joypad info.";
139  return false;
140  }
141 
142  watchdog.start();
143 
144  return true;
145 }
146 
148 {
149  for (auto port : m_ports)
150  {
151  if (port->count)
152  {
153  port->onTimeout(0.5);
154  }
155  }
156 }
157 
158 bool JoypadControlClient::getCount(const int& vocab_toget, unsigned int& value)
159 {
160  if(!m_rpc_only)
161  {
162  switch(vocab_toget)
163  {
164  case VOCAB_BUTTON:
165  value = m_buttonsPort.count;
166  return true;
167 
168  case VOCAB_AXIS:
169 
170  value = m_axisPort.count;
171  return true;
172 
173  case VOCAB_TRACKBALL:
174  value = m_trackballPort.count;
175  return true;
176 
177  case VOCAB_TOUCH:
178 
179  value = m_touchPort.count;
180  return true;
181 
182  case VOCAB_STICK:
183 
184  value = m_stickPort.count;
185  return true;
186 
187  case VOCAB_HAT:
188 
189  value = m_hatsPort.count;
190  return true;
191 
192  default:
193  break;
194  }
195  }
196 
197  Bottle cmd, response;
199  cmd.addVocab32(VOCAB_GET);
200  cmd.addVocab32(vocab_toget);
201  cmd.addVocab32(VOCAB_COUNT);
202  m_rpcPort.write(cmd, response);
203  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isInt32())
204  {
205  value = response.get(1).asInt32();
206  return true;
207  }
208  else
209  {
210  return false;
211  }
212 }
213 
214 bool JoypadControlClient::getRawButtonCount(unsigned int& button_count)
215 {
216  return getCount(VOCAB_BUTTON, button_count);
217 }
218 
219 bool JoypadControlClient::getRawAxisCount(unsigned int& axis_count)
220 {
221  return getCount(VOCAB_AXIS, axis_count);
222 }
223 
224 bool JoypadControlClient::getRawTrackballCount(unsigned int& Trackball_count)
225 {
226  return getCount(VOCAB_TRACKBALL, Trackball_count);
227 }
228 
229 bool JoypadControlClient::getRawHatCount(unsigned int& Hat_count)
230 {
231  return getCount(VOCAB_HAT, Hat_count);
232 }
233 
234 bool JoypadControlClient::getRawTouchSurfaceCount(unsigned int& touch_count)
235 {
236  return getCount(VOCAB_TOUCH, touch_count);
237 }
238 
239 bool JoypadControlClient::getRawStickCount(unsigned int& stick_count)
240 {
241  return getCount(VOCAB_STICK, stick_count);
242 }
243 
244 bool JoypadControlClient::getRawStickDoF(unsigned int stick_id, unsigned int& DoF)
245 {
246  Bottle cmd, response;
248  cmd.addVocab32(VOCAB_GET);
250  cmd.addVocab32(VOCAB_COUNT);
251  cmd.addInt32(stick_id);
252  m_rpcPort.write(cmd, response);
253  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isInt32())
254  {
255  DoF = response.get(1).asInt32();
256  return true;
257  }
258  else
259  {
260  return false;
261  }
262 }
263 
264 bool JoypadControlClient::getRawButton(unsigned int button_id, float& value)
265 {
266  if(m_rpc_only)
267  {
268  Bottle cmd, response;
269 
271  cmd.addVocab32(VOCAB_GET);
273  cmd.addVocab32(VOCAB_VALUE);
274  cmd.addInt32(button_id);
275  m_rpcPort.write(cmd, response);
276  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isFloat64())
277  {
278  value = response.get(1).asFloat64();
279  return true;
280  }
281  else
282  {
283  yCError(JOYPADCONTROLCLIENT) << "GetButton() error. VOCAB_FAILED";
284  return false;
285  }
286  }
287  else
288  {
289  std::lock_guard<std::mutex> l(m_buttonsPort.mutex);
290  if(button_id < m_buttonsPort.storage.size())
291  {
292  value = m_buttonsPort.storage[button_id];
293  return true;
294  }
295  else
296  {
297  yCError(JOYPADCONTROLCLIENT) << "GetButton() error. button_id out of bound";
298  return false;
299  }
300  }
301 }
302 
303 bool JoypadControlClient::getRawTrackball(unsigned int trackball_id, yarp::sig::Vector& value)
304 {
305  value.clear();
306  if(m_rpc_only)
307  {
308  Bottle cmd, response;
309 
311  cmd.addVocab32(VOCAB_GET);
313  cmd.addVocab32(VOCAB_VALUE);
314  cmd.addInt32(trackball_id);
315  m_rpcPort.write(cmd, response);
316  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isFloat64() && response.get(2).isFloat64())
317  {
318  value.push_back(response.get(1).asFloat64());
319  value.push_back(response.get(2).asFloat64());
320  return true;
321  }
322  else
323  {
324  return false;
325  }
326  }
327  else
328  {
329  std::lock_guard<std::mutex> l(m_trackballPort.mutex);
330  if(trackball_id < m_trackballPort.storage.size() / 2)
331  {
332  value.push_back(m_trackballPort.storage[trackball_id * 2]);
333  value.push_back(m_trackballPort.storage[trackball_id * 2 + 1]);
334  return true;
335  }
336  else
337  {
338  return false;
339  }
340  }
341 }
342 
343 bool JoypadControlClient::getRawHat(unsigned int hat_id, unsigned char& value)
344 {
345  if(m_rpc_only)
346  {
347  Bottle cmd, response;
348 
350  cmd.addVocab32(VOCAB_GET);
351  cmd.addVocab32(VOCAB_HAT);
352  cmd.addVocab32(VOCAB_VALUE);
353  cmd.addInt32(hat_id);
354  m_rpcPort.write(cmd, response);
355  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isInt32())
356  {
357  value = response.get(1).asInt32();
358  return true;
359  }
360  else
361  {
362  return false;
363  }
364  }
365  else
366  {
367  std::lock_guard<std::mutex> l(m_hatsPort.mutex);
368  if(hat_id < m_hatsPort.storage.size())
369  {
370  value = m_hatsPort.storage[hat_id];
371  return true;
372  }
373  else
374  {
375  return false;
376  }
377  }
378 }
379 
380 bool JoypadControlClient::getRawAxis(unsigned int axis_id, double& value)
381 {
382  if(m_rpc_only)
383  {
384  Bottle cmd, response;
385 
387  cmd.addVocab32(VOCAB_GET);
388  cmd.addVocab32(VOCAB_AXIS);
389  cmd.addVocab32(VOCAB_VALUE);
390  cmd.addInt32(axis_id);
391  m_rpcPort.write(cmd, response);
392  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isFloat64())
393  {
394  value = response.get(1).asFloat64();
395  return true;
396  }
397  else
398  {
399  yCError(JOYPADCONTROLCLIENT) << "GetAxis() error. VOCAB_FAILED";
400  return false;
401  }
402  }
403  else
404  {
405  std::lock_guard<std::mutex> l(m_axisPort.mutex);
406  if(axis_id < m_axisPort.storage.size())
407  {
408  value = m_axisPort.storage[axis_id];
409  return true;
410  }
411  else
412  {
413  yCError(JOYPADCONTROLCLIENT) << "GetAxis() error. Axis_id out of bound";
414  return false;
415  }
416  }
417 }
418 
419 bool JoypadControlClient::getRawStick(unsigned int stick_id, yarp::sig::Vector& value, JoypadCtrl_coordinateMode coordinate_mode)
420 {
421  value.clear();
422  if(m_rpc_only || coordinate_mode == IJoypadController::JypCtrlcoord_POLAR)
423  {
424  Bottle cmd, response;
425  int dof, coordmode;
426 
427  coordmode = coordinate_mode == IJoypadController::JypCtrlcoord_CARTESIAN ? VOCAB_CARTESIAN : VOCAB_POLAR;
429  cmd.addVocab32(VOCAB_GET);
431  cmd.addVocab32(VOCAB_VALUE);
432  cmd.addInt32(stick_id);
433  m_rpcPort.write(cmd, response);
434 
435  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isInt32())
436  {
437  dof = response.get(1).asInt32();
438  }
439  else
440  {
441  return false;
442  }
444  cmd.addVocab32(VOCAB_GET);
445  cmd.addVocab32(VOCAB_STICK);
446  cmd.addVocab32(VOCAB_VALUE);
447  cmd.addVocab32(coordmode);
448  cmd.addInt32(stick_id);
449  m_rpcPort.write(cmd, response);
450  if(response.get(0).asVocab32() == VOCAB_OK)
451  {
452  for(int i = 0; i < dof; i++)
453  {
454  if(response.get(i).isFloat64())
455  {
456  value.push_back(response.get(i).asFloat64());
457  }
458  else
459  {
460  return false;
461  }
462  }
463  return true;
464  }
465  else
466  {
467  return false;
468  }
469  }
470  else
471  {
472  std::lock_guard<std::mutex> l(m_stickPort.mutex);
473  int offset = 0;
474 
475  unsigned int i;
476  if(getStickCount(i), stick_id >= i)
477  {
478  yCError(JOYPADCONTROLCLIENT) << "GetStick() error. Stick_id out of bound";
479  return false;
480  }
481  for(size_t j = 0; j < stick_id; j++)
482  {
483  offset += m_stickDof[j];
484  }
485 
486  for(size_t i = 0; i < m_stickDof[stick_id]; ++i)
487  {
488  value.push_back(m_stickPort.storage[offset + i]);
489  }
490 
491  return true;
492  }
493 }
494 
495 bool JoypadControlClient::getRawTouch(unsigned int touch_id, yarp::sig::Vector& value)
496 {
497  value.clear();
498  if(m_rpc_only)
499  {
500  Bottle cmd, response;
501 
503  cmd.addVocab32(VOCAB_GET);
504  cmd.addVocab32(VOCAB_TOUCH);
505  cmd.addVocab32(VOCAB_VALUE);
506  cmd.addInt32(touch_id);
507  m_rpcPort.write(cmd, response);
508  if(response.get(0).asVocab32() == VOCAB_OK && response.get(1).isFloat64() && response.get(2).isFloat64())
509  {
510  value.push_back(response.get(1).asFloat64());
511  value.push_back(response.get(2).asFloat64());
512  return true;
513  }
514  else
515  {
516  return false;
517  }
518  }
519  else
520  {
521  std::lock_guard<std::mutex> l(m_touchPort.mutex);
522  if(touch_id < m_touchPort.storage.size()/2)
523  {
524  value.push_back(m_touchPort.storage[touch_id * 2]);
525  value.push_back(m_touchPort.storage[touch_id * 2 + 1]);
526  return true;
527  }
528  else
529  {
530  return false;
531  }
532  }
533 }
534 
536 {
537 
538  std::vector<JoypadControl::LoopablePort*> portv;
539  portv.push_back(&m_buttonsPort);
540  portv.push_back(&m_axisPort);
541  portv.push_back(&m_hatsPort);
542  portv.push_back(&m_touchPort);
543  portv.push_back(&m_trackballPort);
544  portv.push_back(&m_stickPort);
545 
546  for(auto p : portv)
547  {
548  p->contactable->interrupt();
549  p->contactable->close();
550  }
551 
552  m_rpcPort.close();
553  return true;
554 }
constexpr yarp::conf::vocab32_t VOCAB_OK
Definition: GenericVocabs.h:15
constexpr yarp::conf::vocab32_t VOCAB_GET
Definition: GenericVocabs.h:13
constexpr yarp::conf::vocab32_t VOCAB_VALUE
Definition: GenericVocabs.h:38
constexpr yarp::conf::vocab32_t VOCAB_COUNT
Definition: GenericVocabs.h:37
constexpr yarp::conf::vocab32_t VOCAB_BUTTON
constexpr yarp::conf::vocab32_t VOCAB_IJOYPADCTRL
constexpr yarp::conf::vocab32_t VOCAB_TOUCH
constexpr yarp::conf::vocab32_t VOCAB_HAT
constexpr yarp::conf::vocab32_t VOCAB_TRACKBALL
constexpr yarp::conf::vocab32_t VOCAB_CARTESIAN
constexpr yarp::conf::vocab32_t VOCAB_STICKDOF
constexpr yarp::conf::vocab32_t VOCAB_AXIS
constexpr yarp::conf::vocab32_t VOCAB_POLAR
constexpr yarp::conf::vocab32_t VOCAB_STICK
bool getRawAxisCount(unsigned int &axis_count) override
bool getRawHatCount(unsigned int &Hat_count) override
bool getRawButtonCount(unsigned int &button_count) override
bool getRawTrackballCount(unsigned int &Trackball_count) override
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
bool getRawButton(unsigned int button_id, float &value) override
bool getRawHat(unsigned int hat_id, unsigned char &value) override
bool getRawStickDoF(unsigned int stick_id, unsigned int &DoF) override
bool close() override
Close the DeviceDriver.
bool getRawStickCount(unsigned int &stick_count) override
bool getRawStick(unsigned int stick_id, yarp::sig::Vector &value, JoypadCtrl_coordinateMode coordinate_mode) override
bool getRawTrackball(unsigned int trackball_id, yarp::sig::Vector &value) override
bool getRawTouch(unsigned int touch_id, yarp::sig::Vector &value) override
bool getRawTouchSurfaceCount(unsigned int &touch_count) override
bool getRawAxis(unsigned int axis_id, double &value) override
void run() override
Loop function.
std::vector< JoypadControl::LoopablePort * > m_ports
bool getStickDoF(unsigned int stick_id, unsigned int &DoF) override final
Get the Degree Of Freedom count for desired stick.
bool getStickCount(unsigned int &stick_count) override final
Get the number of the sticks.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:164
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:140
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
Definition: Network.cpp:682
bool start()
Call this to start the thread.
bool write(const PortWriter &writer, const PortWriter *callback=nullptr) const override
Write an object to the port.
Definition: Port.cpp:427
void close() override
Stop port activity.
Definition: Port.cpp:354
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition: Port.cpp:79
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
virtual yarp::conf::vocab32_t asVocab32() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:228
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual bool isFloat64() const
Checks if value is a 64-bit floating point number.
Definition: Value.cpp:150
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
void push_back(const T &elem)
Push a new element in the vector: size is changed.
Definition: Vector.h:250
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#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.
Signal processing.
Definition: Image.h:22