2 This file is part of I am car.
4 I am car is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 I am car is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with I am car. If not, see <http://www.gnu.org/licenses/>.
26 #include "rrtplanner.h"
29 #define CATI(a, b) a ## b
30 #define CAT(a, b) CATI(a, b)
31 #define KUWATA2008_CCOST CAT(c, CO)
32 #define KUWATA2008_DCOST CO
34 LaValle1998::LaValle1998(RRTNode *init, RRTNode *goal):
37 srand(static_cast<unsigned>(time(0)));
40 bool LaValle1998::next()
44 if (this->samples().size() == 0)
51 this->samples().push_back(rs);
52 RRTNode *nn = this->nn(rs);
55 for (auto ns: this->steer(nn, rs)) {
59 this->nodes().push_back(ns);
61 pn->add_child(ns, this->cost(pn, ns));
62 if (this->collide(pn, ns)) {
63 pn->children().pop_back();
65 this->iy_[IYI(ns->y())].pop_back();
70 if (this->goal_found(pn, CO)) {
71 this->tlog(this->findt());
77 return this->goal_found();
80 Kuwata2008::Kuwata2008(RRTNode *init, RRTNode *goal):
83 srand(static_cast<unsigned>(time(0)));
86 bool Kuwata2008::next()
89 if (this->samples().size() == 0) {
94 this->samples().push_back(rs);
95 float heur = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
96 if (this->goal_found()) {
98 {}//this->cost = &KUWATA2008_CCOST;
100 {}//this->cost = &KUWATA2008_DCOST;
103 {}//this->cost = &KUWATA2008_CCOST;
105 {}//this->cost = &KUWATA2008_DCOST;
107 RRTNode *nn = this->nn(rs);
109 std::vector<RRTNode *> newly_added;
111 for (auto ns: this->steer(nn, rs)) {
115 this->nodes().push_back(ns);
117 pn->add_child(ns, KUWATA2008_DCOST(pn, ns));
118 if (this->collide(pn, ns)) {
119 pn->children().pop_back();
121 this->iy_[IYI(ns->y())].pop_back();
126 newly_added.push_back(pn);
127 if (this->goal_found(pn, &KUWATA2008_DCOST)) {
128 this->tlog(this->findt());
134 if (this->samples().size() <= 1)
135 return this->goal_found();
136 for (auto na: newly_added) {
139 for (auto ns: this->steer(na, this->goal())) {
143 this->nodes().push_back(ns);
145 pn->add_child(ns, KUWATA2008_DCOST(pn, ns));
146 if (this->collide(pn, ns)) {
147 pn->children().pop_back();
149 this->iy_[IYI(ns->y())].pop_back();
154 if (this->goal_found(pn,
155 &KUWATA2008_DCOST)) {
156 this->tlog(this->findt());
163 return this->goal_found();
166 Karaman2011::Karaman2011(RRTNode *init, RRTNode *goal):
169 srand(static_cast<unsigned>(time(0)));
172 bool Karaman2011::next()
176 if (this->samples().size() == 0)
183 this->samples().push_back(rs);
184 RRTNode *nn = this->nn(rs);
186 std::vector<RRTNode *> nvs;
188 for (auto ns: this->steer(nn, rs)) {
194 this->nodes().size()),
196 this->nodes().push_back(ns);
199 if (!this->connect(pn, ns, nvs)) {
200 this->iy_[IYI(ns->y())].pop_back();
204 this->rewire(nvs, ns);
206 if (this->goal_found(pn, CO)) {
207 this->tlog(this->findt());
213 return this->goal_found();
216 bool Karaman2011::connect(
219 std::vector<RRTNode *> nvs)
221 RRTNode *op; // old parent
222 float od; // old direct cost
223 float oc; // old cumulative cost
224 bool connected = false;
225 pn->add_child(ns, this->cost(pn, ns));
226 if (this->collide(pn, ns)) {
227 pn->children().pop_back();
234 if (!connected || (nv->ccost() + this->cost(nv, ns) <
242 nv->add_child(ns, this->cost(nv, ns));
243 if (this->collide(nv, ns)) {
244 nv->children().pop_back();
251 } else if (connected) {
252 op->children().pop_back();
262 bool Karaman2011::rewire(std::vector<RRTNode *> nvs, RRTNode *ns)
264 RRTNode *op; // old parent
265 float od; // old direct cost
266 float oc; // old cumulative cost
268 if (ns->ccost() + this->cost(ns, nv) < nv->ccost()) {
272 ns->add_child(nv, this->cost(ns, nv));
273 if (this->collide(ns, nv)) {
274 ns->children().pop_back();
286 T1::T1(RRTNode *init, RRTNode *goal):
289 srand(static_cast<unsigned>(time(0)));
295 if (this->samples().size() == 0)
299 this->samples().push_back(rs);
300 RRTNode *nn = this->nn(rs);
302 std::vector<RRTNode *> nvs;
304 RRTNode *op; // old parent
305 float od; // old direct cost
306 float oc; // old cumulative cost
307 std::vector<RRTNode *> steered = this->steer(nn, rs);
308 // RRT* for first node
309 RRTNode *ns = steered[0];
311 nvs = this->nv(ns, MIN(
312 GAMMA_RRTSTAR(this->nodes().size()),
314 this->nodes().push_back(ns);
317 pn->add_child(ns, this->cost(pn, ns));
318 if (this->collide(pn, ns)) {
319 pn->children().pop_back();
325 if (!connected || (nv->ccost() + this->cost(nv, ns) <
330 nv->add_child(ns, this->cost(nv, ns));
331 if (this->collide(nv, ns)) {
332 nv->children().pop_back();
336 } else if (connected) {
337 op->children().pop_back();
347 if (ns->ccost() + this->cost(ns, nv) < nv->ccost()) {
351 ns->add_child(nv, this->cost(ns, nv));
352 if (this->collide(ns, nv)) {
353 ns->children().pop_back();
363 if (this->goal_found(pn, CO)) {
364 this->tlog(this->findt());
368 for (i = 1; i < steered.size(); i++) {
370 this->nodes().push_back(ns);
372 pn->add_child(ns, this->cost(pn, ns));
373 if (this->collide(pn, ns)) {
374 pn->children().pop_back();
378 if (this->goal_found(pn, CO)) {
379 this->tlog(this->findt());
383 return this->goal_found();
390 if (this->samples().size() == 0)
397 this->samples().push_back(rs);
398 RRTNode *nn = this->nn(rs);
402 std::vector<RRTNode *> nvs;
403 std::vector<RRTNode *> newly_added;
406 for (auto ns: this->steer(nn, rs)) {
409 } else if (IS_NEAR(pn, ns)) {
412 if (sgn(ns->s()) == 0 || sgn(pn->s()) != sgn(ns->s()))
420 this->nodes().size()),
422 this->nodes().push_back(ns);
425 if (!this->connect(pn, ns, nvs)) {
426 this->iy_[IYI(ns->y())].pop_back();
430 this->rewire(nvs, ns);
432 newly_added.push_back(pn);
433 if (this->goal_found(pn, CO)) {
435 this->tlog(this->findt());
441 if (this->samples().size() <= 1)
442 return this->goal_found();
443 for (auto na: newly_added) {
447 for (auto ns: this->steer(na, this->goal())) {
450 } else if (IS_NEAR(pn, ns)) {
453 if (sgn(pn->s()) != sgn(ns->s()))
457 this->nodes().push_back(ns);
459 pn->add_child(ns, this->cost(pn, ns));
460 if (this->collide(pn, ns)) {
461 pn->children().pop_back();
463 this->iy_[IYI(ns->y())].pop_back();
468 if (this->goal_found(pn, CO)) {
470 this->tlog(this->findt());
477 return this->goal_found();
480 float T2::goal_cost()
482 std::vector<RRTNode *> nvs;
483 nvs = this->nv(this->goal(), 0.2);
485 if (std::abs(this->goal()->h() - nv->h()) >=
486 this->GOAL_FOUND_ANGLE)
488 if (nv->ccost() + this->cost(nv, this->goal()) >=
489 this->goal()->ccost())
491 RRTNode *op; // old parent
492 float oc; // old cumulative cost
493 float od; // old direct cost
494 op = this->goal()->parent();
495 oc = this->goal()->ccost();
496 od = this->goal()->dcost();
497 nv->add_child(this->goal(),
498 this->cost(nv, this->goal()));
499 if (this->collide(nv, this->goal())) {
500 nv->children().pop_back();
501 this->goal()->parent(op);
502 this->goal()->ccost(oc);
503 this->goal()->dcost(od);
505 op->rem_child(this->goal());
508 return this->goal()->ccost();
511 T3::T3(RRTNode *init, RRTNode *goal):
516 srand(static_cast<unsigned>(time(0)));
521 RRTNode *ron = nullptr;
522 RRTNode *gon = nullptr;
524 ret = this->p_root_.next();
525 ret &= this->p_goal_.next();
526 if (this->overlaptrees(&ron, &gon)) {
527 if (this->connecttrees(ron, gon))
528 this->goal_found(true);
529 this->tlog(this->findt());
535 bool T3::link_obstacles(
536 std::vector<CircleObstacle> *cobstacles,
537 std::vector<SegmentObstacle> *sobstacles)
540 ret = RRTBase::link_obstacles(cobstacles, sobstacles);
541 ret &= this->p_root_.link_obstacles(cobstacles, sobstacles);
542 ret &= this->p_goal_.link_obstacles(cobstacles, sobstacles);
546 bool T3::connecttrees(RRTNode *rn, RRTNode *gn)
548 while (gn != this->goal()) {
549 this->p_root_.nodes().push_back(new RRTNode(
554 this->p_root_.nodes().back(),
557 this->p_root_.nodes().back()));
558 rn = this->p_root_.nodes().back();
561 rn->add_child(this->goal(), this->p_root_.cost(rn, this->goal()));
565 bool T3::overlaptrees(RRTNode **ron, RRTNode **gon)
567 for (auto rn: this->p_root_.nodes()) {
568 if (rn->parent() == nullptr)
570 for (auto gn: this->p_goal_.nodes()) {
571 if (gn->parent() == nullptr)
573 if (IS_NEAR(rn, gn)) {
583 Klemm2015::Klemm2015(RRTNode *init, RRTNode *goal):
584 Karaman2011(init, goal),
588 srand(static_cast<unsigned>(time(0)));
589 this->root()->tree('R');
590 this->goal()->tree('G');
591 this->add_iy(this->goal());
594 bool Klemm2015::next()
596 RRTNode *xn = nullptr;
600 if (this->samples().size() == 0)
607 this->samples().push_back(rs);
608 //std::cerr << "next" << std::endl;
609 if (this->extendstar1(rs, &xn) != 2) {
611 // std::cerr << "- xn: " << xn->x() << ", " << xn->y();
612 // std::cerr << std::endl;
614 // std::cerr << "- xn: nullptr" << std::endl;
617 ret = this->connectstar(xn);
622 this->tlog(this->findt());
625 return this->goal_found();
628 int Klemm2015::extendstar1(RRTNode *rs, RRTNode **xn)
630 int ret = 0; // 0 - advanced, 1 - reached, 2 - trapped
631 char tree = this->root()->tree();
632 //std::cerr << "extend*1" << std::endl;
633 //std::cerr << "- tree is " << tree << std::endl;
634 //std::cerr << " - rs: " << rs->x() << ", " << rs->y() << std::endl;
636 // std::cerr << " - xn: " << (*xn)->x() << ", " << (*xn)->y();
637 // std::cerr << std::endl;
639 //for (int i = 0; i < IYSIZE; i++) {
640 // if (this->iy_[i].size() > 0) {
641 // RRTNode *tmpn = this->iy_[i].back();
642 // float tmpd = EDIST(tmpn, this->goal());
644 // std::cerr << i << ": " << tmpn->x();
645 // std::cerr << ", " << tmpn->y();
646 // std::cerr << ", " << tmpn->tree();
647 // std::cerr << " (" << tmpd << ")";
649 // if (tmpn == this->root())
650 // std::cerr << " root";
651 // if (tmpn == this->goal())
652 // std::cerr << " goal";
653 // std::cerr << std::endl;
656 RRTNode *nn = this->nn(rs);
657 //std::cerr << " - nn: " << nn->x() << ", " << nn->y() << std::endl;
658 std::vector<RRTNode *> nvs;
659 std::vector<RRTNode *> steered = this->steer(nn, rs);
660 RRTNode *ns = steered[1];
666 this->nodes().size()),
668 this->nodes().push_back(ns);
671 if (!this->connect(nn, ns, nvs)) {
672 this->iy_[IYI(ns->y())].pop_back();
676 this->rewire(nvs, ns);
678 for (auto n: steered) {
683 //std::cerr << " - xn: " << (*xn)->x() << ", " << (*xn)->y();
684 //std::cerr << std::endl;
688 int Klemm2015::extendstarC(RRTNode *rs)
690 int ret = 0; // 0 - advanced, 1 - reached, 2 - trapped
691 char tree = this->root()->tree();
692 //std::cerr << "extend*C" << std::endl;
693 //std::cerr << "- tree is " << tree << std::endl;
694 //std::cerr << " - rs: " << rs->x() << ", " << rs->y() << std::endl;
695 RRTNode *nn = this->nn(rs);
697 std::vector<RRTNode *> nvs;
699 for (auto ns: this->steer(nn, rs)) {
707 this->nodes().size()),
709 this->nodes().push_back(ns);
712 if (!this->connect(pn, ns, nvs)) {
713 this->iy_[IYI(ns->y())].pop_back();
718 this->rewire(nvs, ns);
720 if (IS_NEAR(pn, rs)) { // GOAL FOUND !
722 if (this->orig_root_ == this->root()) { // rs is in G tree
723 // add all rs parents to pn
725 } else { // rs is in R tree
730 while (tmp != this->goal()) {
731 this->nodes().push_back(new RRTNode(
735 this->nodes().back()->s(tmp->s());
736 this->nodes().back()->tree('R');
738 this->nodes().back(),
739 this->cost(pn, this->nodes().back()));
740 pn = this->nodes().back();
743 pn->add_child(tmp, this->cost(pn, tmp)); // add goal()
753 int Klemm2015::connectstar(RRTNode *x)
755 int ret = 0; // 0 - advanced, 1 - reached, 2 - trapped
756 //std::cerr << "connect* (start)" << std::endl;
757 ret = this->extendstarC(x);
758 //std::cerr << "connect* (end)" << std::endl;
762 void Klemm2015::swap()
766 this->root(this->goal());