]> rtime.felk.cvut.cz Git - hubacji1/iamcar2.git/blob - bcar/incl/bcar.hh
Mark cusp points in json output
[hubacji1/iamcar2.git] / bcar / incl / bcar.hh
1 /*
2  * SPDX-FileCopyrightText: 2021 Jiri Vlasak <jiri.vlasak.2@cvut.cz>
3  *
4  * SPDX-License-Identifier: GPL-3.0-only
5  */
6
7 /*! \file */
8 #ifndef BCAR_BCAR_H
9 #define BCAR_BCAR_H
10
11 #include <ostream>
12 #include <vector>
13
14 namespace bcar {
15
16 template <typename T> int sgn(T val) {
17         return (T(0) < val) - (val < T(0));
18 }
19
20 class Line;
21
22 class Point {
23 private:
24         double _x = 0.0;
25         double _y = 0.0;
26 public:
27         Point();
28         Point(double x, double y);
29
30         /*! Get horizontal coordinate. */
31         double x() const;
32
33         /*! Set horizontal coordinate. */
34         void x(double x);
35
36         /*! Get vertical coordinate. */
37         double y() const;
38
39         /*! Set vertical coordinate. */
40         void y(double y);
41
42         /*! \brief Return the smallest angle between three points.
43
44         \see https://math.stackexchange.com/questions/361412/finding-the-angle-between-three-points
45         */
46         double min_angle_between(Point const& p1, Point const& p2) const;
47
48         /*! \brief Return `true` if `this` point is inside of polygon `poly`.
49          *
50          * The polygon is given by the vector of `Point`s.
51          *
52          * \see https://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
53          *
54          * \param poly Polygon to consider.
55          */
56         bool inside_of(std::vector<Point> const& poly) const;
57
58         /*! \brief Return `true` if `this` point is inside the circle `c`, `r`.
59          *
60          * \see * https://math.stackexchange.com/questions/198764/how-to-know-if-a-point-is-inside-a-circle#198769
61          */
62         bool inside_of(Point const& c, double const r) const;
63
64         /*! \brief Return `true` if on the right side of the plane.
65          *
66          * The plane is given by the line `li`, where `li->b()` is the base
67          * point and the direction is given by `li->e() - li->b()`.
68          *
69          * \param li The plane to consider is given by `li`.
70          */
71         bool on_right_side_of(Line const& li) const;
72
73         /*! \brief Translate self.
74          *
75          * \param p `Point` offset to translate by.
76          */
77         void translate(Point const& p);
78
79         /*! \brief Rotate self around the point.
80
81         \param c Rotation center `Point`.
82         \param angl Angle of rotation.
83         */
84         void rotate(Point const& c, double const angl);
85
86         /*! \brief Compute reflection of `this` around the `Line`.
87          *
88          * \param li The plane to reflect around is given by `li`.
89          */
90         void reflect(Line const& li);
91
92         /*! Return Euclidean distance to `p`. */
93         double edist(Point const& p) const;
94
95         /*! Generate output for plotting with gnuplot. */
96         void gen_gnuplot_to(std::ostream& out);
97
98         bool operator==(Point const& p);
99         friend std::ostream& operator<<(std::ostream& out, Point const& p);
100 };
101
102 class Line {
103 private:
104         Point _b;
105         Point _e;
106         Point _i1;
107         Point _i2;
108 public:
109         Line(Point const& fp, Point const& lp);
110
111         /*! Get beginning point. */
112         Point b() const&;
113
114         /*! Get end point. */
115         Point e() const&;
116
117         /*! Get middle point. */
118         Point m() const;
119
120         /*! Get intersection point. */
121         Point i1() const&;
122
123         /*! Get intersection point. */
124         Point i2() const&;
125
126         /*! \brief Return if `this` line intersects with line `li`.
127          *
128          * If the method returns `true`, the intersection `Point` is available
129          * in `this->i1()`.
130          *
131          * \see https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
132          *
133          * \param li The line to check the intersection with.
134          */
135         bool intersects_with(Line const& li);
136
137         /*! \brief Return intersections of `this` (infinite) line and circle.
138          *
139          * If the method returns `true`, the intersection `Point`s are available
140          * in `this->i1()` and `this->i2()`.
141          *
142          * \see https://mathworld.wolfram.com/Circle-LineIntersection.html
143          *
144          * \param c Circle center.
145          * \param r Circle radius.
146          */
147         bool intersects_with(Point const& c, double const r);
148
149         double len() const;
150
151         double h() const;
152
153         /*! Generate output for plotting with gnuplot. */
154         void gen_gnuplot_to(std::ostream& out);
155
156         friend std::ostream& operator<<(std::ostream& out, Line const& li);
157 };
158
159 /*! Store coordinates `x`, `y`, and heading `h`. */
160 class Pose : public virtual Point {
161 private:
162         double _h = 0.0;
163 public:
164         using Point::Point;
165         Pose(double x, double y, double h);
166
167         /*! Get heading in the interval [-pi, +pi] radians. */
168         double h() const;
169
170         /*! Set heading in radians. It's recomputed to [-pi, +pi]. */
171         void h(double h);
172
173         /*! Set pose (`x`, `y`, and `h`.) */
174         void set_pose_to(Pose const& p);
175
176         void rotate(Point const& c, double const angl);
177
178         void reflect(Line const& li);
179
180         bool operator==(Pose const& p);
181         friend std::ostream& operator<<(std::ostream& out, Pose const& p);
182 };
183
184 class PoseRange : public virtual Pose {
185 private:
186         Pose _bp;
187         Pose _ep;
188         void set_xyh();
189 public:
190         PoseRange(Pose bp, Pose ep);
191         PoseRange(double x, double y, double b, double e);
192
193         Pose bp() const;
194         Pose ep() const;
195
196         /*! Get heading's begin in the interval [-pi, +pi] radians. */
197         double b() const;
198
199         /*! Get heading's end in the interval [-pi, +pi] radians. */
200         double e() const;
201
202         void translate(Point const& p);
203         void rotate(Point const& c, double const angl);
204         void reflect(Line const& li);
205
206         friend std::ostream& operator<<(std::ostream& out, PoseRange const& p);
207 };
208
209 /*! \brief Store car size.
210  *
211  * - The default is Renault ZOE (www.car.info)
212  */
213 class CarSize {
214 private:
215         double _curb_to_curb = 10.802166641822163;
216         double _width_with_mirrors = 1.945;
217         double _width = 1.771;
218         double _wheelbase = 2.588;
219         double _distance_to_front = 3.427;
220         double _length = 4.084;
221         double _front_track = 1.511;
222 public:
223         /*! Get curb-to-curb distance. */
224         double ctc() const;
225
226         /*! Set curb-to-curb distance. */
227         void ctc(double ctc);
228
229         /*! Get wheelbase. */
230         double wb() const;
231
232         /*! Set wheelbase. */
233         void wb(double wb);
234
235         /*! Get width. */
236         double w() const;
237
238         /*! Set width. */
239         void w(double w);
240
241         /*! Get width with mirrors. */
242         double wwm() const;
243
244         /*! Set width with mirrors. */
245         void wwm(double w);
246
247         /*! Get length. */
248         double len() const;
249
250         /*! Set length. */
251         void len(double len);
252
253         /*! Get distance from rear axle to front. */
254         double df() const;
255
256         /*! Set distance from rear axle to front. */
257         void df(double df);
258
259         /*! Get distance from rear axle to rear. */
260         double dr() const;
261
262         /*! Set front track. */
263         void ft(double ft);
264
265         /*! Get front track. */
266         double ft() const;
267
268         /*! Return rear axle center to right rear corner Euclidean distance. */
269         double edist_to_rr() const;
270
271         /*! Return rear axle center to left front corner Euclidean distance. */
272         double edist_to_lf() const;
273
274         /*! \brief Get minimum turning radius.
275          *
276          * Please, note that the method returns really _minimum turning radius_,
277          * which is the distance from the rear axle center to the center of
278          * left or right rotation given by the kinematics constrants, i.e.
279          * _wheelbase and _curb-to-curb_ distance.
280          *
281          * Sometimes _minimum turning _radius is not radius, not minimum, or not
282          * turning. In this method, _minimum turning _radius is minimum turning
283          * radius.
284          */
285         double mtr() const;
286
287         /*! \brief Return inner radius.
288          *
289          * The inner radius is the distance from minimum turning radius circle
290          * center to the nearest point on the car. In this case, the nearest
291          * points on the car are rear axle endpoints.
292          */
293         double iradi() const;
294
295         /*! \brief Return outer front radius.
296          *
297          * The outer front radius is the distance from minimum turning radius
298          * circle center to the farthest point on the front (from the rear axle
299          * view) part of the car.
300          */
301         double ofradi() const;
302
303         /*! \brief Return outer rear radius.
304          *
305          * The outer rear radius is the distance from minimum turning radius
306          * circle center to the farthest point on the rear (from the rear axle
307          * view) part of the car.
308          */
309         double orradi() const;
310
311         /*! \brief Return inner mirror radius.
312          *
313          * The inner mirror radius is the distance from minimum turning radius
314          * circle center to the farther mirror (from the rear axle view).
315          */
316         double imradi() const;
317
318         /*! \brief Return outer mirror radius.
319          *
320          * The outer mirror radius is the distance from minimum turning radius
321          * circle center to the farther mirror (from the rear axle view).
322          */
323         double omradi() const;
324
325         /*! \brief Return length of perfect parking slot.
326          *
327          * The width of the slot is the same as the width of the car.
328          *
329          * \see Simon R. Blackburn *The Geometry of Perfect Parking*
330          * \see https://www.ma.rhul.ac.uk/SRBparking
331          */
332         double perfect_parking_slot_len() const;
333
334         /*! Set parameters to what car. */
335         void become(std::string const what);
336 };
337
338 /*! Store car motion. */
339 class CarMove {
340 private:
341         double _speed = 0.0;
342         double _steer = 0.0;
343 public:
344         /*! Get speed. */
345         double sp() const;
346
347         /*! Set speed. */
348         void sp(double sp);
349
350         /*! Get steer. */
351         double st() const;
352
353         /*! Set steer. */
354         void st(double st);
355 };
356
357 /*! \brief Geometrical computations of a bicycle car.
358  *
359  * - `x()` and `y()` methods returns coordinates of rear axle center.
360  */
361 class BicycleCar : public virtual Pose, public virtual CarSize,
362                 public virtual CarMove {
363 private:
364 public:
365         /*! \brief Return `true` if `this` can drive to `p` trivially.
366          *
367          * Trivially means that `this` can drive to `p` by line segment - circle
368          * arc - line segment.
369          *
370          * \param p `PoseRange` (resp. `Pose`) to achieve.
371          */
372         bool drivable(PoseRange const& p) const;
373         bool drivable(Pose const& p) const;
374
375         /*! Set maximum steering angle. */
376         void set_max_steer();
377
378         /*! Get frame's left front x coordinate. */
379         double lfx() const;
380
381         /*! Get frame's left front y coordinate. */
382         double lfy() const;
383
384         /*! Get frame's left rear x coordinate. */
385         double lrx() const;
386
387         /*! Get frame's left rear y coordinate. */
388         double lry() const;
389
390         /*! Get frame's right rear x coordinate. */
391         double rrx() const;
392
393         /*! Get frame's right rear y coordinate. */
394         double rry() const;
395
396         /*! Get frame's right front x coordinate. */
397         double rfx() const;
398
399         /*! Get frame's right front y coordinate. */
400         double rfy() const;
401
402         /*! Get frame's left front point. */
403         Point lf() const;
404
405         /*! Get frame's left rear point. */
406         Point lr() const;
407
408         /*! Get frame's right rear point. */
409         Point rr() const;
410
411         /*! Get frame's right front point. */
412         Point rf() const;
413
414         /*! Get frame's left side. */
415         Line left() const;
416
417         /*! Get frame's rear side. */
418         Line rear() const;
419
420         /*! Get frame's right side. */
421         Line right() const;
422
423         /*! Get frame's front side. */
424         Line front() const;
425
426         /*! Get frame's left rear axle x coordinate. */
427         double lrax() const;
428
429         /*! Get frame's left rear axle y coordinate. */
430         double lray() const;
431
432         /*! Get frame's right rear axle x coordinate. */
433         double rrax() const;
434
435         /*! Get frame's right rear axle y coordinate. */
436         double rray() const;
437
438         /*! Get frame's left rear axle point. */
439         Point lra() const;
440
441         /*! Get frame's right rear axle point. */
442         Point rra() const;
443
444         /*! Get frame's left front axle x coordinate. */
445         double lfax() const;
446
447         /*! Get frame's left front axle y coordinate. */
448         double lfay() const;
449
450         /*! Get frame's right front axle x coordinate. */
451         double rfax() const;
452
453         /*! Get frame's right front axle y coordinate. */
454         double rfay() const;
455
456         /*! Get iframe's left front axle point. */
457         Point lfa() const;
458
459         /*! Get frame's right front axle point. */
460         Point rfa() const;
461
462         /*! Get frame's left front mirror x coordinate. */
463         double lfmx() const;
464
465         /*! Get frame's left front mirror y coordinate. */
466         double lfmy() const;
467
468         /*! Get frame's right front mirror x coordinate. */
469         double rfmx() const;
470
471         /*! Get frame's right front mirror y coordinate. */
472         double rfmy() const;
473
474         /*! Get iframe's left front mirror point. */
475         Point lfm() const;
476
477         /*! Get frame's right front mirror point. */
478         Point rfm() const;
479
480         /*! Get frame's center front x coordinate. */
481         double cfx() const;
482
483         /*! Get frame's center front y coordinate. */
484         double cfy() const;
485
486         /*! Get frame's center front point. */
487         Point cf() const;
488
489         /*! Min. turning radius circle center on left. */
490         Point ccl() const;
491
492         /*! Min. turning radius circle center on rigth. */
493         Point ccr() const;
494
495         /*! Next car position based on speed `sp` and steer `st`. */
496         void next();
497
498         /*! Options for generating output for gnuplot. */
499         class GenPlotOpts {
500         public:
501                 bool LF_POINT = false;
502                 bool LR_POINT = false;
503                 bool RR_POINT = false;
504                 bool RF_POINT = false;
505                 bool LFM_POINT = false;
506                 bool RFM_POINT = false;
507                 bool CRA_POINT = false;
508                 bool CAR_POINT = false;
509                 bool LRA_POINT = false;
510                 bool RRA_POINT = false;
511
512                 bool LEFT = false;
513                 bool RIGHT = false;
514                 bool REAR = false;
515                 bool FRONT = false;
516                 bool FRAME = false; // LEFT, RIGHT, REAR, FRONT
517                 bool ARROW = false;
518                 bool CROSS = false;
519                 bool CAR = false; // CROSS, ARROW, FRAME
520                 bool LEFT_MIRROR = false;
521                 bool RIGHT_MIRROR = false;
522                 bool MIRRORS = false; // RIGHT_MIRROR, LEFT_MIRROR
523                 bool ALL = true; // MIRRORS, CAR
524         };
525
526         /*! Generate output for plotting with gnuplot. */
527         void gen_gnuplot_to(std::ostream& out, GenPlotOpts opts);
528 };
529
530 } // namespace bcar
531 #endif /* BCAR_BCAR_H */