Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
map_grid.cpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2017, Locus Robotics
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
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "dwb_critics/map_grid.hpp"
36 #include <cmath>
37 #include <string>
38 #include <vector>
39 #include <utility>
40 #include <algorithm>
41 #include <memory>
42 #include "dwb_core/exceptions.hpp"
43 #include "nav2_costmap_2d/cost_values.hpp"
44 
45 using std::abs;
47 
48 namespace dwb_critics
49 {
50 
51 // Customization of the CostmapQueue validCellToQueue method
53 {
54  return true;
55 }
56 
57 void MapGridCritic::onInit()
58 {
59  costmap_ = costmap_ros_->getCostmap();
60  queue_ = std::make_shared<MapGridQueue>(*costmap_, *this);
61 
62  // Always set to true, but can be overridden by subclasses
63  stop_on_failure_ = true;
64 
65  auto node = node_.lock();
66  if (!node) {
67  throw std::runtime_error{"Failed to lock node"};
68  }
69 
70  std::string aggro_str = node->declare_or_get_parameter(
71  dwb_plugin_name_ + "." + name_ + ".aggregation_type",
72  std::string("last"));
73  std::transform(aggro_str.begin(), aggro_str.end(), aggro_str.begin(), ::tolower);
74  if (aggro_str == "last") {
75  aggregationType_ = ScoreAggregationType::Last;
76  } else if (aggro_str == "sum") {
77  aggregationType_ = ScoreAggregationType::Sum;
78  } else if (aggro_str == "product") {
79  aggregationType_ = ScoreAggregationType::Product;
80  } else {
81  RCLCPP_ERROR(
82  rclcpp::get_logger(
83  "MapGridCritic"), "aggregation_type parameter \"%s\" invalid. Using Last.",
84  aggro_str.c_str());
85  aggregationType_ = ScoreAggregationType::Last;
86  }
87 }
88 
89 void MapGridCritic::setAsObstacle(unsigned int index)
90 {
91  cell_values_[index] = obstacle_score_;
92 }
93 
95 {
96  queue_->reset();
97  cell_values_.resize(costmap_->getSizeInCellsX() * costmap_->getSizeInCellsY());
98  obstacle_score_ = static_cast<double>(cell_values_.size());
99  unreachable_score_ = obstacle_score_ + 1.0;
100  std::fill(cell_values_.begin(), cell_values_.end(), unreachable_score_);
101 }
102 
104 {
105  while (!queue_->isEmpty()) {
106  costmap_queue::CellData cell = queue_->getNextCell();
107  cell_values_[cell.index_] = CellData::absolute_difference(cell.src_x_, cell.x_) +
108  CellData::absolute_difference(cell.src_y_, cell.y_);
109  }
110 }
111 
112 double MapGridCritic::scoreTrajectory(const dwb_msgs::msg::Trajectory2D & traj)
113 {
114  double score = 0.0;
115  unsigned int start_index = 0;
116  if (aggregationType_ == ScoreAggregationType::Product) {
117  score = 1.0;
118  } else if (aggregationType_ == ScoreAggregationType::Last && !stop_on_failure_) {
119  start_index = traj.poses.size() - 1;
120  }
121  double grid_dist;
122 
123  for (unsigned int i = start_index; i < traj.poses.size(); ++i) {
124  grid_dist = scorePose(traj.poses[i]);
125  if (stop_on_failure_) {
126  if (grid_dist == obstacle_score_) {
127  throw dwb_core::
128  IllegalTrajectoryException(name_, "Trajectory Hits Obstacle.");
129  } else if (grid_dist == unreachable_score_) {
130  throw dwb_core::
131  IllegalTrajectoryException(name_, "Trajectory Hits Unreachable Area.");
132  }
133  }
134 
135  switch (aggregationType_) {
136  case ScoreAggregationType::Last:
137  score = grid_dist;
138  break;
139  case ScoreAggregationType::Sum:
140  score += grid_dist;
141  break;
142  case ScoreAggregationType::Product:
143  if (score > 0) {
144  score *= grid_dist;
145  }
146  break;
147  }
148  }
149 
150  return score;
151 }
152 
153 double MapGridCritic::scorePose(const geometry_msgs::msg::Pose & pose)
154 {
155  unsigned int cell_x, cell_y;
156  // we won't allow trajectories that go off the map... shouldn't happen that often anyways
157  if (!costmap_->worldToMap(pose.position.x, pose.position.y, cell_x, cell_y)) {
158  throw dwb_core::
159  IllegalTrajectoryException(name_, "Trajectory Goes Off Grid.");
160  }
161  return getScore(cell_x, cell_y);
162 }
163 
165  std::vector<std::pair<std::string, std::vector<float>>> & cost_channels)
166 {
167  std::pair<std::string, std::vector<float>> grid_scores;
168  grid_scores.first = name_;
169 
170  nav2_costmap_2d::Costmap2D * costmap = costmap_ros_->getCostmap();
171  unsigned int size_x = costmap->getSizeInCellsX();
172  unsigned int size_y = costmap->getSizeInCellsY();
173  grid_scores.second.resize(size_x * size_y);
174  unsigned int i = 0;
175  for (unsigned int cy = 0; cy < size_y; cy++) {
176  for (unsigned int cx = 0; cx < size_x; cx++) {
177  grid_scores.second[i] = getScore(cx, cy);
178  i++;
179  }
180  }
181  cost_channels.push_back(grid_scores);
182 }
183 
184 } // namespace dwb_critics
Storage for cell information used during queue expansion.
bool validCellToQueue(const costmap_queue::CellData &cell) override
Check to see if we should add this cell to the queue. Always true unless overridden.
Definition: map_grid.cpp:52
double scoreTrajectory(const dwb_msgs::msg::Trajectory2D &traj) override
Return a raw score for the given trajectory.
Definition: map_grid.cpp:112
void addCriticVisualization(std::vector< std::pair< std::string, std::vector< float >>> &cost_channels) override
Add information to the given pointcloud for debugging costmap-grid based scores.
Definition: map_grid.cpp:164
void reset() override
Clear the queueDWB_CRITICS_MAP_GRID_He and set cell_values_ to the appropriate number of unreachableC...
Definition: map_grid.cpp:94
void setAsObstacle(unsigned int index)
Sets the score of a particular cell to the obstacle cost.
Definition: map_grid.cpp:89
double getScore(unsigned int x, unsigned int y)
Retrieve the score for a particular cell of the costmap.
Definition: map_grid.hpp:85
double unreachable_score_
Special cell_values.
Definition: map_grid.hpp:136
void propagateManhattanDistances()
Go through the queue and set the cells to the Manhattan distance from their parents.
Definition: map_grid.cpp:103
virtual double scorePose(const geometry_msgs::msg::Pose &pose)
Retrieve the score for a single pose.
Definition: map_grid.cpp:153
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:69
bool worldToMap(double wx, double wy, unsigned int &mx, unsigned int &my) const
Convert from world coordinates to map coordinates.
Definition: costmap_2d.cpp:292
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
Definition: costmap_2d.cpp:548
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
Definition: costmap_2d.cpp:553