18 template <
class TScalar>
36 using Tangent = Eigen::Vector<Scalar, kDof>;
37 using Params = Eigen::Vector<Scalar, kNumParams>;
38 using Point = Eigen::Vector<Scalar, kPointDim>;
40 template <
class TCompatibleScalar>
42 ScalarBinaryOpTraits<Scalar, TCompatibleScalar>::ReturnType;
44 template <
class TCompatibleScalar>
46 Eigen::Vector<ScalarReturn<TCompatibleScalar>,
kNumParams>;
48 template <
class TCompatibleScalar>
51 template <
class TCompatibleScalar>
58 return Eigen::Vector<Scalar, 2>(1.0, 0.0);
62 -> sophus::Expected<Success> {
63 static const Scalar kThr = kEpsilon<Scalar>;
64 const Scalar squared_norm = unit_complex.squaredNorm();
66 if (!(abs(squared_norm - 1.0) <= kThr)) {
68 "complex number ({}, {}) is not unit length.\n"
69 "Squared norm: {}, thr: {}",
75 return sophus::Expected<Success>{};
81 TScalar
const k_pi = kPi<TScalar>;
82 return abs(angle - k_pi) / (angle + k_pi) < kEpsilon<TScalar>;
90 return Eigen::Vector<Scalar, 2>(cos(angle[0]), sin(angle[0]));
95 return Eigen::Vector<Scalar, 1>{atan2(unit_complex.y(), unit_complex.x())};
99 -> Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim> {
100 return Eigen::Matrix<Scalar, 2, 2>{
104 static auto vee(Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim>
const& mat)
105 -> Eigen::Matrix<Scalar, kDof, 1> {
106 return Eigen::Matrix<Scalar, kDof, 1>{mat(1, 0)};
112 return Params(unit_complex.x(), -unit_complex.y());
115 template <
class TCompatibleScalar>
118 Eigen::Matrix<TCompatibleScalar, 2, 1>
const& rhs_params)
121 auto const squared_norm = result.squaredNorm();
130 if (squared_norm != 1.0) {
131 auto const scale = 2.0 / (1.0 + squared_norm);
132 return scale * result;
138 template <
class TCompatibleScalar>
140 Params const& unit_complex,
141 Eigen::Matrix<TCompatibleScalar, 2, 1>
const& point)
146 template <
class TCompatibleScalar>
148 Params const& unit_complex,
156 -> Eigen::Vector<Scalar, kAmbientDim> {
161 -> Eigen::Matrix<Scalar, kDof, kDof> {
162 return Eigen::Matrix<Scalar, 1, 1>::Identity();
168 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
169 return Eigen::Matrix<Scalar, 2, 2>{
170 {unit_complex.x(), -unit_complex.y()},
171 {unit_complex.y(), unit_complex.x()}};
175 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
181 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
182 Scalar sin_theta_by_theta;
183 Scalar one_minus_cos_theta_by_theta;
186 if (abs(theta[0]) < kEpsilon<Scalar>) {
187 Scalar theta_sq = theta[0] * theta[0];
188 sin_theta_by_theta =
Scalar(1.) -
Scalar(1. / 6.) * theta_sq;
189 one_minus_cos_theta_by_theta =
190 Scalar(0.5) * theta[0] -
Scalar(1. / 24.) * theta[0] * theta_sq;
192 sin_theta_by_theta = params.y() / theta[0];
193 one_minus_cos_theta_by_theta = (
Scalar(1.) - params.x()) / theta[0];
195 return Eigen::Matrix<Scalar, 2, 2>(
196 {{sin_theta_by_theta, -one_minus_cos_theta_by_theta},
197 {one_minus_cos_theta_by_theta, sin_theta_by_theta}});
201 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
203 Scalar halftheta_by_tan_of_halftheta;
206 if (abs(real_minus_one) < kEpsilon<Scalar>) {
207 halftheta_by_tan_of_halftheta =
210 halftheta_by_tan_of_halftheta = -(halftheta * z.y()) / (real_minus_one);
212 Eigen::Matrix<Scalar, 2, 2> v_inv;
213 v_inv << halftheta_by_tan_of_halftheta, halftheta, -halftheta,
214 halftheta_by_tan_of_halftheta;
219 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
220 return Eigen::Matrix<Scalar, 2, 1>(point[1], -point[0]);
224 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
225 return Eigen::Vector2<Scalar>(point[1], -point[0]);
229 static auto ad(
Tangent const&) -> Eigen::Matrix<Scalar, kDof, kDof> {
230 return Eigen::Matrix<Scalar, 1, 1>::Zero();
234 -> Eigen::Matrix<Scalar, kNumParams, kDof> {
237 return Eigen::Matrix<Scalar, kNumParams, kDof>(
238 -sin(theta[0]), cos(theta[0]));
241 static auto dxExpXAt0() -> Eigen::Matrix<Scalar, kNumParams, kDof> {
242 return Eigen::Matrix<Scalar, kNumParams, kDof>(0.0, 1.0);
246 -> Eigen::Matrix<Scalar, kNumParams, kDof> {
247 return Eigen::Matrix<Scalar, 2, 1>(-point[1], point[0]);
251 -> Eigen::Matrix<Scalar, kNumParams, kDof> {
252 return -Eigen::Matrix<Scalar, 2, 1>(unit_complex[1], -unit_complex[0]);
256 -> Eigen::Matrix<Scalar, kDof, kNumParams> {
257 return Eigen::Matrix<Scalar, 1, 2>(-unit_complex[1], unit_complex[0]);
263 return std::vector<Tangent>({
275 return std::vector<Params>({
284 return std::vector<Params>({
287 2.0 * Params::UnitX(),