mapping.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2020 Northwestern University
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *********************************************************************/
39 #include <cmath>
40 
43 
44 namespace ergodic_exploration
45 {
51 double logOdds2Prob(double l)
52 {
53  return 1.0 - (1.0 / (1.0 + std::exp(l)));
54 }
55 
61 double prob2LogOdds(double p)
62 {
63  return std::log(p / (1.0 - p));
64 }
65 
67  : Tbs_(Tbs)
68  , prior_(0.5)
69  , prob_occ_(0.90)
70  , prob_free_(0.35)
71  , log_odds_prior_(prob2LogOdds(prior_))
72  , log_odds_occ_(prob2LogOdds(prob_occ_))
73  , log_odds_free_(prob2LogOdds(prob_free_))
74 {
75 }
76 
78  const sensor_msgs::LaserScan::ConstPtr& scan,
79  const vec& pose)
80 {
81  const auto psg = grid.world2Grid(pose(0), pose(1));
82  if (!grid.gridBounds(psg.at(0), psg.at(1)))
83  {
84  std::cout << "WARNING: Cannot update map robot is not within bounds" << std::endl;
85  return false;
86  }
87 
88  // pm = Tmb * Tbs * ps
89  const mat Tms = transform2d(pose(0), pose(1), pose(2)) * Tbs_;
90 
91  const auto range_max = scan->range_max;
92  const auto range_min = scan->range_min;
93 
94  auto beam_angle = scan->angle_min;
95 
96  // Itertate over all measurements
97  for (unsigned int i = 0; i < scan->ranges.size(); i++)
98  {
99  if ((scan->ranges.at(i) > range_max) || (scan->ranges.at(i) < range_min))
100  {
101  beam_angle += scan->angle_increment;
102  continue;
103  }
104 
105  // Transform laser end point into frame of map
106  const vec pt = Tms * polar2CartesianHomo(beam_angle, scan->ranges.at(i));
107  const auto ptg = grid.world2Grid(pt(0), pt(1));
108 
109  // Only map using range measurements within map bounds
110  if (grid.gridBounds(ptg.at(0), ptg.at(1)))
111  {
112  // Ray trace to find cell indices that are free space
113  rayTrace(grid, psg.at(1), psg.at(0), ptg.at(1), ptg.at(0));
114 
115  // Update the end point
116  updateCell(grid, ptg.at(1), ptg.at(0), log_odds_occ_);
117  }
118 
119  else
120  {
121  std::cout << "WARNING: Skipping range measurement, not within bounds" << std::endl;
122  }
123 
124  beam_angle += scan->angle_increment;
125  }
126 
127  return true;
128 }
129 
130 void OccupancyMapper::rayTrace(GridMap& grid, int x0, int y0, int x1, int y1) const
131 {
132  auto dx = x1 - x0;
133  auto dy = y1 - y0;
134 
135  // Case: vertical
137  if (dx == 0)
138  {
139  // std::cout << "Plot Line Vertically" << std::endl;
140  // move down
141  if (dy < 0)
142  {
143  for (auto y = y0; y > y1; y--)
144  {
145  updateCell(grid, x0, y, log_odds_free_);
146  }
147  }
148 
149  // move up
150  else
151  {
152  for (auto y = y0; y < y1; y++)
153  {
154  updateCell(grid, x0, y, log_odds_free_);
155  }
156  }
157  }
159 
160  // Case: horizontal
162  else if (dy == 0)
163  {
164  // std::cout << "Plot Line Horizontally" << std::endl;
165  // move left
166  if (dx < 0)
167  {
168  for (auto x = x0; x > x1; x--)
169  {
170  updateCell(grid, x, y0, log_odds_free_);
171  }
172  }
173 
174  // move right
175  else
176  {
177  for (auto x = x0; x < x1; x++)
178  {
179  updateCell(grid, x, y0, log_odds_free_);
180  }
181  }
182  }
184 
185  // Case: Draw line down and need to move farther in x than in y. (increment x every itertation)
187  else if (std::abs(dy) < std::abs(dx))
188  {
189  // std::cout << "Plot Line Low" << std::endl;
190  // Octant 5
191  if (x0 > x1)
192  {
193  // add starting cell
194  updateCell(grid, x0, y0, log_odds_free_);
195  lineLow(grid, x1, y1, x0, y0);
196  }
197 
198  // Octant 3
199  else
200  {
201  // add starting cell
202  updateCell(grid, x0, y0, log_odds_free_);
203  lineLow(grid, x0, y0, x1, y1);
204  }
205  }
207 
208  // Case: Draw line down and need to move farther in y than in x. (increment y every itertation)
210  else if (std::abs(dy) > std::abs(dx))
211  {
212  // std::cout << "Plot Line High" << std::endl;
213  // Octant 7
214  if (y0 > y1)
215  {
216  // add starting cell
217  updateCell(grid, x0, y0, log_odds_free_);
218  lineHigh(grid, x1, y1, x0, y0);
219  }
220 
221  // Octant 1
222  else
223  {
224  // add starting cell
225  updateCell(grid, x0, y0, log_odds_free_);
226  lineHigh(grid, x0, y0, x1, y1);
227  }
228  }
230 
231  // Case: Diagnol at +/- 45 degrees
233  else if (std::abs(dy) == std::abs(dx))
234  {
235  lineDiag(grid, x0, y0, x1, y1);
236  }
238 
239  else
240  {
241  throw std::invalid_argument("Invalid Bresenham's Line Algorithm State");
242  }
243 }
244 
245 void OccupancyMapper::lineLow(GridMap& grid, int x0, int y0, int x1, int y1) const
246 {
247  auto dx = x1 - x0;
248  auto dy = y1 - y0;
249  auto yi = 1;
250 
251  if (dy < 0)
252  {
253  yi = -1;
254  dy = -dy;
255  }
256 
257  auto D = 2 * dy - dx;
258  auto y = y0;
259 
260  // counter
261  auto ctr = 0;
262 
263  for (auto x = x0; x < x1; x++)
264  {
265  // Start as been added already in function call
266  // prevents adding the end point in the case dx < 0
267  if (ctr != 0)
268  {
269  updateCell(grid, x, y, log_odds_free_);
270  }
271 
272  if (D > 0)
273  {
274  y += yi;
275  D -= 2 * dx;
276  }
277 
278  D += 2 * dy;
279  ctr++;
280  } // end loop
281 }
282 
283 void OccupancyMapper::lineHigh(GridMap& grid, int x0, int y0, int x1, int y1) const
284 {
285  auto dx = x1 - x0;
286  auto dy = y1 - y0;
287  auto xi = 1;
288 
289  if (dx < 0)
290  {
291  xi = -1;
292  dx = -dx;
293  }
294 
295  auto D = 2 * dx - dy;
296  auto x = x0;
297 
298  // counter
299  auto ctr = 0;
300 
301  for (auto y = y0; y < y1; y++)
302  {
303  // Start as been added already in function call
304  // prevents adding the end point in the case dy < 0
305  if (ctr != 0)
306  {
307  updateCell(grid, x, y, log_odds_free_);
308  }
309 
310  if (D > 0)
311  {
312  x += xi;
313  D -= 2 * dy;
314  }
315 
316  D += 2 * dx;
317  ctr++;
318  } // end loop
319 }
320 
321 void OccupancyMapper::lineDiag(GridMap& grid, int x0, int y0, int x1, int y1) const
322 {
323  const auto dx = x1 - x0;
324  const auto dy = y1 - y0;
325 
326  const auto xi = (dx < 0) ? -1 : 1;
327  const auto yi = (dy < 0) ? -1 : 1;
328 
329  auto x = x0;
330  auto y = y0;
331 
332  while (x != x1 and y != y1)
333  {
334  updateCell(grid, x, y, log_odds_free_);
335 
336  x += xi;
337  y += yi;
338  }
339 }
340 
341 void OccupancyMapper::updateCell(GridMap& grid, int x, int y, double log) const
342 {
343  const auto idx = grid.grid2RowMajor(y, x);
344  const auto log_odds = prob2LogOdds(grid.getCell(idx)) + log - log_odds_prior_;
345 
346  // std::cout << logOdds2Prob(log_odds)*100.0 << std::endl;
347  grid.grid_data_.at(idx) = static_cast<int8_t>(logOdds2Prob(log_odds) * 100.0);
348 }
349 
350 } // namespace ergodic_exploration
ergodic_exploration::OccupancyMapper::Tbs_
mat Tbs_
Definition: mapping.hpp:128
ergodic_exploration::GridMap::gridBounds
bool gridBounds(unsigned int i, unsigned int j) const
Test if coordinates are within the grid.
Definition: grid.cpp:96
ergodic_exploration::GridMap::grid2RowMajor
unsigned int grid2RowMajor(unsigned int i, unsigned int j) const
Converts grid indices to row major order index.
Definition: grid.cpp:109
mapping.hpp
Occupancy grid mapping.
ergodic_exploration::OccupancyMapper::rayTrace
void rayTrace(GridMap &grid, int x0, int y0, int x1, int y1) const
Bresenham's line algorithm on occupancy map.
Definition: mapping.cpp:130
ergodic_exploration::prob2LogOdds
double prob2LogOdds(double p)
Convert probability to log odds.
Definition: mapping.cpp:61
ergodic_exploration::OccupancyMapper::log_odds_occ_
double log_odds_occ_
Definition: mapping.hpp:131
ergodic_exploration::OccupancyMapper::updateCell
void updateCell(GridMap &grid, int x, int y, double log) const
Update grid cell probability of occupancy.
Definition: mapping.cpp:341
ergodic_exploration::OccupancyMapper::lineHigh
void lineHigh(GridMap &grid, int x0, int y0, int x1, int y1) const
Bresenham's algorithm for drawing lines upward.
Definition: mapping.cpp:283
ergodic_exploration::OccupancyMapper::lineLow
void lineLow(GridMap &grid, int x0, int y0, int x1, int y1) const
Bresenham's algorithm for drawing lines downward.
Definition: mapping.cpp:245
ergodic_exploration::GridMap::grid_data_
GridData grid_data_
Definition: grid.hpp:258
ergodic_exploration::GridMap::world2Grid
std::vector< unsigned int > world2Grid(double x, double y) const
Convert world coordinates to row and column index in grid.
Definition: grid.cpp:143
ergodic_exploration::OccupancyMapper::updateMap
bool updateMap(GridMap &grid, const sensor_msgs::LaserScan::ConstPtr &scan, const vec &pose)
Update the occupancy grid map.
Definition: mapping.cpp:77
ergodic_exploration
Definition: basis.hpp:43
ergodic_exploration::GridMap
Constructs an 2D grid.
Definition: grid.hpp:79
ergodic_exploration::polar2CartesianHomo
vec polar2CartesianHomo(double angle, double range)
Convert polar to cartesian homogenous coordinates.
Definition: numerics.hpp:198
numerics.hpp
Useful numerical utilities.
ergodic_exploration::OccupancyMapper::lineDiag
void lineDiag(GridMap &grid, int x0, int y0, int x1, int y1) const
Bresenham's algorithm for drawing lines at +/- 45 deg.
Definition: mapping.cpp:321
ergodic_exploration::OccupancyMapper::log_odds_prior_
double log_odds_prior_
Definition: mapping.hpp:130
ergodic_exploration::OccupancyMapper::log_odds_free_
double log_odds_free_
Definition: mapping.hpp:132
ergodic_exploration::transform2d
mat transform2d(double x, double y, double angle)
Construct 2D transformation matrix.
Definition: numerics.hpp:212
ergodic_exploration::logOdds2Prob
double logOdds2Prob(double l)
Convert log odds to a probability.
Definition: mapping.cpp:51
ergodic_exploration::GridMap::getCell
double getCell(double x, double y) const
Get the value of the cell at a specified position.
Definition: grid.cpp:167
ergodic_exploration::OccupancyMapper::OccupancyMapper
OccupancyMapper(const mat &Tbs)
Constructor.
Definition: mapping.cpp:66


ergodic_exploration
Author(s): bostoncleek
autogenerated on Wed Mar 2 2022 00:17:13