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