collision.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 <iostream>
40 #include <stdexcept>
41 
43 
44 namespace ergodic_exploration
45 {
46 Collision::Collision(double boundary_radius, double search_radius,
47  double obstacle_threshold, double occupied_threshold)
48  : boundary_radius_(boundary_radius)
49  , search_radius_(search_radius)
50  , obstacle_threshold_(obstacle_threshold)
51  , occupied_threshold_(occupied_threshold)
52 {
54  {
55  throw std::invalid_argument(
56  "Search radius must be at least the same size as the boundary radius");
57  }
58 
59  if (occupied_threshold_ > 100.0 || occupied_threshold_ < 0.0)
60  {
61  throw std::invalid_argument("Occupied threshold must be between 0 and 100");
62  }
63 }
64 
65 tuple<CollisionMsg, double> Collision::minDistance(const GridMap& grid,
66  const vec& pose) const
67 {
68  const auto psg = grid.world2Grid(pose(0), pose(1));
69 
70  CollisionConfig cfg(
71  std::floor(boundary_radius_ / grid.resolution()),
72  std::floor((boundary_radius_ + obstacle_threshold_) / grid.resolution()),
73  std::floor(search_radius_ / grid.resolution()), psg.at(1), psg.at(0));
74 
75  // std::cout << "r_bnd: " << cfg.r_bnd << std::endl;
76  // std::cout << "r_col: " << cfg.r_col << std::endl;
77  // std::cout << "r_max: " << cfg.r_max << std::endl;
78 
79  if (search(cfg, grid))
80  {
81  return std::make_tuple(CollisionMsg::crash, 0.0);
82  }
83 
84  else if (cfg.sqrd_obs != -1)
85  {
86  const double dmin = std::sqrt(static_cast<double>(cfg.sqrd_obs)) * grid.resolution() -
88 
89  return std::make_tuple(CollisionMsg::obstacle, dmin);
90  }
91 
92  return std::make_tuple(CollisionMsg::none, std::numeric_limits<double>::max());
93 }
94 
95 tuple<CollisionMsg, vec> Collision::minDirection(const GridMap& grid,
96  const vec& pose) const
97 {
98  const auto psg = grid.world2Grid(pose(0), pose(1));
99 
100  CollisionConfig cfg(
101  std::floor(boundary_radius_ / grid.resolution()),
102  std::floor((boundary_radius_ + obstacle_threshold_) / grid.resolution()),
103  std::floor(search_radius_ / grid.resolution()), psg.at(1), psg.at(0));
104 
105  search(cfg, grid);
106 
107  if (search(cfg, grid))
108  {
109  const vec disp(2, arma::fill::zeros);
110  return std::make_tuple(CollisionMsg::crash, disp);
111  }
112 
113  if (cfg.sqrd_obs != -1)
114  {
115  // displacement robot center to obstacle
116  const vec disp = { grid.resolution() * static_cast<double>(cfg.dx),
117  grid.resolution() * static_cast<double>(cfg.dy) };
118  return std::make_tuple(CollisionMsg::obstacle, disp);
119  }
120 
121  const vec disp = { std::numeric_limits<double>::max(),
122  std::numeric_limits<double>::max() };
123  return std::make_tuple(CollisionMsg::none, disp);
124 }
125 
126 bool Collision::collisionCheck(const GridMap& grid, const vec& pose) const
127 {
128  const auto psg = grid.world2Grid(pose(0), pose(1));
129 
130  CollisionConfig cfg(
131  std::floor(boundary_radius_ / grid.resolution()),
132  std::floor((boundary_radius_ + obstacle_threshold_) / grid.resolution()),
133  std::floor(search_radius_ / grid.resolution()), psg.at(1), psg.at(0));
134 
135  if (search(cfg, grid))
136  {
137  return true;
138  }
139 
140  return false;
141 }
142 
144 {
146 }
147 
148 bool Collision::search(CollisionConfig& cfg, const GridMap& grid) const
149 {
150  // initialize start and stop radius
151  const auto rmax = cfg.r_max;
152  auto r = cfg.r_bnd;
153 
154  while (r <= rmax)
155  {
156  if (bresenhamCircle(cfg, grid, r))
157  {
158  return true;
159  }
160  r++;
161  }
162 
163  return false;
164 }
165 
166 bool Collision::bresenhamCircle(CollisionConfig& cfg, const GridMap& grid, int r) const
167 {
168  int x = -r;
169  int y = 0;
170  int err = 2 - 2 * r;
171 
172  while (x < 0)
173  {
174  // Quadrant 1
175  if (checkCell(cfg, grid, cfg.cx - x, cfg.cy + y))
176  {
177  return true;
178  }
179 
180  // Quadrant 2
181  if (checkCell(cfg, grid, cfg.cx - y, cfg.cy - x))
182  {
183  return true;
184  }
185 
186  // Quadrant 3
187  if (checkCell(cfg, grid, cfg.cx + x, cfg.cy - y))
188  {
189  return true;
190  }
191 
192  // Quadrant 4
193  if (checkCell(cfg, grid, cfg.cx + y, cfg.cy + x))
194  {
195  return true;
196  }
197 
198  r = err;
199 
200  if (r <= y)
201  {
202  y++;
203  err += 2 * y + 1;
204  }
205 
206  if (r > x || err > y)
207  {
208  x++;
209  err += 2 * x + 1;
210  }
211  }
212 
213  return false;
214 }
215 
216 bool Collision::checkCell(CollisionConfig& cfg, const GridMap& grid, unsigned int cj,
217  unsigned int ci) const
218 {
219  // within the bounds of the grid
220  if (grid.gridBounds(ci, cj) && !(grid.getCell(ci, cj) < occupied_threshold_))
221  {
222  // squared distance circle center to obstacle
223  const auto sqrd_obs =
224  static_cast<int>((cfg.cx - cj) * (cfg.cx - cj) + (cfg.cy - ci) * (cfg.cy - ci));
225 
226  // update smallest squared distance to obstacle
227  if (sqrd_obs < cfg.sqrd_obs || cfg.sqrd_obs == -1)
228  {
229  cfg.sqrd_obs = sqrd_obs;
230  cfg.dx = cj - cfg.cx;
231  cfg.dy = ci - cfg.cy;
232  }
233 
234  // squared distance is >= 0 the inequality holds
235  // check for collision
236  if (sqrd_obs <= cfg.r_col * cfg.r_col)
237  {
238  return true;
239  }
240  }
241 
242  return false;
243 }
244 } // namespace ergodic_exploration
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::Collision::occupied_threshold_
double occupied_threshold_
Definition: collision.hpp:163
ergodic_exploration::GridMap::resolution
double resolution() const
Return grid resolution.
Definition: grid.hpp:208
collision.hpp
Collision checking in 2D.
ergodic_exploration::Collision::totalPadding
double totalPadding() const
Return the distance from robot center to collision boundary.
Definition: collision.cpp:143
ergodic_exploration::CollisionConfig
Collision detection parameters.
Definition: collision.hpp:63
ergodic_exploration::Collision::minDirection
tuple< CollisionMsg, vec > minDirection(const GridMap &grid, const vec &pose) const
Compose displacement vector from closest obstacle to robot.
Definition: collision.cpp:95
ergodic_exploration::CollisionConfig::r_max
const int r_max
Definition: collision.hpp:78
ergodic_exploration::Collision::bresenhamCircle
bool bresenhamCircle(CollisionConfig &cfg, const GridMap &grid, int r) const
Bresenham's circle algorithm.
Definition: collision.cpp:166
ergodic_exploration::Collision::search_radius_
double search_radius_
Definition: collision.hpp:161
ergodic_exploration::CollisionConfig::dx
int dx
Definition: collision.hpp:80
ergodic_exploration::Collision::Collision
Collision(double boundary_radius, double search_radius, double obstacle_threshold, double occupied_threshold)
Constructor.
Definition: collision.cpp:46
ergodic_exploration::CollisionConfig::r_bnd
const int r_bnd
Definition: collision.hpp:78
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::Collision::boundary_radius_
double boundary_radius_
Definition: collision.hpp:160
ergodic_exploration
Definition: basis.hpp:43
ergodic_exploration::GridMap
Constructs an 2D grid.
Definition: grid.hpp:79
ergodic_exploration::CollisionMsg::obstacle
@ obstacle
ergodic_exploration::CollisionConfig::cx
const int cx
Definition: collision.hpp:79
ergodic_exploration::CollisionConfig::dy
int dy
Definition: collision.hpp:80
ergodic_exploration::CollisionConfig::cy
const int cy
Definition: collision.hpp:79
ergodic_exploration::CollisionMsg::none
@ none
ergodic_exploration::CollisionConfig::r_col
const int r_col
Definition: collision.hpp:78
ergodic_exploration::Collision::obstacle_threshold_
double obstacle_threshold_
Definition: collision.hpp:162
ergodic_exploration::Collision::checkCell
bool checkCell(CollisionConfig &cfg, const GridMap &grid, unsigned int cj, unsigned int ci) const
Check if cell is an obstacle.
Definition: collision.cpp:216
ergodic_exploration::Collision::collisionCheck
bool collisionCheck(const GridMap &grid, const vec &pose) const
Check if the given state is a collision.
Definition: collision.cpp:126
ergodic_exploration::CollisionMsg::crash
@ crash
ergodic_exploration::Collision::minDistance
tuple< CollisionMsg, double > minDistance(const GridMap &grid, const vec &pose) const
Compose distance to closest obstacle.
Definition: collision.cpp:65
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::CollisionConfig::sqrd_obs
int sqrd_obs
Definition: collision.hpp:81
ergodic_exploration::Collision::search
bool search(CollisionConfig &cfg, const GridMap &grid) const
Find occupied cells between collision boundary and max search radius.
Definition: collision.cpp:148


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