HectorMapTools.h
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2011, Stefan Kohlbrecher, TU Darmstadt
3 // All rights reserved.
4 
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the Simulation, Systems Optimization and Robotics
13 // group, TU Darmstadt nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without
15 // specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
29 #ifndef __HectorMapTools_h_
30 #define __HectorMapTools_h_
31 
32 #include <nav_msgs/OccupancyGrid.h>
33 #include <nav_msgs/MapMetaData.h>
34 
35 #include<Eigen/Core>
36 
38 public:
39 
40  template<typename ConcreteScalar>
42  public:
43 
45  {
46 
47  }
48 
49  CoordinateTransformer(const nav_msgs::OccupancyGridConstPtr map)
50  {
51  this->setTransforms(*map);
52  }
53 
54 
55  void setTransforms(const nav_msgs::OccupancyGrid& map)
56  {
57  this->setTransforms(map.info);
58  }
59 
60  void setTransforms(const nav_msgs::MapMetaData& meta)
61  {
62  origo_ = (Eigen::Matrix<ConcreteScalar, 2, 1>(static_cast<ConcreteScalar>(meta.origin.position.x),static_cast<ConcreteScalar>(meta.origin.position.y)));
63  scale_ = (static_cast<ConcreteScalar>(meta.resolution));
64  inv_scale_ = (static_cast<ConcreteScalar>(1.0f / meta.resolution));
65  }
66 
67  void setTransformsBetweenCoordSystems(const Eigen::Matrix<ConcreteScalar, 2, 1>& origoCS1, const Eigen::Matrix<ConcreteScalar, 2, 1>& endCS1,
68  const Eigen::Matrix<ConcreteScalar, 2, 1>& origoCS2, const Eigen::Matrix<ConcreteScalar, 2, 1>& endCS2)
69  {
70  Eigen::Matrix<ConcreteScalar, 2, 1> map_t_geotiff_x_factors = getLinearTransform(Eigen::Vector2f(origoCS1[0], endCS1[0]), Eigen::Vector2f(origoCS2[0], endCS2[0]));
71  Eigen::Matrix<ConcreteScalar, 2, 1> map_t_geotiff_y_factors = getLinearTransform(Eigen::Vector2f(origoCS1[1], endCS1[1]), Eigen::Vector2f(origoCS2[1], endCS2[1]));
72 
73  //std::cout << "\n geo_x: \n" << map_t_geotiff_x_factors << "\n geo_y: \n" << map_t_geotiff_y_factors << "\n";
74 
75  origo_.x() = map_t_geotiff_x_factors[1];
76  origo_.y() = map_t_geotiff_y_factors[1];
77 
78  scale_ = map_t_geotiff_x_factors[0];
79  inv_scale_ = 1.0 / scale_;
80 
81  //std::cout << "\nscale " << scale_ << "\n";
82  }
83 
84  Eigen::Matrix<ConcreteScalar, 2, 1> getC1Coords(const Eigen::Matrix<ConcreteScalar, 2, 1>& mapCoords) const
85  {
86  return origo_ + (mapCoords * scale_);
87  }
88 
89  Eigen::Matrix<ConcreteScalar, 2, 1> getC2Coords(const Eigen::Matrix<ConcreteScalar, 2, 1>& worldCoords) const
90  {
91  return ((worldCoords - origo_) * inv_scale_);
92  }
93 
94  ConcreteScalar getC1Scale(float c2_scale) const
95  {
96  return scale_ * c2_scale;
97  }
98 
99  ConcreteScalar getC2Scale(float c1_scale) const
100  {
101  return inv_scale_ * c1_scale;
102  }
103 
104  protected:
105 
106  Eigen::Matrix<ConcreteScalar, 2, 1> getLinearTransform(const Eigen::Matrix<ConcreteScalar, 2, 1>& coordSystem1, const Eigen::Matrix<ConcreteScalar, 2, 1>& coordSystem2)
107  {
108  ConcreteScalar scaling = (coordSystem2[0] - coordSystem2[1]) / (coordSystem1[0] - coordSystem1[1]);
109  ConcreteScalar translation = coordSystem2[0] - coordSystem1[0] * scaling;
110  return Eigen::Vector2f (scaling, translation);
111  }
112 
113  Eigen::Matrix<ConcreteScalar, 2, 1> origo_;
114  ConcreteScalar scale_;
115  ConcreteScalar inv_scale_;
116  };
117 
119  {
120  public:
122  {
123 
124  }
125 
126  void setMap(const nav_msgs::OccupancyGridConstPtr map)
127  {
128  map_ptr_ = map;
129 
130  world_map_transformer_.setTransforms(*map_ptr_);
131  }
132 
133  float getDist(const Eigen::Vector2f& begin_world, const Eigen::Vector2f& end_world, Eigen::Vector2f* hitCoords = 0)
134  {
135  Eigen::Vector2i end_point_map;
136 
137  Eigen::Vector2i begin_map (world_map_transformer_.getC2Coords(begin_world).cast<int>());
138  Eigen::Vector2i end_map (world_map_transformer_.getC2Coords(end_world).cast<int>());
139  float dist = checkOccupancyBresenhami(begin_map, end_map, &end_point_map);
140 
141  if (hitCoords != 0){
142  *hitCoords = world_map_transformer_.getC1Coords(end_point_map.cast<float>());
143  }
144 
145  return world_map_transformer_.getC1Scale(dist);
146  }
147 
148  inline float checkOccupancyBresenhami( const Eigen::Vector2i& beginMap, const Eigen::Vector2i& endMap, Eigen::Vector2i* hitCoords = 0, unsigned int max_length = UINT_MAX){
149 
150  int x0 = beginMap[0];
151  int y0 = beginMap[1];
152 
153  int sizeX = map_ptr_->info.width;
154  int sizeY = map_ptr_->info.height;
155 
156  //check if beam start point is inside map, cancel update if this is not the case
157  if ((x0 < 0) || (x0 >= sizeX) || (y0 < 0) || (y0 >= sizeY)) {
158  return -1.0f;
159  }
160 
161  int x1 = endMap[0];
162  int y1 = endMap[1];
163 
164  //std::cout << " x: "<< x1 << " y: " << y1 << " length: " << length << " ";
165 
166  //check if beam end point is inside map, cancel update if this is not the case
167  if ((x1 < 0) || (x1 >= sizeX) || (y1 < 0) || (y1 >= sizeY)) {
168  return -1.0f;
169  }
170 
171  int dx = x1 - x0;
172  int dy = y1 - y0;
173 
174  unsigned int abs_dx = abs(dx);
175  unsigned int abs_dy = abs(dy);
176 
177  int offset_dx = dx > 0 ? 1 : -1;
178  int offset_dy = (dy > 0 ? 1 : -1) * sizeX;
179 
180  unsigned int startOffset = beginMap.y() * sizeX + beginMap.x();
181 
182  int end_offset;
183 
184  //if x is dominant
185  if(abs_dx >= abs_dy){
186  int error_y = abs_dx / 2;
187  end_offset = bresenham2D(abs_dx, abs_dy, error_y, offset_dx, offset_dy, startOffset,5000);
188  }else{
189  //otherwise y is dominant
190  int error_x = abs_dy / 2;
191  end_offset = bresenham2D(abs_dy, abs_dx, error_x, offset_dy, offset_dx, startOffset,5000);
192  }
193 
194  if (end_offset != -1){
195  Eigen::Vector2i end_coords(end_offset % sizeX, end_offset / sizeX);
196 
197  int distMap = ((beginMap - end_coords).cast<float>()).norm();
198 
199  if (hitCoords != 0){
200  *hitCoords = end_coords;
201  }
202 
203  return distMap;
204  }
205 
206  return -1.0f;
207 
208  //unsigned int endOffset = endMap.y() * sizeX + endMap.x();
209  //this->bresenhamCellOcc(endOffset);
210  }
211 
212  inline int bresenham2D(unsigned int abs_da, unsigned int abs_db, int error_b, int offset_a, int offset_b,
213  unsigned int offset, unsigned int max_length){
214  unsigned int end = std::min(max_length, abs_da);
215 
216  const std::vector<int8_t>& data = map_ptr_->data;
217 
218  for(unsigned int i = 0; i < end; ++i){
219  if (data[offset] == 100){
220  return static_cast<int>(offset);
221  }
222 
223  offset += offset_a;
224  error_b += abs_db;
225  if((unsigned int)error_b >= abs_da){
226  offset += offset_b;
227  error_b -= abs_da;
228  }
229  }
230  return -1;
231  //at(offset);
232  }
233 
234  protected:
236  nav_msgs::OccupancyGridConstPtr map_ptr_;
237 
238 
239  };
240 
241  static bool getMapExtends(const nav_msgs::OccupancyGrid& map, Eigen::Vector2i& topLeft, Eigen::Vector2i& bottomRight)
242  {
243  int lowerStart = -1;
244  int upperStart = 10000000;
245 
246  int xMaxTemp = lowerStart;
247  int yMaxTemp = lowerStart;
248  int xMinTemp = upperStart;
249  int yMinTemp = upperStart;
250 
251  int width = map.info.width;
252  int height = map.info.height;
253 
254  for (int y = 0; y < height; ++y){
255  for (int x = 0; x < width; ++x){
256 
257  if ( map.data[x+y*width] != -1){
258 
259  if (x > xMaxTemp) {
260  xMaxTemp = x;
261  }
262 
263  if (x < xMinTemp) {
264  xMinTemp = x;
265  }
266 
267  if (y > yMaxTemp) {
268  yMaxTemp = y;
269  }
270 
271  if (y < yMinTemp) {
272  yMinTemp = y;
273  }
274  }
275  }
276  }
277 
278  if ((xMaxTemp != lowerStart) &&
279  (yMaxTemp != lowerStart) &&
280  (xMinTemp != upperStart) &&
281  (yMinTemp != upperStart)) {
282 
283  topLeft = Eigen::Vector2i(xMinTemp,yMinTemp);
284  bottomRight = Eigen::Vector2i(xMaxTemp+1, yMaxTemp+1);
285 
286  return true;
287  } else {
288  return false;
289  }
290  };
291 };
292 
293 #endif
Eigen::Matrix< ConcreteScalar, 2, 1 > getC2Coords(const Eigen::Matrix< ConcreteScalar, 2, 1 > &worldCoords) const
ConcreteScalar getC1Scale(float c2_scale) const
Eigen::Matrix< ConcreteScalar, 2, 1 > getLinearTransform(const Eigen::Matrix< ConcreteScalar, 2, 1 > &coordSystem1, const Eigen::Matrix< ConcreteScalar, 2, 1 > &coordSystem2)
nav_msgs::OccupancyGridConstPtr map_ptr_
Eigen::Matrix< ConcreteScalar, 2, 1 > getC1Coords(const Eigen::Matrix< ConcreteScalar, 2, 1 > &mapCoords) const
void setMap(const nav_msgs::OccupancyGridConstPtr map)
float checkOccupancyBresenhami(const Eigen::Vector2i &beginMap, const Eigen::Vector2i &endMap, Eigen::Vector2i *hitCoords=0, unsigned int max_length=UINT_MAX)
Eigen::Matrix< ConcreteScalar, 2, 1 > origo_
void setTransforms(const nav_msgs::OccupancyGrid &map)
CoordinateTransformer(const nav_msgs::OccupancyGridConstPtr map)
ConcreteScalar getC2Scale(float c1_scale) const
void setTransformsBetweenCoordSystems(const Eigen::Matrix< ConcreteScalar, 2, 1 > &origoCS1, const Eigen::Matrix< ConcreteScalar, 2, 1 > &endCS1, const Eigen::Matrix< ConcreteScalar, 2, 1 > &origoCS2, const Eigen::Matrix< ConcreteScalar, 2, 1 > &endCS2)
void setTransforms(const nav_msgs::MapMetaData &meta)
float getDist(const Eigen::Vector2f &begin_world, const Eigen::Vector2f &end_world, Eigen::Vector2f *hitCoords=0)
CoordinateTransformer< float > world_map_transformer_
static bool getMapExtends(const nav_msgs::OccupancyGrid &map, Eigen::Vector2i &topLeft, Eigen::Vector2i &bottomRight)
int bresenham2D(unsigned int abs_da, unsigned int abs_db, int error_b, int offset_a, int offset_b, unsigned int offset, unsigned int max_length)


hector_map_tools
Author(s): Stefan Kohlbrecher
autogenerated on Sun Nov 3 2019 03:18:30