TrajoptLib
Library for generating time-optimal trajectories for FRC robots.
Loading...
Searching...
No Matches
rotation2.hpp
1// Copyright (c) TrajoptLib contributors
2
3#pragma once
4
5#include <cmath>
6#include <concepts>
7#include <numbers>
8#include <type_traits>
9#include <utility>
10#include <vector>
11
12#include <sleipnir/autodiff/variable.hpp>
13#include <sleipnir/util/concepts.hpp>
14
15namespace trajopt {
16
19template <typename T>
20class Rotation2 {
21 public:
23 constexpr Rotation2() = default;
24
28 // NOLINTNEXTLINE (google-explicit-constructor)
29 constexpr Rotation2(const T& angle) {
30 using std::cos;
31 using std::sin;
32
33 m_cos = cos(angle);
34 m_sin = sin(angle);
35 }
36
41 constexpr Rotation2(T cos, T sin)
42 requires(!std::same_as<T, double>)
43 : m_cos{std::move(cos)}, m_sin{std::move(sin)} {}
44
50 constexpr Rotation2(double x, double y)
51 requires std::same_as<T, double>
52 {
53 double magnitude = std::hypot(x, y);
54 if (magnitude > 1e-6) {
55 m_cos = x / magnitude;
56 m_sin = y / magnitude;
57 } else {
58 m_cos = 1.0;
59 m_sin = 0.0;
60 }
61 }
62
66 template <typename U>
67 constexpr explicit Rotation2(const Rotation2<U>& other)
68 : m_cos{other.cos()}, m_sin{other.sin()} {}
69
75 constexpr Rotation2<T> operator+(const Rotation2<T>& other) const {
76 return rotate_by(other);
77 }
78
84 constexpr Rotation2<T> operator-(const Rotation2<T>& other) const {
85 return *this + -other;
86 }
87
91 constexpr Rotation2<T> operator-() const {
92 return Rotation2<T>{m_cos, -m_sin};
93 }
94
100 template <typename U>
101 constexpr Rotation2<U> rotate_by(const Rotation2<U>& other) const {
102 using R = decltype(std::declval<T>() + std::declval<U>());
103 return Rotation2<R>{cos() * other.cos() - sin() * other.sin(),
104 cos() * other.sin() + sin() * other.cos()};
105 }
106
110 constexpr T radians() const { return atan2(m_sin, m_cos); }
111
115 constexpr T degrees() const {
116 return atan2(m_sin, m_cos) / std::numbers::pi * 180.0;
117 }
118
122 constexpr const T& cos() const { return m_cos; }
123
127 constexpr const T& sin() const { return m_sin; }
128
129 private:
130 T m_cos{1};
131 T m_sin{0};
132};
133
134using Rotation2d = Rotation2<double>;
135
136template <typename Scalar>
137using Rotation2v = Rotation2<slp::Variable<Scalar>>;
138
139template <typename LHS, typename RHS>
140 requires slp::SleipnirType<LHS> && (!slp::SleipnirType<RHS>)
141auto operator==(const Rotation2<LHS>& lhs, const Rotation2<RHS>& rhs) {
142 using Scalar = typename std::decay_t<LHS>::Scalar;
143
144 std::vector<slp::EqualityConstraints<Scalar>> constraints;
145
146 // Constrain angle equality on manifold.
147 //
148 // Let lhs = <cos(a), sin(a)>.
149 // Let rhs = <cos(b), sin(b)>.
150 //
151 // If the angles are equal, the angle between the unit vectors should be
152 // zero.
153 //
154 // lhs x rhs = ‖lhs‖ ‖rhs‖ sin(angleBetween)
155 // = 1 * 1 * 0
156 // = 0
157 //
158 // NOTE: angleBetween = π rad would be another solution
159 constraints.emplace_back(lhs.cos() * rhs.sin() - lhs.sin() * rhs.cos() ==
160 Scalar(0));
161
162 // Require that lhs and rhs are unit vectors if they contain autodiff
163 // variables, since their values can change.
164 constraints.emplace_back(lhs.cos() * lhs.cos() + lhs.sin() * lhs.sin() ==
165 Scalar(1));
166
167 return slp::EqualityConstraints{constraints};
168}
169
170template <typename LHS, typename RHS>
171 requires(!slp::SleipnirType<LHS>) && slp::SleipnirType<RHS>
172auto operator==(const Rotation2<LHS>& lhs, const Rotation2<RHS>& rhs) {
173 using Scalar = typename std::decay_t<RHS>::Scalar;
174
175 std::vector<slp::EqualityConstraints<Scalar>> constraints;
176
177 // Constrain angle equality on manifold.
178 //
179 // Let lhs = <cos(a), sin(a)>.
180 // Let rhs = <cos(b), sin(b)>.
181 //
182 // If the angles are equal, the angle between the unit vectors should be
183 // zero.
184 //
185 // lhs x rhs = ‖lhs‖ ‖rhs‖ sin(angleBetween)
186 // = 1 * 1 * 0
187 // = 0
188 //
189 // NOTE: angleBetween = π rad would be another solution
190 constraints.emplace_back(lhs.cos() * rhs.sin() - lhs.sin() * rhs.cos() ==
191 Scalar(0));
192
193 // Require that lhs and rhs are unit vectors if they contain autodiff
194 // variables, since their values can change.
195 constraints.emplace_back(rhs.cos() * rhs.cos() + rhs.sin() * rhs.sin() ==
196 Scalar(1));
197
198 return slp::EqualityConstraints{constraints};
199}
200
201template <typename LHS, typename RHS>
202 requires slp::SleipnirType<LHS> && slp::SleipnirType<RHS>
203auto operator==(const Rotation2<LHS>& lhs, const Rotation2<RHS>& rhs) {
204 using Scalar = typename std::decay_t<LHS>::Scalar;
205
206 std::vector<slp::EqualityConstraints<Scalar>> constraints;
207
208 // Constrain angle equality on manifold.
209 //
210 // Let lhs = <cos(a), sin(a)>.
211 // Let rhs = <cos(b), sin(b)>.
212 //
213 // If the angles are equal, the angle between the unit vectors should be
214 // zero.
215 //
216 // lhs x rhs = ‖lhs‖ ‖rhs‖ sin(angleBetween)
217 // = 1 * 1 * 0
218 // = 0
219 //
220 // NOTE: angleBetween = π rad would be another solution
221 constraints.emplace_back(lhs.cos() * rhs.sin() - lhs.sin() * rhs.cos() ==
222 Scalar(0));
223
224 // Require that lhs and rhs are unit vectors if they contain autodiff
225 // variables, since their values can change.
226 constraints.emplace_back(lhs.cos() * lhs.cos() + lhs.sin() * lhs.sin() ==
227 Scalar(1));
228 constraints.emplace_back(rhs.cos() * rhs.cos() + rhs.sin() * rhs.sin() ==
229 Scalar(1));
230
231 return slp::EqualityConstraints{constraints};
232}
233
234inline bool operator==(const Rotation2d& lhs, const Rotation2d& rhs) {
235 return lhs.cos() == rhs.cos() && lhs.sin() == rhs.sin();
236}
237
238} // namespace trajopt
Definition rotation2.hpp:20
constexpr T radians() const
Definition rotation2.hpp:110
constexpr T degrees() const
Definition rotation2.hpp:115
constexpr const T & cos() const
Definition rotation2.hpp:122
constexpr Rotation2< T > operator-() const
Definition rotation2.hpp:91
constexpr Rotation2(double x, double y)
Definition rotation2.hpp:50
constexpr Rotation2< U > rotate_by(const Rotation2< U > &other) const
Definition rotation2.hpp:101
constexpr Rotation2(const Rotation2< U > &other)
Definition rotation2.hpp:67
constexpr Rotation2(const T &angle)
Definition rotation2.hpp:29
constexpr Rotation2(T cos, T sin)
Definition rotation2.hpp:41
constexpr const T & sin() const
Definition rotation2.hpp:127
constexpr Rotation2()=default
Constructs a rotation with a default angle of 0 degrees.
constexpr Rotation2< T > operator-(const Rotation2< T > &other) const
Definition rotation2.hpp:84
constexpr Rotation2< T > operator+(const Rotation2< T > &other) const
Definition rotation2.hpp:75