]> rtime.felk.cvut.cz Git - hubacji1/iamcar2.git/blob - rrts/src/rrts.cc
1520d6166fd90809e027bea7292d1485f6cebb79
[hubacji1/iamcar2.git] / rrts / src / rrts.cc
1 /*
2  * SPDX-FileCopyrightText: 2021 Jiri Vlasak <jiri.vlasak.2@cvut.cz>
3  *
4  * SPDX-License-Identifier: GPL-3.0-only
5  */
6
7 #include <algorithm>
8 #include <cassert>
9 #include "rrts.hh"
10
11 #ifndef USE_RRTS
12 #define USE_RRTS 0  // TODO improve, this solution isn't clear.
13 #endif
14
15 namespace rrts {
16
17 void
18 Ter::start()
19 {
20         this->_tstart = std::chrono::high_resolution_clock::now();
21 }
22
23 double
24 Ter::scnt() const
25 {
26         auto t = std::chrono::high_resolution_clock::now() - this->_tstart;
27         auto d = std::chrono::duration_cast<std::chrono::seconds>(t);
28         return d.count();
29 }
30
31 double
32 RRTNode::c() const
33 {
34         return this->_c;
35 }
36
37 void
38 RRTNode::c(double c)
39 {
40         assert(this->_p != nullptr);
41         this->_c = c;
42         this->_cc = this->_p->cc() + c;
43 }
44
45 double
46 RRTNode::cc() const
47 {
48         return this->_cc;
49 }
50
51 RRTNode*
52 RRTNode::p() const
53 {
54         return this->_p;
55 }
56
57 void
58 RRTNode::p(RRTNode& p, bool can_be_too_close)
59 {
60         assert(this != &p);
61         if (!can_be_too_close) {
62                 assert(!(std::abs(p.x() - this->x()) < 1e-3
63                         && std::abs(p.y() - this->y()) < 1e-3
64                         && std::abs(p.h() - this->h()) < 1e-3));
65         }
66         this->_p = &p;
67         this->p_is_cusp(this->would_be_cusp_if_parent(p));
68         this->cusp_cnt(p);
69 }
70
71 void
72 RRTNode::p(RRTNode& p)
73 {
74         return this->p(p, false);
75 }
76
77 unsigned int
78 RRTNode::cusp_cnt() const
79 {
80         return this->_cusp_cnt;
81 }
82
83 void
84 RRTNode::cusp_cnt(RRTNode const& p)
85 {
86         this->_cusp_cnt = p.cusp_cnt();
87         if (this->_p_is_cusp) {
88                 this->_cusp_cnt++;
89         }
90 }
91
92 int
93 RRTNode::st(void)
94 {
95         return this->_segment_type;
96 }
97
98 void
99 RRTNode::st(int st)
100 {
101         this->_segment_type = st;
102 }
103
104 bool
105 RRTNode::p_is_cusp(void) const
106 {
107         return this->_p_is_cusp;
108 }
109
110 void
111 RRTNode::p_is_cusp(bool isit)
112 {
113         this->_p_is_cusp = isit;
114 }
115
116 bool
117 RRTNode::would_be_cusp_if_parent(RRTNode const& p) const
118 {
119         if (std::abs(p.sp()) < 1e-3) {
120                 // It should not be possible to have two zero speed nodes next
121                 // to each other. In practice, this sometimes happens.
122                 //assert(std::abs(this->sp()) > 1e-3);
123                 if (p.p()) {
124                         if (sgn(p.p()->sp()) != sgn(this->sp())) {
125                                 return true;
126                         } else {
127                                 return false;
128                         }
129                 } else {
130                         return true; // only root has no parent and it is cusp
131                 }
132         } else {
133                 if (std::abs(this->sp()) < 1e-3) {
134                         return false; // this is cusp, not the parent
135                 } else if (sgn(p.sp()) != sgn(this->sp())) {
136                         return true;
137                 } else {
138                         return false;
139                 }
140         }
141 }
142
143 bool
144 RRTNode::operator==(RRTNode const& n)
145 {
146         return this == &n;
147 }
148
149 void
150 RRTS::recompute_cc_for_predecessors_and(RRTNode* g)
151 {
152         std::vector<RRTNode*> path;
153         path.reserve(this->_path.size());
154         while (g != nullptr) {
155                 path.push_back(g);
156                 g = g->p();
157         }
158         std::reverse(path.begin(), path.end());
159         for (unsigned int i = 1; i < path.size(); i++) {
160                 path[i]->c(this->cost_build(*path[i - 1], *path[i]));
161         }
162 }
163
164 void
165 RRTS::recompute_path_cc()
166 {
167         this->recompute_cc_for_predecessors_and(&this->_goal);
168 }
169
170 double
171 RRTS::min_gamma_eta() const
172 {
173         double ns = this->_nodes.size();
174         double gamma = pow(log(ns) / ns, 1.0 / 3.0);
175         return std::min(gamma, this->eta());
176 }
177
178 bool
179 RRTS::should_continue() const
180 {
181         return !this->should_finish();
182 }
183
184 void
185 RRTS::join_steered(RRTNode* f)
186 {
187         while (this->_steered.size() > 0) {
188                 this->store(this->_steered.front());
189                 RRTNode* t = &this->_nodes.back();
190                 t->p(*f);
191                 t->c(this->cost_build(*f, *t));
192                 this->_steered.erase(this->_steered.begin());
193                 f = t;
194         }
195 }
196
197 bool
198 RRTS::connect()
199 {
200         RRTNode* f = this->_nn;
201         RRTNode* t = &this->_steered.front();
202         // Require the steer method to return first node equal to nn:
203         assert(std::abs(t->x() - f->x()) < 1e-3
204                 && std::abs(t->y() - f->y()) < 1e-3
205                 && std::abs(t->h() - f->h()) < 1e-3);
206         this->_steered.erase(this->_steered.begin());
207         t = &this->_steered.front();
208         assert(!(std::abs(t->x() - f->x()) < 1e-3
209                 && std::abs(t->y() - f->y()) < 1e-3
210                 && std::abs(t->h() - f->h()) < 1e-3));
211 #if USE_RRTS
212         double cost = f->cc() + this->cost_build(*f, *t);
213         for (auto n: this->nv_) {
214                 double nc = n->cc() + this->cost_build(*n, *t);
215                 if (nc < cost) {
216                         f = n;
217                         cost = nc;
218                 }
219         }
220         // Check if it's possible to drive from *f to *t. If not, then fallback
221         // to *f = _nn. This could be also solved by additional steer from *f to
222         // *t instead of the following code.
223         this->set_bc_pose_to(*f);
224         if (!this->_bc.drivable(*t)) {
225                 f = this->_nn;
226         }
227 #endif
228         this->store(this->_steered.front());
229         t = &this->_nodes.back();
230         t->p(*f);
231         t->c(this->cost_build(*f, *t));
232         this->_steered.erase(this->_steered.begin());
233         return true;
234 }
235
236 void
237 RRTS::rewire()
238 {
239         RRTNode *f = &this->_nodes.back();
240         for (auto n: this->_nv) {
241                 double fc = f->cc() + this->cost_build(*f, *n);
242                 this->set_bc_pose_to(*f);
243                 bool drivable = this->_bc.drivable(*n);
244                 if (drivable && fc < n->cc()) {
245                         n->p(*f);
246                         n->c(this->cost_build(*f, *n));
247                 }
248         }
249 }
250
251 bool
252 RRTS::goal_drivable_from(RRTNode const& f)
253 {
254         this->set_bc_pose_to(f);
255         return this->_bc.drivable(this->_goal);
256 }
257
258 void
259 RRTS::store(RRTNode n)
260 {
261         this->_nodes.push_back(n);
262 }
263
264 double
265 RRTS::cost_build(RRTNode const& f, RRTNode const& t) const
266 {
267         return f.edist(t);
268 }
269
270 double
271 RRTS::cost_search(RRTNode const& f, RRTNode const& t) const
272 {
273         return this->cost_build(f, t);
274 }
275
276 void
277 RRTS::find_nn(RRTNode const& t)
278 {
279         this->_nn = &this->_nodes.front();
280         this->_cost = this->cost_search(*this->_nn, t);
281         for (auto& f: this->_nodes) {
282                 if (this->cost_search(f, t) < this->_cost) {
283                         this->_nn = &f;
284                         this->_cost = this->cost_search(f, t);
285                 }
286         }
287 }
288
289 void
290 RRTS::find_nv(RRTNode const& t)
291 {
292         this->_nv.clear();
293         this->_cost = this->min_gamma_eta();
294         for (auto& f: this->_nodes) {
295                 if (this->cost_search(f, t) < this->_cost) {
296                         this->_nv.push_back(&f);
297                 }
298         }
299 }
300
301 void
302 RRTS::compute_path()
303 {
304         this->_path.clear();
305         RRTNode *g = &this->_goal;
306         if (g->p() == nullptr) {
307                 return;
308         }
309         while (g != nullptr && this->_path.size() < 10000) {
310                 /* FIXME in ext13
311                  *
312                  * There shouldn't be this->_path.size() < 10000 condition.
313                  * However, the RRTS::compute_path() called from
314                  * RRTExt13::compute_path tends to re-allocate this->_path
315                  * infinitely. There's probably node->p() = &node somewhere...
316                  */
317                 this->_path.push_back(g);
318                 g = g->p();
319         }
320         std::reverse(this->_path.begin(), this->_path.end());
321 }
322
323 RRTS::RRTS() : _goal(0.0, 0.0, 0.0, 0.0), _gen(std::random_device{}())
324 {
325         this->_nodes.reserve(4000000);
326         this->_steered.reserve(1000);
327         this->_path.reserve(10000);
328         this->_nv.reserve(1000);
329         this->store(RRTNode()); // root
330 }
331
332 void
333 RRTS::set_bc_pose_to(Pose const& p)
334 {
335         this->_bc.set_pose_to(p);
336 }
337
338 void
339 RRTS::set_bc_to_become(std::string what)
340 {
341         this->_bc.become(what);
342 }
343
344 RRTGoal const&
345 RRTS::goal(void) const
346 {
347         return this->_goal;
348 }
349
350 void
351 RRTS::goal(double x, double y, double b, double e)
352 {
353         this->_goal = RRTGoal(x, y, b, e);
354 }
355
356 unsigned int
357 RRTS::icnt(void) const
358 {
359         return this->_icnt;
360 }
361
362 void
363 RRTS::icnt(unsigned int i)
364 {
365         this->_icnt = i;
366 }
367
368 unsigned int
369 RRTS::icnt_max(void) const
370 {
371         return this->_icnt_max;
372 }
373
374 void
375 RRTS::icnt_max(unsigned int i)
376 {
377         this->_icnt_max = i;
378 }
379
380 void
381 RRTS::tstart(void)
382 {
383         this->_ter.start();
384 }
385
386 double
387 RRTS::scnt() const
388 {
389         return this->_ter.scnt();
390 }
391
392 void
393 RRTS::set_init_pose_to(Pose const& p)
394 {
395         this->_nodes.front().x(p.x());
396         this->_nodes.front().y(p.y());
397         this->_nodes.front().h(p.h());
398 }
399
400 std::vector<Pose>
401 RRTS::path() const
402 {
403         std::vector<Pose> path;
404         for (auto n: this->_path) {
405                 path.push_back(Pose(n->x(), n->y(), n->h()));
406         }
407         return path;
408 }
409
410 double
411 RRTS::path_cost() const
412 {
413         return this->_goal.cc();
414 }
415
416 double
417 RRTS::last_path_cost(void) const
418 {
419         if (this->_logged_paths.size() == 0) {
420                 return 0.0;
421         }
422         assert(this->_logged_paths.back().size() > 0);
423         return this->_logged_paths.back().back().cc();
424 }
425
426 double
427 RRTS::eta() const
428 {
429         return this->_eta;
430 }
431
432 void
433 RRTS::eta(double e)
434 {
435         this->_eta = e;
436 }
437
438 Json::Value
439 RRTS::json(void) const
440 {
441         Json::Value jvo;
442         unsigned int i = 0, j = 0;
443         for (auto path: this->_logged_paths) {
444                 i = 0;
445                 for (auto n: path) {
446                         jvo["paths"][j][i][0] = n.x();
447                         jvo["paths"][j][i][1] = n.y();
448                         jvo["paths"][j][i][2] = n.h();
449                         jvo["paths"][j][i][3] = n.sp();
450                         jvo["paths"][j][i][4] = n.st();
451                         jvo["paths"][j][i][5] = false;
452                         if (n.p_is_cusp()) {
453                                 assert(i > 0);
454                                 jvo["paths"][j][i - 1][5] = true;
455                         }
456                         i++;
457                 }
458                 // Initial point is part of the first segment.
459                 jvo["paths"][j][0][3] = jvo["paths"][j][1][3];
460                 jvo["paths"][j][0][4] = jvo["paths"][j][1][4];
461                 // Goal point is part of the last segment.
462                 jvo["paths"][j][i - 1][3] = jvo["paths"][j][i - 2][3];
463                 jvo["paths"][j][i - 1][4] = jvo["paths"][j][i - 2][4];
464                 // --
465                 jvo["costs"][j] = path.back().cc();
466                 j++;
467         }
468         i = 0;
469         for (auto n: this->_path) {
470                 jvo["paths"][j][i][0] = n->x();
471                 jvo["paths"][j][i][1] = n->y();
472                 jvo["paths"][j][i][2] = n->h();
473                 jvo["paths"][j][i][3] = n->sp();
474                 jvo["paths"][j][i][4] = n->st();
475                 jvo["paths"][j][i][5] = n->p_is_cusp();
476                 jvo["path"][i][0] = n->x();
477                 jvo["path"][i][1] = n->y();
478                 jvo["path"][i][2] = n->h();
479                 jvo["path"][i][3] = n->sp();
480                 jvo["path"][i][4] = n->st();
481                 jvo["path"][i][5] = false;
482                 if (n->p_is_cusp()) {
483                         assert(i > 0);
484                         jvo["path"][i - 1][5] = true;
485                 }
486                 i++;
487         }
488         // Initial point is part of the first segment.
489         jvo["path"][0][3] = jvo["path"][1][3];
490         jvo["path"][0][4] = jvo["path"][1][4];
491         // Goal point is part of the last segment.
492         jvo["path"][i - 1][3] = jvo["path"][i - 2][3];
493         jvo["path"][i - 1][4] = jvo["path"][i - 2][4];
494         // --
495         if (this->_path.size() > 0) {
496                 jvo["costs"][j] = this->_path.back()->cc();
497         }
498         jvo["goal_cc"] = this->_goal.cc(); // TODO remove, use the following
499         jvo["cost"] = this->path_cost();
500         jvo["time"] = this->scnt();
501         return jvo;
502 }
503
504 void
505 RRTS::json(Json::Value jvi)
506 {
507         assert(jvi["init"] != Json::nullValue);
508         assert(jvi["goal"] != Json::nullValue);
509         this->set_init_pose_to(Pose(
510                 jvi["init"][0].asDouble(),
511                 jvi["init"][1].asDouble(),
512                 jvi["init"][2].asDouble()));
513         if (jvi["goal"].size() == 4) {
514                 this->goal(
515                         jvi["goal"][0].asDouble(),
516                         jvi["goal"][1].asDouble(),
517                         jvi["goal"][2].asDouble(),
518                         jvi["goal"][3].asDouble());
519         } else {
520                 this->goal(
521                         jvi["goal"][0].asDouble(),
522                         jvi["goal"][1].asDouble(),
523                         jvi["goal"][2].asDouble(),
524                         jvi["goal"][2].asDouble());
525         }
526 }
527
528 bool
529 RRTS::next()
530 {
531         if (this->icnt() == 0) {
532                 this->tstart();
533         }
534         auto rs = this->sample();
535 #if 1 // anytime RRTs
536 {
537         double d1 = this->cost_search(this->_nodes.front(), rs);
538         double d2 = this->cost_search(rs, this->_goal);
539         if (this->last_path_cost() != 0.0 && d1 + d2 > this->last_path_cost()) {
540                 auto& last_path = this->_logged_paths.back();
541                 rs = last_path[rand() % last_path.size()];
542         }
543 }
544 #endif
545         this->find_nn(rs);
546         this->steer(*this->_nn, rs);
547         if (this->collide_steered()) {
548                 return this->should_continue();
549         }
550 #if USE_RRTS
551         this->find_nv(this->_steered.front());
552 #endif
553         if (!this->connect()) {
554                 return this->should_continue();
555         }
556 #if USE_RRTS
557         this->rewire();
558 #endif
559         unsigned int ss = this->_steered.size();
560         this->join_steered(&this->_nodes.back());
561         RRTNode* just_added = &this->_nodes.back();
562         bool gf = false;
563         while (ss > 0 && just_added != nullptr) {
564                 this->steer(*just_added, this->_goal);
565                 if (this->collide_steered()) {
566                         ss--;
567                         just_added = just_added->p();
568                         continue;
569                 }
570                 // The first of steered is the same as just_added.
571                 this->_steered.erase(this->_steered.begin());
572                 this->join_steered(just_added);
573                 bool gn = this->_goal.edist(this->_nodes.back()) < this->eta();
574                 bool gd = this->goal_drivable_from(this->_nodes.back());
575                 if (gn && gd) {
576                         double nc = this->cost_build(
577                                 this->_nodes.back(),
578                                 this->_goal);
579                         double ncc = this->_nodes.back().cc() + nc;
580                         if (this->_goal.p() == nullptr
581                                         || ncc < this->_goal.cc()) {
582                                 this->_goal.p(this->_nodes.back(), true);
583                                 this->_goal.c(nc);
584                                 gf = true;
585                         }
586                 }
587                 ss--;
588                 just_added = just_added->p();
589         }
590         if (gf) {
591                 this->compute_path();
592         }
593         this->_time = this->scnt();
594         this->icnt(this->icnt() + 1);
595         return this->should_continue();
596 }
597
598 void
599 RRTS::reset()
600 {
601         if (this->path_cost() != 0.0
602                         && this->path_cost() < this->last_path_cost()) {
603                 this->_logged_paths.push_back(std::vector<RRTNode>());
604                 auto& last_path = this->_logged_paths.back();
605                 last_path.reserve(this->_path.size());
606                 RRTNode* p = nullptr;
607                 for (auto n: this->_path) {
608                         last_path.push_back(*n);
609                         if (p != nullptr) {
610                                 last_path.back().p(*p);
611                         }
612                         p = &last_path.back();
613                 }
614                 // Test that last path cost matches.
615                 auto last_path_cost = last_path.back().cc();
616                 for (unsigned int i = 1; i < last_path.size(); i++) {
617                         last_path[i].c(this->cost_build(
618                                 last_path[i - 1],
619                                 last_path[i]));
620                 }
621                 assert(last_path_cost == last_path.back().cc());
622         }
623         this->_goal = RRTGoal(
624                 this->_goal.x(),
625                 this->_goal.y(),
626                 this->_goal.b(),
627                 this->_goal.e());
628         this->_path.clear();
629         this->_steered.clear();
630         this->_nodes.erase(this->_nodes.begin() + 1, this->_nodes.end());
631         this->_nv.clear();
632         this->_nn = nullptr;
633         this->_bc = BicycleCar();
634 }
635
636 } // namespace rrts