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