3#include <ompl/geometric/PathGeometric.h>
4#include <ompl/control/PathControl.h>
14namespace ob = ompl::base;
15namespace og = ompl::geometric;
39 static double slope(
const N &x1,
const N &y1,
const N &x2,
const N &y2) {
40 const auto dy = y2 - y1;
41 const auto dx = x2 - x1;
51 const auto dy = b.
y - a.
y;
52 const auto dx = b.
x - a.
x;
62 const auto dy = b->as<
State>()->getY() - a->as<
State>()->getY();
63 const auto dx = b->as<
State>()->getX() - a->as<
State>()->getX();
80 const auto dy = b->as<
State>()->getY() - a->as<
State>()->getY();
81 const auto dx = b->as<
State>()->getX() - a->as<
State>()->getX();
82 const auto dt = b->as<
State>()->getYaw() - a->as<
State>()->getYaw();
104 static bool collides(
const std::vector<Point> &path) {
105 std::cout <<
"Starting.. " << std::endl;
107 for (
const auto &point : path) {
109 std::cout <<
"check.. " << std::endl;
130 static bool collides(
const ompl::geometric::PathGeometric &path) {
131 for (std::size_t i = 0; i < path.getStateCount(); ++i) {
132 const auto *state = path.getState(i)->as<
State>();
153 OMPL_DEBUG(
"Checking for collision between [%f %f] and [%f %f]",
154 a->as<
State>()->getX(), a->as<
State>()->getY(),
155 b->as<
State>()->getX(), b->as<
State>()->getY());
156 std::cout <<
"global::settings.ompl.state_space->validSegmentCount(a, b): "
181 og::PathGeometric &path) {
184 OMPL_DEBUG(
"Checking for collision between [%f %f] and [%f %f]",
185 a->as<
State>()->getX(), a->as<
State>()->getY(),
186 b->as<
State>()->getX(), b->as<
State>()->getY());
189 std::cout <<
"global::settings.ompl.state_space->validSegmentCount(a, b): "
208 static bool collides(
const std::vector<Point> &path,
209 std::vector<Point> &collisions) {
211 for (std::size_t i = 1; i < path.size(); ++i) {
218 collisions.emplace_back(path[i]);
225 return !collisions.empty();
243 std::vector<Point> &collisions) {
246 std::cout <<
"global::settings.ompl.state_space->validSegmentCount(a, b): "
262 ompl::geometric::PathGeometric path) {
263 if (path.getStateCount() < 2) {
265 OMPL_WARN(
"Tried to interpolate an empty path.");
272 "Cannot interpolate path with %d nodes (maximal %d are allowed).",
279 OMPL_WARN(
"Cannot interpolate path of length %f (maximal %f is allowed).",
285 OMPL_DEBUG(
"Interpolating path with %d nodes and length %f.",
286 path.getStateCount(), path.length());
298 ompl::control::PathControl path) {
299 if (path.getStateCount() < 2) {
301 OMPL_WARN(
"Tried to interpolate an empty path.");
308 "Cannot interpolate path with %d nodes (maximal %d are allowed).",
315 OMPL_WARN(
"Cannot interpolate path of length %f (maximal %f is allowed).",
321 OMPL_DEBUG(
"Interpolating path with %d nodes and length %f.",
322 path.getStateCount(), path.length());
329 bool AverageAngles =
true,
330 bool preventCollisions =
true) {
331 if (path.getStateCount() < 2)
return;
333 std::vector<ob::State *> &states(path.getStates());
335 double theta_old = states[0]->as<
State>()->getYaw();
336 states[0]->as<
State>()->setYaw(
slope(states[0], states[1]));
337 if (preventCollisions &&
collides(states[0], states[1]))
338 states[0]->as<State>()->setYaw(theta_old);
339 for (
int i = 1; i < path.getStateCount() - 1; ++i) {
341 OMPL_DEBUG(
"UpdateAngles: Round %d / %d", i, path.getStateCount() - 2);
343 theta_old = states[i]->as<
State>()->getYaw();
345 double l =
slope(states[i - 1], states[i]);
346 double r =
slope(states[i], states[i + 1]);
353 states[i]->as<
State>()->setYaw((l + r) * 0.5);
355 states[i]->as<
State>()->setYaw(
slope(states[i - 1], states[i]));
357 if (preventCollisions && (
collides(states[i - 1], states[i]) ||
358 collides(states[i], states[i + 1])))
359 states[i]->as<
State>()->setYaw(theta_old);
361 theta_old = states[path.getStateCount() - 1]->as<
State>()->getYaw();
362 states[path.getStateCount() - 1]->as<
State>()->setYaw(
slope(
363 states[path.getStateCount() - 2], states[path.getStateCount() - 1]));
364 if (preventCollisions &&
collides(states[path.getStateCount() - 1],
365 states[path.getStateCount() - 2]))
366 states[path.getStateCount() - 1]->as<
State>()->setYaw(
371 unsigned int rounds,
double eta,
372 double discount = 1.) {
374 for (
int round = 0; round < rounds; ++round) {
376 for (
int i = 1; i < path.getStateCount() - 1; ++i) {
379 path.getStates()[i]->as<
State>()->getX(),
380 path.getStates()[i]->as<
State>()->getY(), dx, dy, 1.);
382 path.getStates()[i]->as<
State>()->getX(),
383 path.getStates()[i]->as<
State>()->getY());
385 path.getStates()[i]->as<
State>()->setX(
386 path.getStates()[i]->as<
State>()->getX() - eta * dx / distance);
387 path.getStates()[i]->as<
State>()->setY(
388 path.getStates()[i]->as<
State>()->getY() + eta * dy / distance);
395 double eta,
double discount = 1.) {
397 for (
int round = 0; round < rounds; ++round) {
399 for (
int i = 1; i < path.size() - 1; ++i) {
404 path[i].x, path[i].y);
406 path[i].x -= eta * dx / distance;
407 path[i].y += eta * dy / distance;
423 std::vector<Point> points;
424 double dx = (b.
x - a.
x);
425 double dy = (b.
y - a.
y);
426 const double size = std::sqrt(dx * dx + dy * dy);
427 if (size == 0)
return std::vector<Point>{a};
430 const auto steps = (int)(size / std::sqrt(dx * dx + dy * dy));
432 for (
int j = 1; j <= steps; ++j)
433 points.emplace_back(a.
x + dx * j, a.
y + dy * j);
435 if (points.empty()) points.emplace_back(a);
469 const std::vector<Point> &points) {
470 if (points.size() == 1)
return points[0].toState();
471 unsigned int closest = 0;
472 double dist = points[closest].distanceSquared(x);
473 for (
unsigned int i = 1; i < points.size() - 1; ++i) {
476 const double d = points[i].distanceSquared(x);
484 theta =
slope(points[0], points[1]);
486 theta =
slope(points[closest - 1], points[closest + 1]);
487 return points[closest].toState(theta);
501 for (
size_t i = 1; i < path.size(); ++i) {
502 l += path[i].distance(path[i - 1]);
516 std::vector<Point> result;
518 const double targetSegment = total / targetSize;
519 result.emplace_back(path[0]);
522 size_t resultCounter = 1;
523 for (
size_t i = 1; i < path.size(); ++i) {
524 double dx = (path[i].x - path[i - 1].x);
525 double dy = (path[i].y - path[i - 1].y);
526 const double l = std::sqrt(dx * dx + dy * dy);
527 if (std::abs(l) < 1e-3)
continue;
530 if (segment + l < targetSegment) {
532 OMPL_DEBUG(
"EquidistantSampling: Segment too short between %i and %i",
536 double start = std::fmod(segment + l, targetSegment) - segment;
538 const auto segmentSteps =
539 static_cast<unsigned int>(std::floor((segment + l) / targetSegment));
540 for (
unsigned int j = 0; j < segmentSteps; ++j) {
541 const double alpha = start + j * targetSegment;
542 const Point p(path[i - 1].x + dx * alpha, path[i - 1].y + dy * alpha);
543 result.emplace_back(p);
545 sofar += segmentSteps * targetSegment;
546 segment = l - segmentSteps * targetSegment;
548 result.emplace_back(path.back());
559 template <
typename N>
560 static std::string
num2str(
const N &v,
unsigned int precision = 3) {
561 std::stringstream stream;
562 stream << std::fixed << std::setprecision(precision) << v;
573 return std::atan2(std::sin(angle), std::cos(angle));
ob::SE2StateSpace::StateType State
Definition: Primitives.h:12
Helper for common operations during planning and evaluation.
Definition: PlannerUtils.hpp:22
static bool collides(const std::vector< Point > &path, std::vector< Point > &collisions)
Check whether points on a path collide with the environment.
Definition: PlannerUtils.hpp:208
static std::vector< Point > linearInterpolate(const Point &a, const Point &b, double dt=0.1)
Linearly interpolate between two points.
Definition: PlannerUtils.hpp:421
static double slope(const Point &a, const Point &b)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: PlannerUtils.hpp:50
static double slope(const ompl::base::State *a, const ompl::base::State *b)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: PlannerUtils.hpp:61
static std::string num2str(const N &v, unsigned int precision=3)
Convert a number to a string with the given precision.
Definition: PlannerUtils.hpp:560
static ompl::geometric::PathGeometric interpolated(ompl::geometric::PathGeometric path)
Interpolate path based on its associated state space.
Definition: PlannerUtils.hpp:261
static bool collides(const ompl::base::State *a, const ompl::base::State *b, og::PathGeometric &path)
Collision check that respects the collision model.
Definition: PlannerUtils.hpp:180
static void gradientDescent(std::vector< Point > &path, unsigned int rounds, double eta, double discount=1.)
Definition: PlannerUtils.hpp:394
static double totalLength(const std::vector< Point > &path)
Compute total length of a path.
Definition: PlannerUtils.hpp:499
static bool equals(const ompl::base::State *a, const ompl::base::State *b)
Check whether two states are equal (up to some tolerance).
Definition: PlannerUtils.hpp:79
static bool collides(const ompl::geometric::PathGeometric &path)
Collision check that respects the collision model.
Definition: PlannerUtils.hpp:130
static void updateAngles(ompl::geometric::PathGeometric &path, bool AverageAngles=true, bool preventCollisions=true)
Definition: PlannerUtils.hpp:328
static bool collides(const std::vector< Point > &path)
Check whether points on a path collide with the environment.
Definition: PlannerUtils.hpp:104
static ompl::control::PathControl interpolated(ompl::control::PathControl path)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: PlannerUtils.hpp:297
static bool collides(const ompl::base::State *a, const ompl::base::State *b, std::vector< Point > &collisions)
Collision check of segment between two states.
Definition: PlannerUtils.hpp:242
static std::vector< Point > linearInterpolate(ompl::base::State *a, ompl::base::State *b, double dt=0.1)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: PlannerUtils.hpp:450
static std::vector< Point > equidistantSampling(const std::vector< Point > &path, size_t targetSize)
Compute equidistance samples along path.
Definition: PlannerUtils.hpp:514
static ompl::base::State * closestPoint(Point x, const std::vector< Point > &points)
Find closest collision-free point in an ordered set of points.
Definition: PlannerUtils.hpp:468
static bool collides(const ompl::base::State *a, const ompl::base::State *b)
Collision check of segment between two states.
Definition: PlannerUtils.hpp:151
static double slope(const N &x1, const N &y1, const N &x2, const N &y2)
Compute the angular slope between two points.
Definition: PlannerUtils.hpp:39
static std::vector< Point > toSteeredPoints(const ob::State *a, const ob::State *b)
Definition: PlannerUtils.hpp:88
static void gradientDescent(ompl::geometric::PathGeometric &path, unsigned int rounds, double eta, double discount=1.)
Definition: PlannerUtils.hpp:370
static double normalizeAngle(double angle)
Normalize angle in radians to the interval .
Definition: PlannerUtils.hpp:572
double max(const std::vector< double > &values)
Definition: PathStatistics.hpp:79
Property< double > state_equality_tolerance
Definition: PlannerSettings.h:416
ompl::base::StateSpacePtr state_space
Definition: PlannerSettings.h:405
std::shared_ptr< Environment > environment
Environment used for planning.
Definition: PlannerSettings.h:73
PlannerSettings::GlobalSettings::OmplSettings ompl
Property< double > max_path_length
Maximal length a og::PathGeometric can have to be interpolated.
Definition: PlannerSettings.h:272
Property< unsigned int > interpolation_limit
Any og::PathGeometric with more nodes will not get interpolated.
Definition: PlannerSettings.h:267
Definition: Primitives.h:42
static std::vector< Point > fromPath(const ompl::geometric::PathGeometric &p, bool interpolate=false)
Definition: Primitives.cpp:25
double x
Definition: Primitives.h:43
double y
Definition: Primitives.h:43
static PlannerSettings::GlobalSettings settings
Definition: PlannerSettings.h:699