CircularPathSmoothing.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cmath>
5#include <cstddef>
6#include <cstdlib>
7#include <type_traits>
8
11
12namespace
13{
14 template <typename T>
15 constexpr T
16 deg2rad(T deg)
17 {
18 static_assert(std::is_floating_point<T>::value);
19 constexpr T c = M_PI / 180;
20 return deg * c;
21 }
22} // namespace
23
25{
26 namespace
27 {
28 // TODO move to Simox
29 float
30 getAngleBetweenVectors(const Eigen::Vector2f& v1, const Eigen::Vector2f& v2)
31 {
32 // Returns an angle between 0 and 180 degree (the minimum angle between the two vectors)
33 const Eigen::Vector2f v1_vec_normed = v1.normalized();
34 const Eigen::Vector2f v2_vec_normed = v2.normalized();
35 const float dot_product_vec =
36 v1_vec_normed(0) * v2_vec_normed(0) + v1_vec_normed(1) * v2_vec_normed(1);
37 float yaw = acos(dot_product_vec);
38 return yaw;
39 }
40 } // namespace
41
44 {
45 Points points;
46
47 points.push_back(p.front());
48
49 // omit start and end
50 for (size_t i = 1; i < (p.size() - 1); i++)
51 {
52 const Eigen::Vector2f& prev = p.at(i - 1);
53 const Eigen::Vector2f& at = p.at(i);
54 const Eigen::Vector2f& next = p.at(i + 1);
55
56 // the largest radius for smoothing
57 const float maxRadius = std::min((prev - at).norm(), (next - at).norm());
58 const float radius = std::min(maxRadius, 300.F);
59
60 const Eigen::Vector2f vIn = (prev - at).normalized();
61 const Eigen::Vector2f vOut = (next - at).normalized();
62
63 // the angle between the lines
64 const float phi = getAngleBetweenVectors(vIn, vOut);
65 const float l = radius / std::tan(phi / 2);
66
67 points.emplace_back(at + Eigen::Vector2f(prev - at).normalized() * l);
68 points.emplace_back(at + Eigen::Vector2f(next - at).normalized() * l);
69 }
70
71 points.push_back(p.back());
72
73 return points;
74 }
75
78 {
80 const auto& p = trajectory.points();
81
82 points.push_back(p.front());
83
84 // omit start and end
85 for (size_t i = 1; i < (p.size() - 1); i++)
86 {
87 const Eigen::Vector2f& prev =
88 navigation::conv::to2D(p.at(i - 1).waypoint.pose.translation());
89 const Eigen::Vector2f& at = navigation::conv::to2D(p.at(i).waypoint.pose.translation());
90 const Eigen::Vector2f& next =
91 navigation::conv::to2D(p.at(i + 1).waypoint.pose.translation());
92
93 // the largest radius for smoothing
94 const float maxRadius = std::min((prev - at).norm(), (next - at).norm());
95 const float radius = std::min(maxRadius, 300.F);
96
97 const Eigen::Vector2f vIn = (prev - at).normalized();
98 const Eigen::Vector2f vOut = (next - at).normalized();
99
100 // the angle between the lines
101 const float phi = getAngleBetweenVectors(vIn, vOut);
102
103 // decide whether it is necessary to smooth the path
104 if (std::abs(phi) < deg2rad(10.F))
105 {
106 points.push_back(p.at(i));
107 }
108 else
109 {
110 const float l = radius / std::tan(phi / 2);
111
112 const Eigen::Vector2f prePos = at + Eigen::Vector2f(prev - at).normalized() * l;
113 const Eigen::Vector2f postPos = at + Eigen::Vector2f(next - at).normalized() * l;
114
115 const auto tpProj = [&](const Eigen::Vector2f& pos) -> core::GlobalTrajectoryPoint
116 {
117 const auto proj =
118 trajectory.getProjection(navigation::conv::to3D(pos),
120
121 return proj.projection;
122 };
123
124 points.push_back(tpProj(prePos));
125 points.push_back(tpProj(postPos));
126 }
127 }
128
129 points.push_back(p.back());
130
131 return points;
132 }
133} // namespace armarx::navigation::algorithm
#define M_PI
Definition MathTools.h:17
constexpr T c
Points smooth(const Points &p)
circular path smoothing
This file is part of ArmarX.
std::vector< Eigen::Vector2f > to2D(const std::vector< Eigen::Vector3f > &v)
Definition eigen.cpp:29
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
Definition eigen.cpp:14
std::vector< GlobalTrajectoryPoint > GlobalTrajectoryPoints
Definition Trajectory.h:44
double norm(const Point &a)
Definition point.hpp:102