]> rtime.felk.cvut.cz Git - hubacji1/psp.git/commitdiff
Merge branch 'feature/find-entry-reverse'
authorJiri Vlasak <hubacji1@fel.cvut.cz>
Mon, 22 Jul 2019 12:34:04 +0000 (14:34 +0200)
committerJiri Vlasak <hubacji1@fel.cvut.cz>
Mon, 22 Jul 2019 12:34:04 +0000 (14:34 +0200)
CHANGELOG.md
api/psp.h
src/psp.cc
ut/psp.t.cc

index 030043f3d24b4898bfe12eba72dafd7958ca04ac..3b344e954691ebd66bb5c6f018107d29b96eb759 100644 (file)
@@ -12,5 +12,7 @@ The format is based on [Keep a Changelog][] and this project adheres to
 - Changelog, license, readme.
 - Doxygen config file.
 - [WvTest][] unit testing framework.
+- Link `bcar` and `pslot` libraries.
+- Implement find entry by reverse method.
 
 [WvTest]: https://github.com/apenwarr/wvtest
index 7711cc180218eff7d064ed2ef3ab5592cb79e4d5..529c04d7ecbe6ce0ec1f97ee0596cf556dbbc8ce 100644 (file)
--- a/api/psp.h
+++ b/api/psp.h
@@ -1,6 +1,8 @@
 #ifndef PSP_H
 #define PSP_H
 
+#include <tuple>
+
 #include "bcar.h"
 #include "pslot.h"
 
 
 \param cc Current bicycle car.
 \param ps Parking slot.
+\param gc Goal car.
 */
 class PSPlanner {
         private:
-                BicycleCar *cc_ = new BicycleCar();
-                ParkingSlot *ps_ = new ParkingSlot();
+                BicycleCar cc_;
+                BicycleCar gc_;
+                ParkingSlot ps_;
         public:
+                /*! \brief Return `true` if there is collision.
+
+                If the parking slot `ps` collide with current car `cc`,
+                return `true`.
+
+                This method depends on `intersection` function that
+                returns `true` or `false` if two line segments collide.
+                Each line segment of current car `cc` (borders) is
+                checked to each line segment of parking slot `ps`
+                (parking slot lines).
+                */
+                bool collide();
+                /*! \brief Has current car `cc` left?
+
+                Return `true` if the current car `cc` left the parking
+                slot `ps`;
+                */
+                bool left();
+
+                // find entry
+                /*! \brief Find entry to the parking slot.
+                */
+                void fe();
+                /*! \brief Find entry to slot by reverse approach.
+
+                See `Vorobieva2015` for more information.
+                */
+                void fer();
+
                 // getters, setters
-                BicycleCar *cc() { return this->cc_; }
-                ParkingSlot *ps() { return this->ps_; }
+                BicycleCar &cc() { return this->cc_; }
+                BicycleCar &gc() { return this->gc_; }
+                ParkingSlot &ps() { return this->ps_; }
 
                 PSPlanner();
 };
 
+/*! \brief Return intersection of two line segments.
+
+The output is tuple `std::tuple<bool, double, double>`, where the first
+value is true when there is an intersection and false otherwise. The
+second and third parameters in the return tuple are coordinates of the
+intersection.
+
+\see https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
+
+\param x1 First line segment first `x` coordinate.
+\param y1 First line segment first `y` coordinate.
+\param x2 First line segment second `x` coordinate.
+\param y2 First line segment second `y` coordinate.
+\param x3 Second line segment first `x` coordinate.
+\param y3 Second line segment first `y` coordinate.
+\param x4 Second line segment second `x` coordinate.
+\param y4 Second line segment second `y` coordinate.
+*/
+std::tuple<bool, double, double> intersect(
+        double x1, double y1,
+        double x2, double y2,
+        double x3, double y3,
+        double x4, double y4
+);
+
 #endif /* PSP_H */
index 89ddce4b53c910e1efd57d601bd190edf6162e4f..a138944d283514e21c8f94358840e3087a232ced 100644 (file)
@@ -1,5 +1,162 @@
 #include "psp.h"
 
+bool PSPlanner::collide()
+{
+        if(std::get<0>(intersect(
+                this->cc().lfx(), this->cc().lfy(),
+                this->cc().lrx(), this->cc().lry(),
+                this->ps().x1(), this->ps().y1(),
+                this->ps().x2(), this->ps().y2()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().rfx(), this->cc().rfy(),
+                this->cc().rrx(), this->cc().rry(),
+                this->ps().x1(), this->ps().y1(),
+                this->ps().x2(), this->ps().y2()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lfx(), this->cc().lfy(),
+                this->cc().rfx(), this->cc().rfy(),
+                this->ps().x1(), this->ps().y1(),
+                this->ps().x2(), this->ps().y2()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lrx(), this->cc().lry(),
+                this->cc().rrx(), this->cc().rry(),
+                this->ps().x1(), this->ps().y1(),
+                this->ps().x2(), this->ps().y2()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lfx(), this->cc().lfy(),
+                this->cc().lrx(), this->cc().lry(),
+                this->ps().x2(), this->ps().y2(),
+                this->ps().x3(), this->ps().y3()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().rfx(), this->cc().rfy(),
+                this->cc().rrx(), this->cc().rry(),
+                this->ps().x2(), this->ps().y2(),
+                this->ps().x3(), this->ps().y3()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lfx(), this->cc().lfy(),
+                this->cc().rfx(), this->cc().rfy(),
+                this->ps().x2(), this->ps().y2(),
+                this->ps().x3(), this->ps().y3()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lrx(), this->cc().lry(),
+                this->cc().rrx(), this->cc().rry(),
+                this->ps().x2(), this->ps().y2(),
+                this->ps().x3(), this->ps().y3()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lfx(), this->cc().lfy(),
+                this->cc().lrx(), this->cc().lry(),
+                this->ps().x3(), this->ps().y3(),
+                this->ps().x4(), this->ps().y4()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().rfx(), this->cc().rfy(),
+                this->cc().rrx(), this->cc().rry(),
+                this->ps().x3(), this->ps().y3(),
+                this->ps().x4(), this->ps().y4()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lfx(), this->cc().lfy(),
+                this->cc().rfx(), this->cc().rfy(),
+                this->ps().x3(), this->ps().y3(),
+                this->ps().x4(), this->ps().y4()
+        )))
+                return true;
+        if(std::get<0>(intersect(
+                this->cc().lrx(), this->cc().lry(),
+                this->cc().rrx(), this->cc().rry(),
+                this->ps().x3(), this->ps().y3(),
+                this->ps().x4(), this->ps().y4()
+        )))
+                return true;
+        return false;
+}
+
+bool PSPlanner::left()
+{
+       double lfx = this->cc().lfx();
+       double lfy = this->cc().lfy();
+       double rfx = this->cc().rfx();
+       double rfy = this->cc().rfy();
+       double ccx = this->cc().x();
+       double ccy = this->cc().y();
+       double lfs = sgn(
+               (lfx - this->ps().x1()) * (this->ps().y4() - this->ps().y1())
+               - (lfy - this->ps().y1()) * (this->ps().x4() - this->ps().x1())
+       );
+       double rfs = sgn(
+               (rfx - this->ps().x1()) * (this->ps().y4() - this->ps().y1())
+               - (rfy - this->ps().y1()) * (this->ps().x4() - this->ps().x1())
+       );
+       double ccs = sgn(
+               (ccx - this->ps().x1()) * (this->ps().y4() - this->ps().y1())
+               - (ccy - this->ps().y1()) * (this->ps().x4() - this->ps().x1())
+       );
+       return lfs == rfs && lfs != ccs;
+}
+
+// find entry
+void PSPlanner::fe()
+{
+}
+
+void PSPlanner::fer()
+{
+        this->cc().st(this->cc().wb() / this->cc().mtr());
+        if (!this->ps().right())
+                this->cc().st(this->cc().st() * -1);
+        this->cc().sp(0.1);
+        while (!this->left()) {
+                while (!this->collide() && !this->left()) {
+                        this->cc().next();
+                }
+                if (this->left() && !this->collide()) {
+                        break;
+                } else {
+                        this->cc().sp(this->cc().sp() * -1);
+                        this->cc().next();
+                        this->cc().st(this->cc().st() * -1);
+                }
+        }
+}
+
 PSPlanner::PSPlanner()
 {
 }
+
+std::tuple<bool, double, double> intersect(
+        double x1, double y1,
+        double x2, double y2,
+        double x3, double y3,
+        double x4, double y4
+)
+{
+        double deno = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
+        if (deno == 0)
+                return std::make_tuple(false, 0, 0);
+        double t = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4);
+        t /= deno;
+        double u = (x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3);
+        u *= -1;
+        u /= deno;
+        if (t < 0 || t > 1 || u < 0 || u > 1)
+                return std::make_tuple(false, 0, 0);
+        return std::make_tuple(true, x1 + t * (x2 - x1), y1 + t * (y2 - y1));
+}
index ca096579935b4e53c2cf87f4c07e960e862b7994..94e8ccabed8b103182029814bb9294f855afef4d 100644 (file)
@@ -5,5 +5,42 @@
 
 WVTEST_MAIN("parking slot planner basic test")
 {
-        PSPlanner *psp = new PSPlanner();
+        PSPlanner psp;
+        psp.ps().border(3, 3, 5, 3, 5, 8, 3, 8);
+        psp.gc().x(4);
+        psp.gc().y(4);
+        psp.gc().h(M_PI / 2);
+        psp.gc().mtr(10);
+        psp.gc().wb(2);
+        psp.gc().w(1);
+        psp.gc().l(3);
+        psp.gc().he(1.5);
+        psp.gc().df(2 + 0.5);
+        psp.gc().dr(0.5);
+        psp.cc() = BicycleCar(psp.gc());
+
+        // init orientation
+        WVPASS(!psp.collide());
+        WVPASSEQ_DOUBLE(psp.ps().heading(), psp.gc().h(), 0.00001);
+
+        // entry point found by reverse
+        WVPASS(!psp.left());
+        psp.fer();
+        WVPASS(psp.left());
+
+        // collide
+        auto tmpi1 = intersect(1, 1, 3, 3, 1, 3, 3, 1);
+        WVPASS(std::get<0>(tmpi1));
+        WVPASSEQ_DOUBLE(std::get<1>(tmpi1), 2, 0.00001);
+        WVPASSEQ_DOUBLE(std::get<2>(tmpi1), 2, 0.00001);
+        auto tmpi2 = intersect(1, 1, 1, 3, 3, 1, 3, 3);
+        WVPASS(!std::get<0>(tmpi2));
+        PSPlanner tpsp;
+        tpsp.ps().border(2, 3, 4, 3, 4, 8, 2, 8);
+        tpsp.gc() = BicycleCar(psp.gc());
+        tpsp.cc() = BicycleCar(tpsp.gc());
+        WVPASS(tpsp.collide());
+        WVPASS(!tpsp.left());
+        tpsp.ps().border(3, 4.1, 3, 2.1, 8, 2.1, 8, 4.1);
+        WVPASS(tpsp.left());
 }