]> rtime.felk.cvut.cz Git - hubacji1/rrts.git/blobdiff - src/rrts.cc
Do not clear opt time log
[hubacji1/rrts.git] / src / rrts.cc
index e5f0334f022e8eade07d67a80e907c0a2b535f03..6ed3d69803aa247dc229c416995ba6a155b2acb0 100644 (file)
@@ -44,8 +44,32 @@ double RRTS::elapsed()
 
 void RRTS::log_path_cost()
 {
-        this->log_path_cost_.push_back(cc(this->goals().front()));
-        this->log_path_time_ += 0.1;
+        if (this->log_path_cost_.size() == 0) {
+                this->log_path_cost_.push_back(this->goals().front().cc);
+        } else {
+                auto lc = this->log_path_cost_.back();
+                auto gc = this->goals().front().cc;
+                auto goal_is_better = this->goals().front().cc > 0 && lc < gc;
+                if (
+                        this->log_path_cost_.back() > 0
+                        && (
+                                this->goals().front().cc == 0
+                                || (
+                                        this->goals().front().cc > 0
+                                        && goal_is_better
+                                )
+                        )
+                ) {
+                        this->log_path_cost_.push_back(
+                                this->log_path_cost_.back()
+                        );
+                } else {
+                        this->log_path_cost_.push_back(
+                                this->goals().front().cc
+                        );
+                }
+        }
+        this->log_path_iter_ += 1;
 }
 
 bool RRTS::should_stop()
@@ -63,9 +87,10 @@ bool RRTS::should_stop()
 bool RRTS::should_finish()
 {
         // decide finish conditions (maybe comment some lines)
-        //if (this->icnt_ > 999) return true;
-        if (this->scnt_ > 2) return true;
-        //if (this->gf()) return true;
+        if (this->icnt_ > 1000) return true;
+        //if (this->scnt_ > 2) return true;
+        if (this->finishit) return true;
+        if (this->gf()) return true;
         // but continue by default
         return false;
 }
@@ -134,6 +159,11 @@ RRTS::collide_steered_from(RRTNode &f)
         }
         return col;
 }
+std::tuple<bool, unsigned int, unsigned int>
+RRTS::collide_tmp_steered_from(RRTNode &f)
+{
+        return std::make_tuple(false, 0, 0);
+}
 
 std::tuple<bool, unsigned int, unsigned int>
 RRTS::collide_two_nodes(RRTNode &f, RRTNode &t)
@@ -202,8 +232,8 @@ void RRTS::sample()
                         this->goals().front().y() - this->nodes().front().y(),
                         this->goals().front().x() - this->nodes().front().x()
                 );
-                double cx = this->goals().front().x() + R/2 * cos(a);
-                double cy = this->goals().front().y() + R/2 * sin(a);
+                double cx = this->goals().front().x() - R/2 * cos(a);
+                double cy = this->goals().front().y() - R/2 * sin(a);
                 double r = R * sqrt(this->udx_(this->gen_));
                 double theta = this->udy_(this->gen_) * 2 * M_PI;
                 x = cx + r * cos(theta);
@@ -211,6 +241,61 @@ void RRTS::sample()
                 h = this->udh_(this->gen_);
         }
                 break;
+        case 3: {
+                if (
+                        this->steered1_.size() == 0
+                        && this->steered2_.size() == 0
+                ) {
+                        x = this->nodes().front().x();
+                        y = this->nodes().front().y();
+                        h = this->nodes().front().h();
+                        this->use_nn = &this->nodes().front();
+                } else {
+                        this->udi1_ = std::uniform_int_distribution<unsigned int>(
+                                0,
+                                this->steered1_.size() - 1
+                        );
+                        this->udi2_ = std::uniform_int_distribution<unsigned int>(
+                                0,
+                                this->steered2_.size() - 1
+                        );
+                        auto ind1 = this->udi1_(this->gen_);
+                        auto ind2 = this->udi2_(this->gen_);
+                        if (
+                                this->steered2_.size() == 0
+                        ) {
+                                auto n1 = this->steered1_[ind1];
+                                x = n1->x();
+                                y = n1->y();
+                                h = n1->h();
+                                this->use_nn = this->steered1_[ind1];
+                        } else if (
+                                this->steered1_.size() == 0
+                        ) {
+                                auto n2 = this->steered2_[ind2];
+                                x = n2->x();
+                                y = n2->y();
+                                h = n2->h();
+                                this->use_nn = this->steered2_[ind2];
+                        } else {
+                                auto n1 = this->steered1_[ind1];
+                                auto n2 = this->steered2_[ind2];
+                                auto which = this->udx_(this->gen_);
+                                if (which > 0.5) {
+                                        x = n1->x();
+                                        y = n1->y();
+                                        h = n1->h();
+                                        this->use_nn = this->steered1_[ind1];
+                                } else {
+                                        x = n2->x();
+                                        y = n2->y();
+                                        h = n2->h();
+                                        this->use_nn = this->steered2_[ind2];
+                                }
+                        }
+                }
+                break;
+                }
         default: // normal
                 x = this->ndx_(this->gen_);
                 y = this->ndy_(this->gen_);
@@ -248,18 +333,19 @@ std::vector<RRTNode *> RRTS::nv(RRTNode &t)
 int cb_rs_steer(double q[4], void *user_data)
 {
         std::vector<RRTNode> *nodes = (std::vector<RRTNode> *) user_data;
-        RRTNode *ln = nullptr;
-        if (nodes->size() > 0)
-                ln = &nodes->back();
         nodes->push_back(RRTNode());
         nodes->back().x(q[0]);
         nodes->back().y(q[1]);
         nodes->back().h(q[2]);
         nodes->back().sp(q[3]);
-        if (nodes->back().sp() == 0)
+        if (nodes->back().sp() == 0) {
                 nodes->back().set_t(RRTNodeType::cusp);
-        else if (ln != nullptr && sgn(ln->sp()) != sgn(nodes->back().sp()))
-                ln->set_t(RRTNodeType::cusp);
+        } else if (nodes->size() >= 2) {
+                RRTNode* lln = nodes->back().p();
+                RRTNode* ln = &nodes->back();
+                if (lln != nullptr && ln != nullptr && sgn(lln->sp()) != sgn(ln->sp()))
+                        ln->set_t(RRTNodeType::cusp);
+        }
         return 0;
 }
 
@@ -269,7 +355,25 @@ void RRTS::steer(RRTNode &f, RRTNode &t)
         double q0[] = {f.x(), f.y(), f.h()};
         double q1[] = {t.x(), t.y(), t.h()};
         ReedsSheppStateSpace rsss(this->bc.mtr());
-        rsss.sample(q0, q1, 0.5, cb_rs_steer, &this->steered());
+        rsss.sample(q0, q1, 0.2, cb_rs_steer, &this->steered());
+}
+void RRTS::tmp_steer(RRTNode &f, RRTNode &t)
+{
+    this->tmp_steered_.clear();
+    double q0[] = {f.x(), f.y(), f.h()};
+    double q1[] = {t.x(), t.y(), t.h()};
+    ReedsSheppStateSpace rsss(this->bc.mtr());
+    rsss.sample(q0, q1, 0.2, cb_rs_steer, &this->tmp_steered_);
+}
+
+void RRTS::steer1(RRTNode &f, RRTNode &t)
+{
+    return this->steer(f, t);
+}
+
+void RRTS::steer2(RRTNode &f, RRTNode &t)
+{
+    return this->steer(f, t);
 }
 
 void RRTS::join_steered(RRTNode *f)
@@ -283,6 +387,17 @@ void RRTS::join_steered(RRTNode *f)
                 f = t;
         }
 }
+void RRTS::join_tmp_steered(RRTNode *f)
+{
+        while (this->tmp_steered_.size() > 0) {
+                this->store_node(this->tmp_steered_.front());
+                RRTNode *t = &this->nodes().back();
+                t->p(f);
+                t->c(this->cost_build(*f, *t));
+                this->tmp_steered_.erase(this->tmp_steered_.begin());
+                f = t;
+        }
+}
 
 bool RRTS::goal_found(RRTNode &f)
 {
@@ -294,7 +409,7 @@ bool RRTS::goal_found(RRTNode &f)
         );
         double adist = std::abs(f.h() - g.h());
         if (edist < 0.05 && adist < M_PI / 32) {
-                if (g.p() == nullptr || cc(f) + cost < cc(g)) {
+                if (g.p() == nullptr || f.cc + cost < g.cc) {
                         g.p(&f);
                         g.c(cost);
                 }
@@ -308,16 +423,36 @@ bool RRTS::connect()
 {
         RRTNode *t = &this->steered().front();
         RRTNode *f = this->nn(this->samples().back());
-        double cost = this->cost_search(*f, *t);
+        double cost = f->cc + this->cost_build(*f, *t);
         for (auto n: this->nv(*t)) {
                 if (
                         !std::get<0>(this->collide_two_nodes(*n, *t))
-                        && this->cost_search(*n, *t) < cost
+                        && n->cc + this->cost_build(*n, *t) < cost
                 ) {
                         f = n;
-                        cost = this->cost_search(*n, *t);
+                        cost = n->cc + this->cost_build(*n, *t);
                 }
         }
+        // steer from f->t and then continue with the steered.
+        this->tmp_steer(*f, *t);
+        if (this->tmp_steered_.size() > 0) {
+                auto col = this->collide_tmp_steered_from(*f);
+                if (std::get<0>(col))
+                        return false;
+                this->join_tmp_steered(f);
+                f = &this->nodes().back();
+        }
+        auto fbc = BicycleCar();
+        fbc.x(f->x());
+        fbc.y(f->y());
+        fbc.h(f->h());
+        auto tbc = BicycleCar();
+        tbc.x(t->x());
+        tbc.y(t->y());
+        tbc.h(t->h());
+        if (!tbc.drivable(fbc))
+            return false;
+        // cont.
         this->store_node(this->steered().front());
         t = &this->nodes().back();
         t->p(f);
@@ -332,8 +467,16 @@ void RRTS::rewire()
         for (auto n: this->nv(*f)) {
                 if (
                         !std::get<0>(this->collide_two_nodes(*f, *n))
-                        && cc(*f) + this->cost_search(*f, *n) < cc(*n)
+                        && f->cc + this->cost_build(*f, *n) < n->cc
                 ) {
+                        this->tmp_steer(*f, *n);
+                        if (this->tmp_steered_.size() > 0) {
+                                auto col = this->collide_tmp_steered_from(*f);
+                                if (std::get<0>(col))
+                                        continue;
+                                this->join_tmp_steered(f);
+                                f = &this->nodes().back();
+                        }
                         n->p(f);
                         n->c(this->cost_build(*f, *n));
                 }
@@ -345,6 +488,28 @@ void RRTS::init()
 {
 }
 
+void RRTS::reset()
+{
+        RRTNode init = RRTNode();
+        init.x(this->nodes().front().x());
+        init.y(this->nodes().front().y());
+        init.h(this->nodes().front().h());
+        this->nodes().clear();
+        this->store_node(RRTNode());
+        this->nodes().front().x(init.x());
+        this->nodes().front().y(init.y());
+        this->nodes().front().h(init.h());
+        this->samples().clear();
+        this->steered().clear();
+        this->path().clear();
+        this->gf(false);
+        for (auto& g: this->goals()) {
+                g.p(nullptr);
+                g.c_ = 0.0;
+                g.cc = 0.0;
+        }
+}
+
 void RRTS::deinit()
 {
         this->nodes().clear();
@@ -357,20 +522,19 @@ void RRTS::deinit()
         this->gf_ = false;
 }
 
-std::vector<RRTNode *> RRTS::path()
+void RRTS::compute_path()
 {
-        std::vector<RRTNode *> path;
         if (this->goals().size() == 0)
-                return path;
-        RRTNode *goal = &this->goals().back();
+                return;
+        RRTNode *goal = &this->goals().front();
         if (goal->p() == nullptr)
-                return path;
+                return;
+        this->path_.clear();
         while (goal != nullptr) {
-                path.push_back(goal);
+                this->path_.push_back(goal);
                 goal = goal->p();
         }
-        std::reverse(path.begin(), path.end());
-        return path;
+        std::reverse(this->path_.begin(), this->path_.end());
 }
 
 bool RRTS::next()
@@ -378,10 +542,10 @@ bool RRTS::next()
         if (this->icnt_ == 0)
                 this->tstart_ = std::chrono::high_resolution_clock::now();
         bool next = true;
-        if (this->scnt_ > this->log_path_time_)
-            this->log_path_cost();
-        if (this->should_stop())
+        if (this->should_stop()) {
+                this->log_path_cost();
                 return false;
+        }
         if (this->samples().size() == 0) {
                 this->samples().push_back(RRTNode());
                 this->samples().back().x(this->goals().front().x());
@@ -390,32 +554,65 @@ bool RRTS::next()
         } else {
                 this->sample();
         }
-        this->steer(
+        this->steer1(
                 *this->nn(this->samples().back()),
                 this->samples().back()
         );
-        if (std::get<0>(this->collide_steered_from(
-                *this->nn(this->samples().back())
-        )))
+        if (this->steered().size() == 0) {
+                this->log_path_cost();
                 return next;
-        if (!this->connect())
+        }
+        auto col = this->collide_steered_from(
+                *this->nn(this->samples().back())
+        );
+        if (std::get<0>(col)) {
+                auto rcnt = this->steered().size() - std::get<1>(col);
+                while (rcnt-- > 0) {
+                        this->steered().pop_back();
+                }
+        }
+        if (!this->connect()) {
+                this->log_path_cost();
                 return next;
+        }
         this->rewire();
         unsigned scnt = this->steered().size();
         this->join_steered(&this->nodes().back());
         RRTNode *just_added = &this->nodes().back();
         while (scnt > 0) {
+                // store all the steered1 nodes
+                this->steered1_.push_back(just_added);
                 scnt--;
                 auto &g = this->goals().front();
-                this->steer(*just_added, g);
-                if (std::get<0>(this->collide_steered_from(
-                        *just_added
-                )))
-                        continue;
+                this->steer2(*just_added, g);
+                auto col = this->collide_steered_from(*just_added);
+                if (std::get<0>(col)) {
+                        auto rcnt = this->steered().size() - std::get<1>(col);
+                        while (rcnt-- > 0) {
+                                this->steered().pop_back();
+                        }
+                }
                 this->join_steered(just_added);
-                this->gf(this->goal_found(this->nodes().back()));
+                // store all the steered2 nodes
+                RRTNode* jap = &this->nodes().back();
+                while (jap != just_added) {
+                        this->steered2_.push_back(jap);
+                        jap = jap->p();
+                }
+                auto gf = this->goal_found(this->nodes().back());
+                this->gf(gf);
                 just_added = just_added->p();
         }
+        if (
+                this->gf()
+                && (
+                        this->path().size() == 0
+                        || this->goals().front().cc < this->path().back()->cc
+                )
+        ) {
+                this->compute_path();
+        }
+        this->log_path_cost();
         return next;
 }
 
@@ -462,6 +659,9 @@ void RRTS::set_sample(
         case 2: // uniform circle
                 this->set_sample_uniform_circle();
                 break;
+        case 3: // uniform index of node in nodes
+                this->set_sample_uniform_circle();
+                break;
         default: // normal
                 this->set_sample_normal(x1, x2, y1, y2, h1, h2);
         }
@@ -486,10 +686,22 @@ Json::Value RRTS::json()
         }
         {
                 if (this->path().size() > 0) {
-                        jvo["cost"] = cc(*this->path().back());
+                        jvo["cost"] = this->path().back()->cc;
                         jvo["entry"][0] = this->goals().front().x();
                         jvo["entry"][1] = this->goals().front().y();
                         jvo["entry"][2] = this->goals().front().h();
+                        if (this->entry_set) {
+                            jvo["entry"][2] = this->entry.b;
+                            jvo["entry"][3] = this->entry.e;
+                        }
+                        if (this->entries_set) {
+                                jvo["entries"][0][0] = this->entry1.x;
+                                jvo["entries"][0][1] = this->entry1.y;
+                                jvo["entries"][0][2] = this->entry1.h;
+                                jvo["entries"][1][0] = this->entry2.x;
+                                jvo["entries"][1][1] = this->entry2.y;
+                                jvo["entries"][1][2] = this->entry2.h;
+                        }
                         jvo["goal"][0] = this->goals().back().x();
                         jvo["goal"][1] = this->goals().back().y();
                         jvo["goal"][2] = this->goals().back().h();
@@ -541,6 +753,11 @@ Json::Value RRTS::json()
                 for (auto i: this->log_path_cost_)
                         jvo["log_path_cost"][cnt++] = i;
         }
+        {
+                unsigned int cnt = 0;
+                for (auto i: this->log_opt_time_)
+                        jvo["log_opt_time"][cnt++] = i;
+        }
         //{
         //        unsigned int ncnt = 0;
         //        for (auto n: this->nodes()) {
@@ -550,6 +767,22 @@ Json::Value RRTS::json()
         //                ncnt++;
         //        }
         //}
+        //{
+        //        unsigned int ncnt = 0;
+        //        for (auto n: this->steered1_) {
+        //                jvo["steered1_x"][ncnt] = n->x();
+        //                jvo["steered1_y"][ncnt] = n->y();
+        //                //jvo["nodes_h"][ncnt] = n.h();
+        //                ncnt++;
+        //        }
+        //        ncnt = 0;
+        //        for (auto n: this->steered2_) {
+        //                jvo["steered2_x"][ncnt] = n->x();
+        //                jvo["steered2_y"][ncnt] = n->y();
+        //                //jvo["nodes_h"][ncnt] = n.h();
+        //                ncnt++;
+        //        }
+        //}
         return jvo;
 }
 
@@ -563,9 +796,32 @@ void RRTS::json(Json::Value jvi)
         this->nodes().front().y(jvi["init"][1].asDouble());
         this->nodes().front().h(jvi["init"][2].asDouble());
         {
-                RRTNode tmp_node;
                 RRTNode* gp = nullptr;
+                if (jvi["entry"] != Json::nullValue) {
+                        this->entry_set = true;
+                        this->entry.x = jvi["entry"][0].asDouble();
+                        this->entry.y = jvi["entry"][1].asDouble();
+                        this->entry.b = jvi["entry"][2].asDouble();
+                        this->entry.e = jvi["entry"][3].asDouble();
+                        RRTNode tmp_node;
+                        tmp_node.x(this->entry.x);
+                        tmp_node.y(this->entry.y);
+                        tmp_node.h((this->entry.b + this->entry.e) / 2.0);
+                        this->goals().push_back(tmp_node);
+                        this->goals().back().p(gp);
+                        gp = &this->goals().back();
+                }
+                if (jvi["entries"] != Json::nullValue) {
+                        this->entries_set = true;
+                        this->entry1.x = jvi["entries"][0][0].asDouble();
+                        this->entry1.y = jvi["entries"][0][1].asDouble();
+                        this->entry1.h = jvi["entries"][0][2].asDouble();
+                        this->entry2.x = jvi["entries"][1][0].asDouble();
+                        this->entry2.y = jvi["entries"][1][1].asDouble();
+                        this->entry2.h = jvi["entries"][1][2].asDouble();
+                }
                 for (auto g: jvi["goals"]) {
+                        RRTNode tmp_node;
                         tmp_node.x(g[0].asDouble());
                         tmp_node.y(g[1].asDouble());
                         tmp_node.h(g[2].asDouble());