Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "cartographer/mapping/internal/optimization/cost_functions/spa_cost_function_2d.h"
00018
00019 #include <array>
00020
00021 #include "Eigen/Core"
00022 #include "Eigen/Geometry"
00023 #include "cartographer/common/math.h"
00024 #include "cartographer/mapping/internal/optimization/cost_functions/cost_helpers.h"
00025 #include "cartographer/transform/rigid_transform.h"
00026 #include "cartographer/transform/transform.h"
00027 #include "ceres/jet.h"
00028
00029 namespace cartographer {
00030 namespace mapping {
00031 namespace optimization {
00032 namespace {
00033
00034 class SpaCostFunction2D {
00035 public:
00036 explicit SpaCostFunction2D(
00037 const PoseGraphInterface::Constraint::Pose& observed_relative_pose)
00038 : observed_relative_pose_(observed_relative_pose) {}
00039
00040 template <typename T>
00041 bool operator()(const T* const start_pose, const T* const end_pose,
00042 T* e) const {
00043 const std::array<T, 3> error =
00044 ScaleError(ComputeUnscaledError(
00045 transform::Project2D(observed_relative_pose_.zbar_ij),
00046 start_pose, end_pose),
00047 observed_relative_pose_.translation_weight,
00048 observed_relative_pose_.rotation_weight);
00049 std::copy(std::begin(error), std::end(error), e);
00050 return true;
00051 }
00052
00053 private:
00054 const PoseGraphInterface::Constraint::Pose observed_relative_pose_;
00055 };
00056
00057 class AnalyticalSpaCostFunction2D
00058 : public ceres::SizedCostFunction<3 ,
00059 3 ,
00060 3 > {
00061 public:
00062 explicit AnalyticalSpaCostFunction2D(
00063 const PoseGraphInterface::Constraint::Pose& constraint_pose)
00064 : observed_relative_pose_(transform::Project2D(constraint_pose.zbar_ij)),
00065 translation_weight_(constraint_pose.translation_weight),
00066 rotation_weight_(constraint_pose.rotation_weight) {}
00067 virtual ~AnalyticalSpaCostFunction2D() {}
00068
00069 bool Evaluate(double const* const* parameters, double* residuals,
00070 double** jacobians) const override {
00071 double const* start = parameters[0];
00072 double const* end = parameters[1];
00073
00074 const double cos_start_rotation = cos(start[2]);
00075 const double sin_start_rotation = sin(start[2]);
00076 const double delta_x = end[0] - start[0];
00077 const double delta_y = end[1] - start[1];
00078
00079 residuals[0] =
00080 translation_weight_ *
00081 (observed_relative_pose_.translation().x() -
00082 (cos_start_rotation * delta_x + sin_start_rotation * delta_y));
00083 residuals[1] =
00084 translation_weight_ *
00085 (observed_relative_pose_.translation().y() -
00086 (-sin_start_rotation * delta_x + cos_start_rotation * delta_y));
00087 residuals[2] =
00088 rotation_weight_ *
00089 common::NormalizeAngleDifference(
00090 observed_relative_pose_.rotation().angle() - (end[2] - start[2]));
00091 if (jacobians == NULL) return true;
00092
00093 const double weighted_cos_start_rotation =
00094 translation_weight_ * cos_start_rotation;
00095 const double weighted_sin_start_rotation =
00096 translation_weight_ * sin_start_rotation;
00097
00098
00099
00100 if (jacobians[0] != NULL) {
00101 jacobians[0][0] = weighted_cos_start_rotation;
00102 jacobians[0][1] = weighted_sin_start_rotation;
00103 jacobians[0][2] = weighted_sin_start_rotation * delta_x -
00104 weighted_cos_start_rotation * delta_y;
00105 jacobians[0][3] = -weighted_sin_start_rotation;
00106 jacobians[0][4] = weighted_cos_start_rotation;
00107 jacobians[0][5] = weighted_cos_start_rotation * delta_x +
00108 weighted_sin_start_rotation * delta_y;
00109 jacobians[0][6] = 0;
00110 jacobians[0][7] = 0;
00111 jacobians[0][8] = rotation_weight_;
00112 }
00113 if (jacobians[1] != NULL) {
00114 jacobians[1][0] = -weighted_cos_start_rotation;
00115 jacobians[1][1] = -weighted_sin_start_rotation;
00116 jacobians[1][2] = 0;
00117 jacobians[1][3] = weighted_sin_start_rotation;
00118 jacobians[1][4] = -weighted_cos_start_rotation;
00119 jacobians[1][5] = 0;
00120 jacobians[1][6] = 0;
00121 jacobians[1][7] = 0;
00122 jacobians[1][8] = -rotation_weight_;
00123 }
00124 return true;
00125 }
00126
00127 private:
00128 const transform::Rigid2d observed_relative_pose_;
00129 const double translation_weight_;
00130 const double rotation_weight_;
00131 };
00132
00133 }
00134
00135 ceres::CostFunction* CreateAutoDiffSpaCostFunction(
00136 const PoseGraphInterface::Constraint::Pose& observed_relative_pose) {
00137 return new ceres::AutoDiffCostFunction<SpaCostFunction2D, 3 ,
00138 3 ,
00139 3 >(
00140 new SpaCostFunction2D(observed_relative_pose));
00141 }
00142
00143 ceres::CostFunction* CreateAnalyticalSpaCostFunction(
00144 const PoseGraphInterface::Constraint::Pose& observed_relative_pose) {
00145 return new AnalyticalSpaCostFunction2D(observed_relative_pose);
00146 }
00147
00148 }
00149 }
00150 }