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):
38 srand(static_cast<unsigned>(time(0)));
41 bool LaValle1998::next()
45 if (this->samples().size() == 0)
52 this->samples().push_back(rs);
53 RRTNode *nn = this->nn(rs);
56 for (auto ns: this->steer(nn, rs)) {
60 this->nodes().push_back(ns);
62 pn->add_child(ns, this->cost(pn, ns));
63 if (this->collide(pn, ns)) {
64 pn->children().pop_back();
66 this->iy_[IYI(ns->y())].pop_back();
71 if (this->goal_found(pn, CO)) {
72 this->tlog(this->findt());
78 return this->goal_found();
81 Kuwata2008::Kuwata2008(RRTNode *init, RRTNode *goal):
85 srand(static_cast<unsigned>(time(0)));
88 bool Kuwata2008::next()
91 if (this->samples().size() == 0) {
96 this->samples().push_back(rs);
97 float heur = static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
98 if (this->goal_found()) {
100 {}//this->cost = &KUWATA2008_CCOST;
102 {}//this->cost = &KUWATA2008_DCOST;
105 {}//this->cost = &KUWATA2008_CCOST;
107 {}//this->cost = &KUWATA2008_DCOST;
109 RRTNode *nn = this->nn(rs);
111 std::vector<RRTNode *> newly_added;
113 for (auto ns: this->steer(nn, rs)) {
117 this->nodes().push_back(ns);
119 pn->add_child(ns, KUWATA2008_DCOST(pn, ns));
120 if (this->collide(pn, ns)) {
121 pn->children().pop_back();
123 this->iy_[IYI(ns->y())].pop_back();
128 newly_added.push_back(pn);
129 if (this->goal_found(pn, &KUWATA2008_DCOST)) {
130 this->tlog(this->findt());
136 if (this->samples().size() <= 1)
137 return this->goal_found();
138 for (auto na: newly_added) {
141 for (auto ns: this->steer(na, this->goal())) {
145 this->nodes().push_back(ns);
147 pn->add_child(ns, KUWATA2008_DCOST(pn, ns));
148 if (this->collide(pn, ns)) {
149 pn->children().pop_back();
151 this->iy_[IYI(ns->y())].pop_back();
156 if (this->goal_found(pn,
157 &KUWATA2008_DCOST)) {
158 this->tlog(this->findt());
165 return this->goal_found();
168 Karaman2011::Karaman2011(RRTNode *init, RRTNode *goal):
172 srand(static_cast<unsigned>(time(0)));
175 bool Karaman2011::next()
179 if (this->samples().size() == 0)
186 this->samples().push_back(rs);
187 RRTNode *nn = this->nn(rs);
189 std::vector<RRTNode *> nvs;
191 for (auto ns: this->steer(nn, rs)) {
197 this->nodes().size()),
199 this->nodes().push_back(ns);
202 if (!this->connect(pn, ns, nvs)) {
203 this->iy_[IYI(ns->y())].pop_back();
207 this->rewire(nvs, ns);
209 if (this->goal_found(pn, CO)) {
210 this->tlog(this->findt());
216 return this->goal_found();
219 bool Karaman2011::connect(
222 std::vector<RRTNode *> nvs)
224 RRTNode *op; // old parent
225 float od; // old direct cost
226 float oc; // old cumulative cost
227 bool connected = false;
228 pn->add_child(ns, this->cost(pn, ns));
229 if (this->collide(pn, ns)) {
230 pn->children().pop_back();
237 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):
290 srand(static_cast<unsigned>(time(0)));
296 if (this->samples().size() == 0)
300 this->samples().push_back(rs);
301 RRTNode *nn = this->nn(rs);
303 std::vector<RRTNode *> nvs;
305 RRTNode *op; // old parent
306 float od; // old direct cost
307 float oc; // old cumulative cost
308 std::vector<RRTNode *> steered = this->steer(nn, rs);
309 // RRT* for first node
310 RRTNode *ns = steered[0];
312 nvs = this->nv(ns, MIN(
313 GAMMA_RRTSTAR(this->nodes().size()),
315 this->nodes().push_back(ns);
318 pn->add_child(ns, this->cost(pn, ns));
319 if (this->collide(pn, ns)) {
320 pn->children().pop_back();
326 if (!connected || (nv->ccost() + this->cost(nv, ns) <
331 nv->add_child(ns, this->cost(nv, ns));
332 if (this->collide(nv, ns)) {
333 nv->children().pop_back();
337 } else if (connected) {
338 op->children().pop_back();
348 if (ns->ccost() + this->cost(ns, nv) < nv->ccost()) {
352 ns->add_child(nv, this->cost(ns, nv));
353 if (this->collide(ns, nv)) {
354 ns->children().pop_back();
364 if (this->goal_found(pn, CO)) {
365 this->tlog(this->findt());
369 for (i = 1; i < steered.size(); i++) {
371 this->nodes().push_back(ns);
373 pn->add_child(ns, this->cost(pn, ns));
374 if (this->collide(pn, ns)) {
375 pn->children().pop_back();
379 if (this->goal_found(pn, CO)) {
380 this->tlog(this->findt());
384 return this->goal_found();
391 if (this->samples().size() == 0)
398 this->samples().push_back(rs);
399 RRTNode *nn = this->nn(rs);
403 std::vector<RRTNode *> nvs;
404 std::vector<RRTNode *> newly_added;
407 for (auto ns: this->steer(nn, rs)) {
410 } else if (IS_NEAR(pn, ns)) {
413 if (sgn(ns->s()) == 0 || sgn(pn->s()) != sgn(ns->s()))
421 this->nodes().size()),
423 this->nodes().push_back(ns);
426 if (!this->connect(pn, ns, nvs)) {
427 this->iy_[IYI(ns->y())].pop_back();
431 this->rewire(nvs, ns);
433 newly_added.push_back(pn);
434 if (this->goal_found(pn, CO)) {
436 this->tlog(this->findt());
442 if (this->samples().size() <= 1)
443 return this->goal_found();
444 for (auto na: newly_added) {
448 for (auto ns: this->steer(na, this->goal())) {
451 } else if (IS_NEAR(pn, ns)) {
454 if (sgn(pn->s()) != sgn(ns->s()))
458 this->nodes().push_back(ns);
460 pn->add_child(ns, this->cost(pn, ns));
461 if (this->collide(pn, ns)) {
462 pn->children().pop_back();
464 this->iy_[IYI(ns->y())].pop_back();
469 if (this->goal_found(pn, CO)) {
471 this->tlog(this->findt());
478 return this->goal_found();
481 float T2::goal_cost()
483 std::vector<RRTNode *> nvs;
484 nvs = this->nv(this->goal(), 0.2);
486 if (std::abs(this->goal()->h() - nv->h()) >=
487 this->GOAL_FOUND_ANGLE)
489 if (nv->ccost() + this->cost(nv, this->goal()) >=
490 this->goal()->ccost())
492 RRTNode *op; // old parent
493 float oc; // old cumulative cost
494 float od; // old direct cost
495 op = this->goal()->parent();
496 oc = this->goal()->ccost();
497 od = this->goal()->dcost();
498 nv->add_child(this->goal(),
499 this->cost(nv, this->goal()));
500 if (this->collide(nv, this->goal())) {
501 nv->children().pop_back();
502 this->goal()->parent(op);
503 this->goal()->ccost(oc);
504 this->goal()->dcost(od);
506 op->rem_child(this->goal());
509 return this->goal()->ccost();
512 T3::T3(RRTNode *init, RRTNode *goal):
517 srand(static_cast<unsigned>(time(0)));
522 RRTNode *ron = nullptr;
523 RRTNode *gon = nullptr;
525 ret = this->p_root_.next();
526 ret &= this->p_goal_.next();
527 if (this->overlaptrees(&ron, &gon)) {
528 if (this->connecttrees(ron, gon))
529 this->goal_found(true);
530 this->tlog(this->findt());
536 bool T3::link_obstacles(
537 std::vector<CircleObstacle> *cobstacles,
538 std::vector<SegmentObstacle> *sobstacles)
541 ret = RRTBase::link_obstacles(cobstacles, sobstacles);
542 ret &= this->p_root_.link_obstacles(cobstacles, sobstacles);
543 ret &= this->p_goal_.link_obstacles(cobstacles, sobstacles);
547 bool T3::connecttrees(RRTNode *rn, RRTNode *gn)
549 while (gn != this->goal()) {
550 this->p_root_.nodes().push_back(new RRTNode(
555 this->p_root_.nodes().back(),
558 this->p_root_.nodes().back()));
559 rn = this->p_root_.nodes().back();
562 rn->add_child(this->goal(), this->p_root_.cost(rn, this->goal()));
566 bool T3::overlaptrees(RRTNode **ron, RRTNode **gon)
568 for (auto rn: this->p_root_.nodes()) {
569 if (rn->parent() == nullptr)
571 for (auto gn: this->p_goal_.nodes()) {
572 if (gn->parent() == nullptr)
574 if (IS_NEAR(rn, gn)) {
584 Klemm2015::Klemm2015(RRTNode *init, RRTNode *goal):
585 Karaman2011(init, goal),
590 srand(static_cast<unsigned>(time(0)));
591 this->root()->tree('R');
592 this->goal()->tree('G');
593 this->add_iy(this->goal());
596 bool Klemm2015::next()
598 RRTNode *xn = nullptr;
602 if (this->samples().size() == 0)
609 this->samples().push_back(rs);
610 //std::cerr << "next" << std::endl;
611 if (this->extendstar1(rs, &xn) != 2) {
613 // std::cerr << "- xn: " << xn->x() << ", " << xn->y();
614 // std::cerr << std::endl;
616 // std::cerr << "- xn: nullptr" << std::endl;
619 ret = this->connectstar(xn);
624 this->tlog(this->findt());
627 return this->goal_found();
630 int Klemm2015::extendstar1(RRTNode *rs, RRTNode **xn)
632 int ret = 0; // 0 - advanced, 1 - reached, 2 - trapped
633 char tree = this->root()->tree();
634 //std::cerr << "extend*1" << std::endl;
635 //std::cerr << "- tree is " << tree << std::endl;
636 //std::cerr << " - rs: " << rs->x() << ", " << rs->y() << std::endl;
638 // std::cerr << " - xn: " << (*xn)->x() << ", " << (*xn)->y();
639 // std::cerr << std::endl;
641 //for (int i = 0; i < IYSIZE; i++) {
642 // if (this->iy_[i].size() > 0) {
643 // RRTNode *tmpn = this->iy_[i].back();
644 // float tmpd = EDIST(tmpn, this->goal());
646 // std::cerr << i << ": " << tmpn->x();
647 // std::cerr << ", " << tmpn->y();
648 // std::cerr << ", " << tmpn->tree();
649 // std::cerr << " (" << tmpd << ")";
651 // if (tmpn == this->root())
652 // std::cerr << " root";
653 // if (tmpn == this->goal())
654 // std::cerr << " goal";
655 // std::cerr << std::endl;
658 RRTNode *nn = this->nn(rs);
659 //std::cerr << " - nn: " << nn->x() << ", " << nn->y() << std::endl;
660 std::vector<RRTNode *> nvs;
661 std::vector<RRTNode *> steered = this->steer(nn, rs);
662 RRTNode *ns = steered[1];
668 this->nodes().size()),
670 this->nodes().push_back(ns);
673 if (!this->connect(nn, ns, nvs)) {
674 this->iy_[IYI(ns->y())].pop_back();
678 this->rewire(nvs, ns);
680 for (auto n: steered) {
685 //std::cerr << " - xn: " << (*xn)->x() << ", " << (*xn)->y();
686 //std::cerr << std::endl;
690 int Klemm2015::extendstarC(RRTNode *rs)
692 int ret = 0; // 0 - advanced, 1 - reached, 2 - trapped
693 char tree = this->root()->tree();
694 //std::cerr << "extend*C" << std::endl;
695 //std::cerr << "- tree is " << tree << std::endl;
696 //std::cerr << " - rs: " << rs->x() << ", " << rs->y() << std::endl;
697 RRTNode *nn = this->nn(rs);
699 std::vector<RRTNode *> nvs;
701 for (auto ns: this->steer(nn, rs)) {
709 this->nodes().size()),
711 this->nodes().push_back(ns);
714 if (!this->connect(pn, ns, nvs)) {
715 this->iy_[IYI(ns->y())].pop_back();
720 this->rewire(nvs, ns);
722 if (IS_NEAR(pn, rs)) { // GOAL FOUND !
724 if (this->orig_root_ == this->root()) { // rs is in G tree
725 // add all rs parents to pn
727 } else { // rs is in R tree
732 while (tmp != this->goal()) {
733 this->nodes().push_back(new RRTNode(
737 this->nodes().back()->s(tmp->s());
738 this->nodes().back()->tree('R');
740 this->nodes().back(),
741 this->cost(pn, this->nodes().back()));
742 pn = this->nodes().back();
745 pn->add_child(tmp, this->cost(pn, tmp)); // add goal()
755 int Klemm2015::connectstar(RRTNode *x)
757 int ret = 0; // 0 - advanced, 1 - reached, 2 - trapped
758 //std::cerr << "connect* (start)" << std::endl;
759 ret = this->extendstarC(x);
760 //std::cerr << "connect* (end)" << std::endl;
764 void Klemm2015::swap()
768 this->root(this->goal());