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