]> rtime.felk.cvut.cz Git - hubacji1/bcar.git/blob - src/pslot.cc
Add slot frame point and side getters
[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 Point
99 ParkingSlot::lf() const
100 {
101         return Point(this->lfx(), this->lfy());
102 }
103
104 Point
105 ParkingSlot::lr() const
106 {
107         return Point(this->lrx(), this->lry());
108 }
109
110 Point
111 ParkingSlot::rr() const
112 {
113         return Point(this->rrx(), this->rry());
114 }
115
116 Point
117 ParkingSlot::rf() const
118 {
119         return Point(this->rfx(), this->rfy());
120 }
121
122 Line
123 ParkingSlot::entry() const
124 {
125         return this->entry_;
126 }
127
128 Line
129 ParkingSlot::rear() const
130 {
131         return this->rear_;
132 }
133
134 Line
135 ParkingSlot::curb() const
136 {
137         return this->curb_;
138 }
139
140 Line
141 ParkingSlot::front() const
142 {
143         return this->front_;
144 }
145
146 void
147 ParkingSlot::set_parking_speed(double s)
148 {
149         this->parking_speed_ = s;
150 }
151
152 void
153 ParkingSlot::set_max_cusp(unsigned int m)
154 {
155         this->max_cusp_ = m;
156 }
157
158 void
159 ParkingSlot::set_delta_angle_to_slot(double d)
160 {
161         this->delta_angle_to_slot_ = d;
162 }
163
164 bool
165 ParkingSlot::parallel() const
166 {
167         return this->entry_.len() > this->rear_.len();
168 }
169
170 bool
171 ParkingSlot::right() const
172 {
173         return this->border_[1].on_right_side_of(this->entry_);
174 }
175
176 void
177 ParkingSlot::swap_side()
178 {
179         this->border_[1].rotate(this->border_[0], M_PI);
180         this->border_[2].rotate(this->border_[3], M_PI);
181         this->entry_ = Line(this->border_[0], this->border_[3]);
182         this->rear_ = Line(this->border_[0], this->border_[1]);
183         this->curb_ = Line(this->border_[1], this->border_[2]);
184         this->front_ = Line(this->border_[2], this->border_[3]);
185 }
186
187 bool
188 ParkingSlot::parked(BicycleCar const& c) const
189 {
190         auto b_len = sizeof(this->border_) / sizeof(this->border_[0]);
191         std::vector<Point> b(this->border_, this->border_ + b_len);
192         return c.lf().inside_of(b) && c.lr().inside_of(b)
193                 && c.rr().inside_of(b) && c.rf().inside_of(b);
194 }
195
196 bool
197 ParkingSlot::collide(BicycleCar const& c) const
198 {
199         return c.left().intersects_with(this->rear_)
200                 || c.left().intersects_with(this->curb_)
201                 || c.left().intersects_with(this->front_)
202                 || c.rear().intersects_with(this->rear_)
203                 || c.rear().intersects_with(this->curb_)
204                 || c.rear().intersects_with(this->front_)
205                 || c.right().intersects_with(this->rear_)
206                 || c.right().intersects_with(this->curb_)
207                 || c.right().intersects_with(this->front_)
208                 || c.front().intersects_with(this->rear_)
209                 || c.front().intersects_with(this->curb_)
210                 || c.front().intersects_with(this->front_);
211 }
212
213 std::vector<BicycleCar>
214 ParkingSlot::drive_in_slot(BicycleCar c)
215 {
216         assert(this->parallel());
217         assert(this->right());
218         assert(c.len() < this->len());
219         assert(c.w() < this->w());
220         std::vector<BicycleCar> path;
221         path.reserve(this->max_cusp_ + 2);
222         path.push_back(c);
223         unsigned int cusp = 0;
224         while (cusp < this->max_cusp_ + 1) {
225                 if (this->parked(c)) {
226                         if (cusp < this->max_cusp_) {
227                                 this->max_cusp_ = cusp;
228                         }
229                         path.push_back(c);
230                         return path;
231                 }
232                 if (c.h() < this->h()) {
233                         return std::vector<BicycleCar>();
234                 }
235                 c.next();
236                 if (this->collide(c)) {
237                         c.sp(c.sp() * -1.0);
238                         c.next();
239                         path.push_back(c);
240                         c.st(c.st() * -1.0);
241                         cusp += 1;
242                 }
243         }
244         return std::vector<BicycleCar>();
245 }
246
247 std::vector<Pose>
248 ParkingSlot::steer_in_slot(BicycleCar c)
249 {
250         std::vector<Pose> path;
251         while (!this->parked(c)) {
252                 path.push_back(c);
253                 c.next();
254                 if (this->collide(c)) {
255                         c.sp(c.sp() * -1.0);
256                         c.next();
257                         c.st(c.st() * -1.0);
258                 }
259         }
260         return path;
261 }
262
263 PoseRange
264 ParkingSlot::fe(BicycleCar c)
265 {
266         assert(this->parallel());
267         assert(this->right());
268         c.h(this->h());
269         double clen = -this->offset_ + this->len() - c.df();
270         double cw = c.w() / 2.0;
271         c.x(this->lrx() + clen * cos(c.h()) + cw * cos(c.h() + M_PI / 2.0));
272         c.y(this->lry() + clen * sin(c.h()) + cw * sin(c.h() + M_PI / 2.0));
273         c.set_max_steer();
274         c.sp(this->parking_speed_);
275         auto const rc = c.rf();
276         this->curb_.intersects_with(rc, c.len());
277         double max_to_slot;
278         auto const& rr = c.rr();
279         auto const& i1 = this->curb_.i1();
280         auto const& i2 = this->curb_.i2();
281         if (rr.edist(i1) < rr.edist(i2)) {
282                 max_to_slot = rr.min_angle_between(rc, i1);
283         } else {
284                 max_to_slot = rr.min_angle_between(rc, i2);
285         }
286         std::vector<BicycleCar> starts;
287         double a_to_slot = 0.0;
288         while (a_to_slot < max_to_slot) {
289                 a_to_slot += this->delta_angle_to_slot_;
290                 c.rotate(rc, this->delta_angle_to_slot_);
291                 starts.push_back(c);
292         }
293         std::vector<std::vector<BicycleCar>> entries;
294         for (auto s: starts) {
295                 auto r = this->drive_in_slot(s);
296                 if (r.size() > 0) {
297                         entries.push_back(r);
298                 }
299         }
300         if (entries.size() == 0) {
301                 return PoseRange(Pose(0.0, 0.0, 0.0), Pose(0.0, 0.0, 0.0));
302         }
303         if (entries.size() == 1) {
304                 auto f = entries.front().front();
305                 return PoseRange(f, f);
306         }
307         auto& c1 = entries.front().front();
308         auto& c2 = entries.back().front();
309         return PoseRange(c1, c2);
310 }
311
312 PoseRange
313 ParkingSlot::recompute_entry(PoseRange p)
314 {
315         p.rotate(Point(0.0, 0.0), this->h());
316         p.translate(this->border_[0]);
317         if (!this->right()) {
318                 p.reflect(this->entry_);
319         }
320         return p;
321 }
322
323 std::ostream&
324 operator<<(std::ostream& o, ParkingSlot const& s)
325 {
326         o << "[";
327         o << s.border_[0] << ",";
328         o << s.border_[1] << ",";
329         o << s.border_[2] << ",";
330         o << s.border_[3];
331         o << "]";
332         return o;
333 }
334
335 } // namespace bcar