]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blob - base/rrtbase.cc
Merge branch 'feature/move-opt-path-to-base'
[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 (pow(xx + yy, 0.5) < this->GOAL_FOUND_DISTANCE &&
308                         dh < this->GOAL_FOUND_ANGLE) {
309                 if (this->goal_found_) {
310                         if (node->ccost() + (*cost)(node, this->goal_) <
311                                         this->goal_->ccost()) {
312                                 RRTNode *op; // old parent
313                                 float oc; // old cumulative cost
314                                 float od; // old direct cost
315                                 op = this->goal_->parent();
316                                 oc = this->goal_->ccost();
317                                 od = this->goal_->dcost();
318                                 node->add_child(this->goal_,
319                                                 (*cost)(node, this->goal_));
320                                 if (this->collide(node, this->goal_)) {
321                                         node->children().pop_back();
322                                         this->goal_->parent(op);
323                                         this->goal_->ccost(oc);
324                                         this->goal_->dcost(od);
325                                 } else {
326                                         op->rem_child(this->goal_);
327                                         return true;
328                                 }
329                         } else {
330                                 return false;
331                         }
332                 } else {
333                         node->add_child(
334                                         this->goal_,
335                                         (*cost)(node, this->goal_));
336                         if (this->collide(node, this->goal_)) {
337                                 node->children().pop_back();
338                                 this->goal_->remove_parent();
339                                 return false;
340                         }
341                         this->goal_found_ = true;
342                         return true;
343                 }
344         }
345         return false;
346 }
347
348 bool RRTBase::collide(RRTNode *init, RRTNode *goal)
349 {
350         std::vector<RRTEdge *> edges;
351         RRTNode *tmp = goal;
352         volatile bool col = false;
353         unsigned int i;
354         while (tmp != init) {
355                 BicycleCar bc(tmp->x(), tmp->y(), tmp->h());
356                 std::vector<RRTEdge *> bcframe = bc.frame();
357                 #pragma omp parallel for reduction(|: col)
358                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
359                         if ((*this->cobstacles_)[i].collide(tmp)) {
360                                 col = true;
361                         }
362                         // TODO collide with car frame
363                 }
364                 if (col) {
365                         for (auto e: bcframe) {
366                                 delete e->init();
367                                 delete e->goal();
368                                 delete e;
369                         }
370                         for (auto e: edges) {
371                                 delete e;
372                         }
373                         return true;
374                 }
375                 #pragma omp parallel for reduction(|: col)
376                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
377                         for (auto &e: bcframe) {
378                                 if ((*this->sobstacles_)[i].collide(e)) {
379                                         col = true;
380                                 }
381                         }
382                 }
383                 if (col) {
384                         for (auto e: bcframe) {
385                                 delete e->init();
386                                 delete e->goal();
387                                 delete e;
388                         }
389                         for (auto e: edges) {
390                                 delete e;
391                         }
392                         return true;
393                 }
394                 if (!tmp->parent()) {
395                         break;
396                 }
397                 edges.push_back(new RRTEdge(tmp, tmp->parent()));
398                 tmp = tmp->parent();
399                 for (auto e: bcframe) {
400                         delete e->init();
401                         delete e->goal();
402                         delete e;
403                 }
404         }
405         for (auto &e: edges) {
406                 #pragma omp parallel for reduction(|: col)
407                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
408                         if ((*this->cobstacles_)[i].collide(e)) {
409                                 col = true;
410                         }
411                 }
412                 if (col) {
413                         for (auto e: edges) {
414                                 delete e;
415                         }
416                         return true;
417                 }
418                 #pragma omp parallel for reduction(|: col)
419                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
420                         if ((*this->sobstacles_)[i].collide(e)) {
421                                 col = true;
422                         }
423                 }
424                 if (col) {
425                         for (auto e: edges) {
426                                 delete e;
427                         }
428                         return true;
429                 }
430         }
431         for (auto e: edges) {
432                 delete e;
433         }
434         return false;
435 }
436
437 class RRTNodeDijkstra {
438         public:
439                 RRTNodeDijkstra(int i):
440                         ni(i),
441                         pi(0),
442                         c(9999),
443                         v(false)
444                 {};
445                 RRTNodeDijkstra(int i, float c):
446                         ni(i),
447                         pi(0),
448                         c(c),
449                         v(false)
450                 {};
451                 RRTNodeDijkstra(int i, int p, float c):
452                         ni(i),
453                         pi(p),
454                         c(c),
455                         v(false)
456                 {};
457                 unsigned int ni;
458                 unsigned int pi;
459                 float c;
460                 bool v;
461                 bool vi()
462                 {
463                         if (this->v)
464                                 return true;
465                         this->v = true;
466                         return false;
467                 };
468 };
469
470 class RRTNodeDijkstraComparator {
471         public:
472                 int operator() (
473                                 const RRTNodeDijkstra& n1,
474                                 const RRTNodeDijkstra& n2)
475                 {
476                         return n1.c > n2.c;
477                 }
478 };
479
480 bool RRTBase::opt_path()
481 {
482         if (this->tlog().size() == 0)
483                 return false;
484         float oc = this->tlog().back().front()->ccost();
485         std::vector<RRTNode *> tmp_cusps;
486         for (auto n: this->tlog().back()) {
487                 if (sgn(n->s()) == 0) {
488                         tmp_cusps.push_back(n);
489                 } else if (n->parent() &&
490                                 sgn(n->s()) != sgn(n->parent()->s())) {
491                         tmp_cusps.push_back(n);
492                         tmp_cusps.push_back(n->parent());
493                 }
494         }
495         if (tmp_cusps.size() < 2)
496                 return false;
497         std::vector<RRTNode *> cusps;
498         for (unsigned int i = 0; i < tmp_cusps.size(); i++) {
499                 if (tmp_cusps[i] != tmp_cusps[i + 1])
500                         cusps.push_back(tmp_cusps[i]);
501         }
502         std::reverse(cusps.begin(), cusps.end());
503         // Begin of Dijkstra
504         std::vector<RRTNodeDijkstra> dnodes;
505         for (unsigned int i = 0; i < cusps.size(); i++)
506                 if (i > 0)
507                         dnodes.push_back(RRTNodeDijkstra(
508                                                 i,
509                                                 i - 1,
510                                                 cusps[i]->ccost()));
511                 else
512                         dnodes.push_back(RRTNodeDijkstra(
513                                                 i,
514                                                 cusps[i]->ccost()));
515         dnodes[0].vi();
516         std::priority_queue<
517                 RRTNodeDijkstra,
518                 std::vector<RRTNodeDijkstra>,
519                 RRTNodeDijkstraComparator> pq;
520         RRTNodeDijkstra tmp = dnodes[0];
521         pq.push(tmp);
522         float ch_cost = 9999;
523         std::vector<RRTNode *> steered;
524         while (!pq.empty() && tmp.ni != cusps.size() - 1) {
525                 tmp = pq.top();
526                 pq.pop();
527                 for (unsigned int i = tmp.ni + 1; i < cusps.size(); i++) {
528                         ch_cost = dnodes[tmp.ni].c +
529                                 CO(cusps[tmp.ni], cusps[i]);
530                         steered = ST(cusps[tmp.ni], cusps[i]);
531                         for (unsigned int j = 0; j < steered.size() - 1; j++)
532                                 steered[j]->add_child(
533                                                 steered[j + 1],
534                                                 CO(
535                                                         steered[j],
536                                                         steered[j + 1]));
537                         if (i != tmp.ni + 1 && this->collide( // TODO
538                                                 steered[0],
539                                                 steered[steered.size() - 1]))
540                                 continue;
541                         if (ch_cost < dnodes[i].c) {
542                                 dnodes[i].c = ch_cost;
543                                 dnodes[i].pi = tmp.ni;
544                                 if (!dnodes[i].vi())
545                                         pq.push(dnodes[i]);
546                         }
547                 }
548         }
549         if (tmp.ni != cusps.size() - 1)
550                 return false;
551         std::vector<int> npi; // new path indexes
552         int tmpi = tmp.ni;
553         while (tmpi > 0) {
554                 npi.push_back(tmpi);
555                 tmpi = dnodes[tmpi].pi;
556         }
557         npi.push_back(tmpi);
558         std::reverse(npi.begin(), npi.end());
559         RRTNode *pn = cusps[npi[0]];
560         for (unsigned int i = 0; i < npi.size() - 1; i++) {
561                 for (auto ns: ST(cusps[npi[i]], cusps[npi[i + 1]])) {
562                         pn->add_child(ns, CO(pn, ns));
563                         pn = ns;
564                 }
565         }
566         pn->add_child(
567                         this->tlog().back().front(),
568                         CO(pn, this->tlog().back().front()));
569         // End of Dijkstra
570         if (this->tlog().back().front()->ccost() < oc)
571                 return true;
572         return false;
573 }
574
575 bool RRTBase::rebase(RRTNode *nr)
576 {
577         if (!nr || this->goal_ == nr || this->root_ == nr)
578                 return false;
579         std::vector<RRTNode *> s; // DFS stack
580         RRTNode *tmp;
581         unsigned int i = 0;
582         unsigned int to_del = 0;
583         int iy = 0;
584         s.push_back(this->root_);
585         while (s.size() > 0) {
586                 tmp = s.back();
587                 s.pop_back();
588                 for (auto ch: tmp->children()) {
589                         if (ch != nr)
590                                 s.push_back(ch);
591                 }
592                 to_del = this->nodes_.size();
593                 #pragma omp parallel for reduction(min: to_del)
594                 for (i = 0; i < this->nodes_.size(); i++) {
595                         if (this->nodes_[i] == tmp)
596                                 to_del = i;
597                 }
598                 if (to_del < this->nodes_.size())
599                         this->nodes_.erase(this->nodes_.begin() + to_del);
600 #if NNVERSION > 1
601                 iy = IYI(tmp->y());
602                 to_del = this->iy_[iy].size();
603                 #pragma omp parallel  for reduction(min: to_del)
604                 for (i = 0; i < this->iy_[iy].size(); i++) {
605                         if (this->iy_[iy][i] == tmp)
606                                 to_del = i;
607                 }
608                 if (to_del < this->iy_[iy].size())
609                         this->iy_[iy].erase(this->iy_[iy].begin() + to_del);
610 #endif
611                 this->dnodes().push_back(tmp);
612         }
613         this->root_ = nr;
614         this->root_->remove_parent();
615         return true;
616 }
617
618 std::vector<RRTNode *> RRTBase::findt()
619 {
620         return this->findt(this->goal_);
621 }
622
623 std::vector<RRTNode *> RRTBase::findt(RRTNode *n)
624 {
625         std::vector<RRTNode *> nodes;
626         if (!n || !n->parent())
627                 return nodes;
628         RRTNode *tmp = n;
629         while (tmp) {
630                 nodes.push_back(tmp);
631                 tmp = tmp->parent();
632         }
633         return nodes;
634 }