37#include "ompl/util/RandomNumbers.h"
38#include "ompl/util/Exception.h"
42#include <boost/math/constants/constants.hpp>
43#include <boost/scoped_ptr.hpp>
44#include <boost/random/uniform_on_sphere.hpp>
45#include <boost/random/variate_generator.hpp>
53 class RNGSeedGenerator
57 : firstSeed_(
std::chrono::duration_cast<
std::chrono::microseconds>(
58 std::chrono::system_clock::
now() -
std::chrono::system_clock::time_point::min())
61 , sDist_(1, 1000000000)
65 std::uint_fast32_t firstSeed()
67 std::lock_guard<std::mutex> slock(rngMutex_);
71 void setSeed(std::uint_fast32_t seed)
73 std::lock_guard<std::mutex> slock(rngMutex_);
76 if (someSeedsGenerated_)
78 OMPL_ERROR(
"Random number generation already started. Changing seed now will not lead to "
79 "deterministic sampling.");
89 if (someSeedsGenerated_)
91 OMPL_WARN(
"Random generator seed cannot be 0. Ignoring seed.");
94 OMPL_WARN(
"Random generator seed cannot be 0. Using 1 instead.");
100 std::uint_fast32_t nextSeed()
102 std::lock_guard<std::mutex> slock(rngMutex_);
103 someSeedsGenerated_ =
true;
104 return sDist_(sGen_);
108 bool someSeedsGenerated_{
false};
109 std::uint_fast32_t firstSeed_;
110 std::mutex rngMutex_;
111 std::ranlux24_base sGen_;
112 std::uniform_int_distribution<> sDist_;
115 std::once_flag g_once;
116 boost::scoped_ptr<RNGSeedGenerator> g_RNGSeedGenerator;
118 void initRNGSeedGenerator()
120 g_RNGSeedGenerator.reset(
new RNGSeedGenerator());
123 RNGSeedGenerator &getRNGSeedGenerator()
125 std::call_once(g_once, &initRNGSeedGenerator);
126 return *g_RNGSeedGenerator;
132class ompl::RNG::SphericalData
136 using container_type_t = std::vector<double>;
139 using spherical_dist_t = boost::uniform_on_sphere<double, container_type_t>;
142 using variate_generator_t = boost::variate_generator<std::mt19937 *, spherical_dist_t>;
145 SphericalData(std::mt19937 *generatorPtr) : generatorPtr_(generatorPtr){};
148 container_type_t generate(
unsigned int dim)
154 allocateDimension(dim);
157 return (*dimVector_.at(dim).second)();
164 for (
auto &i : dimVector_)
174 using dist_gen_pair_t = std::pair<std::shared_ptr<spherical_dist_t>, std::shared_ptr<variate_generator_t>>;
177 std::vector<dist_gen_pair_t> dimVector_;
180 std::mt19937 *generatorPtr_;
183 void growVector(
unsigned int dim)
186 while (dim >= dimVector_.size())
188 dimVector_.emplace_back();
192 void allocateDimension(
unsigned int dim)
195 if (dimVector_.at(dim).first ==
nullptr)
199 dimVector_.at(dim).first = std::make_shared<spherical_dist_t>(dim);
201 dimVector_.at(dim).second = std::make_shared<variate_generator_t>(generatorPtr_, *dimVector_.at(dim).first);
210 return getRNGSeedGenerator().firstSeed();
215 getRNGSeedGenerator().setSeed(seed);
219 : localSeed_(getRNGSeedGenerator().nextSeed())
220 , generator_(localSeed_)
221 , sphericalDataPtr_(
std::make_shared<SphericalData>(&generator_))
226 : localSeed_(localSeed), generator_(localSeed_), sphericalDataPtr_(
std::make_shared<SphericalData>(&generator_))
233 localSeed_ = localSeed;
236 generator_.seed(localSeed_);
241 sphericalDataPtr_->reset();
246 assert(r_min <= r_max);
248 const double mean = r_max - r_min;
249 double v = gaussian(mean, mean / focus);
253 double r = v >= 0.0 ? v + r_min : r_min;
254 return r > r_max ? r_max : r;
259 auto r = (int)floor(halfNormalReal((
double)r_min, (
double)(r_max) + 1.0, focus));
260 return (r > r_max) ? r_max : r;
267 double x0 = uniDist_(generator_);
268 double r1 = sqrt(1.0 - x0), r2 = sqrt(x0);
269 double t1 = 2.0 * boost::math::constants::pi<double>() * uniDist_(generator_),
270 t2 = 2.0 * boost::math::constants::pi<double>() * uniDist_(generator_);
271 double c1 = cos(t1), s1 = sin(t1);
272 double c2 = cos(t2), s2 = sin(t2);
282 value[0] = boost::math::constants::pi<double>() * (-2.0 * uniDist_(generator_) + 1.0);
283 value[1] = acos(1.0 - 2.0 * uniDist_(generator_)) - boost::math::constants::pi<double>() / 2.0;
284 value[2] = boost::math::constants::pi<double>() * (-2.0 * uniDist_(generator_) + 1.0);
291 v = sphericalDataPtr_->generate(v.size());
298 uniformNormalVector(v);
301 double radiusScale = r * std::pow(uniformReal(0.0, 1.0), 1.0 /
static_cast<double>(v.size()));
304 std::transform(v.begin(), v.end(), v.begin(), [radiusScale](
double x) { return radiusScale * x; });
312 std::vector<double> sphere(phsPtr->getDimension());
315 uniformNormalVector(sphere);
318 phsPtr->transform(&sphere[0], value);
325 std::vector<double> sphere(phsPtr->getDimension());
328 uniformInBall(1.0, sphere);
331 phsPtr->transform(&sphere[0], value);
void quaternion(double value[4])
Uniform random unit quaternion sampling. The computed value has the order (x,y,z,w)....
int halfNormalInt(int r_min, int r_max, double focus=3.0)
Generate a random integer using a half-normal distribution. The value is within specified bounds ([r_...
void eulerRPY(double value[3])
Uniform random sampling of Euler roll-pitch-yaw angles, each in the range (-pi, pi]....
void setLocalSeed(std::uint_fast32_t localSeed)
Set the seed used for the instance of a RNG. Use this function to ensure that an instance of an RNG g...
static void setSeed(std::uint_fast32_t seed)
Set the seed used to generate the seeds of each RNG instance. Use this function to ensure the same se...
void uniformNormalVector(std::vector< double > &v)
Uniform random sampling of a unit-length vector. I.e., the surface of an n-ball. The return variable ...
void uniformInBall(double r, std::vector< double > &v)
Uniform random sampling of the content of an n-ball, with a radius appropriately distributed between ...
void uniformProlateHyperspheroid(const std::shared_ptr< const ProlateHyperspheroid > &phsPtr, double value[])
Uniform random sampling of a prolate hyperspheroid, a special symmetric type of n-dimensional ellipse...
RNG()
Constructor. Always sets a different random seed.
static std::uint_fast32_t getSeed()
Get the seed used to generate the seeds of each RNG instance. Passing the returned value to setSeed()...
double halfNormalReal(double r_min, double r_max, double focus=3.0)
Generate a random real using a half-normal distribution. The value is within specified bounds [r_min,...
void uniformProlateHyperspheroidSurface(const std::shared_ptr< const ProlateHyperspheroid > &phsPtr, double value[])
Uniform random sampling of the surface of a prolate hyperspheroid, a special symmetric type of n-dime...
#define OMPL_ERROR(fmt,...)
Log a formatted error string.
#define OMPL_WARN(fmt,...)
Log a formatted warning string.
point now()
Get the current time point.