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, 4>(
64 -> sophus::Expected<Success> {
65 static const Scalar kThr = kEpsilon<Scalar> * kEpsilon<Scalar>;
66 const Scalar squared_norm = non_zero_quat.squaredNorm();
68 if (!(squared_norm > kThr || squared_norm < 1.0 / kThr)) {
70 "complex number ({}, {}) is too large or too small.\n"
71 "Squared norm: {}, thr: {}",
77 return sophus::Expected<Success>{};
82 non_zero_quat.normalized());
93 Eigen::Vector3<Scalar>
const vec_omega = omega_logscale.template head<3>();
96 scale =
max(scale, kEpsilonPlus<Scalar>);
97 scale =
min(scale,
Scalar(1.) / kEpsilonPlus<Scalar>);
98 Scalar sqrt_scale = sqrt(scale);
107 Scalar scale = non_zero_quat.squaredNorm();
109 omega_and_logscale.template head<3>() =
111 omega_and_logscale[3] =
log(scale);
112 return omega_and_logscale;
116 -> Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim> {
117 return Eigen::Matrix<Scalar, 3, 3>{
118 {+omega_logscale(3), -omega_logscale(2), +omega_logscale(1)},
119 {+omega_logscale(2), +omega_logscale(3), -omega_logscale(0)},
120 {-omega_logscale(1), +omega_logscale(0), +omega_logscale(3)}};
123 static auto vee(Eigen::Matrix<Scalar, kAmbientDim, kAmbientDim>
const& mat)
124 -> Eigen::Matrix<Scalar, kDof, 1> {
125 return Eigen::Matrix<Scalar, kDof, 1>{
126 mat(2, 1), mat(0, 2), mat(1, 0), mat(0, 0)};
132 Scalar squared_scale = non_zero_quat.norm();
133 return (1.0 / squared_scale) *
137 template <
class TCompatibleScalar>
140 Eigen::Vector<TCompatibleScalar, kNumParams>
const& rhs_params)
145 R
const squared_scale = result.squaredNorm();
147 if (squared_scale < kEpsilon<Scalar> * kEpsilon<Scalar>) {
150 result *= kEpsilonPlus<R>;
152 if (squared_scale >
Scalar(1.) / (kEpsilon<Scalar> * kEpsilon<Scalar>)) {
155 result /= kEpsilonPlus<R>;
161 template <
class TCompatibleScalar>
163 Params const& non_zero_quat,
164 Eigen::Vector<TCompatibleScalar, kPointDim>
const& point)
166 return matrix(non_zero_quat) * point;
169 template <
class TCompatibleScalar>
171 Params const& non_zero_quat,
176 direction_vector.params());
180 -> Eigen::Vector<Scalar, kAmbientDim> {
185 -> Eigen::Matrix<Scalar, kDof, kDof> {
186 Eigen::Matrix<Scalar, kDof, kDof> mat;
188 mat.template topLeftCorner<3, 3>() =
196 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
197 Eigen::Matrix<Scalar, kPointDim, kPointDim> s_r;
199 Scalar const vx_sq = non_zero_quat.x() * non_zero_quat.x();
200 Scalar const vy_sq = non_zero_quat.y() * non_zero_quat.y();
201 Scalar const vz_sq = non_zero_quat.z() * non_zero_quat.z();
202 Scalar const w_sq = non_zero_quat.w() * non_zero_quat.w();
206 Scalar const two_vx_vy = two_vx * non_zero_quat.y();
207 Scalar const two_vx_vz = two_vx * non_zero_quat.z();
208 Scalar const two_vx_w = two_vx * non_zero_quat.w();
209 Scalar const two_vy_vz = two_vy * non_zero_quat.z();
210 Scalar const two_vy_w = two_vy * non_zero_quat.w();
211 Scalar const two_vz_w = two_vz * non_zero_quat.w();
213 s_r(0, 0) = vx_sq - vy_sq - vz_sq + w_sq;
214 s_r(1, 0) = two_vx_vy + two_vz_w;
215 s_r(2, 0) = two_vx_vz - two_vy_w;
217 s_r(0, 1) = two_vx_vy - two_vz_w;
218 s_r(1, 1) = -vx_sq + vy_sq - vz_sq + w_sq;
219 s_r(2, 1) = two_vx_w + two_vy_vz;
221 s_r(0, 2) = two_vx_vz + two_vy_w;
222 s_r(1, 2) = -two_vx_w + two_vy_vz;
223 s_r(2, 2) = -vx_sq - vy_sq + vz_sq + w_sq;
228 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
234 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
235 Eigen::Matrix<Scalar, 3, 1> omega = angle_logscale.template head<3>();
237 Scalar theta = omega.norm();
238 Eigen::Matrix3<Scalar>
const w =
239 details::calcW<Scalar, 3>(mat_omega, theta, angle_logscale[3]);
245 -> Eigen::Matrix<Scalar, kPointDim, kPointDim> {
246 Eigen::Matrix<Scalar, 3, 1> omega = angle_logscale.template head<3>();
248 Scalar theta = omega.norm();
249 return details::calcWInv<Scalar, 3>(
250 mat_omega, theta, angle_logscale[3], non_zero_quat.squaredNorm());
254 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
255 Eigen::Matrix<Scalar, 3, 4> tr_adj;
256 tr_adj.template topLeftCorner<3, 3>() =
259 tr_adj.template topRightCorner<3, 1>() = -point;
264 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
265 Eigen::Matrix<Scalar, 3, 4> tr_ad;
267 tr_ad.col(3) = -point;
273 static auto ad(
Tangent const& tangent) -> Eigen::Matrix<Scalar, kDof, kDof> {
274 Eigen::Matrix<Scalar, kDof, kDof> mat;
276 mat.template topLeftCorner<3, 3>() =
282 -> Eigen::Matrix<Scalar, kNumParams, kDof> {
285 Eigen::Matrix<Scalar, 4, 4> j;
286 Eigen::Vector3<Scalar>
const omega = a.template head<3>();
287 Scalar const sigma = a[3];
293 j.col(3) = a * scale_half;
297 static auto dxExpXAt0() -> Eigen::Matrix<Scalar, kNumParams, kDof> {
298 static Scalar const kH(0.5);
299 return kH * Eigen::Matrix<Scalar, 4, 4>::Identity();
303 -> Eigen::Matrix<Scalar, kPointDim, kDof> {
304 Eigen::Matrix<Scalar, 3, 4> j;
305 j << Rotation3Impl<Scalar>::hat(-point), point;
310 -> Eigen::Matrix<Scalar, kNumParams, kDof> {
311 Eigen::Matrix<Scalar, 4, 4> j;
312 j.col(3) = non_zero_quat *
Scalar(0.5);
336 -> Eigen::Matrix<Scalar, kDof, kNumParams> {
337 Eigen::Matrix<Scalar, 4, 4> j;
339 j << q.w(), q.z(), -q.y(), -q.x(),
340 -q.z(), q.w(), q.x(), -q.y(),
341 q.y(), -q.x(), q.w(), -q.z(),
342 q.x(), q.y(), q.z(), q.w();
351 return std::vector<Tangent>({
362 Scalar(0.5 * kPi<Scalar> + 0.00001),
368 return std::vector<Params>({
382 {
Scalar(0.5 * kPi<Scalar> + 0.00001),
390 return std::vector<Params>({