Bench-MR
A Motion Planning Benchmark for Wheeled Mobile Robots
Primitives.h
Go to the documentation of this file.
1#pragma once
2
3#include <ompl/base/State.h>
4#include <ompl/base/spaces/SE2StateSpace.h>
5#include <ompl/control/PathControl.h>
6#include <ompl/geometric/PathGeometric.h>
7
8#include <nlohmann/json.hpp>
9
10namespace ob = ompl::base;
11
12typedef ob::SE2StateSpace::StateType State;
13
14namespace base {
15ob::State *StateFromXYT(double x, double y, double theta);
16ob::State *StateFromXY(double x, double y);
17} // namespace base
18
19struct Rectangle {
20 double x1{0}, y1{0};
21 double x2{0}, y2{0};
22
23 Rectangle() = default;
24 Rectangle(double x1, double y1, double x2, double y2)
25 : x1(x1), y1(y1), x2(x2), y2(y2) {}
26
27 inline double x() const { return std::min(x1, x2); }
28 inline double y() const { return std::min(y1, y2); }
29
30 inline double width() const { return std::abs(x1 - x2); }
31 inline double height() const { return std::abs(y1 - y2); }
32
36 void correct() {
37 if (x1 > x2) std::swap(x1, x2);
38 if (y1 > y2) std::swap(y1, y2);
39 }
40};
41
42struct Point {
43 double x{0}, y{0};
44
45 Point() = default;
46 Point(double x, double y) : x(x), y(y) {}
47 Point(const ob::State *state) {
48 if (state == nullptr) {
49 OMPL_WARN("Cannot create point from NULL state.");
50 return;
51 }
52
53 {
54 x = state->as<State>()->getX();
55 y = state->as<State>()->getY();
56 }
57 }
58
59 static std::vector<Point> fromPath(const ompl::geometric::PathGeometric &p,
60 bool interpolate = false);
61
62 static std::vector<Point> fromPath(const ompl::control::PathControl &p,
63 bool interpolate = false);
64
65 static Point centroid(const std::vector<Point> &points) {
66 double x = 0, y = 0;
67 for (auto &p : points) {
68 x += p.x;
69 y += p.y;
70 }
71 return {x / points.size(), y / points.size()};
72 }
73
74 double distance(const Point &p) const {
75 const double dx = p.x - x;
76 const double dy = p.y - y;
77 return std::sqrt(dx * dx + dy * dy);
78 }
79
80 double distance(double x, double y) const {
81 const double dx = this->x - x;
82 const double dy = this->y - y;
83 return std::sqrt(dx * dx + dy * dy);
84 }
85
86 double distanceSquared(const Point &p) const {
87 const double dx = p.x - x;
88 const double dy = p.y - y;
89 return dx * dx + dy * dy;
90 }
91
92 double distanceSquared(double x, double y) const {
93 const double dx = this->x - x;
94 const double dy = this->y - y;
95 return dx * dx + dy * dy;
96 }
97
98 operator Eigen::Matrix<double, 2, 1>() const { return {x, y}; }
99 Point &operator=(const Eigen::Matrix<double, 2, 1> &p) {
100 x = p(0);
101 y = p(1);
102 return *this;
103 }
104
105 Point &operator+=(const Point &p) {
106 x += p.x;
107 y += p.y;
108 return *this;
109 }
110 Point operator+(const Point &p) const { return {x + p.x, y + p.y}; }
111 Point &operator-=(const Point &p) {
112 x -= p.x;
113 y -= p.y;
114 return *this;
115 }
116 Point operator-(const Point &p) const { return {x - p.x, y - p.y}; }
117
118 Point &operator*=(double d) {
119 x *= d;
120 y *= d;
121 return *this;
122 }
123 Point operator*(double d) const { return {x * d, y * d}; }
124
125 Point &operator/=(double d) {
126 x /= d;
127 y /= d;
128 return *this;
129 }
130 Point operator/(double d) const { return {x / d, y / d}; }
131
132 ompl::base::State *toState(double theta = 0) const;
133
134 friend std::ostream &operator<<(std::ostream &stream, const Point &p) {
135 return stream << '[' << p.x << ' ' << p.y << ']';
136 }
137};
138
139inline void to_json(nlohmann::json &j, const Point &p) { j = {p.x, p.y}; }
140inline void from_json(const nlohmann::json &j, Point &p) {
141 p.x = j.at(0);
142 p.y = j.at(1);
143}
144
145struct Polygon {
146 std::vector<Point> points;
147
148 operator std::vector<Point> &() { return points; }
149 operator const std::vector<Point> &() const { return points; }
150
151 Polygon(const std::vector<Point> &points = {}) : points(points) {}
152
153 Point centroid() const {
154 Point c;
155 for (const auto &p : points) c += p;
156 c /= points.size();
157 return c;
158 }
159
163 void center() {
164 const auto c = centroid();
165 for (auto &p : points) p -= c;
166 }
167
168 void scale(double scaling) {
169 for (auto &p : points) p *= scaling;
170 }
171
172 Polygon scaled(double scaling) {
173 Polygon poly(*this);
174 for (auto &p : poly.points) p *= scaling;
175 return poly;
176 }
177
181 static Polygon loadFromSvgPathStr(std::string path_str) {
182 std::replace(path_str.begin(), path_str.end(), ',', ' ');
183 std::vector<std::string> tokens;
184 std::stringstream ss(path_str);
185 std::string word;
186 // split with space
187 while (ss >> word) tokens.emplace_back(word);
188 std::vector<Point> points;
189 Point point;
190 // flip the vertical coordinates to match Inkscape's rendering
191 for (size_t i = 0; i < tokens.size(); i++) {
192 const auto &token = tokens[i];
193 if (token == "m" || token == "l") {
194 for (size_t j = i + 1; j < tokens.size() - 1; j += 2) {
195 if (!is_number(tokens[j])) break;
196 point += {stod(tokens[j]), -stod(tokens[j + 1])};
197 points.emplace_back(point);
198 i += 2;
199 }
200 }
201 if (token == "M" || token == "L") {
202 for (size_t j = i + 1; j < tokens.size() - 1; j += 2) {
203 if (!is_number(tokens[j])) break;
204 point = Point(stod(tokens[j]), -stod(tokens[j + 1]));
205 points.emplace_back(point);
206 i += 2;
207 }
208 }
209 if (token == "h" || token == "v") {
210 for (size_t j = i + 1; j < tokens.size(); j++) {
211 if (!is_number(tokens[j])) break;
212 if (token == "h")
213 point.x += stod(tokens[j]);
214 else
215 point.y -= stod(tokens[j]);
216 points.emplace_back(point);
217 i++;
218 }
219 }
220 if (token == "H" || token == "V") {
221 for (size_t j = i + 1; j < tokens.size(); j++) {
222 if (!is_number(tokens[j])) break;
223 if (token == "H")
224 point.x = stod(tokens[j]);
225 else
226 point.y = -stod(tokens[j]);
227 points.emplace_back(point);
228 i++;
229 }
230 }
231 }
232 return points;
233 }
234
235 void translate(const Point &t) {
236 for (auto &p : points) p += t;
237 }
238
242 void rotate(double angle) {
243 double c = std::cos(angle), s = std::sin(angle);
244 for (auto &p : points) {
245 const Point temp(p);
246 p.x = temp.x * c - temp.y * s;
247 p.y = temp.x * s + temp.y * c;
248 }
249 }
250
252 Polygon p(*this);
253 // std::cout << state->as<State>()->getYaw() << " "
254 // << state->as<State>()->getX() << " " <<
255 // state->as<State>()->getY()
256 // << std::endl;
257 p.rotate(state->as<State>()->getYaw());
258 p.translate({state->as<State>()->getX(), state->as<State>()->getY()});
259 // std::cout << p << std::endl;
260 return p;
261 }
262
266 Point min() const {
267 Point m = points[0];
268 for (const auto &p : points) {
269 if (p.x < m.x) m.x = p.x;
270 if (p.y < m.y) m.y = p.y;
271 }
272 return m;
273 }
277 Point max() const {
278 Point m = points[0];
279 for (const auto &p : points) {
280 if (p.x > m.x) m.x = p.x;
281 if (p.y > m.y) m.y = p.y;
282 }
283 return m;
284 }
285
286 bool isConvex() const;
287
288 Polygon convexHull() const;
289
293 operator std::vector<Eigen::Matrix<double, 2, 1>>() const {
294 std::vector<Eigen::Matrix<double, 2, 1>> v;
295 for (const auto &p : points)
296 v.emplace_back(Eigen::Matrix<double, 2, 1>{p.x, p.y});
297 return v;
298 }
299
300 friend std::ostream &operator<<(std::ostream &stream, const Polygon &p) {
301 for (const auto &point : p.points) stream << point << ' ';
302 return stream;
303 }
304
305 private:
306 static bool is_number(const std::string &s) {
307 try {
308 std::stod(s);
309 } catch (...) {
310 return false;
311 }
312 return true;
313 }
314};
315
316inline void to_json(nlohmann::json &j, const Polygon &p) { j = p.points; }
317inline void from_json(const nlohmann::json &j, Polygon &p) {
318 p.points.clear();
319 for (const auto &element : j) p.points.emplace_back(element);
320}
bool replace(std::string &str, const std::string &from, const std::string &to)
Definition: Log.cpp:49
void from_json(const nlohmann::json &j, Point &p)
Definition: Primitives.h:140
ob::SE2StateSpace::StateType State
Definition: Primitives.h:12
void to_json(nlohmann::json &j, const Point &p)
Definition: Primitives.h:139
Definition: Primitives.h:14
ob::State * StateFromXY(double x, double y)
Definition: Primitives.cpp:14
ob::State * StateFromXYT(double x, double y, double theta)
Definition: Primitives.cpp:6
double min(const std::vector< double > &values)
Definition: PathStatistics.hpp:73
Definition: Primitives.h:42
Point operator/(double d) const
Definition: Primitives.h:130
Point & operator-=(const Point &p)
Definition: Primitives.h:111
Point(const ob::State *state)
Definition: Primitives.h:47
double distance(double x, double y) const
Definition: Primitives.h:80
Point()=default
Point operator+(const Point &p) const
Definition: Primitives.h:110
double distanceSquared(double x, double y) const
Definition: Primitives.h:92
static Point centroid(const std::vector< Point > &points)
Definition: Primitives.h:65
Point & operator/=(double d)
Definition: Primitives.h:125
Point(double x, double y)
Definition: Primitives.h:46
Point & operator=(const Eigen::Matrix< double, 2, 1 > &p)
Definition: Primitives.h:99
double distance(const Point &p) const
Definition: Primitives.h:74
Point operator*(double d) const
Definition: Primitives.h:123
static std::vector< Point > fromPath(const ompl::geometric::PathGeometric &p, bool interpolate=false)
Definition: Primitives.cpp:25
double x
Definition: Primitives.h:43
Point & operator*=(double d)
Definition: Primitives.h:118
double distanceSquared(const Point &p) const
Definition: Primitives.h:86
Point & operator+=(const Point &p)
Definition: Primitives.h:105
ompl::base::State * toState(double theta=0) const
Definition: Primitives.cpp:21
Point operator-(const Point &p) const
Definition: Primitives.h:116
double y
Definition: Primitives.h:43
friend std::ostream & operator<<(std::ostream &stream, const Point &p)
Definition: Primitives.h:134
Definition: Primitives.h:145
Polygon convexHull() const
Definition: Primitives.cpp:106
void center()
Translates points such that the centroid becomes (0, 0).
Definition: Primitives.h:163
friend std::ostream & operator<<(std::ostream &stream, const Polygon &p)
Definition: Primitives.h:300
Polygon scaled(double scaling)
Definition: Primitives.h:172
Polygon(const std::vector< Point > &points={})
Definition: Primitives.h:151
Polygon transformed(const ompl::base::State *state) const
Definition: Primitives.h:251
Point centroid() const
Definition: Primitives.h:153
std::vector< Point > points
Definition: Primitives.h:146
void translate(const Point &t)
Definition: Primitives.h:235
void scale(double scaling)
Definition: Primitives.h:168
bool isConvex() const
Definition: Primitives.cpp:69
Point max() const
Maximum x/y coordinates of all points.
Definition: Primitives.h:277
Point min() const
Minimum x/y coordinates of all points.
Definition: Primitives.h:266
void rotate(double angle)
Rotates polygon counterclockwise about the origin.
Definition: Primitives.h:242
static Polygon loadFromSvgPathStr(std::string path_str)
Loads polygon from a path tag inside an SVG file.
Definition: Primitives.h:181
Definition: Primitives.h:19
double width() const
Definition: Primitives.h:30
void correct()
Ensures that x1, y1 is the bottom-left corner (minimum coordinates).
Definition: Primitives.h:36
double x() const
Definition: Primitives.h:27
double x1
Definition: Primitives.h:20
Rectangle(double x1, double y1, double x2, double y2)
Definition: Primitives.h:24
double y1
Definition: Primitives.h:20
double y() const
Definition: Primitives.h:28
double x2
Definition: Primitives.h:21
double y2
Definition: Primitives.h:21
Rectangle()=default
double height() const
Definition: Primitives.h:31