]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blob - base/rrtbase.cc
Change goal found to include IS_NEAR macro
[hubacji1/iamcar.git] / base / rrtbase.cc
1 /*
2 This file is part of I am car.
3
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.
8
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.
13
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/>.
16 */
17
18 #include <algorithm>
19 #include <cmath>
20 #include <omp.h>
21 #include <queue>
22 #include "bcar.h"
23 #include "rrtbase.h"
24 // OpenGL
25 #include <GL/gl.h>
26 #include <GL/glu.h>
27 #include <SDL2/SDL.h>
28 // RRT
29 #include "cost.h"
30 #include "steer.h"
31
32 extern SDL_Window* gw;
33 extern SDL_GLContext gc;
34
35 RRTBase::~RRTBase()
36 {
37         for (auto n: this->nodes_)
38                 if (n != this->root_)
39                         delete n;
40         for (auto n: this->dnodes_)
41                 if (n != this->root_ && n != this->goal_)
42                         delete n;
43         for (auto s: this->samples_)
44                 if (s != this->goal_)
45                         delete s;
46         for (auto edges: this->rlog_)
47                 for (auto e: edges)
48                         delete e;
49         delete this->root_;
50         delete this->goal_;
51 }
52
53 RRTBase::RRTBase():
54         root_(new RRTNode()),
55         goal_(new RRTNode())
56 {
57         this->nodes_.push_back(this->root_);
58         this->add_iy(this->root_);
59 }
60
61 RRTBase::RRTBase(RRTNode *init, RRTNode *goal):
62         root_(init),
63         goal_(goal)
64 {
65         this->nodes_.push_back(init);
66         this->add_iy(init);
67 }
68
69 RRTNode *RRTBase::root()
70 {
71         return this->root_;
72 }
73
74 RRTNode *RRTBase::goal()
75 {
76         return this->goal_;
77 }
78
79 std::vector<RRTNode *> &RRTBase::nodes()
80 {
81         return this->nodes_;
82 }
83
84 std::vector<RRTNode *> &RRTBase::dnodes()
85 {
86         return this->dnodes_;
87 }
88
89 std::vector<RRTNode *> &RRTBase::samples()
90 {
91         return this->samples_;
92 }
93
94 std::vector<CircleObstacle> *RRTBase::cos()
95 {
96         return this->cobstacles_;
97 }
98
99 std::vector<SegmentObstacle> *RRTBase::sos()
100 {
101         return this->sobstacles_;
102 }
103
104 std::vector<float> &RRTBase::clog()
105 {
106         return this->clog_;
107 }
108
109 std::vector<float> &RRTBase::nlog()
110 {
111         return this->nlog_;
112 }
113
114 std::vector<std::vector<RRTEdge *>> &RRTBase::rlog()
115 {
116         return this->rlog_;
117 }
118
119 std::vector<float> &RRTBase::slog()
120 {
121         return this->slog_;
122 }
123
124 std::vector<std::vector<RRTNode *>> &RRTBase::tlog()
125 {
126         return this->tlog_;
127 }
128
129 bool RRTBase::goal_found()
130 {
131         return this->goal_found_;
132 }
133
134 float RRTBase::elapsed()
135 {
136         std::chrono::duration<float> dt;
137         dt = std::chrono::duration_cast<std::chrono::duration<float>>(
138                         this->tend_ - this->tstart_);
139         return dt.count();
140 }
141
142 bool RRTBase::logr(RRTNode *root)
143 {
144         std::vector<RRTEdge *> e; // Edges to log
145         std::vector<RRTNode *> s; // DFS stack
146         std::vector<RRTNode *> r; // reset visited_
147         RRTNode *tmp;
148         s.push_back(root);
149         while (s.size() > 0) {
150                 tmp = s.back();
151                 s.pop_back();
152                 if (!tmp->visit()) {
153                         r.push_back(tmp);
154                         for (auto ch: tmp->children()) {
155                                 s.push_back(ch);
156                                 e.push_back(new RRTEdge(tmp, ch));
157                         }
158                 }
159         }
160         for (auto n: r)
161                 n->visit(false);
162         this->rlog_.push_back(e);
163         return true;
164 }
165
166 float RRTBase::ocost(RRTNode *n)
167 {
168         float dist = 9999;
169         for (auto o: *this->cobstacles_)
170                 if (o.dist_to(n) < dist)
171                         dist = o.dist_to(n);
172         for (auto o: *this->sobstacles_)
173                 if (o.dist_to(n) < dist)
174                         dist = o.dist_to(n);
175         return n->ocost(dist);
176 }
177
178 bool RRTBase::tlog(std::vector<RRTNode *> t)
179 {
180         if (t.size() > 0) {
181                 this->slog_.push_back(this->elapsed());
182                 this->clog_.push_back(t.front()->ccost() - t.back()->ccost());
183                 this->nlog_.push_back(this->nodes_.size());
184                 this->tlog_.push_back(t);
185                 return true;
186         } else {
187                 return false;
188         }
189 }
190
191 void RRTBase::tstart()
192 {
193         this->tstart_ = std::chrono::high_resolution_clock::now();
194 }
195
196 void RRTBase::tend()
197 {
198         this->tend_ = std::chrono::high_resolution_clock::now();
199 }
200
201 bool RRTBase::link_obstacles(
202                 std::vector<CircleObstacle> *cobstacles,
203                 std::vector<SegmentObstacle> *sobstacles)
204 {
205         this->cobstacles_ = cobstacles;
206         this->sobstacles_ = sobstacles;
207         if (!this->cobstacles_ || !this->sobstacles_) {
208                 return false;
209         }
210         return true;
211 }
212
213 bool RRTBase::add_iy(RRTNode *n)
214 {
215         int i = IYI(n->y());
216         if (i < 0)
217                 i = 0;
218         if (i >= IYSIZE)
219                 i = IYSIZE - 1;
220         this->iy_[i].push_back(n);
221         return true;
222 }
223
224 bool RRTBase::glplot()
225 {
226         glClear(GL_COLOR_BUFFER_BIT);
227         glLineWidth(1);
228         glPointSize(1);
229         // Plot obstacles
230         glBegin(GL_LINES);
231         for (auto o: *this->sobstacles_) {
232                 glColor3f(0, 0, 0);
233                 glVertex2f(GLVERTEX(o.init()));
234                 glVertex2f(GLVERTEX(o.goal()));
235         }
236         glEnd();
237         // Plot root, goal
238         glPointSize(8);
239         glBegin(GL_POINTS);
240         glColor3f(1, 0, 0);
241         glVertex2f(GLVERTEX(this->root_));
242         glVertex2f(GLVERTEX(this->goal_));
243         glEnd();
244         // Plot last sample
245         glPointSize(8);
246         glBegin(GL_POINTS);
247         glColor3f(0, 1, 0);
248         glVertex2f(GLVERTEX(this->samples_.back()));
249         glEnd();
250         // Plot nodes
251         std::vector<RRTNode *> s; // DFS stack
252         std::vector<RRTNode *> r; // reset visited_
253         RRTNode *tmp;
254         glBegin(GL_LINES);
255         s.push_back(this->root_);
256         while (s.size() > 0) {
257                 tmp = s.back();
258                 s.pop_back();
259                 if (!tmp->visit()) {
260                         r.push_back(tmp);
261                         for (auto ch: tmp->children()) {
262                                 s.push_back(ch);
263                                 glColor3f(0.5, 0.5, 0.5);
264                                 glVertex2f(GLVERTEX(tmp));
265                                 glVertex2f(GLVERTEX(ch));
266                         }
267                 }
268         }
269         glEnd();
270         std::vector<RRTNode *> cusps;
271         // Plot last trajectory
272         if (this->tlog().size() > 0) {
273                 glLineWidth(2);
274                 glBegin(GL_LINES);
275                 for (auto n: this->tlog().back()) {
276                         if (n->parent()) {
277                                 glColor3f(0, 0, 1);
278                                 glVertex2f(GLVERTEX(n));
279                                 glVertex2f(GLVERTEX(n->parent()));
280                                 if (sgn(n->s()) != sgn(n->parent()->s()))
281                                         cusps.push_back(n);
282                         }
283                 }
284                 glEnd();
285         }
286         // Plot cusps
287         glPointSize(8);
288         glBegin(GL_POINTS);
289         for (auto n: cusps) {
290                 glColor3f(0, 0, 1);
291                 glVertex2f(GLVERTEX(n));
292         }
293         glEnd();
294         SDL_GL_SwapWindow(gw);
295         for (auto n: r)
296                 n->visit(false);
297         return true;
298 }
299
300 bool RRTBase::goal_found(
301                 RRTNode *node,
302                 float (*cost)(RRTNode *, RRTNode* ))
303 {
304         float xx = pow(node->x() - this->goal_->x(), 2);
305         float yy = pow(node->y() - this->goal_->y(), 2);
306         float dh = std::abs(node->h() - this->goal_->h());
307         if (IS_NEAR(node, this->goal_)) {
308                 if (this->goal_found_) {
309                         if (node->ccost() + (*cost)(node, this->goal_) <
310                                         this->goal_->ccost()) {
311                                 RRTNode *op; // old parent
312                                 float oc; // old cumulative cost
313                                 float od; // old direct cost
314                                 op = this->goal_->parent();
315                                 oc = this->goal_->ccost();
316                                 od = this->goal_->dcost();
317                                 node->add_child(this->goal_,
318                                                 (*cost)(node, this->goal_));
319                                 if (this->collide(node, this->goal_)) {
320                                         node->children().pop_back();
321                                         this->goal_->parent(op);
322                                         this->goal_->ccost(oc);
323                                         this->goal_->dcost(od);
324                                 } else {
325                                         op->rem_child(this->goal_);
326                                         return true;
327                                 }
328                         } else {
329                                 return false;
330                         }
331                 } else {
332                         node->add_child(
333                                         this->goal_,
334                                         (*cost)(node, this->goal_));
335                         if (this->collide(node, this->goal_)) {
336                                 node->children().pop_back();
337                                 this->goal_->remove_parent();
338                                 return false;
339                         }
340                         this->goal_found_ = true;
341                         return true;
342                 }
343         }
344         return false;
345 }
346
347 bool RRTBase::collide(RRTNode *init, RRTNode *goal)
348 {
349         std::vector<RRTEdge *> edges;
350         RRTNode *tmp = goal;
351         volatile bool col = false;
352         unsigned int i;
353         while (tmp != init) {
354                 BicycleCar bc(tmp->x(), tmp->y(), tmp->h());
355                 std::vector<RRTEdge *> bcframe = bc.frame();
356                 #pragma omp parallel for reduction(|: col)
357                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
358                         if ((*this->cobstacles_)[i].collide(tmp)) {
359                                 col = true;
360                         }
361                         // TODO collide with car frame
362                 }
363                 if (col) {
364                         for (auto e: bcframe) {
365                                 delete e->init();
366                                 delete e->goal();
367                                 delete e;
368                         }
369                         for (auto e: edges) {
370                                 delete e;
371                         }
372                         return true;
373                 }
374                 #pragma omp parallel for reduction(|: col)
375                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
376                         for (auto &e: bcframe) {
377                                 if ((*this->sobstacles_)[i].collide(e)) {
378                                         col = true;
379                                 }
380                         }
381                 }
382                 if (col) {
383                         for (auto e: bcframe) {
384                                 delete e->init();
385                                 delete e->goal();
386                                 delete e;
387                         }
388                         for (auto e: edges) {
389                                 delete e;
390                         }
391                         return true;
392                 }
393                 if (!tmp->parent()) {
394                         break;
395                 }
396                 edges.push_back(new RRTEdge(tmp, tmp->parent()));
397                 tmp = tmp->parent();
398                 for (auto e: bcframe) {
399                         delete e->init();
400                         delete e->goal();
401                         delete e;
402                 }
403         }
404         for (auto &e: edges) {
405                 #pragma omp parallel for reduction(|: col)
406                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
407                         if ((*this->cobstacles_)[i].collide(e)) {
408                                 col = true;
409                         }
410                 }
411                 if (col) {
412                         for (auto e: edges) {
413                                 delete e;
414                         }
415                         return true;
416                 }
417                 #pragma omp parallel for reduction(|: col)
418                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
419                         if ((*this->sobstacles_)[i].collide(e)) {
420                                 col = true;
421                         }
422                 }
423                 if (col) {
424                         for (auto e: edges) {
425                                 delete e;
426                         }
427                         return true;
428                 }
429         }
430         for (auto e: edges) {
431                 delete e;
432         }
433         return false;
434 }
435
436 class RRTNodeDijkstra {
437         public:
438                 RRTNodeDijkstra(int i):
439                         ni(i),
440                         pi(0),
441                         c(9999),
442                         v(false)
443                 {};
444                 RRTNodeDijkstra(int i, float c):
445                         ni(i),
446                         pi(0),
447                         c(c),
448                         v(false)
449                 {};
450                 RRTNodeDijkstra(int i, int p, float c):
451                         ni(i),
452                         pi(p),
453                         c(c),
454                         v(false)
455                 {};
456                 unsigned int ni;
457                 unsigned int pi;
458                 float c;
459                 bool v;
460                 bool vi()
461                 {
462                         if (this->v)
463                                 return true;
464                         this->v = true;
465                         return false;
466                 };
467 };
468
469 class RRTNodeDijkstraComparator {
470         public:
471                 int operator() (
472                                 const RRTNodeDijkstra& n1,
473                                 const RRTNodeDijkstra& n2)
474                 {
475                         return n1.c > n2.c;
476                 }
477 };
478
479 bool RRTBase::opt_path()
480 {
481         if (this->tlog().size() == 0)
482                 return false;
483         float oc = this->tlog().back().front()->ccost();
484         std::vector<RRTNode *> tmp_cusps;
485         for (auto n: this->tlog().back()) {
486                 if (sgn(n->s()) == 0) {
487                         tmp_cusps.push_back(n);
488                 } else if (n->parent() &&
489                                 sgn(n->s()) != sgn(n->parent()->s())) {
490                         tmp_cusps.push_back(n);
491                         tmp_cusps.push_back(n->parent());
492                 }
493         }
494         if (tmp_cusps.size() < 2)
495                 return false;
496         std::vector<RRTNode *> cusps;
497         for (unsigned int i = 0; i < tmp_cusps.size(); i++) {
498                 if (tmp_cusps[i] != tmp_cusps[i + 1])
499                         cusps.push_back(tmp_cusps[i]);
500         }
501         std::reverse(cusps.begin(), cusps.end());
502         // Begin of Dijkstra
503         std::vector<RRTNodeDijkstra> dnodes;
504         for (unsigned int i = 0; i < cusps.size(); i++)
505                 if (i > 0)
506                         dnodes.push_back(RRTNodeDijkstra(
507                                                 i,
508                                                 i - 1,
509                                                 cusps[i]->ccost()));
510                 else
511                         dnodes.push_back(RRTNodeDijkstra(
512                                                 i,
513                                                 cusps[i]->ccost()));
514         dnodes[0].vi();
515         std::priority_queue<
516                 RRTNodeDijkstra,
517                 std::vector<RRTNodeDijkstra>,
518                 RRTNodeDijkstraComparator> pq;
519         RRTNodeDijkstra tmp = dnodes[0];
520         pq.push(tmp);
521         float ch_cost = 9999;
522         std::vector<RRTNode *> steered;
523         while (!pq.empty() && tmp.ni != cusps.size() - 1) {
524                 tmp = pq.top();
525                 pq.pop();
526                 for (unsigned int i = tmp.ni + 1; i < cusps.size(); i++) {
527                         ch_cost = dnodes[tmp.ni].c +
528                                 CO(cusps[tmp.ni], cusps[i]);
529                         steered = ST(cusps[tmp.ni], cusps[i]);
530                         for (unsigned int j = 0; j < steered.size() - 1; j++)
531                                 steered[j]->add_child(
532                                                 steered[j + 1],
533                                                 CO(
534                                                         steered[j],
535                                                         steered[j + 1]));
536                         if (i != tmp.ni + 1 && this->collide( // TODO
537                                                 steered[0],
538                                                 steered[steered.size() - 1]))
539                                 continue;
540                         if (ch_cost < dnodes[i].c) {
541                                 dnodes[i].c = ch_cost;
542                                 dnodes[i].pi = tmp.ni;
543                                 if (!dnodes[i].vi())
544                                         pq.push(dnodes[i]);
545                         }
546                 }
547         }
548         if (tmp.ni != cusps.size() - 1)
549                 return false;
550         std::vector<int> npi; // new path indexes
551         int tmpi = tmp.ni;
552         while (tmpi > 0) {
553                 npi.push_back(tmpi);
554                 tmpi = dnodes[tmpi].pi;
555         }
556         npi.push_back(tmpi);
557         std::reverse(npi.begin(), npi.end());
558         RRTNode *pn = cusps[npi[0]];
559         for (unsigned int i = 0; i < npi.size() - 1; i++) {
560                 for (auto ns: ST(cusps[npi[i]], cusps[npi[i + 1]])) {
561                         pn->add_child(ns, CO(pn, ns));
562                         pn = ns;
563                 }
564         }
565         pn->add_child(
566                         this->tlog().back().front(),
567                         CO(pn, this->tlog().back().front()));
568         // End of Dijkstra
569         if (this->tlog().back().front()->ccost() < oc)
570                 return true;
571         return false;
572 }
573
574 bool RRTBase::rebase(RRTNode *nr)
575 {
576         if (!nr || this->goal_ == nr || this->root_ == nr)
577                 return false;
578         std::vector<RRTNode *> s; // DFS stack
579         RRTNode *tmp;
580         unsigned int i = 0;
581         unsigned int to_del = 0;
582         int iy = 0;
583         s.push_back(this->root_);
584         while (s.size() > 0) {
585                 tmp = s.back();
586                 s.pop_back();
587                 for (auto ch: tmp->children()) {
588                         if (ch != nr)
589                                 s.push_back(ch);
590                 }
591                 to_del = this->nodes_.size();
592                 #pragma omp parallel for reduction(min: to_del)
593                 for (i = 0; i < this->nodes_.size(); i++) {
594                         if (this->nodes_[i] == tmp)
595                                 to_del = i;
596                 }
597                 if (to_del < this->nodes_.size())
598                         this->nodes_.erase(this->nodes_.begin() + to_del);
599 #if NNVERSION > 1
600                 iy = IYI(tmp->y());
601                 to_del = this->iy_[iy].size();
602                 #pragma omp parallel  for reduction(min: to_del)
603                 for (i = 0; i < this->iy_[iy].size(); i++) {
604                         if (this->iy_[iy][i] == tmp)
605                                 to_del = i;
606                 }
607                 if (to_del < this->iy_[iy].size())
608                         this->iy_[iy].erase(this->iy_[iy].begin() + to_del);
609 #endif
610                 this->dnodes().push_back(tmp);
611         }
612         this->root_ = nr;
613         this->root_->remove_parent();
614         return true;
615 }
616
617 std::vector<RRTNode *> RRTBase::findt()
618 {
619         return this->findt(this->goal_);
620 }
621
622 std::vector<RRTNode *> RRTBase::findt(RRTNode *n)
623 {
624         std::vector<RRTNode *> nodes;
625         if (!n || !n->parent())
626                 return nodes;
627         RRTNode *tmp = n;
628         while (tmp) {
629                 nodes.push_back(tmp);
630                 tmp = tmp->parent();
631         }
632         return nodes;
633 }