YARP
Yet Another Robot Platform
Map2D_nws_ros.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#include "Map2D_nws_ros.h"
7
8#include <yarp/os/Log.h>
10#include <yarp/os/LogStream.h>
11#include <yarp/os/Node.h>
12#include <yarp/os/Publisher.h>
13#include <yarp/os/Subscriber.h>
14
16#include <yarp/dev/IMap2D.h>
18
19#include <yarp/math/Math.h>
20
23
24#include <cstdlib>
25#include <fstream>
26#include <limits>
27#include <mutex>
28#include <sstream>
29
30using namespace yarp::sig;
31using namespace yarp::dev;
32using namespace yarp::dev::Nav2D;
33using namespace yarp::os;
34
35namespace {
36YARP_LOG_COMPONENT(MAP2D_NWS_ROS, "yarp.device.map2D_nws_ros")
37}
38
39#ifndef M_PI
40#define M_PI 3.14159265358979323846
41#endif
42
43#define RAD2DEG 180/M_PI
44#define DEG2RAD M_PI/180
45
51{
52 m_enable_publish_map = false;
53 m_enable_subscribe_map = false;
54 m_node = nullptr;
55}
56
58
59bool Map2D_nws_ros::read(yarp::os::ConnectionReader& connection)
60{
61 yarp::os::Bottle command;
62 yarp::os::Bottle reply;
63 bool ok = command.read(connection);
64 if (!ok) {
65 return false;
66 }
67
68 reply.clear();
69
70 if (command.get(0).isString() && command.get(0).asString() == "help")
71 {
72 reply.addVocab32("many");
73 reply.addString("No commands currently available:");
74 }
75 else
76 {
77 yCError(MAP2D_NWS_ROS) << "Invalid command. Try `help`";
78 reply.addVocab32(VOCAB_ERR);
79 }
80
81 yarp::os::ConnectionWriter* returnToSender = connection.getWriter();
82 if (returnToSender != nullptr)
83 {
84 reply.write(*returnToSender);
85 }
86
87 return true;
88}
89
91{
92 Property params;
93 params.fromString(config.toString());
94
95 if (!config.check("name"))
96 {
97 m_rpcPortName = "/map2D_nws_ros/rpc";
98 }
99 else
100 {
101 m_rpcPortName = config.find("name").asString();
102 }
103
104 //subdevice handling
105 if (config.check("subdevice"))
106 {
107 Property p;
108 p.fromString(config.toString(), false);
109 p.put("device", config.find("subdevice").asString());
110
111 if (!m_drv.open(p) || !m_drv.isValid())
112 {
113 yCError(MAP2D_NWS_ROS) << "Failed to open subdevice.. check params";
114 return false;
115 }
116
117 if (!attach(&m_drv))
118 {
119 yCError(MAP2D_NWS_ROS) << "Failed to open subdevice.. check params";
120 return false;
121 }
122 }
123 else
124 {
125 yCInfo(MAP2D_NWS_ROS) << "Waiting for device to attach";
126 }
127
128 //open rpc port
129 if (!m_rpcPort.open(m_rpcPortName))
130 {
131 yCError(MAP2D_NWS_ROS, "Failed to open port %s", m_rpcPortName.c_str());
132 return false;
133 }
134 m_rpcPort.setReader(*this);
135
136 //ROS configuration
137 if (config.check("ROS"))
138 {
139 yCInfo(MAP2D_NWS_ROS, "Configuring ROS params");
140 Bottle ROS_config = config.findGroup("ROS");
141
142 if (ROS_config.find("enable_publisher").asInt32() == 1 || ROS_config.find("enable_publisher").asString() == "true")
143 {
144 m_enable_publish_map = true;
145 yCInfo(MAP2D_NWS_ROS) << "Enabled ROS publisher";
146 }
147
148 if (ROS_config.find("enable_subscriber").asInt32() == 1 || ROS_config.find("enable_subscriber").asString() == "true")
149 {
150 m_enable_subscribe_map = true;
151 yCInfo(MAP2D_NWS_ROS) << "Enabled ROS subscriber";
152 }
153
154 if (m_enable_publish_map)
155 {
156 if (m_node == nullptr)
157 {
158 m_node = new yarp::os::Node(ROSNODENAME);
159 }
160 if (!m_publisherPort_map.topic(ROSTOPICNAME_MAP))
161 {
162 yCError(MAP2D_NWS_ROS) << "Unable to publish to" << ROSTOPICNAME_MAP << "topic, check your YARP-ROS network configuration";
163 return false;
164 }
165 if (!m_publisherPort_metamap.topic(ROSTOPICNAME_MAPMETADATA))
166 {
167 yCError(MAP2D_NWS_ROS) << "Unable to publish to " << ROSTOPICNAME_MAPMETADATA << " topic, check your YARP-ROS network configuration";
168 return false;
169 }
170 //should I publish the map now? with which name ?
171 //publishMapToRos();
172 }
173
174 if (m_enable_subscribe_map)
175 {
176 if (!m_subscriberPort_map.topic(ROSTOPICNAME_MAP))
177 {
178 yCError(MAP2D_NWS_ROS) << "Unable to subscribe to " << ROSTOPICNAME_MAP << " topic, check your YARP-ROS network configuration";
179 return false;
180 }
181 if (!m_subscriberPort_metamap.topic(ROSTOPICNAME_MAPMETADATA))
182 {
183 yCError(MAP2D_NWS_ROS) << "Unable to subscribe to " << ROSTOPICNAME_MAPMETADATA << " topic, check your YARP-ROS network configuration";
184 return false;
185 }
186 m_subscriberPort_map.setStrict();
187 m_subscriberPort_metamap.setStrict();
188
189 //should I subscribe the map now ? with which name ?
190 //subscribeMapFromRos();
191 }
192 }
193 else
194 {
195 //no ROS options
196 yCWarning(MAP2D_NWS_ROS) << "ROS Group not configured";
197 }
198
199 return true;
200}
201
202bool Map2D_nws_ros::publishMapToRos(std::string map_name)
203{
204 MapGrid2D current_map;
205 if (!m_iMap2D->get_map(map_name, current_map))
206 {
207 yCError(MAP2D_NWS_ROS) << "publishMapToRos() " << map_name << " does not exists";
208 return false;
209 }
210
211 double tmp = 0;
212 yarp::rosmsg::nav_msgs::OccupancyGrid& ogrid = m_publisherPort_map.prepare();
213 ogrid.clear();
214 ogrid.info.height = current_map.height();
215 ogrid.info.width = current_map.width();
216 current_map.getResolution(tmp);
217 ogrid.info.resolution = tmp;
218 ogrid.header.frame_id = "map";
219 ogrid.info.map_load_time.sec = 0;
220 ogrid.info.map_load_time.nsec = 0;
221 double x, y, t;
222 current_map.getOrigin(x, y, t);
223 ogrid.info.origin.position.x = x;
224 ogrid.info.origin.position.y = y;
227 v[0] = 0; v[1] = 0; v[2] = 1; v[3] = t * DEG2RAD;
228 q.fromAxisAngle(v);
229 ogrid.info.origin.orientation.x = q.x();
230 ogrid.info.origin.orientation.y = q.y();
231 ogrid.info.origin.orientation.z = q.z();
232 ogrid.info.origin.orientation.w = q.w();
233 ogrid.data.resize(current_map.width() * current_map.height());
234 int index = 0;
236 for (cell.y = current_map.height(); cell.y-- > 0;) {
237 for (cell.x = 0; cell.x < current_map.width(); cell.x++)
238 {
239 current_map.getOccupancyData(cell, tmp);
240 ogrid.data[index++] = (int)tmp;
241 }
242 }
243
244 m_publisherPort_map.write();
245
246 //what about the m_publisherPort_metamap ?
247 //I don't know...
248
249 return true;
250}
251
252bool Map2D_nws_ros::subscribeMapFromRos(std::string map_name)
253{
254 //In this block receives data from a ROS topic and stores data on attached device
255 //yarp::os::Time::delay(5);
256 yarp::rosmsg::nav_msgs::OccupancyGrid* map_ros = nullptr;
257 yarp::rosmsg::nav_msgs::MapMetaData* metamap_ros = nullptr;
258
259 map_ros = m_subscriberPort_map.read(true);
260 metamap_ros = m_subscriberPort_metamap.read(true);
261 if (map_ros != nullptr && metamap_ros != nullptr)
262 {
263 yCInfo(MAP2D_NWS_ROS) << "Received map for ROS";
264 std::string map_name = "ros_map";
265 MapGrid2D map;
266 map.setSize_in_cells(map_ros->info.width,map_ros->info.height);
267 map.setResolution(map_ros->info.resolution);
268 map.setMapName(map_name);
270 map_ros->info.origin.orientation.y,
271 map_ros->info.origin.orientation.z,
272 map_ros->info.origin.orientation.w);
273 yarp::sig::Matrix mat = quat.toRotationMatrix4x4();
275 double orig_angle = vec[2];
276 map.setOrigin(map_ros->info.origin.position.x,map_ros->info.origin.position.y,orig_angle);
277 for (size_t y = 0; y < map_ros->info.height; y++)
278 {
279 for (size_t x = 0; x < map_ros->info.width; x++)
280 {
281 XYCell cell(x,map_ros->info.height - 1 - y);
282 double occ = map_ros->data[x + y * map_ros->info.width];
283 map.setOccupancyData(cell,occ);
284
285 if (occ >= 0 && occ <= 70) {
286 map.setMapFlag(cell, MapGrid2D::MAP_CELL_FREE);
287 } else if (occ >= 71 && occ <= 100) {
288 map.setMapFlag(cell, MapGrid2D::MAP_CELL_WALL);
289 } else {
290 map.setMapFlag(cell, MapGrid2D::MAP_CELL_UNKNOWN);
291 }
292 }
293 }
294 if (m_iMap2D->store_map(map))
295 {
296 yCInfo(MAP2D_NWS_ROS) << "Added map " << map.getMapName() << " to storage";
297 return true;
298 }
299
300 yCInfo(MAP2D_NWS_ROS) << "Unable to add map " << map.getMapName() << " to storage";
301 return false;
302 }
303
304 return false;
305}
306
308{
309 yCTrace(MAP2D_NWS_ROS, "Close");
310 if (m_enable_publish_map)
311 {
312 m_publisherPort_map.interrupt();
313 m_publisherPort_metamap.interrupt();
314 m_publisherPort_map.close();
315 m_publisherPort_metamap.close();
316 }
317 if (m_enable_subscribe_map)
318 {
319 m_subscriberPort_map.interrupt();
320 m_subscriberPort_metamap.interrupt();
321 m_subscriberPort_map.close();
322 m_subscriberPort_metamap.close();
323 }
324 return true;
325}
326
327bool Map2D_nws_ros::updateVizMarkers(std::string map_name)
328{
329 if (m_publisherPort_markers.asPort().isOpen()==false)
330 {
331 m_publisherPort_markers.topic("/locationServerMarkers");
332 }
333 yarp::rosmsg::TickDuration dur; dur.sec = 0xFFFFFFFF;
334 double yarpTimeStamp = yarp::os::Time::now();
335 uint64_t time;
336 uint64_t nsec_part;
337 uint64_t sec_part;
339 time = (uint64_t)(yarpTimeStamp * 1000000000UL);
340 nsec_part = (time % 1000000000UL);
341 sec_part = (time / 1000000000UL);
342 if (sec_part > std::numeric_limits<unsigned int>::max())
343 {
344 yCWarning(MAP2D_NWS_ROS) << "Timestamp exceeded the 64 bit representation, resetting it to 0";
345 sec_part = 0;
346 }
347
350 yarp::sig::Vector rpy(3);
352
353 yarp::rosmsg::visualization_msgs::MarkerArray& markers = m_publisherPort_markers.prepare();
354 markers.markers.clear();
355
356 std::vector<std::string> locations;
357 int count = 1;
358 m_iMap2D->getLocationsList(locations);
359 for (auto it : locations)
360 {
362 m_iMap2D->getLocation(it, loc);
363 rpy[0] = 0; //x
364 rpy[1] = 0; //y
365 rpy[2] = loc.theta / 180 * 3.14159265359; //z
368
369 marker.header.frame_id = "map";
370 tt.sec = (yarp::os::NetUint32) sec_part;;
371 tt.nsec = (yarp::os::NetUint32) nsec_part;;
372 marker.header.stamp = tt;
373 marker.ns = "my_namespace";
374 marker.id = count;
377 marker.pose.position.x = loc.x;
378 marker.pose.position.y = loc.y;
379 marker.pose.position.z = 0;
380 marker.pose.orientation.x = q.x();
381 marker.pose.orientation.y = q.y();
382 marker.pose.orientation.z = q.z();
383 marker.pose.orientation.w = q.w();
384 marker.scale.x = 1;
385 marker.scale.y = 0.1;
386 marker.scale.z = 0.1;
387 marker.color.a = 1.0;
388 marker.color.r = 0.0;
389 marker.color.g = 1.0;
390 marker.color.b = 0.0;
391 marker.lifetime = dur;
392 marker.text = it;
393 markers.markers.push_back(marker);
394 count++;
395 }
396
397 m_publisherPort_markers.write();
398 return true;
399}
400
401
403{
404 m_iMap2D = nullptr;
405 return true;
406}
407
409{
410 if (driver->isValid())
411 {
412 driver->view(m_iMap2D);
413 }
414
415 if (nullptr == m_iMap2D)
416 {
417 yCError(MAP2D_NWS_ROS, "Subdevice passed to attach method is invalid");
418 return false;
419 }
420
421 return true;
422}
float t
#define ROSNODENAME
constexpr yarp::conf::vocab32_t VOCAB_ERR
Definition: GenericVocabs.h:17
bool ret
#define DEG2RAD
#define ROSTOPICNAME_MAP
Definition: Map2D_nws_ros.h:86
#define ROSTOPICNAME_MAPMETADATA
Definition: Map2D_nws_ros.h:87
bool close() override
Close the DeviceDriver.
bool attach(yarp::dev::PolyDriver *driver) override
Attach to another object.
bool detach() override
Detach the object (you must have first called attach).
bool open(yarp::os::Searchable &params) override
Open the DeviceDriver.
Map2D_nws_ros()
Map2D_nws_ros.
bool view(T *&x)
Get an interface to the device driver.
Definition: DeviceDriver.h:88
double theta
orientation [deg] in the map reference frame
double y
y position of the location [m], expressed in the map reference frame
double x
x position of the location [m], expressed in the map reference frame
virtual bool get_map(std::string map_name, yarp::dev::Nav2D::MapGrid2D &map)=0
Gets a map from the map server.
virtual bool getLocation(std::string location_name, yarp::dev::Nav2D::Map2DLocation &loc)=0
Retrieves a location specified by the user in the world reference frame.
virtual bool store_map(const yarp::dev::Nav2D::MapGrid2D &map)=0
Stores a map into the map server.
virtual bool getLocationsList(std::vector< std::string > &locations)=0
Get a list of the names of all stored locations.
size_t height() const
Retrieves the map height, expressed in cells.
Definition: MapGrid2D.cpp:177
bool setResolution(double resolution)
Sets the resolution of the map, i.e.
Definition: MapGrid2D.cpp:1058
bool setOrigin(double x, double y, double theta)
Sets the origin of the map reference frame (according to ROS convention)
Definition: MapGrid2D.cpp:1024
std::string getMapName() const
Retrieves the map name.
Definition: MapGrid2D.cpp:1085
bool setSize_in_cells(size_t x, size_t y)
Sets the size of the map in cells.
Definition: MapGrid2D.cpp:1108
void getOrigin(double &x, double &y, double &theta) const
Retrieves the origin of the map reference frame (according to ROS convention)
Definition: MapGrid2D.cpp:1051
bool setMapName(std::string map_name)
Sets the map name.
Definition: MapGrid2D.cpp:1074
bool setMapFlag(XYCell cell, map_flags flag)
Set the flag of a specific cell of the map.
Definition: MapGrid2D.cpp:1136
size_t width() const
Retrieves the map width, expressed in cells.
Definition: MapGrid2D.cpp:182
bool setOccupancyData(XYCell cell, double occupancy)
Set the occupancy data of a specific cell of the map.
Definition: MapGrid2D.cpp:1158
bool getOccupancyData(XYCell cell, double &occupancy) const
Retrieves the occupancy data of a specific cell of the map.
Definition: MapGrid2D.cpp:1176
void getResolution(double &resolution) const
Retrieves the resolution of the map, i.e.
Definition: MapGrid2D.cpp:1069
A container for a device driver.
Definition: PolyDriver.h:23
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
void fromRotationMatrix(const yarp::sig::Matrix &R)
Converts a rotation matrix to a quaternion.
Definition: Quaternion.cpp:162
double x() const
Definition: Quaternion.cpp:81
void fromAxisAngle(const yarp::sig::Vector &v)
Computes the quaternion from an axis-angle representation.
Definition: Quaternion.cpp:282
double z() const
Definition: Quaternion.cpp:91
double w() const
Definition: Quaternion.cpp:76
double y() const
Definition: Quaternion.cpp:86
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
void setReader(PortReader &reader) override
Set an external reader for port data.
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
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 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
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.
The Node class.
Definition: Node.h:23
bool isOpen() const
Check if the port has been opened.
Definition: Port.cpp:677
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.
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
void close() override
Stop port activity.
Definition: Publisher.h:84
bool topic(const std::string &name)
Set topic to publish to.
Definition: Publisher.h:63
Port & asPort() override
Get the concrete Port being used for communication.
Definition: Publisher.h:169
void interrupt() override
Interrupt any current reads or writes attached to the port.
Definition: Publisher.h:90
void write(bool forceStrict=false)
Write the current object being returned by Publisher::prepare.
Definition: Publisher.h:148
T & prepare()
Access the object which will be transmitted by the next call to yarp::os::Publisher::write.
Definition: Publisher.h:123
A base class for nested structures that can be searched.
Definition: Searchable.h:63
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual 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.
T * read(bool shouldWait=true)
Read a message from the port.
Definition: Subscriber.h:113
void close() override
Stop port activity.
Definition: Subscriber.h:83
void setStrict(bool strict=true)
Definition: Subscriber.h:150
bool topic(const std::string &name)
Set topic to subscribe to.
Definition: Subscriber.h:62
void interrupt() override
Interrupt any current reads or writes attached to the port.
Definition: Subscriber.h:89
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:156
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
std::uint32_t nsec
Definition: TickTime.h:30
std::uint32_t sec
Definition: TickTime.h:29
yarp::conf::float64_t y
Definition: Point.h:33
yarp::conf::float64_t x
Definition: Point.h:32
yarp::conf::float64_t z
Definition: Point.h:34
yarp::rosmsg::geometry_msgs::Point position
Definition: Pose.h:33
yarp::rosmsg::geometry_msgs::Quaternion orientation
Definition: Pose.h:34
yarp::conf::float64_t y
Definition: Vector3.h:38
yarp::conf::float64_t z
Definition: Vector3.h:39
yarp::conf::float64_t x
Definition: Vector3.h:37
yarp::rosmsg::geometry_msgs::Pose origin
Definition: MapMetaData.h:46
yarp::conf::float32_t resolution
Definition: MapMetaData.h:43
yarp::rosmsg::TickTime map_load_time
Definition: MapMetaData.h:42
std::vector< std::int8_t > data
Definition: OccupancyGrid.h:43
yarp::rosmsg::nav_msgs::MapMetaData info
Definition: OccupancyGrid.h:42
yarp::rosmsg::std_msgs::Header header
Definition: OccupancyGrid.h:41
yarp::conf::float32_t b
Definition: ColorRGBA.h:34
yarp::conf::float32_t a
Definition: ColorRGBA.h:35
yarp::conf::float32_t g
Definition: ColorRGBA.h:33
yarp::conf::float32_t r
Definition: ColorRGBA.h:32
yarp::rosmsg::TickTime stamp
Definition: Header.h:45
std::vector< yarp::rosmsg::visualization_msgs::Marker > markers
Definition: MarkerArray.h:30
yarp::rosmsg::std_msgs::ColorRGBA color
Definition: Marker.h:101
static const std::uint8_t ARROW
Definition: Marker.h:78
yarp::rosmsg::TickDuration lifetime
Definition: Marker.h:102
yarp::rosmsg::geometry_msgs::Vector3 scale
Definition: Marker.h:100
static const std::uint8_t ADD
Definition: Marker.h:90
yarp::rosmsg::geometry_msgs::Pose pose
Definition: Marker.h:99
yarp::rosmsg::std_msgs::Header header
Definition: Marker.h:94
A class for a Matrix.
Definition: Matrix.h:39
#define yCInfo(component,...)
Definition: LogComponent.h:171
#define yCError(component,...)
Definition: LogComponent.h:213
#define yCTrace(component,...)
Definition: LogComponent.h:84
#define yCWarning(component,...)
Definition: LogComponent.h:192
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:76
For streams capable of holding different kinds of content, check what they actually have.
yarp::sig::Matrix rpy2dcm(const yarp::sig::Vector &rpy)
Converts roll-pitch-yaw angles in the corresponding dcm (direction cosine matrix) rotation matrix (de...
Definition: math.cpp:847
yarp::sig::Vector dcm2rpy(const yarp::sig::Matrix &R)
Converts a dcm (direction cosine matrix) rotation matrix to roll-pitch-yaw angles (defined in Math....
Definition: math.cpp:808
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::uint32_t NetUint32
Definition of the NetUint32 type.
Definition: NetUint32.h:29