WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
Transform3d.hpp
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 <utility>
8
12
13namespace wpi::math {
14
15class Pose3d;
16struct Twist3d;
17
18/**
19 * Represents a transformation for a Pose3d in the pose's frame. Translation is
20 * applied before rotation. (The translation is applied in the pose's original
21 * frame, not the transformed frame.)
22 */
24 public:
25 /**
26 * Constructs the transform that maps the initial pose to the final pose.
27 *
28 * @param initial The initial pose for the transformation.
29 * @param final The final pose for the transformation.
30 */
31 constexpr Transform3d(const Pose3d& initial, const Pose3d& final);
32
33 /**
34 * Constructs a transform with the given translation and rotation components.
35 *
36 * @param translation Translational component of the transform.
37 * @param rotation Rotational component of the transform.
38 */
39 constexpr Transform3d(Translation3d translation, Rotation3d rotation)
40 : m_translation{std::move(translation)},
41 m_rotation{std::move(rotation)} {}
42
43 /**
44 * Constructs a transform with x, y, and z translations instead of a separate
45 * Translation3d.
46 *
47 * @param x The x component of the translational component of the transform.
48 * @param y The y component of the translational component of the transform.
49 * @param z The z component of the translational component of the transform.
50 * @param rotation The rotational component of the transform.
51 */
52 constexpr Transform3d(wpi::units::meter_t x, wpi::units::meter_t y,
53 wpi::units::meter_t z, Rotation3d rotation)
54 : m_translation{x, y, z}, m_rotation{std::move(rotation)} {}
55
56 /**
57 * Constructs a transform with the specified affine transformation matrix.
58 *
59 * @param matrix The affine transformation matrix.
60 * @throws std::domain_error if the affine transformation matrix is invalid.
61 */
62 constexpr explicit Transform3d(const Eigen::Matrix4d& matrix)
63 : m_translation{Eigen::Vector3d{
64 {matrix(0, 3)}, {matrix(1, 3)}, {matrix(2, 3)}}},
65 m_rotation{
66 Eigen::Matrix3d{{matrix(0, 0), matrix(0, 1), matrix(0, 2)},
67 {matrix(1, 0), matrix(1, 1), matrix(1, 2)},
68 {matrix(2, 0), matrix(2, 1), matrix(2, 2)}}} {
69 if (matrix(3, 0) != 0.0 || matrix(3, 1) != 0.0 || matrix(3, 2) != 0.0 ||
70 matrix(3, 3) != 1.0) {
71 throw std::domain_error("Affine transformation matrix is invalid");
72 }
73 }
74
75 /**
76 * Constructs the identity transform -- maps an initial pose to itself.
77 */
78 constexpr Transform3d() = default;
79
80 /**
81 * Constructs a 3D transform from a 2D transform in the X-Y plane.
82 **
83 * @param transform The 2D transform.
84 * @see Rotation3d(Rotation2d)
85 * @see Translation3d(Translation2d)
86 */
87 constexpr explicit Transform3d(const wpi::math::Transform2d& transform)
88 : m_translation{wpi::math::Translation3d{transform.Translation()}},
89 m_rotation{wpi::math::Rotation3d{transform.Rotation()}} {}
90
91 /**
92 * Returns the translation component of the transformation.
93 *
94 * @return Reference to the translational component of the transform.
95 */
96 constexpr const Translation3d& Translation() const { return m_translation; }
97
98 /**
99 * Returns the X component of the transformation's translation.
100 *
101 * @return The x component of the transformation's translation.
102 */
103 constexpr wpi::units::meter_t X() const { return m_translation.X(); }
104
105 /**
106 * Returns the Y component of the transformation's translation.
107 *
108 * @return The y component of the transformation's translation.
109 */
110 constexpr wpi::units::meter_t Y() const { return m_translation.Y(); }
111
112 /**
113 * Returns the Z component of the transformation's translation.
114 *
115 * @return The z component of the transformation's translation.
116 */
117 constexpr wpi::units::meter_t Z() const { return m_translation.Z(); }
118
119 /**
120 * Returns an affine transformation matrix representation of this
121 * transformation.
122 */
123 constexpr Eigen::Matrix4d ToMatrix() const {
124 auto vec = m_translation.ToVector();
125 auto mat = m_rotation.ToMatrix();
126 return Eigen::Matrix4d{{mat(0, 0), mat(0, 1), mat(0, 2), vec(0)},
127 {mat(1, 0), mat(1, 1), mat(1, 2), vec(1)},
128 {mat(2, 0), mat(2, 1), mat(2, 2), vec(2)},
129 {0.0, 0.0, 0.0, 1.0}};
130 }
131
132 /**
133 * Returns the rotational component of the transformation.
134 *
135 * @return Reference to the rotational component of the transform.
136 */
137 constexpr const Rotation3d& Rotation() const { return m_rotation; }
138
139 /**
140 * Returns a Twist3d of the current transform (pose delta). If b is the output
141 * of {@code a.Log()}, then {@code b.Exp()} would yield a.
142 *
143 * @return The twist that maps the current transform.
144 */
145 constexpr Twist3d Log() const;
146
147 /**
148 * Invert the transformation. This is useful for undoing a transformation.
149 *
150 * @return The inverted transformation.
151 */
152 constexpr Transform3d Inverse() const {
153 // We are rotating the difference between the translations
154 // using a clockwise rotation matrix. This transforms the global
155 // delta into a local delta (relative to the initial pose).
156 return Transform3d{(-Translation()).RotateBy(Rotation().Inverse()),
157 Rotation().Inverse()};
158 }
159
160 /**
161 * Multiplies the transform by the scalar.
162 *
163 * @param scalar The scalar.
164 * @return The scaled Transform3d.
165 */
166 constexpr Transform3d operator*(double scalar) const {
167 return Transform3d(m_translation * scalar, m_rotation * scalar);
168 }
169
170 /**
171 * Divides the transform by the scalar.
172 *
173 * @param scalar The scalar.
174 * @return The scaled Transform3d.
175 */
176 constexpr Transform3d operator/(double scalar) const {
177 return *this * (1.0 / scalar);
178 }
179
180 /**
181 * Composes two transformations. The second transform is applied relative to
182 * the orientation of the first.
183 *
184 * @param other The transform to compose with this one.
185 * @return The composition of the two transformations.
186 */
187 constexpr Transform3d operator+(const Transform3d& other) const;
188
189 /**
190 * Checks equality between this Transform3d and another object.
191 */
192 constexpr bool operator==(const Transform3d&) const = default;
193
194 private:
195 Translation3d m_translation;
196 Rotation3d m_rotation;
197};
198
199} // namespace wpi::math
200
204
205namespace wpi::math {
206
207constexpr Transform3d::Transform3d(const Pose3d& initial, const Pose3d& final) {
208 // To transform the global translation delta to be relative to the initial
209 // pose, rotate by the inverse of the initial pose's orientation.
210 m_translation = (final.Translation() - initial.Translation())
211 .RotateBy(initial.Rotation().Inverse());
212
213 m_rotation = final.Rotation().RelativeTo(initial.Rotation());
214}
215
216constexpr Transform3d Transform3d::operator+(const Transform3d& other) const {
217 return Transform3d{Pose3d{}, Pose3d{}.TransformBy(*this).TransformBy(other)};
218}
219
220constexpr Twist3d Transform3d::Log() const {
221 // Implementation from Section 3.2 of https://ethaneade.org/lie.pdf
222
223 auto impl = [this]<typename Matrix3d, typename Vector3d>() -> Twist3d {
224 Vector3d u{{m_translation.X().value(), m_translation.Y().value(),
225 m_translation.Z().value()}};
226 Vector3d rvec = m_rotation.ToVector();
227 Matrix3d omega = detail::RotationVectorToMatrix(rvec);
228 Matrix3d omegaSq = omega * omega;
229 double theta = rvec.norm();
230 double thetaSq = theta * theta;
231
232 double C;
233 if (gcem::abs(theta) < 1E-7) {
234 // Taylor Expansions around θ = 0
235 // A = 1/1! - θ²/3! + θ⁴/5!
236 // B = 1/2! - θ²/4! + θ⁴/6!
237 // C = 1/6 * (1/2 + θ²/5! + θ⁴/7!)
238 // sources:
239 // A:
240 // https://www.wolframalpha.com/input?i2d=true&i=series+expansion+of+Divide%5Bsin%5C%2840%29x%5C%2841%29%2Cx%5D+at+x%3D0
241 // B:
242 // https://www.wolframalpha.com/input?i2d=true&i=series+expansion+of+Divide%5B1-cos%5C%2840%29x%5C%2841%29%2CPower%5Bx%2C2%5D%5D+at+x%3D0
243 // C:
244 // https://www.wolframalpha.com/input?i2d=true&i=series+expansion+of+Divide%5B1-Divide%5BDivide%5Bsin%5C%2840%29x%5C%2841%29%2Cx%5D%2C2Divide%5B1-cos%5C%2840%29x%5C%2841%29%2CPower%5Bx%2C2%5D%5D%5D%2CPower%5Bx%2C2%5D%5D+at+x%3D0
245 C = 1 / 12.0 + thetaSq / 720 + thetaSq * thetaSq / 30240;
246 } else {
247 // A = std::sin(θ)/θ
248 // B = (1 - std::cos(θ)) / θ²
249 // C = (1 - A/(2*B)) / θ²
250 double A = gcem::sin(theta) / theta;
251 double B = (1 - gcem::cos(theta)) / thetaSq;
252 C = (1 - A / (2 * B)) / thetaSq;
253 }
254
255 Matrix3d V_inv = Matrix3d::Identity() - 0.5 * omega + C * omegaSq;
256
257 Vector3d translation_component = V_inv * u;
258
259 return Twist3d{wpi::units::meter_t{translation_component(0)},
260 wpi::units::meter_t{translation_component(1)},
261 wpi::units::meter_t{translation_component(2)},
262 wpi::units::radian_t{rvec(0)},
263 wpi::units::radian_t{rvec(1)},
264 wpi::units::radian_t{rvec(2)}};
265 };
266
267 if (std::is_constant_evaluated()) {
268 return impl.template operator()<ct_matrix3d, ct_vector3d>();
269 }
270 return impl.template operator()<Eigen::Matrix3d, Eigen::Vector3d>();
271}
272
273} // namespace wpi::math
274
#define WPILIB_DLLEXPORT
Definition SymbolExports.hpp:36
Represents a 3D pose containing translational and rotational elements.
Definition Pose3d.hpp:28
constexpr Pose3d TransformBy(const Transform3d &other) const
Transforms the pose by the given transformation and returns the new transformed pose.
Definition Pose3d.hpp:324
constexpr const Translation3d & Translation() const
Returns the underlying translation.
Definition Pose3d.hpp:120
constexpr const Rotation3d & Rotation() const
Returns the underlying rotation.
Definition Pose3d.hpp:148
A rotation in a 3D coordinate frame, represented by a quaternion.
Definition Rotation3d.hpp:69
constexpr Rotation3d Inverse() const
Takes the inverse of the current rotation.
Definition Rotation3d.hpp:290
Represents a transformation for a Pose2d in the pose's frame.
Definition Transform2d.hpp:21
Represents a transformation for a Pose3d in the pose's frame.
Definition Transform3d.hpp:23
constexpr const Rotation3d & Rotation() const
Returns the rotational component of the transformation.
Definition Transform3d.hpp:137
constexpr Transform3d()=default
Constructs the identity transform – maps an initial pose to itself.
constexpr const Translation3d & Translation() const
Returns the translation component of the transformation.
Definition Transform3d.hpp:96
constexpr Transform3d Inverse() const
Invert the transformation.
Definition Transform3d.hpp:152
constexpr Transform3d(const Pose3d &initial, const Pose3d &final)
Constructs the transform that maps the initial pose to the final pose.
Definition Transform3d.hpp:207
constexpr Transform3d operator/(double scalar) const
Divides the transform by the scalar.
Definition Transform3d.hpp:176
constexpr wpi::units::meter_t Z() const
Returns the Z component of the transformation's translation.
Definition Transform3d.hpp:117
constexpr bool operator==(const Transform3d &) const =default
Checks equality between this Transform3d and another object.
constexpr Transform3d(const wpi::math::Transform2d &transform)
Constructs a 3D transform from a 2D transform in the X-Y plane.
Definition Transform3d.hpp:87
constexpr Transform3d(const Eigen::Matrix4d &matrix)
Constructs a transform with the specified affine transformation matrix.
Definition Transform3d.hpp:62
constexpr Twist3d Log() const
Returns a Twist3d of the current transform (pose delta).
Definition Transform3d.hpp:220
constexpr wpi::units::meter_t X() const
Returns the X component of the transformation's translation.
Definition Transform3d.hpp:103
constexpr Transform3d(Translation3d translation, Rotation3d rotation)
Constructs a transform with the given translation and rotation components.
Definition Transform3d.hpp:39
constexpr Transform3d(wpi::units::meter_t x, wpi::units::meter_t y, wpi::units::meter_t z, Rotation3d rotation)
Constructs a transform with x, y, and z translations instead of a separate Translation3d.
Definition Transform3d.hpp:52
constexpr wpi::units::meter_t Y() const
Returns the Y component of the transformation's translation.
Definition Transform3d.hpp:110
constexpr Transform3d operator*(double scalar) const
Multiplies the transform by the scalar.
Definition Transform3d.hpp:166
constexpr Eigen::Matrix4d ToMatrix() const
Returns an affine transformation matrix representation of this transformation.
Definition Transform3d.hpp:123
constexpr Transform3d operator+(const Transform3d &other) const
Composes two transformations.
Definition Transform3d.hpp:216
Represents a translation in 3D space.
Definition Translation3d.hpp:31
Definition variable.hpp:916
constexpr T abs(const T x) noexcept
Compile-time absolute value function.
Definition abs.hpp:40
constexpr return_t< T > cos(const T x) noexcept
Compile-time cosine function.
Definition cos.hpp:83
constexpr return_t< T > sin(const T x) noexcept
Compile-time sine function.
Definition sin.hpp:85
Definition StringMap.hpp:773
Definition RobotBase.hpp:26
constexpr ct_matrix3d RotationVectorToMatrix(const ct_vector3d &rotation)
Definition RotationVectorToMatrix.hpp:13
Definition LinearSystem.hpp:20
ct_vector< double, 3 > ct_vector3d
Definition ct_matrix.hpp:387
ct_matrix< double, 3, 3 > ct_matrix3d
Definition ct_matrix.hpp:385
Definition CvSource.hpp:15
A change in distance along a 3D arc since the last pose update.
Definition Twist3d.hpp:23