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