]> rtime.felk.cvut.cz Git - hubacji1/rrts.git/blob - src/rrts.cc
Add tmp steered
[hubacji1/rrts.git] / src / rrts.cc
1 #include <algorithm>
2 #include "rrts.h"
3
4 #include "reeds_shepp.h"
5
6 template <typename T> int sgn(T val) {
7         return (T(0) < val) - (val < T(0));
8 }
9
10 double edist(RRTNode const& n1, RRTNode const& n2)
11 {
12     auto dx = n2.x() - n1.x();
13     auto dy = n2.y() - n1.y();
14     return sqrt(dx*dx + dy*dy);
15 }
16 double edist(RRTNode const* n1, RRTNode const* n2)
17 {
18     return edist(*n1, *n2);
19 }
20
21 RRTNode::RRTNode()
22 {
23 }
24
25 RRTNode::RRTNode(const BicycleCar &bc)
26 {
27     this->x(bc.x());
28     this->y(bc.y());
29     this->h(bc.h());
30     this->sp(bc.sp());
31     this->st(bc.st());
32 }
33
34 bool RRTNode::operator==(const RRTNode& n)
35 {
36         if (this == &n)
37                 return true;
38         return false;
39 }
40
41 Obstacle::Obstacle()
42 {
43 }
44
45 double RRTS::elapsed()
46 {
47         std::chrono::duration<double> dt;
48         dt = std::chrono::duration_cast<std::chrono::duration<double>>(
49                 std::chrono::high_resolution_clock::now()
50                 - this->tstart_
51         );
52         this->scnt_ = dt.count();
53         return this->scnt_;
54 }
55
56 void RRTS::log_path_cost()
57 {
58         this->log_path_cost_.push_back(cc(this->goals().front()));
59         this->log_path_time_ += 0.1;
60 }
61
62 bool RRTS::should_stop()
63 {
64         // the following counters must be updated, do not comment
65         this->icnt_++;
66         this->elapsed();
67         // current iteration stop conditions
68         if (this->should_finish()) return true;
69         if (this->should_break()) return true;
70         // but continue by default
71         return false;
72 }
73
74 bool RRTS::should_finish()
75 {
76         // decide finish conditions (maybe comment some lines)
77         //if (this->icnt_ > 999) return true;
78         if (this->scnt_ > 2) return true;
79         if (this->finishit) return true;
80         //if (this->gf()) return true;
81         // but continue by default
82         return false;
83 }
84
85 bool RRTS::should_break()
86 {
87         // decide break conditions (maybe comment some lines)
88         //if (this->scnt_ - this->pcnt_ > 2) return true;
89         // but continue by default
90         return false;
91 }
92
93 bool RRTS::should_continue()
94 {
95         // decide the stop conditions (maybe comment some lines)
96         // it is exact opposite of `should_stop`
97         //if (this->icnt_ > 999) return false;
98         if (this->scnt_ > 10) return false;
99         if (this->gf()) return false;
100         // and reset pause counter if should continue
101         this->pcnt_ = this->scnt_;
102         return true;
103 }
104
105 void RRTS::store_node(RRTNode n)
106 {
107         this->nodes().push_back(n);
108 }
109
110 // RRT procedures
111 std::tuple<bool, unsigned int, unsigned int>
112 RRTS::collide(std::vector<std::tuple<double, double>> &poly)
113 {
114         for (auto &o: this->obstacles())
115                 if (std::get<0>(::collide(poly, o.poly())))
116                         return ::collide(poly, o.poly());
117         return std::make_tuple(false, 0, 0);
118 }
119
120 std::tuple<bool, unsigned int, unsigned int>
121 RRTS::collide_steered_from(RRTNode &f)
122 {
123         auto fbc = BicycleCar();
124         fbc.x(f.x());
125         fbc.y(f.y());
126         fbc.h(f.h());
127         std::vector<std::tuple<double, double>> s;
128         s.push_back(std::make_tuple(fbc.x(), fbc.y()));
129         for (auto &n: this->steered()) {
130                 auto nbc = BicycleCar();
131                 nbc.x(n.x());
132                 nbc.y(n.y());
133                 nbc.h(n.h());
134                 s.push_back(std::make_tuple(nbc.lfx(), nbc.lfy()));
135                 s.push_back(std::make_tuple(nbc.lrx(), nbc.lry()));
136                 s.push_back(std::make_tuple(nbc.rrx(), nbc.rry()));
137                 s.push_back(std::make_tuple(nbc.rfx(), nbc.rfy()));
138         }
139         auto col = this->collide(s);
140         auto strip_from = this->steered().size() - std::get<1>(col) / 4;
141         if (std::get<0>(col) && strip_from > 0) {
142                 while (strip_from-- > 0) {
143                         this->steered().pop_back();
144                 }
145                 return this->collide_steered_from(f);
146         }
147         return col;
148 }
149
150 std::tuple<bool, unsigned int, unsigned int>
151 RRTS::collide_two_nodes(RRTNode &f, RRTNode &t)
152 {
153         auto fbc = BicycleCar();
154         fbc.x(f.x());
155         fbc.y(f.y());
156         fbc.h(f.h());
157         auto tbc = BicycleCar();
158         tbc.x(f.x());
159         tbc.y(f.y());
160         tbc.h(f.h());
161         std::vector<std::tuple<double, double>> p;
162         p.push_back(std::make_tuple(fbc.lfx(), fbc.lfy()));
163         p.push_back(std::make_tuple(fbc.lrx(), fbc.lry()));
164         p.push_back(std::make_tuple(fbc.rrx(), fbc.rry()));
165         p.push_back(std::make_tuple(fbc.rfx(), fbc.rfy()));
166         p.push_back(std::make_tuple(tbc.lfx(), tbc.lfy()));
167         p.push_back(std::make_tuple(tbc.lrx(), tbc.lry()));
168         p.push_back(std::make_tuple(tbc.rrx(), tbc.rry()));
169         p.push_back(std::make_tuple(tbc.rfx(), tbc.rfy()));
170         return this->collide(p);
171 }
172
173 double RRTS::cost_build(RRTNode &f, RRTNode &t)
174 {
175         double cost = 0;
176         cost = sqrt(pow(t.y() - f.y(), 2) + pow(t.x() - f.x(), 2));
177         return cost;
178 }
179
180 double RRTS::cost_search(RRTNode &f, RRTNode &t)
181 {
182         double cost = 0;
183         cost = sqrt(pow(t.y() - f.y(), 2) + pow(t.x() - f.x(), 2));
184         return cost;
185 }
186
187 void RRTS::sample()
188 {
189         double x = 0;
190         double y = 0;
191         double h = 0;
192         switch (this->sample_dist_type()) {
193         case 1: // uniform
194                 x = this->udx_(this->gen_);
195                 y = this->udy_(this->gen_);
196                 h = this->udh_(this->gen_);
197                 break;
198         case 2: // uniform circle
199         {
200                 // see https://stackoverflow.com/questions/5837572/generate-a-random-point-within-a-circle-uniformly/50746409#50746409
201                 double R = sqrt(
202                         pow(
203                                 this->nodes().front().x()
204                                 - this->goals().front().x(),
205                                 2
206                         )
207                         + pow(
208                                 this->nodes().front().y()
209                                 - this->goals().front().y(),
210                                 2
211                         )
212                 );
213                 double a = atan2(
214                         this->goals().front().y() - this->nodes().front().y(),
215                         this->goals().front().x() - this->nodes().front().x()
216                 );
217                 double cx = this->goals().front().x() - R/2 * cos(a);
218                 double cy = this->goals().front().y() - R/2 * sin(a);
219                 double r = R * sqrt(this->udx_(this->gen_));
220                 double theta = this->udy_(this->gen_) * 2 * M_PI;
221                 x = cx + r * cos(theta);
222                 y = cy + r * sin(theta);
223                 h = this->udh_(this->gen_);
224         }
225                 break;
226         case 3: {
227                 if (
228                         this->steered1_.size() == 0
229                         && this->steered2_.size() == 0
230                 ) {
231                         x = this->nodes().front().x();
232                         y = this->nodes().front().y();
233                         h = this->nodes().front().h();
234                 } else {
235                         this->udi1_ = std::uniform_int_distribution<unsigned int>(
236                                 0,
237                                 this->steered1_.size() - 1
238                         );
239                         this->udi2_ = std::uniform_int_distribution<unsigned int>(
240                                 0,
241                                 this->steered2_.size() - 1
242                         );
243                         auto ind1 = this->udi1_(this->gen_);
244                         auto ind2 = this->udi2_(this->gen_);
245                         if (
246                                 this->steered2_.size() == 0
247                         ) {
248                                 auto n1 = this->steered1_[ind1];
249                                 x = n1->x();
250                                 y = n1->y();
251                                 h = n1->h();
252                         } else if (
253                                 this->steered1_.size() == 0
254                         ) {
255                                 auto n2 = this->steered2_[ind2];
256                                 x = n2->x();
257                                 y = n2->y();
258                                 h = n2->h();
259                         } else {
260                                 auto n1 = this->steered1_[ind1];
261                                 auto n2 = this->steered2_[ind2];
262                                 auto which = this->udx_(this->gen_);
263                                 if (which > 0.5) {
264                                         x = n1->x();
265                                         y = n1->y();
266                                         h = n1->h();
267                                 } else {
268                                         x = n2->x();
269                                         y = n2->y();
270                                         h = n2->h();
271                                 }
272                         }
273                 }
274                 break;
275                 }
276         default: // normal
277                 x = this->ndx_(this->gen_);
278                 y = this->ndy_(this->gen_);
279                 h = this->ndh_(this->gen_);
280         }
281         this->samples().push_back(RRTNode());
282         this->samples().back().x(x);
283         this->samples().back().y(y);
284         this->samples().back().h(h);
285 }
286
287 RRTNode *RRTS::nn(RRTNode &t)
288 {
289         RRTNode *nn = &this->nodes().front();
290         double cost = this->cost_search(*nn, t);
291         for (auto &f: this->nodes()) {
292                 if (this->cost_search(f, t) < cost) {
293                         nn = &f;
294                         cost = this->cost_search(f, t);
295                 }
296         }
297         return nn;
298 }
299
300 std::vector<RRTNode *> RRTS::nv(RRTNode &t)
301 {
302         std::vector<RRTNode *> nv;
303         double cost = std::min(GAMMA(this->nodes().size()), ETA);
304         for (auto &f: this->nodes())
305                 if (this->cost_search(f, t) < cost)
306                         nv.push_back(&f);
307         return nv;
308 }
309
310 int cb_rs_steer(double q[4], void *user_data)
311 {
312         std::vector<RRTNode> *nodes = (std::vector<RRTNode> *) user_data;
313         nodes->push_back(RRTNode());
314         nodes->back().x(q[0]);
315         nodes->back().y(q[1]);
316         nodes->back().h(q[2]);
317         nodes->back().sp(q[3]);
318         if (nodes->back().sp() == 0) {
319                 nodes->back().set_t(RRTNodeType::cusp);
320         } else if (nodes->size() >= 2) {
321                 RRTNode* lln = nodes->back().p();
322                 RRTNode* ln = &nodes->back();
323                 if (lln != nullptr && ln != nullptr && sgn(lln->sp()) != sgn(ln->sp()))
324                         ln->set_t(RRTNodeType::cusp);
325         }
326         return 0;
327 }
328
329 void RRTS::steer(RRTNode &f, RRTNode &t)
330 {
331         this->steered().clear();
332         double q0[] = {f.x(), f.y(), f.h()};
333         double q1[] = {t.x(), t.y(), t.h()};
334         ReedsSheppStateSpace rsss(this->bc.mtr());
335         rsss.sample(q0, q1, 0.2, cb_rs_steer, &this->steered());
336 }
337 void RRTS::tmp_steer(RRTNode &f, RRTNode &t)
338 {
339     this->tmp_steered_.clear();
340     double q0[] = {f.x(), f.y(), f.h()};
341     double q1[] = {t.x(), t.y(), t.h()};
342     ReedsSheppStateSpace rsss(this->bc.mtr());
343     rsss.sample(q0, q1, 0.2, cb_rs_steer, &this->tmp_steered_);
344 }
345
346 void RRTS::steer1(RRTNode &f, RRTNode &t)
347 {
348     return this->steer(f, t);
349 }
350
351 void RRTS::steer2(RRTNode &f, RRTNode &t)
352 {
353     return this->steer(f, t);
354 }
355
356 void RRTS::join_steered(RRTNode *f)
357 {
358         while (this->steered().size() > 0) {
359                 this->store_node(this->steered().front());
360                 RRTNode *t = &this->nodes().back();
361                 t->p(f);
362                 t->c(this->cost_build(*f, *t));
363                 this->steered().erase(this->steered().begin());
364                 f = t;
365         }
366 }
367 void RRTS::join_tmp_steered(RRTNode *f)
368 {
369         while (this->tmp_steered_.size() > 0) {
370                 this->store_node(this->tmp_steered_.front());
371                 RRTNode *t = &this->nodes().back();
372                 t->p(f);
373                 t->c(this->cost_build(*f, *t));
374                 this->tmp_steered_.erase(this->tmp_steered_.begin());
375                 f = t;
376         }
377 }
378
379 bool RRTS::goal_found(RRTNode &f)
380 {
381         auto &g = this->goals().front();
382         double cost = this->cost_build(f, g);
383         double edist = sqrt(
384                 pow(f.x() - g.x(), 2)
385                 + pow(f.y() - g.y(), 2)
386         );
387         double adist = std::abs(f.h() - g.h());
388         if (edist < 0.05 && adist < M_PI / 32) {
389                 if (g.p() == nullptr || cc(f) + cost < cc(g)) {
390                         g.p(&f);
391                         g.c(cost);
392                 }
393                 return true;
394         }
395         return false;
396 }
397
398 // RRT* procedures
399 bool RRTS::connect()
400 {
401         RRTNode *t = &this->steered().front();
402         RRTNode *f = this->nn(this->samples().back());
403         double cost = this->cost_search(*f, *t);
404         for (auto n: this->nv(*t)) {
405                 if (
406                         !std::get<0>(this->collide_two_nodes(*n, *t))
407                         && this->cost_search(*n, *t) < cost
408                 ) {
409                         f = n;
410                         cost = this->cost_search(*n, *t);
411                 }
412         }
413         // steer from f->t and then continue with the steered.
414         this->tmp_steer(*f, *t);
415         if (this->tmp_steered_.size() > 0) {
416                 auto col = this->collide_tmp_steered_from(*f);
417                 if (std::get<0>(col))
418                         return false;
419                 this->join_tmp_steered(f);
420                 f = &this->nodes().back();
421         }
422         if (edist(f, t) > 0.2)
423                 return false;
424         // cont.
425         this->store_node(this->steered().front());
426         t = &this->nodes().back();
427         t->p(f);
428         t->c(this->cost_build(*f, *t));
429         t->set_t(RRTNodeType::connected);
430         return true;
431 }
432
433 void RRTS::rewire()
434 {
435         RRTNode *f = &this->nodes().back();
436         for (auto n: this->nv(*f)) {
437                 if (
438                         !std::get<0>(this->collide_two_nodes(*f, *n))
439                         && cc(*f) + this->cost_search(*f, *n) < cc(*n)
440                 ) {
441                         n->p(f);
442                         n->c(this->cost_build(*f, *n));
443                 }
444         }
445 }
446
447 // API
448 void RRTS::init()
449 {
450 }
451
452 void RRTS::deinit()
453 {
454         this->nodes().clear();
455         this->samples().clear();
456         this->steered().clear();
457         this->store_node(RRTNode()); // root
458         this->icnt_ = 0;
459         this->scnt_ = 0;
460         this->pcnt_ = 0;
461         this->gf_ = false;
462 }
463
464 std::vector<RRTNode *> RRTS::path()
465 {
466         std::vector<RRTNode *> path;
467         if (this->goals().size() == 0)
468                 return path;
469         RRTNode *goal = &this->goals().back();
470         if (goal->p() == nullptr)
471                 return path;
472         while (goal != nullptr) {
473                 path.push_back(goal);
474                 goal = goal->p();
475         }
476         std::reverse(path.begin(), path.end());
477         return path;
478 }
479
480 bool RRTS::next()
481 {
482         if (this->icnt_ == 0)
483                 this->tstart_ = std::chrono::high_resolution_clock::now();
484         bool next = true;
485         if (this->scnt_ > this->log_path_time_)
486             this->log_path_cost();
487         if (this->should_stop())
488                 return false;
489         if (this->samples().size() == 0) {
490                 this->samples().push_back(RRTNode());
491                 this->samples().back().x(this->goals().front().x());
492                 this->samples().back().y(this->goals().front().y());
493                 this->samples().back().h(this->goals().front().h());
494         } else {
495                 this->sample();
496         }
497         this->steer1(
498                 *this->nn(this->samples().back()),
499                 this->samples().back()
500         );
501         if (this->steered().size() == 0)
502                 return next;
503         auto col = this->collide_steered_from(
504                 *this->nn(this->samples().back())
505         );
506         if (std::get<0>(col)) {
507                 auto rcnt = this->steered().size() - std::get<1>(col);
508                 while (rcnt-- > 0) {
509                         this->steered().pop_back();
510                 }
511         }
512         if (!this->connect())
513                 return next;
514         this->rewire();
515         unsigned scnt = this->steered().size();
516         this->join_steered(&this->nodes().back());
517         RRTNode *just_added = &this->nodes().back();
518         while (scnt > 0) {
519                 // store all the steered1 nodes
520                 this->steered1_.push_back(just_added);
521                 scnt--;
522                 auto &g = this->goals().front();
523                 this->steer2(*just_added, g);
524                 auto col = this->collide_steered_from(*just_added);
525                 if (std::get<0>(col)) {
526                         auto rcnt = this->steered().size() - std::get<1>(col);
527                         while (rcnt-- > 0) {
528                                 this->steered().pop_back();
529                         }
530                 }
531                 this->join_steered(just_added);
532                 // store all the steered2 nodes
533                 RRTNode* jap = &this->nodes().back();
534                 while (jap != just_added) {
535                         this->steered2_.push_back(jap);
536                         jap = jap->p();
537                 }
538                 this->gf(this->goal_found(this->nodes().back()));
539                 just_added = just_added->p();
540         }
541         return next;
542 }
543
544 void RRTS::set_sample_normal(
545         double mx, double dx,
546         double my, double dy,
547         double mh, double dh
548 )
549 {
550         this->ndx_ = std::normal_distribution<double>(mx, dx);
551         this->ndy_ = std::normal_distribution<double>(my, dy);
552         this->ndh_ = std::normal_distribution<double>(mh, dh);
553 }
554 void RRTS::set_sample_uniform(
555         double xmin, double xmax,
556         double ymin, double ymax,
557         double hmin, double hmax
558 )
559 {
560         this->udx_ = std::uniform_real_distribution<double>(xmin,xmax);
561         this->udy_ = std::uniform_real_distribution<double>(ymin,ymax);
562         this->udh_ = std::uniform_real_distribution<double>(hmin,hmax);
563 }
564 void RRTS::set_sample_uniform_circle()
565 {
566         this->udx_ = std::uniform_real_distribution<double>(0, 1);
567         this->udy_ = std::uniform_real_distribution<double>(0, 1);
568         this->udh_ = std::uniform_real_distribution<double>(0, 2 * M_PI);
569 }
570 void RRTS::set_sample(
571         double x1, double x2,
572         double y1, double y2,
573         double h1, double h2
574 )
575 {
576         switch (this->sample_dist_type()) {
577         case 1: // uniform
578                 x1 += this->nodes().front().x();
579                 x2 += this->nodes().front().x();
580                 y1 += this->nodes().front().y();
581                 y2 += this->nodes().front().y();
582                 this->set_sample_uniform(x1, x2, y1, y2, h1, h2);
583                 break;
584         case 2: // uniform circle
585                 this->set_sample_uniform_circle();
586                 break;
587         case 3: // uniform index of node in nodes
588                 this->set_sample_uniform_circle();
589                 break;
590         default: // normal
591                 this->set_sample_normal(x1, x2, y1, y2, h1, h2);
592         }
593 }
594
595 Json::Value RRTS::json()
596 {
597         Json::Value jvo;
598         {
599                 jvo["time"] = this->scnt();
600         }
601         {
602                 jvo["iterations"] = this->icnt();
603         }
604         {
605                 jvo["init"][0] = this->nodes().front().x();
606                 jvo["init"][1] = this->nodes().front().y();
607                 jvo["init"][2] = this->nodes().front().h();
608         }
609         {
610                 jvo["path_cost_before_opt"] = this->path_cost_before_opt_;
611         }
612         {
613                 if (this->path().size() > 0) {
614                         jvo["cost"] = cc(*this->path().back());
615                         jvo["entry"][0] = this->goals().front().x();
616                         jvo["entry"][1] = this->goals().front().y();
617                         jvo["entry"][2] = this->goals().front().h();
618                         jvo["goal"][0] = this->goals().back().x();
619                         jvo["goal"][1] = this->goals().back().y();
620                         jvo["goal"][2] = this->goals().back().h();
621                 }
622         }
623         {
624                 unsigned int cu = 0;
625                 unsigned int co = 0;
626                 unsigned int pcnt = 0;
627                 for (auto n: this->path()) {
628                         jvo["path"][pcnt][0] = n->x();
629                         jvo["path"][pcnt][1] = n->y();
630                         jvo["path"][pcnt][2] = n->h();
631                         if (n->t(RRTNodeType::cusp))
632                                 cu++;
633                         if (n->t(RRTNodeType::connected))
634                                 co++;
635                         pcnt++;
636                 }
637                 jvo["cusps-in-path"] = cu;
638                 jvo["connecteds-in-path"] = co;
639         }
640         {
641                 unsigned int gcnt = 0;
642                 for (auto g: this->goals()) {
643                         jvo["goals"][gcnt][0] = g.x();
644                         jvo["goals"][gcnt][1] = g.y();
645                         jvo["goals"][gcnt][2] = g.h();
646                         gcnt++;
647                 }
648         }
649         {
650                 unsigned int ocnt = 0;
651                 for (auto o: this->obstacles()) {
652                         unsigned int ccnt = 0;
653                         for (auto c: o.poly()) {
654                                 jvo["obst"][ocnt][ccnt][0] = std::get<0>(c);
655                                 jvo["obst"][ocnt][ccnt][1] = std::get<1>(c);
656                                 ccnt++;
657                         }
658                         ocnt++;
659                 }
660         }
661         {
662                 jvo["nodes"] = (unsigned int) this->nodes().size();
663         }
664         {
665                 unsigned int cnt = 0;
666                 for (auto i: this->log_path_cost_)
667                         jvo["log_path_cost"][cnt++] = i;
668         }
669         //{
670         //        unsigned int ncnt = 0;
671         //        for (auto n: this->nodes()) {
672         //                jvo["nodes_x"][ncnt] = n.x();
673         //                jvo["nodes_y"][ncnt] = n.y();
674         //                //jvo["nodes_h"][ncnt] = n.h();
675         //                ncnt++;
676         //        }
677         //}
678         //{
679         //        unsigned int ncnt = 0;
680         //        for (auto n: this->steered1_) {
681         //                jvo["steered1_x"][ncnt] = n->x();
682         //                jvo["steered1_y"][ncnt] = n->y();
683         //                //jvo["nodes_h"][ncnt] = n.h();
684         //                ncnt++;
685         //        }
686         //        ncnt = 0;
687         //        for (auto n: this->steered2_) {
688         //                jvo["steered2_x"][ncnt] = n->x();
689         //                jvo["steered2_y"][ncnt] = n->y();
690         //                //jvo["nodes_h"][ncnt] = n.h();
691         //                ncnt++;
692         //        }
693         //}
694         return jvo;
695 }
696
697 void RRTS::json(Json::Value jvi)
698 {
699         assert(jvi["init"] != Json::nullValue);
700         assert(jvi["goals"] != Json::nullValue);
701         assert(jvi["obst"] != Json::nullValue);
702
703         this->nodes().front().x(jvi["init"][0].asDouble());
704         this->nodes().front().y(jvi["init"][1].asDouble());
705         this->nodes().front().h(jvi["init"][2].asDouble());
706         {
707                 RRTNode* gp = nullptr;
708                 if (jvi["entry"] != Json::nullValue) {
709                         this->entry_set = true;
710                         this->entry.x = jvi["entry"][0].asDouble();
711                         this->entry.y = jvi["entry"][1].asDouble();
712                         this->entry.b = jvi["entry"][2].asDouble();
713                         this->entry.e = jvi["entry"][3].asDouble();
714                         RRTNode tmp_node;
715                         tmp_node.x(this->entry.x);
716                         tmp_node.y(this->entry.y);
717                         tmp_node.h((this->entry.b + this->entry.e) / 2.0);
718                         this->goals().push_back(tmp_node);
719                         this->goals().back().p(gp);
720                         gp = &this->goals().back();
721                 }
722                 for (auto g: jvi["goals"]) {
723                         RRTNode tmp_node;
724                         tmp_node.x(g[0].asDouble());
725                         tmp_node.y(g[1].asDouble());
726                         tmp_node.h(g[2].asDouble());
727                         this->goals().push_back(tmp_node);
728                         this->goals().back().p(gp);
729                         gp = &this->goals().back();
730                 }
731                 this->goals().front().set_t(RRTNodeType::cusp);
732                 this->goals().back().set_t(RRTNodeType::cusp);
733         }
734         {
735                 Obstacle tmp_obstacle;
736                 for (auto o: jvi["obst"]) {
737                         tmp_obstacle.poly().clear();
738                         for (auto c: o) {
739                                 double tmp_x = c[0].asDouble();
740                                 double tmp_y = c[1].asDouble();
741                                 auto tmp_tuple = std::make_tuple(tmp_x, tmp_y);
742                                 tmp_obstacle.poly().push_back(tmp_tuple);
743                         }
744                         this->obstacles().push_back(tmp_obstacle);
745                 }
746         }
747         {
748                 double edist_init_goal = sqrt(
749                         pow(
750                                 this->nodes().front().x()
751                                 - this->goals().front().x(),
752                                 2
753                         )
754                         + pow(
755                                 this->nodes().front().y()
756                                 - this->goals().front().y(),
757                                 2
758                         )
759                 );
760                 this->set_sample(
761                         this->nodes().front().x(), edist_init_goal,
762                         this->nodes().front().y(), edist_init_goal,
763                         0, 2 * M_PI
764                 );
765         }
766 }
767
768 RRTS::RRTS()
769         : gen_(std::random_device{}())
770 {
771         this->goals().reserve(100);
772         this->nodes().reserve(4000000);
773         this->samples().reserve(1000);
774         this->steered().reserve(20000);
775         this->store_node(RRTNode()); // root
776 }
777
778 double cc(RRTNode &t)
779 {
780         RRTNode *n = &t;
781         double cost = 0;
782         while (n != nullptr) {
783                 cost += n->c();
784                 n = n->p();
785         }
786         return cost;
787 }