]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blob - base/rrtbase.cc
Fix scaling for `iy_` nearest neighbour structure
[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 bool RRTBase::tlog(std::vector<RRTNode *> t)
155 {
156         this->slog_.push_back(this->elapsed());
157         this->clog_.push_back(this->goal_->ccost());
158         this->nlog_.push_back(this->nodes_.size());
159         this->tlog_.push_back(t);
160         return true;
161 }
162
163 void RRTBase::tstart()
164 {
165         this->tstart_ = std::chrono::high_resolution_clock::now();
166 }
167
168 void RRTBase::tend()
169 {
170         this->tend_ = std::chrono::high_resolution_clock::now();
171 }
172
173 bool RRTBase::link_obstacles(
174                 std::vector<CircleObstacle> *cobstacles,
175                 std::vector<SegmentObstacle> *sobstacles)
176 {
177         this->cobstacles_ = cobstacles;
178         this->sobstacles_ = sobstacles;
179         if (!this->cobstacles_ || !this->sobstacles_) {
180                 return false;
181         }
182         return true;
183 }
184
185 bool RRTBase::add_iy(RRTNode *n)
186 {
187         int i = floor(n->y() / IYSTEP);
188         this->iy_[i].push_back(n);
189         return true;
190 }
191
192 bool RRTBase::goal_found(
193                 RRTNode *node,
194                 float (*cost)(RRTNode *, RRTNode* ))
195 {
196         float xx = pow(node->x() - this->goal_->x(), 2);
197         float yy = pow(node->y() - this->goal_->y(), 2);
198         float dh = std::abs(node->h() - this->goal_->h());
199         if (pow(xx + yy, 0.5) < this->GOAL_FOUND_DISTANCE &&
200                         dh < this->GOAL_FOUND_ANGLE) {
201                 if (this->goal_found_) {
202                         if (node->ccost() + (*cost)(node, this->goal_) <
203                                         this->goal_->ccost()) {
204                                 RRTNode *op; // old parent
205                                 float oc; // old cumulative cost
206                                 float od; // old direct cost
207                                 op = this->goal_->parent();
208                                 oc = this->goal_->ccost();
209                                 od = this->goal_->dcost();
210                                 node->add_child(this->goal_,
211                                                 (*cost)(node, this->goal_));
212                                 if (this->collide(node, this->goal_)) {
213                                         node->children().pop_back();
214                                         this->goal_->parent(op);
215                                         this->goal_->ccost(oc);
216                                         this->goal_->dcost(od);
217                                 } else {
218                                         op->rem_child(this->goal_);
219                                         return true;
220                                 }
221                         } else {
222                                 return false;
223                         }
224                 } else {
225                         node->add_child(
226                                         this->goal_,
227                                         (*cost)(node, this->goal_));
228                         if (this->collide(node, this->goal_)) {
229                                 node->children().pop_back();
230                                 this->goal_->remove_parent();
231                                 return false;
232                         }
233                         this->goal_found_ = true;
234                         return true;
235                 }
236         }
237         return false;
238 }
239
240 bool RRTBase::collide(RRTNode *init, RRTNode *goal)
241 {
242         std::vector<RRTEdge *> edges;
243         RRTNode *tmp = goal;
244         volatile bool col = false;
245         unsigned int i;
246         while (tmp != init) {
247                 BicycleCar bc(tmp->x(), tmp->y(), tmp->h());
248                 std::vector<RRTEdge *> bcframe = bc.frame();
249                 #pragma omp parallel for reduction(|: col)
250                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
251                         if ((*this->cobstacles_)[i].collide(tmp)) {
252                                 col = true;
253                         }
254                         // TODO collide with car frame
255                 }
256                 if (col) {
257                         for (auto e: bcframe) {
258                                 delete e->init();
259                                 delete e->goal();
260                                 delete e;
261                         }
262                         for (auto e: edges) {
263                                 delete e;
264                         }
265                         return true;
266                 }
267                 #pragma omp parallel for reduction(|: col)
268                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
269                         for (auto &e: bcframe) {
270                                 if ((*this->sobstacles_)[i].collide(e)) {
271                                         col = true;
272                                 }
273                         }
274                 }
275                 if (col) {
276                         for (auto e: bcframe) {
277                                 delete e->init();
278                                 delete e->goal();
279                                 delete e;
280                         }
281                         for (auto e: edges) {
282                                 delete e;
283                         }
284                         return true;
285                 }
286                 if (!tmp->parent()) {
287                         break;
288                 }
289                 edges.push_back(new RRTEdge(tmp, tmp->parent()));
290                 tmp = tmp->parent();
291                 for (auto e: bcframe) {
292                         delete e->init();
293                         delete e->goal();
294                         delete e;
295                 }
296         }
297         for (auto &e: edges) {
298                 #pragma omp parallel for reduction(|: col)
299                 for (i = 0; i < (*this->cobstacles_).size(); i++) {
300                         if ((*this->cobstacles_)[i].collide(e)) {
301                                 col = true;
302                         }
303                 }
304                 if (col) {
305                         for (auto e: edges) {
306                                 delete e;
307                         }
308                         return true;
309                 }
310                 #pragma omp parallel for reduction(|: col)
311                 for (i = 0; i < (*this->sobstacles_).size(); i++) {
312                         if ((*this->sobstacles_)[i].collide(e)) {
313                                 col = true;
314                         }
315                 }
316                 if (col) {
317                         for (auto e: edges) {
318                                 delete e;
319                         }
320                         return true;
321                 }
322         }
323         for (auto e: edges) {
324                 delete e;
325         }
326         return false;
327 }
328
329 bool RRTBase::rebase(RRTNode *nr)
330 {
331         std::vector<RRTNode *> s; // DFS stack
332         RRTNode *tmp;
333         unsigned int i = 0;
334         unsigned int to_del = 0;
335         int iy = 0;
336         s.push_back(this->root_);
337         while (s.size() > 0) {
338                 tmp = s.back();
339                 s.pop_back();
340                 for (auto ch: tmp->children()) {
341                         if (ch != nr)
342                                 s.push_back(ch);
343                 }
344                 to_del = this->nodes_.size();
345                 #pragma omp parallel for reduction(min: to_del)
346                 for (i = 0; i < this->nodes_.size(); i++) {
347                         if (this->nodes_[i] == tmp)
348                                 to_del = i;
349                 }
350                 if (to_del < this->nodes_.size())
351                         this->nodes_.erase(this->nodes_.begin() + to_del);
352                 to_del = this->samples_.size();
353                 #pragma omp parallel for reduction(min: to_del)
354                 for (i = 0; i < this->samples_.size(); i++) {
355                         if (this->samples_[i] == tmp)
356                                 to_del = i;
357                 }
358                 if (to_del < this->samples_.size())
359                         this->samples_.erase(this->nodes_.begin() + to_del);
360                 iy = floor(tmp->y() / IYSTEP);
361                 to_del = this->iy_[iy].size();
362                 #pragma omp parallel  for reduction(min: to_del)
363                 for (i = 0; i < this->iy_[iy].size(); i++) {
364                         if (this->iy_[iy][i] == tmp)
365                                 to_del = i;
366                 }
367                 if (to_del < this->iy_[iy].size())
368                         this->iy_[iy].erase(this->iy_[iy].begin() + to_del);
369                 this->dnodes().push_back(tmp);
370         }
371         this->root_ = nr;
372         this->root_->remove_parent();
373         return true;
374 }
375
376 std::vector<RRTNode *> RRTBase::findt()
377 {
378         return this->findt(this->goal_);
379 }
380
381 std::vector<RRTNode *> RRTBase::findt(RRTNode *n)
382 {
383         std::vector<RRTNode *> nodes;
384         if (!n->parent())
385                 return nodes;
386         RRTNode *tmp = n;
387         while (tmp) {
388                 nodes.push_back(tmp);
389                 tmp = tmp->parent();
390         }
391         return nodes;
392 }