2 * SPDX-FileCopyrightText: 2021 Jiri Vlasak <jiri.vlasak.2@cvut.cz>
4 * SPDX-License-Identifier: GPL-3.0-only
16 Point::Point(double x, double y) : _x(x), _y(y)
45 Point::min_angle_between(Point const& p1, Point const& p2) const
47 double d1x = p1.x() - this->x();
48 double d1y = p1.y() - this->y();
49 double d2x = p2.x() - p1.x();
50 double d2y = p2.y() - p1.y();
52 double dot = d1x*d2x + d1y*d2y;
53 double d1 = sqrt(d1x*d1x + d1y*d1y);
54 double d2 = sqrt(d2x*d2x + d2y*d2y);
56 double delta = acos(dot / (d1 * d2));
57 return std::min(delta, M_PI - delta);
61 Point::inside_of(std::vector<Point> const& poly) const
63 unsigned int num = poly.size();
64 unsigned int j = num - 1;
66 for (unsigned int i = 0; i < num; i++) {
67 if (this->x() == poly[i].x() && this->y() == poly[i].y()) {
70 if ((poly[i].y() > this->y()) != (poly[j].y() > this->y())) {
71 auto slope1 = this->x() - poly[i].x();
72 slope1 *= poly[j].y() - poly[i].y();
73 auto slope2 = poly[j].x() - poly[i].x();
74 slope2 *= this->y() - poly[i].y();
75 auto slope = slope1 - slope2;
79 if ((slope < 0.0) != (poly[j].y() < poly[i].y())) {
89 Point::on_right_side_of(Line const& li) const
97 if (sgn((x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1)) < 0.0) {
105 Point::translate(Point const& p)
112 Point::rotate(Point const& c, double const angl)
114 double px = this->x();
115 double py = this->y();
118 double nx = px * cos(angl) - py * sin(angl);
119 double ny = px * sin(angl) + py * cos(angl);
125 Point::reflect(Line const& li)
127 this->rotate(li.b(), -li.h());
128 this->_y -= li.b().y();
130 this->_y += li.b().y();
131 this->rotate(li.b(), li.h());
135 Point::edist(Point const& p) const
137 return sqrt(pow(p.x() - this->_x, 2.0) + pow(p.y() - this->_y, 2.0));
141 Point::operator==(Point const& p)
143 return this->x() == p.x() && this->y() == p.y();
147 operator<<(std::ostream& out, Point const& p)
149 out << "[" << p.x() << "," << p.y() << "]";
153 Line::Line(Point const& b, Point const& e): _b(b), _e(e)
172 return Point((this->_b.x() + this->_e.x()) / 2.0,
173 (this->_b.y() + this->_e.y()) / 2.0);
189 Line::intersects_with(Line const& li)
191 auto x1 = this->_b.x();
192 auto y1 = this->_b.y();
193 auto x2 = this->_e.x();
194 auto y2 = this->_e.y();
195 auto x3 = li.b().x();
196 auto y3 = li.b().y();
197 auto x4 = li.e().x();
198 auto y4 = li.e().y();
199 double deno = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
203 double t = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4);
205 double u = (x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3);
208 if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0) {
211 this->_i1.x(x1 + t * (x2 - x1));
212 this->_i1.y(y1 + t * (y2 - y1));
217 Line::intersects_with(Point const& c, double const r)
219 auto x1 = this->_b.x();
220 auto y1 = this->_b.y();
221 auto x2 = this->_e.x();
222 auto y2 = this->_e.y();
234 double dr = sqrt(dx*dx + dy*dy);
235 double D = x1*y2 - x2*y1;
236 if (r*r * dr*dr - D*D < 0.0) {
239 // intersection coordinates
240 double ix1 = (D*dy + sgn(dy)*dx*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
242 double ix2 = (D*dy - sgn(dy)*dx*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
244 double iy1 = (-D*dx + std::abs(dy)*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
246 double iy2 = (-D*dx - std::abs(dy)*sqrt(r*r * dr*dr - D*D)) / (dr*dr);
258 return this->_b.edist(this->_e);
264 return atan2(this->_e.y() - this->_b.y(), this->_e.x() - this->_b.x());
268 operator<<(std::ostream& out, Line const& li)
270 out << "[" << li._b << "," << li._e << "]";
274 Pose::Pose(double x, double y, double h) : Point(x, y), _h(h)
297 Pose::set_pose(Pose const& p)
305 Pose::rotate(Point const& c, double const angl)
307 Point::rotate(c, angl);
308 this->h(this->h() + angl);
312 Pose::reflect(Line const& li)
315 double dh = li.h() - this->h();
316 this->h(this->h() + 2.0 * dh);
320 Pose::operator==(Pose const& p)
322 return this->x() == p.x() && this->y() == p.y() && this->h() == p.h();
326 operator<<(std::ostream& out, Pose const& p)
328 out << "[" << p.x() << "," << p.y() << "," << p.h() << "]";
336 double bpbx = this->_bp.x() - clen * cos(this->_bp.h());
337 double bpby = this->_bp.y() - clen * sin(this->_bp.h());
338 double bpfx = this->_bp.x() + clen * cos(this->_bp.h());
339 double bpfy = this->_bp.y() + clen * sin(this->_bp.h());
340 Line li1(Point(bpbx, bpby), Point(bpfx, bpfy));
341 double epbx = this->_ep.x() - clen * cos(this->_ep.h());
342 double epby = this->_ep.y() - clen * sin(this->_ep.h());
343 double epfx = this->_ep.x() + clen * cos(this->_ep.h());
344 double epfy = this->_ep.y() + clen * sin(this->_ep.h());
345 Line li2(Point(epbx, epby), Point(epfx, epfy));
346 li1.intersects_with(li2);
347 this->x(li1.i1().x());
348 this->y(li1.i1().y());
349 double bh = this->b();
354 double eh = this->e();
359 this->h((this->b() + this->e()) / 2.0);
362 PoseRange::PoseRange(Pose bp, Pose ep) : _bp(bp), _ep(ep)
364 if (this->_bp == this->_ep) {
365 this->set_pose(this->_ep);
371 PoseRange::PoseRange(double x, double y, double b, double e)
372 : PoseRange(Pose(x, y, b), Pose(x, y, e))
377 PoseRange::bp() const
383 PoseRange::ep() const
391 return std::min(this->_bp.h(), this->_ep.h());
397 return std::max(this->_bp.h(), this->_ep.h());
401 PoseRange::translate(Point const& p)
403 this->_bp.translate(p);
404 this->_ep.translate(p);
409 PoseRange::rotate(Point const& c, double const angl)
411 this->_bp.rotate(c, angl);
412 this->_ep.rotate(c, angl);
417 PoseRange::reflect(Line const& li)
419 this->_bp.reflect(li);
420 this->_ep.reflect(li);
425 operator<<(std::ostream& out, PoseRange const& p)
427 out << "[" << p.x() << "," << p.y() << "," << p.b() << "," << p.e();
435 return this->_curb_to_curb;
439 CarSize::ctc(double ctc)
441 this->_curb_to_curb = ctc;
447 return this->_wheelbase;
451 CarSize::wb(double wb)
453 this->_wheelbase = wb;
471 return this->_length;
475 CarSize::len(double len)
483 return this->_distance_to_front;
487 CarSize::df(double df)
489 this->_distance_to_front = df;
495 return this->len() - this->df();
499 CarSize::ft(double ft)
501 this->_front_track = ft;
507 return this->_front_track;
513 auto ctc2 = pow(this->ctc() / 2.0, 2.0);
514 auto wb2 = pow(this->wb(), 2.0);
515 return sqrt(ctc2 - wb2) - this->ft() / 2.0;
519 CarSize::iradi() const
521 return this->mtr() - this->w() / 2;
525 CarSize::ofradi() const
527 auto mtrw2 = pow(this->mtr() + this->w() / 2.0, 2.0);
528 auto df2 = pow(this->df(), 2.0);
529 return sqrt(mtrw2 + df2);
533 CarSize::orradi() const
535 auto mtrw2 = pow(this->mtr() + this->w() / 2.0, 2.0);
536 auto dr2 = pow(this->dr(), 2.0);
537 return sqrt(mtrw2 + dr2);
541 CarSize::perfect_parking_slot_len() const
543 auto r = this->ctc() / 2.0;
545 auto k = this->df() - this->wb();
547 auto r2l2 = r * r - l * l;
548 auto s = r2l2 + pow(l + k, 2.0) - pow(sqrt(r2l2) - w, 2.0);
549 return this->len() + sqrt(s) - l - k;
559 CarMove::sp(double sp)
571 CarMove::st(double st)
577 BicycleCar::drivable(Pose const& p) const
579 return this->drivable(PoseRange(p, p));
583 BicycleCar::drivable(PoseRange const& p) const
585 double a_1 = atan2(p.y() - this->y(), p.x() - this->x()) - this->h();
590 double h_d = p.h() - this->h();
596 if (h_d == 0 && (a_1 == 0 || a_2 == M_PI || a_2 == -M_PI)) {
598 } else if (0 < a_1 && a_1 <= M_PI/2) { // left front
599 BicycleCar z(*this); // zone border
601 h_d = p.h() - this->h();
602 z.rotate(this->ccl(), h_d);
603 // assert z.h() == p.h()
604 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
606 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
611 if (z.h() >= a_2 && a_2 >= this->h())
613 } else if (M_PI/2 < a_1 && a_1 <= M_PI) { // left rear
614 BicycleCar z(*this); // zone border
616 h_d = p.h() - this->h();
617 z.rotate(this->ccl(), h_d);
618 // assert z.h() == p.h()
619 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
621 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
627 if (this->h() >= a_2 && a_2 >= z.h())
629 } else if (0 > a_1 && a_1 >= -M_PI/2) { // right front
630 BicycleCar z(*this); // zone border
632 h_d = p.h() - this->h();
633 z.rotate(this->ccr(), h_d);
634 // assert z.h() == p.h()
635 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
637 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
642 if (this->h() >= a_2 && a_2 >= z.h())
644 } else if (-M_PI/2 > a_1 && a_1 >= -M_PI) { // right rear
645 BicycleCar z(*this); // zone border
647 h_d = p.h() - this->h();
648 z.rotate(this->ccr(), h_d);
649 // assert z.h() == p.h()
650 if (p.y() == z.y() && p.x() == z.x()) // p on zone border
652 a_2 = atan2(p.y() - z.y(), p.x() - z.x());
658 if (z.h() >= a_2 && a_2 >= this->h())
661 // Not happenning, as ``-pi <= a <= pi``.
667 BicycleCar::set_max_steer()
669 this->st(atan(this->wb() / this->mtr()));
673 BicycleCar::lfx() const
675 double lfx = this->x();
676 lfx += (this->w() / 2.0) * cos(this->h() + M_PI / 2.0);
677 lfx += this->df() * cos(this->h());
682 BicycleCar::lfy() const
684 double lfy = this->y();
685 lfy += (this->w() / 2.0) * sin(this->h() + M_PI / 2.0);
686 lfy += this->df() * sin(this->h());
691 BicycleCar::lrx() const
693 double lrx = this->x();
694 lrx += (this->w() / 2.0) * cos(this->h() + M_PI / 2.0);
695 lrx += -this->dr() * cos(this->h());
700 BicycleCar::lry() const
702 double lry = this->y();
703 lry += (this->w() / 2.0) * sin(this->h() + M_PI / 2.0);
704 lry += -this->dr() * sin(this->h());
709 BicycleCar::rrx() const
711 double rrx = this->x();
712 rrx += (this->w() / 2.0) * cos(this->h() - M_PI / 2.0);
713 rrx += -this->dr() * cos(this->h());
718 BicycleCar::rry() const
720 double rry = this->y();
721 rry += (this->w() / 2.0) * sin(this->h() - M_PI / 2.0);
722 rry += -this->dr() * sin(this->h());
727 BicycleCar::rfx() const
729 double rfx = this->x();
730 rfx += (this->w() / 2.0) * cos(this->h() - M_PI / 2.0);
731 rfx += this->df() * cos(this->h());
736 BicycleCar::rfy() const
738 double rfy = this->y();
739 rfy += (this->w() / 2.0) * sin(this->h() - M_PI / 2.0);
740 rfy += this->df() * sin(this->h());
745 BicycleCar::lf() const
747 return Point(this->lfx(), this->lfy());
751 BicycleCar::lr() const
753 return Point(this->lrx(), this->lry());
757 BicycleCar::rr() const
759 return Point(this->rrx(), this->rry());
763 BicycleCar::rf() const
765 return Point(this->rfx(), this->rfy());
769 BicycleCar::left() const
771 return Line(this->lr(), this->lf());
775 BicycleCar::rear() const
777 return Line(this->lr(), this->rr());
781 BicycleCar::right() const
783 return Line(this->rr(), this->rf());
787 BicycleCar::front() const
789 return Line(this->rf(), this->lf());
793 BicycleCar::ralx() const
795 double lrx = this->x();
796 lrx += (this->w() / 2.0) * cos(this->h() + M_PI / 2.0);
800 BicycleCar::raly() const
802 double lry = this->y();
803 lry += (this->w() / 2.0) * sin(this->h() + M_PI / 2.0);
808 BicycleCar::rarx() const
810 double rrx = this->x();
811 rrx += (this->w() / 2.0) * cos(this->h() - M_PI / 2.0);
816 BicycleCar::rary() const
818 double rry = this->y();
819 rry += (this->w() / 2.0) * sin(this->h() - M_PI / 2.0);
824 BicycleCar::ccl() const
827 this->x() + this->mtr() * cos(this->h() + M_PI / 2.0),
828 this->y() + this->mtr() * sin(this->h() + M_PI / 2.0)
833 BicycleCar::ccr() const
836 this->x() + this->mtr() * cos(this->h() - M_PI / 2.0),
837 this->y() + this->mtr() * sin(this->h() - M_PI / 2.0)
844 this->x(this->x() + this->sp() * cos(this->h()));
845 this->y(this->y() + this->sp() * sin(this->h()));
846 this->h(this->h() + this->sp() / this->wb() * tan(this->st()));