Loading...
Searching...
No Matches
MulticopterPlanning.cpp
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2025, University of Santa Cruz Hybrid Systems Laboratory
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the University of Santa Cruz nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Beverly Xu */
36
37#include "CommonMath/Trajectory.h"
38#include "CommonMath/RectPrism.h"
39#include "Polyfit.h"
40#include "Quartic.h"
41#include "CommonMath/RectPrism.h"
42#include "CommonMath/ConvexObj.h"
43
44#include "ompl/control/planners/sst/HySST.h"
45#include "ompl/base/GoalTypes.h"
46#include "ompl/base/Planner.h"
47#include "ompl/base/spaces/RealVectorStateSpace.h"
48#include "ompl/control/PathControl.h"
49#include "ompl/control/SpaceInformation.h"
50#include "ompl/control/ODESolver.h"
51#include "ompl/base/goals/GoalRegion.h"
52
53using namespace CommonMath;
54
55enum CollisionResult
56{
57 NoCollision = 0,
58 Collision = 1,
59 CollisionIndeterminable = 2,
60};
61
62struct DetailedCollisionResult
63{
64 CollisionResult collisionType;
65 double collisionTime;
66};
67
68// Instantiate obstacles
69CommonMath::RectPrism leftRect = CommonMath::RectPrism(Vec3(0.25, 2, 0), Vec3(0.5, 2, 2));
70CommonMath::RectPrism topRect = CommonMath::RectPrism(Vec3(2.5, 2.75, 0), Vec3(4, 0.5, 2));
71CommonMath::RectPrism bottomRect = CommonMath::RectPrism(Vec3(2.5, 1.25, 0), Vec3(4, 0.5, 2));
72
73// Instantiate obstacles as shared pointers
74std::shared_ptr<CommonMath::RectPrism> leftRectPrism = std::make_shared<CommonMath::RectPrism>((leftRect));
75std::shared_ptr<CommonMath::RectPrism> topRectPrism = std::make_shared<CommonMath::RectPrism>((topRect));
76std::shared_ptr<CommonMath::RectPrism> bottomRectPrism = std::make_shared<CommonMath::RectPrism>((bottomRect));
77
79DetailedCollisionResult polyCollisionChecker(double ts, double tf, std::shared_ptr<CommonMath::ConvexObj> obstacle,
80 double minTimeSection, unsigned iterationNumber,
82{
83 DetailedCollisionResult testResult;
84
85 // First find the position halfway between the start and end time of this segment
86 double midTime = (ts + tf) / 2.0;
87 Vec3 midpoint = _traj.GetValue(midTime);
88
89 if (obstacle->IsPointInside(midpoint))
90 {
91 if ((tf - ts) <= minTimeSection)
92 {
93 // If the time section is small enough, consider it a collision
94 testResult.collisionType = Collision;
95 testResult.collisionTime = ts;
96 return testResult;
97 }
98 else
99 {
100 // Recursively check both halves of the trajectory
101 unsigned nextIterationNumber = iterationNumber + 1;
102 DetailedCollisionResult firstHalfResult =
103 polyCollisionChecker(ts, midTime, obstacle, minTimeSection, nextIterationNumber, _traj);
104 DetailedCollisionResult secondHalfResult =
105 polyCollisionChecker(midTime, tf, obstacle, minTimeSection, nextIterationNumber, _traj);
106
107 // Merge or prioritize collision results from both halves as needed
108 // For simplicity, this example prioritizes collisions in the first half
109 if (firstHalfResult.collisionType != NoCollision)
110 return firstHalfResult;
111 else
112 return secondHalfResult;
113 }
114 }
115
116 if (tf - ts < minTimeSection)
117 {
118 // Our time resolution is too small, just give up (trajectory is likely tangent to obstacle surface)
119 testResult.collisionType = CollisionIndeterminable;
120 testResult.collisionTime = ts;
121 return testResult;
122 }
123
124 Vec3 endPoint = _traj.GetValue(tf);
125 if (obstacle->IsPointInside(endPoint))
126 {
127 // Recursively check both halves of the trajectory based on collision in the first half
128 DetailedCollisionResult firstHalfResult;
129 unsigned nextIterationNumber = iterationNumber + 1;
130 firstHalfResult = polyCollisionChecker(ts, midTime, obstacle, minTimeSection, nextIterationNumber, _traj);
131 if (firstHalfResult.collisionType != NoCollision)
132 return firstHalfResult;
133 else
134 {
135 // Recursively check the second half of the trajectory
136 unsigned nextIterationNumber = iterationNumber + 1;
137 return polyCollisionChecker(midTime, tf, obstacle, minTimeSection, nextIterationNumber, _traj);
138 }
139 }
140
141 // Get the plane separating the midpoint and the obstacle
142 CommonMath::Boundary tangentPlane = obstacle->GetTangentPlane(midpoint);
143
144 // Take the dot product of the trajectory with the unit normal of the separating plane.
145 // This gives the distance of the trajectory from the plane as a function of time
146 double c[5] = {0, 0, 0, 0, 0};
147 std::vector<Vec3> trajDerivativeCoeffs = _traj.GetDerivativeCoeffs();
148 for (unsigned dim = 0; dim < 3; dim++)
149 {
150 c[0] += tangentPlane.normal[dim] * trajDerivativeCoeffs[0][dim]; // t**4
151 c[1] += tangentPlane.normal[dim] * trajDerivativeCoeffs[1][dim]; // t**3
152 c[2] += tangentPlane.normal[dim] * trajDerivativeCoeffs[2][dim]; // t**2
153 c[3] += tangentPlane.normal[dim] * trajDerivativeCoeffs[3][dim]; // t
154 c[4] += tangentPlane.normal[dim] * trajDerivativeCoeffs[4][dim]; // 1
155 }
156
157 // Solve the roots
158 double roots[4];
159 unsigned rootCount;
160 if (fabs(c[0]) > double(1e-6))
161 rootCount = Quartic::solve_quartic(c[1] / c[0], c[2] / c[0], c[3] / c[0], c[4] / c[0], roots);
162 else
163 rootCount = Quartic::solveP3(c[2] / c[1], c[3] / c[1], c[4] / c[1], roots);
164 // The first "rootCount" entries of roots are now the unordered roots
165 std::sort(roots, roots + rootCount);
166 // The first "rootCount" entries of roots are now the roots in ascending order
167
168 // Get both lists of points to check (in ascending order)
169 std::vector<double> testPointsLow;
170 std::vector<double> testPointsHigh;
171 testPointsLow.reserve(6);
172 testPointsHigh.reserve(6);
173 testPointsLow.push_back(ts); // ts is always the first critical point in testPointsLow
174 testPointsHigh.push_back(midTime); // midTime is always the first critical point in testPointsHigh
175 for (unsigned int i = 0; i < rootCount; i++)
176 {
177 if (roots[i] <= ts) // Skip root if it's before ts
178 continue;
179 else if (roots[i] < midTime) // Root is between ts and midTime
180 testPointsLow.push_back(roots[i]);
181 else if (roots[i] < tf) // Root is between midTime and tf
182 testPointsHigh.push_back(roots[i]);
183 else // Because the roots are in ascending order, there are no more roots are on (ts,tf)
184 break;
185 }
186 testPointsLow.push_back(midTime); // midTime is always the last critical point in testPointsLow
187 testPointsHigh.push_back(tf); // tf is always the last critical point in testPointsHigh
188
189 // Check testPointsLow first. If the collision already takes place in first half, we can ignore the second half and
190 // return the collision time.
191 for (typename std::vector<double>::reverse_iterator it = testPointsLow.rbegin() + 1; it != testPointsLow.rend();
192 it++)
193 {
194 // Check whether the critical point occurs on the obstacle side of the plane
195 if ((_traj.GetValue(*it) - tangentPlane.point).Dot(tangentPlane.normal) <= 0)
196 {
197 // This critical point is on the obstacle side of the plane, so we must
198 // keep searching over the rest of the trajectory starting at the
199 // previous critical point and ending at ts (recall we are searching
200 // backwards in time).
201
202 DetailedCollisionResult lowTestPointsResult;
203 lowTestPointsResult = polyCollisionChecker(ts, *(it - 1), obstacle, minTimeSection, iterationNumber, _traj);
204 if (lowTestPointsResult.collisionType == NoCollision)
205 break;
206 else
207 return lowTestPointsResult;
208 }
209 }
210
211 for (typename std::vector<double>::iterator it = testPointsHigh.begin() + 1; it != testPointsHigh.end(); it++)
212 {
213 // Check whether the critical point occurs on the obstacle side of the plane
214 if ((_traj.GetValue(*it) - tangentPlane.point).Dot(tangentPlane.normal) <= 0)
215 {
216 // This critical point is on the obstacle side of the plane, so we must
217 // keep searching over the rest of the trajectory starting at the
218 // previous critical point and ending at tf.
219 DetailedCollisionResult highTestPointsResult;
220 unsigned nextIterationNumber = iterationNumber + 1;
221 highTestPointsResult =
222 polyCollisionChecker(*(it - 1), tf, obstacle, minTimeSection, nextIterationNumber, _traj);
223 if (highTestPointsResult.collisionType ==
224 NoCollision) // The section from the previous critical point until tf was feasible, meaning that all of
225 // the trajectory from midTime to tf does not collide with the obstacle
226 break;
227 else // Either a collision was detected between the previous critical point and tf, or the recursion became
228 // too deep (i.e. the time resolution too small) and the collision was indeterminable.
229 return highTestPointsResult;
230 }
231 }
232 // Both segments are free of collision
233
234 testResult.collisionType = NoCollision;
235 testResult.collisionTime = 100000; // A very large time to indicate no collision;
236 return testResult;
237}
238
239// Fit the points to a fifth degree polynomial in order to use the above collision checker.
240Trajectory polyFit3D(std::vector<std::vector<double>> states, std::vector<double> tValues)
241{ // state is a matrix of however many rows, but four columns (x, y, z, tF)
242 Eigen::VectorXd yValues(states.size());
243 Eigen::VectorXd xValues(states.size());
244 Eigen::VectorXd xCoeffs(5);
245 Eigen::VectorXd yCoeffs(5);
246 Eigen::VectorXd zCoeffs(5);
247
248 for (unsigned rows = 0; rows < states.size(); rows++)
249 {
250 xValues[rows] = states[rows][0];
251 yValues[rows] = states[rows][1];
252 }
253
254 xCoeffs = polyfit_Eigen(tValues, xValues, 5);
255 yCoeffs = polyfit_Eigen(tValues, yValues, 5);
256
257 std::vector<Vec3> coeffs;
258 // Change order of coefficients from 0->n to n->0
259 for (int i = 5; i >= 0; i--)
260 coeffs.push_back(Vec3(xCoeffs.coeffRef(i), yCoeffs.coeffRef(i), zCoeffs.coeffRef(i))); // Empty z coefficients
261
262 Trajectory traj(coeffs, tValues.front(), tValues.back());
263 return traj;
264}
265
266double distanceFunc(ompl::base::State *state1, ompl::base::State *state2)
267{
268 double distSqr = 0;
269 for (int i = 0; i < 6; i++)
270 {
271 distSqr += pow(state1->as<ompl::base::HybridStateSpace::StateType>()
273 ->values[i] -
276 ->values[i],
277 2);
278 }
279
280 return fabs(sqrt(distSqr));
281}
282
283bool collisionregion1(double x1, double x2)
284{ // True if collision
285 return x1 <= 4.5 && x1 >= 0.5 && x2 >= 1 && x2 <= 1.5;
286}
287
288bool collisionregion2(double x1, double x2)
289{ // True if collision
290 return x1 <= 4.5 && x1 >= 0.5 && x2 >= 1.4 && x2 <= 1.5;
291}
292
293bool collisionregion3(double x1, double x2)
294{ // True if collision
295 return x1 <= 4.5 && x1 >= 0.5 && x2 >= 2.5 && x2 <= 3.0;
296}
297
298bool collisionregion4(double x1, double x2)
299{ // True if collision
300 return x1 <= 4.5 && x1 >= 0.5 && x2 >= 2.9 && x2 <= 3;
301}
302
303bool collisionregion5(double x1, double x2)
304{ // True if collision
305 return x1 <= 0.5 && x1 >= 0.0 && x2 >= 1.5 && x2 <= 2.5;
306}
307
308bool collisionregion6(double x1, double x2)
309{ // True if collision
310 return x1 <= 4.5 && x1 >= 4.4 && x2 >= 1 && x2 <= 1.5;
311}
312
313bool collisionregion7(double x1, double x2)
314{ // True if collision
315 return x1 <= 4.5 && x1 >= 4.4 && x2 >= 2.5 && x2 <= 3;
316}
317
318bool Xu(double x1, double x2)
319{
320 if (x1 <= 4.4 && x1 >= 0 && x2 >= 1.1 && x2 <= 1.4)
321 return true;
322 if (x1 <= 0.4 && x1 >= 0 && x2 >= 1.1 && x2 <= 2.9)
323 return true;
324 if (x1 <= 4.4 && x1 >= 0 && x2 >= 2.6 && x2 <= 2.9)
325 return true;
326 return false;
327}
328
330bool jumpSet(ompl::control::HySST::Motion *motion)
331{
332 double x1 = motion->state->as<ompl::base::HybridStateSpace::StateType>()
333 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
334 ->values[0];
335 double x2 = motion->state->as<ompl::base::HybridStateSpace::StateType>()
336 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
337 ->values[1];
338 bool value = false;
339
340 // Jump state
341 if (Xu(x1, x2) || collisionregion1(x1, x2) || collisionregion2(x1, x2) || collisionregion3(x1, x2) ||
342 collisionregion4(x1, x2) || collisionregion5(x1, x2) || collisionregion6(x1, x2) || collisionregion7(x1, x2))
343 value = true;
344
345 return value;
346}
347
349bool flowSet(ompl::control::HySST::Motion *motion)
350{
351 return !jumpSet(motion);
352}
353
355bool unsafeSet(ompl::control::HySST::Motion *motion)
356{
357 std::vector<double> x_cur = {motion->state->as<ompl::base::HybridStateSpace::StateType>()
358 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
359 ->values[0],
361 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
362 ->values[1],
364 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
365 ->values[2],
367 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
368 ->values[3]};
369 if (x_cur[0] < 0.5 || x_cur[0] > 6 || x_cur[1] < 0 || x_cur[1] > 7)
370 return true;
371 return false;
372}
373
376ompl::base::State *discreteSimulator(ompl::base::State *x_cur, const ompl::control::Control *u,
377 ompl::base::State *new_state)
378{
379 (void)u;
380 double x1 = x_cur->as<ompl::base::HybridStateSpace::StateType>()
381 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
382 ->values[0];
383 double x2 = x_cur->as<ompl::base::HybridStateSpace::StateType>()
384 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
385 ->values[1];
386 double x3 = x_cur->as<ompl::base::HybridStateSpace::StateType>()
387 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
388 ->values[2];
389 double x4 = x_cur->as<ompl::base::HybridStateSpace::StateType>()
390 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
391 ->values[3];
392
393 double e = 0.43;
394 double kappa = 0.20;
395 double vn, vt, vnplus, vtplus;
396
397 if (collisionregion1(x1, x2) || collisionregion2(x1, x2) || collisionregion3(x1, x2) || collisionregion4(x1, x2))
398 {
399 vn = x3;
400 vt = x4;
401 vnplus = -e * vn;
402 vtplus = vt + kappa * (-e - 1) * std::atan(vt / vn) * vn;
403 x3 = vnplus;
404 x4 = vtplus;
405 }
406 else
407 {
408 vn = x4;
409 vt = x3;
410 vnplus = -e * vn;
411 vtplus = vt + kappa * (-e - 1) * std::atan(vt / vn) * vn;
412 x3 = vtplus;
413 x4 = vnplus;
414 }
415
417 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
418 ->values[0] = x1;
420 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
421 ->values[1] = x2;
423 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
424 ->values[2] = x3;
426 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
427 ->values[3] = x4;
429 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
430 ->values[4] = 0;
432 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
433 ->values[5] = 0;
434 return new_state;
435}
436
438bool collisionChecker(ompl::control::HySST::Motion *motion,
439 std::function<bool(ompl::control::HySST::Motion *motion)> obstacleSet,
440 ompl::base::State *new_state, double *collisionTime)
441{
442 (void)obstacleSet;
443 double ts = motion->solutionPair->at(0)
445 ->as<ompl::base::HybridTimeStateSpace::StateType>(1)
446 ->position;
447 double tf = new_state->as<ompl::base::HybridStateSpace::StateType>()
448 ->as<ompl::base::HybridTimeStateSpace::StateType>(1)
449 ->position;
450 std::vector<std::vector<double>> *propStepStatesDouble = new std::vector<std::vector<double>>();
451 for (unsigned int i = 0; i < motion->solutionPair->size(); i++)
452 {
453 std::vector<double> row;
454 for (int j = 0; j < 6; j++)
455 row.push_back(motion->solutionPair->at(i)
458 ->values[j]);
459 propStepStatesDouble->push_back(row);
460 }
461
462 std::vector<double> tValues;
463 for (unsigned int i = 0; i < motion->solutionPair->size(); i++)
464 {
465 tValues.push_back(motion->solutionPair->at(i)
468 ->position);
469 }
470
471 if (tValues.front() == tValues.back())
472 return false;
473
474 ts = tValues.front();
475 tf = tValues.back();
476
477 Trajectory _traj = polyFit3D(*propStepStatesDouble, tValues);
478
479 DetailedCollisionResult leftCollisionResult = polyCollisionChecker(ts, tf, leftRectPrism, 1e-03, 0, _traj);
480 DetailedCollisionResult topCollisionResult = polyCollisionChecker(ts, tf, topRectPrism, 1e-03, 0, _traj);
481 DetailedCollisionResult bottomCollisionResult = polyCollisionChecker(ts, tf, bottomRectPrism, 1e-03, 0, _traj);
482
483 DetailedCollisionResult trueCollisionResult; // Default is no collision
484 bool run = true;
485
486 if (leftCollisionResult.collisionType == Collision)
487 trueCollisionResult = leftCollisionResult;
488 else if (topCollisionResult.collisionType == Collision)
489 trueCollisionResult = topCollisionResult;
490 else if (bottomCollisionResult.collisionType == Collision)
491 trueCollisionResult = bottomCollisionResult;
492 else
493 {
494 run = false;
495 }
496
497 bool collision = run && trueCollisionResult.collisionType == Collision;
498 std::vector<double> collision_point;
499
500 if (collision)
501 {
502 Vec3 collision_point = _traj.GetValue(trueCollisionResult.collisionTime);
503 std::vector<Vec3> collision_vel_coeffs = _traj.GetDerivativeCoeffs();
504 collision_vel_coeffs.insert(collision_vel_coeffs.begin(), Vec3(0.0, 0.0, 0.0));
505 Trajectory _deriv_traj(collision_vel_coeffs, ts, tf);
506 Vec3 vel_collision_point = _deriv_traj.GetValue(trueCollisionResult.collisionTime);
507
508 // push back final motion with collision as last point
510 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
511 ->values[0] = collision_point[0];
513 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
514 ->values[1] = collision_point[1];
516 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
517 ->values[2] = vel_collision_point[0];
519 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
520 ->values[3] = vel_collision_point[1];
521 *collisionTime = trueCollisionResult.collisionTime;
522 }
523 return collision && run;
524}
525
528void flowODE(const ompl::control::ODESolver::StateType &x_cur, const ompl::control::Control *u,
530{
531 // Retrieve control values.
532 const double *input = u->as<ompl::control::RealVectorControlSpace::ControlType>()->values;
533 const double u_1 = input[0];
534 const double u_2 = input[1];
535
536 // Retrieve the current orientation of the multicopter.
537 const double v_1 = x_cur[2];
538 const double v_2 = x_cur[3];
539 const double a_1 = x_cur[4];
540 const double a_2 = x_cur[5];
541
542 // Ensure qdot is the same size as q. Zero out all values.
543 x_new.resize(x_cur.size(), 0);
544
545 x_new[0] = v_1;
546 x_new[1] = v_2;
547 x_new[2] = a_1;
548 x_new[3] = a_2;
549 x_new[4] = u_1;
550 x_new[5] = u_2;
551}
552
553// Define goal region as a ball of radius 0.2 centered at (5, 4)
554class EuclideanGoalRegion : public ompl::base::Goal
555{
556public:
557 EuclideanGoalRegion(const ompl::base::SpaceInformationPtr &si) : ompl::base::Goal(si)
558 {
559 }
560
561 virtual bool isSatisfied(const ompl::base::State *st, double *distance) const
562 {
563 // perform any operations and return a truth value
564 std::vector<double> goal = {5, 4};
565 double distSqr = 0;
566 for (int i = 0; i < 2; i++)
567 {
568 distSqr +=
569 pow(st->as<ompl::base::CompoundState>()->as<ompl::base::RealVectorStateSpace::StateType>(0)->values[i] -
570 goal[i],
571 2);
572 }
573
574 *distance = sqrt(distSqr);
575
576 if (*distance < 0.2)
577 return true;
578 else
579 return false;
580 }
581
582 virtual bool isSatisfied(const ompl::base::State *st) const
583 {
584 double distance = 0.0;
585 return isSatisfied(st, &distance);
586 }
587};
588
589int main()
590{
591 // Set the bounds of space
593 statespace->addDimension(1, 6.0);
594 statespace->addDimension(1, 5.0);
595 statespace->addDimension(-10, 10);
596 statespace->addDimension(-10, 10);
597 statespace->addDimension(-10, 10);
598 statespace->addDimension(-10, 10);
599
600 ompl::base::StateSpacePtr stateSpacePtr(statespace);
601 ompl::base::HybridStateSpace *hybridSpace = new ompl::base::HybridStateSpace(stateSpacePtr);
602 ompl::base::StateSpacePtr hybridSpacePtr(hybridSpace);
603
604 // Define control space
605 ompl::control::RealVectorControlSpace *flowControlSpace =
606 new ompl::control::RealVectorControlSpace(hybridSpacePtr, 2);
607 ompl::control::RealVectorControlSpace *jumpControlSpace =
608 new ompl::control::RealVectorControlSpace(hybridSpacePtr, 2);
609
610 ompl::base::RealVectorBounds flowBounds(2);
611 flowBounds.setLow(0, -0.5);
612 flowBounds.setLow(1, -1);
613 flowBounds.setHigh(0, 1);
614 flowBounds.setHigh(1, 1);
615 flowControlSpace->setBounds(flowBounds);
616
617 ompl::base::RealVectorBounds jumpBounds(2);
618 jumpBounds.setLow(0, 0);
619 jumpBounds.setLow(0, 0);
620 jumpBounds.setHigh(0, 0);
621 jumpBounds.setHigh(0, 0);
622 jumpControlSpace->setBounds(jumpBounds);
623
624 ompl::control::RealVectorControlUniformSampler flowControlSampler(flowControlSpace);
625 flowControlSpace->setControlSamplerAllocator(
626 [](const ompl::control::ControlSpace *space) -> ompl::control::ControlSamplerPtr
627 { return std::make_shared<ompl::control::RealVectorControlUniformSampler>(space); });
628
630 jumpControlSpace); // Doesn't do anything because the bounds for jump input are just [0, 0], but here for
631 // demonstration
632 jumpControlSpace->setControlSamplerAllocator(
633 [](const ompl::control::ControlSpace *space) -> ompl::control::ControlSamplerPtr
634 { return std::make_shared<ompl::control::RealVectorControlUniformSampler>(space); });
635
636 ompl::control::ControlSpacePtr flowControlSpacePtr(flowControlSpace);
637 ompl::control::ControlSpacePtr jumpControlSpacePtr(jumpControlSpace);
638
640 controlSpace->addSubspace(flowControlSpacePtr);
641 controlSpace->addSubspace(jumpControlSpacePtr);
642
643 ompl::control::ControlSpacePtr controlSpacePtr(controlSpace);
644
645 // Construct a space information instance for this state space
646 ompl::control::SpaceInformationPtr si(new ompl::control::SpaceInformation(hybridSpacePtr, controlSpacePtr));
647 ompl::control::ODESolverPtr odeSolver(new ompl::control::ODEBasicSolver<>(si, &flowODE));
648
649 si->setStatePropagator(ompl::control::ODESolver::getStatePropagator(odeSolver));
650 si->setPropagationStepSize(0.05);
651 si->setMinMaxControlDuration(1, 1);
652
653 si->setup();
654
655 // Set start state to be (1, 2)
656 ompl::base::ScopedState<> start(hybridSpacePtr);
658 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
659 ->values[0] = 1;
661 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
662 ->values[1] = 2;
664 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
665 ->values[2] = 0;
667 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
668 ->values[3] = 0;
670 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
671 ->values[4] = 0;
673 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
674 ->values[5] = 0;
675
676 std::shared_ptr<EuclideanGoalRegion> goal = std::make_shared<EuclideanGoalRegion>(si);
677
678 // Create a problem instance
679 ompl::base::ProblemDefinitionPtr pdef(new ompl::base::ProblemDefinition(si));
680
681 // Set the start and goal states
682 pdef->addStartState(start);
683 pdef->setGoal(goal);
684
685 ompl::control::HySST cHySST(si);
686
687 // Set parameters
688 cHySST.setProblemDefinition(pdef);
689 cHySST.setup();
690 cHySST.setDistanceFunction(distanceFunc);
691 cHySST.setDiscreteSimulator(discreteSimulator);
692 cHySST.setFlowSet(flowSet);
693 cHySST.setJumpSet(jumpSet);
694 cHySST.setTm(2);
695 cHySST.setFlowStepDuration(0.05);
696 cHySST.setUnsafeSet(unsafeSet);
697 cHySST.setCollisionChecker(collisionChecker);
698 cHySST.setSelectionRadius(0.2);
699 cHySST.setPruningRadius(0.1);
700 cHySST.setBatchSize(1);
701
702 // attempt to solve the planning problem within 30 seconds
705 double planTime = ompl::time::seconds(ompl::time::now() - t0);
706
707 if (solved) // If either approximate or exact solution has beenf ound
708 OMPL_INFORM("Solution found in %f seconds", planTime);
709 OMPL_INFORM("Solution status: %s", solved.asString().c_str());
710
711 // print path
712 pdef->getSolutionPath()->as<ompl::control::PathControl>()->printAsMatrix(std::cout);
713}
A rectangular prism.
Definition RectPrism.h:34
Represents a qunitic polynomial in 3D.
Definition Trajectory.h:35
Vec3 GetValue(double t) const
Returns the 3D position of the polynomial at a given time.
Definition Trajectory.h:87
std::vector< Vec3 > GetDerivativeCoeffs() const
Returns the coefficient of the time derivative of the trajectory.
Definition Trajectory.h:119
3D vector class with common vector operations.
Definition Vec3.h:36
Abstract definition of goals.
Definition Goal.h:63
A state space consisting of a space and a time component.
Definition of a problem to be solved. This includes the start state(s) for the system and a goal spec...
The lower and upper bounds for an Rn space.
double * values
The value of the actual vector in Rn.
A state space representing Rn. The distance function is the L2 norm.
void addDimension(double minBound=0.0, double maxBound=0.0)
Increase the dimensionality of the state space by 1. Optionally, bounds can be specified for this add...
Definition of a scoped state.
Definition ScopedState.h:57
ompl::base::State StateType
Define the type of state allocated by this space.
Definition StateSpace.h:78
Definition of an abstract state.
Definition State.h:50
const T * as() const
Cast this instance to a desired type.
Definition State.h:66
A control space to allow the composition of control spaces.
virtual void addSubspace(const ControlSpacePtr &component)
Adds a control space as a component of the compound control space.
A control space representing the space of applicable controls.
void setControlSamplerAllocator(const ControlSamplerAllocator &csa)
Set the sampler allocator to use.
Definition of an abstract control.
Definition Control.h:48
const T * as() const
Cast this instance to a desired type.
Definition Control.h:64
Representation of a motion.
Definition HySST.h:80
std::vector< base::State * > * solutionPair
The integration steps defining the edge of the motion, between the parent and child vertices.
Definition HySST.h:121
base::State * state
The state contained by the motion.
Definition HySST.h:109
Basic solver for ordinary differential equations of the type q' = f(q, u), where q is the current sta...
Definition ODESolver.h:200
std::vector< double > StateType
Portable data type for the state values.
Definition ODESolver.h:77
static StatePropagatorPtr getStatePropagator(ODESolverPtr solver, const PostPropagationEvent &postEvent=nullptr)
Retrieve a StatePropagator object that solves a system of ordinary differential equations defined by ...
Definition ODESolver.h:127
Definition of a control path.
Definition PathControl.h:61
A control space representing Rn.
void setBounds(const base::RealVectorBounds &bounds)
Set the bounds (min max values for each dimension) for the control.
Uniform sampler for the Rn state space.
Space information containing necessary information for planning with controls. setup() needs to be ca...
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition Console.h:68
PlannerTerminationCondition timedPlannerTerminationCondition(double duration)
Return a termination condition that will become true duration seconds in the future (wall-time).
std::chrono::system_clock::time_point point
Representation of a point in time.
Definition Time.h:52
point now()
Get the current time point.
Definition Time.h:58
duration seconds(double sec)
Return the time duration representing a given number of seconds.
Definition Time.h:64
A struct defining the properties of a plane.
Definition ConvexObj.h:31
Vec3 point
A point on the plane.
Definition ConvexObj.h:55
Vec3 normal
A unit vector normal to the plane.
Definition ConvexObj.h:56
A class to store the exit status of Planner::solve().
std::string asString() const
Return a string representation.