// ext2
#include "cute_c2.h"
+/*! \brief Use Dijkstra algorithm to find the shorter path.
+*/
+class RRTExt3 : public virtual RRTS {
+ private:
+ std::vector<RRTNode *> orig_path_;
+ double orig_path_cost_;
+ public:
+ std::vector<RRTNode *> path();
+
+ // getter, setter
+ std::vector<RRTNode *> &orig_path()
+ {
+ return this->orig_path_;
+ };
+ double &orig_path_cost() { return this->orig_path_cost_; }
+ void orig_path_cost(double c) { this->orig_path_cost_ = c; }
+};
+
/*! \brief Use cute_c2 for collision detection.
\see https://github.com/RandyGaul/cute_headers/blob/master/cute_c2.h
the current iteration should be the last one.
*/
bool should_stop();
-
+ protected:
// RRT procedures
std::tuple<bool, unsigned int, unsigned int>
collide(std::vector<std::tuple<double, double>> &poly);
bool connect();
void rewire();
public:
+ /*! \brief Initialize RRT algorithm if needed.
+ */
+ virtual void init();
+ /*! \brief Deinitialize RRT algorithm if needed.
+ */
+ virtual void deinit();
/*! \brief Return path found by RRT*.
*/
- std::vector<RRTNode *> path();
+ virtual std::vector<RRTNode *> path();
/*! \brief Run next RRT* iteration.
*/
bool next();
--- /dev/null
+#include <queue>
+#include "rrtext.h"
+
+std::vector<RRTNode *> RRTExt3::path()
+{
+ if (this->orig_path().size() == 0) {
+ this->orig_path_ = RRTS::path();
+ if (this->orig_path().size() == 0)
+ return this->orig_path();
+ else
+ this->orig_path_cost(cc(*this->orig_path().back()));
+ }
+ class DijkstraNode : public RRTNode {
+ public:
+ DijkstraNode *s = nullptr;
+ RRTNode *n = nullptr;
+ unsigned int i = 0;
+ double cc = 9999;
+ bool v = false;
+ bool vi()
+ {
+ if (this->v)
+ return true;
+ this->v = true;
+ return false;
+ }
+ using RRTNode::RRTNode;
+ // override
+ DijkstraNode *p_ = nullptr;
+ DijkstraNode *p() const { return this->p_; }
+ void p(DijkstraNode *p) { this->p_ = p; }
+ };
+ class DijkstraNodeComparator {
+ public:
+ int operator() (
+ const DijkstraNode &n1,
+ const DijkstraNode &n2
+ )
+ {
+ return n1.cc > n2.cc;
+ }
+ };
+ std::vector<DijkstraNode> dn;
+ dn.reserve(this->orig_path().size());
+ unsigned int dncnt = 0;
+ for (auto n: this->orig_path()) {
+ if (
+ n->t(RRTNodeType::cusp)
+ || n->t(RRTNodeType::connected)
+ ) {
+ dn.push_back(DijkstraNode(*n));
+ dn.back().cc = cc(*n);
+ dn.back().s = &dn.back();
+ dn.back().n = n;
+ dn.back().i = dncnt++;
+ }
+ }
+ dn.push_back(DijkstraNode(*this->orig_path().back()));
+ dn.back().cc = cc(*this->orig_path().back());
+ dn.back().s = &dn.back();
+ dn.back().n = this->orig_path().back();
+ dn.back().i = dncnt++;
+ std::priority_queue<
+ DijkstraNode,
+ std::vector<DijkstraNode>,
+ DijkstraNodeComparator
+ > pq;
+ dn.front().vi();
+ pq.push(dn.front());
+ while (!pq.empty()) {
+ DijkstraNode f = pq.top();
+ pq.pop();
+ for (unsigned int i = f.i + 1; i < dncnt; i++) {
+ double cost = f.cc + this->cost_search(f, dn[i]);
+ this->steer(f, dn[i]);
+ if (this->steered().size() == 0)
+ break; // TODO why not continue?
+ if (std::get<0>(this->collide_steered_from(f)))
+ continue;
+ if (cost < dn[i].cc) {
+ dn[i].cc = cost;
+ dn[i].p(f.s);
+ if (!dn[i].vi())
+ pq.push(dn[i]);
+ }
+ }
+ }
+ DijkstraNode *ln = nullptr;
+ for (auto &n: dn) {
+ if (n.v)
+ ln = &n;
+ }
+ if (ln == nullptr || ln->p() == nullptr)
+ return this->orig_path();
+ while (ln->p() != nullptr) {
+ RRTNode *t = ln->n;
+ RRTNode *f = ln->p()->n;
+ this->steer(*f, *t);
+ if (std::get<0>(this->collide_steered_from(*f)))
+ return this->orig_path();
+ this->join_steered(f);
+ t->p(&this->nodes().back());
+ t->c(this->cost_build(this->nodes().back(), *t));
+ ln = ln->p();
+ }
+ return RRTS::path();
+}