YARP
Yet Another Robot Platform
Localization2D_nws_yarp.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: LGPL-2.1-or-later
4  */
5 
6 #define _USE_MATH_DEFINES
7 
9 
10 #include <yarp/os/Bottle.h>
11 #include <yarp/os/LogComponent.h>
12 #include <yarp/os/LogStream.h>
13 #include <yarp/os/Network.h>
14 #include <yarp/os/Port.h>
15 #include <yarp/os/RFModule.h>
16 #include <yarp/os/Time.h>
17 
18 #include <yarp/sig/Vector.h>
19 
22 #include <yarp/dev/IMap2D.h>
23 #include <yarp/dev/PolyDriver.h>
24 
25 #include <yarp/math/Math.h>
26 
27 #include <cmath>
28 
31 using namespace yarp::os;
32 using namespace yarp::dev;
33 using namespace yarp::dev::Nav2D;
34 
35 #define DEFAULT_THREAD_PERIOD 0.01
36 
37 namespace
38 {
39  YARP_LOG_COMPONENT(LOCALIZATION2D_NWS_YARP, "yarp.device.localization2D_nws_yarp")
40 }
41 
42 //------------------------------------------------------------------------------------------------------------------------------
43 
45  m_period(DEFAULT_THREAD_PERIOD)
46 {
48 }
49 
51 {
52  if (driver->isValid())
53  {
54  driver->view(iLoc);
55  }
56 
57  if (nullptr == iLoc)
58  {
59  yCError(LOCALIZATION2D_NWS_YARP, "Subdevice passed to attach method is invalid");
60  return false;
61  }
62 
63  //initialize m_current_position and m_current_status, if available
64  bool ret = true;
66  Map2DLocation loc;
67  ret &= iLoc->getLocalizationStatus(status);
68  ret &= iLoc->getCurrentPosition(loc);
69  if (ret)
70  {
71  m_current_status = status;
72  m_current_position = loc;
73  }
74  else
75  {
76  yCWarning(LOCALIZATION2D_NWS_YARP) << "Localization data not yet available during server initialization";
77  }
78 
79  PeriodicThread::setPeriod(m_period);
80  return PeriodicThread::start();
81 }
82 
84 {
85  if (PeriodicThread::isRunning())
86  {
87  PeriodicThread::stop();
88  }
89  iLoc = nullptr;
90  return true;
91 }
92 
94 {
95  Property params;
96  params.fromString(config.toString().c_str());
97  yCDebug(LOCALIZATION2D_NWS_YARP) << "Configuration: \n" << config.toString().c_str();
98 
99  if (config.check("GENERAL") == false)
100  {
101  yCWarning(LOCALIZATION2D_NWS_YARP) << "Missing GENERAL group, assuming default options";
102  }
103 
104  Bottle& general_group = config.findGroup("GENERAL");
105  if (!general_group.check("period"))
106  {
107  yCInfo(LOCALIZATION2D_NWS_YARP) << "Missing 'period' parameter. Using default value: " << DEFAULT_THREAD_PERIOD;
109  }
110  else
111  {
112  m_period = general_group.find("period").asFloat64();
113  yCInfo(LOCALIZATION2D_NWS_YARP) << "Period requested: " << m_period;
114  }
115 
116  if (!general_group.check("publish_odometry"))
117  {
118  m_enable_publish_odometry = general_group.find("publish_odometry").asBool();
119  yCInfo(LOCALIZATION2D_NWS_YARP) << "publish_odometry=" << m_enable_publish_odometry;
120  }
121  if (!general_group.check("publish_location"))
122  {
123  m_enable_publish_location = general_group.find("publish_location").asBool();
124  yCInfo(LOCALIZATION2D_NWS_YARP) << "publish_location=" << m_enable_publish_location;
125  }
126 
127  if (!general_group.check("retrieve_position_periodically"))
128  {
129  yCInfo(LOCALIZATION2D_NWS_YARP) << "Missing 'retrieve_position_periodically' parameter. Using default value: true. Period:" << m_period ;
131  }
132  else
133  {
134  m_getdata_using_periodic_thread = general_group.find("retrieve_position_periodically").asBool();
136  { yCInfo(LOCALIZATION2D_NWS_YARP) << "retrieve_position_periodically requested, Period:" << m_period; }
137  else
138  { yCInfo(LOCALIZATION2D_NWS_YARP) << "retrieve_position_periodically NOT requested. Localization data obtained asynchronously."; }
139  }
140 
141  if (!general_group.check("name"))
142  {
143  yCInfo(LOCALIZATION2D_NWS_YARP) << "Missing 'name' parameter. Using default value:" << m_local_name;
144  }
145  else
146  {
147  m_local_name = general_group.find("name").asString();
148  if (m_local_name.c_str()[0] != '/') { yCError(LOCALIZATION2D_NWS_YARP) << "Missing '/' in name parameter" ; return false; }
149  yCInfo(LOCALIZATION2D_NWS_YARP) << "Using local name:" << m_local_name;
150  }
151 
152  m_rpcPortName = m_local_name + "/rpc";
153  m_2DLocationPortName = m_local_name + "/streaming:o";
154  m_odometryPortName = m_local_name + "/odometry:o";
155 
156  if (config.check("subdevice"))
157  {
158  Property p;
159  p.fromString(config.toString(), false);
160  p.put("device", config.find("subdevice").asString());
161 
162  if (!pLoc.open(p) || !pLoc.isValid())
163  {
164  yCError(LOCALIZATION2D_NWS_YARP) << "Failed to open subdevice.. check params";
165  return false;
166  }
167 
168  if (!attach(&pLoc))
169  {
170  yCError(LOCALIZATION2D_NWS_YARP) << "Failed to open subdevice.. check params";
171  return false;
172  }
173  }
174  else
175  {
176  yCInfo(LOCALIZATION2D_NWS_YARP) << "Waiting for device to attach";
177  }
179 
180  if (!initialize_YARP(config))
181  {
182  yCError(LOCALIZATION2D_NWS_YARP) << "Error initializing YARP ports";
183  return false;
184  }
185 
186  return true;
187 }
188 
190 {
192  {
193  yCError(LOCALIZATION2D_NWS_YARP, "Failed to open port %s", m_2DLocationPortName.c_str());
194  return false;
195  }
196 
197  if (!m_odometryPort.open(m_odometryPortName.c_str()))
198  {
199  yCError(LOCALIZATION2D_NWS_YARP, "Failed to open port %s", m_odometryPortName.c_str());
200  return false;
201  }
202 
203  if (!m_rpcPort.open(m_rpcPortName.c_str()))
204  {
205  yCError(LOCALIZATION2D_NWS_YARP, "Failed to open port %s", m_rpcPortName.c_str());
206  return false;
207  }
208  m_rpcPort.setReader(*this);
209 
210  return true;
211 }
212 
214 {
215  yCTrace(LOCALIZATION2D_NWS_YARP, "Close");
216  if (PeriodicThread::isRunning())
217  {
218  PeriodicThread::stop();
219  }
220 
221  detach();
222 
228  m_rpcPort.close();
229 
230  yCDebug(LOCALIZATION2D_NWS_YARP) << "Execution terminated";
231  return true;
232 }
233 
235 {
236  yarp::os::Bottle command;
237  yarp::os::Bottle reply;
238  bool ok = command.read(connection);
239  if (!ok) {
240  return false;
241  }
242 
243  reply.clear();
244 
245  if (command.get(0).isVocab32())
246  {
247  if (command.get(0).asVocab32() == VOCAB_INAVIGATION && command.get(1).isVocab32())
248  {
249  int request = command.get(1).asVocab32();
250  if (request == VOCAB_NAV_GET_CURRENT_POS)
251  {
252  bool b = true;
254  {
255  //m_current_position is obtained by run()
256  }
257  else
258  {
259  //m_current_position is obtained by getCurrentPosition()
261  }
262  if (b)
263  {
264  reply.addVocab32(VOCAB_OK);
269  }
270  else
271  {
272  reply.addVocab32(VOCAB_ERR);
273  }
274  }
275  else if (request == VOCAB_NAV_GET_ESTIMATED_ODOM)
276  {
277  bool b = true;
279  {
280  //m_current_position is obtained by run()
281  }
282  else
283  {
284  //m_current_position is obtained by getCurrentPosition()
286  }
287  if (b)
288  {
289  reply.addVocab32(VOCAB_OK);
299  }
300  else
301  {
302  reply.addVocab32(VOCAB_ERR);
303  }
304  }
305  else if (request == VOCAB_NAV_SET_INITIAL_POS)
306  {
307  Map2DLocation init_loc;
308  init_loc.map_id = command.get(2).asString();
309  init_loc.x = command.get(3).asFloat64();
310  init_loc.y = command.get(4).asFloat64();
311  init_loc.theta = command.get(5).asFloat64();
312  iLoc->setInitialPose(init_loc);
313  reply.addVocab32(VOCAB_OK);
314  }
315  else if (request == VOCAB_NAV_GET_CURRENT_POSCOV)
316  {
317  Map2DLocation init_loc;
318  yarp::sig::Matrix cov(3, 3);
319  iLoc->getCurrentPosition(init_loc, cov);
320  reply.addVocab32(VOCAB_OK);
325  yarp::os::Bottle& mc = reply.addList();
326  for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < 3; j++) { mc.addFloat64(cov[i][j]); } }
327  }
328  else if (request == VOCAB_NAV_SET_INITIAL_POSCOV)
329  {
330  Map2DLocation init_loc;
331  yarp::sig::Matrix cov(3,3);
332  init_loc.map_id = command.get(2).asString();
333  init_loc.x = command.get(3).asFloat64();
334  init_loc.y = command.get(4).asFloat64();
335  init_loc.theta = command.get(5).asFloat64();
336  Bottle* mc = command.get(6).asList();
337  if (mc!=nullptr && mc->size() == 9)
338  {
339  for (size_t i = 0; i < 3; i++) { for (size_t j = 0; j < 3; j++) { cov[i][j] = mc->get(i * 3 + j).asFloat64(); } }
340  bool ret = iLoc->setInitialPose(init_loc, cov);
341  if (ret) { reply.addVocab32(VOCAB_OK); }
342  else { reply.addVocab32(VOCAB_ERR); }
343  }
344  else
345  {
346  reply.addVocab32(VOCAB_ERR);
347  }
348  }
349  else if (request == VOCAB_NAV_LOCALIZATION_START)
350  {
352  reply.addVocab32(VOCAB_OK);
353  }
354  else if (request == VOCAB_NAV_LOCALIZATION_STOP)
355  {
357  reply.addVocab32(VOCAB_OK);
358  }
359  else if (request == VOCAB_NAV_GET_LOCALIZER_STATUS)
360  {
362  {
363  //m_current_status is obtained by run()
364  reply.addVocab32(VOCAB_OK);
366  }
367  else
368  {
369  //m_current_status is obtained by getLocalizationStatus()
371  reply.addVocab32(VOCAB_OK);
373  }
374  }
375  else if (request == VOCAB_NAV_GET_LOCALIZER_POSES)
376  {
377  std::vector<Map2DLocation> poses;
378  iLoc->getEstimatedPoses(poses);
379  reply.addVocab32(VOCAB_OK);
380  reply.addInt32(poses.size());
381  for (size_t i=0; i<poses.size(); i++)
382  {
383  Bottle& b = reply.addList();
384  b.addString(poses[i].map_id);
385  b.addFloat64(poses[i].x);
386  b.addFloat64(poses[i].y);
387  b.addFloat64(poses[i].theta);
388  }
389  }
390  else
391  {
392  reply.addVocab32(VOCAB_ERR);
393  }
394  }
395  else
396  {
397  yCError(LOCALIZATION2D_NWS_YARP) << "Invalid vocab received";
398  reply.addVocab32(VOCAB_ERR);
399  }
400  }
401  else if (command.get(0).isString() && command.get(0).asString() == "help")
402  {
403  reply.addVocab32("many");
404  reply.addString("Available commands are:");
405  reply.addString("getLoc");
406  reply.addString("initLoc <map_name> <x> <y> <angle in degrees>");
407  }
408  else if (command.get(0).isString() && command.get(0).asString() == "getLoc")
409  {
410  Map2DLocation curr_loc;
411  iLoc->getCurrentPosition(curr_loc);
412  std::string s = std::string("Current Location is: ") + curr_loc.toString();
413  reply.addString(s);
414  }
415  else if (command.get(0).isString() && command.get(0).asString() == "initLoc")
416  {
417  Map2DLocation init_loc;
418  init_loc.map_id = command.get(1).asString();
419  init_loc.x = command.get(2).asFloat64();
420  init_loc.y = command.get(3).asFloat64();
421  init_loc.theta = command.get(4).asFloat64();
422  iLoc->setInitialPose(init_loc);
423  std::string s = std::string("Localization initialized to: ") + init_loc.toString();
424  reply.addString(s);
425  }
426  else
427  {
428  yCError(LOCALIZATION2D_NWS_YARP) << "Invalid command type";
429  reply.addVocab32(VOCAB_ERR);
430  }
431 
432  yarp::os::ConnectionWriter *returnToSender = connection.getWriter();
433  if (returnToSender != nullptr)
434  {
435  reply.write(*returnToSender);
436  }
437 
438  return true;
439 }
440 
442 {
443  double m_stats_time_curr = yarp::os::Time::now();
444  if (m_stats_time_curr - m_stats_time_last > 5.0)
445  {
446  yCInfo(LOCALIZATION2D_NWS_YARP) << "Running";
448  }
449 
451  {
453  if (ret == false)
454  {
455  yCError(LOCALIZATION2D_NWS_YARP) << "getLocalizationStatus() failed";
456  }
457 
459  {
461  if (ret2 == false)
462  {
463  yCError(LOCALIZATION2D_NWS_YARP) << "getCurrentPosition() failed";
464  }
465  else
466  {
468  }
470  if (ret3 == false)
471  {
472  //yCError(LOCALIZATION2D_NWS_YARP) << "getEstimatedOdometry() failed";
473  }
474  else
475  {
477  }
478  }
479  else
480  {
481  yCWarning(LOCALIZATION2D_NWS_YARP, "The system is not properly localized!");
482  }
483  }
484 
486  publish_odometry_on_yarp_port();
487  }
489  publish_2DLocation_on_yarp_port();
490  }
491 }
492 
493 void Localization2D_nws_yarp::publish_odometry_on_yarp_port()
494 {
495  if (m_odometryPort.getOutputCount() > 0)
496  {
498  odom = m_current_odometry;
499 
500  //send data to port
503  }
504 }
505 
506 void Localization2D_nws_yarp::publish_2DLocation_on_yarp_port()
507 {
509  {
512  {
513  loc = m_current_position;
514  }
515  else
516  {
517  Map2DLocation temp_loc;
518  temp_loc.x = std::nan("");
519  temp_loc.y = std::nan("");
520  temp_loc.theta = std::nan("");
521  loc = temp_loc;
522  }
523 
524  //send data to port
527  }
528 }
define control board standard interfaces
constexpr yarp::conf::vocab32_t VOCAB_OK
Definition: GenericVocabs.h:15
constexpr yarp::conf::vocab32_t VOCAB_ERR
Definition: GenericVocabs.h:17
constexpr yarp::conf::vocab32_t VOCAB_NAV_GET_LOCALIZER_POSES
constexpr yarp::conf::vocab32_t VOCAB_INAVIGATION
constexpr yarp::conf::vocab32_t VOCAB_NAV_LOCALIZATION_STOP
constexpr yarp::conf::vocab32_t VOCAB_NAV_SET_INITIAL_POSCOV
constexpr yarp::conf::vocab32_t VOCAB_NAV_GET_CURRENT_POS
constexpr yarp::conf::vocab32_t VOCAB_NAV_GET_LOCALIZER_STATUS
constexpr yarp::conf::vocab32_t VOCAB_NAV_GET_ESTIMATED_ODOM
constexpr yarp::conf::vocab32_t VOCAB_NAV_SET_INITIAL_POS
constexpr yarp::conf::vocab32_t VOCAB_NAV_GET_CURRENT_POSCOV
constexpr yarp::conf::vocab32_t VOCAB_NAV_LOCALIZATION_START
bool ret
#define DEFAULT_THREAD_PERIOD
contains the definition of a Vector type
void run() override
Loop function.
yarp::dev::OdometryData m_current_odometry
yarp::os::BufferedPort< yarp::dev::OdometryData > m_odometryPort
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
yarp::dev::PolyDriver pLoc
yarp::dev::Nav2D::ILocalization2D * iLoc
bool initialize_YARP(yarp::os::Searchable &config)
bool open(yarp::os::Searchable &prop) override
Open the DeviceDriver.
bool attach(yarp::dev::PolyDriver *driver) override
Attach to another object.
bool close() override
Close the DeviceDriver.
bool detach() override
Detach the object (you must have first called attach).
yarp::dev::Nav2D::LocalizationStatusEnum m_current_status
yarp::dev::Nav2D::Map2DLocation m_current_position
yarp::os::BufferedPort< yarp::dev::Nav2D::Map2DLocation > m_2DLocationPort
bool view(T *&x)
Get an interface to the device driver.
Definition: DeviceDriver.h:74
virtual bool getEstimatedOdometry(yarp::dev::OdometryData &odom)=0
Gets the estimated odometry the robot, including its velocity expressed in the world and in the local...
virtual bool getCurrentPosition(yarp::dev::Nav2D::Map2DLocation &loc)=0
Gets the current position of the robot w.r.t world reference frame.
virtual bool getEstimatedPoses(std::vector< yarp::dev::Nav2D::Map2DLocation > &poses)=0
Gets a set of pose estimates computed by the localization algorithm.
virtual bool startLocalizationService()=0
Starts the localization service.
virtual bool stopLocalizationService()=0
Stops the localization service.
virtual bool setInitialPose(const yarp::dev::Nav2D::Map2DLocation &loc)=0
Sets the initial pose for the localization algorithm which estimates the current position of the robo...
virtual bool getLocalizationStatus(LocalizationStatusEnum &status)=0
Gets the current status of the localization task.
double base_vel_x
velocity of the robot [m/s] expressed in the robot reference frame
Definition: OdometryData.h:42
double odom_vel_y
velocity of the robot [m/s] expressed in the world reference frame
Definition: OdometryData.h:58
double base_vel_theta
angular velocity of the robot [deg/s] expressed in the robot reference frame
Definition: OdometryData.h:50
double odom_vel_theta
angular velocity of the robot [deg/s] expressed in the world reference frame
Definition: OdometryData.h:62
double base_vel_y
velocity of the robot [m/s] expressed in the robot reference frame
Definition: OdometryData.h:46
double odom_x
position of the robot [m], expressed in the world reference frame
Definition: OdometryData.h:30
double odom_y
position of the robot [m], expressed in the world reference frame
Definition: OdometryData.h:34
double odom_theta
orientation the robot [deg], expressed in the world reference frame
Definition: OdometryData.h:38
double odom_vel_x
velocity of the robot [m/s] expressed in the world reference frame
Definition: OdometryData.h:54
A container for a device driver.
Definition: PolyDriver.h:24
bool isValid() const
Check if device is valid.
Definition: PolyDriver.cpp:196
bool open(const std::string &txt)
Construct and configure a device by its common name.
Definition: PolyDriver.cpp:140
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:164
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
Definition: Bottle.cpp:182
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
void addFloat64(yarp::conf::float64_t x)
Places a 64-bit floating point number in the bottle, at the end of the list.
Definition: Bottle.cpp:158
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Bottle.cpp:277
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
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:287
void close() override
Stop port activity.
bool setEnvelope(PortWriter &envelope) override
Set an envelope (e.g., a timestamp) to the next message which will be sent.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
void interrupt() override
Interrupt any current reads or writes attached to the port.
int getOutputCount() override
Determine how many output connections this port has.
void write(bool forceStrict=false)
Write the current object being returned by BufferedPort::prepare.
T & prepare()
Access the object which will be transmitted by the next call to yarp::os::BufferedPort::write.
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.
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition: Port.cpp:502
void interrupt() override
Interrupt any current reads or writes attached to the port.
Definition: Port.cpp:374
void close() override
Stop port activity.
Definition: Port.cpp:354
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition: Port.cpp:79
A class for storing options and configuration information.
Definition: Property.h:34
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1063
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:1015
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
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
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:156
virtual yarp::conf::vocab32_t asVocab32() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:228
virtual bool asBool() const
Get boolean value.
Definition: Value.cpp:186
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
virtual bool isVocab32() const
Checks if value is a vocabulary identifier.
Definition: Value.cpp:174
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
A class for a Matrix.
Definition: Matrix.h:43
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCTrace(component,...)
Definition: LogComponent.h:85
#define yCWarning(component,...)
Definition: LogComponent.h:143
#define yCDebug(component,...)
Definition: LogComponent.h:109
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
An interface for the device drivers.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:121
An interface to the operating system, including Port based communication.
std::string toString() const
Returns text representation of the location.
Definition: Map2DLocation.h:74