TrajectoryChecker2D.cpp
Go to the documentation of this file.
1/**
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "TrajectoryChecker2D.h"
18
19#include <cmath>
20
21
23
25{
27 costmap_(costmap),
28 clearance_(clearance)
29 {
30 }
31
32 float TrajectoryChecker2D::clearanceAt(float x, float y) const
33 {
34 const auto value = costmap_.value(Eigen::Vector2f{x, y});
35
36 // Unknown or masked reads as collision.
37 return value.has_value() ? value.value() : 0.F;
38 }
39
40 bool TrajectoryChecker2D::isInCollision(float x, float y) const
41 {
42 return clearanceAt(x, y) < static_cast<float>(clearance_);
43 }
44
45 std::vector<TrajectoryChecker2D::Violation>
47 {
48 std::vector<Violation> found;
49
50 const auto& points = trajectory.points();
51
52 for (std::size_t i = 0; i < points.size(); i++)
53 {
54 const auto& p = points[i].waypoint.pose.translation();
55
56 if (isInCollision(p.x(), p.y()))
57 {
58 found.push_back({.index = i,
59 .clearance = clearanceAt(p.x(), p.y()),
60 .onSegment = false});
61 }
62
63 if (i + 1 >= points.size())
64 {
65 break;
66 }
67
68 // Same sampling as check(), so the two cannot disagree about what passes.
69 constexpr float segmentResolution = 50.0F;
70
71 const auto& q = points[i + 1].waypoint.pose.translation();
72 const float dx = q.x() - p.x();
73 const float dy = q.y() - p.y();
74 int numSamples = static_cast<int>(std::ceil(std::hypot(dx, dy) / segmentResolution));
75 if (numSamples < 2)
76 {
77 numSamples = 2;
78 }
79
80 for (int s = 1; s < numSamples; s++)
81 {
82 const float t = static_cast<float>(s) / static_cast<float>(numSamples);
83 const float x = p.x() + t * dx;
84 const float y = p.y() + t * dy;
85
86 if (isInCollision(x, y))
87 {
88 found.push_back(
89 {.index = i, .clearance = clearanceAt(x, y), .onSegment = true});
90 break; // one report per segment is enough to locate the problem
91 }
92 }
93 }
94
95 return found;
96 }
97
99 {
100 bool collisionFree = true;
101
102 // Check waypoints.
103 for (std::size_t i = 0; i < trajectory.points().size(); ++i)
104 {
105 const auto& p = trajectory.points()[i].waypoint.pose.translation();
106 if (isInCollision(p.x(), p.y()))
107 {
108 collisionFree = false;
109 if (logDetails)
110 {
111 ARMARX_INFO << "[TrajectoryChecker2D] Collision at waypoint " << i << " : ("
112 << p.x() << ", " << p.y() << ")";
113 }
114 }
115 }
116
117 // Check segments.
118 constexpr float segmentResolution = 50.0f;
119 for (std::size_t i = 0; i + 1 < trajectory.points().size(); ++i)
120 {
121 const auto& p1 = trajectory.points()[i].waypoint.pose.translation();
122 const auto& p2 = trajectory.points()[i + 1].waypoint.pose.translation();
123
124 const float dx = p2.x() - p1.x();
125 const float dy = p2.y() - p1.y();
126 const float dist = std::hypot(dx, dy);
127 int numSamples = static_cast<int>(std::ceil(dist / segmentResolution));
128 if (numSamples < 2)
129 numSamples = 2;
130
131 for (int s = 1; s < numSamples; ++s)
132 {
133 const float t = static_cast<float>(s) / numSamples;
134 const float x = p1.x() + t * dx;
135 const float y = p1.y() + t * dy;
136 if (isInCollision(x, y))
137 {
138 collisionFree = false;
139 if (logDetails)
140 {
141 ARMARX_INFO << "[TrajectoryChecker2D] Collision on segment " << i << "-"
142 << (i + 1) << " at t=" << t;
143 }
144 }
145 }
146 }
147
148 return collisionFree;
149 }
150
151} // namespace armarx::navigation::algorithms::spfa::smoothing
std::optional< float > value(const Index &index) const
Definition Costmap.cpp:541
TrajectoryChecker2D(const algorithms::Costmap &costmap, double clearance)
std::vector< Violation > violations(const core::GlobalTrajectory &trajectory) const
Every place the trajectory falls below the clearance.
bool check(const core::GlobalTrajectory &trajectory, bool logDetails=false) const
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:179
#define q
This file offers overloads of toIce() and fromIce() functions for STL container types.