Loading...
Searching...
No Matches
PathControl.cpp
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2010, Rice University
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 Rice University nor the names of its
18 * 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: Ioan Sucan */
36
37#include "ompl/control/PathControl.h"
38#include "ompl/control/spaces/DiscreteControlSpace.h"
39#include "ompl/geometric/PathGeometric.h"
40#include "ompl/base/samplers/UniformValidStateSampler.h"
41#include "ompl/base/OptimizationObjective.h"
42#include "ompl/util/Exception.h"
43#include "ompl/util/Console.h"
44#include <numeric>
45#include <cmath>
46
47namespace
48{
49 unsigned int getNumberOfDiscreteControls(const ompl::control::ControlSpace *cs)
50 {
51 if (cs->isCompound())
52 {
53 const auto *ccs = cs->as<ompl::control::CompoundControlSpace>();
54 unsigned int num = 0;
55 for (unsigned int i = 0; i < ccs->getSubspaceCount(); ++i)
56 num += getNumberOfDiscreteControls(ccs->getSubspace(i).get());
57
58 return num;
59 }
60 if (dynamic_cast<const ompl::control::DiscreteControlSpace *>(cs) != nullptr)
61 return 1;
62 return 0;
63 }
64
65 void printDiscreteControls(std::ostream &out, const ompl::control::ControlSpace *cs,
67 {
68 if (cs->isCompound())
69 {
70 const auto *ccs = cs->as<ompl::control::CompoundControlSpace>();
71 for (unsigned int i = 0; i < ccs->getSubspaceCount(); ++i)
72 printDiscreteControls(out, ccs->getSubspace(i).get(),
74 }
75 else if (dynamic_cast<const ompl::control::DiscreteControlSpace *>(cs) != nullptr)
77 }
78} // namespace
79
80ompl::control::PathControl::PathControl(const base::SpaceInformationPtr &si) : base::Path(si)
81{
82 if (dynamic_cast<const SpaceInformation *>(si_.get()) == nullptr)
83 throw Exception("Cannot create a path with controls from a space that does not support controls");
84}
85
87{
88 copyFrom(path);
89}
90
99
101{
102 freeMemory();
103 si_ = other.si_;
104 copyFrom(other);
105 return *this;
106}
107
109{
110 states_.resize(other.states_.size());
111 controls_.resize(other.controls_.size());
112
113 for (unsigned int i = 0; i < states_.size(); ++i)
114 states_[i] = si_->cloneState(other.states_[i]);
115
116 const auto *si = static_cast<const SpaceInformation *>(si_.get());
117 for (unsigned int i = 0; i < controls_.size(); ++i)
118 controls_[i] = si->cloneControl(other.controls_[i]);
119
121}
122
123ompl::base::Cost ompl::control::PathControl::cost(const base::OptimizationObjectivePtr &opt) const
124{
125 if (states_.empty())
126 return opt->identityCost();
127 // Compute path cost by accumulating the cost along the path
128 base::Cost cost(opt->initialCost(states_.front()));
129 const auto *si = static_cast<const SpaceInformation *>(si_.get());
130 const double dt = si->getPropagationStepSize();
131 for (std::size_t i = 1; i < states_.size(); ++i)
132 {
133 const auto steps = static_cast<unsigned int>(std::llround(controlDurations_[i - 1] / dt));
134 cost = opt->combineCosts(cost, opt->controlMotionCost(states_[i - 1], controls_[i - 1], steps, states_[i]));
135 }
136 cost = opt->combineCosts(cost, opt->terminalCost(states_.back()));
137 return cost;
138}
139
141{
142 return std::accumulate(controlDurations_.begin(), controlDurations_.end(), 0.0);
143}
144
145void ompl::control::PathControl::print(std::ostream &out) const
146{
147 const auto *si = static_cast<const SpaceInformation *>(si_.get());
148 double res = si->getPropagationStepSize();
149 out << "Control path with " << states_.size() << " states" << std::endl;
150 for (unsigned int i = 0; i < controls_.size(); ++i)
151 {
152 out << "At state ";
153 si_->printState(states_[i], out);
154 out << " apply control ";
155 si->printControl(controls_[i], out);
156 out << " for " << (int)floor(0.5 + controlDurations_[i] / res) << " steps" << std::endl;
157 }
158 out << "Arrive at state ";
159 si_->printState(states_[controls_.size()], out);
160 out << std::endl;
161}
162
163void ompl::control::PathControl::printAsMatrix(std::ostream &out) const
164{
165 if (states_.empty())
166 return;
167 const base::StateSpace *space(si_->getStateSpace().get());
168 const auto *si = static_cast<const SpaceInformation *>(si_.get());
169 const ControlSpace *cspace(si->getControlSpace().get());
170 std::vector<double> reals;
171
172 space->copyToReals(reals, states_[0]);
173 std::copy(reals.begin(), reals.end(), std::ostream_iterator<double>(out, " "));
174 if (controls_.empty())
175 return;
176
177 const ControlSpace *cs = static_cast<const SpaceInformation *>(si_.get())->getControlSpace().get();
178 unsigned int n = 0, m = getNumberOfDiscreteControls(cs);
179 double *val;
180 while ((val = cspace->getValueAddressAtIndex(controls_[0], n)) != nullptr)
181 ++n;
182 for (unsigned int i = 0; i < n + m; ++i)
183 out << "0 ";
184 out << '0' << std::endl;
185 for (unsigned int i = 0; i < controls_.size(); ++i)
186 {
187 space->copyToReals(reals, states_[i + 1]);
188 std::copy(reals.begin(), reals.end(), std::ostream_iterator<double>(out, " "));
189 // print discrete controls
190 printDiscreteControls(out, cs, controls_[i]);
191 // print real-valued controls
192 for (unsigned int j = 0; j < n; ++j)
193 out << *cspace->getValueAddressAtIndex(controls_[i], j) << ' ';
194 out << controlDurations_[i] << std::endl;
195 }
196}
197
199{
200 if (states_.size() <= controls_.size())
201 {
202 OMPL_ERROR("Interpolation not performed. Number of states in the path should be strictly greater than the "
203 "number of controls.");
204 return;
205 }
206
207 const auto *si = static_cast<const SpaceInformation *>(si_.get());
208 std::vector<base::State *> newStates;
209 std::vector<Control *> newControls;
210 std::vector<double> newControlDurations;
211
212 double res = si->getPropagationStepSize();
213 for (unsigned int i = 0; i < controls_.size(); ++i)
214 {
215 auto steps = (int)floor(0.5 + controlDurations_[i] / res);
216 assert(steps >= 0);
217 if (steps <= 1)
218 {
219 newStates.push_back(states_[i]);
220 newControls.push_back(controls_[i]);
221 newControlDurations.push_back(controlDurations_[i]);
222 continue;
223 }
224 std::vector<base::State *> istates;
225 si->propagate(states_[i], controls_[i], steps, istates, true);
226 // last state is already in the non-interpolated path
227 if (!istates.empty())
228 {
229 si_->freeState(istates.back());
230 istates.pop_back();
231 }
232 newStates.push_back(states_[i]);
233 newStates.insert(newStates.end(), istates.begin(), istates.end());
234 newControls.push_back(controls_[i]);
235 newControlDurations.push_back(res);
236 for (int j = 1; j < steps; ++j)
237 {
238 newControls.push_back(si->cloneControl(controls_[i]));
239 newControlDurations.push_back(res);
240 }
241 }
242 newStates.push_back(states_[controls_.size()]);
243 states_.swap(newStates);
244 controls_.swap(newControls);
245 controlDurations_.swap(newControlDurations);
246}
247
249{
250 if (controls_.empty())
251 {
252 if (states_.size() == 1)
253 return si_->isValid(states_[0]);
254 return false;
255 }
256
257 bool valid = true;
258 const auto *si = static_cast<const SpaceInformation *>(si_.get());
259 double res = si->getPropagationStepSize();
260 base::State *next = si_->allocState();
261 for (unsigned int i = 0; valid && i < controls_.size(); ++i)
262 {
263 auto steps = (unsigned int)floor(0.5 + controlDurations_[i] / res);
264 if (!si->isValid(states_[i]) || si->propagateWhileValid(states_[i], controls_[i], steps, next) != steps ||
265 si->distance(next, states_[i + 1]) > std::numeric_limits<float>::epsilon())
266 valid = false;
267 }
268 si_->freeState(next);
269
270 return valid;
271}
272
274{
275 states_.push_back(si_->cloneState(state));
276}
277
278void ompl::control::PathControl::append(const base::State *state, const Control *control, double duration)
279{
280 const auto *si = static_cast<const SpaceInformation *>(si_.get());
281 states_.push_back(si->cloneState(state));
282 controls_.push_back(si->cloneControl(control));
283 controlDurations_.push_back(duration);
284}
285
287{
288 freeMemory();
289 states_.resize(2);
290 controlDurations_.resize(1);
291 controls_.resize(1);
292
293 const auto *si = static_cast<const SpaceInformation *>(si_.get());
294 states_[0] = si->allocState();
295 states_[1] = si->allocState();
296 controls_[0] = si->allocControl();
297
298 base::StateSamplerPtr ss = si->allocStateSampler();
299 ss->sampleUniform(states_[0]);
301 cs->sample(controls_[0], states_[0]);
302 unsigned int steps = cs->sampleStepCount(si->getMinControlDuration(), si->getMaxControlDuration());
303 controlDurations_[0] = steps * si->getPropagationStepSize();
304 si->propagate(states_[0], controls_[0], steps, states_[1]);
305}
306
308{
309 freeMemory();
310 states_.resize(2);
311 controlDurations_.resize(1);
312 controls_.resize(1);
313
314 const auto *si = static_cast<const SpaceInformation *>(si_.get());
315 states_[0] = si->allocState();
316 states_[1] = si->allocState();
317 controls_[0] = si->allocControl();
318
320 auto uvss(std::make_shared<base::UniformValidStateSampler>(si));
321 uvss->setNrAttempts(attempts);
322 bool ok = false;
323 for (unsigned int i = 0; i < attempts; ++i)
324 if (uvss->sample(states_[0]))
325 {
326 cs->sample(controls_[0], states_[0]);
327 unsigned int steps = cs->sampleStepCount(si->getMinControlDuration(), si->getMaxControlDuration());
328 controlDurations_[0] = steps * si->getPropagationStepSize();
329 if (si->propagateWhileValid(states_[0], controls_[0], steps, states_[1]) == steps)
330 {
331 ok = true;
332 break;
333 }
334 }
335
336 if (!ok)
337 {
338 freeMemory();
339 states_.clear();
340 controls_.clear();
341 controlDurations_.clear();
342 }
343 return ok;
344}
345
347{
348 for (auto &state : states_)
349 si_->freeState(state);
350 const auto *si = static_cast<const SpaceInformation *>(si_.get());
351 for (auto &control : controls_)
352 si->freeControl(control);
353}
The exception type for ompl.
Definition Exception.h:47
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Definition Cost.h:48
SpaceInformationPtr si_
The space information this path is part of.
Definition Path.h:123
Representation of a space in which planning can be performed. Topology specific sampling,...
Definition StateSpace.h:71
virtual void copyToReals(std::vector< double > &reals, const State *source) const
Copy all the real values from a state source to the array reals using getValueAddressAtLocation().
Definition of an abstract state.
Definition State.h:50
A control space to allow the composition of control spaces.
Definition of a compound control.
Definition Control.h:85
Control ** components
The components that make up a compound control.
Definition Control.h:118
A shared pointer wrapper for ompl::control::ControlSampler.
A control space representing the space of applicable controls.
virtual ControlSamplerPtr allocControlSampler() const
Allocate an instance of the control sampler for this space. This sampler will be allocated with the s...
virtual bool isCompound() const
Check if the control space is compound.
T * as()
Cast this instance to a desired type.
virtual double * getValueAddressAtIndex(Control *control, unsigned int index) const
Many controls contain a number of double values. This function provides a means to get the memory add...
Definition of an abstract control.
Definition Control.h:48
const T * as() const
Cast this instance to a desired type.
Definition Control.h:64
A space representing discrete controls; i.e. there are a small number of discrete controls the system...
Definition of a control path.
Definition PathControl.h:61
void print(std::ostream &out) const override
Print the path to a stream.
bool check() const override
Check if the path is valid.
base::Cost cost(const base::OptimizationObjectivePtr &opt) const override
Not yet implemented.
bool randomValid(unsigned int attempts)
Set this path to a random valid segment. Sample attempts times for valid segments....
void append(const base::State *state)
Append state to the end of the path; it is assumed state is the first state, so no control is applied...
void random()
Set this path to a random segment.
PathControl & operator=(const PathControl &other)
Assignment operator.
void copyFrom(const PathControl &other)
Copy the content of a path to this one.
double length() const override
The path length (sum of control durations).
virtual void printAsMatrix(std::ostream &out) const
Print the path as a real-valued matrix where the i-th row represents the i-th state along the path,...
PathControl(const base::SpaceInformationPtr &si)
Constructor.
std::vector< double > controlDurations_
The duration of the control applied at each state. This array contains one element less than the list...
void freeMemory()
Free the memory allocated by the path.
std::vector< base::State * > states_
The list of states that make up the path.
std::vector< Control * > controls_
The control applied at each state. This array contains one element less than the list of states.
geometric::PathGeometric asGeometric() const
Convert this path into a geometric path (interpolation is performed and then states are copied).
void interpolate()
Make the path such that all controls are applied for a single time step (computes intermediate states...
Space information containing necessary information for planning with controls. setup() needs to be ca...
const ControlSpacePtr & getControlSpace() const
Get the control space.
double getPropagationStepSize() const
Propagation is performed at integer multiples of a specified step size. This function returns the val...
void freeControl(Control *control) const
Free the memory of a control.
Definition of a geometric path.
std::vector< base::State * > & getStates()
Get the states that make up the path (as a reference, so it can be modified, hence the function is no...
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
Definition Console.h:64
This namespace contains sampling based planning routines shared by both planning under geometric cons...
This namespace contains sampling based planning routines used by planning under differential constrai...
Definition Control.h:45