10 #ifndef CTRL_UTILS_EUCLIDIAN_H_
11 #define CTRL_UTILS_EUCLIDIAN_H_
13 #include <ctrl_utils/eigen.h>
41 const Eigen::Quaterniond& quat_des);
56 inline Eigen::Vector3d
LookatError(
const Eigen::Vector3d& vec,
57 const Eigen::Vector3d& vec_des);
84 const Eigen::Quaterniond& quat,
const Eigen::Quaterniond& quat_reference);
99 Eigen::Ref<const Eigen::Matrix3d> ori,
100 const Eigen::Quaterniond& quat_reference);
115 const Eigen::Quaterniond& quat,
const Eigen::Quaterniond& quat_reference);
130 const Eigen::Ref<const Eigen::Matrix3d> ori,
131 const Eigen::Quaterniond& quat_reference);
153 template <
typename Derived>
154 Eigen::Vector3d Log(
const Eigen::RotationBase<Derived, 3>& ori);
156 inline Eigen::Matrix3d Exp(
const Eigen::Vector3d& w);
163 inline Eigen::Matrix3d LogMapDerivative(
const Eigen::AngleAxisd& aa);
166 struct ExpMapJacobianReturnType;
170 using type = Eigen::Matrix3d;
175 using type = Eigen::Matrix<double, 9, Cols>;
194 template <
typename Derived>
196 Eigen::MatrixBase<Derived>::ColsAtCompileTime>::type
198 const Eigen::MatrixBase<Derived>& X);
201 const Eigen::AngleAxisd& aa) {
205 inline Eigen::Vector6d Log(
const Eigen::Isometry3d& T);
209 inline Eigen::Matrix6d LogMapDerivative(
const Eigen::Isometry3d& T);
216 const Eigen::Quaterniond& quat_des) {
217 Eigen::Quaterniond quat_err = quat * quat_des.conjugate();
218 Eigen::AngleAxisd aa_err(quat_err);
220 (quat_err.w() < 0) ? aa_err.angle() - 2 * M_PI : aa_err.angle();
221 return angle * aa_err.axis();
225 const Eigen::Vector3d& vec_des) {
226 Eigen::Quaterniond quat_err =
227 Eigen::Quaterniond::FromTwoVectors(vec_des, vec);
228 Eigen::AngleAxisd aa_err(quat_err);
230 (quat_err.w() < 0) ? aa_err.angle() - 2 * M_PI : aa_err.angle();
231 return angle * aa_err.axis();
235 const Eigen::Quaterniond& quat_reference) {
236 Eigen::Quaterniond result = quat;
237 if (quat.dot(quat_reference) < 0) result.coeffs() *= -1;
242 const Eigen::Quaterniond& quat_reference) {
243 Eigen::Quaterniond result(ori);
244 if (result.dot(quat_reference) < 0) result.coeffs() *= -1;
249 const Eigen::Quaterniond& quat_reference) {
250 Eigen::Quaterniond result = quat;
251 if (quat.dot(quat_reference) > 0) result.coeffs() *= -1;
256 const Eigen::Quaterniond& quat_reference) {
257 Eigen::Quaterniond result(ori);
258 if (result.dot(quat_reference) > 0) result.coeffs() *= -1;
262 template <
typename Derived>
263 Eigen::Vector3d Log(
const Eigen::RotationBase<Derived, 3>& ori) {
264 const Eigen::AngleAxisd aa(ori.derived());
265 return aa.angle() * aa.axis();
268 Eigen::Matrix3d Exp(
const Eigen::Vector3d& w) {
269 return Eigen::AngleAxisd(w.norm(), w.normalized()).toRotationMatrix();
273 const double theta = aa.angle();
275 return Eigen::Matrix3d::Zero();
276 }
else if (theta * theta < std::numeric_limits<double>::epsilon()) {
277 return Eigen::Matrix3d::Identity();
279 return Eigen::Matrix3d::Identity() +
280 (1. - std::cos(theta)) / theta * CrossMatrix(aa.axis()) +
281 (1. - std::sin(theta) / theta) * DoubleCrossMatrix(aa.axis());
284 Eigen::Matrix3d LogMapDerivative(
const Eigen::AngleAxisd& aa) {
285 const double theta = aa.angle();
287 return Eigen::Matrix3d::Zero();
288 }
else if (theta * theta < std::numeric_limits<double>::epsilon()) {
289 return Eigen::Matrix3d::Identity();
291 return Eigen::Matrix3d::Identity() - 0.5 * theta * CrossMatrix(aa.axis()) +
292 (1. - 0.5 * theta * std::sin(theta) / (1. - std::cos(theta))) *
293 DoubleCrossMatrix(aa.axis());
296 inline Eigen::Matrix<double, 9, 3> LogMapHessian(
297 const Eigen::AngleAxisd& aa) {
298 const double theta = aa.angle();
299 Eigen::Matrix<double, 9, 3> G;
303 }
else if (theta * theta < std::numeric_limits<double>::epsilon()) {
304 G.topRows<3>().setIdentity();
305 G.middleRows<3>(3).setIdentity();
306 G.bottomRows<3>().setIdentity();
316 Eigen::Matrix<double, 9, 3> GG;
317 const Eigen::Matrix3d w_x = ctrl_utils::CrossMatrix(theta * aa.axis());
318 GG.topRows<3>() = w_x * G.topRows<3>() + G.topRows<3>() * w_x;
319 GG.middleRows<3>(3) = w_x * G.middleRows<3>(3) + G.middleRows<3>(3) * w_x;
320 GG.bottomRows<3>() = w_x * G.bottomRows<3>() + G.bottomRows<3>() * w_x;
321 const double cos_theta = std::cos(theta);
322 const double sin_theta = std::sin(theta);
323 const double factor =
324 (1. - 0.5 * (theta * sin_theta) / (1. - cos_theta)) / (theta * theta);
325 const double dfactor =
326 -2. / (theta * theta * theta) -
327 0.5 / (theta * theta * (1. - cos_theta) * (1. - cos_theta)) *
328 (theta * (1. - cos_theta) * cos_theta -
329 sin_theta * (1. - cos_theta + theta * sin_theta));
330 const Eigen::Matrix3d w_x_w_x =
331 ctrl_utils::DoubleCrossMatrix(theta * aa.axis());
332 Eigen::Matrix<double, 9, 3> WW;
333 WW.topRows<3>() = dfactor * aa.axis()(0) * w_x_w_x;
334 WW.middleRows<3>(3) = dfactor * aa.axis()(1) * w_x_w_x;
335 WW.bottomRows<3>(3) = dfactor * aa.axis()(2) * w_x_w_x;
336 return -0.5 * G + dfactor * WW + factor * GG;
339 template <
typename Derived>
340 inline typename ExpMapJacobianReturnType<
341 Eigen::MatrixBase<Derived>::ColsAtCompileTime>::type
343 const Eigen::MatrixBase<Derived>& X) {
344 constexpr
int Cols = Eigen::MatrixBase<Derived>::ColsAtCompileTime;
345 typename ExpMapJacobianReturnType<Cols>::type J;
347 const typename Eigen::MatrixBase<Derived>::PlainObject RX = aa * X;
348 for (
size_t i = 0; i < 3; i++) {
349 Eigen::Map<Eigen::MatrixXd> J_i(J.data() + 3 * RX.cols() * i, 3,
351 J_i = RX.colwise().cross(-dExp.col(i));
357 inline typename ExpMapJacobianReturnType<Cols>::type ExpCoordsJacobianImpl(
358 const Eigen::Matrix3d& R,
const Eigen::AngleAxisd& aa,
359 const Eigen::Matrix<double, 3, Cols>& X);
362 inline Eigen::Matrix3d ExpCoordsJacobianImpl<1>(
const Eigen::Matrix3d& R,
363 const Eigen::AngleAxisd& aa,
364 const Eigen::Vector3d& p) {
365 const double theta = aa.angle();
367 return Eigen::Matrix3d::Zero();
368 }
else if (theta < std::numeric_limits<double>::epsilon()) {
369 return -ctrl_utils::CrossMatrix(p);
371 const Eigen::Vector3d w = theta * aa.axis();
373 return R * ctrl_utils::CrossMatrix(p / -(theta * theta)) *
374 (w * w.transpose() + (R.transpose() - Eigen::Matrix3d::Identity()) *
375 ctrl_utils::CrossMatrix(w));
379 inline Eigen::Matrix<double, 9, 3> ExpCoordsJacobianImpl<3>(
380 const Eigen::Matrix3d& R,
const Eigen::AngleAxisd& aa,
381 const Eigen::Matrix3d& I) {
382 Eigen::Matrix<double, 9, 3> dR_dw;
384 const double theta = aa.angle();
388 }
else if (theta < std::numeric_limits<double>::epsilon()) {
389 for (
size_t i = 0; i < 3; i++) {
390 Eigen::Map<Eigen::Matrix3d> dR_dwi(dR_dw.col(i).data());
391 dR_dwi = ctrl_utils::CrossMatrix(Eigen::Vector3d::Unit(i));
396 const Eigen::Vector3d w = theta * aa.axis();
397 const Eigen::Matrix3d w_cross = ctrl_utils::CrossMatrix(w);
398 const Eigen::Matrix3d R_hat = R / (theta * theta);
399 for (
size_t i = 0; i < 3; i++) {
400 Eigen::Map<Eigen::Matrix3d> dR_dwi(dR_dw.col(i).data());
401 dR_dwi = (w(i) * w_cross + ctrl_utils::CrossMatrix(w.cross(
402 Eigen::Vector3d::Unit(i) - R.col(i)))) *
408 template <
typename Derived>
409 inline typename ExpMapJacobianReturnType<
410 Eigen::MatrixBase<Derived>::ColsAtCompileTime>::type
411 ExpMapJacobianOld(
const Eigen::AngleAxisd& aa,
412 const Eigen::MatrixBase<Derived>& X) {
413 return ExpCoordsJacobianImpl(aa.toRotationMatrix(), aa, X.eval());
416 inline typename ExpMapJacobianReturnType<3>::type ExpMapJacobianOld(
417 const Eigen::AngleAxisd& aa) {
418 return ExpCoordsJacobianImpl(aa.toRotationMatrix(), aa,
419 Eigen::Matrix3d::Identity().eval());
430 Eigen::Vector6d Log(
const Eigen::Isometry3d& T) {
431 const Eigen::AngleAxisd aa(T.linear());
432 const double theta = aa.angle();
433 const Eigen::Vector3d w = theta * aa.axis();
434 const auto& p = T.translation();
435 const Eigen::Vector3d w_x_p = aa.axis().cross(p);
437 1. - 0.5 * theta * std::sin(theta) / (1. - std::cos(theta));
440 v.head<3>() = p - 0.5 * theta * w_x_p + a * aa.axis().cross(w_x_p);
441 if (theta < 1e-5) v.head<3>().setZero();
446 inline Eigen::Matrix3d ExpMapDerivativeCrossTerm(
447 const Eigen::AngleAxisd& aa, Eigen::Ref<const Eigen::Vector3d> x) {
448 const double theta = aa.angle();
449 const double theta_sq = theta * theta;
450 if (theta_sq < std::numeric_limits<double>::epsilon()) {
451 return Eigen::Matrix3d::Zero();
453 const double s_theta = std::sin(theta);
454 const double c_theta = std::cos(theta);
455 const double w_dot_u = aa.axis().dot(x);
456 const Eigen::Matrix3d x_x = CrossMatrix(x);
457 const Eigen::Matrix3d w_x = CrossMatrix(aa.axis());
458 const Eigen::Matrix3d w_x_x_x = w_x * x_x;
459 return (1. - c_theta) / theta_sq * x_x +
460 (theta - s_theta) / theta_sq * (w_x_x_x + w_x_x_x.transpose()) +
461 w_dot_u * (s_theta - 2. * (1 - c_theta) / theta) / theta * w_x +
462 w_dot_u * (-2. - c_theta + 3 * s_theta / theta) / theta *
463 DoubleCrossMatrix(aa.axis());
467 const Eigen::AngleAxisd aa(T.linear());
468 const auto& x = T.translation();
469 Eigen::Matrix6d dExp;
471 dExp.topLeftCorner<3, 3>() = dExp_w;
472 dExp.bottomLeftCorner<3, 3>().fill(0.);
473 dExp.topRightCorner<3, 3>() = ExpMapDerivativeCrossTerm(aa, x);
474 dExp.bottomRightCorner<3, 3>() = dExp_w;
478 Eigen::Matrix6d LogMapDerivative(
const Eigen::Isometry3d& T) {
479 const Eigen::AngleAxisd aa(T.linear());
480 const auto& x = T.translation();
481 Eigen::Matrix6d dExp;
482 const Eigen::Matrix3d dLog_w = LogMapDerivative(aa);
483 dExp.topLeftCorner<3, 3>() = dLog_w;
484 dExp.bottomLeftCorner<3, 3>().fill(0.);
485 dExp.topRightCorner<3, 3>() =
486 -dLog_w * ExpMapDerivativeCrossTerm(aa, x) * dLog_w;
487 dExp.bottomRightCorner<3, 3>() = dLog_w;
Definition: ctrl_utils.cc:18
ExpMapJacobianReturnType< Eigen::MatrixBase< Derived >::ColsAtCompileTime >::type ExpMapJacobian(const Eigen::AngleAxisd &aa, const Eigen::MatrixBase< Derived > &X)
Definition: euclidian.h:342
Eigen::Quaterniond FarQuaternion(const Eigen::Quaterniond &quat, const Eigen::Quaterniond &quat_reference)
Definition: euclidian.h:248
Eigen::Matrix3d ExpMapDerivative(const Eigen::AngleAxisd &aa)
Definition: euclidian.h:272
Eigen::Vector3d OrientationError(const Eigen::Quaterniond &quat, const Eigen::Quaterniond &quat_des)
Definition: euclidian.h:215
Eigen::Quaterniond NearQuaternion(const Eigen::Quaterniond &quat, const Eigen::Quaterniond &quat_reference)
Definition: euclidian.h:234
Eigen::Vector3d LookatError(const Eigen::Vector3d &vec, const Eigen::Vector3d &vec_des)
Definition: euclidian.h:224
Definition: euclidian.h:174