YARP
Yet Another Robot Platform
xmlapploader.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 
10 #include <yarp/manager/utility.h>
11 #include <yarp/conf/filesystem.h>
12 #include <dirent.h>
13 #include <tinyxml.h>
14 #include <yarp/os/Value.h>
15 #ifdef WITH_GEOMETRY
16 #include <yarp/os/Property.h> // for parsing geometry information
17 #endif
18 
19 #include <algorithm>
20 #include <cctype>
21 #include <string>
22 #include <fstream>
24 
25 
26 
27 using namespace std;
28 using namespace yarp::manager;
29 
30 
36 XmlAppLoader::XmlAppLoader(const char* szPath, const char* szAppName)
37 {
38  parser = new(TextParser);
39  app.clear();
40  if(szAppName)
41  strAppName = szAppName;
42 
43  if(strlen(szPath))
44  {
45  const std::string directorySeparator{yarp::conf::filesystem::preferred_separator};
46  strPath = szPath;
47  if((strPath.rfind(directorySeparator)==string::npos) ||
48  (strPath.rfind(directorySeparator)!=strPath.size()-1))
49  strPath = strPath + string(directorySeparator);
50  }
51 }
52 
56 XmlAppLoader::XmlAppLoader(const char* szFileName)
57 {
58  parser = new(TextParser);
59  app.clear();
60  if(szFileName)
61  strFileName = szFileName;
62 }
63 
64 
65 XmlAppLoader::~XmlAppLoader()
66 {
67  if(parser)
68  {
69  delete parser;
70  }
71 }
72 
73 
74 bool XmlAppLoader::init()
75 {
76  app.clear();
77  fileNames.clear();
78  ErrorLogger* logger = ErrorLogger::Instance();
79 
83  if(!strFileName.empty())
84  {
85  fileNames.push_back(strFileName);
86  return true;
87  }
88 
89  if(strPath.empty())
90  {
91  logger->addError("No application path is introduced.");
92  return false;
93  }
94 
95  DIR *dir;
96  struct dirent *entry;
97  if ((dir = opendir(strPath.c_str())) == nullptr)
98  {
99  OSTRINGSTREAM err;
100  err<<"Cannot access "<<strPath;
101  logger->addError(err);
102  return false;
103  }
104 
105  /* we need to load all xml apps */
106  while((entry = readdir(dir)))
107  {
108  string name = entry->d_name;
109  if(name.size() > 3)
110  {
111  string ext = name.substr(name.size()-3,3);
112  if(compareString(ext.c_str(), "xml"))
113  fileNames.push_back(strPath+name);
114  }
115  }
116  closedir(dir);
117 /*
118  if(fileNames.empty())
119  {
120  OSTRINGSTREAM err;
121  err<<"No xml application file found in "<<strPath;
122  logger->addWarning(err);
123  //return false;
124  }
125 */
126  return true;
127 }
128 
129 void XmlAppLoader::reset()
130 {
131  fini();
132  init();
133 }
134 
135 
136 void XmlAppLoader::fini()
137 {
138  fileNames.clear();
139  app.clear();
140 }
141 
142 
143 Application* XmlAppLoader::getNextApplication()
144 {
145  if(strAppName.empty())
146  {
147  Application* app = nullptr;
148  while(!app)
149  {
150  if(fileNames.empty())
151  return nullptr;
152  string fname = fileNames.back();
153  fileNames.pop_back();
154  app = parsXml(fname.c_str());
155  }
156  return app;
157  }
158  else
159  {
160  vector<string>::iterator itr;
161  for(itr=fileNames.begin(); itr<fileNames.end(); itr++)
162  {
163  Application* app = parsXml((*itr).c_str());
164  if(app && (string(app->getName())==strAppName))
165  return app;
166  }
167  }
168  return nullptr;
169 }
170 
171 Application* XmlAppLoader::parsXml(const char* szFile)
172 {
173  app.clear();
174 
175  ErrorLogger* logger = ErrorLogger::Instance();
176 
177  TiXmlDocument doc(szFile);
178  if(!doc.LoadFile())
179  {
180  OSTRINGSTREAM err;
181  err<<"Syntax error while loading "<<szFile<<" at line "\
182  <<doc.ErrorRow()<<": ";
183  err<<doc.ErrorDesc();
184  logger->addError(err);
185  return nullptr;
186  }
187 
188  /* retrieving root element */
189  TiXmlElement *root = doc.RootElement();
190  if(!root)
191  {
192  OSTRINGSTREAM err;
193  err<<"Syntax error while loading "<<szFile<<" . ";
194  err<<"No root element.";
195  logger->addError(err);
196  return nullptr;
197  }
198 
199  if(!compareString(root->Value(), "application"))
200  {
201  //OSTRINGSTREAM err;
202  //err<<"File "<<szFile<<" has no tag <application>.";
203  //logger->addError(err);
204  return nullptr;
205  }
206 
207  /* retrieving name */
208  auto* name = (TiXmlElement*) root->FirstChild("name");
209  if(!name || !name->GetText())
210  {
211  OSTRINGSTREAM err;
212  err<<"Module from "<<szFile<<" has no name.";
213  logger->addError(err);
214  //return NULL;
215  }
216 
217  for(TiXmlElement* var = root->FirstChildElement("var"); var; var = var->NextSiblingElement())
218  {
219  if(var->Attribute("name") && var->GetText())
220  {
221  parser->addVariable(var->Attribute("name"), var->GetText());
222  }
223  }
224 
225  app.setXmlFile(szFile);
226 
227  if(name)
228  {
229  string strname = parser->parseText(name->GetText());
230  for(char& i : strname)
231  if(i == ' ')
232  i = '_';
233  app.setName(strname.c_str());
234  }
235 
236  /* retrieving description */
237  TiXmlElement* desc;
238  if((desc = (TiXmlElement*) root->FirstChild("description")))
239  app.setDescription(parser->parseText(desc->GetText()).c_str());
240 
241  /* retrieving version */
242  TiXmlElement* ver;
243  if((ver = (TiXmlElement*) root->FirstChild("version")))
244  app.setVersion(parser->parseText(ver->GetText()).c_str());
245 
246  /*
247  * TODO: setting prefix of the main application is inactivated.
248  * Check this should be supported in future or not!
249  */
250  /*
251  //retrieving application prefix
252  TiXmlElement* pref;
253  if((pref = (TiXmlElement*) root->FirstChild("prefix")))
254  app.setPrefix(pref->GetText());
255  */
256 
257  /* retrieving authors information*/
258  TiXmlElement* authors;
259  if((authors = (TiXmlElement*) root->FirstChild("authors")))
260  for(TiXmlElement* ath = authors->FirstChildElement(); ath;
261  ath = ath->NextSiblingElement())
262  {
263  if(compareString(ath->Value(), "author"))
264  {
265  Author author;
266  if(ath->GetText())
267  author.setName(parser->parseText(ath->GetText()).c_str());
268  if(ath->Attribute("email"))
269  author.setEmail(ath->Attribute("email"));
270  app.addAuthor(author);
271  }
272  else
273  {
274  OSTRINGSTREAM war;
275  war<<"Unrecognized tag from "<<szFile<<" at line "\
276  <<ath->Row()<<".";
277  logger->addWarning(war);
278  }
279  }
280 
281  /* retrieving resources information*/
282  TiXmlElement* resources;
283  if((resources = (TiXmlElement*) root->FirstChild("dependencies")))
284  for(TiXmlElement* res = resources->FirstChildElement(); res;
285  res = res->NextSiblingElement())
286  {
287  if(compareString(res->Value(), "port"))
288  {
289  if(res->GetText())
290  {
291  ResYarpPort resource(parser->parseText(res->GetText()).c_str());
292  resource.setPort(parser->parseText(res->GetText()).c_str());
293  app.addResource(resource);
294  }
295  }
296  else
297  {
298  OSTRINGSTREAM war;
299  war<<"Unrecognized tag from "<<szFile<<" at line "\
300  <<res->Row()<<".";
301  logger->addWarning(war);
302  }
303  }
304 
305  /* retrieving modules information*/
306  using setter = void (ModuleInterface::*)(const char*);
307 
308  vector<pair<const char*, setter> > modList;
309  pair<const char*, setter> pairNode;
310 
311  pairNode.first = "node"; pairNode.second = &ModuleInterface::setHost; modList.push_back(pairNode);
312  pairNode.first = "parameters"; pairNode.second = &ModuleInterface::setParam; modList.push_back(pairNode);
313  pairNode.first = "stdio"; pairNode.second = &ModuleInterface::setStdio; modList.push_back(pairNode);
314  pairNode.first = "workdir"; pairNode.second = &ModuleInterface::setWorkDir; modList.push_back(pairNode);
315  pairNode.first = "deployer"; pairNode.second = &ModuleInterface::setBroker; modList.push_back(pairNode);
316  pairNode.first = "prefix"; pairNode.second = &ModuleInterface::setPrefix; modList.push_back(pairNode);
317  pairNode.first = "environment"; pairNode.second = &ModuleInterface::setEnvironment; modList.push_back(pairNode);
318  pairNode.first = "display"; pairNode.second = &ModuleInterface::setDisplay; modList.push_back(pairNode);
319  for(TiXmlElement* mod = root->FirstChildElement(); mod; mod = mod->NextSiblingElement())
320  {
321  if(compareString(mod->Value(), "module"))
322  {
323  TiXmlElement* element;
324  if((element = (TiXmlElement*) mod->FirstChild("name")))
325  {
326  string elemText;
327  const char* text;
328 
329 
330  text = nullptr;
331  if(element->GetText())
332  {
333  elemText = parser->parseText(element->GetText());
334  text = elemText.c_str();
335  }
336 
337  ModuleInterface module(text);
338 
339  for(auto& i : modList)
340  {
341  if((element = (TiXmlElement*) mod->FirstChild(i.first)))
342  {
343  text = nullptr;
344  if(element->GetText())
345  {
346  elemText = parser->parseText(element->GetText());
347  text = elemText.c_str();
348  }
349 
350  (module.*(i.second))(text);
351  }
352  }
353 
354  if((element = (TiXmlElement*) mod->FirstChild("rank")))
355  {
356  if(element->GetText())
357  {
358  elemText = parser->parseText(element->GetText());
359  text = elemText.c_str();
360  }
361 
362  module.setRank(atoi(text));
363  }
364 
365 #ifdef WITH_GEOMETRY
366  element = (TiXmlElement*) mod->FirstChild("geometry");
367  if(element && element->GetText())
368  {
369  yarp::os::Property prop(parser->parseText(element->GetText()).c_str());
370  GraphicModel model;
371  GyPoint pt;
372  if(prop.check("Pos"))
373  {
374  pt.x = prop.findGroup("Pos").find("x").asFloat64();
375  pt.y = prop.findGroup("Pos").find("y").asFloat64();
376  model.points.push_back(pt);
377  module.setModelBase(model);
378  }
379  }
380 #endif
381  /* retrieving resources information*/
382  TiXmlElement* resources;
383  if((resources = (TiXmlElement*) mod->FirstChild("dependencies")))
384  {
385  for(TiXmlElement* res = resources->FirstChildElement(); res;
386  res = res->NextSiblingElement())
387  {
388  if(compareString(res->Value(), "port"))
389  {
390  if(res->GetText())
391  {
392  ResYarpPort resource(parser->parseText(res->GetText()).c_str());
393  resource.setPort(parser->parseText(res->GetText()).c_str());
394  if(res->Attribute("timeout"))
395  resource.setTimeout(atof(res->Attribute("timeout")));
396  if(res->Attribute("request"))
397  resource.setRequest(res->Attribute("request"));
398  if(res->Attribute("reply"))
399  resource.setReply(res->Attribute("reply"));
400  module.addResource(resource);
401  }
402  }
403  else
404  {
405  OSTRINGSTREAM war;
406  war<<"Unrecognized tag from "<<szFile<<" at line "\
407  <<res->Row()<<".";
408  logger->addWarning(war);
409  }
410  }
411  }
412 
413  /* retrieving resources information*/
414  TiXmlElement* ensure;
415  if((ensure = (TiXmlElement*) mod->FirstChild("ensure")))
416  {
417  for(TiXmlElement* res = ensure->FirstChildElement(); res;
418  res = res->NextSiblingElement())
419  {
420  if(compareString(res->Value(), "wait"))
421  {
422  if (res->Attribute("when") && compareString(res->Attribute("when"), "start")) {
423  if(parser->parseText(res->GetText()).c_str())
424  module.setPostExecWait(atof(parser->parseText(res->GetText()).c_str()));
425  }
426  else if (res->Attribute("when") && compareString(res->Attribute("when"), "stop")) {
427  if(parser->parseText(res->GetText()).c_str())
428  module.setPostStopWait(atof(parser->parseText(res->GetText()).c_str()));
429  }
430  else if (res->Attribute("when") && strlen(res->Attribute("when"))) {
431  OSTRINGSTREAM war;
432  war << "Unrecognized value for 'when' property from " << szFile << " at line "<< res->Row() << ".";
433  logger->addWarning(war);
434  }
435  else { // if "when" has not been specified, use setPostExecWait!
436  if(parser->parseText(res->GetText()).c_str())
437  module.setPostExecWait(atof(parser->parseText(res->GetText()).c_str()));
438  }
439  }
440  else
441  {
442  OSTRINGSTREAM war;
443  war<<"Unrecognized tag from "<<szFile<<" at line "\
444  <<res->Row()<<".";
445  logger->addWarning(war);
446  }
447  }
448  }
449  /* retrieving portmaps */
450  for(TiXmlElement* map = mod->FirstChildElement(); map;
451  map = map->NextSiblingElement())
452  if(compareString(map->Value(), "portmap"))
453  {
454  TiXmlElement* first;
455  TiXmlElement* second;
456  if((first=(TiXmlElement*) map->FirstChild("old")) &&
457  (second=(TiXmlElement*) map->FirstChild("new")) )
458  {
459  Portmap portmap(parser->parseText(first->GetText()).c_str(), parser->parseText(second->GetText()).c_str());
460  module.addPortmap(portmap);
461  }
462  }
463 
464  app.addImodule(module);
465  }
466  else
467  {
468  OSTRINGSTREAM war;
469  war<<"Module from "<<szFile<<" at line "\
470  <<mod->Row()<<" has not name tag.";
471  logger->addWarning(war);
472  }
473 
474  }
475  }
476 
477  /* retrieving embedded application information*/
478  for(TiXmlElement* embApp = root->FirstChildElement(); embApp;
479  embApp = embApp->NextSiblingElement())
480  {
481  if(compareString(embApp->Value(), "application"))
482  {
483  TiXmlElement* name;
484  TiXmlElement* prefix;
485  if((name=(TiXmlElement*) embApp->FirstChild("name")))
486  {
487  ApplicationInterface IApp(parser->parseText(name->GetText()).c_str());
488  if((prefix=(TiXmlElement*) embApp->FirstChild("prefix")))
489  IApp.setPrefix(parser->parseText(prefix->GetText()).c_str());
490 #ifdef WITH_GEOMETRY
491  auto* element = (TiXmlElement*) embApp->FirstChild("geometry");
492  if(element && element->GetText())
493  {
494  yarp::os::Property prop(parser->parseText(element->GetText()).c_str());
495  GraphicModel model;
496  GyPoint pt;
497  if(prop.check("Pos"))
498  {
499  pt.x = prop.findGroup("Pos").find("x").asFloat64();
500  pt.y = prop.findGroup("Pos").find("y").asFloat64();
501  model.points.push_back(pt);
502  IApp.setModelBase(model);
503  }
504  }
505 #endif
506  app.addIapplication(IApp);
507  }
508  else
509  {
510  OSTRINGSTREAM war;
511  war<<"Incomplete application tag from "<<szFile<<" at line "\
512  <<embApp->Row()<<". (no name)";
513  logger->addWarning(war);
514  }
515  }
516  }
517 
518 
519  /* retrieving arbitrator information*/
520  for(TiXmlElement* arb = root->FirstChildElement(); arb;
521  arb = arb->NextSiblingElement())
522  {
523  if(compareString(arb->Value(), "arbitrator"))
524  {
525  auto* port = (TiXmlElement*) arb->FirstChild("port");
526  if(port && port->GetText())
527  {
528  Arbitrator arbitrator(parser->parseText(port->GetText()).c_str());
529 
530  // retrieving rules
531  for(TiXmlElement* rule = arb->FirstChildElement(); rule;
532  rule = rule->NextSiblingElement())
533  {
534  if(compareString(rule->Value(), "rule"))
535  {
536  if(rule->Attribute("connection"))
537  arbitrator.addRule(rule->Attribute("connection"), parser->parseText(rule->GetText()).c_str());
538  }
539  }
540 #ifdef WITH_GEOMETRY
541  auto* geometry = (TiXmlElement*) arb->FirstChild("geometry");
542  if(geometry && geometry->GetText())
543  {
544  yarp::os::Property prop(parser->parseText(geometry->GetText()).c_str());
545  GraphicModel model;
546  if(prop.check("Pos"))
547  {
548  yarp::os::Bottle pos = prop.findGroup("Pos");
549  for(size_t i=1; i<pos.size(); i++)
550  {
551  GyPoint pt;
552  pt.x = pos.get(i).find("x").asFloat64();
553  pt.y = pos.get(i).find("y").asFloat64();
554  model.points.push_back(pt);
555  }
556  arbitrator.setModelBase(model);
557  }
558  }
559 #endif
560  app.addArbitrator(arbitrator);
561  }
562  else
563  {
564  OSTRINGSTREAM war;
565  war<<"Incomplete arbitrator tag from "<<szFile<<" at line "\
566  <<arb->Row()<<".";
567  logger->addWarning(war);
568  }
569  }
570  }
571 
572  /* retrieving connections information*/
573  for(TiXmlElement* cnn = root->FirstChildElement(); cnn;
574  cnn = cnn->NextSiblingElement())
575  {
576  if(compareString(cnn->Value(), "connection"))
577  {
578  auto* from = (TiXmlElement*) cnn->FirstChild("from");
579  auto* to = (TiXmlElement*) cnn->FirstChild("to");
580 
581  if(!from)
582  from = (TiXmlElement*) cnn->FirstChild("output");
583  if(!to)
584  to = (TiXmlElement*) cnn->FirstChild("input");
585 
586  TiXmlElement* protocol;
587  if(from && to)
588  {
589  string strCarrier;
590  if((protocol=(TiXmlElement*) cnn->FirstChild("protocol")) &&
591  protocol->GetText())
592  strCarrier = parser->parseText(protocol->GetText());
593  Connection connection(parser->parseText(from->GetText()).c_str(),
594  parser->parseText(to->GetText()).c_str(),
595  strCarrier.c_str());
596 
597  // check if Qos is set for the connection
598  if(cnn->Attribute("qos")) {
599  connection.setQosTo(cnn->Attribute("qos"));
600  connection.setQosFrom(cnn->Attribute("qos"));
601  }
602 
603  if(from->Attribute("external") &&
604  compareString(from->Attribute("external"), "true"))
605  {
606  connection.setFromExternal(true);
607  if(from->GetText())
608  {
609  ResYarpPort resource(parser->parseText(from->GetText()).c_str());
610  resource.setPort(parser->parseText(from->GetText()).c_str());
611  app.addResource(resource);
612  }
613  }
614  if(from->Attribute("qos"))
615  connection.setQosFrom(from->Attribute("qos"));
616  if(to->Attribute("external") &&
617  compareString(to->Attribute("external"), "true"))
618  {
619  if(to->GetText())
620  {
621  connection.setToExternal(true);
622  ResYarpPort resource(parser->parseText(to->GetText()).c_str());
623  resource.setPort(parser->parseText(to->GetText()).c_str());
624  app.addResource(resource);
625  }
626  }
627  if(to->Attribute("qos"))
628  connection.setQosTo(to->Attribute("qos"));
629 
630  //Connections which have the same port name in Port Resources
631  // should also be set as external
632  for(int i=0; i<app.resourcesCount(); i++)
633  {
634  ResYarpPort res = app.getResourceAt(i);
635  if(compareString(res.getPort(), connection.from()))
636  connection.setFromExternal(true);
637  if(compareString(res.getPort(), connection.to()))
638  connection.setToExternal(true);
639  }
640 
641  if(cnn->Attribute("id"))
642  connection.setId(cnn->Attribute("id"));
643 
644  if(cnn->Attribute("persist") &&
645  compareString(cnn->Attribute("persist"), "true"))
646  connection.setPersistent(true);
647 
648 #ifdef WITH_GEOMETRY
649  auto* geometry = (TiXmlElement*) cnn->FirstChild("geometry");
650  if(geometry && geometry->GetText())
651  {
652  yarp::os::Property prop(parser->parseText(geometry->GetText()).c_str());
653  GraphicModel model;
654  if(prop.check("Pos"))
655  {
656  yarp::os::Bottle pos = prop.findGroup("Pos");
657  for(size_t i=1; i<pos.size(); i++)
658  {
659  GyPoint pt;
660  pt.x = pos.get(i).find("x").asFloat64();
661  pt.y = pos.get(i).find("y").asFloat64();
662  model.points.push_back(pt);
663  }
664  connection.setModelBase(model);
665  }
666  }
667 #endif
668 
669  app.addConnection(connection);
670  }
671  else
672  {
673  OSTRINGSTREAM war;
674  war<<"Incomplete connection tag from "<<szFile<<" at line "\
675  <<cnn->Row()<<".";
676  logger->addWarning(war);
677  }
678  }
679  }
680 
681 
682  return &app;
683 
684 }
yarp::manager::Application
Class Application.
Definition: application.h:292
filesystem.h
yarp::os::Bottle
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
yarp::os::Value::find
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Value.cpp:330
yarp::manager::Author::setName
void setName(const char *name)
Definition: module.h:33
yarp::manager::__GyPoint
Definition: ymm-types.h:45
xmlapploader.h
yarp::manager::Application::getName
const char * getName()
Definition: application.h:306
yarp::os::Bottle::size
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:254
yarp::manager::Connection
Class Connection.
Definition: application.h:60
yarp::manager::Arbitrator
Class port Arbitrator.
Definition: arbitrator.h:28
yarp::manager::Author::setEmail
void setEmail(const char *email)
Definition: module.h:34
yarp::manager::OSTRINGSTREAM
std::stringstream OSTRINGSTREAM
Definition: utility.h:52
yarp::manager
Definition: application.h:24
yarp::manager::ErrorLogger
Singleton class ErrorLogger.
Definition: utility.h:60
utility.h
yarp::manager::ModuleInterface
Class ModuleInterface.
Definition: application.h:164
yarp::manager::compareString
bool compareString(const char *szFirst, const char *szSecond)
Definition: utility.cpp:305
yarp::manager::GraphicModel::points
std::vector< GyPoint > points
Definition: node.h:33
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::manager::TextParser
Definition: textparser.h:24
yarp::manager::__GyPoint::y
double y
Definition: ymm-types.h:47
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
yarp::manager::ApplicationInterface
Class ApplicationInterface.
Definition: application.h:256
Property.h
yarp::manager::ErrorLogger::addError
void addError(const char *szError)
Definition: utility.cpp:121
yarp::manager::ResYarpPort
Definition: logicresource.h:47
textparser.h
module
static RFModule * module
Definition: RFModule.cpp:234
yarp::manager::ErrorLogger::addWarning
void addWarning(const char *szWarning)
Definition: utility.cpp:108
yarp::manager::Application::clear
void clear()
Definition: application.h:362
yarp::manager::GraphicModel
Definition: node.h:28
yarp::manager::ResYarpPort::getPort
const char * getPort()
Definition: logicresource.h:53
yarp::manager::__GyPoint::x
double x
Definition: ymm-types.h:46
yarp::conf::filesystem::preferred_separator
static constexpr value_type preferred_separator
Definition: filesystem.h:28
yarp::conf::environment::setEnvironment
void setEnvironment(const std::string &key, const std::string &val)
Set or change an environment variable.
Definition: environment.h:51
yarp::manager::Author
Definition: module.h:24
yarp::os::Value::asFloat64
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:225
Value.h
yarp::os::Property
A class for storing options and configuration information.
Definition: Property.h:37
yarp::manager::Portmap
Class Portmap.
Definition: application.h:30