]> rtime.felk.cvut.cz Git - hubacji1/bcar.git/blob - incl/bcar.hh
e1a17ddad9e32bd5e7e8ef98680aa4ccd1668989
[hubacji1/bcar.git] / incl / bcar.hh
1 /*! \file */
2 #ifndef BCAR_BCAR_H
3 #define BCAR_BCAR_H
4
5 #include <ostream>
6 #include <vector>
7
8 namespace bcar {
9
10 template <typename T> int sgn(T val) {
11         return (T(0) < val) - (val < T(0));
12 }
13
14 class Line;
15
16 class Point {
17 private:
18         double x_ = 0.0;
19         double y_ = 0.0;
20 public:
21         Point();
22         Point(double x, double y);
23
24         /*! Get horizontal coordinate. */
25         double x() const;
26
27         /*! Set horizontal coordinate. */
28         void x(double x);
29
30         /*! Get vertical coordinate. */
31         double y() const;
32
33         /*! Set vertical coordinate. */
34         void y(double y);
35
36         /*! \brief Return the smallest angle between three points.
37
38         \see https://math.stackexchange.com/questions/361412/finding-the-angle-between-three-points
39         */
40         double min_angle_between(Point const& p1, Point const& p2) const;
41
42         /*! \brief Return `true` if `this` point is inside of polygon `poly`.
43          *
44          * The polygon is given by the vector of `Point`s.
45          *
46          * \see https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
47          *
48          * \param poly Polygon to consider.
49          */
50         bool inside_of(std::vector<Point> const& poly) const;
51
52         /*! \brief Return `true` if on the right side of the plane.
53          *
54          * The plane is given by the line `li`, where `li->b()` is the base
55          * point and the direction is given by `li->e() - li->b()`.
56          *
57          * \param li The plane to consider is given by `li`.
58          */
59         bool on_right_side_of(Line const& li) const;
60
61         /*! \brief Translate self.
62          *
63          * \param p `Point` offset to translate by.
64          */
65         void translate(Point const& p);
66
67         /*! \brief Rotate self around the point.
68
69         \param c Rotation center `Point`.
70         \param angl Angle of rotation.
71         */
72         void rotate(Point const& c, double const angl);
73
74         /*! \brief Compute reflection of `this` around the `Line`.
75          *
76          * \param li The plane to reflect around is given by `li`.
77          */
78         void reflect(Line const& li);
79
80         /*! Return Euclidean distance to `p`. */
81         double edist(Point const& p) const;
82
83         bool operator==(Point const& p);
84         friend std::ostream& operator<<(std::ostream& out, Point const& p);
85 };
86
87 class Line {
88 private:
89         Point b_;
90         Point e_;
91         Point i1_;
92         Point i2_;
93 public:
94         Line(Point const& fp, Point const& lp);
95
96         /*! Get beginning point. */
97         Point b() const&;
98
99         /*! Get end point. */
100         Point e() const&;
101
102         /*! Get middle point. */
103         Point m() const;
104
105         /*! Get intersection point. */
106         Point i1() const&;
107
108         /*! Get intersection point. */
109         Point i2() const&;
110
111         /*! \brief Return if `this` line intersects with line `li`.
112          *
113          * If the method returns `true`, the intersection `Point` is available
114          * in `this->i1()`.
115          *
116          * \see https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
117          *
118          * \param li The line to check the intersection with.
119          */
120         bool intersects_with(Line const& li);
121
122         /*! \brief Return intersections of `this` (infinite) line and circle.
123          *
124          * If the method returns `true`, the intersection `Point`s are available
125          * in `this->i1()` and `this->i2()`.
126          *
127          * \see https://mathworld.wolfram.com/Circle-LineIntersection.html
128          *
129          * \param c Circle center.
130          * \param r Circle radius.
131          */
132         bool intersects_with(Point const& c, double const r);
133
134         double len() const;
135
136         double h() const;
137
138         friend std::ostream& operator<<(std::ostream& out, Line const& li);
139 };
140
141 /*! Store coordinates `x`, `y`, and heading `h`. */
142 class Pose : public virtual Point {
143 private:
144         double h_ = 0.0;
145 public:
146         using Point::Point;
147         Pose(double x, double y, double h);
148
149         /*! Get heading in the interval [-pi, +pi] radians. */
150         double h() const;
151
152         /*! Set heading in radians. It's recomputed to [-pi, +pi]. */
153         void h(double h);
154
155         /*! Set pose (`x`, `y`, and `h`.) */
156         void set_pose(Pose const& p);
157
158         void rotate(Point const& c, double const angl);
159
160         void reflect(Line const& li);
161
162         bool operator==(Pose const& p);
163         friend std::ostream& operator<<(std::ostream& out, Pose const& p);
164 };
165
166 class PoseRange : public virtual Pose {
167 private:
168         Pose bp_;
169         Pose ep_;
170         void set_xyh();
171 public:
172         PoseRange(Pose bp, Pose ep);
173         PoseRange(double x, double y, double b, double e);
174
175         Pose bp() const;
176         Pose ep() const;
177
178         /*! Get heading's begin in the interval [-pi, +pi] radians. */
179         double b() const;
180
181         /*! Get heading's end in the interval [-pi, +pi] radians. */
182         double e() const;
183
184         void translate(Point const& p);
185         void rotate(Point const& c, double const angl);
186         void reflect(Line const& li);
187
188         friend std::ostream& operator<<(std::ostream& out, PoseRange const& p);
189 };
190
191 /*! \brief Store car size.
192  *
193  * - Default is https://en.wikipedia.org/wiki/Fiat_Punto
194  */
195 class CarSize {
196 private:
197         double curb_to_curb_ = 10.820;
198         double width_ = 1.625;
199         double wheelbase_ = 2.450;
200         double distance_to_front_ = 3.105;
201         double length_ = 3.760;
202 public:
203         /*! Get curb-to-curb distance. */
204         double ctc() const;
205
206         /*! Set curb-to-curb distance. */
207         void ctc(double ctc);
208
209         /*! Get wheelbase. */
210         double wb() const;
211
212         /*! Set wheelbase. */
213         void wb(double wb);
214
215         /*! Get width. */
216         double w() const;
217
218         /*! Set width. */
219         void w(double w);
220
221         /*! Get length. */
222         double len() const;
223
224         /*! Set length. */
225         void len(double len);
226
227         /*! Get distance from rear axle to front. */
228         double df() const;
229
230         /*! Set distance from rear axle to front. */
231         void df(double df);
232
233         /*! Get distance from rear axle to rear. */
234         double dr() const;
235
236         /*! \brief Get minimum turning radius.
237          *
238          * Please, note that the method returns really _minimum turning radius_,
239          * which is the distance from the rear axle center to the center of
240          * left or right rotation given by the kinematics constrants, i.e.
241          * _wheelbase_ and _curb-to-curb_ distance.
242          *
243          * Sometimes _minimum turning radius_ is not radius, not minimum, or not
244          * turning. In this method, _minimum turning radius_ is minimum turning
245          * radius.
246          */
247         double mtr() const;
248
249         /*! \brief Return inner radius.
250          *
251          * The inner radius is the distance from minimum turning radius circle
252          * center to the nearest point on the car. In this case, the nearest
253          * points on the car are rear axle endpoints.
254          */
255         double iradi() const;
256
257         /*! \brief Return outer front radius.
258          *
259          * The outer front radius is the distance from minimum turning radius
260          * circle center to the farthest point on the front (from the rear axle
261          * view) part of the car.
262          */
263         double ofradi() const;
264
265         /*! \brief Return outer rear radius.
266          *
267          * The outer rear radius is the distance from minimum turning radius
268          * circle center to the farthest point on the rear (from the rear axle
269          * view) part of the car.
270          */
271         double orradi() const;
272
273         /*! \brief Return length of perfect parking slot.
274          *
275          * The width of the slot is the same as the width of the car.
276          *
277          * \see Simon R. Blackburn *The Geometry of Perfect Parking*
278          * \see https://www.ma.rhul.ac.uk/SRBparking
279          */
280         double perfect_parking_slot_len() const;
281 };
282
283 /*! Store car motion. */
284 class CarMove {
285 private:
286         double speed_ = 0.0;
287         double steer_ = 0.0;
288 public:
289         /*! Get speed. */
290         double sp() const;
291
292         /*! Set speed. */
293         void sp(double sp);
294
295         /*! Get steer. */
296         double st() const;
297
298         /*! Set steer. */
299         void st(double st);
300 };
301
302 /*! \brief Geometrical computations of a bicycle car.
303  *
304  * - `x()` and `y()` methods returns coordinates of rear axle center.
305  */
306 class BicycleCar : public virtual Pose, public virtual CarSize,
307                 public virtual CarMove {
308 private:
309 public:
310         /*! \brief Return `true` if `this` can drive to `p` trivially.
311          *
312          * Trivially means that `this` can drive to `p` by line segment - circle
313          * arc - line segment.
314          *
315          * \param p `PoseRange` (resp. `Pose`) to achieve.
316          */
317         bool drivable(PoseRange const& p) const;
318         bool drivable(Pose const& p) const;
319
320         /*! Set maximum steering angle. */
321         void set_max_steer();
322
323         /*! Get frame's left front x coordinate. */
324         double lfx() const;
325
326         /*! Get frame's left front y coordinate. */
327         double lfy() const;
328
329         /*! Get frame's left rear x coordinate. */
330         double lrx() const;
331
332         /*! Get frame's left rear y coordinate. */
333         double lry() const;
334
335         /*! Get frame's right rear x coordinate. */
336         double rrx() const;
337
338         /*! Get frame's right rear y coordinate. */
339         double rry() const;
340
341         /*! Get frame's right front x coordinate. */
342         double rfx() const;
343
344         /*! Get frame's right front y coordinate. */
345         double rfy() const;
346
347         /*! Get frame's left front point. */
348         Point lf() const;
349
350         /*! Get frame's left rear point. */
351         Point lr() const;
352
353         /*! Get frame's right rear point. */
354         Point rr() const;
355
356         /*! Get frame's right front point. */
357         Point rf() const;
358
359         /*! Get frame's left side. */
360         Line left() const;
361
362         /*! Get frame's rear side. */
363         Line rear() const;
364
365         /*! Get frame's right side. */
366         Line right() const;
367
368         /*! Get frame's front side. */
369         Line front() const;
370
371         /*! Get rear axle's left x coordinate. */
372         double ralx() const;
373
374         /*! Get rear axle's left y coordinate. */
375         double raly() const;
376
377         /*! Get rear axle's right x coordinate. */
378         double rarx() const;
379
380         /*! Get rear axle's right y coordinate. */
381         double rary() const;
382
383         /*! Min. turning radius circle center on left. */
384         Point ccl() const;
385
386         /*! Min. turning radius circle center on rigth. */
387         Point ccr() const;
388
389         /*! Next car position based on speed `sp` and steer `st`. */
390         void next();
391 };
392
393 } // namespace bcar
394 #endif /* BCAR_BCAR_H */