19 template <
class TScalar>
37 using Tangent = Eigen::Vector<Scalar, kDof>;
38 using Params = Eigen::Vector<Scalar, kNumParams>;
39 using Point = Eigen::Vector<Scalar, kPointDim>;
41 template <
class TCompatibleScalar>
43 ScalarBinaryOpTraits<Scalar, TCompatibleScalar>::ReturnType;
45 template <
class TCompatibleScalar>
47 Eigen::Vector<ScalarReturn<TCompatibleScalar>,
kNumParams>;
49 template <
class TCompatibleScalar>
52 template <
class TCompatibleScalar>
59 return Eigen::Vector<Scalar, 2>(1.0, 0.0);
63 -> sophus::Expected<Success> {
64 static const Scalar kThr = kEpsilon<Scalar> * kEpsilon<Scalar>;
65 const Scalar squared_norm = non_zero_complex.squaredNorm();
67 if (!(squared_norm > kThr || squared_norm < 1.0 / kThr)) {
69 "complex number ({}, {}) is too large or too small.\n"
70 "Squared norm: {}, thr: {}",
76 return sophus::Expected<Success>{};
81 non_zero_complex.normalized());
91 Scalar const sigma = angle_logscale[1];
94 s =
max(s, kEpsilonPlus<Scalar>);
95 s =
min(s,
Scalar(1.) / kEpsilonPlus<Scalar>);
96 Eigen::Vector2<Scalar> z =
106 Eigen::Vector<Scalar, 1>{atan2(complex.y(), complex.x())}[0];
107 theta_sigma[1] =
log(complex.norm());
112 -> Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim> {
113 return Eigen::Matrix<Scalar, 2, 2>{
114 {angle_logscale[1], -angle_logscale[0]},
115 {angle_logscale[0], angle_logscale[1]}};
118 static auto vee(Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim>
const& mat)
119 -> Eigen::Matrix<Scalar, kDof, 1> {
120 return Eigen::Matrix<Scalar, kDof, 1>{mat(1, 0), mat(0, 0)};
126 Scalar squared_scale = non_zero_complex.squaredNorm();
128 non_zero_complex.x() / squared_scale,
129 -non_zero_complex.y() / squared_scale);
132 template <
class TCompatibleScalar>
135 Eigen::Vector<TCompatibleScalar, kNumParams>
const& rhs_params)
139 ScalarReturn const squared_scale = result.squaredNorm();
141 if (squared_scale < kEpsilon<Scalar> * kEpsilon<Scalar>) {
144 result *= kEpsilonPlus<ScalarReturn>;
147 Scalar(1.) / (kEpsilon<ScalarReturn> * kEpsilon<ScalarReturn>)) {
150 result /= kEpsilonPlus<ScalarReturn>;
156 template <
class TCompatibleScalar>
158 Params const& non_zero_complex,
159 Eigen::Vector<TCompatibleScalar, kPointDim>
const& point)
161 return matrix(non_zero_complex) * point;
165 -> Eigen::Vector<Scalar, kAmbientDim> {
169 template <
class TCompatibleScalar>
171 Params const& non_zero_complex,
176 direction_vector.params());
180 -> Eigen::Matrix<Scalar, kDof, kDof> {
181 return Eigen::Matrix<Scalar, 2, 2>::Identity();
187 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
188 return Eigen::Matrix<Scalar, 2, 2>{
189 {
Scalar(non_zero_complex.x()),
Scalar(-non_zero_complex.y())},
190 {
Scalar(non_zero_complex.y()),
Scalar(non_zero_complex.x())}};
194 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
200 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
201 return details::calcW<Scalar, 2>(
208 Params const& non_zero_complex,
Tangent const& angle_logscale)
209 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
210 return details::calcWInv<Scalar, 2>(
214 non_zero_complex.norm());
218 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
219 return Eigen::Matrix<Scalar, 2, 2>{
220 {point[1], -point[0]}, {-point[0], -point[1]}};
224 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
225 Eigen::Matrix<Scalar, 2, 2> mat;
226 mat.col(0) = Eigen::Vector2<Scalar>(point[1], -point[0]);
234 -> Eigen::Matrix<Scalar, kDof, kDof> {
235 return Eigen::Matrix<Scalar, 2, 2>::Zero();
239 -> Eigen::Matrix<Scalar, kNumParams, kDof> {
243 Scalar const theta = a[0];
244 Scalar const sigma = a[1];
246 Eigen::Matrix<Scalar, 2, 2> d;
248 d << -sin(theta), cos(theta),
249 cos(theta), sin(theta);
251 return d *
exp(sigma);
254 static auto dxExpXAt0() -> Eigen::Matrix<Scalar, kNumParams, kDof> {
255 Eigen::Matrix<Scalar, 2, 2> d;
266 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
267 Eigen::Matrix<Scalar, 2, 2> d;
268 d << Rotation2Impl<Scalar>::dxExpXTimesPointAt0(point), point;
273 -> Eigen::Matrix<Scalar, kNumParams, kDof> {
274 Eigen::Matrix<Scalar, 2, 2> d;
276 d << -non_zero_complex.y(), non_zero_complex.x(),
277 non_zero_complex.x(), non_zero_complex.y();
283 -> Eigen::Matrix<Scalar, kDof, kNumParams> {
284 Eigen::Matrix<Scalar, 2, 2> d;
285 const Scalar norm_sq_inv =
Scalar(1.) / non_zero_complex.squaredNorm();
287 d << -non_zero_complex.y(), non_zero_complex.x(),
288 non_zero_complex.x(), non_zero_complex.y();
290 return d * norm_sq_inv;
296 return std::vector<Tangent>({
302 Tangent{0.5 * kPi<Scalar>, 0.9},
303 Tangent{0.5 * kPi<Scalar> + 0.00001, 0.2},
308 return std::vector<Params>({
320 return std::vector<Params>({