Loading...
Searching...
No Matches
BouncingBallPlanning.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 "ompl/control/planners/rrt/HyRRT.h"
38#include "ompl/base/StateSpace.h"
39#include "ompl/control/spaces/RealVectorControlSpace.h"
40#include "ompl/base/spaces/HybridStateSpace.h"
41#include "ompl/control/ODESolver.h"
42
44double distanceFunc(ompl::base::State *state1, ompl::base::State *state2)
45{
46 double dist = 0;
47 dist = sqrt(pow(state1->as<ompl::base::HybridStateSpace::StateType>()
49 ->values[0] -
52 ->values[0],
53 2) +
56 ->values[1] -
59 ->values[1],
60 2));
61 return fabs(dist);
62}
63
65bool jumpSet(ompl::control::HyRRT::Motion *motion)
66{
67 auto *motion_state =
68 motion->state->as<ompl::base::CompoundState>()->as<ompl::base::RealVectorStateSpace::StateType>(0);
69 double velocity = motion_state->values[1];
70 double pos_cur = motion_state->values[0];
71
72 if (pos_cur <= 0 && velocity <= 0)
73 return true;
74 else
75 return false;
76}
77
79bool flowSet(ompl::control::HyRRT::Motion *motion)
80{
81 return !jumpSet(motion);
82}
83
85bool unsafeSet(ompl::control::HyRRT::Motion *motion)
86{
87 double u = motion->control->as<ompl::control::RealVectorControlSpace::ControlType>()->values[0];
88 if (u > 5 || u < 0)
89 return true;
90 return false;
91}
92
95void flowODE(const ompl::control::ODESolver::StateType &x_cur, const ompl::control::Control *u,
97{
98 (void)u; // No control is applied when a state is in the flow set
99
100 // Ensure qdot is the same size as q. Zero out all values.
101 x_new.resize(x_cur.size(), 0);
102
103 x_new[0] = x_cur[1]; // x-dot
104 x_new[1] = x_cur[2]; // v-dot
105 x_new[2] = 0; // a-dot
106}
107
109ompl::base::State *discreteSimulator(ompl::base::State *x_cur, const ompl::control::Control *u,
110 ompl::base::State *new_state)
111{
112 double velocity = -0.8 * x_cur->as<ompl::base::HybridStateSpace::StateType>()
113 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
114 ->values[1];
115
117 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
118 ->values[0] = x_cur->as<ompl::base::HybridStateSpace::StateType>()
119 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
120 ->values[0];
122 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
123 ->values[1] = velocity - u->as<ompl::control::RealVectorControlSpace::ControlType>()->values[0];
125 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
126 ->values[2] = x_cur->as<ompl::base::HybridStateSpace::StateType>()
127 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
128 ->values[2];
129 return new_state;
130}
131
132// Define goal region as a ball of radius 0.1 centered at {height, velocity} = {0, 0}
133class EuclideanGoalRegion : public ompl::base::Goal
134{
135public:
136 EuclideanGoalRegion(const ompl::base::SpaceInformationPtr &si) : ompl::base::Goal(si)
137 {
138 }
139
140 virtual bool isSatisfied(const ompl::base::State *st, double *distance) const
141 {
142 // perform any operations and return a truth value
143 std::vector<double> goal = {0, 0};
144 double distSqr = 0;
145 for (int i = 0; i < 2; i++)
146 {
147 distSqr +=
148 pow(st->as<ompl::base::CompoundState>()->as<ompl::base::RealVectorStateSpace::StateType>(0)->values[i] -
149 goal[i],
150 2);
151 }
152
153 *distance = sqrt(distSqr);
154
155 if (*distance < 0.1)
156 return true;
157 else
158 return false;
159 }
160
161 virtual bool isSatisfied(const ompl::base::State *st) const
162 {
163 double distance = 0.0;
164 return isSatisfied(st, &distance);
165 }
166};
167
168int main()
169{
170 // Set the bounds of space
172 statespace->addDimension(-10, 10);
173 statespace->addDimension(-10, 10);
174 statespace->addDimension(-10, 5);
175 ompl::base::StateSpacePtr stateSpacePtr(statespace);
176
177 ompl::base::HybridStateSpace *hybridSpace = new ompl::base::HybridStateSpace(stateSpacePtr);
178 ompl::base::StateSpacePtr hybridSpacePtr(hybridSpace);
179
180 // Define control space
181 ompl::control::RealVectorControlSpace *flowControlSpace =
182 new ompl::control::RealVectorControlSpace(hybridSpacePtr, 1);
183 ompl::control::RealVectorControlSpace *jumpControlSpace =
184 new ompl::control::RealVectorControlSpace(hybridSpacePtr, 1);
185
186 ompl::base::RealVectorBounds flowBounds(1);
187 flowBounds.setLow(0, 0);
188 flowBounds.setHigh(0, 0);
189 flowControlSpace->setBounds(flowBounds);
190
191 ompl::base::RealVectorBounds jumpBounds(1);
192 jumpBounds.setLow(0, 0);
193 jumpBounds.setHigh(0, 5);
194 jumpControlSpace->setBounds(jumpBounds);
195
196 ompl::control::RealVectorControlUniformSampler flowControlSampler(flowControlSpace);
197 flowControlSpace->setControlSamplerAllocator(
198 [](const ompl::control::ControlSpace *space) -> ompl::control::ControlSamplerPtr
199 { return std::make_shared<ompl::control::RealVectorControlUniformSampler>(space); });
200
202 jumpControlSpace); // Doesn't do anything because the bounds for jump input are just [0, 0], but here for
203 // demonstration
204 jumpControlSpace->setControlSamplerAllocator(
205 [](const ompl::control::ControlSpace *space) -> ompl::control::ControlSamplerPtr
206 { return std::make_shared<ompl::control::RealVectorControlUniformSampler>(space); });
207
208 ompl::control::ControlSpacePtr flowControlSpacePtr(flowControlSpace);
209 ompl::control::ControlSpacePtr jumpControlSpacePtr(jumpControlSpace);
210
212 controlSpace->addSubspace(flowControlSpacePtr);
213 controlSpace->addSubspace(jumpControlSpacePtr);
214
215 ompl::control::ControlSpacePtr controlSpacePtr(controlSpace);
216
217 // Construct a space information instance for this state space
218 ompl::control::SpaceInformationPtr si(new ompl::control::SpaceInformation(hybridSpacePtr, controlSpacePtr));
219 ompl::control::ODESolverPtr odeSolver(new ompl::control::ODEBasicSolver<>(si, &flowODE));
220
221 si->setStatePropagator(ompl::control::ODESolver::getStatePropagator(odeSolver));
222 si->setPropagationStepSize(0.01);
223 si->setup();
224
225 // Set start state to be 1 unit above the floor with zero velocity and gravitaional acceleration of 9.81
226 ompl::base::ScopedState<> start(hybridSpacePtr);
228 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
229 ->values[0] = 1;
231 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
232 ->values[1] = 0;
234 ->as<ompl::base::RealVectorStateSpace::StateType>(0)
235 ->values[2] = -9.81;
236
237 // Set goal state to be on floor with a zero velocity, and tolerance of 0.1
238 std::shared_ptr<EuclideanGoalRegion> goal = std::make_shared<EuclideanGoalRegion>(si);
239
240 // Create a problem instance
241 ompl::base::ProblemDefinitionPtr pdef(new ompl::base::ProblemDefinition(si));
242
243 // Set the start and goal states
244 pdef->addStartState(start);
245 pdef->setGoal(goal);
246
247 ompl::control::HyRRT cHyRRT(si);
248
249 // Set the problem instance for our planner to solve
250 cHyRRT.setProblemDefinition(pdef);
251 cHyRRT.setup();
252
253 // Set parameters
254 cHyRRT.setDiscreteSimulator(discreteSimulator);
255 cHyRRT.setDistanceFunction(distanceFunc);
256 cHyRRT.setFlowSet(flowSet);
257 cHyRRT.setJumpSet(jumpSet);
258 cHyRRT.setTm(0.5);
259 cHyRRT.setFlowStepDuration(0.01);
260 cHyRRT.setUnsafeSet(unsafeSet);
261
262 // attempt to solve the planning problem within 2 seconds
265 double planTime = ompl::time::seconds(ompl::time::now() - t0);
266
267 if (solved) // If either approximate or exact solution has beenf ound
268 OMPL_INFORM("Solution found in %f seconds", planTime);
269 OMPL_INFORM("Solution status: %s", solved.asString().c_str());
270
271 // print path
272 pdef->getSolutionPath()->as<ompl::control::PathControl>()->printAsMatrix(std::cout);
273}
Definition of a compound state.
Definition State.h:87
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 in the search tree.
Definition HyRRT.h:100
control::Control * control
The control contained by the motion.
Definition HyRRT.h:128
base::State * state
The state contained by the motion.
Definition HyRRT.h:114
Hybrid Rapidly-exploring Random Trees.
Definition HyRRT.h:77
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 class to store the exit status of Planner::solve().
std::string asString() const
Return a string representation.