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