Brick
Loading...
Searching...
No Matches
rotation2d.h
1#pragma once
2
3#include "cevalm.hpp"
4#include "core/math/eigen_interface.h"
5#include "core/math/units.h"
6
7/**
8 * Class representing a rotation in 2d space.
9 * Stores cos and sin, and computes angles based on that.
10 *
11 * By nature the stored angle is wrapped, but there are functions
12 * that return angles wrapped specifically between e.g. [-180, 180) and [0, 360)
13 *
14 * If you need your angle to be continuous use units::Angle instead.
15 */
17 private:
18 double cos_ = 1;
19 double sin_ = 0;
20
21 public:
22 /// Default Constructor for Rotation2d
23 constexpr Rotation2d() = default;
24
25 /// Constructs a rotation given a units::Angle
26 constexpr Rotation2d(units::Angle value) : cos_(units::cos(value)), sin_(units::sin(value)) {}
27
28 /// Constructs a rotation given an angle in radians.
29 constexpr Rotation2d(double value) : cos_(cevalm::cos(value)), sin_(cevalm::sin(value)) {}
30
31 /**
32 * Constructs a rotation given x and y values, as the angle from the x axis to
33 * the point.
34 *
35 * [theta] = [atan2(y, x)]
36 *
37 * @param x The x value of the point.
38 * @param y The y value of the point.
39 */
40 constexpr Rotation2d(double x, double y) {
41 double mag = cevalm::hypot(x, y);
42 if (x != 0 || y != 0) {
43 cos_ = x / mag;
44 sin_ = y / mag;
45 } else {
46 cos_ = 1;
47 sin_ = 0;
48 }
49 }
50
51 /**
52 * Constructs a rotation given x and y values, as the angle from the x
53 * axis to the point.
54 *
55 * [theta] = [atan2(y, x)]
56 *
57 * @param x The x value of the point.
58 * @param y The y value of the point.
59 */
60 constexpr Rotation2d(units::Length x, units::Length y)
61 : Rotation2d(x.to(units::inches), y.to(units::inches)) {}
62
63 /// Gets an Angle equal to this rotation.
64 constexpr units::Angle angle() const {
65 return units::Angle(cevalm::atan2(sin_, cos_), units::radians);
66 }
67
68 /// Gets the angle in the supplied unit.
69 constexpr double angle(units::Angle unit) const { return angle().to(unit); }
70
71 /// Gets the rotation in radians.
72 constexpr double radians() const { return angle().to(units::radians); }
73
74 /// Gets the rotation in degrees.
75 constexpr double degrees() const { return angle().to(units::degrees); }
76
77 /// Gets the rotation in revolutions.
78 constexpr double revolutions() const { return angle().to(units::revolutions); }
79
80 /// Gets the rotation in gradians.
81 constexpr double gradians() const { return angle().to(units::gradians); }
82
83 /// Gets the cosine of the rotation.
84 constexpr double f_cos() const { return cos_; }
85
86 /// Gets the sine of the rotation.
87 constexpr double f_sin() const { return sin_; }
88
89 /// Gets the tangent of the rotation.
90 constexpr double f_tan() const { return sin_ / cos_; }
91
92 /// Inverts this rotation (conjugate).
93 constexpr Rotation2d inverse() const { return Rotation2d(cos_, -sin_); }
94
95 /// Flips this rotation across the origin.
96 constexpr Rotation2d opposite() const { return Rotation2d(-cos_, -sin_); }
97
98 /// Gets the rotation matrix corresponding to this rotation.
99 constexpr EMat<2, 2> rotation_matrix() const { return EMat<2, 2>{{cos_, -sin_}, {sin_, cos_}}; }
100
101 /// Gets the value of this rotation in radians from [-pi, pi].
102 constexpr double wrapped_radians_180() const { return wrap_radians_180(radians()); }
103
104 /// Gets the value of this rotation in degrees from [-180, 180].
105 constexpr double wrapped_degrees_180() const { return wrap_degrees_180(degrees()); }
106
107 /// Gets the value of this rotation in revolutions from [-0.5, 0.5].
108 constexpr double wrapped_revolutions_180() const { return wrap_revolutions_180(revolutions()); }
109
110 /// Gets the value of this rotation in gradians from [-200, 200].
111 constexpr double wrapped_gradians_180() const { return wrap_gradians_180(gradians()); }
112
113 /// Gets the value of this rotation in radians from [0, 2pi).
114 constexpr double wrapped_radians_360() const { return wrap_radians_360(radians()); }
115
116 /// Gets the value of this rotation in degrees from [0, 360).
117 constexpr double wrapped_degrees_360() const { return wrap_degrees_360(degrees()); }
118
119 /// Gets the value of this rotation in revolutions from [0, 1).
120 constexpr double wrapped_revolutions_360() const { return wrap_revolutions_360(revolutions()); }
121
122 /// Gets the value of this rotation in gradians from [0, 400).
123 constexpr double wrapped_gradians_360() const { return wrap_gradians_360(gradians()); }
124
125 /// Adds another rotation to this rotation
126 constexpr Rotation2d operator+(Rotation2d other) const {
127 return Rotation2d(cos_ * other.cos_ - sin_ * other.sin_, cos_ * other.sin_ + sin_ * other.cos_);
128 }
129
130 /// Adds another rotation to this rotation.
131 constexpr Rotation2d& operator+=(Rotation2d other) { return *this = *this + other; }
132
133 /// Subtracts another rotation from this rotation.
134 constexpr Rotation2d operator-(Rotation2d other) const { return *this + -other; }
135
136 /// Subtracts another rotation from this rotation.
137 constexpr Rotation2d& operator-=(Rotation2d other) { return *this = *this - other; }
138
139 /// Inverts this rotation (conjugate).
140 constexpr Rotation2d operator-() const { return inverse(); }
141
142 /// Multiplies this rotation by a scalar.
143 constexpr Rotation2d operator*(double scalar) const { return Rotation2d(radians() * scalar); }
144
145 /// Multiplies a scalar by this rotation.
146 friend constexpr Rotation2d operator*(double scalar, Rotation2d rotation) {
147 return rotation * scalar;
148 }
149
150 /// Multiplies this rotation by a scalar.
151 constexpr Rotation2d& operator*=(double scalar) { return *this = *this * scalar; }
152
153 /// Divides this rotation by a scalar.
154 constexpr Rotation2d operator/(double scalar) const { return *this * (1.0 / scalar); }
155
156 /// Divides this rotation by a scalar.
157 constexpr Rotation2d& operator/=(double scalar) { return *this = *this / scalar; }
158
159 /// Checks exact equality between this rotation and another rotation.
160 constexpr bool operator==(Rotation2d other) const {
161 return cos_ == other.cos_ && sin_ == other.sin_;
162 }
163
164 /// Compares two angles with a default tolerance of 1e-6 radians.
165 constexpr bool is_near(Rotation2d other, units::Angle tolerance = units::Angle(1e-6)) const {
166 return units::abs((*this - other).angle()) <= tolerance;
167 }
168
169 /**
170 * Helper function that converts degrees to radians.
171 *
172 * @param deg angle degrees
173 * @return double angle radians.
174 */
175 static constexpr double deg2rad(double deg) { return deg * (std::numbers::pi / 180.0); }
176
177 /**
178 * Helper function that converts radians to degrees.
179 *
180 * @param deg angle in radians
181 * @return double angle in degrees.
182 */
183 static constexpr double rad2deg(double rad) { return rad * (180.0 / std::numbers::pi); }
184
185 /**
186 * Helper function that wraps an angle in radians from [-pi, pi].
187 *
188 * @param angle The angle to wrap.
189 * @return The wrapped angle.
190 */
191 static constexpr double wrap_radians_180(double angle) {
192 if (angle >= -std::numbers::pi && angle <= std::numbers::pi) {
193 return angle;
194 }
195 double x = cevalm::fmod(angle, 2 * std::numbers::pi);
196 if (x > std::numbers::pi) {
197 x -= 2 * std::numbers::pi;
198 } else if (x < -std::numbers::pi) {
199 x += 2 * std::numbers::pi;
200 }
201 return x;
202 }
203
204 /**
205 * Helper function that wraps an angle in degrees from [-180, 180].
206 *
207 * @param angle The angle to wrap.
208 * @return The wrapped angle.
209 */
210 static constexpr double wrap_degrees_180(double angle) {
211 if (angle >= -180.0 && angle <= 180.0) {
212 return angle;
213 }
214 double x = cevalm::fmod(angle, 360.0);
215 if (x > 180.0) {
216 x -= 360.0;
217 } else if (x < -180.0) {
218 x += 360.0;
219 }
220 return x;
221 }
222
223 /**
224 * Helper function that wraps an angle in revolutions from [-0.5, 0.5].
225 *
226 * @param angle The angle to wrap.
227 * @return The wrapped angle.
228 */
229 static constexpr double wrap_revolutions_180(double angle) {
230 if (angle >= -0.5 && angle <= 0.5) {
231 return angle;
232 }
233 double x = cevalm::fmod(angle, 1.0);
234 if (x > 0.5) {
235 x -= 1.0;
236 } else if (x < -0.5) {
237 x += 1.0;
238 }
239 return x;
240 }
241
242 /**
243 * Helper function that wraps an angle in gradians from [-200, 200].
244 *
245 * @param angle The angle to wrap.
246 * @return The wrapped angle.
247 */
248 static constexpr double wrap_gradians_180(double angle) {
249 if (angle >= -200.0 && angle <= 200.0) {
250 return angle;
251 }
252 double x = cevalm::fmod(angle, 400.0);
253 if (x > 200.0) {
254 x -= 400.0;
255 } else if (x < -200.0) {
256 x += 400.0;
257 }
258 return x;
259 }
260
261 /**
262 * Helper function that wraps an angle in radians from [0, 2pi).
263 *
264 * @param angle The angle to wrap.
265 * @return The wrapped angle.
266 */
267 static constexpr double wrap_radians_360(double angle) {
268 if (angle >= 0.0 && angle < 2 * std::numbers::pi) {
269 return angle;
270 }
271 double x = cevalm::fmod(angle, 2 * std::numbers::pi);
272 if (x < 0.0) {
273 x += 2 * std::numbers::pi;
274 }
275 return (x >= 2 * std::numbers::pi) ? 0.0 : x;
276 }
277
278 /**
279 * Helper function that wraps an angle in degrees from [0, 360).
280 *
281 * @param angle The angle to wrap.
282 * @return The wrapped angle.
283 */
284 static constexpr double wrap_degrees_360(double angle) {
285 if (angle >= 0.0 && angle < 360.0) {
286 return angle;
287 }
288 double x = cevalm::fmod(angle, 360.0);
289 if (x < 0.0) {
290 x += 360.0;
291 }
292 return (x >= 360.0) ? 0.0 : x;
293 }
294
295 /**
296 * Helper function that wraps an angle in revolutions from [0, 1).
297 *
298 * @param angle The angle to wrap.
299 * @return The wrapped angle.
300 */
301 static constexpr double wrap_revolutions_360(double angle) {
302 if (angle >= 0.0 && angle < 1.0) {
303 return angle;
304 }
305 double x = cevalm::fmod(angle, 1.0);
306 if (x < 0.0) {
307 x += 1.0;
308 }
309 return (x >= 1.0) ? 0.0 : x;
310 }
311
312 /**
313 * Helper function that wraps an angle in gradians from [0, 400).
314 *
315 * @param angle The angle to wrap.
316 * @return The wrapped angle.
317 */
318 static constexpr double wrap_gradians_360(double angle) {
319 if (angle >= 0.0 && angle < 400.0) {
320 return angle;
321 }
322 double x = cevalm::fmod(angle, 400.0);
323 if (x < 0.0) {
324 x += 400.0;
325 }
326 return (x >= 400.0) ? 0.0 : x;
327 }
328};
constexpr double wrapped_revolutions_180() const
Gets the value of this rotation in revolutions from [-0.5, 0.5].
Definition rotation2d.h:108
constexpr Rotation2d & operator*=(double scalar)
Multiplies this rotation by a scalar.
Definition rotation2d.h:151
constexpr double radians() const
Gets the rotation in radians.
Definition rotation2d.h:72
constexpr double f_sin() const
Gets the sine of the rotation.
Definition rotation2d.h:87
static constexpr double wrap_degrees_180(double angle)
Definition rotation2d.h:210
constexpr double wrapped_gradians_180() const
Gets the value of this rotation in gradians from [-200, 200].
Definition rotation2d.h:111
constexpr Rotation2d(units::Length x, units::Length y)
Definition rotation2d.h:60
static constexpr double wrap_revolutions_360(double angle)
Definition rotation2d.h:301
static constexpr double wrap_gradians_360(double angle)
Definition rotation2d.h:318
constexpr Rotation2d(double x, double y)
Definition rotation2d.h:40
constexpr Rotation2d & operator/=(double scalar)
Divides this rotation by a scalar.
Definition rotation2d.h:157
constexpr Rotation2d operator-(Rotation2d other) const
Subtracts another rotation from this rotation.
Definition rotation2d.h:134
constexpr double revolutions() const
Gets the rotation in revolutions.
Definition rotation2d.h:78
constexpr double wrapped_degrees_180() const
Gets the value of this rotation in degrees from [-180, 180].
Definition rotation2d.h:105
constexpr double degrees() const
Gets the rotation in degrees.
Definition rotation2d.h:75
constexpr double f_tan() const
Gets the tangent of the rotation.
Definition rotation2d.h:90
static constexpr double wrap_gradians_180(double angle)
Definition rotation2d.h:248
constexpr double wrapped_degrees_360() const
Gets the value of this rotation in degrees from [0, 360).
Definition rotation2d.h:117
constexpr double wrapped_gradians_360() const
Gets the value of this rotation in gradians from [0, 400).
Definition rotation2d.h:123
constexpr Rotation2d(units::Angle value)
Constructs a rotation given a units::Angle.
Definition rotation2d.h:26
constexpr Rotation2d operator*(double scalar) const
Multiplies this rotation by a scalar.
Definition rotation2d.h:143
static constexpr double wrap_radians_180(double angle)
Definition rotation2d.h:191
constexpr units::Angle angle() const
Gets an Angle equal to this rotation.
Definition rotation2d.h:64
constexpr Rotation2d & operator+=(Rotation2d other)
Adds another rotation to this rotation.
Definition rotation2d.h:131
constexpr double angle(units::Angle unit) const
Gets the angle in the supplied unit.
Definition rotation2d.h:69
static constexpr double wrap_revolutions_180(double angle)
Definition rotation2d.h:229
constexpr Rotation2d operator+(Rotation2d other) const
Adds another rotation to this rotation.
Definition rotation2d.h:126
constexpr Rotation2d operator-() const
Inverts this rotation (conjugate).
Definition rotation2d.h:140
static constexpr double rad2deg(double rad)
Definition rotation2d.h:183
constexpr bool operator==(Rotation2d other) const
Checks exact equality between this rotation and another rotation.
Definition rotation2d.h:160
constexpr Rotation2d()=default
Default Constructor for Rotation2d.
constexpr double gradians() const
Gets the rotation in gradians.
Definition rotation2d.h:81
friend constexpr Rotation2d operator*(double scalar, Rotation2d rotation)
Multiplies a scalar by this rotation.
Definition rotation2d.h:146
constexpr double wrapped_radians_180() const
Gets the value of this rotation in radians from [-pi, pi].
Definition rotation2d.h:102
constexpr Rotation2d & operator-=(Rotation2d other)
Subtracts another rotation from this rotation.
Definition rotation2d.h:137
static constexpr double deg2rad(double deg)
Definition rotation2d.h:175
constexpr Rotation2d inverse() const
Inverts this rotation (conjugate).
Definition rotation2d.h:93
constexpr Rotation2d(double value)
Constructs a rotation given an angle in radians.
Definition rotation2d.h:29
constexpr Rotation2d opposite() const
Flips this rotation across the origin.
Definition rotation2d.h:96
constexpr EMat< 2, 2 > rotation_matrix() const
Gets the rotation matrix corresponding to this rotation.
Definition rotation2d.h:99
constexpr bool is_near(Rotation2d other, units::Angle tolerance=units::Angle(1e-6)) const
Compares two angles with a default tolerance of 1e-6 radians.
Definition rotation2d.h:165
static constexpr double wrap_radians_360(double angle)
Definition rotation2d.h:267
constexpr double wrapped_radians_360() const
Gets the value of this rotation in radians from [0, 2pi).
Definition rotation2d.h:114
static constexpr double wrap_degrees_360(double angle)
Definition rotation2d.h:284
constexpr double wrapped_revolutions_360() const
Gets the value of this rotation in revolutions from [0, 1).
Definition rotation2d.h:120
constexpr Rotation2d operator/(double scalar) const
Divides this rotation by a scalar.
Definition rotation2d.h:154
constexpr double f_cos() const
Gets the cosine of the rotation.
Definition rotation2d.h:84
Definition units.h:12