Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
utils.hpp
1 // Copyright (c) 2021, Samsung Research America
2 // Copyright (c) 2023, Open Navigation LLC
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License. Reserved.
15 
16 #ifndef NAV2_SMAC_PLANNER__UTILS_HPP_
17 #define NAV2_SMAC_PLANNER__UTILS_HPP_
18 
19 #include <vector>
20 #include <memory>
21 #include <string>
22 
23 #include "nlohmann/json.hpp"
24 #include "geometry_msgs/msg/quaternion.hpp"
25 #include "geometry_msgs/msg/pose.hpp"
26 #include "tf2/utils.hpp"
27 #include "nav2_costmap_2d/costmap_2d_ros.hpp"
28 #include "nav2_costmap_2d/inflation_layer_interface.hpp"
29 #include "visualization_msgs/msg/marker_array.hpp"
30 #include "nav2_smac_planner/types.hpp"
31 #include "rclcpp/duration.hpp"
32 #include "rclcpp/logger.hpp"
33 #include "rclcpp/logging.hpp"
34 #include "rclcpp/time.hpp"
35 
36 namespace nav2_smac_planner
37 {
38 
46 inline geometry_msgs::msg::Pose getWorldCoords(
47  const float & mx, const float & my, const nav2_costmap_2d::Costmap2D * costmap)
48 {
49  geometry_msgs::msg::Pose msg;
50  msg.position.x =
51  static_cast<float>(costmap->getOriginX()) + mx * costmap->getResolution();
52  msg.position.y =
53  static_cast<float>(costmap->getOriginY()) + my * costmap->getResolution();
54  return msg;
55 }
56 
62 inline geometry_msgs::msg::Quaternion getWorldOrientation(
63  const float & theta)
64 {
65  // theta is in radians already
66  tf2::Quaternion q;
67  q.setRPY(0.0, 0.0, theta);
68  return tf2::toMsg(q);
69 }
70 
78 inline double findCircumscribedCost(std::shared_ptr<nav2_costmap_2d::Costmap2DROS> costmap)
79 {
80  double result = -1.0;
81  std::vector<std::shared_ptr<nav2_costmap_2d::Layer>>::iterator layer;
82 
83  // check if the costmap has an inflation layer
84  const auto inflation_layer = nav2_costmap_2d::InflationLayerInterface::getInflationLayer(costmap);
85  if (inflation_layer != nullptr) {
86  double circum_radius = costmap->getLayeredCostmap()->getCircumscribedRadius();
87  double resolution = costmap->getCostmap()->getResolution();
88  double inflation_radius = inflation_layer->getInflationRadius();
89  if (inflation_radius < circum_radius) {
90  RCLCPP_ERROR(
91  rclcpp::get_logger("computeCircumscribedCost"),
92  "The inflation radius (%f) is smaller than the circumscribed radius (%f) "
93  "If this is an SE2-collision checking plugin, it cannot use costmap potential "
94  "field to speed up collision checking by only checking the full footprint "
95  "when robot is within possibly-inscribed radius of an obstacle. This may "
96  "significantly slow down planning times!",
97  inflation_radius, circum_radius);
98  result = 0.0;
99  return result;
100  }
101  result = static_cast<double>(inflation_layer->computeCost(circum_radius / resolution));
102  } else {
103  RCLCPP_WARN(
104  rclcpp::get_logger("computeCircumscribedCost"),
105  "No inflation layer found in costmap configuration. "
106  "If this is an SE2-collision checking plugin, it cannot use costmap potential "
107  "field to speed up collision checking by only checking the full footprint "
108  "when robot is within possibly-inscribed radius of an obstacle. This may "
109  "significantly slow down planning times!");
110  }
111 
112  return result;
113 }
114 
120 inline void fromJsonToMetaData(const nlohmann::json & json, LatticeMetadata & lattice_metadata)
121 {
122  json.at("turning_radius").get_to(lattice_metadata.min_turning_radius);
123  json.at("grid_resolution").get_to(lattice_metadata.grid_resolution);
124  json.at("num_of_headings").get_to(lattice_metadata.number_of_headings);
125  json.at("heading_angles").get_to(lattice_metadata.heading_angles);
126  json.at("number_of_trajectories").get_to(lattice_metadata.number_of_trajectories);
127  json.at("motion_model").get_to(lattice_metadata.motion_model);
128 }
129 
135 inline void fromJsonToPose(const nlohmann::json & json, MotionPose & pose)
136 {
137  pose._x = json[0];
138  pose._y = json[1];
139  pose._theta = json[2];
140 }
141 
147 inline void fromJsonToMotionPrimitive(
148  const nlohmann::json & json, MotionPrimitive & motion_primitive)
149 {
150  json.at("trajectory_id").get_to(motion_primitive.trajectory_id);
151  json.at("start_angle_index").get_to(motion_primitive.start_angle);
152  json.at("end_angle_index").get_to(motion_primitive.end_angle);
153  json.at("trajectory_radius").get_to(motion_primitive.turning_radius);
154  json.at("trajectory_length").get_to(motion_primitive.trajectory_length);
155  json.at("arc_length").get_to(motion_primitive.arc_length);
156  json.at("straight_length").get_to(motion_primitive.straight_length);
157  json.at("left_turn").get_to(motion_primitive.left_turn);
158 
159  for (unsigned int i = 0; i < json["poses"].size(); i++) {
160  MotionPose pose;
161  fromJsonToPose(json["poses"][i], pose);
162  motion_primitive.poses.push_back(pose);
163  }
164 }
165 
171 inline std::vector<geometry_msgs::msg::Point> transformFootprintToEdges(
172  const geometry_msgs::msg::Pose & pose,
173  const std::vector<geometry_msgs::msg::Point> & footprint)
174 {
175  const double & x = pose.position.x;
176  const double & y = pose.position.y;
177  const double & yaw = tf2::getYaw(pose.orientation);
178  const double sin_yaw = sin(yaw);
179  const double cos_yaw = cos(yaw);
180 
181  std::vector<geometry_msgs::msg::Point> out_footprint;
182  out_footprint.resize(2 * footprint.size());
183  for (unsigned int i = 0; i < footprint.size(); i++) {
184  out_footprint[2 * i].x = x + cos_yaw * footprint[i].x - sin_yaw * footprint[i].y;
185  out_footprint[2 * i].y = y + sin_yaw * footprint[i].x + cos_yaw * footprint[i].y;
186  if (i == 0) {
187  out_footprint.back().x = out_footprint[i].x;
188  out_footprint.back().y = out_footprint[i].y;
189  } else {
190  out_footprint[2 * i - 1].x = out_footprint[2 * i].x;
191  out_footprint[2 * i - 1].y = out_footprint[2 * i].y;
192  }
193  }
194  return out_footprint;
195 }
196 
205 inline visualization_msgs::msg::Marker createMarker(
206  const std::vector<geometry_msgs::msg::Point> edge,
207  unsigned int i, const std::string & frame_id, const rclcpp::Time & timestamp)
208 {
209  visualization_msgs::msg::Marker marker;
210  marker.header.frame_id = frame_id;
211  marker.header.stamp = timestamp;
212  marker.frame_locked = false;
213  marker.ns = "planned_footprint";
214  marker.action = visualization_msgs::msg::Marker::ADD;
215  marker.type = visualization_msgs::msg::Marker::LINE_LIST;
216  marker.lifetime = rclcpp::Duration(0, 0);
217 
218  marker.id = i;
219  for (auto & point : edge) {
220  marker.points.push_back(point);
221  }
222 
223  marker.pose.orientation.x = 0.0;
224  marker.pose.orientation.y = 0.0;
225  marker.pose.orientation.z = 0.0;
226  marker.pose.orientation.w = 1.0;
227  marker.scale.x = 0.05;
228  marker.scale.y = 0.05;
229  marker.scale.z = 0.05;
230  marker.color.r = 0.0f;
231  marker.color.g = 0.0f;
232  marker.color.b = 1.0f;
233  marker.color.a = 1.3f;
234  return marker;
235 }
236 
237 
238 } // namespace nav2_smac_planner
239 
240 #endif // NAV2_SMAC_PLANNER__UTILS_HPP_
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:69
double getResolution() const
Accessor for the resolution of the costmap.
Definition: costmap_2d.cpp:578
double getOriginY() const
Accessor for the y origin of the costmap.
Definition: costmap_2d.cpp:573
double getOriginX() const
Accessor for the x origin of the costmap.
Definition: costmap_2d.cpp:568
static std::shared_ptr< InflationLayerInterface > getInflationLayer(std::shared_ptr< nav2_costmap_2d::Costmap2DROS > &costmap_ros, const std::string layer_name="")
Get the inflation layer from a costmap, checking for both InflationLayer and LegacyInflationLayer imp...