YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
AnalogWrapper.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 "AnalogWrapper.h"
7#include <sstream>
8#include <iostream>
11#include <yarp/os/LogStream.h>
12
13using namespace yarp::sig;
14using namespace yarp::dev;
15using namespace yarp::os;
16
17
18YARP_LOG_COMPONENT(ANALOGWRAPPER, "yarp.devices.AnalogWrapper")
19
20
26{
27 yarp::dev::IAnalogSensor* is; // analog sensor to calibrate, when required
28 yarp::os::Port rpcPort; // rpc port related to the analog sensor
29
30public:
31 AnalogServerHandler(const char* n);
33
34 void setInterface(yarp::dev::IAnalogSensor *is);
35
36 bool _handleIAnalog(yarp::os::Bottle &cmd, yarp::os::Bottle &reply);
37
38 bool read(yarp::os::ConnectionReader& connection) override;
39};
40
41
48{
49public:
51 std::string port_name; // the complete name of the port
52 int offset; // an offset, the port is mapped starting from this taxel
53 int length; // length of the output vector of the port (-1 for max length)
57};
58
59
66{
67 rpcPort.open(n);
68 rpcPort.setReader(*this);
69}
70
72{
73 rpcPort.close();
74 is = nullptr;
75}
76
81
83{
84 if (is == nullptr) {
85 return false;
86 }
87
88 const size_t msgsize=cmd.size();
90
91 int code=cmd.get(1).asVocab32();
92 switch (code)
93 {
94 case VOCAB_CALIBRATE:
95 if (msgsize == 2) {
96 ret = is->calibrateSensor();
97 } else if (msgsize > 2) {
98 size_t offset = 2;
99 Vector v(msgsize - offset);
100 for (unsigned int i = 0; i < v.size(); i++) {
101 v[i] = cmd.get(i + offset).asFloat64();
102 }
103 ret = is->calibrateSensor(v);
104 }
105 break;
107 if (msgsize==3)
108 {
109 int ch=cmd.get(2).asInt32();
110 ret=is->calibrateChannel(ch);
111 }
112 else if (msgsize==4)
113 {
114 int ch=cmd.get(2).asInt32();
115 double v=cmd.get(3).asFloat64();
116 ret=is->calibrateChannel(ch, v);
117 }
118 break;
119 default:
120 return false;
121 }
122
123 reply.addInt32(ret);
124 return true;
125}
126
128{
131 bool ok=in.read(connection);
132 if (!ok) {
133 return false;
134 }
135
136 // parse in, prepare out
137 int code = in.get(0).asVocab32();
138 bool ret=false;
139 if (code==VOCAB_IANALOG)
140 {
141 ret=_handleIAnalog(in, out);
142 }
143
144 if (!ret)
145 {
146 out.clear();
148 }
149
151 if (returnToSender!=nullptr) {
152 out.write(*returnToSender);
153 }
154 return true;
155}
156
157
165 offset(0),
166 length(0)
167{}
168
170{
171 this->length = alt.length;
172 this->offset = alt.offset;
173 this->port_name = alt.port_name;
174}
175
177{
178 this->length = alt.length;
179 this->offset = alt.offset;
180 this->port_name = alt.port_name;
181 return *this;
182}
183
184 // closing anonimous namespace
185
186
192bool AnalogWrapper::createPort(const char* name, int rate)
193{
194 analogSensor_p=nullptr;
195 analogPorts.resize(1);
196 analogPorts[0].offset = 0;
197 analogPorts[0].length = -1; // max length
198 analogPorts[0].port_name = std::string(name);
199 setHandlers();
200 setPeriod(rate / 1000.0);
201 return true;
202}
203
204bool AnalogWrapper::createPorts(const std::vector<AnalogPortEntry>& _analogPorts, int rate)
205{
206 analogSensor_p=nullptr;
207 this->analogPorts=_analogPorts;
208 setHandlers();
209 setPeriod(rate / 1000.0);
210 return true;
211}
212
217
219{
221 close();
222 _rate = DEFAULT_THREAD_PERIOD;
223 analogSensor_p = nullptr;
224}
225
226void AnalogWrapper::setHandlers()
227{
228 for(auto& analogPort : analogPorts)
229 {
230 std::string rpcPortName = analogPort.port_name;
231 rpcPortName += "/rpc:i";
232 auto* ash = new AnalogServerHandler(rpcPortName.c_str());
233 handlers.push_back(ash);
234 }
235}
236
237void AnalogWrapper::removeHandlers()
238{
239 for(auto& handler : handlers)
240 {
241 if (handler != nullptr)
242 {
243 delete handler;
244 handler = nullptr;
245 }
246 }
247 handlers.clear();
248}
249
255{
256 if (analog2attach.size() != 1)
257 {
258 yCError(ANALOGWRAPPER, "AnalogWrapper: cannot attach more than one device");
259 return false;
260 }
261
263
264 if (Idevice2attach->isValid())
265 {
266 Idevice2attach->view(analogSensor_p);
267 }
268
269 if(nullptr == analogSensor_p)
270 {
271 yCError(ANALOGWRAPPER, "AnalogWrapper: subdevice passed to attach method is invalid");
272 return false;
273 }
274 attach(analogSensor_p);
275 PeriodicThread::setPeriod(_rate / 1000.0);
276 return PeriodicThread::start();
277}
278
280{
281 analogSensor_p = nullptr;
282 for(unsigned int i=0; i<analogPorts.size(); i++)
283 {
284 if (handlers[i] != nullptr) {
285 handlers[i]->setInterface(analogSensor_p);
286 }
287 }
288 return true;
289}
290
292{
293 analogSensor_p=s;
294 for(unsigned int i=0; i<analogPorts.size(); i++)
295 {
296 handlers[i]->setInterface(analogSensor_p);
297 }
298 //Resize vector of read data to avoid further allocation of memory
299 //as long as the number of channels does not change
300 lastDataRead.resize((size_t)analogSensor_p->getChannels(),0.0);
301}
302
304{
305 // Set interface to NULL
306 analogSensor_p = nullptr;
307 for(unsigned int i=0; i<analogPorts.size(); i++)
308 {
309 handlers[i]->setInterface(analogSensor_p);
310 }
311}
312
314{
315 for(auto& analogPort : analogPorts)
316 {
317 // open data port
318 if (!analogPort.port.open(analogPort.port_name))
319 {
320 yCError(ANALOGWRAPPER, "AnalogWrapper: failed to open port %s", analogPort.port_name.c_str());
321 return false;
322 }
323 }
324 return true;
325}
326
328{
329 yCWarning(ANALOGWRAPPER) << "The 'AnalogWrapper' device is deprecated.";
330 yCWarning(ANALOGWRAPPER) << "Possible alternatives, depending on the specific type sensor data, are:";
331 yCWarning(ANALOGWRAPPER) << "'MultipleAnalogSensorsRemapper`+`MultipleAnalogSensorsServer`, `PoseStampedRosPublisher`, `WrenchStampedRosPublisher`,`IMURosPublisher`,etc.";
332 yCWarning(ANALOGWRAPPER) << "The old device is no longer supported, and it will be deprecated in YARP 3.7 and removed in YARP 4.";
333 yCWarning(ANALOGWRAPPER) << "Please update your scripts.";
334
335 Property params;
336 params.fromString(config.toString());
337 yCTrace(ANALOGWRAPPER) << "AnalogWrapper params are: " << config.toString();
338
339 if (!config.check("period"))
340 {
341 yCError(ANALOGWRAPPER) << "AnalogWrapper: missing 'period' parameter. Check you configuration file\n";
342 return false;
343 }
344 else
345 {
346 _rate = config.find("period").asInt32();
347 }
348
349 if (config.check("deviceId"))
350 {
351 yCError(ANALOGWRAPPER) << "AnalogWrapper: the parameter 'deviceId' has been removed, please use parameter 'name' instead. \n"
352 << "e.g. In the FT wrapper configuration files of your robot, replace '<param name=""deviceId""> left_arm </param>' \n"
353 << "with '/icub/left_arm/analog:o' ";
354 return false;
355 }
356
357 if (!config.check("name"))
358 {
359 yCError(ANALOGWRAPPER) << "AnalogWrapper: missing 'name' parameter. Check you configuration file; it must be like:\n"
360 " name: full name of the port, like /robotName/deviceId/sensorType:o";
361 return false;
362 }
363 else
364 {
365 streamingPortName = config.find("name").asString();
366 }
367
368 if(!initialize_YARP(config) )
369 {
370 yCError(ANALOGWRAPPER) << sensorId << "Error initializing YARP ports";
371 return false;
372 }
373
374 return true;
375}
376
377bool AnalogWrapper::initialize_YARP(yarp::os::Searchable &params)
378{
379 // Create the list of ports
380 // port names are optional, do not check for correctness.
381 if(!params.check("ports"))
382 {
383 // if there is no "ports" section open only 1 port and use name as is.
384 if (Network::exists(streamingPortName + "/rpc:i") || Network::exists(streamingPortName))
385 {
386 yCError(ANALOGWRAPPER) << "AnalogWrapper: unable to open the analog server, address conflict";
387 return false;
388 }
389 createPort((streamingPortName ).c_str(), _rate );
390 // since createPort always return true, check the port is really been opened is done here
391 if (!Network::exists(streamingPortName + "/rpc:i")) {
392 return false;
393 }
394 }
395 else
396 {
397 Bottle *ports=params.find("ports").asList();
398
399 Value &deviceChannels = params.find("channels");
400 if (deviceChannels.isNull())
401 {
402 yCError(ANALOGWRAPPER, "AnalogWrapper: 'channels' parameters was not found in config file.");
403 return false;
404 }
405
406 int nports=ports->size();
407 int sumOfChannels = 0;
408 std::vector<AnalogPortEntry> tmpPorts;
409 tmpPorts.resize(nports);
410
411 for(size_t k=0; k<ports->size(); k++)
412 {
413 Bottle parameters=params.findGroup(ports->get(k).asString());
414
415 if (parameters.size()!=5)
416 {
417 yCError(ANALOGWRAPPER) << "AnalogWrapper: check skin port parameters in part description, I was expecting "
418 << ports->get(k).asString().c_str() << " followed by four integers";
419 yCError(ANALOGWRAPPER) << " your param is " << parameters.toString();
420 return false;
421 }
422
423 if (Network::exists(streamingPortName + "/" + std::string(ports->get(k).asString()) + "/rpc:i")
424 || Network::exists(streamingPortName + "/" + std::string(ports->get(k).asString())))
425 {
426 yCError(ANALOGWRAPPER) << "AnalogWrapper: unable to open the analog server, address conflict";
427 return false;
428 }
429 int wBase=parameters.get(1).asInt32();
430 int wTop=parameters.get(2).asInt32();
431 int base=parameters.get(3).asInt32();
432 int top=parameters.get(4).asInt32();
433
434 yCDebug(ANALOGWRAPPER) << "--> " << wBase << " " << wTop << " " << base << " " << top;
435
436 //check consistenty
437 if(wTop-wBase != top-base){
438 yCError(ANALOGWRAPPER) << "AnalogWrapper: numbers of mapped taxels do not match, check "
439 << ports->get(k).asString().c_str() << " port parameters in part description";
440 return false;
441 }
442 int portChannels = top-base+1;
443
444 tmpPorts[k].length = portChannels;
445 tmpPorts[k].offset = wBase;
446 yCDebug(ANALOGWRAPPER) << "opening port " << ports->get(k).asString().c_str();
447 tmpPorts[k].port_name = streamingPortName+ "/" + std::string(ports->get(k).asString());
448
450 }
451 createPorts(tmpPorts, _rate);
452
453 if (sumOfChannels!=deviceChannels.asInt32())
454 {
455 yCError(ANALOGWRAPPER) << "AnalogWrapper: Total number of mapped taxels does not correspond to total taxels";
456 return false;
457 }
458 }
459 return true;
460}
461
463{
464 for(auto& analogPort : analogPorts)
465 {
466 analogPort.port.interrupt();
467 analogPort.port.close();
468 }
469}
470
472{
473 int first, last, ret;
474
475 if (analogSensor_p!=nullptr)
476 {
477 ret=analogSensor_p->read(lastDataRead);
478
480 {
481 if (lastDataRead.size()>0)
482 {
483 if(1)
484 {
485 lastStateStamp.update();
486 // send the data on the port(s), splitting them as specified in the config file
487 for(auto& analogPort : analogPorts)
488 {
489 yarp::sig::Vector &pv = analogPort.port.prepare();
490 first = analogPort.offset;
491 if (analogPort.length == -1) { // read the max length available
492 last = lastDataRead.size()-1;
493 } else {
494 last = analogPort.offset + analogPort.length - 1;
495 }
496
497 // check vector limit
498 if(last>=(int)lastDataRead.size()){
499 yCError(ANALOGWRAPPER, )<<"AnalogWrapper: error while sending analog sensor output on port "<< analogPort.port_name
500 <<" Vector size expected to be at least "<<last<<" whereas it is "<< lastDataRead.size();
501 continue;
502 }
503 pv = lastDataRead.subVector(first, last);
504
505 analogPort.port.setEnvelope(lastStateStamp);
506 analogPort.port.write();
507 }
508 }
509 }
510 else
511 {
512 yCError(ANALOGWRAPPER, "AnalogWrapper: %s: vector size non valid: %lu", sensorId.c_str(), static_cast<unsigned long> (lastDataRead.size()));
513 }
514 }
515 else
516 {
517 switch(ret)
518 {
520 yCError(ANALOGWRAPPER, "AnalogWrapper: %s: Sensor returned overflow error (code %d).", sensorId.c_str(), ret);
521 break;
523 yCError(ANALOGWRAPPER, "AnalogWrapper: %s: Sensor returned timeout error (code %d).", sensorId.c_str(), ret);
524 break;
526 default:
527 yCError(ANALOGWRAPPER, "AnalogWrapper: %s: Sensor returned error with code %d.", sensorId.c_str(), ret);
528 break;
529 }
530 }
531 }
532}
533
535{
536 yCTrace(ANALOGWRAPPER, "AnalogWrapper::Close");
538 {
540 }
541
542 detachAll();
543 removeHandlers();
544
545 return true;
546}
const yarp::os::LogComponent & ANALOGWRAPPER()
#define DEFAULT_THREAD_PERIOD
define control board standard interfaces
#define DEFAULT_THREAD_PERIOD
constexpr yarp::conf::vocab32_t VOCAB_FAILED
constexpr yarp::conf::vocab32_t VOCAB_IANALOG
constexpr yarp::conf::vocab32_t VOCAB_CALIBRATE
constexpr yarp::conf::vocab32_t VOCAB_CALIBRATE_CHANNEL
bool ret
static void handler(int sig)
Definition RFModule.cpp:241
A yarp port that output data read from an analog sensor.
std::string port_name
AnalogPortEntry & operator=(const AnalogPortEntry &alt)
yarp::os::BufferedPort< yarp::sig::Vector > port
AnalogPortEntry()
A yarp port that output data read from an analog sensor.
Handler of the rpc port related to an analog sensor.
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
AnalogServerHandler(const char *n)
Handler of the rpc port related to an analog sensor.
void setInterface(yarp::dev::IAnalogSensor *is)
bool _handleIAnalog(yarp::os::Bottle &cmd, yarp::os::Bottle &reply)
void threadRelease() override
Release method.
void attach(yarp::dev::IAnalogSensor *s)
bool threadInit() override
Initialization method.
~AnalogWrapper() override
void run() override
Loop function.
bool open(yarp::os::Searchable &params) override
Open the DeviceDriver.
bool close() override
Close the DeviceDriver.
bool attachAll(const yarp::dev::PolyDriverList &p) override
Specify which analog sensor this thread has to read from.
bool detachAll() override
Detach the object (you must have first called attach).
A generic interface to sensors (gyro, a/d converters).
virtual int calibrateSensor()=0
Calibrates the whole sensor.
virtual int read(yarp::sig::Vector &out)=0
Read a vector from the sensor.
virtual int getChannels()=0
Get the number of channels of the sensor.
virtual int calibrateChannel(int ch)=0
Calibrates one single channel.
A container for a device driver.
Definition PolyDriver.h:23
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
size_type size() const
Gets the number of elements in the bottle.
Definition Bottle.cpp:251
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition Bottle.cpp:240
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:246
void clear()
Empties the bottle of any objects it contains.
Definition Bottle.cpp:121
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition Bottle.cpp:230
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition Bottle.cpp:140
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition Bottle.cpp:211
A mini-server for performing network communication in the background.
An interface for reading from a network connection.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
An interface for writing to a network connection.
An abstraction for a periodic thread.
bool setPeriod(double period)
Set the (new) period of the thread.
bool isRunning() const
Returns true when the thread is started, false otherwise.
bool start()
Call this to start the thread.
void stop()
Call this to stop the thread, this call blocks until the thread is terminated (and releaseThread() ca...
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
Definition PortReader.h:24
A mini-server for network communication.
Definition Port.h:46
bool write(const PortWriter &writer, const PortWriter *callback=nullptr) const override
Write an object to the port.
Definition Port.cpp:436
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition Port.cpp:511
void interrupt() override
Interrupt any current reads or writes attached to the port.
Definition Port.cpp:383
bool setEnvelope(PortWriter &envelope) override
Set an envelope (e.g., a timestamp) to the next message which will be sent.
Definition Port.cpp:547
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 class for storing options and configuration information.
Definition Property.h:33
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition Stamp.cpp:124
A single value (typically within a Bottle).
Definition Value.h:43
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
void resize(size_t size) override
Resize the vector.
Definition Vector.h:221
size_t size() const
Definition Vector.h:341
VectorOf< T > subVector(unsigned int first, unsigned int last) const
Creates and returns a new vector, being the portion of the original vector defined by the first and l...
Definition Vector.h:420
#define yCError(component,...)
#define yCTrace(component,...)
#define yCWarning(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
For streams capable of holding different kinds of content, check what they actually have.
An interface to the operating system, including Port based communication.
The main, catch-all namespace for YARP.
Definition dirs.h:16