37 #include "ompl/base/spaces/DubinsStateSpace.h"
38 #include "ompl/base/SpaceInformation.h"
39 #include "ompl/util/Exception.h"
41 #include <boost/math/constants/constants.hpp>
47 constexpr
double twopi = 2. * boost::math::constants::pi<double>();
48 constexpr
double onepi = boost::math::constants::pi<double>();
49 constexpr
double halfpi = boost::math::constants::half_pi<double>();
50 const double DUBINS_EPS = 1e-6;
51 const double DUBINS_ZERO = -1e-7;
73 inline double mod2pi(
double x)
75 if (x < 0 && x > DUBINS_ZERO)
77 double xm = x - twopi * floor(x / twopi);
78 if (twopi - xm < .5 * DUBINS_EPS)
83 inline double t_lsr(
double d,
double alpha,
double beta)
85 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
86 const double tmp = -2.0 + d * d + 2.0 * (ca * cb + sa * sb + d * (sa + sb));
87 const double p = sqrtf(std::max(tmp, 0.0));
88 const double theta = atan2f(-ca - cb, d + sa + sb) - atan2f(-2.0, p);
89 return mod2pi(-alpha + theta);
92 inline double p_lsr(
double d,
double alpha,
double beta)
94 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
95 const double tmp = -2.0 + d * d + 2.0 * (ca * cb + sa * sb + d * (sa + sb));
96 return sqrtf(std::max(tmp, 0.0));
99 inline double q_lsr(
double d,
double alpha,
double beta)
101 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
102 const double tmp = -2.0 + d * d + 2.0 * (ca * cb + sa * sb + d * (sa + sb));
103 const double p = sqrtf(std::max(tmp, 0.0));
104 const double theta = atan2f(-ca - cb, d + sa + sb) - atan2f(-2.0, p);
105 return mod2pi(-beta + theta);
108 inline double t_rsl(
double d,
double alpha,
double beta)
110 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
111 const double tmp = d * d - 2.0 + 2.0 * (ca * cb + sa * sb - d * (sa + sb));
112 const double p = sqrtf(std::max(tmp, 0.0));
113 const double theta = atan2f(ca + cb, d - sa - sb) - atan2f(2.0, p);
114 return mod2pi(alpha - theta);
117 inline double p_rsl(
double d,
double alpha,
double beta)
119 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
120 const double tmp = d * d - 2.0 + 2.0 * (ca * cb + sa * sb - d * (sa + sb));
121 return sqrtf(std::max(tmp, 0.0));
124 inline double q_rsl(
double d,
double alpha,
double beta)
126 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
127 const double tmp = d * d - 2.0 + 2.0 * (ca * cb + sa * sb - d * (sa + sb));
128 const double p = sqrtf(std::max(tmp, 0.));
129 const double theta = atan2f(ca + cb, d - sa - sb) - atan2f(2.0, p);
130 return mod2pi(beta - theta);
133 inline double t_rsr(
double d,
double alpha,
double beta)
135 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
136 const double theta = atan2f(ca - cb, d - sa + sb);
137 return mod2pi(alpha - theta);
140 inline double p_rsr(
double d,
double alpha,
double beta)
142 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
143 const double tmp = 2.0 + d * d - 2.0 * (ca * cb + sa * sb - d * (sb - sa));
144 return sqrtf(std::max(tmp, 0.0));
147 inline double q_rsr(
double d,
double alpha,
double beta)
149 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
150 const double theta = atan2f(ca - cb, d - sa + sb);
151 return mod2pi(-beta + theta);
154 inline double t_lsl(
double d,
double alpha,
double beta)
156 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
157 const double theta = atan2f(cb - ca, d + sa - sb);
158 return mod2pi(-alpha + theta);
161 inline double p_lsl(
double d,
double alpha,
double beta)
163 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
164 const double tmp = 2.0 + d * d - 2.0 * (ca * cb + sa * sb - d * (sa - sb));
165 return sqrtf(std::max(tmp, 0.0));
168 inline double q_lsl(
double d,
double alpha,
double beta)
170 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
171 const double theta = atan2f(cb - ca, d + sa - sb);
172 return mod2pi(beta - theta);
175 inline double s_12(
double d,
double alpha,
double beta)
177 return p_rsr(d, alpha, beta) - p_rsl(d, alpha, beta) - 2.0 * (q_rsl(d, alpha, beta) - onepi);
180 inline double s_13(
double d,
double alpha,
double beta)
182 return t_rsr(d, alpha, beta) - onepi;
185 inline double s_14_1(
double d,
double alpha,
double beta)
187 return t_rsr(d, alpha, beta) - onepi;
190 inline double s_21(
double d,
double alpha,
double beta)
192 return p_lsl(d, alpha, beta) - p_rsl(d, alpha, beta) - 2.0 * (t_rsl(d, alpha, beta) - onepi);
195 inline double s_22_1(
double d,
double alpha,
double beta)
197 return p_lsl(d, alpha, beta) - p_rsl(d, alpha, beta) - 2.0 * (t_rsl(d, alpha, beta) - onepi);
200 inline double s_22_2(
double d,
double alpha,
double beta)
202 return p_rsr(d, alpha, beta) - p_rsl(d, alpha, beta) - 2.0 * (q_rsl(d, alpha, beta) - onepi);
205 inline double s_24(
double d,
double alpha,
double beta)
207 return q_rsr(d, alpha, beta) - onepi;
210 inline double s_31(
double d,
double alpha,
double beta)
212 return q_lsl(d, alpha, beta) - onepi;
215 inline double s_33_1(
double d,
double alpha,
double beta)
217 return p_rsr(d, alpha, beta) - p_lsr(d, alpha, beta) - 2.0 * (t_lsr(d, alpha, beta) - onepi);
220 inline double s_33_2(
double d,
double alpha,
double beta)
222 return p_lsl(d, alpha, beta) - p_lsr(d, alpha, beta) - 2.0 * (q_lsr(d, alpha, beta) - onepi);
225 inline double s_34(
double d,
double alpha,
double beta)
227 return p_rsr(d, alpha, beta) - p_lsr(d, alpha, beta) - 2.0 * (t_lsr(d, alpha, beta) - onepi);
230 inline double s_41_1(
double d,
double alpha,
double beta)
232 return t_lsl(d, alpha, beta) - onepi;
235 inline double s_41_2(
double d,
double alpha,
double beta)
237 return q_lsl(d, alpha, beta) - onepi;
240 inline double s_42(
double d,
double alpha,
double beta)
242 return t_lsl(d, alpha, beta) - onepi;
245 inline double s_43(
double d,
double alpha,
double beta)
247 return p_lsl(d, alpha, beta) - p_lsr(d, alpha, beta) - 2.0 * (q_lsr(d, alpha, beta) - onepi);
252 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
253 double tmp = 2. + d * d - 2. * (ca * cb + sa * sb - d * (sa - sb));
254 if (tmp >= DUBINS_ZERO)
256 double theta = atan2(cb - ca, d + sa - sb);
257 double t = mod2pi(-alpha + theta);
258 double p = sqrt(std::max(tmp, 0.));
259 double q = mod2pi(beta - theta);
260 assert(fabs(p * cos(alpha + t) - sa + sb - d) < (1 + p) * DUBINS_EPS);
261 assert(fabs(p * sin(alpha + t) + ca - cb) < (1 + p) * DUBINS_EPS);
262 assert(mod2pi(alpha + t + q - beta + .5 * DUBINS_EPS) < DUBINS_EPS);
270 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
271 double tmp = 2. + d * d - 2. * (ca * cb + sa * sb - d * (sb - sa));
272 if (tmp >= DUBINS_ZERO)
274 double theta = atan2(ca - cb, d - sa + sb);
275 double t = mod2pi(alpha - theta);
276 double p = sqrt(std::max(tmp, 0.));
277 double q = mod2pi(-beta + theta);
278 assert(fabs(p * cos(alpha - t) + sa - sb - d) < (1 + p) * DUBINS_EPS);
279 assert(fabs(p * sin(alpha - t) - ca + cb) < (1 + p) * DUBINS_EPS);
280 assert(mod2pi(alpha - t - q - beta + .5 * DUBINS_EPS) < DUBINS_EPS);
288 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
289 double tmp = d * d - 2. + 2. * (ca * cb + sa * sb - d * (sa + sb));
290 if (tmp >= DUBINS_ZERO)
292 double p = sqrt(std::max(tmp, 0.));
293 double theta = atan2(ca + cb, d - sa - sb) - atan2(2., p);
294 double t = mod2pi(alpha - theta);
295 double q = mod2pi(beta - theta);
296 assert(fabs(p * cos(alpha - t) - 2. * sin(alpha - t) + sa + sb - d) < 2 * DUBINS_EPS);
297 assert(fabs(p * sin(alpha - t) + 2. * cos(alpha - t) - ca - cb) < 2 * DUBINS_EPS);
298 assert(mod2pi(alpha - t + q - beta + .5 * DUBINS_EPS) < DUBINS_EPS);
306 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
307 double tmp = -2. + d * d + 2. * (ca * cb + sa * sb + d * (sa + sb));
308 if (tmp >= DUBINS_ZERO)
310 double p = sqrt(std::max(tmp, 0.));
311 double theta = atan2(-ca - cb, d + sa + sb) - atan2(-2., p);
312 double t = mod2pi(-alpha + theta);
313 double q = mod2pi(-beta + theta);
314 assert(fabs(p * cos(alpha + t) + 2. * sin(alpha + t) - sa - sb - d) < 2 * DUBINS_EPS);
315 assert(fabs(p * sin(alpha + t) - 2. * cos(alpha + t) + ca + cb) < 2 * DUBINS_EPS);
316 assert(mod2pi(alpha + t - q - beta + .5 * DUBINS_EPS) < DUBINS_EPS);
324 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
325 double tmp = .125 * (6. - d * d + 2. * (ca * cb + sa * sb + d * (sa - sb)));
328 double p = twopi - acos(tmp);
329 double theta = atan2(ca - cb, d - sa + sb);
330 double t = mod2pi(alpha - theta + .5 * p);
331 double q = mod2pi(alpha - beta - t + p);
332 assert(fabs(2. * sin(alpha - t + p) - 2. * sin(alpha - t) - d + sa - sb) < 2 * DUBINS_EPS);
333 assert(fabs(-2. * cos(alpha - t + p) + 2. * cos(alpha - t) - ca + cb) < 2 * DUBINS_EPS);
334 assert(mod2pi(alpha - t + p - q - beta + .5 * DUBINS_EPS) < DUBINS_EPS);
342 double ca = cos(alpha), sa = sin(alpha), cb = cos(beta), sb = sin(beta);
343 double tmp = .125 * (6. - d * d + 2. * (ca * cb + sa * sb - d * (sa - sb)));
346 double p = twopi - acos(tmp);
347 double theta = atan2(-ca + cb, d + sa - sb);
348 double t = mod2pi(-alpha + theta + .5 * p);
349 double q = mod2pi(beta - alpha - t + p);
350 assert(fabs(-2. * sin(alpha + t - p) + 2. * sin(alpha + t) - d - sa + sb) < 2 * DUBINS_EPS);
351 assert(fabs(2. * cos(alpha + t - p) - 2. * cos(alpha + t) + ca - cb) < 2 * DUBINS_EPS);
352 assert(mod2pi(alpha + t - p + q - beta + .5 * DUBINS_EPS) < DUBINS_EPS);
358 bool isLongPath(
double d,
double alpha,
double beta)
360 return (std::abs(std::sin(alpha)) + std::abs(std::sin(beta)) +
361 std::sqrt(4 - std::pow(std::cos(alpha) + std::cos(beta), 2)) - d) < 0;
366 if (d < DUBINS_EPS && fabs(alpha - beta) < DUBINS_EPS)
370 double len, minLength = path.length();
372 if ((len = tmp.length()) < minLength)
377 tmp = dubinsRSL(d, alpha, beta);
378 if ((len = tmp.length()) < minLength)
383 tmp = dubinsLSR(d, alpha, beta);
384 if ((len = tmp.length()) < minLength)
389 tmp = dubinsRLR(d, alpha, beta);
390 if ((len = tmp.length()) < minLength)
395 tmp = dubinsLRL(d, alpha, beta);
396 if ((len = tmp.length()) < minLength)
401 DubinsClass getDubinsClass(
const double alpha,
const double beta)
403 int row(0), column(0);
404 if (0 <= alpha && alpha <= halfpi)
408 else if (halfpi < alpha && alpha <= onepi)
412 else if (onepi < alpha && alpha <= 3 * halfpi)
416 else if (3 * halfpi < alpha && alpha <= twopi)
421 if (0 <= beta && beta <= halfpi)
425 else if (halfpi < beta && beta <= onepi)
429 else if (onepi < beta && beta <= 3 * halfpi)
433 else if (3 * halfpi < beta && beta <= 2.0 * onepi)
438 assert(row >= 1 && row <= 4 &&
439 "alpha is not in the range of [0,2pi] in classifyPath(double alpha, double beta).");
440 assert(column >= 1 && column <= 4 &&
441 "beta is not in the range of [0,2pi] in classifyPath(double alpha, double beta).");
442 assert((column - 1) + 4 * (row - 1) >= 0 && (column - 1) + 4 * (row - 1) <= 15 &&
443 "class is not in range [0,15].");
444 return (DubinsClass)((column - 1) + 4 * (row - 1));
449 if (d < DUBINS_EPS && fabs(alpha - beta) < DUBINS_EPS)
458 auto dubins_class = getDubinsClass(alpha, beta);
459 switch (dubins_class)
461 case DubinsClass::A11:
463 path = dubinsRSL(d, alpha, beta);
466 case DubinsClass::A12:
468 if (s_13(d, alpha, beta) < 0.0)
470 path = (s_12(d, alpha, beta) < 0.0) ? dubinsRSR(d, alpha, beta) : dubinsRSL(d, alpha, beta);
474 path = dubinsLSR(d, alpha, beta);
476 if (path.length() > tmp.length())
483 case DubinsClass::A13:
485 if (s_13(d, alpha, beta) < 0.0)
487 path = dubinsRSR(d, alpha, beta);
491 path = dubinsLSR(d, alpha, beta);
495 case DubinsClass::A14:
497 if (s_14_1(d, alpha, beta) > 0.0)
499 path = dubinsLSR(d, alpha, beta);
501 else if (s_24(d, alpha, beta) > 0.0)
503 path = dubinsRSL(d, alpha, beta);
507 path = dubinsRSR(d, alpha, beta);
511 case DubinsClass::A21:
513 if (s_31(d, alpha, beta) < 0.0)
515 if (s_21(d, alpha, beta) < 0.0)
517 path = dubinsLSL(d, alpha, beta);
521 path = dubinsRSL(d, alpha, beta);
526 path = dubinsLSR(d, alpha, beta);
528 if (path.length() > tmp.length())
535 case DubinsClass::A22:
539 path = (s_22_1(d, alpha, beta) < 0.0) ? dubinsLSL(d, alpha, beta) : dubinsRSL(d, alpha, beta);
543 path = (s_22_2(d, alpha, beta) < 0.0) ? dubinsRSR(d, alpha, beta) : dubinsRSL(d, alpha, beta);
547 case DubinsClass::A23:
549 path = dubinsRSR(d, alpha, beta);
552 case DubinsClass::A24:
554 if (s_24(d, alpha, beta) < 0.0)
556 path = dubinsRSR(d, alpha, beta);
560 path = dubinsRSL(d, alpha, beta);
564 case DubinsClass::A31:
566 if (s_31(d, alpha, beta) < 0.0)
568 path = dubinsLSL(d, alpha, beta);
572 path = dubinsLSR(d, alpha, beta);
576 case DubinsClass::A32:
578 path = dubinsLSL(d, alpha, beta);
581 case DubinsClass::A33:
585 if (s_33_1(d, alpha, beta) < 0.0)
587 path = dubinsRSR(d, alpha, beta);
591 path = dubinsLSR(d, alpha, beta);
596 if (s_33_2(d, alpha, beta) < 0.0)
598 path = dubinsLSL(d, alpha, beta);
602 path = dubinsLSR(d, alpha, beta);
607 case DubinsClass::A34:
609 if (s_24(d, alpha, beta) < 0.0)
611 if (s_34(d, alpha, beta) < 0.0)
613 path = dubinsRSR(d, alpha, beta);
617 path = dubinsLSR(d, alpha, beta);
622 path = dubinsLSR(d, alpha, beta);
624 if (path.length() > tmp.length())
631 case DubinsClass::A41:
633 if (s_41_1(d, alpha, beta) > 0.0)
635 path = dubinsRSL(d, alpha, beta);
637 else if (s_41_2(d, alpha, beta) > 0.0)
639 path = dubinsLSR(d, alpha, beta);
643 path = dubinsLSL(d, alpha, beta);
647 case DubinsClass::A42:
649 if (s_42(d, alpha, beta) < 0.0)
651 path = dubinsLSL(d, alpha, beta);
655 path = dubinsRSL(d, alpha, beta);
659 case DubinsClass::A43:
661 if (s_42(d, alpha, beta) < 0.0)
663 if (s_43(d, alpha, beta) < 0.0)
665 path = dubinsLSL(d, alpha, beta);
669 path = dubinsLSR(d, alpha, beta);
674 path = dubinsLSR(d, alpha, beta);
676 if (path.length() > tmp.length())
683 case DubinsClass::A44:
685 path = dubinsLSR(d, alpha, beta);
698 os <<
"DubinsPath[ type=";
699 for (
unsigned i = 0; i < 3; ++i)
700 if (path.type_->at(i) == DubinsStateSpace::DUBINS_LEFT)
702 else if (path.type_->at(i) == DubinsStateSpace::DUBINS_STRAIGHT)
706 os <<
", length=" << path.length_[0] <<
'+' << path.length_[1] <<
'+' << path.length_[2] <<
'=' << path.length()
707 <<
", reverse=" << path.reverse_ <<
" ]";
714 if (d < DUBINS_EPS && fabs(alpha - beta) < DUBINS_EPS)
716 alpha = mod2pi(alpha);
718 return isLongPath(d, alpha, beta) ? ::dubinsClassification(d, alpha, beta) : ::dubinsExhaustive(d, alpha, beta);
723 {{DUBINS_LEFT, DUBINS_STRAIGHT, DUBINS_LEFT}},
724 {{DUBINS_RIGHT, DUBINS_STRAIGHT, DUBINS_RIGHT}},
725 {{DUBINS_RIGHT, DUBINS_STRAIGHT, DUBINS_LEFT}},
726 {{DUBINS_LEFT, DUBINS_STRAIGHT, DUBINS_RIGHT}},
727 {{DUBINS_RIGHT, DUBINS_LEFT, DUBINS_RIGHT}},
728 {{DUBINS_LEFT, DUBINS_RIGHT, DUBINS_LEFT}}
737 return radius *
dubins(state1, state2, radius).length();
739 double DubinsStateSpace::symmetricDistance(
const State *state1,
const State *state2,
double radius)
741 return radius * std::min(
dubins(state1, state2, radius).length(),
dubins(state2, state1, radius).length());
746 bool firstTime =
true;
752 DubinsPath &path,
State *state)
const
772 DubinsPath path2(
dubins(to, from));
773 if (path2.length() < path.length())
775 path2.reverse_ =
true;
788 double seg = t * path.length(), phi, v;
794 for (
unsigned int i = 0; i < 3 && seg > 0; ++i)
796 v = std::min(seg, path.length_[i]);
799 switch (path.type_->at(i))
802 s->setXY(s->getX() + sin(phi + v) - sin(phi), s->getY() - cos(phi + v) + cos(phi));
806 s->setXY(s->getX() - sin(phi - v) + sin(phi), s->getY() + cos(phi - v) - cos(phi));
809 case DUBINS_STRAIGHT:
810 s->setXY(s->getX() + v * cos(phi), s->getY() + v * sin(phi));
817 for (
unsigned int i = 0; i < 3 && seg > 0; ++i)
819 v = std::min(seg, path.length_[2 - i]);
822 switch (path.type_->at(2 - i))
825 s->setXY(s->getX() + sin(phi - v) - sin(phi), s->getY() - cos(phi - v) + cos(phi));
829 s->setXY(s->getX() - sin(phi + v) + sin(phi), s->getY() + cos(phi + v) - cos(phi));
832 case DUBINS_STRAIGHT:
833 s->setXY(s->getX() - v * cos(phi), s->getY() - v * sin(phi));
859 double x1 = s1->
getX(), y1 = s1->getY(), th1 = s1->getYaw();
860 double x2 = s2->getX(), y2 = s2->getY(), th2 = s2->getYaw();
861 double dx = x2 - x1, dy = y2 - y1, d = sqrt(dx * dx + dy * dy) / radius, th = atan2(dy, dx);
862 double alpha = mod2pi(th1 - th), beta = mod2pi(th2 - th);
863 return ::dubins(d, alpha, beta);
866 void DubinsMotionValidator::defaultSettings()
869 if (stateSpace_ ==
nullptr)
870 throw Exception(
"No state space for motion validator");
877 bool result =
true, firstTime =
true;
886 for (
int j = 1; j < nd; ++j)
888 stateSpace_->
interpolate(s1, s2, (
double)j / (
double)nd, firstTime, path, test);
891 lastValid.second = (double)(j - 1) / (double)nd;
892 if (lastValid.first !=
nullptr)
893 stateSpace_->
interpolate(s1, s2, lastValid.second, firstTime, path, lastValid.first);
904 lastValid.second = (double)(nd - 1) / (double)nd;
905 if (lastValid.first !=
nullptr)
906 stateSpace_->
interpolate(s1, s2, lastValid.second, firstTime, path, lastValid.first);
924 bool result =
true, firstTime =
true;
929 std::queue<std::pair<int, int>> pos;
932 pos.emplace(1, nd - 1);
940 std::pair<int, int> x = pos.front();
942 int mid = (x.first + x.second) / 2;
943 stateSpace_->
interpolate(s1, s2, (
double)mid / (double)nd, firstTime, path, test);
954 pos.emplace(x.first, mid - 1);
956 pos.emplace(mid + 1, x.second);