]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blobdiff - decision_control/slotplanner.cc
Protect usage of `n` when it is `nullptr`
[hubacji1/iamcar.git] / decision_control / slotplanner.cc
index 22669b1e94246f7e08ad4a31e9171599f95771e2..3f903aa6527a8a2a0be99d78de7bf80c6e3b26de 100644 (file)
@@ -68,6 +68,11 @@ SlotType ParallelSlot::slotType()
         return this->slotType_;
 }
 
+float ParallelSlot::poseHeading()
+{
+        return this->poseHeading_;
+}
+
 // setter
 void ParallelSlot::DH(float dh)
 {
@@ -84,9 +89,13 @@ void ParallelSlot::setAll()
         float dy = y3 - y0;
         float dx = x3 - x0;
         this->slotHeading_ = atan2(dy, dx);
-        // slot side
+        // pose heading
         float y1 = this->slot().bnodes()[1]->y();
         float x1 = this->slot().bnodes()[1]->x();
+        dy = y0 - y1;
+        dx = x0 - x1;
+        this->poseHeading_ = atan2(dy, dx);
+        // slot side
         if (sgn((x1 - x0) * (y3 - y0) - (y1 - y0) * (x3 - x0)) < 0)
                 this->slotSide_ = LEFT;
         else
@@ -136,9 +145,16 @@ void ParallelSlot::fip(
                                 && p->h() < this->slotHeading()
                         ) || (
                                 this->slotSide() == RIGHT
-                                && p->h() > this->slotHeading()
+                                && (
+                                        p->h() > this->slotHeading()
+                                        || p->h() < 0
+                                )
                         ))
                 ) {
+                        if (tmpc.size() == 0) {
+                                i = 0;
+                                p = this->getFP();
+                        }
                         bool end = false;
                         std::vector<RRTEdge *> eds = p->frame();
                         for (auto o: co)
@@ -217,6 +233,63 @@ createcuspandfinish:
         std::swap(q, empty);
 }
 
+void ParallelSlot::fipf(
+        std::vector<CircleObstacle>& co,
+        std::vector<SegmentObstacle>& so
+)
+{
+        this->setAll();
+        std::vector<RRTNode *> tmpc;
+        BicycleCar *tmpf = this->getFPf();
+        BicycleCar *tmpb = this->getISPPf(tmpf);
+        RRTNode *cc;
+        if (this->slotSide() == LEFT)
+                cc = tmpb->ccl();
+        else
+                cc = tmpb->ccr();
+        if (this->slotSide() == LEFT)
+                this->DH(-1 * 0.5 / tmpb->out_radi());
+        else
+                this->DH(1 * 0.5 / tmpb->out_radi());
+        BicycleCar *p;
+        int i = 1;
+        p = tmpb->move(cc, i * this->DH());
+        while (
+                !this->slot().collide(p->frame())
+                && ((
+                        this->slotSide() == LEFT
+                        && p->h() > this->slotHeading()
+                ) || (
+                        this->slotSide() == RIGHT
+                        && p->h() < this->slotHeading()
+                ))
+        ) {
+                if (tmpc.size() == 0) {
+                        i = 0;
+                        p = this->getFPf();
+                }
+                bool end = false;
+                std::vector<RRTEdge *> eds = p->frame();
+                for (auto o: co)
+                        if (o.collide(eds))
+                                end = true;
+                for (auto o: so)
+                        if (o.collide(eds))
+                                end = true;
+                for (auto e: eds)
+                        delete e;
+                if (end)
+                        break;
+                this->goals_.push_back(p);
+                tmpc.push_back(p);
+                i += 1;
+                p = tmpb->move(cc, i * this->DH());
+        }
+        if (tmpc.size() > 0)
+                this->cusp().push_back(tmpc);
+        return;
+}
+
 BicycleCar *ParallelSlot::flnc(
         BicycleCar *B,
         std::vector<CircleObstacle>& co,
@@ -583,6 +656,7 @@ BicycleCar *ParallelSlot::getFP()
         float x = this->slot().bnodes()[0]->x();
         float y = this->slot().bnodes()[0]->y();
         float h = this->slotHeading();
+        float ph = this->poseHeading();
         float nx;
         float ny;
         if (this->slotType() == PARALLEL) {
@@ -597,47 +671,133 @@ BicycleCar *ParallelSlot::getFP()
                 y = ny + ((BCAR_LENGTH - BCAR_WHEEL_BASE) / 2 + 0.01) * sin(h);
         } else {
                 if (this->slotSide() == LEFT) {
-                        h -= M_PI / 2;
                         nx = x + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
-                                * cos(h + M_PI);
+                                * cos(ph + M_PI);
                         ny = y + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
-                                * sin(h + M_PI);
-                        x = nx + (BCAR_DIAG_RRADI) * cos(h + M_PI / 2);
-                        y = ny + (BCAR_DIAG_RRADI) * sin(h + M_PI / 2);
+                                * sin(ph + M_PI);
+                        x = nx + (BCAR_DIAG_RRADI) * cos(h);
+                        y = ny + (BCAR_DIAG_RRADI) * sin(h);
                 } else {
-                        h += M_PI / 2;
                         nx = x + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
-                                * cos(h - M_PI);
+                                * cos(ph + M_PI);
                         ny = y + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
-                                * sin(h - M_PI);
-                        x = nx + (BCAR_DIAG_RRADI) * cos(h - M_PI / 2);
-                        y = ny + (BCAR_DIAG_RRADI) * sin(h - M_PI / 2);
+                                * sin(ph + M_PI);
+                        x = nx + (BCAR_DIAG_RRADI) * cos(h);
+                        y = ny + (BCAR_DIAG_RRADI) * sin(h);
                 }
         }
-        return new BicycleCar(x, y, h);
+        return new BicycleCar(x, y, ph);
 }
 
 BicycleCar *ParallelSlot::getISPP(BicycleCar *B)
 {
+        // rigt side (for right parking slot)
         float x = this->slot().bnodes().back()->x();
         float y = this->slot().bnodes().back()->y();
-        float y0;
-        if (this->slotSide() == LEFT) // TODO only for backward parking now
-                y0 = B->ccl()->y();
-        else
-                y0 = B->ccr()->y();
+        float x1;
+        float y1;
+        if (this->slotSide() == LEFT) {
+                x1 = B->ccl()->x();
+                y1 = B->ccl()->y();
+        } else {
+                x1 = B->ccr()->x();
+                y1 = B->ccr()->y();
+        }
         float IR = BCAR_IN_RADI;
         float a = 1;
-        float b = -2 * x;
-        float c = pow(x, 2) + pow(y - y0, 2) - pow(IR, 2);
+        float b = (x1 - x) * 2 * cos(B->h()) + (y1 - y) * 2 * sin(B->h());
+        float c = pow(x - x1, 2) + pow(y - y1, 2) - pow(IR, 2);
         float D = pow(b, 2) - 4 * a * c;
-        float x0;
-        if (this->slotSide() == LEFT)
-                x0 = -b - sqrt(D);
-        else
-                x0 = -b + sqrt(D);
-        x0 /= 2 * a;
-        return new BicycleCar(x0, B->y(), B->h());
+        float delta;
+        delta = -b - sqrt(D);
+        delta /= 2 * a;
+        float delta_1 = delta;
+        // left front (for right parking slot)
+        x = this->slot().bnodes().front()->x();
+        y = this->slot().bnodes().front()->y();
+        IR = BCAR_OUT_RADI;
+        a = 1;
+        b = (x1 - x) * 2 * cos(B->h()) + (y1 - y) * 2 * sin(B->h());
+        c = pow(x - x1, 2) + pow(y - y1, 2) - pow(IR, 2);
+        D = pow(b, 2) - 4 * a * c;
+        //delta = -b + sqrt(D);
+        //delta /= 2 * a;
+        float delta_2 = delta;
+        delta = -b - sqrt(D);
+        delta /= 2 * a;
+        float delta_3 = delta;
+        delta = std::max(delta_1, std::max(delta_2, delta_3));
+        return new BicycleCar(
+                B->x() + delta * cos(B->h()),
+                B->y() + delta * sin(B->h()),
+                B->h()
+        );
+}
+
+BicycleCar *ParallelSlot::getFPf()
+{
+        this->setAll();
+        float x = this->slot().bnodes().front()->x();
+        float y = this->slot().bnodes().front()->y();
+        float h = this->slotHeading();
+        float ph = this->poseHeading();
+        ph += M_PI;
+        while (ph > M_PI)
+                ph -= 2 * M_PI;
+        while (ph <= -M_PI)
+                ph += 2 * M_PI;
+        float nx;
+        float ny;
+        nx = x + (BCAR_LENGTH - BCAR_WHEEL_BASE) / 2 * cos(ph);
+        ny = y + (BCAR_LENGTH - BCAR_WHEEL_BASE) / 2 * sin(ph);
+        x = nx + (BCAR_DIAG_RRADI) * cos(h);
+        y = ny + (BCAR_DIAG_RRADI) * sin(h);
+        return new BicycleCar(x, y, ph);
+}
+
+BicycleCar *ParallelSlot::getISPPf(BicycleCar *B)
+{
+        // right rear (for right parking slot)
+        float x = this->slot().bnodes().front()->x();
+        float y = this->slot().bnodes().front()->y();
+        float x1;
+        float y1;
+        if (this->slotSide() == LEFT) {
+                x1 = B->ccl()->x();
+                y1 = B->ccl()->y();
+        } else {
+                x1 = B->ccr()->x();
+                y1 = B->ccr()->y();
+        }
+        float IR = BCAR_IN_RADI;
+        float a = 1;
+        float b = (x - x1) * 2 * cos(B->h()) + (y - y1) * 2 * sin(B->h());
+        float c = pow(x - x1, 2) + pow(y - y1, 2) - pow(IR, 2);
+        float D = pow(b, 2) - 4 * a * c;
+        float delta;
+        delta = -b - sqrt(D); // TODO why this works?
+        delta /= 2 * a;
+        float delta_1 = delta;
+        // left front (for right parking slot)
+        x = this->slot().bnodes().back()->x();
+        y = this->slot().bnodes().back()->y();
+        IR = BCAR_OUT_RADI;
+        a = 1;
+        b = (x - x1) * 2 * cos(B->h()) + (y - y1) * 2 * sin(B->h());
+        c = pow(x - x1, 2) + pow(y - y1, 2) - pow(IR, 2);
+        D = pow(b, 2) - 4 * a * c;
+        delta = -b + sqrt(D);
+        delta /= 2 * a;
+        float delta_2 = delta;
+        delta = -b - sqrt(D);
+        delta /= 2 * a;
+        float delta_3 = delta;
+        delta = std::max(delta_1, std::max(delta_2, delta_3));
+        return new BicycleCar(
+                B->x() - delta * cos(B->h()),
+                B->y() - delta * sin(B->h()),
+                B->h()
+        );
 }
 
 bool ParallelSlot::isInside(BicycleCar *c)
@@ -667,21 +827,34 @@ struct SamplingInfo ParallelSlot::getSamplingInfo()
 {
         struct SamplingInfo si;
         RRTNode *n = this->getMidd();
+        if (n == nullptr)
+                return si;
+        BicycleCar *bc = new BicycleCar(n->x(), n->y(), n->h());
+        RRTNode *cc;
+        if (this->slotSide() == LEFT)
+                cc = bc->ccl();
+        else
+                cc = bc->ccr();
         if (this->slotType() == PARALLEL) {
-                if (n != nullptr) {
-                        si.x0 = n->x() + 1.5 * BCAR_LENGTH * cos(n->h());
-                        si.y0 = n->y() + 1.5 * BCAR_LENGTH * sin(n->h());
-                        si.h0 = n->h();
-                } else {
-                        si.x0 = this->slot().bnodes().front()->x();
-                        si.y0 = this->slot().bnodes().front()->y();
-                        si.h0 = this->slotHeading();
-                }
+                BicycleCar *nbc = bc->move(cc, this->slotHeading() - n->h());
+                si.x0 = nbc->x();
+                si.y0 = nbc->y();
+                si.h0 = nbc->h();
                 si.x = BCAR_WIDTH;
                 si.y = BCAR_WIDTH;
                 si.h = M_PI / 8;
         } else {
-                // TODO
+                BicycleCar *nbc;
+                if (this->slotSide() == LEFT)
+                        nbc = bc->move(cc, M_PI/4);
+                else
+                        nbc = bc->move(cc, -M_PI/4);
+                si.x0 = nbc->x();
+                si.y0 = nbc->y();
+                si.h0 = nbc->h();
+                si.x = BCAR_WIDTH;
+                si.y = BCAR_WIDTH;
+                si.h = M_PI / 8;
         }
         return si;
 }