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
8#include <yarp/os/LogStream.h>
9#include <tuple>
11
12using namespace yarp::dev;
13using namespace yarp::sig;
14using namespace yarp::os;
15
16namespace {
17YARP_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
31bool 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
158bool 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;
200 cmd.addVocab32(vocab_toget);
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
214bool JoypadControlClient::getRawButtonCount(unsigned int& button_count)
215{
216 return getCount(VOCAB_BUTTON, button_count);
217}
218
219bool JoypadControlClient::getRawAxisCount(unsigned int& axis_count)
220{
221 return getCount(VOCAB_AXIS, axis_count);
222}
223
224bool JoypadControlClient::getRawTrackballCount(unsigned int& Trackball_count)
225{
226 return getCount(VOCAB_TRACKBALL, Trackball_count);
227}
228
229bool JoypadControlClient::getRawHatCount(unsigned int& Hat_count)
230{
231 return getCount(VOCAB_HAT, Hat_count);
232}
233
234bool JoypadControlClient::getRawTouchSurfaceCount(unsigned int& touch_count)
235{
236 return getCount(VOCAB_TOUCH, touch_count);
237}
238
239bool JoypadControlClient::getRawStickCount(unsigned int& stick_count)
240{
241 return getCount(VOCAB_STICK, stick_count);
242}
243
244bool JoypadControlClient::getRawStickDoF(unsigned int stick_id, unsigned int& DoF)
245{
246 Bottle cmd, response;
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
264bool JoypadControlClient::getRawButton(unsigned int button_id, float& value)
265{
266 if(m_rpc_only)
267 {
268 Bottle cmd, response;
269
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
303bool 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
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
343bool JoypadControlClient::getRawHat(unsigned int hat_id, unsigned char& value)
344{
345 if(m_rpc_only)
346 {
347 Bottle cmd, response;
348
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
380bool JoypadControlClient::getRawAxis(unsigned int axis_id, double& value)
381{
382 if(m_rpc_only)
383 {
384 Bottle cmd, response;
385
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
419bool 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;
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 }
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
495bool 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
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:64
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:436
void close() override
Stop port activity.
Definition: Port.cpp:363
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:63
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
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:248
#define yCInfo(component,...)
Definition: LogComponent.h:171
#define yCError(component,...)
Definition: LogComponent.h:213
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:76
For streams capable of holding different kinds of content, check what they actually have.
An interface to the operating system, including Port based communication.