]> rtime.felk.cvut.cz Git - hubacji1/bcar.git/blob - src/pslot.cc
6966377bf8999107a36f3b24645fbdeacccf6b71
[hubacji1/bcar.git] / src / pslot.cc
1 #include <cassert>
2 #include <cmath>
3 #include "pslot.hh"
4
5 namespace bcar {
6
7 ParkingSlot::ParkingSlot(Point p, double h, double W, double L) :
8                 border_({p,
9                         Point(p.x() + W * cos(h - M_PI / 2.0),
10                                 p.y() + W * sin(h - M_PI / 2.0)),
11                         Point(p.x() + W * cos(h - M_PI / 2.0) + L * cos(h),
12                                 p.y() + W * sin(h - M_PI / 2.0) + L * sin(h)),
13                         Point(p.x() + L * cos(h), p.y() + L * sin(h))}),
14                 entry_(border_[0], border_[3]),
15                 rear_(border_[0], border_[1]),
16                 curb_(border_[1], border_[2]),
17                 front_(border_[2], border_[3])
18 {
19 }
20
21 ParkingSlot::ParkingSlot(double lrx, double lry, double rrx, double rry,
22                 double rfx, double rfy, double lfx, double lfy) :
23                         border_({Point(lrx, lry), Point(rrx, rry),
24                                 Point(rfx, rfy), Point(lfx, lfy)}),
25                         entry_(border_[0], border_[3]),
26                         rear_(border_[0], border_[1]),
27                         curb_(border_[1], border_[2]),
28                         front_(border_[2], border_[3])
29 {
30 }
31
32 double
33 ParkingSlot::len() const
34 {
35         return this->entry_.len();
36 }
37
38 double
39 ParkingSlot::w() const
40 {
41         return this->rear_.len();
42 }
43
44 double
45 ParkingSlot::lfx() const
46 {
47         return this->border_[3].x();
48 }
49
50 double
51 ParkingSlot::lfy() const
52 {
53         return this->border_[3].y();
54 }
55
56 double
57 ParkingSlot::lrx() const
58 {
59         return this->border_[0].x();
60 }
61
62 double
63 ParkingSlot::lry() const
64 {
65         return this->border_[0].y();
66 }
67
68 double
69 ParkingSlot::rrx() const
70 {
71         return this->border_[1].x();
72 }
73
74 double
75 ParkingSlot::rry() const
76 {
77         return this->border_[1].y();
78 }
79
80 double
81 ParkingSlot::rfx() const
82 {
83         return this->border_[2].x();
84 }
85
86 double
87 ParkingSlot::rfy() const
88 {
89         return this->border_[2].y();
90 }
91
92 double
93 ParkingSlot::h() const
94 {
95         return atan2(this->lfy() - this->lry(), this->lfx() - this->lrx());
96 }
97
98 void
99 ParkingSlot::set_parking_speed(double s)
100 {
101         this->parking_speed_ = s;
102 }
103
104 void
105 ParkingSlot::set_max_cusp(unsigned int m)
106 {
107         this->max_cusp_ = m;
108 }
109
110 void
111 ParkingSlot::set_delta_angle_to_slot(double d)
112 {
113         this->delta_angle_to_slot_ = d;
114 }
115
116 bool
117 ParkingSlot::parallel() const
118 {
119         return this->entry_.len() > this->rear_.len();
120 }
121
122 bool
123 ParkingSlot::right() const
124 {
125         return this->border_[1].on_right_side_of(this->entry_);
126 }
127
128 void
129 ParkingSlot::swap_side()
130 {
131         this->border_[1].rotate(this->border_[0], M_PI);
132         this->border_[2].rotate(this->border_[3], M_PI);
133         this->entry_ = Line(this->border_[0], this->border_[3]);
134         this->rear_ = Line(this->border_[0], this->border_[1]);
135         this->curb_ = Line(this->border_[1], this->border_[2]);
136         this->front_ = Line(this->border_[2], this->border_[3]);
137 }
138
139 bool
140 ParkingSlot::parked(BicycleCar const& c) const
141 {
142         auto b_len = sizeof(this->border_) / sizeof(this->border_[0]);
143         std::vector<Point> b(this->border_, this->border_ + b_len);
144         return c.lf().inside_of(b) && c.lr().inside_of(b)
145                 && c.rr().inside_of(b) && c.rf().inside_of(b);
146 }
147
148 bool
149 ParkingSlot::collide(BicycleCar const& c) const
150 {
151         return c.left().intersects_with(this->rear_)
152                 || c.left().intersects_with(this->curb_)
153                 || c.left().intersects_with(this->front_)
154                 || c.rear().intersects_with(this->rear_)
155                 || c.rear().intersects_with(this->curb_)
156                 || c.rear().intersects_with(this->front_)
157                 || c.right().intersects_with(this->rear_)
158                 || c.right().intersects_with(this->curb_)
159                 || c.right().intersects_with(this->front_)
160                 || c.front().intersects_with(this->rear_)
161                 || c.front().intersects_with(this->curb_)
162                 || c.front().intersects_with(this->front_);
163 }
164
165 std::vector<BicycleCar>
166 ParkingSlot::drive_in_slot(BicycleCar c)
167 {
168         assert(this->parallel());
169         assert(this->right());
170         assert(c.len() < this->len());
171         assert(c.w() < this->w());
172         std::vector<BicycleCar> path;
173         path.reserve(this->max_cusp_ + 2);
174         path.push_back(c);
175         unsigned int cusp = 0;
176         while (cusp < this->max_cusp_ + 1) {
177                 if (this->parked(c)) {
178                         if (cusp < this->max_cusp_) {
179                                 this->max_cusp_ = cusp;
180                         }
181                         path.push_back(c);
182                         return path;
183                 }
184                 if (c.h() < this->h()) {
185                         return std::vector<BicycleCar>();
186                 }
187                 c.next();
188                 if (this->collide(c)) {
189                         c.sp(c.sp() * -1.0);
190                         c.next();
191                         path.push_back(c);
192                         c.st(c.st() * -1.0);
193                         cusp += 1;
194                 }
195         }
196         return std::vector<BicycleCar>();
197 }
198
199 std::vector<Pose>
200 ParkingSlot::steer_in_slot(BicycleCar c)
201 {
202         std::vector<Pose> path;
203         while (!this->parked(c)) {
204                 path.push_back(c);
205                 c.next();
206                 if (this->collide(c)) {
207                         c.sp(c.sp() * -1.0);
208                         c.next();
209                         c.st(c.st() * -1.0);
210                 }
211         }
212         path.push_back(c);
213         return path;
214 }
215
216 PoseRange
217 ParkingSlot::fe(BicycleCar c)
218 {
219         assert(this->parallel());
220         assert(this->right());
221         c.h(this->h());
222         double clen = -this->offset_ + this->len() - c.df();
223         double cw = c.w() / 2.0;
224         c.x(this->lrx() + clen * cos(c.h()) + cw * cos(c.h() + M_PI / 2.0));
225         c.y(this->lry() + clen * sin(c.h()) + cw * sin(c.h() + M_PI / 2.0));
226         c.set_max_steer();
227         c.sp(this->parking_speed_);
228         auto const rc = c.rf();
229         this->curb_.intersects_with(rc, c.len());
230         double max_to_slot;
231         auto const& rr = c.rr();
232         auto const& i1 = this->curb_.i1();
233         auto const& i2 = this->curb_.i2();
234         if (rr.edist(i1) < rr.edist(i2)) {
235                 max_to_slot = rr.min_angle_between(rc, i1);
236         } else {
237                 max_to_slot = rr.min_angle_between(rc, i2);
238         }
239         std::vector<BicycleCar> starts;
240         double a_to_slot = 0.0;
241         while (a_to_slot < max_to_slot) {
242                 a_to_slot += this->delta_angle_to_slot_;
243                 c.rotate(rc, this->delta_angle_to_slot_);
244                 starts.push_back(c);
245         }
246         std::vector<std::vector<BicycleCar>> entries;
247         for (auto s: starts) {
248                 auto r = this->drive_in_slot(s);
249                 if (r.size() > 0) {
250                         entries.push_back(r);
251                 }
252         }
253         if (entries.size() == 0) {
254                 return PoseRange(Pose(0.0, 0.0, 0.0), Pose(0.0, 0.0, 0.0));
255         }
256         if (entries.size() == 1) {
257                 auto f = entries.front().front();
258                 return PoseRange(f, f);
259         }
260         auto& c1 = entries.front().front();
261         auto& c2 = entries.back().front();
262         return PoseRange(c1, c2);
263 }
264
265 PoseRange
266 ParkingSlot::recompute_entry(PoseRange p)
267 {
268         p.rotate(Point(0.0, 0.0), this->h());
269         p.x(p.x() + this->lrx());
270         p.y(p.y() + this->lry());
271         if (!this->right()) {
272                 p.reflect(this->entry_);
273         }
274         return p;
275 }
276
277 std::ostream&
278 operator<<(std::ostream& o, ParkingSlot const& s)
279 {
280         o << "[";
281         o << s.border_[0] << ",";
282         o << s.border_[1] << ",";
283         o << s.border_[2] << ",";
284         o << s.border_[3];
285         o << "]";
286         return o;
287 }
288
289 } // namespace bcar