2 * SPDX-FileCopyrightText: 2021 Jiri Vlasak <jiri.vlasak.2@cvut.cz>
4 * SPDX-License-Identifier: GPL-3.0-only
16 this->tstart_ = std::chrono::high_resolution_clock::now();
22 using namespace std::chrono;
23 auto t = high_resolution_clock::now() - this->tstart_;
24 auto d = duration_cast<duration<double>>(t);
37 assert(this->p_ != nullptr);
39 this->cc_ = this->p_->cc() + c;
55 RRTNode::p(RRTNode& p)
69 RRTNode::cusp(RRTNode const& p)
71 this->cusp_ = p.cusp();
72 if (this->sp() != p.sp() || this->sp() == 0.0) {
78 RRTNode::operator==(RRTNode const& n)
84 RRTS::recompute_cc(RRTNode* g)
87 while (g != nullptr) {
88 this->path_.push_back(g);
91 std::reverse(this->path_.begin(), this->path_.end());
92 for (unsigned int i = 1; i < this->path_.size(); i++) {
93 this->path_[i]->c(this->cost_build(*this->path_[i - 1],
99 RRTS::recompute_path_cc()
101 this->recompute_cc(&this->goal_);
105 RRTS::min_gamma_eta() const
107 double ns = this->nodes_.size();
108 double gamma = pow(log(ns) / ns, 1.0 / 3.0);
109 return std::min(gamma, this->eta_);
113 RRTS::should_continue() const
115 return !this->should_finish();
119 RRTS::join_steered(RRTNode* f)
121 while (this->steered_.size() > 0) {
122 this->store(this->steered_.front());
123 RRTNode* t = &this->nodes_.back();
125 t->c(this->cost_build(*f, *t));
127 this->steered_.erase(this->steered_.begin());
141 RRTNode* f = this->nn_;
142 RRTNode* t = &this->steered_.front();
143 double cost = f->cc() + this->cost_build(*f, *t);
144 for (auto n: this->nv_) {
145 double nc = n->cc() + this->cost_build(*n, *t);
151 // Check if it's possible to drive from *f to *t. If not, then fallback
152 // to *f = nn_. This could be also solved by additional steer from *f to
153 // *t instead of the following code.
154 this->bc_.set_pose(*f);
155 if (!this->bc_.drivable(*t)) {
158 this->store(this->steered_.front());
159 t = &this->nodes_.back();
161 t->c(this->cost_build(*f, *t));
163 this->steered_.erase(this->steered_.begin());
170 RRTNode *f = &this->nodes_.back();
171 for (auto n: this->nv_) {
172 double fc = f->cc() + this->cost_build(*f, *n);
173 this->bc_.set_pose(*f);
174 bool drivable = this->bc_.drivable(*n);
175 if (drivable && fc < n->cc()) {
177 n->c(this->cost_build(*f, *n));
183 RRTS::goal_drivable_from(RRTNode const& f)
185 this->bc_.set_pose(f);
186 return this->bc_.drivable(this->goal_);
190 RRTS::store(RRTNode n)
192 this->nodes_.push_back(n);
196 RRTS::cost_build(RRTNode const& f, RRTNode const& t) const
202 RRTS::cost_search(RRTNode const& f, RRTNode const& t) const
204 return this->cost_build(f, t);
208 RRTS::find_nn(RRTNode const& t)
210 this->nn_ = &this->nodes_.front();
211 this->cost_ = this->cost_search(*this->nn_, t);
212 for (auto& f: this->nodes_) {
213 if (this->cost_search(f, t) < this->cost_) {
215 this->cost_ = this->cost_search(f, t);
221 RRTS::find_nv(RRTNode const& t)
224 this->cost_ = this->min_gamma_eta();
225 for (auto& f: this->nodes_) {
226 if (this->cost_search(f, t) < this->cost_) {
227 this->nv_.push_back(&f);
236 RRTNode *g = &this->goal_;
237 if (g->p() == nullptr) {
240 while (g != nullptr && this->path_.size() < 10000) {
243 * There shouldn't be this->path_.size() < 10000 condition.
244 * However, the RRTS::compute_path() called from
245 * RRTExt13::compute_path tends to re-allocate this->path_
246 * infinitely. There's probably node->p() = &node somewhere...
248 this->path_.push_back(g);
251 std::reverse(this->path_.begin(), this->path_.end());
254 RRTS::RRTS() : gen_(std::random_device{}()), goal_(0.0, 0.0, 0.0, 0.0)
256 this->nodes_.reserve(4000000);
257 this->steered_.reserve(1000);
258 this->path_.reserve(10000);
259 this->nv_.reserve(1000);
260 this->store(RRTNode()); // root
270 RRTS::icnt(unsigned int i)
278 return this->ter_.scnt();
286 for (auto n: this->path_) {
287 jvo["path"][i][0] = n->x();
288 jvo["path"][i][1] = n->y();
289 jvo["path"][i][2] = n->h();
292 jvo["goal_cc"] = this->goal_.cc();
293 jvo["time"] = this->time_;
298 RRTS::json(Json::Value jvi)
300 assert(jvi["init"] != Json::nullValue);
301 assert(jvi["goal"] != Json::nullValue);
302 this->nodes_.front().x(jvi["init"][0].asDouble());
303 this->nodes_.front().y(jvi["init"][1].asDouble());
304 this->nodes_.front().h(jvi["init"][2].asDouble());
305 if (jvi["goal"].size() == 4) {
306 this->goal_ = RRTGoal(jvi["goal"][0].asDouble(),
307 jvi["goal"][1].asDouble(),
308 jvi["goal"][2].asDouble(),
309 jvi["goal"][3].asDouble());
311 this->goal_ = RRTGoal(jvi["goal"][0].asDouble(),
312 jvi["goal"][1].asDouble(),
313 jvi["goal"][2].asDouble(),
314 jvi["goal"][2].asDouble());
321 if (this->icnt_ == 0) {
325 auto rs = this->sample();
326 #if 1 // anytime RRTs
328 double d1 = this->cost_search(this->nodes_.front(), rs);
329 double d2 = this->cost_search(rs, this->goal_);
330 if (this->last_goal_cc_ != 0.0 && d1 + d2 > this->last_goal_cc_) {
331 rs = this->last_path_[rand() % this->last_path_.size()];
336 this->steer(this->nn(), rs);
337 if (this->collide_steered()) {
338 return this->should_continue();
340 this->find_nv(this->steered_.front());
341 if (!this->connect()) {
342 return this->should_continue();
345 unsigned int ss = this->steered_.size();
346 this->join_steered(&this->nodes_.back());
347 RRTNode* just_added = &this->nodes_.back();
349 while (ss > 0 && just_added->p() != nullptr) {
350 this->steer(*just_added, this->goal_);
351 if (this->collide_steered()) {
353 just_added = just_added->p();
356 this->join_steered(just_added);
357 bool gn = this->goal_.edist(this->nodes_.back()) < this->eta_;
358 bool gd = this->goal_drivable_from(this->nodes_.back());
360 double nc = this->cost_build(this->nodes_.back(),
362 double ncc = this->nodes_.back().cc() + nc;
363 if (this->goal_.p() == nullptr
364 || ncc < this->goal_.cc()) {
365 this->goal_.p(this->nodes_.back());
371 just_added = just_added->p();
374 this->compute_path();
376 this->time_ = this->ter_.scnt();
377 return this->should_continue();
383 if (this->goal_.cc() != 0.0 && this->goal_.cc() < this->last_goal_cc_) {
384 this->last_goal_cc_ = this->goal_.cc();
385 this->last_path_.clear();
386 for (auto n: this->path_) {
387 this->last_path_.push_back(*n);
390 this->goal_ = RRTGoal(this->goal_.x(), this->goal_.y(), this->goal_.b(),
393 this->steered_.clear();
394 this->nodes_.erase(this->nodes_.begin() + 1, this->nodes_.end());