Add a 'cost_helpers' library. (#862)
* Add a 'cost_helpers' library. * Change naming and add comments.master
							parent
							
								
									93568641f9
								
							
						
					
					
						commit
						708e7fc57d
					
				|  | @ -0,0 +1,55 @@ | |||
| /*
 | ||||
|  * Copyright 2018 The Cartographer Authors | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef CARTOGRAPHER_MAPPING_POSE_GRAPH_COST_HELPERS_H_ | ||||
| #define CARTOGRAPHER_MAPPING_POSE_GRAPH_COST_HELPERS_H_ | ||||
| 
 | ||||
| #include "Eigen/Core" | ||||
| #include "Eigen/Geometry" | ||||
| #include "cartographer/transform/rigid_transform.h" | ||||
| #include "cartographer/transform/transform.h" | ||||
| 
 | ||||
| namespace cartographer { | ||||
| namespace mapping { | ||||
| namespace pose_graph { | ||||
| 
 | ||||
| // Computes the error between the given relative pose and the difference of
 | ||||
| // poses 'start' and 'end' which are both in an arbitrary common frame.
 | ||||
| //
 | ||||
| // 'start' and 'end' poses have the format [x, y, rotation].
 | ||||
| template <typename T> | ||||
| static std::array<T, 3> ComputeUnscaledError2d( | ||||
|     const transform::Rigid2d& relative_pose, const T* const start, | ||||
|     const T* const end); | ||||
| 
 | ||||
| // Computes the error between the given relative pose and the difference of
 | ||||
| // poses 'start' and 'end' which are both in an arbitrary common frame.
 | ||||
| //
 | ||||
| // 'start' and 'end' translation has the format [x, y, z].
 | ||||
| // 'start' and 'end' rotation are quaternions in the format [w, n_1, n_2, n_3].
 | ||||
| template <typename T> | ||||
| static std::array<T, 6> ComputeUnscaledError3d( | ||||
|     const transform::Rigid3d& relative_pose, const T* const start_rotation, | ||||
|     const T* const start_translation, const T* const end_rotation, | ||||
|     const T* const end_translation); | ||||
| 
 | ||||
| }  // namespace pose_graph
 | ||||
| }  // namespace mapping
 | ||||
| }  // namespace cartographer
 | ||||
| 
 | ||||
| #include "cartographer/mapping/pose_graph/cost_helpers_impl.h" | ||||
| 
 | ||||
| #endif  // CARTOGRAPHER_MAPPING_POSE_GRAPH_COST_HELPERS_H_
 | ||||
|  | @ -0,0 +1,76 @@ | |||
| /*
 | ||||
|  * Copyright 2018 The Cartographer Authors | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef CARTOGRAPHER_MAPPING_POSE_GRAPH_COST_HELPERS_IMPL_H_ | ||||
| #define CARTOGRAPHER_MAPPING_POSE_GRAPH_COST_HELPERS_IMPL_H_ | ||||
| 
 | ||||
| namespace cartographer { | ||||
| namespace mapping { | ||||
| namespace pose_graph { | ||||
| 
 | ||||
| template <typename T> | ||||
| static std::array<T, 3> ComputeUnscaledError2d( | ||||
|     const transform::Rigid2d& relative_pose, const T* const start, | ||||
|     const T* const end) { | ||||
|   const T cos_theta_i = cos(start[2]); | ||||
|   const T sin_theta_i = sin(start[2]); | ||||
|   const T delta_x = end[0] - start[0]; | ||||
|   const T delta_y = end[1] - start[1]; | ||||
|   const T h[3] = {cos_theta_i * delta_x + sin_theta_i * delta_y, | ||||
|                   -sin_theta_i * delta_x + cos_theta_i * delta_y, | ||||
|                   end[2] - start[2]}; | ||||
|   return {{T(relative_pose.translation().x()) - h[0], | ||||
|            T(relative_pose.translation().y()) - h[1], | ||||
|            common::NormalizeAngleDifference( | ||||
|                T(relative_pose.rotation().angle()) - h[2])}}; | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| static std::array<T, 6> ComputeUnscaledError3d( | ||||
|     const transform::Rigid3d& relative_pose, const T* const start_rotation, | ||||
|     const T* const start_translation, const T* const end_rotation, | ||||
|     const T* const end_translation) { | ||||
|   const Eigen::Quaternion<T> R_i_inverse(start_rotation[0], -start_rotation[1], | ||||
|                                          -start_rotation[2], | ||||
|                                          -start_rotation[3]); | ||||
| 
 | ||||
|   const Eigen::Matrix<T, 3, 1> delta(end_translation[0] - start_translation[0], | ||||
|                                      end_translation[1] - start_translation[1], | ||||
|                                      end_translation[2] - start_translation[2]); | ||||
|   const Eigen::Matrix<T, 3, 1> h_translation = R_i_inverse * delta; | ||||
| 
 | ||||
|   const Eigen::Quaternion<T> h_rotation_inverse = | ||||
|       Eigen::Quaternion<T>(end_rotation[0], -end_rotation[1], -end_rotation[2], | ||||
|                            -end_rotation[3]) * | ||||
|       Eigen::Quaternion<T>(start_rotation[0], start_rotation[1], | ||||
|                            start_rotation[2], start_rotation[3]); | ||||
| 
 | ||||
|   const Eigen::Matrix<T, 3, 1> angle_axis_difference = | ||||
|       transform::RotationQuaternionToAngleAxisVector( | ||||
|           h_rotation_inverse * relative_pose.rotation().cast<T>()); | ||||
| 
 | ||||
|   return {{T(relative_pose.translation().x()) - h_translation[0], | ||||
|            T(relative_pose.translation().y()) - h_translation[1], | ||||
|            T(relative_pose.translation().z()) - h_translation[2], | ||||
|            angle_axis_difference[0], angle_axis_difference[1], | ||||
|            angle_axis_difference[2]}}; | ||||
| } | ||||
| 
 | ||||
| }  // namespace pose_graph
 | ||||
| }  // namespace mapping
 | ||||
| }  // namespace cartographer
 | ||||
| 
 | ||||
| #endif  // CARTOGRAPHER_MAPPING_POSE_GRAPH_COST_HELPERS_IMPL_H_
 | ||||
|  | @ -19,8 +19,8 @@ | |||
| 
 | ||||
| #include "Eigen/Core" | ||||
| #include "Eigen/Geometry" | ||||
| #include "cartographer/mapping/pose_graph/cost_helpers.h" | ||||
| #include "cartographer/mapping/pose_graph_interface.h" | ||||
| #include "cartographer/mapping_3d/pose_graph/spa_cost_function.h" | ||||
| #include "cartographer/transform/rigid_transform.h" | ||||
| #include "cartographer/transform/transform.h" | ||||
| #include "ceres/ceres.h" | ||||
|  | @ -62,7 +62,7 @@ std::array<T, 4> SlerpQuaternions(const T* const prev_rotation, | |||
| class LandmarkCostFunction { | ||||
|  public: | ||||
|   using LandmarkObservation = | ||||
|       mapping::PoseGraph::LandmarkNode::LandmarkObservation; | ||||
|       mapping::PoseGraphInterface::LandmarkNode::LandmarkObservation; | ||||
| 
 | ||||
|   static ceres::CostFunction* CreateAutoDiffCostFunction( | ||||
|       const LandmarkObservation& observation, common::Time prev_node_time, | ||||
|  | @ -99,13 +99,9 @@ class LandmarkCostFunction { | |||
|     std::array<T, 4> interpolated_pose_rotation = SlerpQuaternions( | ||||
|         prev_node_rotation, next_node_rotation, T(interpolation_parameter_)); | ||||
| 
 | ||||
|     // TODO(pifon2a): Move functions common for all cost functions outside of
 | ||||
|     // SpaCostFunction scope.
 | ||||
|     const std::array<T, 6> unscaled_error = | ||||
|         mapping_3d::pose_graph::SpaCostFunction::ComputeUnscaledError( | ||||
|             landmark_to_tracking_transform_, interpolated_pose_rotation.data(), | ||||
|             interpolated_pose_translation, landmark_rotation, | ||||
|             landmark_translation); | ||||
|     const std::array<T, 6> unscaled_error = ComputeUnscaledError3d( | ||||
|         landmark_to_tracking_transform_, interpolated_pose_rotation.data(), | ||||
|         interpolated_pose_translation, landmark_rotation, landmark_translation); | ||||
| 
 | ||||
|     e[0] = T(translation_weight_) * unscaled_error[0]; | ||||
|     e[1] = T(translation_weight_) * unscaled_error[1]; | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ using ::testing::DoubleEq; | |||
| using ::testing::ElementsAre; | ||||
| 
 | ||||
| using LandmarkObservation = | ||||
|     mapping::PoseGraph::LandmarkNode::LandmarkObservation; | ||||
|     mapping::PoseGraphInterface::LandmarkNode::LandmarkObservation; | ||||
| 
 | ||||
| TEST(LandmarkCostFunctionTest, SmokeTest) { | ||||
|   auto* cost_function = LandmarkCostFunction::CreateAutoDiffCostFunction( | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include "Eigen/Geometry" | ||||
| #include "cartographer/common/math.h" | ||||
| #include "cartographer/mapping/pose_graph.h" | ||||
| #include "cartographer/mapping/pose_graph/cost_helpers.h" | ||||
| #include "cartographer/transform/rigid_transform.h" | ||||
| #include "cartographer/transform/transform.h" | ||||
| #include "ceres/ceres.h" | ||||
|  | @ -50,34 +51,14 @@ class SpaCostFunction { | |||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   // Computes the error between the node-to-submap alignment 'zbar_ij' and the
 | ||||
|   // difference of submap pose 'c_i' and node pose 'c_j' which are both in an
 | ||||
|   // arbitrary common frame.
 | ||||
|   template <typename T> | ||||
|   static std::array<T, 3> ComputeUnscaledError( | ||||
|       const transform::Rigid2d& zbar_ij, const T* const c_i, | ||||
|       const T* const c_j) { | ||||
|     const T cos_theta_i = cos(c_i[2]); | ||||
|     const T sin_theta_i = sin(c_i[2]); | ||||
|     const T delta_x = c_j[0] - c_i[0]; | ||||
|     const T delta_y = c_j[1] - c_i[1]; | ||||
|     const T h[3] = {cos_theta_i * delta_x + sin_theta_i * delta_y, | ||||
|                     -sin_theta_i * delta_x + cos_theta_i * delta_y, | ||||
|                     c_j[2] - c_i[2]}; | ||||
|     return {{T(zbar_ij.translation().x()) - h[0], | ||||
|              T(zbar_ij.translation().y()) - h[1], | ||||
|              common::NormalizeAngleDifference(T(zbar_ij.rotation().angle()) - | ||||
|                                               h[2])}}; | ||||
|   } | ||||
| 
 | ||||
|   // Computes the error scaled by 'translation_weight' and 'rotation_weight',
 | ||||
|   // storing it in 'e'.
 | ||||
|   template <typename T> | ||||
|   static void ComputeScaledError(const Constraint::Pose& pose, | ||||
|                                  const T* const c_i, const T* const c_j, | ||||
|                                  T* const e) { | ||||
|     const std::array<T, 3> e_ij = | ||||
|         ComputeUnscaledError(transform::Project2D(pose.zbar_ij), c_i, c_j); | ||||
|     const std::array<T, 3> e_ij = mapping::pose_graph::ComputeUnscaledError2d( | ||||
|         transform::Project2D(pose.zbar_ij), c_i, c_j); | ||||
|     e[0] = e_ij[0] * T(pose.translation_weight); | ||||
|     e[1] = e_ij[1] * T(pose.translation_weight); | ||||
|     e[2] = e_ij[2] * T(pose.rotation_weight); | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include "Eigen/Geometry" | ||||
| #include "cartographer/common/math.h" | ||||
| #include "cartographer/mapping/pose_graph.h" | ||||
| #include "cartographer/mapping/pose_graph/cost_helpers.h" | ||||
| #include "cartographer/transform/rigid_transform.h" | ||||
| #include "cartographer/transform/transform.h" | ||||
| #include "ceres/ceres.h" | ||||
|  | @ -53,39 +54,6 @@ class SpaCostFunction { | |||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   // Computes the error between the node-to-submap alignment 'zbar_ij' and the
 | ||||
|   // difference of submap pose 'c_i' and node pose 'c_j' which are both in an
 | ||||
|   // arbitrary common frame.
 | ||||
|   template <typename T> | ||||
|   static std::array<T, 6> ComputeUnscaledError( | ||||
|       const transform::Rigid3d& zbar_ij, const T* const c_i_rotation, | ||||
|       const T* const c_i_translation, const T* const c_j_rotation, | ||||
|       const T* const c_j_translation) { | ||||
|     const Eigen::Quaternion<T> R_i_inverse(c_i_rotation[0], -c_i_rotation[1], | ||||
|                                            -c_i_rotation[2], -c_i_rotation[3]); | ||||
| 
 | ||||
|     const Eigen::Matrix<T, 3, 1> delta(c_j_translation[0] - c_i_translation[0], | ||||
|                                        c_j_translation[1] - c_i_translation[1], | ||||
|                                        c_j_translation[2] - c_i_translation[2]); | ||||
|     const Eigen::Matrix<T, 3, 1> h_translation = R_i_inverse * delta; | ||||
| 
 | ||||
|     const Eigen::Quaternion<T> h_rotation_inverse = | ||||
|         Eigen::Quaternion<T>(c_j_rotation[0], -c_j_rotation[1], | ||||
|                              -c_j_rotation[2], -c_j_rotation[3]) * | ||||
|         Eigen::Quaternion<T>(c_i_rotation[0], c_i_rotation[1], c_i_rotation[2], | ||||
|                              c_i_rotation[3]); | ||||
| 
 | ||||
|     const Eigen::Matrix<T, 3, 1> angle_axis_difference = | ||||
|         transform::RotationQuaternionToAngleAxisVector( | ||||
|             h_rotation_inverse * zbar_ij.rotation().cast<T>()); | ||||
| 
 | ||||
|     return {{T(zbar_ij.translation().x()) - h_translation[0], | ||||
|              T(zbar_ij.translation().y()) - h_translation[1], | ||||
|              T(zbar_ij.translation().z()) - h_translation[2], | ||||
|              angle_axis_difference[0], angle_axis_difference[1], | ||||
|              angle_axis_difference[2]}}; | ||||
|   } | ||||
| 
 | ||||
|   // Computes the error scaled by 'translation_weight' and 'rotation_weight',
 | ||||
|   // storing it in 'e'.
 | ||||
|   template <typename T> | ||||
|  | @ -94,9 +62,9 @@ class SpaCostFunction { | |||
|                                  const T* const c_i_translation, | ||||
|                                  const T* const c_j_rotation, | ||||
|                                  const T* const c_j_translation, T* const e) { | ||||
|     const std::array<T, 6> e_ij = | ||||
|         ComputeUnscaledError(pose.zbar_ij, c_i_rotation, c_i_translation, | ||||
|                              c_j_rotation, c_j_translation); | ||||
|     const std::array<T, 6> e_ij = mapping::pose_graph::ComputeUnscaledError3d( | ||||
|         pose.zbar_ij, c_i_rotation, c_i_translation, c_j_rotation, | ||||
|         c_j_translation); | ||||
|     for (int ij : {0, 1, 2}) { | ||||
|       e[ij] = e_ij[ij] * T(pose.translation_weight); | ||||
|     } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue