00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef CARTOGRAPHER_MAPPING_INTERNAL_OPTIMIZATION_COST_FUNCTIONS_COST_HELPERS_IMPL_H_
00018 #define CARTOGRAPHER_MAPPING_INTERNAL_OPTIMIZATION_COST_FUNCTIONS_COST_HELPERS_IMPL_H_
00019
00020 #include "Eigen/Core"
00021 #include "cartographer/transform/rigid_transform.h"
00022 #include "cartographer/transform/transform.h"
00023
00024 namespace cartographer {
00025 namespace mapping {
00026 namespace optimization {
00027
00028 template <typename T>
00029 static std::array<T, 3> ComputeUnscaledError(
00030 const transform::Rigid2d& relative_pose, const T* const start,
00031 const T* const end) {
00032 const T cos_theta_i = cos(start[2]);
00033 const T sin_theta_i = sin(start[2]);
00034 const T delta_x = end[0] - start[0];
00035 const T delta_y = end[1] - start[1];
00036 const T h[3] = {cos_theta_i * delta_x + sin_theta_i * delta_y,
00037 -sin_theta_i * delta_x + cos_theta_i * delta_y,
00038 end[2] - start[2]};
00039 return {{T(relative_pose.translation().x()) - h[0],
00040 T(relative_pose.translation().y()) - h[1],
00041 common::NormalizeAngleDifference(
00042 T(relative_pose.rotation().angle()) - h[2])}};
00043 }
00044
00045 template <typename T>
00046 std::array<T, 3> ScaleError(const std::array<T, 3>& error,
00047 double translation_weight, double rotation_weight) {
00048
00049 return {{
00050 error[0] * translation_weight,
00051 error[1] * translation_weight,
00052 error[2] * rotation_weight
00053 }};
00054
00055 }
00056
00057 template <typename T>
00058 static std::array<T, 6> ComputeUnscaledError(
00059 const transform::Rigid3d& relative_pose, const T* const start_rotation,
00060 const T* const start_translation, const T* const end_rotation,
00061 const T* const end_translation) {
00062 const Eigen::Quaternion<T> R_i_inverse(start_rotation[0], -start_rotation[1],
00063 -start_rotation[2],
00064 -start_rotation[3]);
00065
00066 const Eigen::Matrix<T, 3, 1> delta(end_translation[0] - start_translation[0],
00067 end_translation[1] - start_translation[1],
00068 end_translation[2] - start_translation[2]);
00069 const Eigen::Matrix<T, 3, 1> h_translation = R_i_inverse * delta;
00070
00071 const Eigen::Quaternion<T> h_rotation_inverse =
00072 Eigen::Quaternion<T>(end_rotation[0], -end_rotation[1], -end_rotation[2],
00073 -end_rotation[3]) *
00074 Eigen::Quaternion<T>(start_rotation[0], start_rotation[1],
00075 start_rotation[2], start_rotation[3]);
00076
00077 const Eigen::Matrix<T, 3, 1> angle_axis_difference =
00078 transform::RotationQuaternionToAngleAxisVector(
00079 h_rotation_inverse * relative_pose.rotation().cast<T>());
00080
00081 return {{T(relative_pose.translation().x()) - h_translation[0],
00082 T(relative_pose.translation().y()) - h_translation[1],
00083 T(relative_pose.translation().z()) - h_translation[2],
00084 angle_axis_difference[0], angle_axis_difference[1],
00085 angle_axis_difference[2]}};
00086 }
00087
00088 template <typename T>
00089 std::array<T, 6> ScaleError(const std::array<T, 6>& error,
00090 double translation_weight, double rotation_weight) {
00091
00092 return {{
00093 error[0] * translation_weight,
00094 error[1] * translation_weight,
00095 error[2] * translation_weight,
00096 error[3] * rotation_weight,
00097 error[4] * rotation_weight,
00098 error[5] * rotation_weight
00099 }};
00100
00101 }
00102
00103
00104
00105 template <typename T>
00106 std::array<T, 4> SlerpQuaternions(const T* const start, const T* const end,
00107 double factor) {
00108
00109
00110 const T cos_theta = start[0] * end[0] + start[1] * end[1] +
00111 start[2] * end[2] + start[3] * end[3];
00112
00113 const T abs_cos_theta = ceres::abs(cos_theta);
00114
00115
00116 T prev_scale(1. - factor);
00117 T next_scale(factor);
00118 if (abs_cos_theta < T(1. - 1e-5)) {
00119 const T theta = acos(abs_cos_theta);
00120 const T sin_theta = sin(theta);
00121 prev_scale = sin((1. - factor) * theta) / sin_theta;
00122 next_scale = sin(factor * theta) / sin_theta;
00123 }
00124 if (cos_theta < T(0.)) {
00125 next_scale = -next_scale;
00126 }
00127 return {{prev_scale * start[0] + next_scale * end[0],
00128 prev_scale * start[1] + next_scale * end[1],
00129 prev_scale * start[2] + next_scale * end[2],
00130 prev_scale * start[3] + next_scale * end[3]}};
00131 }
00132
00133 template <typename T>
00134 std::tuple<std::array<T, 4> , std::array<T, 3> >
00135 InterpolateNodes3D(const T* const prev_node_rotation,
00136 const T* const prev_node_translation,
00137 const T* const next_node_rotation,
00138 const T* const next_node_translation,
00139 const double interpolation_parameter) {
00140 return std::make_tuple(
00141 SlerpQuaternions(prev_node_rotation, next_node_rotation,
00142 interpolation_parameter),
00143 std::array<T, 3>{
00144 {prev_node_translation[0] +
00145 interpolation_parameter *
00146 (next_node_translation[0] - prev_node_translation[0]),
00147 prev_node_translation[1] +
00148 interpolation_parameter *
00149 (next_node_translation[1] - prev_node_translation[1]),
00150 prev_node_translation[2] +
00151 interpolation_parameter *
00152 (next_node_translation[2] - prev_node_translation[2])}});
00153 }
00154
00155 template <typename T>
00156 std::tuple<std::array<T, 4> , std::array<T, 3> >
00157 InterpolateNodes2D(const T* const prev_node_pose,
00158 const Eigen::Quaterniond& prev_node_gravity_alignment,
00159 const T* const next_node_pose,
00160 const Eigen::Quaterniond& next_node_gravity_alignment,
00161 const double interpolation_parameter) {
00162
00163
00164 const Eigen::Quaternion<T> prev_quaternion(
00165 (Eigen::AngleAxis<T>(prev_node_pose[2], Eigen::Matrix<T, 3, 1>::UnitZ()) *
00166 prev_node_gravity_alignment.cast<T>())
00167 .normalized());
00168 const std::array<T, 4> prev_node_rotation = {
00169 {prev_quaternion.w(), prev_quaternion.x(), prev_quaternion.y(),
00170 prev_quaternion.z()}};
00171
00172
00173
00174 const Eigen::Quaternion<T> next_quaternion(
00175 (Eigen::AngleAxis<T>(next_node_pose[2], Eigen::Matrix<T, 3, 1>::UnitZ()) *
00176 next_node_gravity_alignment.cast<T>())
00177 .normalized());
00178 const std::array<T, 4> next_node_rotation = {
00179 {next_quaternion.w(), next_quaternion.x(), next_quaternion.y(),
00180 next_quaternion.z()}};
00181
00182 return std::make_tuple(
00183 SlerpQuaternions(prev_node_rotation.data(), next_node_rotation.data(),
00184 interpolation_parameter),
00185 std::array<T, 3>{
00186 {prev_node_pose[0] + interpolation_parameter *
00187 (next_node_pose[0] - prev_node_pose[0]),
00188 prev_node_pose[1] + interpolation_parameter *
00189 (next_node_pose[1] - prev_node_pose[1]),
00190 T(0)}});
00191 }
00192
00193 }
00194 }
00195 }
00196
00197 #endif // CARTOGRAPHER_MAPPING_INTERNAL_OPTIMIZATION_COST_FUNCTIONS_COST_HELPERS_IMPL_H_