-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathgeometry_utils.hpp
185 lines (166 loc) · 5.02 KB
/
geometry_utils.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright (c) 2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef NAV2_UTIL__GEOMETRY_UTILS_HPP_
#define NAV2_UTIL__GEOMETRY_UTILS_HPP_
#include <cmath>
#include "geometry_msgs/msg/pose.hpp"
#include "geometry_msgs/msg/pose_stamped.hpp"
#include "geometry_msgs/msg/pose2_d.hpp"
#include "geometry_msgs/msg/point.hpp"
#include "geometry_msgs/msg/quaternion.hpp"
#include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
#include "nav_msgs/msg/path.hpp"
namespace nav2_util
{
namespace geometry_utils
{
/**
* @brief Get a geometry_msgs Quaternion from a yaw angle
* @param angle Yaw angle to generate a quaternion from
* @return geometry_msgs Quaternion
*/
inline geometry_msgs::msg::Quaternion orientationAroundZAxis(double angle)
{
tf2::Quaternion q;
q.setRPY(0, 0, angle); // void returning function
return tf2::toMsg(q);
}
/**
* @brief Get the euclidean distance between 2 geometry_msgs::Points
* @param pos1 First point
* @param pos1 Second point
* @param is_3d True if a true L2 distance is desired (default false)
* @return double L2 distance
*/
inline double euclidean_distance(
const geometry_msgs::msg::Point & pos1,
const geometry_msgs::msg::Point & pos2,
const bool is_3d = false)
{
double dx = pos1.x - pos2.x;
double dy = pos1.y - pos2.y;
if (is_3d) {
double dz = pos1.z - pos2.z;
return std::hypot(dx, dy, dz);
}
return std::hypot(dx, dy);
}
/**
* @brief Get the L2 distance between 2 geometry_msgs::Poses
* @param pos1 First pose
* @param pos1 Second pose
* @param is_3d True if a true L2 distance is desired (default false)
* @return double euclidean distance
*/
inline double euclidean_distance(
const geometry_msgs::msg::Pose & pos1,
const geometry_msgs::msg::Pose & pos2,
const bool is_3d = false)
{
double dx = pos1.position.x - pos2.position.x;
double dy = pos1.position.y - pos2.position.y;
if (is_3d) {
double dz = pos1.position.z - pos2.position.z;
return std::hypot(dx, dy, dz);
}
return std::hypot(dx, dy);
}
/**
* @brief Get the L2 distance between 2 geometry_msgs::PoseStamped
* @param pos1 First pose
* @param pos1 Second pose
* @param is_3d True if a true L2 distance is desired (default false)
* @return double L2 distance
*/
inline double euclidean_distance(
const geometry_msgs::msg::PoseStamped & pos1,
const geometry_msgs::msg::PoseStamped & pos2,
const bool is_3d = false)
{
return euclidean_distance(pos1.pose, pos2.pose, is_3d);
}
/**
* @brief Get the L2 distance between 2 geometry_msgs::Pose2D
* @param pos1 First pose
* @param pos1 Second pose
* @return double L2 distance
*/
inline double euclidean_distance(
const geometry_msgs::msg::Pose2D & pos1,
const geometry_msgs::msg::Pose2D & pos2)
{
double dx = pos1.x - pos2.x;
double dy = pos1.y - pos2.y;
return std::hypot(dx, dy);
}
/**
* Find element in iterator with the minimum calculated value
*/
template<typename Iter, typename Getter>
inline Iter min_by(Iter begin, Iter end, Getter getCompareVal)
{
if (begin == end) {
return end;
}
auto lowest = getCompareVal(*begin);
Iter lowest_it = begin;
for (Iter it = ++begin; it != end; ++it) {
auto comp = getCompareVal(*it);
if (comp <= lowest) {
lowest = comp;
lowest_it = it;
}
}
return lowest_it;
}
/**
* Find first element in iterator that is greater integrated distance than comparevalue
*/
template<typename Iter, typename Getter>
inline Iter first_after_integrated_distance(Iter begin, Iter end, Getter getCompareVal)
{
if (begin == end) {
return end;
}
Getter dist = 0.0;
for (Iter it = begin; it != end - 1; it++) {
dist += euclidean_distance(*it, *(it + 1));
if (dist > getCompareVal) {
return it + 1;
}
}
return end;
}
/**
* @brief Calculate the length of the provided path, starting at the provided index
* @param path Path containing the poses that are planned
* @param start_index Optional argument specifying the starting index for
* the calculation of path length. Provide this if you want to calculate length of a
* subset of the path.
* @return double Path length
*/
inline double calculate_path_length(const nav_msgs::msg::Path & path, size_t start_index = 0)
{
if (start_index + 1 >= path.poses.size()) {
return 0.0;
}
double path_length = 0.0;
for (size_t idx = start_index; idx < path.poses.size() - 1; ++idx) {
path_length += euclidean_distance(path.poses[idx].pose, path.poses[idx + 1].pose);
}
return path_length;
}
} // namespace geometry_utils
} // namespace nav2_util
#endif // NAV2_UTIL__GEOMETRY_UTILS_HPP_