Valkyrie 2026
Loading...
Searching...
No Matches
Pose.h
1#pragma once
2
3#include <algorithm>
4#include <initializer_list>
5#include <limits>
6
7#include <frc/geometry/Translation2d.h>
8#include <units/angle.h>
9#include <units/angular_velocity.h>
10#include <units/base.h>
11#include <units/dimensionless.h>
12#include <units/length.h>
13#include <units/math.h>
14#include <units/time.h>
15#include <units/velocity.h>
16
17#include "frc/geometry/Pose2d.h"
18#include "frc/geometry/Pose3d.h"
19#include "frc/geometry/Rotation2d.h"
20#include "frc/geometry/Transform2d.h"
21#include "frc/geometry/Transform3d.h"
22#include "frc/geometry/Translation3d.h"
24
25namespace valor {
26namespace geometry {
27
28// Forward declarations
29class Translation2d;
30class Translation3d;
31class Rotation2d;
32class Rotation3d;
33class Pose2d;
34class Pose3d;
35class Transform2d;
36class Transform3d;
37
38// ============================================================
39// Translation2d
40// ============================================================
41
45class Translation2d : public EigenUnit::NamedPhysicalVector<Translation2d, EigenUnit::VectorN<units::meter, 2>> {
46 public:
47 using NamedPhysicalVector::NamedPhysicalVector;
48
49 Translation2d(const EigenUnit::UnitVector<units::meter, units::meter>& b) : NamedPhysicalVector(b) {}
50
55 explicit Translation2d(frc::Translation2d frcTranslation) : Translation2d(frcTranslation.X(), frcTranslation.Y()) {};
56
61 explicit Translation2d(frc::Translation3d frcTranslation) : Translation2d(frcTranslation.X(), frcTranslation.Y()) {};
62
67 explicit Translation2d(const Translation3d& t);
68
74 Translation2d RotateBy(const Rotation2d& rot) const;
75
81 units::meter_t Distance(const Translation2d& other) const { return (*this - other).Norm(); }
82};
83
84// ============================================================
85// Rotation2d
86// ============================================================
87
91class Rotation2d
92 : public EigenUnit::NamedPhysicalMatrix<Rotation2d, EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 2>,
93 EigenUnit::VectorN<units::dimensionless::scalar, 2>>> {
94 using BaseMatrix =
95 EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 2>, EigenUnit::VectorN<units::dimensionless::scalar, 2>>;
96
97 public:
98 using NamedPhysicalMatrix::NamedPhysicalMatrix;
99
100 Rotation2d(const BaseMatrix& b) : NamedPhysicalMatrix(b) {}
101
116 template <class AngleUnit, std::enable_if_t<units::traits::is_angle_unit<AngleUnit>::value, int> = 0>
117 Rotation2d(units::unit_t<AngleUnit> theta) : Rotation2d(units::radian_t{theta}) {}
118
119 Rotation2d(units::radian_t theta)
120 : NamedPhysicalMatrix(BaseMatrix::FromRows(
121 EigenUnit::VectorN<units::dimensionless::scalar, 2>{units::math::cos(theta), -units::math::sin(theta)},
122 EigenUnit::VectorN<units::dimensionless::scalar, 2>{units::math::sin(theta), units::math::cos(theta)})) {}
123
128 explicit Rotation2d(frc::Rotation2d frcRotation) : Rotation2d(frcRotation.Radians()) {};
129
135 explicit Rotation2d(frc::Rotation3d frcRotation) : Rotation2d(frcRotation.Z()) {};
136
141 explicit Rotation2d(const Rotation3d& rot);
142
144 units::radian_t GetAngle() const { return units::math::atan2(Get<1, 0>(), Get<0, 0>()); }
145
147 Rotation2d operator-() const { return Rotation2d(-GetAngle()); }
148
150 Rotation2d operator*(double scalar) const { return Rotation2d(GetAngle() * scalar); }
151
153 static Rotation2d Exp(units::radian_t theta) { return Rotation2d(theta); }
154
156 units::radian_t Log() const { return GetAngle(); }
157};
158
159// ============================================================
160// HomogeneousVector2d / Pose2d internals
161// ============================================================
162
166class HomogeneousVector2d : public EigenUnit::UnitVector<units::meter, units::meter, units::dimensionless::scalar> {
167 public:
168 using UnitVector::UnitVector;
169};
170
171// ============================================================
172// Transform2d
173// ============================================================
174
181class Transform2d
182 : public EigenUnit::NamedPhysicalMatrix<Transform2d, EigenUnit::PhysicalMatrix<HomogeneousVector2d, HomogeneousVector2d>> {
183 using BaseMatrix = EigenUnit::PhysicalMatrix<HomogeneousVector2d, HomogeneousVector2d>;
184
185 public:
186 using NamedPhysicalMatrix::NamedPhysicalMatrix;
187
188 Transform2d(const BaseMatrix& b) : NamedPhysicalMatrix(b) {}
189
196 : NamedPhysicalMatrix{
197 BaseMatrix::FromBlocks(
198 rot,
199 EigenUnit::UnitMatrix<std::tuple<units::meter, units::meter>, std::tuple<units::dimensionless::scalar>>::FromCols(
200 trans),
201 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>, std::tuple<units::meter, units::meter>>::Zero(),
202 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>, std::tuple<units::dimensionless::scalar>>::Identity()),
203 } {}
204
210 explicit Transform2d(frc::Translation2d frcTrans, frc::Rotation2d frcRot) : Transform2d(Translation2d(frcTrans), Rotation2d(frcRot)) {}
211
216 explicit Transform2d(frc::Transform2d frcTransform) : Transform2d(frcTransform.Translation(), frcTransform.Rotation()) {};
217
219 static Transform2d Identity() { return Transform2d(Translation2d(0_m, 0_m), Rotation2d(0_rad)); }
220
221 inline Translation2d Translation() const { return this->TopRight<2, 1>().Col<0>(); }
222
223 inline Rotation2d Rotation() const { return this->TopLeft<2, 2>(); }
224
226 Transform2d Inverse() const {
227 // Correct inversion: T^{-1} = [ R^T -R^T * t ]
228 // [ 0 1 ]
229 auto invR = Rotation().Inverse();
230 auto invT = Translation2d(invR * (-Translation()));
231 return Transform2d(invT, invR);
232 }
233
235 Transform2d operator*(double scalar) const { return Transform2d(Translation() * scalar, Rotation2d(Rotation().GetAngle() * scalar)); }
236};
237
238// ============================================================
239// Pose2d
240// ============================================================
241
245class Pose2d : public EigenUnit::NamedPhysicalMatrix<Pose2d, EigenUnit::PhysicalMatrix<HomogeneousVector2d, HomogeneousVector2d>> {
246 using BaseMatrix = EigenUnit::PhysicalMatrix<HomogeneousVector2d, HomogeneousVector2d>;
247
248 public:
249 using NamedPhysicalMatrix::NamedPhysicalMatrix;
250
251 Pose2d(const BaseMatrix& b) : NamedPhysicalMatrix(b) {}
252
262 : NamedPhysicalMatrix{
263 BaseMatrix::FromBlocks(
264 rot,
265 EigenUnit::UnitMatrix<std::tuple<units::meter, units::meter>, std::tuple<units::dimensionless::scalar>>::FromCols(
266 trans),
267 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>, std::tuple<units::meter, units::meter>>::Zero(),
268 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>, std::tuple<units::dimensionless::scalar>>::Identity()),
269 } {}
270
276 explicit Pose2d(frc::Translation2d frcTrans, frc::Rotation2d frcRot) : Pose2d(Translation2d(frcTrans), Rotation2d(frcRot)) {};
277
282 explicit Pose2d(frc::Pose2d frcPose) : Pose2d(frcPose.Translation(), frcPose.Rotation()) {};
283
289 explicit Pose2d(frc::Pose3d frcPose) : Pose2d(Translation2d(frcPose.Translation()), Rotation2d(frcPose.Rotation())) {};
290
295 explicit Pose2d(const Pose3d& pose);
296
297 inline Translation2d Translation() const { return this->TopRight<2, 1>().Col<0>(); }
298
299 inline Rotation2d Rotation() const { return this->TopLeft<2, 2>(); }
300
301 inline units::meter_t X() const { return Translation().X(); }
302
303 inline units::meter_t Y() const { return Translation().Y(); }
304
310 inline Pose2d TransformBy(const Transform2d& transform) const { return Pose2d((*this) * transform); }
311
317 inline Pose2d RelativeTo(const Pose2d& other) const { return Pose2d(other.Inverse() * (*this)); }
318
324 Pose2d RotateBy(const Rotation2d& rot) const { return Pose2d(Translation().RotateBy(rot), Rotation2d(rot * Rotation())); }
325
332 Pose2d RotateAround(const Translation2d& point, const Rotation2d& rot) const {
333 Translation2d newTrans = point + Translation2d(rot * (Translation() - point));
334 return Pose2d(newTrans, Rotation2d(rot * Rotation()));
335 }
336
342 Pose2d Nearest(std::initializer_list<Pose2d> poses) const {
343 Pose2d best = *poses.begin();
344 units::meter_t bestDist = Translation().Distance(best.Translation());
345 for (const valor::geometry::Pose2d& p : poses) {
346 units::meter_t d = Translation().Distance(p.Translation());
347 if (d < bestDist) {
348 bestDist = d;
349 best = p;
350 }
351 }
352 return best;
353 }
354
356 Pose2d operator+(const Transform2d& transform) const { return TransformBy(transform); }
357
359 Transform2d operator-(const Pose2d& other) const {
360 Pose2d rel = RelativeTo(other);
361 return Transform2d(rel.Translation(), rel.Rotation());
362 }
363
365 Pose2d operator*(double scalar) const { return Pose2d(Translation() * scalar, Rotation2d(Rotation().GetAngle() * scalar)); }
366
368 Pose2d operator/(double scalar) const { return (*this) * (1.0 / scalar); }
369
371
373 static Pose2d Exp(Twist2d twist) {
374 units::radian_t theta = twist.Get<2>();
375 EigenUnit::UnitVector<units::meter, units::meter> linearDisplacement = twist.Head<2>();
376
377 if (units::math::abs(theta) < 1e-9_rad) {
378 return {Translation2d(linearDisplacement), Rotation2d(0_rad)};
379 }
380
381 using VMatrix = EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::meter, 2>, EigenUnit::VectorN<units::meter, 2>>;
382
383 units::scalar_t s_over_t = units::math::sin(theta) * 1_rad / theta;
384 units::scalar_t c_over_t = (units::scalar_t{1.0} - units::math::cos(theta)) * 1_rad / theta;
385
386 VMatrix V = VMatrix::FromElems(s_over_t, -c_over_t, c_over_t, s_over_t);
387
388 return {Translation2d(V * linearDisplacement), Rotation2d::Exp(theta)};
389 }
390
392 Twist2d Log() const {
393 units::radian_t theta = Rotation().GetAngle();
394
395 if (units::math::abs(theta) < 1e-9_rad) {
396 Translation2d t = Translation();
397 return {t.X(), t.Y(), 0_rad};
398 }
399
400 using VInvMatrix = EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::meter, 2>, EigenUnit::VectorN<units::meter, 2>>;
401
402 units::scalar_t a = (theta * units::math::sin(theta)) / (2.0_rad * (units::scalar_t{1.0} - units::math::cos(theta)));
403 units::scalar_t b = theta / 2.0_rad;
404
405 VInvMatrix V_inv = VInvMatrix::FromElems(a, b, -b, a);
406
407 auto trans = V_inv * Translation();
408 return {trans.X(), trans.Y(), theta};
409 }
410};
411
412// ============================================================
413// Translation3d
414// ============================================================
415
419class Translation3d
420 : public EigenUnit::NamedPhysicalVector<Translation3d, EigenUnit::UnitVector<units::meter, units::meter, units::meter>> {
421 public:
422 using NamedPhysicalVector::NamedPhysicalVector;
423
424 Translation3d(const EigenUnit::UnitVector<units::meter, units::meter, units::meter>& b) : NamedPhysicalVector(b) {}
425
430 explicit Translation3d(const Translation2d& t) : Translation3d(t.X(), t.Y(), 0_m) {}
431
438 Translation3d(units::meter_t distance, const Rotation3d& direction);
439
444 explicit Translation3d(frc::Translation3d frcTrans) : Translation3d(frcTrans.X(), frcTrans.Y(), frcTrans.Z()) {};
445
450 explicit Translation3d(frc::Translation2d frcTrans) : Translation3d(frcTrans.X(), frcTrans.Y(), 0_m) {};
451
457
463 Translation3d RotateBy(const Rotation3d& rot) const;
464
470 units::meter_t Distance(const Translation3d& other) const { return (*this - other).Norm(); }
471
473 Translation3d operator*(double scalar) const {
475 }
476
478 Translation3d operator/(double scalar) const {
480 }
481};
482
483// ============================================================
484// Rotation3d
485// ============================================================
486
490class Rotation3d
491 : public EigenUnit::NamedPhysicalMatrix<Rotation3d, EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 3>,
492 EigenUnit::VectorN<units::dimensionless::scalar, 3>>> {
493 using BaseMatrix =
494 EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 3>, EigenUnit::VectorN<units::dimensionless::scalar, 3>>;
495
496 public:
497 using NamedPhysicalMatrix::NamedPhysicalMatrix;
498
499 Rotation3d(const BaseMatrix& b) : NamedPhysicalMatrix(b) {}
500
501 Rotation3d(units::radian_t pitch, units::radian_t roll, units::radian_t yaw)
502 : Rotation3d{
503 BaseMatrix::FromRows(
504 EigenUnit::VectorN<units::dimensionless::scalar, 3>{units::math::cos(pitch), 0, units::math::sin(pitch)},
505 EigenUnit::VectorN<units::dimensionless::scalar, 3>{0, 1, 0},
506 EigenUnit::VectorN<units::dimensionless::scalar, 3>{-units::math::sin(pitch), 0, units::math::cos(pitch)}),
507 BaseMatrix::FromRows(
508 EigenUnit::VectorN<units::dimensionless::scalar, 3>{1, 0, 0},
509 EigenUnit::VectorN<units::dimensionless::scalar, 3>{0, units::math::cos(roll), -units::math::sin(roll)},
510 EigenUnit::VectorN<units::dimensionless::scalar, 3>{0, units::math::sin(roll), units::math::cos(roll)}),
511 BaseMatrix::FromRows(EigenUnit::VectorN<units::dimensionless::scalar, 3>{units::math::cos(yaw), -units::math::sin(yaw), 0},
512 EigenUnit::VectorN<units::dimensionless::scalar, 3>{units::math::sin(yaw), units::math::cos(yaw), 0},
513 EigenUnit::VectorN<units::dimensionless::scalar, 3>{0, 0, 1}),
514 } {}
515
520 explicit Rotation3d(const Rotation2d& rot) : Rotation3d(0_rad, 0_rad, rot.GetAngle()) {}
521
531 explicit Rotation3d(frc::Rotation3d frcRot) : Rotation3d(frcRot.Y(), frcRot.X(), frcRot.Z()) {};
532
538 explicit Rotation3d(frc::Rotation2d frcRot) : Rotation3d(0_rad, 0_rad, frcRot.Radians()) {};
539
541 Rotation3d operator*(double scalar) const { return Rotation3d::Exp(Log() * scalar); }
542
544 static Rotation3d Exp(EigenUnit::VectorN<units::radian, 3> w) {
545 units::radian_t theta = w.Norm();
546 if (theta < 1e-9_rad) {
547 return Identity();
548 }
549 EigenUnit::VectorN<units::dimensionless::scalar, 3> axis = w / theta;
550 BaseMatrix K = EigenUnit::VectorN<units::dimensionless::scalar, 3>::Skew(axis);
551 auto R = BaseMatrix::Identity() + units::math::sin(theta) * K + (1.0 - units::math::cos(theta)) * (K * K);
552 return Rotation3d(R);
553 }
554
556 EigenUnit::VectorN<units::radian, 3> Log() const {
557 units::dimensionless::scalar_t cos_theta = (this->Trace() - 1.0) / 2.0;
558 cos_theta = units::dimensionless::scalar_t{std::clamp(cos_theta.value(), -1.0, 1.0)};
559 units::radian_t theta = units::math::acos(cos_theta);
560 if (theta < 1e-9_rad) {
561 return EigenUnit::VectorN<units::radian, 3>::Zero();
562 }
563 BaseMatrix K = ((*this) - this->Transpose()) / (2.0 * units::math::sin(theta));
564 return EigenUnit::VectorN<units::radian, 3>{
565 K.Get<2, 1>() * theta,
566 K.Get<0, 2>() * theta,
567 K.Get<1, 0>() * theta,
568 };
569 }
570
572 Rotation3d Interpolate(const Rotation3d& other, double t) const {
573 return Rotation3d((*this) * Rotation3d::Exp(Rotation3d(other * this->Inverse()).Log() * t));
574 }
575
576 units::radian_t Pitch() const { return units::math::asin(-Get<2, 0>()); }
577
578 units::radian_t Roll() const { return units::math::atan2(Get<2, 1>(), Get<2, 2>()); }
579
580 units::radian_t Yaw() const { return units::math::atan2(Get<1, 0>(), Get<0, 0>()); }
581
582 private:
583 Rotation3d(
584 EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 3>, EigenUnit::VectorN<units::dimensionless::scalar, 3>>
585 p,
586 EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 3>, EigenUnit::VectorN<units::dimensionless::scalar, 3>>
587 r,
588 EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 3>, EigenUnit::VectorN<units::dimensionless::scalar, 3>>
589 y)
590 : NamedPhysicalMatrix{y * p * r}, pitchMatrix(p), rollMatrix(r), yawMatrix(y) {}
591
592 EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::dimensionless::scalar, 3>, EigenUnit::VectorN<units::dimensionless::scalar, 3>>
593 pitchMatrix, rollMatrix, yawMatrix;
594};
595
596inline Translation2d Translation2d::RotateBy(const Rotation2d& rot) const {
597 return rot * (*this);
598}
599
600inline Translation2d::Translation2d(const Translation3d& t) : Translation2d(t.X(), t.Y()) {}
601
602inline Rotation2d::Rotation2d(const Rotation3d& rot) : Rotation2d(rot.Yaw()) {}
603
607class HomogeneousVector3d : public EigenUnit::UnitVector<units::meter, units::meter, units::meter, units::dimensionless::scalar> {
608 public:
609 using UnitVector::UnitVector;
610};
611
612// ============================================================
613// Transform3d
614// ============================================================
615
621class Transform3d
622 : public EigenUnit::NamedPhysicalMatrix<Transform3d, EigenUnit::PhysicalMatrix<HomogeneousVector3d, HomogeneousVector3d>> {
623 using BaseMatrix = EigenUnit::PhysicalMatrix<HomogeneousVector3d, HomogeneousVector3d>;
624
625 public:
626 using NamedPhysicalMatrix::NamedPhysicalMatrix;
627
628 Transform3d(const BaseMatrix& b) : NamedPhysicalMatrix(b) {}
629
636 : NamedPhysicalMatrix{
637 FromBlocks(
638 rot,
639 EigenUnit::UnitMatrix<std::tuple<units::meter, units::meter, units::meter>,
640 std::tuple<units::dimensionless::scalar>>::FromCols(trans),
641 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>,
642 std::tuple<units::meter, units::meter, units::meter>>::Zero(),
643 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>, std::tuple<units::dimensionless::scalar>>::Identity()),
644 } {}
645
650 explicit Transform3d(const Transform2d& t) : Transform3d(Translation3d(t.Translation()), Rotation3d(t.Rotation())) {}
651
657 explicit Transform3d(frc::Translation3d frcTrans, frc::Rotation3d frcRot) : Transform3d(Translation3d(frcTrans), Rotation3d(frcRot)) {};
658
663 explicit Transform3d(frc::Transform3d frcTransform) : Transform3d(frcTransform.Translation(), frcTransform.Rotation()) {};
664
670 explicit Transform3d(frc::Transform2d frcTransform)
671 : Transform3d(Translation3d(frcTransform.Translation()), Rotation3d(frcTransform.Rotation())) {};
672
674 static Transform3d Identity() { return Transform3d(Translation3d(0_m, 0_m, 0_m), Rotation3d(0_rad, 0_rad, 0_rad)); }
675
676 inline Translation3d Translation() const { return this->TopRight<3, 1>().Col<0>(); }
677
678 inline Rotation3d Rotation() const { return this->TopLeft<3, 3>(); }
679
681 Transform3d Inverse() const {
682 Rotation3d invR = Rotation().Inverse();
683 Translation3d invT = invR * (-Translation());
684 return Transform3d(invT, invR);
685 }
686};
687
688// ============================================================
689// Pose3d
690// ============================================================
691
695class Pose3d : public EigenUnit::NamedPhysicalMatrix<Pose3d, EigenUnit::PhysicalMatrix<HomogeneousVector3d, HomogeneousVector3d>> {
696 using BaseMatrix = EigenUnit::PhysicalMatrix<HomogeneousVector3d, HomogeneousVector3d>;
697
698 public:
699 using NamedPhysicalMatrix::NamedPhysicalMatrix;
700
701 Pose3d(const BaseMatrix& b) : NamedPhysicalMatrix(b) {}
702
713 : NamedPhysicalMatrix{
714 FromBlocks(
715 rot,
716 EigenUnit::UnitMatrix<std::tuple<units::meter, units::meter, units::meter>,
717 std::tuple<units::dimensionless::scalar>>::FromCols(trans),
718 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>,
719 std::tuple<units::meter, units::meter, units::meter>>::Zero(),
720 EigenUnit::UnitMatrix<std::tuple<units::dimensionless::scalar>, std::tuple<units::dimensionless::scalar>>::Identity()),
721 } {}
722
727 explicit Pose3d(const Pose2d& pose) : Pose3d(Translation3d(pose.Translation()), Rotation3d(pose.Rotation())) {}
728
734 explicit Pose3d(frc::Translation3d frcTrans, frc::Rotation3d frcRot) : Pose3d(Translation3d(frcTrans), Rotation3d(frcRot)) {};
735
740 explicit Pose3d(frc::Pose3d frcPose) : Pose3d(frcPose.Translation(), frcPose.Rotation()) {};
741
747 explicit Pose3d(frc::Pose2d frcPose) : Pose3d(Translation3d(frcPose.Translation()), Rotation3d(frcPose.Rotation())) {};
748
749 inline Translation3d Translation() const { return this->TopRight<3, 1>().Col<0>(); }
750
751 inline Rotation3d Rotation() const { return this->TopLeft<3, 3>(); }
752
753 inline units::meter_t X() const { return Translation().X(); }
754
755 inline units::meter_t Y() const { return Translation().Y(); }
756
757 inline units::meter_t Z() const { return Translation().Z(); }
758
763 Pose2d ToPose2d() const { return Pose2d(*this); }
764
770 inline Pose3d TransformBy(const Transform3d& transform) const { return Pose3d{(*this) * transform}; }
771
777 inline Pose3d RelativeTo(const Pose3d& other) const { return Pose3d{other.Inverse() * (*this)}; }
778
784 Pose3d RotateBy(const Rotation3d& rot) const { return Pose3d{Translation().RotateBy(rot), Rotation3d(rot * Rotation())}; }
785
792 Pose3d RotateAround(const Translation3d& point, const Rotation3d& rot) const {
793 Translation3d newTrans = point + Translation3d(rot * (Translation() - point));
794 return Pose3d{newTrans, Rotation3d{rot * Rotation()}};
795 }
796
802 Pose3d Nearest(std::initializer_list<Pose3d> poses) const {
803 Pose3d best = *poses.begin();
804 units::meter_t bestDist = Translation().Distance(best.Translation());
805 for (const valor::geometry::Pose3d& p : poses) {
806 units::meter_t d = Translation().Distance(p.Translation());
807 if (d < bestDist) {
808 bestDist = d;
809 best = p;
810 }
811 }
812 return best;
813 }
814
816 Pose3d operator+(const Transform3d& transform) const { return TransformBy(transform); }
817
819 Transform3d operator-(const Pose3d& other) const {
820 Pose3d rel = RelativeTo(other);
821 return Transform3d{rel.Translation(), rel.Rotation()};
822 }
823
825 Pose3d operator*(double scalar) const { return Pose3d(Translation() * scalar, Rotation() * scalar); }
826
828 Pose3d operator/(double scalar) const { return (*this) * (1.0 / scalar); }
829
831
833 static Pose3d Exp(Twist3d twist) {
834 auto w = twist.Tail<3>();
835 units::radian_t theta = w.Norm();
836 auto v = twist.Head<3>();
837
838 if (theta < 1e-9_rad) {
839 return Pose3d{Translation3d(v), Rotation3d::Identity()};
840 }
841
842 double s = units::math::sin(theta).value();
843 double c = units::math::cos(theta).value();
844 double t = theta.value();
845
846 using VMatrix = EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::meter, 3>, EigenUnit::VectorN<units::meter, 3>>;
847 VMatrix K{EigenUnit::VectorN<units::dimensionless::scalar, 3>::Skew(w / theta).Raw()};
848
849 VMatrix V = VMatrix::Identity() + ((1.0 - c) / t) * K + ((t - s) / t) * (K * K);
850
851 return Pose3d{Translation3d(V * v), Rotation3d::Exp(w)};
852 }
853
855 Twist3d Log() const {
856 valor::EigenUnit::VectorN<units::radian, 3> w = Rotation().Log();
857 units::radian_t theta = w.Norm();
858 Translation3d T = Translation();
859
860 if (theta < 1e-9_rad) {
861 return Twist3d{
862 T.X(), T.Y(), T.Z(), 0_rad, 0_rad, 0_rad,
863 };
864 }
865
866 double s = units::math::sin(theta).value();
867 double c = units::math::cos(theta).value();
868 double t = theta.value();
869
870 using VInvMatrix = EigenUnit::PhysicalMatrix<EigenUnit::VectorN<units::meter, 3>, EigenUnit::VectorN<units::meter, 3>>;
871 VInvMatrix K{EigenUnit::VectorN<units::dimensionless::scalar, 3>::Skew(w / theta).Raw()};
872
873 VInvMatrix V_inv = VInvMatrix::Identity() - (t / 2.0) * K + (1.0 - (t * s) / (2.0 * (1.0 - c))) * (K * K);
874
876 return {v.X(), v.Y(), v.Z(), w.X(), w.Y(), w.Z()};
877 }
878};
879
880// ============================================================
881// Deferred Pose2d / Translation3d / Rotation3d method bodies
882// ============================================================
883
884inline Pose2d::Pose2d(const Pose3d& pose) : Pose2d{Translation2d{pose.Translation()}, Rotation2d{pose.Rotation()}} {}
885
886inline Translation3d Translation3d::RotateBy(const Rotation3d& rot) const {
887 return Translation3d{rot * (*this)};
888}
889
890inline Translation3d::Translation3d(units::meter_t distance, const Rotation3d& direction)
891 : Translation3d{
892 distance * units::math::cos(direction.Pitch()) * units::math::cos(direction.Yaw()),
893 distance * units::math::cos(direction.Pitch()) * units::math::sin(direction.Yaw()),
894 distance * units::math::sin(direction.Pitch()),
895 } {}
896
897} // namespace geometry
898} // namespace valor
Provides a unit-safe wrapper for Eigen matrices and vectors.
A vector wrapper that enforces units for each element.
Definition UnitVector.h:22
auto Norm() const
Computes the L2 norm (magnitude). Requires all elements to have the same unit tag.
Definition UnitVector.h:143
constexpr auto Get() const
Get the value of the N-th element with its unit.
Definition UnitVector.h:118
constexpr auto Head() const
Extract the first N elements as a new UnitVector.
Definition UnitVector.h:182
constexpr auto Tail() const
Extract the last N elements as a new UnitVector.
Definition UnitVector.h:193
constexpr auto Y() const
Definition UnitVector.h:438
constexpr const StorageType & Raw() const
Definition UnitVector.h:103
constexpr auto X() const
Definition UnitVector.h:424
constexpr auto Z() const
Definition UnitVector.h:452
Represents a 2D homogeneous transformation vector (x, y, 1).
Definition Pose.h:166
Represents a 3D homogeneous transformation vector (x, y, z, 1).
Definition Pose.h:607
Represents a 2D pose as a 3x3 homogeneous transformation matrix.
Definition Pose.h:245
Pose2d RelativeTo(const Pose2d &other) const
Express this pose relative to another pose.
Definition Pose.h:317
Pose2d(frc::Pose2d frcPose)
Construct a Pose2d from an frc::Pose2d.
Definition Pose.h:282
Pose2d operator*(double scalar) const
Scalar multiplication of both translation and rotation.
Definition Pose.h:365
Pose2d(frc::Translation2d frcTrans, frc::Rotation2d frcRot)
Construct a Pose2d from an frc::Translation2d and frc::Rotation2d.
Definition Pose.h:276
Pose2d RotateAround(const Translation2d &point, const Rotation2d &rot) const
Rotate this pose around an arbitrary point.
Definition Pose.h:332
static Pose2d Exp(Twist2d twist)
Exponential map: se(2) -> SE(2).
Definition Pose.h:373
Transform2d operator-(const Pose2d &other) const
operator- returns the Transform2d mapping other -> this.
Definition Pose.h:359
Pose2d operator/(double scalar) const
Scalar division.
Definition Pose.h:368
Pose2d RotateBy(const Rotation2d &rot) const
Rotate this pose around the global origin.
Definition Pose.h:324
Pose2d operator+(const Transform2d &transform) const
operator+ applies a Transform2d.
Definition Pose.h:356
Pose2d Nearest(std::initializer_list< Pose2d > poses) const
Find the nearest pose from a collection.
Definition Pose.h:342
Pose2d TransformBy(const Transform2d &transform) const
Apply a Transform2d in this pose's frame.
Definition Pose.h:310
Twist2d Log() const
Logarithm map: SE(2) -> se(2).
Definition Pose.h:392
Pose2d(Translation2d trans, Rotation2d rot)
Construct a Pose2d from a translation and rotation.
Definition Pose.h:261
Pose2d(frc::Pose3d frcPose)
Construct a Pose2d from an frc::Pose3d by projecting onto the X-Y plane. Z, pitch,...
Definition Pose.h:289
Represents a 3D pose as a 4x4 homogeneous transformation matrix.
Definition Pose.h:695
Pose3d(frc::Pose3d frcPose)
Construct a Pose3d from an frc::Pose3d.
Definition Pose.h:740
Pose3d RotateAround(const Translation3d &point, const Rotation3d &rot) const
Rotate this pose around an arbitrary point in 3D space.
Definition Pose.h:792
Pose3d operator*(double scalar) const
Scalar multiplication of both translation and rotation.
Definition Pose.h:825
Pose3d(frc::Pose2d frcPose)
Construct a Pose3d from an frc::Pose2d, lifting into 3D. Z is set to zero and pitch and roll are set ...
Definition Pose.h:747
Pose3d(frc::Translation3d frcTrans, frc::Rotation3d frcRot)
Construct a Pose3d from an frc::Translation3d and frc::Rotation3d.
Definition Pose.h:734
static Pose3d Exp(Twist3d twist)
Exponential map: se(3) -> SE(3).
Definition Pose.h:833
Pose3d operator+(const Transform3d &transform) const
operator+ applies a Transform3d.
Definition Pose.h:816
Pose3d(const Pose2d &pose)
Construct a Pose3d from a Pose2d in the X-Y plane.
Definition Pose.h:727
Pose3d TransformBy(const Transform3d &transform) const
Apply a Transform3d in this pose's frame.
Definition Pose.h:770
Pose3d RotateBy(const Rotation3d &rot) const
Rotate this pose around the global origin.
Definition Pose.h:784
Pose3d operator/(double scalar) const
Scalar division.
Definition Pose.h:828
Pose3d(Translation3d trans, Rotation3d rot)
Construct a Pose3d from a translation and rotation.
Definition Pose.h:712
Transform3d operator-(const Pose3d &other) const
operator- returns the Transform3d mapping other -> this.
Definition Pose.h:819
Pose2d ToPose2d() const
Project this pose onto the X-Y plane.
Definition Pose.h:763
Pose3d Nearest(std::initializer_list< Pose3d > poses) const
Find the nearest pose from a collection.
Definition Pose.h:802
Pose3d RelativeTo(const Pose3d &other) const
Express this pose relative to another pose.
Definition Pose.h:777
Twist3d Log() const
Logarithm map: SE(3) -> se(3).
Definition Pose.h:855
Represents a 2D rotation matrix (2x2).
Definition Pose.h:93
Rotation2d operator*(double scalar) const
Scalar multiplication of the angle.
Definition Pose.h:150
units::radian_t GetAngle() const
Get the rotation angle.
Definition Pose.h:144
Rotation2d(units::unit_t< AngleUnit > theta)
Construct a Rotation2d from any angle unit (degrees, radians, etc.).
Definition Pose.h:117
Rotation2d operator-() const
Unary negation — inverse rotation.
Definition Pose.h:147
static Rotation2d Exp(units::radian_t theta)
Exponential map: so(2) -> SO(2).
Definition Pose.h:153
Rotation2d(frc::Rotation2d frcRotation)
Construct a Rotation2d from an frc::Rotation2d.
Definition Pose.h:128
Rotation2d(frc::Rotation3d frcRotation)
Construct a Rotation2d from an frc::Rotation3d by extracting the yaw. Pitch and roll components are d...
Definition Pose.h:135
units::radian_t Log() const
Logarithm map: SO(2) -> so(2).
Definition Pose.h:156
Represents a 3D rotation matrix (3x3).
Definition Pose.h:492
Rotation3d operator*(double scalar) const
Scalar multiplication of the rotation axis-angle.
Definition Pose.h:541
Rotation3d(frc::Rotation2d frcRot)
Construct a Rotation3d from an frc::Rotation2d as a pure yaw rotation. Pitch and roll are set to zero...
Definition Pose.h:538
Rotation3d(const Rotation2d &rot)
Construct a Rotation3d from a Rotation2d (rotation about Z).
Definition Pose.h:520
Rotation3d Interpolate(const Rotation3d &other, double t) const
Spherical Linear Interpolation (SLERP).
Definition Pose.h:572
static Rotation3d Exp(EigenUnit::VectorN< units::radian, 3 > w)
Exponential map: so(3) -> SO(3) using Rodrigues' formula.
Definition Pose.h:544
EigenUnit::VectorN< units::radian, 3 > Log() const
Logarithm map: SO(3) -> so(3).
Definition Pose.h:556
Rotation3d(frc::Rotation3d frcRot)
Construct a Rotation3d from an frc::Rotation3d.
Definition Pose.h:531
Represents a relative 2D transformation (translation + rotation).
Definition Pose.h:182
Transform2d(frc::Transform2d frcTransform)
Construct a Transform2d from an frc::Transform2d.
Definition Pose.h:216
Transform2d(frc::Translation2d frcTrans, frc::Rotation2d frcRot)
Construct a Transform2d from an frc::Translation2d and frc::Rotation2d.
Definition Pose.h:210
static Transform2d Identity()
The identity transform.
Definition Pose.h:219
Transform2d Inverse() const
Invert the transform.
Definition Pose.h:226
Transform2d(Translation2d trans, Rotation2d rot)
Construct a Transform2d from a translation and rotation.
Definition Pose.h:195
Transform2d operator*(double scalar) const
Scalar multiplication of the translation and rotation angle.
Definition Pose.h:235
Represents a relative 3D transformation (translation + rotation).
Definition Pose.h:622
Transform3d(frc::Translation3d frcTrans, frc::Rotation3d frcRot)
Construct a Transform3d from an frc::Translation3d and frc::Rotation3d.
Definition Pose.h:657
Transform3d(const Transform2d &t)
Construct a Transform3d from a Transform2d in the X-Y plane.
Definition Pose.h:650
Transform3d(frc::Transform3d frcTransform)
Construct a Transform3d from an frc::Transform3d.
Definition Pose.h:663
Transform3d(frc::Transform2d frcTransform)
Construct a Transform3d from an frc::Transform2d, lifting into 3D. Z is set to zero and pitch and rol...
Definition Pose.h:670
static Transform3d Identity()
The identity transform.
Definition Pose.h:674
Transform3d Inverse() const
Invert the transform.
Definition Pose.h:681
Transform3d(Translation3d trans, Rotation3d rot)
Construct a Transform3d from a translation and rotation.
Definition Pose.h:635
Represents a 2D translation vector (x, y).
Definition Pose.h:45
Translation2d(frc::Translation3d frcTranslation)
Construct a 2D translation from an frc::Translation3d by dropping Z.
Definition Pose.h:61
units::meter_t Distance(const Translation2d &other) const
Distance from this translation to another.
Definition Pose.h:81
Translation2d RotateBy(const Rotation2d &rot) const
Rotate this translation by a Rotation2d.
Definition Pose.h:596
Translation2d(frc::Translation2d frcTranslation)
Construct a 2D translation from an frc::Translation2d.
Definition Pose.h:55
Represents a 3D translation vector (x, y, z).
Definition Pose.h:420
Translation3d(const Translation2d &t)
Construct a 3D translation from a 2D translation (z = 0).
Definition Pose.h:430
Translation2d ToTranslation2d() const
Project this translation onto the X-Y plane.
Definition Pose.h:456
Translation3d RotateBy(const Rotation3d &rot) const
Rotate this translation by a Rotation3d.
Definition Pose.h:886
Translation3d operator/(double scalar) const
Scalar division.
Definition Pose.h:478
Translation3d(frc::Translation3d frcTrans)
Construct a 3D translation from an frc::Translation3d.
Definition Pose.h:444
units::meter_t Distance(const Translation3d &other) const
Distance from this translation to another.
Definition Pose.h:470
Translation3d(frc::Translation2d frcTrans)
Construct a 3D translation from an frc::Translation2d, setting Z to zero.
Definition Pose.h:450
Translation3d operator*(double scalar) const
Scalar multiplication.
Definition Pose.h:473
Template specializations for std::tuple_size and std::tuple_element to support UnitVector.
Definition Formatters.h:8
Definition UnitMatrix.h:600
Definition UnitVector.h:675