aboutsummaryrefslogtreecommitdiff
path: root/include/ceres/rotation.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ceres/rotation.h')
-rw-r--r--include/ceres/rotation.h73
1 files changed, 40 insertions, 33 deletions
diff --git a/include/ceres/rotation.h b/include/ceres/rotation.h
index ea0b769..e3dbfe8 100644
--- a/include/ceres/rotation.h
+++ b/include/ceres/rotation.h
@@ -395,7 +395,7 @@ void AngleAxisToRotationMatrix(
const MatrixAdapter<T, row_stride, col_stride>& R) {
static const T kOne = T(1.0);
const T theta2 = DotProduct(angle_axis, angle_axis);
- if (theta2 > 0.0) {
+ if (theta2 > T(std::numeric_limits<double>::epsilon())) {
// We want to be careful to only evaluate the square root if the
// norm of the angle_axis vector is greater than zero. Otherwise
// we get a division by zero.
@@ -417,15 +417,15 @@ void AngleAxisToRotationMatrix(
R(1, 2) = -wx*sintheta + wy*wz*(kOne - costheta);
R(2, 2) = costheta + wz*wz*(kOne - costheta);
} else {
- // At zero, we switch to using the first order Taylor expansion.
+ // Near zero, we switch to using the first order Taylor expansion.
R(0, 0) = kOne;
- R(1, 0) = -angle_axis[2];
- R(2, 0) = angle_axis[1];
- R(0, 1) = angle_axis[2];
+ R(1, 0) = angle_axis[2];
+ R(2, 0) = -angle_axis[1];
+ R(0, 1) = -angle_axis[2];
R(1, 1) = kOne;
- R(2, 1) = -angle_axis[0];
- R(0, 2) = -angle_axis[1];
- R(1, 2) = angle_axis[0];
+ R(2, 1) = angle_axis[0];
+ R(0, 2) = angle_axis[1];
+ R(1, 2) = -angle_axis[0];
R(2, 2) = kOne;
}
}
@@ -580,12 +580,8 @@ T DotProduct(const T x[3], const T y[3]) {
template<typename T> inline
void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
- T w[3];
- T sintheta;
- T costheta;
-
const T theta2 = DotProduct(angle_axis, angle_axis);
- if (theta2 > 0.0) {
+ if (theta2 > T(std::numeric_limits<double>::epsilon())) {
// Away from zero, use the rodriguez formula
//
// result = pt costheta +
@@ -597,19 +593,25 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
// we get a division by zero.
//
const T theta = sqrt(theta2);
- w[0] = angle_axis[0] / theta;
- w[1] = angle_axis[1] / theta;
- w[2] = angle_axis[2] / theta;
- costheta = cos(theta);
- sintheta = sin(theta);
- T w_cross_pt[3];
- CrossProduct(w, pt, w_cross_pt);
- T w_dot_pt = DotProduct(w, pt);
- for (int i = 0; i < 3; ++i) {
- result[i] = pt[i] * costheta +
- w_cross_pt[i] * sintheta +
- w[i] * (T(1.0) - costheta) * w_dot_pt;
- }
+ const T costheta = cos(theta);
+ const T sintheta = sin(theta);
+ const T theta_inverse = 1.0 / theta;
+
+ const T w[3] = { angle_axis[0] * theta_inverse,
+ angle_axis[1] * theta_inverse,
+ angle_axis[2] * theta_inverse };
+
+ // Explicitly inlined evaluation of the cross product for
+ // performance reasons.
+ const T w_cross_pt[3] = { w[1] * pt[2] - w[2] * pt[1],
+ w[2] * pt[0] - w[0] * pt[2],
+ w[0] * pt[1] - w[1] * pt[0] };
+ const T tmp =
+ (w[0] * pt[0] + w[1] * pt[1] + w[2] * pt[2]) * (T(1.0) - costheta);
+
+ result[0] = pt[0] * costheta + w_cross_pt[0] * sintheta + w[0] * tmp;
+ result[1] = pt[1] * costheta + w_cross_pt[1] * sintheta + w[1] * tmp;
+ result[2] = pt[2] * costheta + w_cross_pt[2] * sintheta + w[2] * tmp;
} else {
// Near zero, the first order Taylor approximation of the rotation
// matrix R corresponding to a vector w and angle w is
@@ -623,13 +625,18 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
// and actually performing multiplication with the point pt, gives us
// R * pt = pt + w x pt.
//
- // Switching to the Taylor expansion at zero helps avoid all sorts
- // of numerical nastiness.
- T w_cross_pt[3];
- CrossProduct(angle_axis, pt, w_cross_pt);
- for (int i = 0; i < 3; ++i) {
- result[i] = pt[i] + w_cross_pt[i];
- }
+ // Switching to the Taylor expansion near zero provides meaningful
+ // derivatives when evaluated using Jets.
+ //
+ // Explicitly inlined evaluation of the cross product for
+ // performance reasons.
+ const T w_cross_pt[3] = { angle_axis[1] * pt[2] - angle_axis[2] * pt[1],
+ angle_axis[2] * pt[0] - angle_axis[0] * pt[2],
+ angle_axis[0] * pt[1] - angle_axis[1] * pt[0] };
+
+ result[0] = pt[0] + w_cross_pt[0];
+ result[1] = pt[1] + w_cross_pt[1];
+ result[2] = pt[2] + w_cross_pt[2];
}
}