YARP
Yet Another Robot Platform
AnalogWrapper.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  *
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 
9 #include "AnalogWrapper.h"
10 #include <sstream>
11 #include <iostream>
13 #include <yarp/os/LogComponent.h>
14 #include <yarp/os/LogStream.h>
15 
16 using namespace yarp::sig;
17 using namespace yarp::dev;
18 using namespace yarp::os;
19 using namespace std;
20 
21 
22 YARP_LOG_COMPONENT(ANALOGWRAPPER, "yarp.devices.AnalogWrapper")
23 
24 
29  public yarp::os::PortReader
30 {
31  yarp::dev::IAnalogSensor* is; // analog sensor to calibrate, when required
32  yarp::os::Port rpcPort; // rpc port related to the analog sensor
33 
34 public:
35  AnalogServerHandler(const char* n);
37 
38  void setInterface(yarp::dev::IAnalogSensor *is);
39 
40  bool _handleIAnalog(yarp::os::Bottle &cmd, yarp::os::Bottle &reply);
41 
42  bool read(yarp::os::ConnectionReader& connection) override;
43 };
44 
45 
52 {
53 public:
55  std::string port_name; // the complete name of the port
56  int offset; // an offset, the port is mapped starting from this taxel
57  int length; // length of the output vector of the port (-1 for max length)
59  AnalogPortEntry(const AnalogPortEntry &alt);
60  AnalogPortEntry &operator =(const AnalogPortEntry &alt);
61 };
62 
63 
69 AnalogServerHandler::AnalogServerHandler(const char* n) : is(nullptr)
70 {
71  rpcPort.open(n);
72  rpcPort.setReader(*this);
73 }
74 
76 {
77  rpcPort.close();
78  is = nullptr;
79 }
80 
82 {
83  this->is = is;
84 }
85 
87 {
88  if (is==nullptr)
89  return false;
90 
91  const size_t msgsize=cmd.size();
92  int ret=IAnalogSensor::AS_ERROR;
93 
94  int code=cmd.get(1).asVocab();
95  switch (code)
96  {
97  case VOCAB_CALIBRATE:
98  if (msgsize==2)
99  ret=is->calibrateSensor();
100  else if (msgsize>2)
101  {
102  size_t offset=2;
103  Vector v(msgsize-offset);
104  for (unsigned int i=0; i<v.size(); i++)
105  {
106  v[i]=cmd.get(i+offset).asFloat64();
107  }
108  ret=is->calibrateSensor(v);
109  }
110  break;
112  if (msgsize==3)
113  {
114  int ch=cmd.get(2).asInt32();
115  ret=is->calibrateChannel(ch);
116  }
117  else if (msgsize==4)
118  {
119  int ch=cmd.get(2).asInt32();
120  double v=cmd.get(3).asFloat64();
121  ret=is->calibrateChannel(ch, v);
122  }
123  break;
124  default:
125  return false;
126  }
127 
128  reply.addInt32(ret);
129  return true;
130 }
131 
133 {
134  yarp::os::Bottle in;
135  yarp::os::Bottle out;
136  bool ok=in.read(connection);
137  if (!ok) return false;
138 
139  // parse in, prepare out
140  int code = in.get(0).asVocab();
141  bool ret=false;
142  if (code==VOCAB_IANALOG)
143  {
144  ret=_handleIAnalog(in, out);
145  }
146 
147  if (!ret)
148  {
149  out.clear();
150  out.addVocab(VOCAB_FAILED);
151  }
152 
153  yarp::os::ConnectionWriter *returnToSender = connection.getWriter();
154  if (returnToSender!=nullptr) {
155  out.write(*returnToSender);
156  }
157  return true;
158 }
159 
160 
168  offset(0),
169  length(0)
170 {}
171 
173 {
174  this->length = alt.length;
175  this->offset = alt.offset;
176  this->port_name = alt.port_name;
177 }
178 
180 {
181  this->length = alt.length;
182  this->offset = alt.offset;
183  this->port_name = alt.port_name;
184  return *this;
185 }
186 
187  // closing anonimous namespace
188 
189 
195 bool AnalogWrapper::createPort(const char* name, int rate)
196 {
197  analogSensor_p=nullptr;
198  analogPorts.resize(1);
199  analogPorts[0].offset = 0;
200  analogPorts[0].length = -1; // max length
201  analogPorts[0].port_name = std::string(name);
202  setHandlers();
203  setPeriod(rate / 1000.0);
204  return true;
205 }
206 
207 bool AnalogWrapper::createPorts(const std::vector<AnalogPortEntry>& _analogPorts, int rate)
208 {
209  analogSensor_p=nullptr;
210  this->analogPorts=_analogPorts;
211  setHandlers();
212  setPeriod(rate / 1000.0);
213  return true;
214 }
215 
218 {
219  // init ROS struct
220  frame_idVec.resize(1);
221  frame_idVec.at(0) = "";
222  rosTopicNamesVec.resize(1);
223  rosTopicNamesVec.at(0) = "";
224  rosMsgCounterVec.resize(1);
225  rosMsgCounterVec.at(0) = 0;
226 }
227 
229 {
230  threadRelease();
231  close();
232  _rate = DEFAULT_THREAD_PERIOD;
233  analogSensor_p = nullptr;
234 }
235 
236 void AnalogWrapper::setHandlers()
237 {
238  for(auto& analogPort : analogPorts)
239  {
240  std::string rpcPortName = analogPort.port_name;
241  rpcPortName += "/rpc:i";
242  auto* ash = new AnalogServerHandler(rpcPortName.c_str());
243  handlers.push_back(ash);
244  }
245 }
246 
247 void AnalogWrapper::removeHandlers()
248 {
249  for(auto& handler : handlers)
250  {
251  if (handler != nullptr)
252  {
253  delete handler;
254  handler = nullptr;
255  }
256  }
257  handlers.clear();
258 }
259 
260 bool AnalogWrapper::openAndAttachSubDevice(Searchable &prop)
261 {
262  Property p;
263  subDeviceOwned = new PolyDriver;
264  p.fromString(prop.toString());
265 
266 // p.setMonitor(prop.getMonitor(), "subdevice"); // pass on any monitoring
267  p.unput("device");
268  p.put("device", prop.find("subdevice").asString()); // subdevice was already checked before
269 
270  // if errors occurred during open, quit here.
271  yCDebug(ANALOGWRAPPER, "opening AnalogWrapper subdevice...");
272  subDeviceOwned->open(p);
273 
274  if (!subDeviceOwned->isValid())
275  {
276  yCError(ANALOGWRAPPER, "opening AnalogWrapper subdevice... FAILED\n");
277  return false;
278  }
279 
280  subDeviceOwned->view(analogSensor_p);
281 
282  if (analogSensor_p == nullptr)
283  {
284  yCError(ANALOGWRAPPER, "Opening IAnalogSensor interface of AnalogWrapper subdevice... FAILED\n");
285  return false;
286  }
287 
288  int chNum = analogSensor_p->getChannels();
289 
290  if (chNum <= 0)
291  {
292  yCError(ANALOGWRAPPER, "Calling analog sensor has invalid channels number %d.\n", chNum);
293  return false;
294  }
295 
296  attach(analogSensor_p);
297  PeriodicThread::setPeriod(_rate / 1000.0);
298  return PeriodicThread::start();
299 }
300 
301 
302 bool AnalogWrapper::openDeferredAttach(yarp::os::Searchable &prop)
303 {
304  // nothing to do here?
305  if( (subDeviceOwned != nullptr) || (ownDevices == true) )
306  yCError(ANALOGWRAPPER) << "AnalogWrapper: something wrong with the initialization.";
307  return true;
308 }
309 
310 
315 bool AnalogWrapper::attachAll(const PolyDriverList &analog2attach)
316 {
317  //check if we already instantiated a subdevice previously
318  if (ownDevices)
319  return false;
320 
321  if (analog2attach.size() != 1)
322  {
323  yCError(ANALOGWRAPPER, "AnalogWrapper: cannot attach more than one device");
324  return false;
325  }
326 
327  yarp::dev::PolyDriver * Idevice2attach=analog2attach[0]->poly;
328 
329  if (Idevice2attach->isValid())
330  {
331  Idevice2attach->view(analogSensor_p);
332  }
333 
334  if(nullptr == analogSensor_p)
335  {
336  yCError(ANALOGWRAPPER, "AnalogWrapper: subdevice passed to attach method is invalid");
337  return false;
338  }
339  attach(analogSensor_p);
340  PeriodicThread::setPeriod(_rate / 1000.0);
341  return PeriodicThread::start();
342 }
343 
345 {
346  //check if we already instantiated a subdevice previously
347  if (ownDevices)
348  return false;
349 
350  analogSensor_p = nullptr;
351  for(unsigned int i=0; i<analogPorts.size(); i++)
352  {
353  if(handlers[i] != nullptr)
354  handlers[i]->setInterface(analogSensor_p);
355  }
356  return true;
357 }
358 
360 {
361  analogSensor_p=s;
362  for(unsigned int i=0; i<analogPorts.size(); i++)
363  {
364  handlers[i]->setInterface(analogSensor_p);
365  }
366  //Resize vector of read data to avoid further allocation of memory
367  //as long as the number of channels does not change
368  lastDataRead.resize((size_t)analogSensor_p->getChannels(),0.0);
369 }
370 
372 {
373  // Set interface to NULL
374  analogSensor_p = nullptr;
375  for(unsigned int i=0; i<analogPorts.size(); i++)
376  {
377  handlers[i]->setInterface(analogSensor_p);
378  }
379 }
380 
382 {
383  for(auto& analogPort : analogPorts)
384  {
385  // open data port
386  if (!analogPort.port.open(analogPort.port_name))
387  {
388  yCError(ANALOGWRAPPER, "AnalogWrapper: failed to open port %s", analogPort.port_name.c_str());
389  return false;
390  }
391  }
392  return true;
393 }
394 
395 void AnalogWrapper::setId(const std::string &id)
396 {
397  sensorId=id;
398 }
399 
400 std::string AnalogWrapper::getId()
401 {
402  return sensorId;
403 }
404 
405 bool AnalogWrapper::checkROSParams(Searchable &config)
406 {
407  // check for ROS parameter group
408  if(!config.check("ROS") )
409  {
410  useROS = ROS_disabled;
411  yCInfo(ANALOGWRAPPER) << "No ROS group found in config file ... skipping ROS initialization.";
412  return true;
413  }
414 
415  yCInfo(ANALOGWRAPPER) << "ROS group was FOUND in config file.";
416 
417  Bottle &rosGroup = config.findGroup("ROS");
418  if(rosGroup.isNull())
419  {
420  yCError(ANALOGWRAPPER) << sensorId << "ROS group params is not a valid group or empty";
421  useROS = ROS_config_error;
422  return false;
423  }
424 
425  // check for useROS parameter
426  if(!rosGroup.check("useROS"))
427  {
428  yCError(ANALOGWRAPPER) << sensorId << " cannot find useROS parameter, mandatory when using ROS message. \n \
429  Allowed values are true, false, ROS_only";
430  useROS = ROS_config_error;
431  return false;
432  }
433  std::string ros_use_type = rosGroup.find("useROS").asString();
434  if(ros_use_type == "false")
435  {
436  yCInfo(ANALOGWRAPPER) << sensorId << "useROS topic if set to 'false'";
437  useROS = ROS_disabled;
438  return true;
439  }
440  else if(ros_use_type == "true")
441  {
442  yCInfo(ANALOGWRAPPER) << sensorId << "useROS topic if set to 'true'";
443  useROS = ROS_enabled;
444  }
445  else if(ros_use_type == "only")
446  {
447  yCInfo(ANALOGWRAPPER) << sensorId << "useROS topic if set to 'only";
448  useROS = ROS_only;
449  }
450  else
451  {
452  yCInfo(ANALOGWRAPPER) << sensorId << "useROS parameter is set to unvalid value ('" << ros_use_type << "'), supported values are 'true', 'false', 'only'";
453  useROS = ROS_config_error;
454  return false;
455  }
456 
457  // check for ROS_nodeName parameter
458  if(!rosGroup.check("ROS_nodeName"))
459  {
460  yCError(ANALOGWRAPPER) << sensorId << " cannot find ROS_nodeName parameter, mandatory when using ROS message";
461  useROS = ROS_config_error;
462  return false;
463  }
464  rosNodeName = rosGroup.find("ROS_nodeName").asString(); // TODO: check name is correct
465  yCInfo(ANALOGWRAPPER) << sensorId << "rosNodeName is " << rosNodeName;
466 
467  // check for ROS_topicName parameter
468  if(!rosGroup.check("ROS_topicName"))
469  {
470  yCError(ANALOGWRAPPER) << sensorId << " cannot find ROS_topicName parameter, mandatory when using ROS message";
471  useROS = ROS_config_error;
472  return false;
473  }
474 
475  if(rosGroup.find("ROS_topicName").isString())
476  {
477  rosTopicNamesVec.at(0) = rosGroup.find("ROS_topicName").asString();
478  yCInfo(ANALOGWRAPPER) << sensorId << "ROS_topicName is " << rosTopicNamesVec.at(0);
479 
480  }
481  else if(rosGroup.find("ROS_topicName").isList())
482  {
483  yarp::os::Bottle *rosTopicNamesBottle = rosGroup.find("ROS_topicName").asList();
484  yCInfo(ANALOGWRAPPER) << sensorId << "ROS_topicName list is " << rosTopicNamesBottle->toString();
485 
486  rosTopicNamesVec.resize(rosTopicNamesBottle->size());
487  for(size_t i = 0; i < rosTopicNamesBottle->size(); i++)
488  {
489  rosTopicNamesVec.at(i) = rosTopicNamesBottle->get(i).asString();
490  }
491 
492  // resize the ros msg counter vector
493  rosMsgCounterVec.resize(rosTopicNamesVec.size());
494  }
495 
496  // check for ROS_msgType parameter
497  if (!rosGroup.check("ROS_msgType"))
498  {
499  yCError(ANALOGWRAPPER) << sensorId << " cannot find ROS_msgType parameter, mandatory when using ROS message";
500  useROS = ROS_config_error;
501  return false;
502  }
503  rosMsgType = rosGroup.find("ROS_msgType").asString();
504 
505  // check for frame_id parameter
506  if (rosMsgType == "geometry_msgs/WrenchStamped")
507  {
508  yCInfo(ANALOGWRAPPER) << sensorId << "ROS_msgType is " << rosMsgType;
509  if (!rosGroup.check("frame_id"))
510  {
511  yCError(ANALOGWRAPPER) << sensorId << " cannot find frame_id parameter, mandatory when using ROS message";
512  useROS = ROS_config_error;
513  return false;
514  }
515 
516  if(rosGroup.find("frame_id").isString())
517  {
518  frame_idVec.at(0) = rosGroup.find("frame_id").asString();
519  yCInfo(ANALOGWRAPPER) << sensorId << "frame_id is " << frame_idVec.at(0);
520 
521  }
522  else if(rosGroup.find("frame_id").isList())
523  {
524  yarp::os::Bottle *frame_idBottle = rosGroup.find("frame_id").asList();
525 
526  if(frame_idBottle->size() != rosTopicNamesVec.size())
527  {
528  yCError(ANALOGWRAPPER, "AnalogWrapper: mismatch between the number of ros topics and frame_ids");
529  return false;
530  }
531 
532  yCInfo(ANALOGWRAPPER) << sensorId << "frame_id list is " << frame_idBottle->toString();
533 
534  frame_idVec.resize(frame_idBottle->size());
535  for(size_t i = 0; i < frame_idBottle->size(); i++)
536  {
537  frame_idVec.at(i) = frame_idBottle->get(i).asString();
538  }
539  }
540 
541  if(!rosGroup.check("rosOffset"))
542  {
543  yCWarning(ANALOGWRAPPER) << sensorId << "cannot find rosOffset parameter, using the default offset 0 while reading analog sensor data";
544  }
545 
546  if(rosGroup.find("rosOffset").isInt32())
547  {
548  rosOffset = rosGroup.find("rosOffset").asInt32();
549  yCInfo(ANALOGWRAPPER) << sensorId << " rosOffset is " << rosOffset;
550  }
551 
552  if(!rosGroup.check("rosPadding"))
553  {
554  yCWarning(ANALOGWRAPPER) << sensorId << "cannot find rosPadding parameter, using the default padding 0 while reading analog sensor data";
555  }
556 
557  if(rosGroup.find("rosPadding").isInt32())
558  {
559  rosOffset = rosGroup.find("rosPadding").asInt32();
560  yCInfo(ANALOGWRAPPER) << sensorId << " rosPadding is " << rosOffset;
561  }
562  }
563  else if (rosMsgType == "sensor_msgs/JointState")
564  {
565  std::string jointName;
566  yCInfo(ANALOGWRAPPER) << sensorId << "ROS_msgType is " << rosMsgType;
567  bool oldParam = false;
568  bool newParam = false;
569 
570  if(rosGroup.check("joint_names"))
571  {
572  oldParam = true;
573  jointName = "joint_names";
574  yCWarning(ANALOGWRAPPER) << sensorId << " using DEPRECATED 'joint_names' parameter. Please use 'jointNames' instead.";
575  }
576 
577  if(rosGroup.check("jointNames"))
578  {
579  newParam = true;
580  jointName = "jointNames";
581  }
582 
583  if(!oldParam && !newParam)
584  {
585  yCError(ANALOGWRAPPER) << sensorId << " missing 'jointNames' parameter needed when broadcasting 'sensor_msgs/JointState' message type";
586  useROS = ROS_config_error;
587  return false;
588  }
589  // Throw an error if both new and old are present
590  if(oldParam && newParam)
591  {
592  yCError(ANALOGWRAPPER) << sensorId << " found both DEPRECATED 'joint_names' and new 'jointNames' parameters. Please remove the old 'joint_names' from your config file.";
593  useROS = ROS_config_error;
594  return false;
595  }
596 
597  yarp::os::Bottle& jnam = rosGroup.findGroup(jointName);
598  if(jnam.isNull())
599  {
600  yCError(ANALOGWRAPPER) << sensorId << "Cannot find 'jointNames' parameters.";
601  return false;
602  }
603 
604  // Cannot check number of channels here because need to wait for the attach function
605  int joint_names_size = jnam.size()-1;
606  for (int i = 0; i < joint_names_size; i++)
607  {
608  ros_joint_names.push_back(jnam.get(i+1).asString());
609  }
610  }
611  else
612  {
613  yCError(ANALOGWRAPPER) << sensorId << "ROS_msgType '" << rosMsgType << "' not supported ";
614  return false;
615  }
616 
617  return true;
618 }
619 
620 bool AnalogWrapper::initialize_ROS()
621 {
622  bool success = false;
623  switch(useROS)
624  {
625  case ROS_enabled:
626  case ROS_only:
627  {
628  rosNode = new yarp::os::Node(rosNodeName); // add a ROS node
629 
630  if(rosNode == nullptr)
631  {
632  yCError(ANALOGWRAPPER) << " opening " << rosNodeName << " Node, check your yarp-ROS network configuration\n";
633  success = false;
634  break;
635  }
636 
637  if (rosMsgType == "geometry_msgs/WrenchStamped")
638  {
639  rosPublisherWrenchPortVec.resize(rosTopicNamesVec.size());
640 
641  for(size_t i = 0; i < rosTopicNamesVec.size(); i++)
642  {
643  if(!rosPublisherWrenchPortVec.at(i).topic(rosTopicNamesVec.at(i)))
644  {
645  yCError(ANALOGWRAPPER) << " opening " << rosTopicNamesVec.at(i) << " Topic, check your yarp-ROS network configuration\n";
646  success = false;
647  break;
648  }
649  }
650  }
651  else if (rosMsgType == "sensor_msgs/JointState")
652  {
653  if (!rosPublisherJointPort.topic(rosTopicNamesVec.at(0)))
654  {
655  yCError(ANALOGWRAPPER) << " opening " << rosTopicNamesVec.at(0) << " Topic, check your yarp-ROS network configuration\n";
656  success = false;
657  break;
658  }
659  }
660  else
661  {
662  yCError(ANALOGWRAPPER) << sensorId << "Invalid rosMsgType: " << rosMsgType;
663  }
664 
665  yCInfo(ANALOGWRAPPER) << sensorId << "ROS initialized successfully, node:" << rosNodeName << " and opened the following topics: ";
666  for(size_t i = 0; i < rosTopicNamesVec.size(); i++)
667  {
668  yCInfo(ANALOGWRAPPER) << rosTopicNamesVec.at(0);
669  }
670 
671  success = true;
672  } break;
673 
674  case ROS_disabled:
675  {
676  yCInfo(ANALOGWRAPPER) << sensorId << ": no ROS initialization required";
677  success = true;
678  } break;
679 
680  case ROS_config_error:
681  {
682  yCError(ANALOGWRAPPER) << sensorId << " ROS parameter are not correct, check your configuration file";
683  success = false;
684  } break;
685 
686  default:
687  {
688  yCError(ANALOGWRAPPER) << sensorId << " something went wrong with ROS configuration, we should never be here!!!";
689  success = false;
690  } break;
691  }
692  return success;
693 }
694 
696 {
697  Property params;
698  params.fromString(config.toString());
699  yCTrace(ANALOGWRAPPER) << "AnalogWrapper params are: " << config.toString();
700 
701  if (!config.check("period"))
702  {
703  yCError(ANALOGWRAPPER) << "AnalogWrapper: missing 'period' parameter. Check you configuration file\n";
704  return false;
705  }
706  else
707  {
708  _rate = config.find("period").asInt32();
709  }
710 
711  if (config.check("deviceId"))
712  {
713  yCError(ANALOGWRAPPER) << "AnalogWrapper: the parameter 'deviceId' has been removed, please use parameter 'name' instead. \n"
714  << "e.g. In the FT wrapper configuration files of your robot, replace '<param name=""deviceId""> left_arm </param>' \n"
715  << "with '/icub/left_arm/analog:o' ";
716  return false;
717  }
718 
719  if (!config.check("name"))
720  {
721  yCError(ANALOGWRAPPER) << "AnalogWrapper: missing 'name' parameter. Check you configuration file; it must be like:\n"
722  " name: full name of the port, like /robotName/deviceId/sensorType:o";
723  return false;
724  }
725  else
726  {
727  streamingPortName = config.find("name").asString();
728  setId("AnalogServer");
729  }
730 
731  if(!checkROSParams(config) )
732  {
733  yCError(ANALOGWRAPPER) << sensorId << "ROS parameter are not correct, check your configuration file";
734  return false;
735  }
736 
737  if(!initialize_YARP(config) )
738  {
739  yCError(ANALOGWRAPPER) << sensorId << "Error initializing YARP ports";
740  return false;
741  }
742 
743  if(!initialize_ROS() )
744  {
745  yCError(ANALOGWRAPPER) << sensorId << "Error initializing ROS topics";
746  return false;
747  }
748 
749  // check if we need to create subdevice or if they are
750  // passed later on thorugh attachAll()
751  if(config.check("subdevice"))
752  {
753  ownDevices=true;
754  if(! openAndAttachSubDevice(config))
755  {
756  yCError(ANALOGWRAPPER, "AnalogWrapper: error while opening subdevice\n");
757  return false;
758  }
759  }
760  else
761  {
762  ownDevices=false;
763  if(!openDeferredAttach(config))
764  return false;
765  }
766 
767  return true;
768 }
769 
770 bool AnalogWrapper::initialize_YARP(yarp::os::Searchable &params)
771 {
772  switch(useROS)
773  {
774  case ROS_only:
775  {
776  yCInfo(ANALOGWRAPPER) << sensorId << " No YARP initialization required";
777  return true;
778  } break;
779 
780  default:
781  {
782  // Create the list of ports
783  // port names are optional, do not check for correctness.
784  if(!params.check("ports"))
785  {
786  // if there is no "ports" section open only 1 port and use name as is.
787  if (Network::exists(streamingPortName + "/rpc:i") || Network::exists(streamingPortName))
788  {
789  yCError(ANALOGWRAPPER) << "AnalogWrapper: unable to open the analog server, address conflict";
790  return false;
791  }
792  createPort((streamingPortName ).c_str(), _rate );
793  // since createPort always return true, check the port is really been opened is done here
794  if(! Network::exists(streamingPortName + "/rpc:i"))
795  return false;
796  }
797  else
798  {
799  Bottle *ports=params.find("ports").asList();
800 
801  Value &deviceChannels = params.find("channels");
802  if (deviceChannels.isNull())
803  {
804  yCError(ANALOGWRAPPER, "AnalogWrapper: 'channels' parameters was not found in config file.");
805  return false;
806  }
807 
808  int nports=ports->size();
809  int sumOfChannels = 0;
810  std::vector<AnalogPortEntry> tmpPorts;
811  tmpPorts.resize(nports);
812 
813  for(size_t k=0; k<ports->size(); k++)
814  {
815  Bottle parameters=params.findGroup(ports->get(k).asString());
816 
817  if (parameters.size()!=5)
818  {
819  yCError(ANALOGWRAPPER) << "AnalogWrapper: check skin port parameters in part description, I was expecting "
820  << ports->get(k).asString().c_str() << " followed by four integers";
821  yCError(ANALOGWRAPPER) << " your param is " << parameters.toString();
822  return false;
823  }
824 
825  if (Network::exists(streamingPortName + "/" + string(ports->get(k).asString()) + "/rpc:i")
826  || Network::exists(streamingPortName + "/" + string(ports->get(k).asString())))
827  {
828  yCError(ANALOGWRAPPER) << "AnalogWrapper: unable to open the analog server, address conflict";
829  return false;
830  }
831  int wBase=parameters.get(1).asInt32();
832  int wTop=parameters.get(2).asInt32();
833  int base=parameters.get(3).asInt32();
834  int top=parameters.get(4).asInt32();
835 
836  yCDebug(ANALOGWRAPPER) << "--> " << wBase << " " << wTop << " " << base << " " << top;
837 
838  //check consistenty
839  if(wTop-wBase != top-base){
840  yCError(ANALOGWRAPPER) << "AnalogWrapper: numbers of mapped taxels do not match, check "
841  << ports->get(k).asString().c_str() << " port parameters in part description";
842  return false;
843  }
844  int portChannels = top-base+1;
845 
846  tmpPorts[k].length = portChannels;
847  tmpPorts[k].offset = wBase;
848  yCDebug(ANALOGWRAPPER) << "opening port " << ports->get(k).asString().c_str();
849  tmpPorts[k].port_name = streamingPortName+ "/" + string(ports->get(k).asString());
850 
851  sumOfChannels+=portChannels;
852  }
853  createPorts(tmpPorts, _rate);
854 
855  if (sumOfChannels!=deviceChannels.asInt32())
856  {
857  yCError(ANALOGWRAPPER) << "AnalogWrapper: Total number of mapped taxels does not correspond to total taxels";
858  return false;
859  }
860  }
861  } break;
862  }
863  return true;
864 }
865 
867 {
868  for(auto& analogPort : analogPorts)
869  {
870  analogPort.port.interrupt();
871  analogPort.port.close();
872  }
873 }
874 
876 {
877  int first, last, ret;
878 
879  if (analogSensor_p!=nullptr)
880  {
881  ret=analogSensor_p->read(lastDataRead);
882 
884  {
885  if (lastDataRead.size()>0)
886  {
887  if(useROS != ROS_only)
888  {
889  lastStateStamp.update();
890  // send the data on the port(s), splitting them as specified in the config file
891  for(auto& analogPort : analogPorts)
892  {
893  yarp::sig::Vector &pv = analogPort.port.prepare();
894  first = analogPort.offset;
895  if(analogPort.length == -1) // read the max length available
896  last = lastDataRead.size()-1;
897  else
898  last = analogPort.offset + analogPort.length - 1;
899 
900  // check vector limit
901  if(last>=(int)lastDataRead.size()){
902  yCError(ANALOGWRAPPER, )<<"AnalogWrapper: error while sending analog sensor output on port "<< analogPort.port_name
903  <<" Vector size expected to be at least "<<last<<" whereas it is "<< lastDataRead.size();
904  continue;
905  }
906  pv = lastDataRead.subVector(first, last);
907 
908  analogPort.port.setEnvelope(lastStateStamp);
909  analogPort.port.write();
910  }
911  }
912 
913  if (useROS != ROS_disabled && rosMsgType == "geometry_msgs/WrenchStamped")
914  {
915  std::vector<yarp::rosmsg::geometry_msgs::WrenchStamped> rosDataVec;
916  rosDataVec.resize(rosPublisherWrenchPortVec.size());
917 
918  for(size_t i = 0; i < rosDataVec.size(); i++)
919  {
920  rosDataVec.at(i).header.seq = rosMsgCounterVec.at(i)++;
921  rosDataVec.at(i).header.stamp = yarp::os::Time::now();
922  rosDataVec.at(i).header.frame_id = frame_idVec.at(i);
923 
924  rosDataVec.at(i).wrench.force.x = lastDataRead[(rosOffset + 6 + rosPadding) * i + 0];
925  rosDataVec.at(i).wrench.force.y = lastDataRead[(rosOffset + 6 + rosPadding) * i + 1];
926  rosDataVec.at(i).wrench.force.z = lastDataRead[(rosOffset + 6 + rosPadding) * i + 2];
927 
928  rosDataVec.at(i).wrench.torque.x = lastDataRead[(rosOffset + 6 + rosPadding) * i + 3];
929  rosDataVec.at(i).wrench.torque.y = lastDataRead[(rosOffset + 6 + rosPadding) * i + 4];
930  rosDataVec.at(i).wrench.torque.z = lastDataRead[(rosOffset + 6 + rosPadding) * i + 5];
931 
932  rosPublisherWrenchPortVec.at(i).write(rosDataVec.at(i));
933  }
934  }
935  else if (useROS != ROS_disabled && rosMsgType == "sensor_msgs/JointState")
936  {
938  size_t data_size = lastDataRead.size();
939  rosData.name.resize(data_size);
940  rosData.position.resize(data_size);
941  rosData.velocity.resize(data_size);
942  rosData.effort.resize(data_size);
943 
944  if (data_size != ros_joint_names.size())
945  {
946  yCDebug(ANALOGWRAPPER) << "Invalid jointNames size:" << data_size << "!=" << ros_joint_names.size();
947  }
948  else
949  {
950  for (size_t i = 0; i< data_size; i++)
951  {
952  //JointTypeEnum jType;
953  // if (jType == VOCAB_JOINTTYPE_REVOLUTE)
954  {
955  rosData.name[i] = ros_joint_names[i];
956  rosData.position[i] = convertDegreesToRadians(lastDataRead[i]);
957  rosData.velocity[i] = 0;
958  rosData.effort[i] = 0;
959  }
960  }
961  }
962  rosData.header.seq = rosMsgCounterVec.at(0)++;
963  rosData.header.stamp = yarp::os::Time::now();
964  rosPublisherJointPort.write(rosData);
965  }
966  }
967  else
968  {
969  yCError(ANALOGWRAPPER, "AnalogWrapper: %s: vector size non valid: %lu", sensorId.c_str(), static_cast<unsigned long> (lastDataRead.size()));
970  }
971  }
972  else
973  {
974  switch(ret)
975  {
976  case IAnalogSensor::AS_OVF:
977  yCError(ANALOGWRAPPER, "AnalogWrapper: %s: Sensor returned overflow error (code %d).", sensorId.c_str(), ret);
978  break;
979  case IAnalogSensor::AS_TIMEOUT:
980  yCError(ANALOGWRAPPER, "AnalogWrapper: %s: Sensor returned timeout error (code %d).", sensorId.c_str(), ret);
981  break;
982  case IAnalogSensor::AS_ERROR:
983  default:
984  yCError(ANALOGWRAPPER, "AnalogWrapper: %s: Sensor returned error with code %d.", sensorId.c_str(), ret);
985  break;
986  }
987  }
988  }
989 }
990 
992 {
993  yCTrace(ANALOGWRAPPER, "AnalogWrapper::Close");
994  if (PeriodicThread::isRunning())
995  {
996  PeriodicThread::stop();
997  }
998 
999  detachAll();
1000  removeHandlers();
1001 
1002  if(subDeviceOwned)
1003  {
1004  subDeviceOwned->close();
1005  delete subDeviceOwned;
1006  subDeviceOwned = nullptr;
1007  }
1008 
1009  if(rosNode!=nullptr) {
1010  rosNode->interrupt();
1011  delete rosNode;
1012 
1013  rosNode = nullptr;
1014  }
1015 
1016  return true;
1017 }
yarp::os::Port::close
void close() override
Stop port activity.
Definition: Port.cpp:357
LogStream.h
ROS_only
@ ROS_only
Definition: yarpRosHelper.h:23
yarp::os::Bottle
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
AnalogServerHandler::~AnalogServerHandler
~AnalogServerHandler()
Definition: AnalogWrapper.cpp:75
yarp::os::Value::asVocab
virtual std::int32_t asVocab() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:231
yarp::dev::IAnalogSensor::AS_OK
@ AS_OK
Definition: IAnalogSensor.h:35
yarp::os::Bottle::toString
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:214
yarp::os::Property::put
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:998
yarp::os::Bottle::clear
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:124
yarp::sig::VectorOf::resize
void resize(size_t size) override
Resize the vector.
Definition: Vector.h:254
yarp::os::Searchable
A base class for nested structures that can be searched.
Definition: Searchable.h:69
yarp::sig::file::read
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:827
yarp::os::Bottle::size
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:254
AnalogPortEntry::offset
int offset
Definition: AnalogWrapper.cpp:56
yarp::sig
Signal processing.
Definition: Image.h:25
AnalogWrapper::AnalogWrapper
AnalogWrapper()
Definition: AnalogWrapper.cpp:216
yarp::os::Searchable::findGroup
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
AnalogPortEntry::length
int length
Definition: AnalogWrapper.cpp:57
yCWarning
#define yCWarning(component,...)
Definition: LogComponent.h:146
yarp::os::Searchable::toString
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
yarp::os::Property::fromString
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1046
yarp::dev::PolyDriverList::size
int size() const
Definition: PolyDriverList.cpp:39
yarp::dev::PolyDriver::isValid
bool isValid() const
Check if device is valid.
Definition: PolyDriver.cpp:199
yarp::dev::IAnalogSensor::calibrateSensor
virtual int calibrateSensor()=0
Calibrates the whole sensor.
AnalogWrapper::~AnalogWrapper
~AnalogWrapper() override
Definition: AnalogWrapper.cpp:228
YARP_LOG_COMPONENT
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
AnalogPortEntry::port
yarp::os::BufferedPort< yarp::sig::Vector > port
Definition: AnalogWrapper.cpp:54
ROS_enabled
@ ROS_enabled
Definition: yarpRosHelper.h:22
convertDegreesToRadians
double convertDegreesToRadians(double degrees)
convert degrees to radiants for ROS messages
Definition: yarpRosHelper.h:30
AnalogWrapper::threadInit
bool threadInit() override
Initialization method.
Definition: AnalogWrapper.cpp:381
AnalogPortEntry::AnalogPortEntry
AnalogPortEntry()
A yarp port that output data read from an analog sensor.
Definition: AnalogWrapper.cpp:167
yarp::dev::DeviceDriver::view
bool view(T *&x)
Get an interface to the device driver.
Definition: DeviceDriver.h:77
yarp::os::Port::open
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition: Port.cpp:82
yarp::rosmsg::sensor_msgs::JointState::effort
std::vector< yarp::conf::float64_t > effort
Definition: JointState.h:62
ret
bool ret
Definition: ImplementAxisInfo.cpp:72
yarp::dev::PolyDriverList
Definition: PolyDriverList.h:22
ControlBoardInterfaces.h
define control board standard interfaces
yarp::dev::PolyDriver::open
bool open(const std::string &txt)
Construct and configure a device by its common name.
Definition: PolyDriver.cpp:143
yarp::os::Bottle::find
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:290
yarp::os::Time::now
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
yarp::dev
An interface for the device drivers.
Definition: audioBufferSizeData.cpp:17
AnalogWrapper::detachAll
bool detachAll() override
Detach the object (you must have first called attach).
Definition: AnalogWrapper.cpp:344
AnalogServerHandler::_handleIAnalog
bool _handleIAnalog(yarp::os::Bottle &cmd, yarp::os::Bottle &reply)
Definition: AnalogWrapper.cpp:86
yarp::sig::VectorOf< double >
yarp::os::Port
A mini-server for network communication.
Definition: Port.h:50
yarp::os::BufferedPort< yarp::sig::Vector >
yarp::os::Bottle::check
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Bottle.cpp:280
AnalogWrapper::attachAll
bool attachAll(const yarp::dev::PolyDriverList &p) override
Specify which analog sensor this thread has to read from.
Definition: AnalogWrapper.cpp:315
yarp::os::Bottle::findGroup
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
Definition: Bottle.cpp:305
yarp::rosmsg::std_msgs::Header::seq
std::uint32_t seq
Definition: Header.h:47
yarp::os::Value::isString
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:159
yarp::dev::IAnalogSensor::read
virtual int read(yarp::sig::Vector &out)=0
Read a vector from the sensor.
yarp::os::Publisher::topic
bool topic(const std::string &name)
Set topic to publish to.
Definition: Publisher.h:67
yarp::rosmsg::sensor_msgs::JointState::velocity
std::vector< yarp::conf::float64_t > velocity
Definition: JointState.h:61
yarp::dev::IAnalogSensor::calibrateChannel
virtual int calibrateChannel(int ch)=0
Calibrates one single channel.
yarp::os::PortReader
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
Definition: PortReader.h:28
yarp::os::Bottle::get
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
AnalogWrapper::close
bool close() override
Close the DeviceDriver.
Definition: AnalogWrapper.cpp:991
yarp::os::Publisher::write
void write(bool forceStrict=false)
Write the current object being returned by Publisher::prepare.
Definition: Publisher.h:152
yarp::os::Bottle::write
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition: Bottle.cpp:233
AnalogPortEntry::operator=
AnalogPortEntry & operator=(const AnalogPortEntry &alt)
Definition: AnalogWrapper.cpp:179
yarp::os::ConnectionWriter
An interface for writing to a network connection.
Definition: ConnectionWriter.h:40
AnalogWrapper::setId
void setId(const std::string &id)
Definition: AnalogWrapper.cpp:395
handler
static void handler(int sig)
Definition: RFModule.cpp:244
AnalogWrapper::detach
void detach()
Definition: AnalogWrapper.cpp:371
yarp::os::Value::asString
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
yarp::dev::PolyDriver
A container for a device driver.
Definition: PolyDriver.h:27
VOCAB_FAILED
constexpr yarp::conf::vocab32_t VOCAB_FAILED
Definition: GenericVocabs.h:19
yarp::dev::PolyDriver::close
bool close() override
Close the DeviceDriver.
Definition: PolyDriver.cpp:176
ROS_disabled
@ ROS_disabled
Definition: yarpRosHelper.h:21
yarp::os::Searchable::check
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
yarp::os::PeriodicThread::setPeriod
bool setPeriod(double period)
Set the (new) period of the thread.
Definition: PeriodicThread.cpp:281
AnalogWrapper::threadRelease
void threadRelease() override
Release method.
Definition: AnalogWrapper.cpp:866
yarp::os::Value::isNull
bool isNull() const override
Checks if the object is invalid.
Definition: Value.cpp:383
yarp::os::Searchable::find
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
AnalogWrapper::run
void run() override
Loop function.
Definition: AnalogWrapper.cpp:875
yarp::os::Bottle::addInt32
void addInt32(std::int32_t x)
Places a 32-bit integer in the bottle, at the end of the list.
Definition: Bottle.cpp:143
yarp::rosmsg::sensor_msgs::JointState::header
yarp::rosmsg::std_msgs::Header header
Definition: JointState.h:58
AnalogPortEntry
A yarp port that output data read from an analog sensor.
Definition: AnalogWrapper.cpp:52
yarp::dev::IAnalogSensor
A generic interface to sensors (gyro, a/d converters).
Definition: IAnalogSensor.h:31
yarp::os::Node
The Node class.
Definition: Node.h:27
AnalogWrapper::getId
std::string getId()
Definition: AnalogWrapper.cpp:400
yarp::os::ConnectionReader::getWriter
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
yarp::os::Port::setReader
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition: Port.cpp:505
yarp::os::PeriodicThread
An abstraction for a periodic thread.
Definition: PeriodicThread.h:25
yarp::os::Bottle::addVocab
void addVocab(int x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:167
LogComponent.h
yarp::os::Value::isList
virtual bool isList() const
Checks if value is a list.
Definition: Value.cpp:165
yarp::os::Bottle::isNull
bool isNull() const override
Checks if the object is invalid.
Definition: Bottle.cpp:373
yarp::os::ConnectionReader
An interface for reading from a network connection.
Definition: ConnectionReader.h:40
AnalogWrapper::attach
void attach(yarp::dev::IAnalogSensor *s)
Definition: AnalogWrapper.cpp:359
AnalogPortEntry::port_name
std::string port_name
Definition: AnalogWrapper.cpp:55
yCError
#define yCError(component,...)
Definition: LogComponent.h:157
yarp::os::Value::asInt32
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:207
yarp::os::Stamp::update
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Stamp.cpp:113
yCInfo
#define yCInfo(component,...)
Definition: LogComponent.h:135
yarp::os
An interface to the operating system, including Port based communication.
Definition: AbstractCarrier.h:17
yCDebug
#define yCDebug(component,...)
Definition: LogComponent.h:112
AnalogWrapper::open
bool open(yarp::os::Searchable &params) override
Open the DeviceDriver.
Definition: AnalogWrapper.cpp:695
DEFAULT_THREAD_PERIOD
#define DEFAULT_THREAD_PERIOD
Definition: AnalogWrapper.h:45
yarp
The main, catch-all namespace for YARP.
Definition: environment.h:18
yarp::rosmsg::sensor_msgs::JointState::name
std::vector< std::string > name
Definition: JointState.h:59
yarp::rosmsg::sensor_msgs::JointState
Definition: JointState.h:56
AnalogServerHandler
Handler of the rpc port related to an analog sensor.
Definition: AnalogWrapper.cpp:30
yarp::os::Bottle::read
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:243
yarp::os::Value::asList
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:243
yarp::os::Node::interrupt
void interrupt()
interrupt delegates the call to the Node port interrupt.
Definition: Node.cpp:600
AnalogServerHandler::read
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
Definition: AnalogWrapper.cpp:132
AnalogServerHandler::setInterface
void setInterface(yarp::dev::IAnalogSensor *is)
Definition: AnalogWrapper.cpp:81
AnalogWrapper.h
yarp::sig::VectorOf::size
size_t size() const
Definition: Vector.h:355
yarp::dev::IAnalogSensor::getChannels
virtual int getChannels()=0
Get the number of channels of the sensor.
AnalogServerHandler::AnalogServerHandler
AnalogServerHandler(const char *n)
Handler of the rpc port related to an analog sensor.
Definition: AnalogWrapper.cpp:69
yCTrace
#define yCTrace(component,...)
Definition: LogComponent.h:88
ANALOGWRAPPER
const yarp::os::LogComponent & ANALOGWRAPPER()
Definition: AnalogWrapper.cpp:22
yarp::os::Value
A single value (typically within a Bottle).
Definition: Value.h:47
yarp::rosmsg::sensor_msgs::JointState::position
std::vector< yarp::conf::float64_t > position
Definition: JointState.h:60
ROS_config_error
@ ROS_config_error
Definition: yarpRosHelper.h:20
VOCAB_IANALOG
constexpr yarp::conf::vocab32_t VOCAB_IANALOG
Definition: IAnalogSensor.h:17
yarp::os::Property::unput
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
Definition: Property.cpp:1029
yarp::os::Value::asFloat64
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:225
yarp::rosmsg::std_msgs::Header::stamp
yarp::rosmsg::TickTime stamp
Definition: Header.h:48
yarp::sig::VectorOf::subVector
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:433
VOCAB_CALIBRATE_CHANNEL
constexpr yarp::conf::vocab32_t VOCAB_CALIBRATE_CHANNEL
Definition: IControlCalibration.h:147
yarp::os::Property
A class for storing options and configuration information.
Definition: Property.h:37
VOCAB_CALIBRATE
constexpr yarp::conf::vocab32_t VOCAB_CALIBRATE
Definition: IControlCalibration.h:146
yarp::os::Value::isInt32
virtual bool isInt32() const
Checks if value is a 32-bit integer.
Definition: Value.cpp:135