MapHelper.hpp
Go to the documentation of this file.
1 
20 #pragma once
21 
22 #include <ros/ros.h>
23 #include <nav_msgs/GetMap.h>
24 #include <nav_msgs/OccupancyGrid.h>
25 #include <nav_msgs/Path.h>
26 #include <nav_msgs/GetPlan.h>
27 #include <geometry_msgs/PoseStamped.h>
28 #include <cmath>
29 #include <vector>
30 #include <boost/tuple/tuple.hpp>
32 #include <tf/transform_listener.h>
37 
38 namespace robot_model_services {
39  struct RayTracingIndex {
40  int32_t x;
41  int32_t y;
42  int8_t occupancy;
43  public:
44  static bool topologicalCompare(const RayTracingIndex &source, const RayTracingIndex &firstIndex, const RayTracingIndex &secondIndex) {
45  SimpleVector2 sourceVector(source.x, source.y);
46  SimpleVector2 firstIndexVector(firstIndex.x, firstIndex.y);
47  SimpleVector2 secondIndexVector(secondIndex.x, secondIndex.y);
48 
49  return (firstIndexVector - sourceVector).squaredNorm() < (secondIndexVector - sourceVector).squaredNorm();
50  }
51 
52  static bool equals(const RayTracingIndex &firstIndex, const RayTracingIndex &secondIndex) {
53  SimpleVector2 firstIndexVector(firstIndex.x, firstIndex.y);
54  SimpleVector2 secondIndexVector(secondIndex.x, secondIndex.y);
55  return firstIndexVector == secondIndexVector;
56  }
57  };
59  typedef std::vector<RayTracingIndex> Ray;
60 
61 
62  class MapHelper {
63  private:
65 
70  nav_msgs::OccupancyGrid mMap;
72  nav_msgs::OccupancyGrid mRaytracingMap;
73  // table to translate from values 0-255 in Costmap2D to values -1 to 100 in OccupancyGrid
74  int8_t mCostTranslationTable[256];
75  public:
76  MapHelper(const std::string &mapTopicName = "map", const std::string &getPlanServiceName = "move_base/make_plan") : mMapReceived(false), mCollisionThreshold(45) {
77  mDebugHelperPtr = DebugHelper::getInstance();
78 
79  // set cost translation table
80  mCostTranslationTable[0] = 0; // NO obstacle
81  mCostTranslationTable[253] = 99; // INSCRIBED obstacle
82  mCostTranslationTable[254] = 100; // LETHAL obstacle
83  mCostTranslationTable[255] = -1; // UNKNOWN
84 
85  for (int i = 1; i < 253; i++) {
86  mCostTranslationTable[i] = int8_t(1 + (97 * (i - 1)) / 251);
87  }
88 
89  ros::Subscriber mapSubscriber = mGlobalNodeHandle.subscribe<nav_msgs::OccupancyGrid>(mapTopicName, 1, &MapHelper::mapReceived, this);
90  while(ros::ok() && !mMapReceived) {
91  mDebugHelperPtr->write(std::stringstream() << "Waiting for map to arrive on topic '" << mapSubscriber.getTopic() << "'",
93 
94  ros::spinOnce();
95  ros::Duration(0.5).sleep();
96  }
97 
98  mDebugHelperPtr->write(std::stringstream() << "waiting for service: " << getPlanServiceName, DebugHelper::MAP);
99  ros::service::waitForService(getPlanServiceName, -1);
100  mGetPlanServiceClient = mGlobalNodeHandle.serviceClient<nav_msgs::GetPlan>(getPlanServiceName, true);
101  while(ros::ok() && !mGetPlanServiceClient.exists()) {
102  mDebugHelperPtr->write(std::stringstream() << "Waiting for planning server to start on service '"
103  << mGetPlanServiceClient.getService(), DebugHelper::MAP);
104  ros::spinOnce();
105  ros::Duration(0.5).sleep();
106  }
107  this->setCostmap();
108  this->aggregateRaytracingMap();
109  }
110 
111  virtual ~MapHelper() { }
112  private:
113  void mapReceived(nav_msgs::OccupancyGrid map) {
114  mDebugHelperPtr->write("Map received", DebugHelper::MAP);
115  mMap = map;
116  mMapReceived = true;
117  mDebugHelperPtr->write(std::stringstream() << "Map resolution: " << mMap.info.resolution, DebugHelper::MAP);
118  mDebugHelperPtr->write(std::stringstream() << "Map translation: " << this->getTranslation(), DebugHelper::MAP);
119  mDebugHelperPtr->write(std::stringstream() << "Map orientation: " << this->getOrientation().w() << ", "
120  << this->getOrientation().x() << ", "
121  << this->getOrientation().y() << ", "
122  << this->getOrientation().z(),
124  mDebugHelperPtr->write(std::stringstream() << "Map metric width: " << this->getMetricWidth(), DebugHelper::MAP);
125  mDebugHelperPtr->write(std::stringstream() << "Map metric height: " << this->getMetricHeight(), DebugHelper::MAP);
126  }
127 
128  void setCostmap() {
130  std::string name = "global_costmap";
131  costmap_2d::Costmap2DROS costmapRos(name, tf);
132  costmapRos.start();
133  costmapRos.updateMap();
134  costmapRos.stop();
135 
136  mCostmap = *(costmapRos.getCostmap());
137 
138  // get output path
139  std::string path;
140  mGlobalNodeHandle.getParam("/nbv/mMapsImagePath", path);
141 
142  // output costmap
143  std::string costmapPath = path + "/costmap.pgm";
144  mDebugHelperPtr->write("Outputting calculated costmap to " + costmapPath,
146  mCostmap.saveMap(costmapPath);
147  }
148 
150  mDebugHelperPtr->write("Aggregating raytracing map.", DebugHelper::MAP);
151  if (mMap.info.width != mCostmap.getSizeInCellsX() || mMap.info.height != mCostmap.getSizeInCellsY()) {
152  ROS_ERROR("Cannot aggregate raytracing map. Dimensions of map and costmap do not match!");
153  mDebugHelperPtr->write(std::stringstream() << "Map size: " << mMap.info.width << "x" << mMap.info.height, DebugHelper::MAP);
154  mDebugHelperPtr->write(std::stringstream() << "Costmap size: " << mCostmap.getSizeInCellsX() << "x" << mCostmap.getSizeInCellsY(), DebugHelper::MAP);
155  assert(mMap.info.width == mCostmap.getSizeInCellsX() && mMap.info.height == mCostmap.getSizeInCellsY());
156  }
157 
158  mRaytracingMap.info = mMap.info;
159  mRaytracingMap.data.reserve(mMap.data.size());
160  for (unsigned int y = 0; y < mMap.info.height; y++) {
161  for (unsigned int x = 0; x < mMap.info.width; x++) {
162  unsigned int index = y * mMap.info.width + x;
163  int8_t mapOccupancyValue = mMap.data[index];
164  int8_t costmapOccupancyValue = mCostTranslationTable[mCostmap.getCost(x, y)];
165  int8_t aggregatedOccupancyValue = mapOccupancyValue == -1 ? -1 : costmapOccupancyValue;
166 
167  mRaytracingMap.data[index] = aggregatedOccupancyValue;
168  }
169  }
170  mDebugHelperPtr->write("Aggregation done.", DebugHelper::MAP);
171  }
172 
173  int8_t getOccupancyValue(const nav_msgs::OccupancyGrid &map, const SimpleVector3 &position) {
174  int32_t mapX, mapY;
175  this->worldToMapCoordinates(position, mapX, mapY);
176  return this->getOccupancyValue(map, mapX, mapY);
177  }
178 
179  int8_t getOccupancyValue(const costmap_2d::Costmap2D &costmap, const SimpleVector3 &position) {
180  int32_t mapX, mapY;
181  this->worldToMapCoordinates(position, mapX, mapY);
182  return this->getOccupancyValue(costmap, mapX, mapY);
183  }
184 
185  int8_t getOccupancyValue(const nav_msgs::OccupancyGrid &map, const int32_t &mapX, const int32_t &mapY) {
186  uint32_t width = map.info.width;
187  uint32_t height = map.info.height;
188 
189  if (mapX < 0 || mapY < 0 || mapX >= (int32_t)width || mapY >= (int32_t)height) {
190  return -1;
191  }
192 
193  return map.data[mapX + mapY * width];
194  }
195 
196  int8_t getOccupancyValue(const costmap_2d::Costmap2D &costmap, const int32_t &mapX, const int32_t &mapY) {
197  uint32_t width = costmap.getSizeInCellsX();
198  uint32_t height = costmap.getSizeInCellsY();
199 
200  if (mapX < 0 || mapY < 0 || mapX >= (int32_t)width || mapY >= (int32_t)height) {
201  return -1;
202  }
203 
204  unsigned char cost = costmap.getCost(mapX, mapY);
205  return mCostTranslationTable[cost];
206  }
207 
208  public:
209  int8_t getMapOccupancyValue(const SimpleVector3 &position) {
210  return this->getOccupancyValue(mMap, position);
211  }
212 
213  int8_t getMapOccupancyValue(const int32_t &mapX, const int32_t &mapY) {
214  return this->getOccupancyValue(mMap, mapX, mapY);
215  }
216 
217 
218  int8_t getCostmapOccupancyValue(const SimpleVector3 &position) {
219  return this->getOccupancyValue(mCostmap, position);
220  }
221 
222  int8_t getCostmapOccupancyValue(const int32_t &mapX, const int32_t &mapY) {
223  return this->getOccupancyValue(mCostmap, mapX, mapY);
224  }
225 
226 
228  return this->getOccupancyValue(mRaytracingMap, position);
229  }
230 
231  int8_t getRaytracingMapOccupancyValue(const int32_t &mapX, const int32_t &mapY) {
232  return this->getOccupancyValue(mRaytracingMap, mapX, mapY);
233  }
234 
235  bool doRaytracing(const SimpleVector3 &fromPoint, const SimpleVector3 &toPoint) {
236  Ray ray;
237  bool retVal = this->doRaytracing(fromPoint, toPoint, ray);
238  return retVal;
239  }
240 
241  bool doRaytracing(const SimpleVector3 &fromPoint, const SimpleVector3 &toPoint, Ray &ray) {
242  // clear ray
243  ray.clear();
244 
245  // get the discrete coordinates from world coordinates
246  int32_t fromMapX, fromMapY;
247  this->worldToMapCoordinates(fromPoint, fromMapX, fromMapY);
248 
249  int32_t toMapX, toMapY;
250  this->worldToMapCoordinates(toPoint, toMapX, toMapY);
251 
252  // calculate the distances
253  int32_t distanceX = toMapX - fromMapX;
254  int32_t distanceY = toMapY - fromMapY;
255 
256  // return the result of a zero length raytracing
257  if (distanceX == 0 && distanceY == 0) {
258  int8_t occupancyValue = this->getRaytracingMapOccupancyValue(fromMapX, fromMapY);
259  return this->isOccupancyValueAcceptable(occupancyValue);
260  }
261 
262  // get the bounds - needed to prevent non feasible results
263  int32_t minX = std::min(fromMapX, toMapX);
264  int32_t maxX = std::max(fromMapX, toMapX);
265  int32_t minY = std::min(fromMapY, toMapY);
266  int32_t maxY = std::max(fromMapY, toMapY);
267 
268  // get the resolution
269  float resolution = mRaytracingMap.info.resolution;
270 
271  // get the signum of the distance
272  int32_t signumX = distanceX < 0 ? - 1 : 1;
273  int32_t signumY = distanceY < 0 ? - 1 : 1;
274 
275  // calculate the difference between the two points
276  SimpleVector2 diff = (toPoint - fromPoint).block<2, 1>(0, 0);
277 
278  // contains the value about success of raytracing
279  bool rayTracingSucceeded = true;
280 
281  // tracing along the x-axis
282  for (int32_t offsetX = 0; offsetX <= abs(distanceX) + 1 && diff[0] != 0; offsetX += 1) {
283  double x = (fromMapX + signumX * offsetX) * resolution;
284  double t = (x - fromPoint[0]) / diff[0];
285  double y = fromPoint[1] + t * diff[1];
286 
287  RayTracingIndex idx;
288  idx.x = (int32_t) (x / resolution);
289  idx.y = (int32_t) (y / resolution);
290  idx.occupancy = this->getRaytracingMapOccupancyValue(idx.x, idx.y);
291 
292  if (idx.x < minX || idx.x > maxX || idx.y < minY || idx.y > maxY) {
293  continue;
294  }
295 
296  if (!this->isOccupancyValueAcceptable(idx.occupancy)) {
297  rayTracingSucceeded = false;
298  }
299 
300  ray.push_back(idx);
301  }
302 
303  // tracing along the y axis.
304  for (int32_t offsetY = 0; offsetY <= abs(distanceY) + 1 && diff[1] != 0; offsetY += 1) {
305  double y = (fromMapY + signumY * offsetY) * resolution;
306  double t = (y - fromPoint[1]) / diff[1];
307  double x = fromPoint[0] + t * diff[0];
308 
309  RayTracingIndex idx;
310  idx.x = (int32_t) (x / resolution);
311  idx.y = (int32_t) (y / resolution);
312  idx.occupancy = this->getRaytracingMapOccupancyValue(idx.x, idx.y);
313 
314  if (idx.x < minX || idx.x > maxX || idx.y < minY || idx.y > maxY) {
315  continue;
316  }
317 
318  if (!this->isOccupancyValueAcceptable(idx.occupancy)) {
319  rayTracingSucceeded = false;
320  }
321 
322  ray.push_back(idx);
323  }
324 
325  // do a topological sort by distance to the fromPoint
326  RayTracingIndex source = {fromMapX, fromMapY, 0};
327  std::stable_sort(ray.begin(), ray.end(), boost::bind(&RayTracingIndex::topologicalCompare, source, _1, _2));
328 
329  // remove duplicate values
330  Ray::iterator endIterator = std::unique(ray.begin(), ray.end(), &RayTracingIndex::equals);
331  ray.resize(std::distance(ray.begin(), endIterator));
332 
333  return rayTracingSucceeded;
334  }
335 
336  float getMetricWidth() {
337  return mMap.info.width * mMap.info.resolution;
338  }
339 
340  float getMetricHeight() {
341  return mMap.info.height * mMap.info.resolution;
342  }
343 
344  void worldToMapCoordinates(const SimpleVector3 &position, int32_t &x, int32_t &y) {
345  SimpleVector3 continuousMapCoords;
346  worldToMapCoordinates(position, continuousMapCoords);
347 
348  // get the map coords
349  x = (int32_t) floor(continuousMapCoords[0]);
350  y = (int32_t) floor(continuousMapCoords[1]);
351  }
352 
353  void worldToMapCoordinates(const SimpleVector3 &position, SimpleVector3 &result) {
354  SimpleVector3 translation = this->getTranslation();
355  SimpleQuaternion orientation = this->getOrientation();
356  SimpleMatrix3 rotationMatrix = orientation.toRotationMatrix();
357 
358  // the map is rotated by rotation matrix, for back transform do a transpose.
359  result = (rotationMatrix.transpose() * position - translation) / mMap.info.resolution;
360  }
361 
362  void mapToWorldCoordinates(const int32_t &x, const int32_t &y, SimpleVector3 &result) {
363  mapToWorldCoordinates(SimpleVector3(x, y, 0.0), result);
364  }
365 
366  void mapToWorldCoordinates(const SimpleVector3 &position, SimpleVector3 &result) {
367  SimpleVector3 translation = this->getTranslation();
368  SimpleQuaternion orientation = this->getOrientation();
369  result = orientation.toRotationMatrix() * position * mMap.info.resolution + translation;
370  }
371 
372  void mapToWorldSize(const double &size, double &result) {
373  result = size * mMap.info.resolution;
374  }
375 
376  void worldToMapSize(const double &size, double &result) {
377  result = size / mMap.info.resolution;
378  }
379 
381  return SimpleVector3(mMap.info.origin.position.x, mMap.info.origin.position.y, mMap.info.origin.position.z);
382  }
383 
385  return TypeHelper::getSimpleQuaternion(mMap.info.origin.orientation);
386  }
387 
388  bool isOccupancyValueAcceptable(const int8_t &occupancyValue) {
389  return occupancyValue >= 0 && occupancyValue <= mCollisionThreshold;
390  }
391 
392  void setCollisionThreshold(int8_t thresholdValue) {
393  mCollisionThreshold = thresholdValue;
394  }
395 
397  return mCollisionThreshold;
398  }
399 
400  float getSquaredDistance(const SimpleVector3 &start, const SimpleVector3 &goal) {
401  return (goal - start).squaredNorm();
402  }
403  };
404 
406 }
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
static SimpleQuaternion getSimpleQuaternion(const geometry_msgs::Pose &pose)
Definition: TypeHelper.cpp:65
Eigen::Matrix< Precision, 2, 1 > SimpleVector2
Definition: typedef.hpp:49
void worldToMapCoordinates(const SimpleVector3 &position, SimpleVector3 &result)
Definition: MapHelper.hpp:353
costmap_2d::Costmap2D mCostmap
Definition: MapHelper.hpp:71
float getSquaredDistance(const SimpleVector3 &start, const SimpleVector3 &goal)
Definition: MapHelper.hpp:400
int8_t getOccupancyValue(const nav_msgs::OccupancyGrid &map, const int32_t &mapX, const int32_t &mapY)
Definition: MapHelper.hpp:185
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool isOccupancyValueAcceptable(const int8_t &occupancyValue)
Definition: MapHelper.hpp:388
void setCollisionThreshold(int8_t thresholdValue)
Definition: MapHelper.hpp:392
static boost::shared_ptr< DebugHelper > getInstance()
Definition: DebugHelper.cpp:29
int8_t getMapOccupancyValue(const int32_t &mapX, const int32_t &mapY)
Definition: MapHelper.hpp:213
bool sleep() const
ros::NodeHandle mGlobalNodeHandle
Definition: MapHelper.hpp:68
void mapToWorldCoordinates(const int32_t &x, const int32_t &y, SimpleVector3 &result)
Definition: MapHelper.hpp:362
Eigen::Matrix< Precision, 3, 1 > SimpleVector3
Definition: typedef.hpp:50
void mapToWorldCoordinates(const SimpleVector3 &position, SimpleVector3 &result)
Definition: MapHelper.hpp:366
int8_t getOccupancyValue(const nav_msgs::OccupancyGrid &map, const SimpleVector3 &position)
Definition: MapHelper.hpp:173
int8_t getRaytracingMapOccupancyValue(const int32_t &mapX, const int32_t &mapY)
Definition: MapHelper.hpp:231
bool doRaytracing(const SimpleVector3 &fromPoint, const SimpleVector3 &toPoint, Ray &ray)
Definition: MapHelper.hpp:241
boost::shared_ptr< MapHelper > MapHelperPtr
Definition: MapHelper.hpp:405
ros::ServiceClient mGetPlanServiceClient
Definition: MapHelper.hpp:69
std::vector< RayTracingIndex > Ray
Definition: MapHelper.hpp:59
int8_t getOccupancyValue(const costmap_2d::Costmap2D &costmap, const int32_t &mapX, const int32_t &mapY)
Definition: MapHelper.hpp:196
unsigned char getCost(unsigned int mx, unsigned int my) const
void mapToWorldSize(const double &size, double &result)
Definition: MapHelper.hpp:372
int8_t getCostmapOccupancyValue(const int32_t &mapX, const int32_t &mapY)
Definition: MapHelper.hpp:222
int8_t getMapOccupancyValue(const SimpleVector3 &position)
Definition: MapHelper.hpp:209
void worldToMapSize(const double &size, double &result)
Definition: MapHelper.hpp:376
bool saveMap(std::string file_name)
int8_t getRaytracingMapOccupancyValue(const SimpleVector3 &position)
Definition: MapHelper.hpp:227
nav_msgs::OccupancyGrid mMap
Definition: MapHelper.hpp:70
int8_t getCostmapOccupancyValue(const SimpleVector3 &position)
Definition: MapHelper.hpp:218
std::string getTopic() const
this namespace contains all generally usable classes.
Definition: DebugHelper.hpp:27
ROSCPP_DECL bool ok()
unsigned int getSizeInCellsY() const
static bool equals(const RayTracingIndex &firstIndex, const RayTracingIndex &secondIndex)
Definition: MapHelper.hpp:52
bool doRaytracing(const SimpleVector3 &fromPoint, const SimpleVector3 &toPoint)
Definition: MapHelper.hpp:235
SimpleQuaternion getOrientation()
Definition: MapHelper.hpp:384
TFSIMD_FORCE_INLINE const tfScalar & z() const
void worldToMapCoordinates(const SimpleVector3 &position, int32_t &x, int32_t &y)
Definition: MapHelper.hpp:344
TFSIMD_FORCE_INLINE const tfScalar & w() const
MapHelper(const std::string &mapTopicName="map", const std::string &getPlanServiceName="move_base/make_plan")
Definition: MapHelper.hpp:76
static bool topologicalCompare(const RayTracingIndex &source, const RayTracingIndex &firstIndex, const RayTracingIndex &secondIndex)
Definition: MapHelper.hpp:44
unsigned int getSizeInCellsX() const
Eigen::Matrix< Precision, 3, 3 > SimpleMatrix3
Definition: typedef.hpp:37
bool getParam(const std::string &key, std::string &s) const
boost::shared_ptr< RayTracingIndex > RayTracingIndexPtr
Definition: MapHelper.hpp:58
void mapReceived(nav_msgs::OccupancyGrid map)
Definition: MapHelper.hpp:113
std::string getService()
Costmap2D * getCostmap()
nav_msgs::OccupancyGrid mRaytracingMap
Definition: MapHelper.hpp:72
int8_t getOccupancyValue(const costmap_2d::Costmap2D &costmap, const SimpleVector3 &position)
Definition: MapHelper.hpp:179
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
Eigen::Quaternion< Precision > SimpleQuaternion
Definition: typedef.hpp:64
ROSCPP_DECL bool waitForService(const std::string &service_name, int32_t timeout)


asr_robot_model_services
Author(s): Aumann Florian, Borella Jocelyn, Heller Florian, Meißner Pascal, Schleicher Ralf, Stöckle Patrick, Stroh Daniel, Trautmann Jeremias, Walter Milena, Wittenbeck Valerij
autogenerated on Mon Jun 10 2019 12:49:59