WPILibC++ 2026.2.1
Loading...
Searching...
No Matches
Rotation3d.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <string>
8#include <type_traits>
9
10#include <Eigen/Core>
11#include <fmt/format.h>
12#include <gcem.hpp>
13#include <wpi/MathExtras.h>
14#include <wpi/SymbolExports.h>
15#include <wpi/json_fwd.h>
16
17#include "frc/ct_matrix.h"
18#include "frc/fmt/Eigen.h"
21#include "units/angle.h"
22#include "units/math.h"
23#include "wpimath/MathShared.h"
24
25namespace frc {
26
27/**
28 * A rotation in a 3D coordinate frame, represented by a quaternion. Note that
29 * unlike 2D rotations, 3D rotations are not always commutative, so changing the
30 * order of rotations changes the result.
31 *
32 * As an example of the order of rotations mattering, suppose we have a card
33 * that looks like this:
34 *
35 * <pre>
36 *   ┌───┐ ┌───┐
37 * │ X │ │ x │
38 * Front: │ | │ Back: │ · │
39 * │ | │ │ · │
40 * └───┘ └───┘
41 * </pre>
42 *
43 * If we rotate 90º clockwise around the axis into the page, then flip around
44 * the left/right axis, we get one result:
45 *
46 * <pre>
47 *  ┌───┐
48 * │ X │ ┌───────┐ ┌───────┐
49 * │ | │ → │------X│ → │······x│
50 * │ | │ └───────┘ └───────┘
51 * └───┘
52 * </pre>
53 *
54 * If we flip around the left/right axis, then rotate 90º clockwise around the
55 * axis into the page, we get a different result:
56 *
57 * <pre>
58 *   ┌───┐ ┌───┐
59 * │ X │ │ · │ ┌───────┐
60 * │ | │ → │ · │ → │x······│
61 * │ | │ │ x │ └───────┘
62 * └───┘ └───┘
63 * </pre>
64 *
65 * Because order matters for 3D rotations, we need to distinguish between
66 * <em>extrinsic</em> rotations and <em>intrinsic</em> rotations. Rotating
67 * extrinsically means rotating around the global axes, while rotating
68 * intrinsically means rotating from the perspective of the other rotation. A
69 * neat property is that applying a series of rotations extrinsically is the
70 * same as applying the same series in the opposite order intrinsically.
71 */
73 public:
74 /**
75 * Constructs a Rotation3d representing no rotation.
76 */
77 constexpr Rotation3d() = default;
78
79 /**
80 * Constructs a Rotation3d from a quaternion.
81 *
82 * @param q The quaternion.
83 */
84 constexpr explicit Rotation3d(const Quaternion& q) { m_q = q.Normalize(); }
85
86 /**
87 * Constructs a Rotation3d from extrinsic roll, pitch, and yaw.
88 *
89 * Extrinsic rotations occur in that order around the axes in the fixed global
90 * frame rather than the body frame.
91 *
92 * Angles are measured counterclockwise with the rotation axis pointing "out
93 * of the page". If you point your right thumb along the positive axis
94 * direction, your fingers curl in the direction of positive rotation.
95 *
96 * @param roll The counterclockwise rotation angle around the X axis (roll).
97 * @param pitch The counterclockwise rotation angle around the Y axis (pitch).
98 * @param yaw The counterclockwise rotation angle around the Z axis (yaw).
99 */
100 constexpr Rotation3d(units::radian_t roll, units::radian_t pitch,
101 units::radian_t yaw) {
102 // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Euler_angles_to_quaternion_conversion
103 double cr = units::math::cos(roll * 0.5);
104 double sr = units::math::sin(roll * 0.5);
105
106 double cp = units::math::cos(pitch * 0.5);
107 double sp = units::math::sin(pitch * 0.5);
108
109 double cy = units::math::cos(yaw * 0.5);
110 double sy = units::math::sin(yaw * 0.5);
111
112 m_q = Quaternion{cr * cp * cy + sr * sp * sy, sr * cp * cy - cr * sp * sy,
113 cr * sp * cy + sr * cp * sy, cr * cp * sy - sr * sp * cy};
114 }
115
116 /**
117 * Constructs a Rotation3d with the given axis-angle representation. The axis
118 * doesn't have to be normalized.
119 *
120 * @param axis The rotation axis.
121 * @param angle The rotation around the axis.
122 */
123 constexpr Rotation3d(const Eigen::Vector3d& axis, units::radian_t angle) {
124 double norm = ct_matrix{axis}.norm();
125 if (norm == 0.0) {
126 return;
127 }
128
129 // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Definition
130 Eigen::Vector3d v{{axis(0) / norm * units::math::sin(angle / 2.0),
131 axis(1) / norm * units::math::sin(angle / 2.0),
132 axis(2) / norm * units::math::sin(angle / 2.0)}};
133 m_q = Quaternion{units::math::cos(angle / 2.0), v(0), v(1), v(2)};
134 }
135
136 /**
137 * Constructs a Rotation3d with the given rotation vector representation. This
138 * representation is equivalent to axis-angle, where the normalized axis is
139 * multiplied by the rotation around the axis in radians.
140 *
141 * @param rvec The rotation vector.
142 */
143 constexpr explicit Rotation3d(const Eigen::Vector3d& rvec)
144 : Rotation3d{rvec, units::radian_t{ct_matrix{rvec}.norm()}} {}
145
146 /**
147 * Constructs a Rotation3d from a rotation matrix.
148 *
149 * @param rotationMatrix The rotation matrix.
150 * @throws std::domain_error if the rotation matrix isn't special orthogonal.
151 */
152 constexpr explicit Rotation3d(const Eigen::Matrix3d& rotationMatrix) {
153 auto impl = []<typename Matrix3d>(const Matrix3d& R) -> Quaternion {
154 // Require that the rotation matrix is special orthogonal. This is true if
155 // the matrix is orthogonal (RRᵀ = I) and normalized (determinant is 1).
156 if ((R * R.transpose() - Matrix3d::Identity()).norm() > 1e-9) {
157 throw std::domain_error("Rotation matrix isn't orthogonal");
158 }
159 // HACK: Uses ct_matrix instead of <Eigen/LU> for determinant because
160 // including <Eigen/LU> doubles compilation times on MSVC, even if
161 // this constructor is unused. MSVC's frontend inefficiently parses
162 // large headers; GCC and Clang are largely unaffected.
163 if (gcem::abs(ct_matrix{R}.determinant() - 1.0) > 1e-9) {
164 throw std::domain_error(
165 "Rotation matrix is orthogonal but not special orthogonal");
166 }
167
168 // Turn rotation matrix into a quaternion
169 // https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
170 double trace = R(0, 0) + R(1, 1) + R(2, 2);
171 double w;
172 double x;
173 double y;
174 double z;
175
176 if (trace > 0.0) {
177 double s = 0.5 / gcem::sqrt(trace + 1.0);
178 w = 0.25 / s;
179 x = (R(2, 1) - R(1, 2)) * s;
180 y = (R(0, 2) - R(2, 0)) * s;
181 z = (R(1, 0) - R(0, 1)) * s;
182 } else {
183 if (R(0, 0) > R(1, 1) && R(0, 0) > R(2, 2)) {
184 double s = 2.0 * gcem::sqrt(1.0 + R(0, 0) - R(1, 1) - R(2, 2));
185 w = (R(2, 1) - R(1, 2)) / s;
186 x = 0.25 * s;
187 y = (R(0, 1) + R(1, 0)) / s;
188 z = (R(0, 2) + R(2, 0)) / s;
189 } else if (R(1, 1) > R(2, 2)) {
190 double s = 2.0 * gcem::sqrt(1.0 + R(1, 1) - R(0, 0) - R(2, 2));
191 w = (R(0, 2) - R(2, 0)) / s;
192 x = (R(0, 1) + R(1, 0)) / s;
193 y = 0.25 * s;
194 z = (R(1, 2) + R(2, 1)) / s;
195 } else {
196 double s = 2.0 * gcem::sqrt(1.0 + R(2, 2) - R(0, 0) - R(1, 1));
197 w = (R(1, 0) - R(0, 1)) / s;
198 x = (R(0, 2) + R(2, 0)) / s;
199 y = (R(1, 2) + R(2, 1)) / s;
200 z = 0.25 * s;
201 }
202 }
203
204 return Quaternion{w, x, y, z};
205 };
206
207 if (std::is_constant_evaluated()) {
208 m_q = impl(ct_matrix3d{rotationMatrix});
209 } else {
210 m_q = impl(rotationMatrix);
211 }
212 }
213
214 /**
215 * Constructs a Rotation3d that rotates the initial vector onto the final
216 * vector.
217 *
218 * This is useful for turning a 3D vector (final) into an orientation relative
219 * to a coordinate system vector (initial).
220 *
221 * @param initial The initial vector.
222 * @param final The final vector.
223 */
224 constexpr Rotation3d(const Eigen::Vector3d& initial,
225 const Eigen::Vector3d& final) {
226 double dot = ct_matrix{initial}.dot(ct_matrix{final});
227 double normProduct = ct_matrix{initial}.norm() * ct_matrix{final}.norm();
228 double dotNorm = dot / normProduct;
229
230 if (dotNorm > 1.0 - 1E-9) {
231 // If the dot product is 1, the two vectors point in the same direction so
232 // there's no rotation. The default initialization of m_q will work.
233 return;
234 } else if (dotNorm < -1.0 + 1E-9) {
235 // If the dot product is -1, the two vectors are antiparallel, so a 180°
236 // rotation is required. Any other vector can be used to generate an
237 // orthogonal one.
238
239 double x = gcem::abs(initial(0));
240 double y = gcem::abs(initial(1));
241 double z = gcem::abs(initial(2));
242
243 // Find vector that is most orthogonal to initial vector
244 Eigen::Vector3d other;
245 if (x < y) {
246 if (x < z) {
247 // Use x-axis
248 other = Eigen::Vector3d{{1, 0, 0}};
249 } else {
250 // Use z-axis
251 other = Eigen::Vector3d{{0, 0, 1}};
252 }
253 } else {
254 if (y < z) {
255 // Use y-axis
256 other = Eigen::Vector3d{{0, 1, 0}};
257 } else {
258 // Use z-axis
259 other = Eigen::Vector3d{{0, 0, 1}};
260 }
261 }
262
263 auto axis = ct_matrix{initial}.cross(ct_matrix{other});
264
265 double axisNorm = axis.norm();
266 m_q = Quaternion{0.0, axis(0) / axisNorm, axis(1) / axisNorm,
267 axis(2) / axisNorm};
268 } else {
269 auto axis = ct_matrix{initial}.cross(final);
270
271 // https://stackoverflow.com/a/11741520
272 m_q =
273 Quaternion{normProduct + dot, axis(0), axis(1), axis(2)}.Normalize();
274 }
275 }
276
277 /**
278 * Constructs a 3D rotation from a 2D rotation in the X-Y plane.
279 *
280 * @param rotation The 2D rotation.
281 * @see Pose3d(Pose2d)
282 * @see Transform3d(Transform2d)
283 */
284 constexpr explicit Rotation3d(const Rotation2d& rotation)
285 : Rotation3d{0_rad, 0_rad, rotation.Radians()} {}
286
287 /**
288 * Adds two rotations together. The other rotation is applied extrinsically to
289 * this rotation, which is equivalent to this rotation being applied
290 * intrinsically to the other rotation. See the class comment for definitions
291 * of extrinsic and intrinsic rotations.
292 *
293 * Note that `a - b + b` always equals `a`, but `b + (a - b)`
294 * sometimes doesn't. To apply a rotation offset, use either `offset =
295 * -measurement + actual; newAngle = angle + offset;` or `offset = actual -
296 * measurement; newAngle = offset + angle;`, depending on how the corrected
297 * angle needs to change as the input angle changes.
298 *
299 * @param other The rotation to add (applied extrinsically).
300 *
301 * @return The sum of the two rotations.
302 */
303 constexpr Rotation3d operator+(const Rotation3d& other) const {
304 return RotateBy(other);
305 }
306
307 /**
308 * Subtracts the new rotation from the current rotation and returns the new
309 * rotation. The new rotation is from the perspective of the other rotation
310 * (like Pose3d::operator-), so it needs to be applied intrinsically. See the
311 * class comment for definitions of extrinsic and intrinsic rotations.
312 *
313 * Note that `a - b + b` always equals `a`, but `b + (a - b)` sometimes
314 * doesn't. To apply a rotation offset, use either `offset = -measurement +
315 * actual; newAngle = angle + offset;` or `offset = actual - measurement;
316 * newAngle = offset + angle;`, depending on how the corrected angle needs to
317 * change as the input angle changes.
318 *
319 * @param other The rotation to subtract.
320 *
321 * @return The difference between the two rotations, from the perspective of
322 * the other rotation.
323 */
324 constexpr Rotation3d operator-(const Rotation3d& other) const {
325 return *this + -other;
326 }
327
328 /**
329 * Takes the inverse of the current rotation.
330 *
331 * @return The inverse of the current rotation.
332 */
333 constexpr Rotation3d operator-() const { return Rotation3d{m_q.Inverse()}; }
334
335 /**
336 * Multiplies the current rotation by a scalar.
337 *
338 * @param scalar The scalar.
339 *
340 * @return The new scaled Rotation3d.
341 */
342 constexpr Rotation3d operator*(double scalar) const {
343 // https://en.wikipedia.org/wiki/Slerp#Quaternion_Slerp
344 if (m_q.W() >= 0.0) {
345 return Rotation3d{Eigen::Vector3d{{m_q.X(), m_q.Y(), m_q.Z()}},
346 2.0 * units::radian_t{scalar * gcem::acos(m_q.W())}};
347 } else {
348 return Rotation3d{Eigen::Vector3d{{-m_q.X(), -m_q.Y(), -m_q.Z()}},
349 2.0 * units::radian_t{scalar * gcem::acos(-m_q.W())}};
350 }
351 }
352
353 /**
354 * Divides the current rotation by a scalar.
355 *
356 * @param scalar The scalar.
357 *
358 * @return The new scaled Rotation3d.
359 */
360 constexpr Rotation3d operator/(double scalar) const {
361 return *this * (1.0 / scalar);
362 }
363
364 /**
365 * Checks equality between this Rotation3d and another object.
366 */
367 constexpr bool operator==(const Rotation3d& other) const {
368 return gcem::abs(gcem::abs(m_q.Dot(other.m_q)) -
369 m_q.Norm() * other.m_q.Norm()) < 1e-9;
370 }
371
372 /**
373 * Adds the new rotation to the current rotation. The other rotation is
374 * applied extrinsically, which means that it rotates around the global axes.
375 * For example, Rotation3d{90_deg, 0, 0}.RotateBy(Rotation3d{0, 45_deg, 0})
376 * rotates by 90 degrees around the +X axis and then by 45 degrees around the
377 * global +Y axis. (This is equivalent to Rotation3d{90_deg, 45_deg, 0})
378 *
379 * @param other The extrinsic rotation to rotate by.
380 *
381 * @return The new rotated Rotation3d.
382 */
383 constexpr Rotation3d RotateBy(const Rotation3d& other) const {
384 return Rotation3d{other.m_q * m_q};
385 }
386
387 /**
388 * Returns the current rotation relative to the given rotation. Because the
389 * result is in the perspective of the given rotation, it must be applied
390 * intrinsically. See the class comment for definitions of extrinsic and
391 * intrinsic rotations.
392 *
393 * @param other The rotation describing the orientation of the new coordinate
394 * frame that the current rotation will be converted into.
395 *
396 * @return The current rotation relative to the new orientation of the
397 * coordinate frame.
398 */
399 constexpr Rotation3d RelativeTo(const Rotation3d& other) const {
400 // To apply a quaternion intrinsically, we must right-multiply by that
401 // quaternion. Therefore, "this_q relative to other_q" is the q such that
402 // other_q q = this_q:
403 //
404 // other_q q = this_q
405 // q = other_q⁻¹ this_q
406 return Rotation3d{other.m_q.Inverse() * m_q};
407 }
408
409 /**
410 * Returns the quaternion representation of the Rotation3d.
411 */
412 constexpr const Quaternion& GetQuaternion() const { return m_q; }
413
414 /**
415 * Returns the counterclockwise rotation angle around the X axis (roll).
416 */
417 constexpr units::radian_t X() const {
418 double w = m_q.W();
419 double x = m_q.X();
420 double y = m_q.Y();
421 double z = m_q.Z();
422
423 // wpimath/algorithms.md
424 double cxcy = 1.0 - 2.0 * (x * x + y * y);
425 double sxcy = 2.0 * (w * x + y * z);
426 double cy_sq = cxcy * cxcy + sxcy * sxcy;
427 if (cy_sq > 1e-20) {
428 return units::radian_t{gcem::atan2(sxcy, cxcy)};
429 } else {
430 return 0_rad;
431 }
432 }
433
434 /**
435 * Returns the counterclockwise rotation angle around the Y axis (pitch).
436 */
437 constexpr units::radian_t Y() const {
438 double w = m_q.W();
439 double x = m_q.X();
440 double y = m_q.Y();
441 double z = m_q.Z();
442
443 // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Quaternion_to_Euler_angles_(in_3-2-1_sequence)_conversion
444 double ratio = 2.0 * (w * y - z * x);
445 if (gcem::abs(ratio) >= 1.0) {
446 return units::radian_t{gcem::copysign(std::numbers::pi / 2.0, ratio)};
447 } else {
448 return units::radian_t{gcem::asin(ratio)};
449 }
450 }
451
452 /**
453 * Returns the counterclockwise rotation angle around the Z axis (yaw).
454 */
455 constexpr units::radian_t Z() const {
456 double w = m_q.W();
457 double x = m_q.X();
458 double y = m_q.Y();
459 double z = m_q.Z();
460
461 // wpimath/algorithms.md
462 double cycz = 1.0 - 2.0 * (y * y + z * z);
463 double cysz = 2.0 * (w * z + x * y);
464 double cy_sq = cycz * cycz + cysz * cysz;
465 if (cy_sq > 1e-20) {
466 return units::radian_t{gcem::atan2(cysz, cycz)};
467 } else {
468 return units::radian_t{gcem::atan2(2.0 * w * z, w * w - z * z)};
469 }
470 }
471
472 /**
473 * Returns the axis in the axis-angle representation of this rotation.
474 */
475 constexpr Eigen::Vector3d Axis() const {
476 double norm = gcem::hypot(m_q.X(), m_q.Y(), m_q.Z());
477 if (norm == 0.0) {
478 return Eigen::Vector3d{{0.0, 0.0, 0.0}};
479 } else {
480 return Eigen::Vector3d{{m_q.X() / norm, m_q.Y() / norm, m_q.Z() / norm}};
481 }
482 }
483
484 /**
485 * Returns the angle in the axis-angle representation of this rotation.
486 */
487 constexpr units::radian_t Angle() const {
488 double norm = gcem::hypot(m_q.X(), m_q.Y(), m_q.Z());
489 return units::radian_t{2.0 * gcem::atan2(norm, m_q.W())};
490 }
491
492 /**
493 * Returns rotation matrix representation of this rotation.
494 */
495 constexpr Eigen::Matrix3d ToMatrix() const {
496 double w = m_q.W();
497 double x = m_q.X();
498 double y = m_q.Y();
499 double z = m_q.Z();
500
501 // https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Quaternion-derived_rotation_matrix
502 return Eigen::Matrix3d{{1.0 - 2.0 * (y * y + z * z), 2.0 * (x * y - w * z),
503 2.0 * (x * z + w * y)},
504 {2.0 * (x * y + w * z), 1.0 - 2.0 * (x * x + z * z),
505 2.0 * (y * z - w * x)},
506 {2.0 * (x * z - w * y), 2.0 * (y * z + w * x),
507 1.0 - 2.0 * (x * x + y * y)}};
508 }
509
510 /**
511 * Returns rotation vector representation of this rotation.
512 *
513 * @return Rotation vector representation of this rotation.
514 */
515 constexpr Eigen::Vector3d ToVector() const { return m_q.ToRotationVector(); }
516
517 /**
518 * Returns a Rotation2d representing this Rotation3d projected into the X-Y
519 * plane.
520 */
521 constexpr Rotation2d ToRotation2d() const { return Rotation2d{Z()}; }
522
523 private:
524 Quaternion m_q;
525};
526
528void to_json(wpi::json& json, const Rotation3d& rotation);
529
531void from_json(const wpi::json& json, Rotation3d& rotation);
532
533} // namespace frc
534
535template <>
536constexpr frc::Rotation3d wpi::Lerp(const frc::Rotation3d& startValue,
537 const frc::Rotation3d& endValue, double t) {
538 return (endValue - startValue) * t + startValue;
539}
540
#define WPILIB_DLLEXPORT
Definition SymbolExports.h:36
namespace for Niels Lohmann
Definition json.h:99
Represents a quaternion.
Definition Quaternion.h:19
constexpr Quaternion Normalize() const
Normalizes the quaternion.
Definition Quaternion.h:138
A rotation in a 2D coordinate frame represented by a point on the unit circle (cosine and sine).
Definition Rotation2d.h:31
A rotation in a 3D coordinate frame, represented by a quaternion.
Definition Rotation3d.h:72
constexpr const Quaternion & GetQuaternion() const
Returns the quaternion representation of the Rotation3d.
Definition Rotation3d.h:412
constexpr Rotation3d(const Quaternion &q)
Constructs a Rotation3d from a quaternion.
Definition Rotation3d.h:84
constexpr Rotation3d operator+(const Rotation3d &other) const
Adds two rotations together.
Definition Rotation3d.h:303
constexpr Eigen::Matrix3d ToMatrix() const
Returns rotation matrix representation of this rotation.
Definition Rotation3d.h:495
constexpr units::radian_t Z() const
Returns the counterclockwise rotation angle around the Z axis (yaw).
Definition Rotation3d.h:455
constexpr Rotation3d()=default
Constructs a Rotation3d representing no rotation.
constexpr Rotation3d(const Eigen::Vector3d &initial, const Eigen::Vector3d &final)
Constructs a Rotation3d that rotates the initial vector onto the final vector.
Definition Rotation3d.h:224
constexpr Rotation3d operator/(double scalar) const
Divides the current rotation by a scalar.
Definition Rotation3d.h:360
constexpr Rotation2d ToRotation2d() const
Returns a Rotation2d representing this Rotation3d projected into the X-Y plane.
Definition Rotation3d.h:521
constexpr Rotation3d(const Eigen::Matrix3d &rotationMatrix)
Constructs a Rotation3d from a rotation matrix.
Definition Rotation3d.h:152
constexpr Rotation3d operator*(double scalar) const
Multiplies the current rotation by a scalar.
Definition Rotation3d.h:342
constexpr Rotation3d operator-(const Rotation3d &other) const
Subtracts the new rotation from the current rotation and returns the new rotation.
Definition Rotation3d.h:324
constexpr Eigen::Vector3d Axis() const
Returns the axis in the axis-angle representation of this rotation.
Definition Rotation3d.h:475
constexpr Rotation3d operator-() const
Takes the inverse of the current rotation.
Definition Rotation3d.h:333
constexpr units::radian_t Angle() const
Returns the angle in the axis-angle representation of this rotation.
Definition Rotation3d.h:487
constexpr units::radian_t X() const
Returns the counterclockwise rotation angle around the X axis (roll).
Definition Rotation3d.h:417
constexpr Eigen::Vector3d ToVector() const
Returns rotation vector representation of this rotation.
Definition Rotation3d.h:515
constexpr Rotation3d RotateBy(const Rotation3d &other) const
Adds the new rotation to the current rotation.
Definition Rotation3d.h:383
constexpr Rotation3d(const Eigen::Vector3d &rvec)
Constructs a Rotation3d with the given rotation vector representation.
Definition Rotation3d.h:143
constexpr Rotation3d(const Eigen::Vector3d &axis, units::radian_t angle)
Constructs a Rotation3d with the given axis-angle representation.
Definition Rotation3d.h:123
constexpr units::radian_t Y() const
Returns the counterclockwise rotation angle around the Y axis (pitch).
Definition Rotation3d.h:437
constexpr bool operator==(const Rotation3d &other) const
Checks equality between this Rotation3d and another object.
Definition Rotation3d.h:367
constexpr Rotation3d RelativeTo(const Rotation3d &other) const
Returns the current rotation relative to the given rotation.
Definition Rotation3d.h:399
constexpr Rotation3d(units::radian_t roll, units::radian_t pitch, units::radian_t yaw)
Constructs a Rotation3d from extrinsic roll, pitch, and yaw.
Definition Rotation3d.h:100
constexpr Rotation3d(const Rotation2d &rotation)
Constructs a 3D rotation from a 2D rotation in the X-Y plane.
Definition Rotation3d.h:284
Compile-time wrapper for Eigen::Matrix.
Definition ct_matrix.h:26
constexpr Scalar dot(const ct_matrix< Scalar, RhsRows, RhsCols > &rhs) const
Constexpr version of Eigen's vector dot member function.
Definition ct_matrix.h:262
constexpr Scalar determinant() const
Constexpr version of Eigen's 2x2 matrix determinant member function.
Definition ct_matrix.h:316
constexpr Scalar norm() const
Constexpr version of Eigen's norm member function.
Definition ct_matrix.h:281
constexpr ct_matrix< Scalar, 3, 1 > cross(const ct_matrix< Scalar, 3, 1 > &rhs)
Constexpr version of Eigen's 3D vector cross member function.
Definition ct_matrix.h:303
Definition CAN.h:11
WPILIB_DLLEXPORT void to_json(wpi::json &json, const Rotation3d &rotation)
WPILIB_DLLEXPORT void from_json(const wpi::json &json, Rotation3d &rotation)
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition abs.hpp:40
constexpr return_t< T > asin(const T x) noexcept
Compile-time arcsine function.
Definition asin.hpp:82
constexpr T1 copysign(const T1 x, const T2 y) noexcept
Compile-time copy sign function.
Definition copysign.hpp:41
constexpr common_return_t< T1, T2 > hypot(const T1 x, const T2 y) noexcept
Compile-time Pythagorean addition function.
Definition hypot.hpp:147
constexpr return_t< T > sqrt(const T x) noexcept
Compile-time square-root function.
Definition sqrt.hpp:109
constexpr return_t< T > acos(const T x) noexcept
Compile-time arccosine function.
Definition acos.hpp:84
constexpr common_return_t< T1, T2 > atan2(const T1 y, const T2 x) noexcept
Compile-time two-argument arctangent function.
Definition atan2.hpp:88
constexpr T Lerp(const T &startValue, const T &endValue, double t)
Linearly interpolates between two values.
Definition MathExtras.h:772