]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blob - base/rrtbase.cc
Plot last sample, plot bigger root, goal
[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         // Plot last trajectory
266         if (this->tlog().size() > 0) {
267                 glLineWidth(2);
268                 glBegin(GL_LINES);
269                 for (auto n: this->tlog().back()) {
270                         if (n->parent()) {
271                                 glColor3f(0, 0, 1);
272                                 glVertex2f(GLVERTEX(n));
273                                 glVertex2f(GLVERTEX(n->parent()));
274                         }
275                 }
276                 glEnd();
277         }
278         SDL_GL_SwapWindow(gw);
279         for (auto n: r)
280                 n->visit(false);
281         return true;
282 }
283
284 bool RRTBase::goal_found(
285                 RRTNode *node,
286                 float (*cost)(RRTNode *, RRTNode* ))
287 {
288         float xx = pow(node->x() - this->goal_->x(), 2);
289         float yy = pow(node->y() - this->goal_->y(), 2);
290         float dh = std::abs(node->h() - this->goal_->h());
291         if (pow(xx + yy, 0.5) < this->GOAL_FOUND_DISTANCE &&
292                         dh < this->GOAL_FOUND_ANGLE) {
293                 if (this->goal_found_) {
294                         if (node->ccost() + (*cost)(node, this->goal_) <
295                                         this->goal_->ccost()) {
296                                 RRTNode *op; // old parent
297                                 float oc; // old cumulative cost
298                                 float od; // old direct cost
299                                 op = this->goal_->parent();
300                                 oc = this->goal_->ccost();
301                                 od = this->goal_->dcost();
302                                 node->add_child(this->goal_,
303                                                 (*cost)(node, this->goal_));
304                                 if (this->collide(node, this->goal_)) {
305                                         node->children().pop_back();
306                                         this->goal_->parent(op);
307                                         this->goal_->ccost(oc);
308                                         this->goal_->dcost(od);
309                                 } else {
310                                         op->rem_child(this->goal_);
311                                         return true;
312                                 }
313                         } else {
314                                 return false;
315                         }
316                 } else {
317                         node->add_child(
318                                         this->goal_,
319                                         (*cost)(node, this->goal_));
320                         if (this->collide(node, this->goal_)) {
321                                 node->children().pop_back();
322                                 this->goal_->remove_parent();
323                                 return false;
324                         }
325                         this->goal_found_ = true;
326                         return true;
327                 }
328         }
329         return false;
330 }
331
332 bool RRTBase::collide(RRTNode *init, RRTNode *goal)
333 {
334         std::vector<RRTEdge *> edges;
335         RRTNode *tmp = goal;
336         volatile bool col = false;
337         unsigned int i;
338         while (tmp != init) {
339                 BicycleCar bc(tmp->x(), tmp->y(), tmp->h());
340                 std::vector<RRTEdge *> bcframe = bc.frame();
341                 #pragma omp parallel for reduction(|: col)
342                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
343                         if ((*this->cobstacles_)[i].collide(tmp)) {
344                                 col = true;
345                         }
346                         // TODO collide with car frame
347                 }
348                 if (col) {
349                         for (auto e: bcframe) {
350                                 delete e->init();
351                                 delete e->goal();
352                                 delete e;
353                         }
354                         for (auto e: edges) {
355                                 delete e;
356                         }
357                         return true;
358                 }
359                 #pragma omp parallel for reduction(|: col)
360                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
361                         for (auto &e: bcframe) {
362                                 if ((*this->sobstacles_)[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                 if (!tmp->parent()) {
379                         break;
380                 }
381                 edges.push_back(new RRTEdge(tmp, tmp->parent()));
382                 tmp = tmp->parent();
383                 for (auto e: bcframe) {
384                         delete e->init();
385                         delete e->goal();
386                         delete e;
387                 }
388         }
389         for (auto &e: edges) {
390                 #pragma omp parallel for reduction(|: col)
391                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
392                         if ((*this->cobstacles_)[i].collide(e)) {
393                                 col = true;
394                         }
395                 }
396                 if (col) {
397                         for (auto e: edges) {
398                                 delete e;
399                         }
400                         return true;
401                 }
402                 #pragma omp parallel for reduction(|: col)
403                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
404                         if ((*this->sobstacles_)[i].collide(e)) {
405                                 col = true;
406                         }
407                 }
408                 if (col) {
409                         for (auto e: edges) {
410                                 delete e;
411                         }
412                         return true;
413                 }
414         }
415         for (auto e: edges) {
416                 delete e;
417         }
418         return false;
419 }
420
421 bool RRTBase::rebase(RRTNode *nr)
422 {
423         if (this->goal_ == nr || this->root_ == nr)
424                 return false;
425         std::vector<RRTNode *> s; // DFS stack
426         RRTNode *tmp;
427         unsigned int i = 0;
428         unsigned int to_del = 0;
429         int iy = 0;
430         s.push_back(this->root_);
431         while (s.size() > 0) {
432                 tmp = s.back();
433                 s.pop_back();
434                 for (auto ch: tmp->children()) {
435                         if (ch != nr)
436                                 s.push_back(ch);
437                 }
438                 to_del = this->nodes_.size();
439                 #pragma omp parallel for reduction(min: to_del)
440                 for (i = 0; i < this->nodes_.size(); i++) {
441                         if (this->nodes_[i] == tmp)
442                                 to_del = i;
443                 }
444                 if (to_del < this->nodes_.size())
445                         this->nodes_.erase(this->nodes_.begin() + to_del);
446 #if NNVERSION > 1
447                 iy = IYI(tmp->y());
448                 to_del = this->iy_[iy].size();
449                 #pragma omp parallel  for reduction(min: to_del)
450                 for (i = 0; i < this->iy_[iy].size(); i++) {
451                         if (this->iy_[iy][i] == tmp)
452                                 to_del = i;
453                 }
454                 if (to_del < this->iy_[iy].size())
455                         this->iy_[iy].erase(this->iy_[iy].begin() + to_del);
456 #endif
457                 this->dnodes().push_back(tmp);
458         }
459         this->root_ = nr;
460         this->root_->remove_parent();
461         return true;
462 }
463
464 std::vector<RRTNode *> RRTBase::findt()
465 {
466         return this->findt(this->goal_);
467 }
468
469 std::vector<RRTNode *> RRTBase::findt(RRTNode *n)
470 {
471         std::vector<RRTNode *> nodes;
472         if (!n->parent())
473                 return nodes;
474         RRTNode *tmp = n;
475         while (tmp) {
476                 nodes.push_back(tmp);
477                 tmp = tmp->parent();
478         }
479         return nodes;
480 }