]> rtime.felk.cvut.cz Git - hubacji1/rrts.git/blob - src/rrts.cc
a309bc3065daa0709d4fca22a25ade43fefcd3ed
[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::deinit()
492 {
493         this->nodes().clear();
494         this->samples().clear();
495         this->steered().clear();
496         this->store_node(RRTNode()); // root
497         this->icnt_ = 0;
498         this->scnt_ = 0;
499         this->pcnt_ = 0;
500         this->gf_ = false;
501 }
502
503 void RRTS::compute_path()
504 {
505         if (this->goals().size() == 0)
506                 return;
507         RRTNode *goal = &this->goals().front();
508         if (goal->p() == nullptr)
509                 return;
510         this->path_.clear();
511         while (goal != nullptr) {
512                 this->path_.push_back(goal);
513                 goal = goal->p();
514         }
515         std::reverse(this->path_.begin(), this->path_.end());
516 }
517
518 bool RRTS::next()
519 {
520         if (this->icnt_ == 0)
521                 this->tstart_ = std::chrono::high_resolution_clock::now();
522         bool next = true;
523         if (this->should_stop()) {
524                 this->log_path_cost();
525                 return false;
526         }
527         if (this->samples().size() == 0) {
528                 this->samples().push_back(RRTNode());
529                 this->samples().back().x(this->goals().front().x());
530                 this->samples().back().y(this->goals().front().y());
531                 this->samples().back().h(this->goals().front().h());
532         } else {
533                 this->sample();
534         }
535         this->steer1(
536                 *this->nn(this->samples().back()),
537                 this->samples().back()
538         );
539         if (this->steered().size() == 0) {
540                 this->log_path_cost();
541                 return next;
542         }
543         auto col = this->collide_steered_from(
544                 *this->nn(this->samples().back())
545         );
546         if (std::get<0>(col)) {
547                 auto rcnt = this->steered().size() - std::get<1>(col);
548                 while (rcnt-- > 0) {
549                         this->steered().pop_back();
550                 }
551         }
552         if (!this->connect()) {
553                 this->log_path_cost();
554                 return next;
555         }
556         this->rewire();
557         unsigned scnt = this->steered().size();
558         this->join_steered(&this->nodes().back());
559         RRTNode *just_added = &this->nodes().back();
560         while (scnt > 0) {
561                 // store all the steered1 nodes
562                 this->steered1_.push_back(just_added);
563                 scnt--;
564                 auto &g = this->goals().front();
565                 this->steer2(*just_added, g);
566                 auto col = this->collide_steered_from(*just_added);
567                 if (std::get<0>(col)) {
568                         auto rcnt = this->steered().size() - std::get<1>(col);
569                         while (rcnt-- > 0) {
570                                 this->steered().pop_back();
571                         }
572                 }
573                 this->join_steered(just_added);
574                 // store all the steered2 nodes
575                 RRTNode* jap = &this->nodes().back();
576                 while (jap != just_added) {
577                         this->steered2_.push_back(jap);
578                         jap = jap->p();
579                 }
580                 auto gf = this->goal_found(this->nodes().back());
581                 this->gf(gf);
582                 just_added = just_added->p();
583         }
584         if (
585                 this->gf()
586                 && (
587                         this->path().size() == 0
588                         || this->goals().front().cc < this->path().back()->cc
589                 )
590         ) {
591                 this->compute_path();
592         }
593         this->log_path_cost();
594         return next;
595 }
596
597 void RRTS::set_sample_normal(
598         double mx, double dx,
599         double my, double dy,
600         double mh, double dh
601 )
602 {
603         this->ndx_ = std::normal_distribution<double>(mx, dx);
604         this->ndy_ = std::normal_distribution<double>(my, dy);
605         this->ndh_ = std::normal_distribution<double>(mh, dh);
606 }
607 void RRTS::set_sample_uniform(
608         double xmin, double xmax,
609         double ymin, double ymax,
610         double hmin, double hmax
611 )
612 {
613         this->udx_ = std::uniform_real_distribution<double>(xmin,xmax);
614         this->udy_ = std::uniform_real_distribution<double>(ymin,ymax);
615         this->udh_ = std::uniform_real_distribution<double>(hmin,hmax);
616 }
617 void RRTS::set_sample_uniform_circle()
618 {
619         this->udx_ = std::uniform_real_distribution<double>(0, 1);
620         this->udy_ = std::uniform_real_distribution<double>(0, 1);
621         this->udh_ = std::uniform_real_distribution<double>(0, 2 * M_PI);
622 }
623 void RRTS::set_sample(
624         double x1, double x2,
625         double y1, double y2,
626         double h1, double h2
627 )
628 {
629         switch (this->sample_dist_type()) {
630         case 1: // uniform
631                 x1 += this->nodes().front().x();
632                 x2 += this->nodes().front().x();
633                 y1 += this->nodes().front().y();
634                 y2 += this->nodes().front().y();
635                 this->set_sample_uniform(x1, x2, y1, y2, h1, h2);
636                 break;
637         case 2: // uniform circle
638                 this->set_sample_uniform_circle();
639                 break;
640         case 3: // uniform index of node in nodes
641                 this->set_sample_uniform_circle();
642                 break;
643         default: // normal
644                 this->set_sample_normal(x1, x2, y1, y2, h1, h2);
645         }
646 }
647
648 Json::Value RRTS::json()
649 {
650         Json::Value jvo;
651         {
652                 jvo["time"] = this->scnt();
653         }
654         {
655                 jvo["iterations"] = this->icnt();
656         }
657         {
658                 jvo["init"][0] = this->nodes().front().x();
659                 jvo["init"][1] = this->nodes().front().y();
660                 jvo["init"][2] = this->nodes().front().h();
661         }
662         {
663                 jvo["path_cost_before_opt"] = this->path_cost_before_opt_;
664         }
665         {
666                 if (this->path().size() > 0) {
667                         jvo["cost"] = this->path().back()->cc;
668                         jvo["entry"][0] = this->goals().front().x();
669                         jvo["entry"][1] = this->goals().front().y();
670                         jvo["entry"][2] = this->goals().front().h();
671                         if (this->entry_set) {
672                             jvo["entry"][2] = this->entry.b;
673                             jvo["entry"][3] = this->entry.e;
674                         }
675                         if (this->entries_set) {
676                                 jvo["entries"][0][0] = this->entry1.x;
677                                 jvo["entries"][0][1] = this->entry1.y;
678                                 jvo["entries"][0][2] = this->entry1.h;
679                                 jvo["entries"][1][0] = this->entry2.x;
680                                 jvo["entries"][1][1] = this->entry2.y;
681                                 jvo["entries"][1][2] = this->entry2.h;
682                         }
683                         jvo["goal"][0] = this->goals().back().x();
684                         jvo["goal"][1] = this->goals().back().y();
685                         jvo["goal"][2] = this->goals().back().h();
686                 }
687         }
688         {
689                 unsigned int cu = 0;
690                 unsigned int co = 0;
691                 unsigned int pcnt = 0;
692                 for (auto n: this->path()) {
693                         jvo["path"][pcnt][0] = n->x();
694                         jvo["path"][pcnt][1] = n->y();
695                         jvo["path"][pcnt][2] = n->h();
696                         if (n->t(RRTNodeType::cusp))
697                                 cu++;
698                         if (n->t(RRTNodeType::connected))
699                                 co++;
700                         pcnt++;
701                 }
702                 jvo["cusps-in-path"] = cu;
703                 jvo["connecteds-in-path"] = co;
704         }
705         {
706                 unsigned int gcnt = 0;
707                 for (auto g: this->goals()) {
708                         jvo["goals"][gcnt][0] = g.x();
709                         jvo["goals"][gcnt][1] = g.y();
710                         jvo["goals"][gcnt][2] = g.h();
711                         gcnt++;
712                 }
713         }
714         {
715                 unsigned int ocnt = 0;
716                 for (auto o: this->obstacles()) {
717                         unsigned int ccnt = 0;
718                         for (auto c: o.poly()) {
719                                 jvo["obst"][ocnt][ccnt][0] = std::get<0>(c);
720                                 jvo["obst"][ocnt][ccnt][1] = std::get<1>(c);
721                                 ccnt++;
722                         }
723                         ocnt++;
724                 }
725         }
726         {
727                 jvo["nodes"] = (unsigned int) this->nodes().size();
728         }
729         {
730                 unsigned int cnt = 0;
731                 for (auto i: this->log_path_cost_)
732                         jvo["log_path_cost"][cnt++] = i;
733         }
734         {
735                 unsigned int cnt = 0;
736                 for (auto i: this->log_opt_time_)
737                         jvo["log_opt_time"][cnt++] = i;
738         }
739         //{
740         //        unsigned int ncnt = 0;
741         //        for (auto n: this->nodes()) {
742         //                jvo["nodes_x"][ncnt] = n.x();
743         //                jvo["nodes_y"][ncnt] = n.y();
744         //                //jvo["nodes_h"][ncnt] = n.h();
745         //                ncnt++;
746         //        }
747         //}
748         //{
749         //        unsigned int ncnt = 0;
750         //        for (auto n: this->steered1_) {
751         //                jvo["steered1_x"][ncnt] = n->x();
752         //                jvo["steered1_y"][ncnt] = n->y();
753         //                //jvo["nodes_h"][ncnt] = n.h();
754         //                ncnt++;
755         //        }
756         //        ncnt = 0;
757         //        for (auto n: this->steered2_) {
758         //                jvo["steered2_x"][ncnt] = n->x();
759         //                jvo["steered2_y"][ncnt] = n->y();
760         //                //jvo["nodes_h"][ncnt] = n.h();
761         //                ncnt++;
762         //        }
763         //}
764         return jvo;
765 }
766
767 void RRTS::json(Json::Value jvi)
768 {
769         assert(jvi["init"] != Json::nullValue);
770         assert(jvi["goals"] != Json::nullValue);
771         assert(jvi["obst"] != Json::nullValue);
772
773         this->nodes().front().x(jvi["init"][0].asDouble());
774         this->nodes().front().y(jvi["init"][1].asDouble());
775         this->nodes().front().h(jvi["init"][2].asDouble());
776         {
777                 RRTNode* gp = nullptr;
778                 if (jvi["entry"] != Json::nullValue) {
779                         this->entry_set = true;
780                         this->entry.x = jvi["entry"][0].asDouble();
781                         this->entry.y = jvi["entry"][1].asDouble();
782                         this->entry.b = jvi["entry"][2].asDouble();
783                         this->entry.e = jvi["entry"][3].asDouble();
784                         RRTNode tmp_node;
785                         tmp_node.x(this->entry.x);
786                         tmp_node.y(this->entry.y);
787                         tmp_node.h((this->entry.b + this->entry.e) / 2.0);
788                         this->goals().push_back(tmp_node);
789                         this->goals().back().p(gp);
790                         gp = &this->goals().back();
791                 }
792                 if (jvi["entries"] != Json::nullValue) {
793                         this->entries_set = true;
794                         this->entry1.x = jvi["entries"][0][0].asDouble();
795                         this->entry1.y = jvi["entries"][0][1].asDouble();
796                         this->entry1.h = jvi["entries"][0][2].asDouble();
797                         this->entry2.x = jvi["entries"][1][0].asDouble();
798                         this->entry2.y = jvi["entries"][1][1].asDouble();
799                         this->entry2.h = jvi["entries"][1][2].asDouble();
800                 }
801                 for (auto g: jvi["goals"]) {
802                         RRTNode tmp_node;
803                         tmp_node.x(g[0].asDouble());
804                         tmp_node.y(g[1].asDouble());
805                         tmp_node.h(g[2].asDouble());
806                         this->goals().push_back(tmp_node);
807                         this->goals().back().p(gp);
808                         gp = &this->goals().back();
809                 }
810                 this->goals().front().set_t(RRTNodeType::cusp);
811                 this->goals().back().set_t(RRTNodeType::cusp);
812         }
813         {
814                 Obstacle tmp_obstacle;
815                 for (auto o: jvi["obst"]) {
816                         tmp_obstacle.poly().clear();
817                         for (auto c: o) {
818                                 double tmp_x = c[0].asDouble();
819                                 double tmp_y = c[1].asDouble();
820                                 auto tmp_tuple = std::make_tuple(tmp_x, tmp_y);
821                                 tmp_obstacle.poly().push_back(tmp_tuple);
822                         }
823                         this->obstacles().push_back(tmp_obstacle);
824                 }
825         }
826         {
827                 double edist_init_goal = sqrt(
828                         pow(
829                                 this->nodes().front().x()
830                                 - this->goals().front().x(),
831                                 2
832                         )
833                         + pow(
834                                 this->nodes().front().y()
835                                 - this->goals().front().y(),
836                                 2
837                         )
838                 );
839                 this->set_sample(
840                         this->nodes().front().x(), edist_init_goal,
841                         this->nodes().front().y(), edist_init_goal,
842                         0, 2 * M_PI
843                 );
844         }
845 }
846
847 RRTS::RRTS()
848         : gen_(std::random_device{}())
849 {
850         this->goals().reserve(100);
851         this->nodes().reserve(4000000);
852         this->samples().reserve(1000);
853         this->steered().reserve(20000);
854         this->store_node(RRTNode()); // root
855 }
856
857 double cc(RRTNode &t)
858 {
859         RRTNode *n = &t;
860         double cost = 0;
861         while (n != nullptr) {
862                 cost += n->c();
863                 n = n->p();
864         }
865         return cost;
866 }