along with I am car. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <algorithm>
+#include <cmath>
+#include <list>
+#include <queue>
#include "slotplanner.h"
ParallelSlot::ParallelSlot()
{}
+// getter
+std::vector<RRTNode *> &ParallelSlot::goals()
+{
+ return this->goals_;
+}
+
+RRTNode *ParallelSlot::getMidd()
+{
+ if (this->cusp().size() > 0)
+ return this->cusp().front().front();
+ else
+ return nullptr;
+}
+
+std::vector<std::vector<RRTNode *>> &ParallelSlot::cusp()
+{
+ return this->cusp_;
+}
+
+float ParallelSlot::DH() const
+{
+ return this->DH_;
+}
+
PolygonObstacle &ParallelSlot::slot()
{
return this->slot_;
}
+
+float ParallelSlot::slotHeading()
+{
+ return this->slotHeading_;
+}
+
+SlotSide ParallelSlot::slotSide()
+{
+ return this->slotSide_;
+}
+
+SlotType ParallelSlot::slotType()
+{
+ return this->slotType_;
+}
+
+float ParallelSlot::poseHeading()
+{
+ return this->poseHeading_;
+}
+
+// setter
+void ParallelSlot::DH(float dh)
+{
+ this->DH_ = dh;
+}
+
+void ParallelSlot::setAll()
+{
+ // slot heading
+ float y0 = this->slot().bnodes()[0]->y();
+ float x0 = this->slot().bnodes()[0]->x();
+ float y3 = this->slot().bnodes()[3]->y();
+ float x3 = this->slot().bnodes()[3]->x();
+ float dy = y3 - y0;
+ float dx = x3 - x0;
+ this->slotHeading_ = atan2(dy, dx);
+ // 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
+ this->slotSide_ = RIGHT;
+ // slot type
+ float d1 = EDIST(
+ this->slot().bnodes()[0],
+ this->slot().bnodes()[1]
+ );
+ float d2 = EDIST(
+ this->slot().bnodes()[1],
+ this->slot().bnodes()[2]
+ );
+ if (d1 > d2)
+ this->slotType_ = PERPENDICULAR;
+ else
+ this->slotType_ = PARALLEL;
+}
+
+// other
+void ParallelSlot::fip(
+ std::vector<CircleObstacle>& co,
+ std::vector<SegmentObstacle>& so
+)
+{
+ this->setAll();
+ if (this->slotType() == PERPENDICULAR) {
+ std::vector<RRTNode *> tmpc;
+ BicycleCar *tmpf = this->getFP();
+ BicycleCar *tmpb = this->getISPP(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()
+ || 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)
+ 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;
+ }
+ // see https://courses.cs.washington.edu/courses/cse326/03su/homework/hw3/bfs.html
+ // RRTNode.s() works as iteration level
+ std::queue<BicycleCar *, std::list<BicycleCar *>> q;
+ std::queue<BicycleCar *, std::list<BicycleCar *>> empty;
+ int di = -1;
+ if (this->slotSide() == LEFT)
+ di = 1;
+ BicycleCar *CC = this->getEPC();
+ BicycleCar *B = this->getEP();
+ this->DH(di * 0.01 / CC->out_radi());
+ BicycleCar *c;
+ int i = 0;
+ c = B->move(CC, -i * di * 0.01 / CC->diag_radi());
+ while (!this->slot().collide(c->frame())) {
+ bool end = false;
+ std::vector<RRTEdge *> eds = c->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)
+ q.push(c);
+ c = B->move(CC, -i * di * 0.01 / CC->diag_radi());
+ i += 1;
+ }
+ delete c; // not in q and collide
+ while (!q.empty()) {
+ c = q.front();
+ q.pop();
+ if (this->isInside(c)) {
+ goto createcuspandfinish;
+ } else if (c->s() < 9) {
+ BicycleCar *cc = this->flnc(c, co, so);
+ cc->s(c->s() + 1);
+ cc->bcparent(c);
+ q.push(cc);
+ } else {
+ delete c; // not in q and collide
+ }
+ }
+ std::swap(q, empty);
+ return;
+createcuspandfinish:
+ std::vector<RRTNode *> cusp;
+ while (c) {
+ cusp.push_back(new RRTNode(c->x(), c->y(), c->h()));
+ c = c->bcparent();
+ }
+ std::reverse(cusp.begin(), cusp.end());
+ this->cusp().push_back(cusp);
+ 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,
+ std::vector<SegmentObstacle>& so
+)
+{
+ RRTNode *cc;
+ if (this->slotSide() == LEFT) {
+ if (int(B->s()) % 2 == 0)
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccr();
+ else
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccl();
+ } else {
+ if (int(B->s()) % 2 == 0)
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccl();
+ else
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccr();
+ }
+ BicycleCar *p;
+ int i = 1;
+ p = B->move(cc, i * this->DH());
+ while (
+ !this->slot().collide(p->frame())
+ && std::abs(this->slotHeading() - p->h()) < M_PI / 2
+ ) {
+ delete p;
+ i += 10;
+ p = B->move(cc, i * this->DH());
+ 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;
+ }
+ i -= 10;
+ p = B->move(cc, i * this->DH());
+ while (
+ !this->slot().collide(p->frame())
+ && std::abs(this->slotHeading() - p->h()) < M_PI / 2
+ ) {
+ if (this->isInside(p)) {
+ i += 1;
+ break;
+ }
+ delete p;
+ i += 1;
+ p = B->move(cc, i * this->DH());
+ 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;
+ }
+ delete p;
+ return B->move(cc, (i - 1) * this->DH());
+}
+
+void ParallelSlot::fipr(RRTNode *n)
+{
+ return this->fipr(new BicycleCar(n->x(), n->y(), n->h()));
+}
+
+void ParallelSlot::fipr(BicycleCar *B)
+{
+ std::vector<RRTNode *> cusp;
+ cusp.push_back(new RRTNode(B->x(), B->y(), B->h()));
+ int di = 1;
+ if (this->slotSide() == LEFT)
+ di = -1;
+ if (this->slotType() == PERPENDICULAR) {
+ this->DH(di * 0.01 / B->out_radi()); // TODO car in slot h()
+ RRTNode *cc;
+ if (this->slotSide() == LEFT)
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccl();
+ else
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccr();
+ BicycleCar *p;
+ int i = 1;
+ p = B->move(cc, i * this->DH());
+ while (
+ !this->slot().collide(p->frame())
+ && this->slot().collide(p)
+ ) {
+ delete p;
+ i += 10;
+ p = B->move(cc, i * this->DH());
+ }
+ i -= 10;
+ p = B->move(cc, i * this->DH());
+ while (
+ !this->slot().collide(p->frame())
+ && this->slot().collide(p)
+ ) {
+ delete p;
+ i += 1;
+ p = B->move(cc, i * this->DH());
+ }
+ i -= 1;
+ p = B->move(cc, i * this->DH());
+ cusp.push_back(new RRTNode(p->x(), p->y(), p->h()));
+ std::reverse(cusp.begin(), cusp.end());
+ this->cusp().push_back(cusp);
+ return;
+ }
+ this->DH(di * 0.01 / B->out_radi());
+ BicycleCar *c;
+ c = this->flncr(B);
+ c->s(B->s() + 1);
+ while ((
+ this->slotSide() == LEFT
+ && this->slot().collide(new RRTNode(c->lfx(), c->lfy(), 0))
+ ) || (
+ this->slotSide() == RIGHT
+ && this->slot().collide(new RRTNode(c->rfx(), c->rfy(), 0))
+ )) {
+ cusp.push_back(new RRTNode(c->x(), c->y(), c->h()));
+ BicycleCar *cc = this->flncr(c);
+ cc->s(c->s() + 1);
+ delete c;
+ c = cc;
+ }
+ cusp.push_back(new RRTNode(c->x(), c->y(), c->h()));
+ std::reverse(cusp.begin(), cusp.end());
+ this->cusp().push_back(cusp);
+}
+
+BicycleCar *ParallelSlot::flncr(BicycleCar *B)
+{
+ RRTNode *cc;
+ if (this->slotSide() == LEFT) {
+ if (int(B->s()) % 2 == 0)
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccr();
+ else
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccl();
+ } else {
+ if (int(B->s()) % 2 == 0)
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccl();
+ else
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccr();
+ }
+ BicycleCar *p;
+ int i = 1;
+ p = B->move(cc, i * this->DH());
+ while (
+ !this->slot().collide(p->frame())
+ && ((
+ this->slotSide() == LEFT
+ && this->slot().collide(new RRTNode(
+ p->lfx(),
+ p->lfy(),
+ 0
+ ))
+ ) || (
+ this->slotSide() == RIGHT
+ && this->slot().collide(new RRTNode(
+ p->rfx(),
+ p->rfy(),
+ 0
+ ))
+ ))
+ ) {
+ delete p;
+ i += 10;
+ p = B->move(cc, i * this->DH());
+ }
+ i -= 10;
+ p = B->move(cc, i * this->DH());
+ while (!this->slot().collide(p->frame())) {
+ if(
+ this->slotSide() == LEFT
+ && !this->slot().collide(new RRTNode(
+ p->lfx(),
+ p->lfy(),
+ 0
+ ))
+ ) {
+ i += 1;
+ break;
+ }
+ if(
+ this->slotSide() == RIGHT
+ && !this->slot().collide(new RRTNode(
+ p->rfx(),
+ p->rfy(),
+ 0
+ ))
+ ) {
+ i += 1;
+ break;
+ }
+ i += 1;
+ p = B->move(cc, i * this->DH());
+ }
+ delete p;
+ return B->move(cc, (i - 1) * this->DH());
+}
+
+RRTNode *ParallelSlot::fposecenter()
+{
+ return this->slot().bnodes().back();
+}
+
+bool ParallelSlot::flast(
+ RRTNode *P,
+ bool right,
+ int il,
+ std::vector<RRTNode *> &cusp
+)
+{
+ BicycleCar *B = new BicycleCar(P->x(), P->y(), P->h());
+ RRTNode *cc;
+ if (right)
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccr();
+ else
+ cc = BicycleCar(B->x(), B->y(), B->h()).ccl();
+ BicycleCar *p;
+ int i = 1;
+ p = B->move(cc, i * this->DH());
+ while (!this->slot().collide(p->frame())
+ && (
+ (this->DH() > 0 && p->x() <= 0)
+ || (this->DH() < 0 && p->x() >= 0)
+ )) {
+ delete p;
+ i += 10;
+ p = B->move(cc, i * this->DH());
+ }
+ i -= 10;
+ p = B->move(cc, i * this->DH());
+ while (!this->slot().collide(p->frame())
+ && (
+ (this->DH() > 0 && p->x() <= 0)
+ || (this->DH() < 0 && p->x() >= 0)
+ )) {
+ if (this->DH() > 0 && p->rfx() <= 0 && p->rrx() <= 0) {
+ i += 1;
+ break;
+ }
+ if (this->DH() < 0 && p->lfx() >= 0 && p->lrx() >= 0) {
+ i += 1;
+ break;
+ }
+ delete p;
+ i += 1;
+ p = B->move(cc, i * this->DH());
+ }
+ delete p;
+ p = B->move(cc, (i - 1) * this->DH());
+ if (this->DH() > 0 && p->rfx() <= 0 && p->rrx() <= 0) {
+ cusp.push_back(p);
+ return true;
+ } else if (this->DH() < 0 && p->lfx() >= 0 && p->lrx() >= 0) {
+ cusp.push_back(p);
+ return true;
+ } else if (il < 8) {
+ cusp.push_back(p);
+ return this->flast(p, !right, il + 1, cusp);
+ }
+ return false;
+}
+
+void ParallelSlot::fpose()
+{
+ bool left = false; // right parking slot
+ float di = -1;
+ BicycleCar *CC = new BicycleCar(
+ this->fposecenter()->x(),
+ this->fposecenter()->y() - 0.01,
+ this->slotHeading()
+ );
+ BicycleCar *B = new BicycleCar(
+ CC->x() - CC->width() / 2,
+ CC->y() - (CC->length() + CC->wheelbase()) / 2,
+ this->slotHeading()
+ );
+ if (this->slot().bnodes()[0]->x() > this->slot().bnodes()[1]->x()) {
+ left = true;
+ di = 1;
+ delete B;
+ B = new BicycleCar(
+ CC->x() + CC->width() / 2,
+ CC->y() - (CC->length() + CC->wheelbase()) / 2,
+ this->slotHeading()
+ );
+ }
+ this->DH(di * 0.01 / CC->out_radi());
+ BicycleCar *p;
+ int i = 0;
+ p = B->move(CC, -i * di * 0.01 / CC->diag_radi());
+ while (!this->slot().collide(p->frame())) {
+ std::vector<RRTNode *> tmpcusp;
+ tmpcusp.push_back(new BicycleCar(p->x(), p->y(), p->h()));
+ if (this->flast(p, left, 0, tmpcusp)) {
+ this->cusp().push_back(tmpcusp);
+ return;
+ }
+ i += 1;
+ delete p;
+ p = B->move(CC, -i * di * 0.01 / CC->diag_radi());
+ }
+}
+
+BicycleCar *ParallelSlot::getEP()
+{
+ // new pose for parallel parking to right slot
+ float tnx;
+ float tny;
+ float nx;
+ float ny;
+ BicycleCar *CC = this->getEPC();
+ // move left by car width / 2
+ tnx = CC->x() + CC->width() / 2 * cos(CC->h() + M_PI / 2);
+ tny = CC->y() + CC->width() / 2 * sin(CC->h() + M_PI / 2);
+ if (this->slotSide() == LEFT) {
+ // move right by car width / 2
+ tnx = CC->x() + CC->width() / 2 * cos(CC->h() - M_PI / 2);
+ tny = CC->y() + CC->width() / 2 * sin(CC->h() - M_PI / 2);
+ }
+ if (this->slotType() == PARALLEL) {
+ // move down
+ nx = tnx - (CC->length() + CC->wheelbase()) / 2 * cos(CC->h());
+ ny = tny - (CC->length() + CC->wheelbase()) / 2 * sin(CC->h());
+ } else {
+ // move down
+ nx = tnx + (CC->length() - CC->wheelbase()) / 2 * cos(CC->h());
+ ny = tny + (CC->length() - CC->wheelbase()) / 2 * sin(CC->h());
+ }
+ return new BicycleCar(nx, ny, CC->h());
+}
+
+BicycleCar *ParallelSlot::getEPC()
+{
+ // new pose for parallel parking to right slot
+ float ta;
+ float nx;
+ float ny;
+ ta = this->slotHeading() + M_PI;
+ if (this->slotSide() == RIGHT)
+ ta -= M_PI / 4;
+ else
+ ta += M_PI / 4;
+ nx = this->fposecenter()->x() + 0.01 * cos(ta);
+ ny = this->fposecenter()->y() + 0.01 * sin(ta);
+ return new BicycleCar(nx, ny, this->slotHeading());
+}
+
+BicycleCar *ParallelSlot::getFP()
+{
+ this->setAll();
+ 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) {
+ if (this->slotSide() == LEFT) {
+ nx = x + BCAR_WIDTH / 2 * cos(h + M_PI / 2);
+ ny = y + BCAR_WIDTH / 2 * sin(h + M_PI / 2);
+ } else {
+ nx = x + BCAR_WIDTH / 2 * cos(h - M_PI / 2);
+ ny = y + BCAR_WIDTH / 2 * sin(h - M_PI / 2);
+ }
+ x = nx + ((BCAR_LENGTH - BCAR_WHEEL_BASE) / 2 + 0.01) * cos(h);
+ y = ny + ((BCAR_LENGTH - BCAR_WHEEL_BASE) / 2 + 0.01) * sin(h);
+ } else {
+ if (this->slotSide() == LEFT) {
+ nx = x + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
+ * cos(ph + M_PI);
+ ny = y + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
+ * sin(ph + M_PI);
+ x = nx + (BCAR_DIAG_RRADI) * cos(h);
+ y = ny + (BCAR_DIAG_RRADI) * sin(h);
+ } else {
+ nx = x + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
+ * cos(ph + M_PI);
+ ny = y + (BCAR_LENGTH + BCAR_WHEEL_BASE) / 2
+ * sin(ph + M_PI);
+ x = nx + (BCAR_DIAG_RRADI) * cos(h);
+ y = ny + (BCAR_DIAG_RRADI) * sin(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 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 = (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 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)
+{
+ bool inside = true;
+ RRTNode *tmpn;
+ tmpn = new RRTNode(c->lfx(), c->lfy(), 0);
+ if (!this->slot().collide(tmpn))
+ inside = false;
+ delete tmpn;
+ tmpn = new RRTNode(c->lrx(), c->lry(), 0);
+ if (!this->slot().collide(tmpn))
+ inside = false;
+ delete tmpn;
+ tmpn = new RRTNode(c->rrx(), c->rry(), 0);
+ if (!this->slot().collide(tmpn))
+ inside = false;
+ delete tmpn;
+ tmpn = new RRTNode(c->rfx(), c->rfy(), 0);
+ if (!this->slot().collide(tmpn))
+ inside = false;
+ delete tmpn;
+ return inside;
+}
+
+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) {
+ 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 {
+ 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;
+}