10 this->tstart_ = std::chrono::high_resolution_clock::now();
16 using namespace std::chrono;
17 auto t = high_resolution_clock::now() - this->tstart_;
18 auto d = duration_cast<duration<double>>(t);
31 assert(this->p_ != nullptr);
33 this->cc_ = this->p_->cc() + c;
49 RRTNode::p(RRTNode& p)
57 RRTNode::operator==(RRTNode const& n)
63 RRTS::min_gamma_eta() const
65 double ns = this->nodes_.size();
66 double gamma = pow(log(ns) / ns, 1.0 / 3.0);
67 return std::min(gamma, this->eta_);
71 RRTS::should_continue() const
73 return !this->should_finish();
77 RRTS::join_steered(RRTNode* f)
79 while (this->steered_.size() > 0) {
80 this->store(this->steered_.front());
81 RRTNode* t = &this->nodes_.back();
83 t->c(this->cost_build(*f, *t));
84 this->steered_.erase(this->steered_.begin());
98 RRTNode* f = this->nn_;
99 RRTNode* t = &this->steered_.front();
100 double cost = f->cc() + this->cost_build(*f, *t);
101 for (auto n: this->nv_) {
102 double nc = n->cc() + this->cost_build(*n, *t);
108 // Check if it's possible to drive from *f to *t. If not, then fallback
109 // to *f = nn_. This could be also solved by additional steer from *f to
110 // *t instead of the following code.
111 this->bc_.set_pose(*f);
112 if (!this->bc_.drivable(*t)) {
115 this->store(this->steered_.front());
116 t = &this->nodes_.back();
118 t->c(this->cost_build(*f, *t));
119 this->steered_.erase(this->steered_.begin());
126 RRTNode *f = &this->nodes_.back();
127 for (auto n: this->nv_) {
128 double fc = f->cc() + this->cost_build(*f, *n);
129 this->bc_.set_pose(*f);
130 bool drivable = this->bc_.drivable(*n);
131 if (drivable && fc < n->cc()) {
133 n->c(this->cost_build(*f, *n));
139 RRTS::goal_drivable_from(RRTNode const& f)
141 this->bc_.set_pose(f);
142 return this->bc_.drivable(this->goal_);
146 RRTS::store(RRTNode n)
148 this->nodes_.push_back(n);
152 RRTS::cost_build(RRTNode const& f, RRTNode const& t) const
158 RRTS::cost_search(RRTNode const& f, RRTNode const& t) const
160 return this->cost_build(f, t);
164 RRTS::find_nn(RRTNode const& t)
166 this->nn_ = &this->nodes_.front();
167 this->cost_ = this->cost_search(*this->nn_, t);
168 for (auto& f: this->nodes_) {
169 if (this->cost_search(f, t) < this->cost_) {
171 this->cost_ = this->cost_search(f, t);
177 RRTS::find_nv(RRTNode const& t)
180 this->cost_ = this->min_gamma_eta();
181 for (auto& f: this->nodes_) {
182 if (this->cost_search(f, t) < this->cost_) {
183 this->nv_.push_back(&f);
192 RRTNode *g = &this->goal_;
193 if (g->p() == nullptr) {
196 while (g != nullptr && this->path_.size() < 10000) {
199 * There shouldn't be this->path_.size() < 10000 condition.
200 * However, the RRTS::compute_path() called from
201 * RRTExt13::compute_path tends to re-allocate this->path_
202 * infinitely. There's probably node->p() = &node somewhere...
204 this->path_.push_back(g);
207 std::reverse(this->path_.begin(), this->path_.end());
210 RRTS::RRTS() : gen_(std::random_device{}())
212 this->nodes_.reserve(4000000);
213 this->steered_.reserve(1000);
214 this->path_.reserve(10000);
215 this->nv_.reserve(1000);
216 this->store(RRTNode()); // root
226 RRTS::icnt(unsigned int i)
234 return this->ter_.scnt();
242 for (auto n: this->path_) {
243 jvo["path"][i][0] = n->x();
244 jvo["path"][i][1] = n->y();
245 jvo["path"][i][2] = n->h();
248 jvo["goal_cc"] = this->goal_.cc();
249 jvo["time"] = this->time_;
254 RRTS::json(Json::Value jvi)
256 assert(jvi["init"] != Json::nullValue);
257 assert(jvi["goal"] != Json::nullValue);
258 assert(jvi["obst"] != Json::nullValue);
259 this->nodes_.front().x(jvi["init"][0].asDouble());
260 this->nodes_.front().y(jvi["init"][1].asDouble());
261 this->nodes_.front().h(jvi["init"][2].asDouble());
262 this->goal_.x(jvi["goal"][0].asDouble());
263 this->goal_.y(jvi["goal"][1].asDouble());
264 this->goal_.b(jvi["goal"][2].asDouble());
265 if (jvi["goal"].size() == 4) {
266 this->goal_.e(jvi["goal"][3].asDouble());
268 this->goal_.e(jvi["goal"][2].asDouble());
275 if (this->icnt_ == 0) {
279 auto rs = this->sample();
281 this->steer(this->nn(), rs);
282 if (this->collide_steered()) {
283 return this->should_continue();
285 this->find_nv(this->steered_.front());
286 if (!this->connect()) {
287 return this->should_continue();
290 unsigned int ss = this->steered_.size();
291 this->join_steered(&this->nodes_.back());
292 RRTNode* just_added = &this->nodes_.back();
293 while (ss > 0 && just_added->p() != nullptr) {
294 //if (!this->goal_drivable_from(*just_added)) {
296 // just_added = just_added->p();
299 this->steer(*just_added, this->goal_);
300 if (this->collide_steered()) {
302 just_added = just_added->p();
305 this->join_steered(just_added);
306 bool gn = this->goal_.edist(this->nodes_.back()) < this->eta_;
307 bool gd = this->goal_drivable_from(this->nodes_.back());
309 double nc = this->cost_build(this->nodes_.back(),
311 double ncc = this->nodes_.back().cc() + nc;
312 if (this->goal_.p() == nullptr
313 || ncc < this->goal_.cc()) {
314 this->goal_.p(this->nodes_.back());
316 this->compute_path();
320 just_added = just_added->p();
323 ////if (!this->goal_drivable_from(this->nodes_.back())) {
324 //// return this->should_continue();
326 //this->steer(this->nodes_.back(), this->goal_);
327 //if (this->collide_steered()) {
328 // return this->should_continue();
330 //this->join_steered(&this->nodes_.back());
331 //bool gn = this->goal_.edist(this->nodes_.back()) < this->eta_;
332 //bool gd = this->goal_drivable_from(this->nodes_.back());
334 // double nc = this->cost_build(this->nodes_.back(), this->goal_);
335 // double ncc = this->nodes_.back().cc() + nc;
336 // if (this->goal_.p() == nullptr || ncc < this->goal_.cc()) {
337 // this->goal_.p(this->nodes_.back());
338 // this->goal_.c(nc);
339 // this->compute_path();
342 this->time_ = this->ter_.scnt();
343 return this->should_continue();
349 this->goal_ = RRTGoal();
351 this->steered_.clear();
352 this->nodes_.erase(this->nodes_.begin() + 1, this->nodes_.end());