Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
geometry_utils.hpp
1 // Copyright (c) 2019 Intel Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef NAV2_UTIL__GEOMETRY_UTILS_HPP_
16 #define NAV2_UTIL__GEOMETRY_UTILS_HPP_
17 
18 #include <cmath>
19 #include <vector>
20 
21 #include "geometry_msgs/msg/pose.hpp"
22 #include "geometry_msgs/msg/pose_stamped.hpp"
23 #include "geometry_msgs/msg/point.hpp"
24 #include "geometry_msgs/msg/quaternion.hpp"
25 #include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
26 #include "nav_msgs/msg/path.hpp"
27 #include "nav2_msgs/msg/waypoint_status.hpp"
28 
29 namespace nav2_util
30 {
31 namespace geometry_utils
32 {
33 
39 inline geometry_msgs::msg::Quaternion orientationAroundZAxis(double angle)
40 {
41  tf2::Quaternion q;
42  q.setRPY(0, 0, angle); // void returning function
43  return tf2::toMsg(q);
44 }
45 
53 inline double euclidean_distance(
54  const geometry_msgs::msg::Point & pos1,
55  const geometry_msgs::msg::Point & pos2,
56  const bool is_3d = false)
57 {
58  double dx = pos1.x - pos2.x;
59  double dy = pos1.y - pos2.y;
60 
61  if (is_3d) {
62  double dz = pos1.z - pos2.z;
63  return std::hypot(dx, dy, dz);
64  }
65 
66  return std::hypot(dx, dy);
67 }
68 
76 inline double euclidean_distance(
77  const geometry_msgs::msg::Pose & pos1,
78  const geometry_msgs::msg::Pose & pos2,
79  const bool is_3d = false)
80 {
81  double dx = pos1.position.x - pos2.position.x;
82  double dy = pos1.position.y - pos2.position.y;
83 
84  if (is_3d) {
85  double dz = pos1.position.z - pos2.position.z;
86  return std::hypot(dx, dy, dz);
87  }
88 
89  return std::hypot(dx, dy);
90 }
91 
99 inline double euclidean_distance(
100  const geometry_msgs::msg::PoseStamped & pos1,
101  const geometry_msgs::msg::PoseStamped & pos2,
102  const bool is_3d = false)
103 {
104  return euclidean_distance(pos1.pose, pos2.pose, is_3d);
105 }
106 
110 template<typename Iter, typename Getter>
111 inline Iter min_by(Iter begin, Iter end, Getter getCompareVal)
112 {
113  if (begin == end) {
114  return end;
115  }
116  auto lowest = getCompareVal(*begin);
117  Iter lowest_it = begin;
118  for (Iter it = ++begin; it != end; ++it) {
119  auto comp = getCompareVal(*it);
120  if (comp <= lowest) {
121  lowest = comp;
122  lowest_it = it;
123  }
124  }
125  return lowest_it;
126 }
127 
131 template<typename Iter, typename Getter>
132 inline Iter first_after_integrated_distance(Iter begin, Iter end, Getter getCompareVal)
133 {
134  if (begin == end) {
135  return end;
136  }
137  Getter dist = 0.0;
138  for (Iter it = begin; it != end - 1; it++) {
139  dist += euclidean_distance(*it, *(it + 1));
140  if (dist > getCompareVal) {
141  return it + 1;
142  }
143  }
144  return end;
145 }
146 
155 inline double calculate_path_length(const nav_msgs::msg::Path & path, size_t start_index = 0)
156 {
157  if (start_index + 1 >= path.poses.size()) {
158  return 0.0;
159  }
160  double path_length = 0.0;
161  for (size_t idx = start_index; idx < path.poses.size() - 1; ++idx) {
162  path_length += euclidean_distance(path.poses[idx].pose, path.poses[idx + 1].pose);
163  }
164  return path_length;
165 }
166 
174 inline int find_next_matching_goal_in_waypoint_statuses(
175  const std::vector<nav2_msgs::msg::WaypointStatus> & waypoint_statuses,
176  const geometry_msgs::msg::PoseStamped & goal)
177 {
178  auto itr = std::find_if(waypoint_statuses.begin(), waypoint_statuses.end(),
179  [&goal](const nav2_msgs::msg::WaypointStatus & status){
180  return status.waypoint_pose == goal &&
181  status.waypoint_status == nav2_msgs::msg::WaypointStatus::PENDING;
182  });
183 
184  if (itr == waypoint_statuses.end()) {
185  return -1;
186  }
187 
188  return itr - waypoint_statuses.begin();
189 }
190 
191 } // namespace geometry_utils
192 } // namespace nav2_util
193 
194 #endif // NAV2_UTIL__GEOMETRY_UTILS_HPP_