Skip to content

Commit fc50de9

Browse files
committed
Restore original style for swept collision checker
1 parent 935ffb9 commit fc50de9

File tree

11 files changed

+292
-5
lines changed

11 files changed

+292
-5
lines changed

nav2_smac_planner/include/nav2_smac_planner/collision_checker.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,24 @@ class GridCollisionChecker
9292
const unsigned int & i,
9393
const bool & traverse_unknown);
9494

95+
/**
96+
* @brief Check if in collision by sweeping between two poses
97+
* @param x0 X coordinate of starting pose
98+
* @param y0 Y coordinate of starting pose
99+
* @param theta0 Angle bin number of starting pose (NOT radians)
100+
* @param x1 X coordinate of ending pose
101+
* @param y1 Y coordinate of ending pose
102+
* @param theta1 Angle bin number of ending pose (NOT radians)
103+
* @param traverse_unknown Whether or not to traverse in unknown space
104+
* @param min_turning_radius Minimum turning radius in grid coordinates
105+
* @return boolean if in collision or not
106+
*/
107+
bool inCollision(
108+
const float & x0, const float & y0, const float & theta0,
109+
const float & x1, const float & y1, const float & theta1,
110+
const bool & traverse_unknown,
111+
const float & min_turning_radius);
112+
95113
/**
96114
* @brief Get cost at footprint pose in costmap
97115
* @return the cost at the pose in costmap

nav2_smac_planner/include/nav2_smac_planner/node_hybrid.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ class NodeHybrid
484484
// Dubin / Reeds-Shepp lookup and size for dereferencing
485485
NAV2_SMAC_PLANNER_COMMON_EXPORT static LookupTable dist_heuristic_lookup_table;
486486
NAV2_SMAC_PLANNER_COMMON_EXPORT static float size_lookup;
487+
NAV2_SMAC_PLANNER_COMMON_EXPORT static bool use_swept_collision_checker;
487488

488489
private:
489490
float _cell_cost;

nav2_smac_planner/include/nav2_smac_planner/node_lattice.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ class NodeLattice
420420
// Dubin / Reeds-Shepp lookup and size for dereferencing
421421
NAV2_SMAC_PLANNER_COMMON_EXPORT static LookupTable dist_heuristic_lookup_table;
422422
NAV2_SMAC_PLANNER_COMMON_EXPORT static float size_lookup;
423+
NAV2_SMAC_PLANNER_COMMON_EXPORT static bool use_swept_collision_checker;
423424

424425
private:
425426
float _cell_cost;

nav2_smac_planner/include/nav2_smac_planner/smac_planner_hybrid.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class SmacPlannerHybrid : public nav2_core::GlobalPlanner
120120
double _max_planning_time;
121121
double _lookup_table_size;
122122
double _minimum_turning_radius_global_coords;
123+
bool _use_swept_collision_checker;
123124
bool _debug_visualizations;
124125
std::string _motion_model_for_search;
125126
MotionModel _motion_model;

nav2_smac_planner/include/nav2_smac_planner/smac_planner_lattice.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class SmacPlannerLattice : public nav2_core::GlobalPlanner
115115
nav2::Publisher<nav_msgs::msg::Path>::SharedPtr _raw_plan_publisher;
116116
double _max_planning_time;
117117
double _lookup_table_size;
118+
bool _use_swept_collision_checker;
118119
bool _debug_visualizations;
119120
nav2::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr
120121
_planned_footprints_publisher;

nav2_smac_planner/src/collision_checker.cpp

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License. Reserved.
1414

15+
#include <algorithm>
16+
#include <cmath>
17+
#include <unordered_set>
18+
19+
#include "nav2_util/line_iterator.hpp"
1520
#include "nav2_smac_planner/collision_checker.hpp"
1621

22+
1723
namespace nav2_smac_planner
1824
{
1925

@@ -182,6 +188,166 @@ bool GridCollisionChecker::inCollision(
182188
return center_cost_ >= INSCRIBED_COST;
183189
}
184190

191+
bool GridCollisionChecker::inCollision(
192+
const float & x0, const float & y0, const float & theta0,
193+
const float & x1, const float & y1, const float & theta1,
194+
const bool & traverse_unknown,
195+
const float & min_turning_radius)
196+
{
197+
// Convert angle bins to radians
198+
float start_theta = angles_[static_cast<unsigned int>(theta0)];
199+
float end_theta = angles_[static_cast<unsigned int>(theta1)];
200+
float dtheta = end_theta - start_theta;
201+
if (dtheta > M_PI) {
202+
dtheta -= 2.0f * static_cast<float>(M_PI);
203+
} else if (dtheta < -M_PI) {
204+
dtheta += 2.0f * static_cast<float>(M_PI);
205+
}
206+
207+
// Quick checks to see if sweeping is necessary. If both poses are well
208+
// clear of obstacles, fall back to the single pose check on the child node
209+
const unsigned int size_x = costmap_->getSizeInCellsX();
210+
const unsigned int size_y = costmap_->getSizeInCellsY();
211+
212+
if (outsideRange(size_x, x0) || outsideRange(size_y, y0) ||
213+
outsideRange(size_x, x1) || outsideRange(size_y, y1))
214+
{
215+
return true;
216+
}
217+
218+
unsigned int mx0 = static_cast<unsigned int>(x0 + 0.5f);
219+
unsigned int my0 = static_cast<unsigned int>(y0 + 0.5f);
220+
unsigned int mx1 = static_cast<unsigned int>(x1 + 0.5f);
221+
unsigned int my1 = static_cast<unsigned int>(y1 + 0.5f);
222+
float start_cost = static_cast<float>(costmap_->getCost(mx0, my0));
223+
float end_cost = static_cast<float>(costmap_->getCost(mx1, my1));
224+
225+
bool parent_safe = possible_collision_cost_ > 0.0f &&
226+
start_cost < possible_collision_cost_;
227+
bool child_safe = possible_collision_cost_ > 0.0f &&
228+
end_cost < possible_collision_cost_;
229+
230+
if (parent_safe && child_safe) {
231+
return inCollision(x1, y1, theta1, traverse_unknown);
232+
}
233+
234+
float dx = x1 - x0;
235+
float dy = y1 - y0;
236+
float distance = hypotf(dx, dy);
237+
float arc = fabsf(dtheta) * min_turning_radius;
238+
int steps = static_cast<int>(ceilf(std::max(std::max(distance, arc), 1.0f)));
239+
240+
std::unordered_set<unsigned int> cells;
241+
float cx = 0.0f, cy = 0.0f;
242+
const bool use_arc = fabsf(dtheta) > 1e-3f;
243+
if (use_arc) {
244+
if (dtheta > 0.0f) {
245+
cx = x0 - min_turning_radius * sin(start_theta);
246+
cy = y0 + min_turning_radius * cos(start_theta);
247+
} else {
248+
cx = x0 + min_turning_radius * sin(start_theta);
249+
cy = y0 - min_turning_radius * cos(start_theta);
250+
}
251+
}
252+
253+
for (int step = 0; step <= steps; ++step) {
254+
float t = static_cast<float>(step) / static_cast<float>(steps);
255+
float xi, yi, theta;
256+
if (use_arc) {
257+
theta = start_theta + t * dtheta;
258+
if (dtheta > 0.0f) {
259+
xi = cx + min_turning_radius * sin(theta);
260+
yi = cy - min_turning_radius * cos(theta);
261+
} else {
262+
xi = cx - min_turning_radius * sin(theta);
263+
yi = cy + min_turning_radius * cos(theta);
264+
}
265+
} else {
266+
xi = x0 + t * dx;
267+
yi = y0 + t * dy;
268+
theta = start_theta;
269+
}
270+
271+
while (theta < 0.0f) {
272+
theta += 2.0f * static_cast<float>(M_PI);
273+
}
274+
while (theta >= 2.0f * static_cast<float>(M_PI)) {
275+
theta -= 2.0f * static_cast<float>(M_PI);
276+
}
277+
unsigned int angle_bin = static_cast<unsigned int>(
278+
theta / (2.0f * static_cast<float>(M_PI)) * angles_.size());
279+
angle_bin %= angles_.size();
280+
281+
if (footprint_is_radius_) {
282+
if (outsideRange(costmap_->getSizeInCellsX(), xi) ||
283+
outsideRange(costmap_->getSizeInCellsY(), yi))
284+
{
285+
return true;
286+
}
287+
unsigned int mx = static_cast<unsigned int>(xi + 0.5f);
288+
unsigned int my = static_cast<unsigned int>(yi + 0.5f);
289+
cells.insert(my * size_x + mx);
290+
continue;
291+
}
292+
293+
// Always include center cell
294+
if (outsideRange(costmap_->getSizeInCellsX(), xi) ||
295+
outsideRange(costmap_->getSizeInCellsY(), yi))
296+
{
297+
return true;
298+
}
299+
unsigned int mx = static_cast<unsigned int>(xi + 0.5f);
300+
unsigned int my = static_cast<unsigned int>(yi + 0.5f);
301+
cells.insert(my * size_x + mx);
302+
303+
double wx, wy;
304+
costmap_->mapToWorld(static_cast<double>(xi), static_cast<double>(yi), wx, wy);
305+
const nav2_costmap_2d::Footprint & oriented = oriented_footprints_[angle_bin];
306+
307+
unsigned int x_prev, y_prev, x_curr, y_curr;
308+
if (!worldToMap(wx + oriented[0].x, wy + oriented[0].y, x_prev, y_prev)) {
309+
return true;
310+
}
311+
for (unsigned int i = 1; i < oriented.size(); ++i) {
312+
if (!worldToMap(wx + oriented[i].x, wy + oriented[i].y, x_curr, y_curr)) {
313+
return true;
314+
}
315+
for (nav2_util::LineIterator line(x_prev, y_prev, x_curr, y_curr);
316+
line.isValid(); line.advance())
317+
{
318+
cells.insert(line.getY() * size_x + line.getX());
319+
}
320+
x_prev = x_curr;
321+
y_prev = y_curr;
322+
}
323+
if (!worldToMap(wx + oriented[0].x, wy + oriented[0].y, x_curr, y_curr)) {
324+
return true;
325+
}
326+
for (nav2_util::LineIterator line(x_prev, y_prev, x_curr, y_curr);
327+
line.isValid(); line.advance())
328+
{
329+
cells.insert(line.getY() * size_x + line.getX());
330+
}
331+
}
332+
333+
float max_cost = 0.0f;
334+
for (auto index : cells) {
335+
center_cost_ = static_cast<float>(costmap_->getCost(index));
336+
if (center_cost_ == UNKNOWN_COST && traverse_unknown) {
337+
continue;
338+
}
339+
if (center_cost_ >= INSCRIBED_COST) {
340+
return true;
341+
}
342+
if (center_cost_ > max_cost) {
343+
max_cost = center_cost_;
344+
}
345+
}
346+
347+
center_cost_ = max_cost;
348+
return false;
349+
}
350+
185351
float GridCollisionChecker::getCost()
186352
{
187353
// Assumes inCollision called prior

nav2_smac_planner/src/node_hybrid.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ LookupTable NodeHybrid::dist_heuristic_lookup_table;
4343
std::shared_ptr<nav2_costmap_2d::Costmap2DROS> NodeHybrid::costmap_ros = nullptr;
4444

4545
ObstacleHeuristicQueue NodeHybrid::obstacle_heuristic_queue;
46+
bool NodeHybrid::use_swept_collision_checker = false;
4647

4748
// Each of these tables are the projected motion models through
4849
// time and space applied to the search on the current node in
@@ -382,8 +383,15 @@ bool NodeHybrid::isNodeValid(
382383
return _is_node_valid;
383384
}
384385

385-
_is_node_valid = !collision_checker->inCollision(
386-
this->pose.x, this->pose.y, this->pose.theta /*bin number*/, traverse_unknown);
386+
if (use_swept_collision_checker && parent) {
387+
_is_node_valid = !collision_checker->inCollision(
388+
parent->pose.x, parent->pose.y, parent->pose.theta,
389+
this->pose.x, this->pose.y, this->pose.theta,
390+
traverse_unknown, motion_table.min_turning_radius);
391+
} else {
392+
_is_node_valid = !collision_checker->inCollision(
393+
this->pose.x, this->pose.y, this->pose.theta /*bin number*/, traverse_unknown);
394+
}
387395
_cell_cost = collision_checker->getCost();
388396
return _is_node_valid;
389397
}

nav2_smac_planner/src/node_lattice.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace nav2_smac_planner
3939
LatticeMotionTable NodeLattice::motion_table;
4040
float NodeLattice::size_lookup = 25;
4141
LookupTable NodeLattice::dist_heuristic_lookup_table;
42+
bool NodeLattice::use_swept_collision_checker = false;
4243

4344
// Each of these tables are the projected motion models through
4445
// time and space applied to the search on the current node in
@@ -229,6 +230,15 @@ bool NodeLattice::isNodeValid(
229230
return _is_node_valid;
230231
}
231232

233+
if (use_swept_collision_checker && parent) {
234+
_is_node_valid = !collision_checker->inCollision(
235+
parent->pose.x, parent->pose.y, parent->pose.theta,
236+
this->pose.x, this->pose.y, this->pose.theta,
237+
traverse_unknown, motion_table.min_turning_radius);
238+
_cell_cost = collision_checker->getCost();
239+
return _is_node_valid;
240+
}
241+
232242
// Check primitive end pose
233243
// Convert grid quantization of primitives to radians, then collision checker quantization
234244
static const double bin_size = 2.0 * M_PI / collision_checker->getPrecomputedAngles().size();

nav2_smac_planner/src/smac_planner_hybrid.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ SmacPlannerHybrid::SmacPlannerHybrid()
3636
_smoother(nullptr),
3737
_costmap(nullptr),
3838
_costmap_ros(nullptr),
39-
_costmap_downsampler(nullptr)
39+
_costmap_downsampler(nullptr),
40+
_use_swept_collision_checker(false)
4041
{
4142
}
4243

@@ -103,6 +104,10 @@ void SmacPlannerHybrid::configure(
103104
nav2::declare_parameter_if_not_declared(
104105
node, name + ".minimum_turning_radius", rclcpp::ParameterValue(0.4));
105106
node->get_parameter(name + ".minimum_turning_radius", _minimum_turning_radius_global_coords);
107+
nav2::declare_parameter_if_not_declared(
108+
node, name + ".use_swept_collision_check", rclcpp::ParameterValue(false));
109+
node->get_parameter(name + ".use_swept_collision_check", _use_swept_collision_checker);
110+
NodeHybrid::use_swept_collision_checker = _use_swept_collision_checker;
106111
nav2::declare_parameter_if_not_declared(
107112
node, name + ".allow_primitive_interpolation", rclcpp::ParameterValue(false));
108113
node->get_parameter(
@@ -703,6 +708,9 @@ SmacPlannerHybrid::dynamicParametersCallback(std::vector<rclcpp::Parameter> para
703708
} else if (param_name == _name + ".analytic_expansion_max_cost_override") {
704709
_search_info.analytic_expansion_max_cost_override = parameter.as_bool();
705710
reinit_a_star = true;
711+
} else if (param_name == _name + ".use_swept_collision_check") {
712+
_use_swept_collision_checker = parameter.as_bool();
713+
NodeHybrid::use_swept_collision_checker = _use_swept_collision_checker;
706714
}
707715
} else if (param_type == ParameterType::PARAMETER_INTEGER) {
708716
if (param_name == _name + ".downsampling_factor") {

nav2_smac_planner/src/smac_planner_lattice.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#include <vector>
1818
#include <algorithm>
1919
#include <limits>
20-
2120
#include "nav2_smac_planner/smac_planner_lattice.hpp"
21+
#include "nav2_smac_planner/node_lattice.hpp"
2222

2323
// #define BENCHMARK_TESTING
2424

@@ -32,7 +32,8 @@ SmacPlannerLattice::SmacPlannerLattice()
3232
: _a_star(nullptr),
3333
_collision_checker(nullptr, 1, nullptr),
3434
_smoother(nullptr),
35-
_costmap(nullptr)
35+
_costmap(nullptr),
36+
_use_swept_collision_checker(false)
3637
{
3738
}
3839

@@ -82,6 +83,12 @@ void SmacPlannerLattice::configure(
8283
node, name + ".smooth_path", rclcpp::ParameterValue(true));
8384
node->get_parameter(name + ".smooth_path", smooth_path);
8485

86+
nav2::declare_parameter_if_not_declared(
87+
node, name + ".use_swept_collision_check", rclcpp::ParameterValue(false));
88+
node->get_parameter(
89+
name + ".use_swept_collision_check", _use_swept_collision_checker);
90+
NodeLattice::use_swept_collision_checker = _use_swept_collision_checker;
91+
8592
// Default to a well rounded model: 16 bin, 0.4m turning radius, ackermann model
8693
nav2::declare_parameter_if_not_declared(
8794
node, name + ".lattice_filepath", rclcpp::ParameterValue(
@@ -591,6 +598,9 @@ SmacPlannerLattice::dynamicParametersCallback(std::vector<rclcpp::Parameter> par
591598
} else if (param_name == _name + ".cache_obstacle_heuristic") {
592599
reinit_a_star = true;
593600
_search_info.cache_obstacle_heuristic = parameter.as_bool();
601+
} else if (param_name == _name + ".use_swept_collision_check") {
602+
_use_swept_collision_checker = parameter.as_bool();
603+
NodeLattice::use_swept_collision_checker = _use_swept_collision_checker;
594604
} else if (param_name == _name + ".allow_reverse_expansion") {
595605
reinit_a_star = true;
596606
_search_info.allow_reverse_expansion = parameter.as_bool();

0 commit comments

Comments
 (0)