]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blob - base/rrtbase.cc
Not return trajectory if init node is null
[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 <cmath>
19 #include <omp.h>
20 #include "bcar.h"
21 #include "rrtbase.h"
22 // OpenGL
23 #include <GL/gl.h>
24 #include <GL/glu.h>
25 #include <SDL2/SDL.h>
26
27 extern SDL_Window* gw;
28 extern SDL_GLContext gc;
29
30 RRTBase::~RRTBase()
31 {
32         for (auto n: this->nodes_)
33                 if (n != this->root_)
34                         delete n;
35         for (auto n: this->dnodes_)
36                 if (n != this->root_ && n != this->goal_)
37                         delete n;
38         for (auto s: this->samples_)
39                 if (s != this->goal_)
40                         delete s;
41         for (auto edges: this->rlog_)
42                 for (auto e: edges)
43                         delete e;
44         delete this->root_;
45         delete this->goal_;
46 }
47
48 RRTBase::RRTBase():
49         root_(new RRTNode()),
50         goal_(new RRTNode())
51 {
52         this->nodes_.push_back(this->root_);
53         this->add_iy(this->root_);
54 }
55
56 RRTBase::RRTBase(RRTNode *init, RRTNode *goal):
57         root_(init),
58         goal_(goal)
59 {
60         this->nodes_.push_back(init);
61         this->add_iy(init);
62 }
63
64 RRTNode *RRTBase::root()
65 {
66         return this->root_;
67 }
68
69 RRTNode *RRTBase::goal()
70 {
71         return this->goal_;
72 }
73
74 std::vector<RRTNode *> &RRTBase::nodes()
75 {
76         return this->nodes_;
77 }
78
79 std::vector<RRTNode *> &RRTBase::dnodes()
80 {
81         return this->dnodes_;
82 }
83
84 std::vector<RRTNode *> &RRTBase::samples()
85 {
86         return this->samples_;
87 }
88
89 std::vector<CircleObstacle> *RRTBase::cos()
90 {
91         return this->cobstacles_;
92 }
93
94 std::vector<SegmentObstacle> *RRTBase::sos()
95 {
96         return this->sobstacles_;
97 }
98
99 std::vector<float> &RRTBase::clog()
100 {
101         return this->clog_;
102 }
103
104 std::vector<float> &RRTBase::nlog()
105 {
106         return this->nlog_;
107 }
108
109 std::vector<std::vector<RRTEdge *>> &RRTBase::rlog()
110 {
111         return this->rlog_;
112 }
113
114 std::vector<float> &RRTBase::slog()
115 {
116         return this->slog_;
117 }
118
119 std::vector<std::vector<RRTNode *>> &RRTBase::tlog()
120 {
121         return this->tlog_;
122 }
123
124 bool RRTBase::goal_found()
125 {
126         return this->goal_found_;
127 }
128
129 float RRTBase::elapsed()
130 {
131         std::chrono::duration<float> dt;
132         dt = std::chrono::duration_cast<std::chrono::duration<float>>(
133                         this->tend_ - this->tstart_);
134         return dt.count();
135 }
136
137 bool RRTBase::logr(RRTNode *root)
138 {
139         std::vector<RRTEdge *> e; // Edges to log
140         std::vector<RRTNode *> s; // DFS stack
141         std::vector<RRTNode *> r; // reset visited_
142         RRTNode *tmp;
143         s.push_back(root);
144         while (s.size() > 0) {
145                 tmp = s.back();
146                 s.pop_back();
147                 if (!tmp->visit()) {
148                         r.push_back(tmp);
149                         for (auto ch: tmp->children()) {
150                                 s.push_back(ch);
151                                 e.push_back(new RRTEdge(tmp, ch));
152                         }
153                 }
154         }
155         for (auto n: r)
156                 n->visit(false);
157         this->rlog_.push_back(e);
158         return true;
159 }
160
161 float RRTBase::ocost(RRTNode *n)
162 {
163         float dist = 9999;
164         for (auto o: *this->cobstacles_)
165                 if (o.dist_to(n) < dist)
166                         dist = o.dist_to(n);
167         for (auto o: *this->sobstacles_)
168                 if (o.dist_to(n) < dist)
169                         dist = o.dist_to(n);
170         return n->ocost(dist);
171 }
172
173 bool RRTBase::tlog(std::vector<RRTNode *> t)
174 {
175         if (t.size() > 0) {
176                 this->slog_.push_back(this->elapsed());
177                 this->clog_.push_back(t.front()->ccost() - t.back()->ccost());
178                 this->nlog_.push_back(this->nodes_.size());
179                 this->tlog_.push_back(t);
180                 return true;
181         } else {
182                 return false;
183         }
184 }
185
186 void RRTBase::tstart()
187 {
188         this->tstart_ = std::chrono::high_resolution_clock::now();
189 }
190
191 void RRTBase::tend()
192 {
193         this->tend_ = std::chrono::high_resolution_clock::now();
194 }
195
196 bool RRTBase::link_obstacles(
197                 std::vector<CircleObstacle> *cobstacles,
198                 std::vector<SegmentObstacle> *sobstacles)
199 {
200         this->cobstacles_ = cobstacles;
201         this->sobstacles_ = sobstacles;
202         if (!this->cobstacles_ || !this->sobstacles_) {
203                 return false;
204         }
205         return true;
206 }
207
208 bool RRTBase::add_iy(RRTNode *n)
209 {
210         int i = IYI(n->y());
211         if (i < 0)
212                 i = 0;
213         if (i >= IYSIZE)
214                 i = IYSIZE - 1;
215         this->iy_[i].push_back(n);
216         return true;
217 }
218
219 bool RRTBase::glplot()
220 {
221         glClear(GL_COLOR_BUFFER_BIT);
222         glLineWidth(1);
223         glPointSize(1);
224         // Plot obstacles
225         glBegin(GL_LINES);
226         for (auto o: *this->sobstacles_) {
227                 glColor3f(0, 0, 0);
228                 glVertex2f(GLVERTEX(o.init()));
229                 glVertex2f(GLVERTEX(o.goal()));
230         }
231         glEnd();
232         // Plot root, goal
233         glPointSize(8);
234         glBegin(GL_POINTS);
235         glColor3f(1, 0, 0);
236         glVertex2f(GLVERTEX(this->root_));
237         glVertex2f(GLVERTEX(this->goal_));
238         glEnd();
239         // Plot last sample
240         glPointSize(8);
241         glBegin(GL_POINTS);
242         glColor3f(0, 1, 0);
243         glVertex2f(GLVERTEX(this->samples_.back()));
244         glEnd();
245         // Plot nodes
246         std::vector<RRTNode *> s; // DFS stack
247         std::vector<RRTNode *> r; // reset visited_
248         RRTNode *tmp;
249         glBegin(GL_LINES);
250         s.push_back(this->root_);
251         while (s.size() > 0) {
252                 tmp = s.back();
253                 s.pop_back();
254                 if (!tmp->visit()) {
255                         r.push_back(tmp);
256                         for (auto ch: tmp->children()) {
257                                 s.push_back(ch);
258                                 glColor3f(0.5, 0.5, 0.5);
259                                 glVertex2f(GLVERTEX(tmp));
260                                 glVertex2f(GLVERTEX(ch));
261                         }
262                 }
263         }
264         glEnd();
265         std::vector<RRTNode *> cusps;
266         // Plot last trajectory
267         if (this->tlog().size() > 0) {
268                 glLineWidth(2);
269                 glBegin(GL_LINES);
270                 for (auto n: this->tlog().back()) {
271                         if (n->parent()) {
272                                 glColor3f(0, 0, 1);
273                                 glVertex2f(GLVERTEX(n));
274                                 glVertex2f(GLVERTEX(n->parent()));
275                                 if (sgn(n->s()) != sgn(n->parent()->s()))
276                                         cusps.push_back(n);
277                         }
278                 }
279                 glEnd();
280         }
281         // Plot cusps
282         glPointSize(8);
283         glBegin(GL_POINTS);
284         for (auto n: cusps) {
285                 glColor3f(0, 0, 1);
286                 glVertex2f(GLVERTEX(n));
287         }
288         glEnd();
289         SDL_GL_SwapWindow(gw);
290         for (auto n: r)
291                 n->visit(false);
292         return true;
293 }
294
295 bool RRTBase::goal_found(
296                 RRTNode *node,
297                 float (*cost)(RRTNode *, RRTNode* ))
298 {
299         float xx = pow(node->x() - this->goal_->x(), 2);
300         float yy = pow(node->y() - this->goal_->y(), 2);
301         float dh = std::abs(node->h() - this->goal_->h());
302         if (pow(xx + yy, 0.5) < this->GOAL_FOUND_DISTANCE &&
303                         dh < this->GOAL_FOUND_ANGLE) {
304                 if (this->goal_found_) {
305                         if (node->ccost() + (*cost)(node, this->goal_) <
306                                         this->goal_->ccost()) {
307                                 RRTNode *op; // old parent
308                                 float oc; // old cumulative cost
309                                 float od; // old direct cost
310                                 op = this->goal_->parent();
311                                 oc = this->goal_->ccost();
312                                 od = this->goal_->dcost();
313                                 node->add_child(this->goal_,
314                                                 (*cost)(node, this->goal_));
315                                 if (this->collide(node, this->goal_)) {
316                                         node->children().pop_back();
317                                         this->goal_->parent(op);
318                                         this->goal_->ccost(oc);
319                                         this->goal_->dcost(od);
320                                 } else {
321                                         op->rem_child(this->goal_);
322                                         return true;
323                                 }
324                         } else {
325                                 return false;
326                         }
327                 } else {
328                         node->add_child(
329                                         this->goal_,
330                                         (*cost)(node, this->goal_));
331                         if (this->collide(node, this->goal_)) {
332                                 node->children().pop_back();
333                                 this->goal_->remove_parent();
334                                 return false;
335                         }
336                         this->goal_found_ = true;
337                         return true;
338                 }
339         }
340         return false;
341 }
342
343 bool RRTBase::collide(RRTNode *init, RRTNode *goal)
344 {
345         std::vector<RRTEdge *> edges;
346         RRTNode *tmp = goal;
347         volatile bool col = false;
348         unsigned int i;
349         while (tmp != init) {
350                 BicycleCar bc(tmp->x(), tmp->y(), tmp->h());
351                 std::vector<RRTEdge *> bcframe = bc.frame();
352                 #pragma omp parallel for reduction(|: col)
353                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
354                         if ((*this->cobstacles_)[i].collide(tmp)) {
355                                 col = true;
356                         }
357                         // TODO collide with car frame
358                 }
359                 if (col) {
360                         for (auto e: bcframe) {
361                                 delete e->init();
362                                 delete e->goal();
363                                 delete e;
364                         }
365                         for (auto e: edges) {
366                                 delete e;
367                         }
368                         return true;
369                 }
370                 #pragma omp parallel for reduction(|: col)
371                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
372                         for (auto &e: bcframe) {
373                                 if ((*this->sobstacles_)[i].collide(e)) {
374                                         col = true;
375                                 }
376                         }
377                 }
378                 if (col) {
379                         for (auto e: bcframe) {
380                                 delete e->init();
381                                 delete e->goal();
382                                 delete e;
383                         }
384                         for (auto e: edges) {
385                                 delete e;
386                         }
387                         return true;
388                 }
389                 if (!tmp->parent()) {
390                         break;
391                 }
392                 edges.push_back(new RRTEdge(tmp, tmp->parent()));
393                 tmp = tmp->parent();
394                 for (auto e: bcframe) {
395                         delete e->init();
396                         delete e->goal();
397                         delete e;
398                 }
399         }
400         for (auto &e: edges) {
401                 #pragma omp parallel for reduction(|: col)
402                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
403                         if ((*this->cobstacles_)[i].collide(e)) {
404                                 col = true;
405                         }
406                 }
407                 if (col) {
408                         for (auto e: edges) {
409                                 delete e;
410                         }
411                         return true;
412                 }
413                 #pragma omp parallel for reduction(|: col)
414                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
415                         if ((*this->sobstacles_)[i].collide(e)) {
416                                 col = true;
417                         }
418                 }
419                 if (col) {
420                         for (auto e: edges) {
421                                 delete e;
422                         }
423                         return true;
424                 }
425         }
426         for (auto e: edges) {
427                 delete e;
428         }
429         return false;
430 }
431
432 bool RRTBase::rebase(RRTNode *nr)
433 {
434         if (this->goal_ == nr || this->root_ == nr)
435                 return false;
436         std::vector<RRTNode *> s; // DFS stack
437         RRTNode *tmp;
438         unsigned int i = 0;
439         unsigned int to_del = 0;
440         int iy = 0;
441         s.push_back(this->root_);
442         while (s.size() > 0) {
443                 tmp = s.back();
444                 s.pop_back();
445                 for (auto ch: tmp->children()) {
446                         if (ch != nr)
447                                 s.push_back(ch);
448                 }
449                 to_del = this->nodes_.size();
450                 #pragma omp parallel for reduction(min: to_del)
451                 for (i = 0; i < this->nodes_.size(); i++) {
452                         if (this->nodes_[i] == tmp)
453                                 to_del = i;
454                 }
455                 if (to_del < this->nodes_.size())
456                         this->nodes_.erase(this->nodes_.begin() + to_del);
457 #if NNVERSION > 1
458                 iy = IYI(tmp->y());
459                 to_del = this->iy_[iy].size();
460                 #pragma omp parallel  for reduction(min: to_del)
461                 for (i = 0; i < this->iy_[iy].size(); i++) {
462                         if (this->iy_[iy][i] == tmp)
463                                 to_del = i;
464                 }
465                 if (to_del < this->iy_[iy].size())
466                         this->iy_[iy].erase(this->iy_[iy].begin() + to_del);
467 #endif
468                 this->dnodes().push_back(tmp);
469         }
470         this->root_ = nr;
471         this->root_->remove_parent();
472         return true;
473 }
474
475 std::vector<RRTNode *> RRTBase::findt()
476 {
477         return this->findt(this->goal_);
478 }
479
480 std::vector<RRTNode *> RRTBase::findt(RRTNode *n)
481 {
482         std::vector<RRTNode *> nodes;
483         if (!n || !n->parent())
484                 return nodes;
485         RRTNode *tmp = n;
486         while (tmp) {
487                 nodes.push_back(tmp);
488                 tmp = tmp->parent();
489         }
490         return nodes;
491 }