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