spa_cost_function_2d.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2018 The Cartographer Authors
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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 /* number of residuals */,
00059                                       3 /* size of start pose */,
00060                                       3 /* size of end pose */> {
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     // Jacobians in Ceres are ordered by the parameter blocks:
00099     // jacobian[i] = [(dr_0 / dx_i)^T, ..., (dr_n / dx_i)^T].
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 }  // namespace
00134 
00135 ceres::CostFunction* CreateAutoDiffSpaCostFunction(
00136     const PoseGraphInterface::Constraint::Pose& observed_relative_pose) {
00137   return new ceres::AutoDiffCostFunction<SpaCostFunction2D, 3 /* residuals */,
00138                                          3 /* start pose variables */,
00139                                          3 /* end pose variables */>(
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 }  // namespace optimization
00149 }  // namespace mapping
00150 }  // namespace cartographer


cartographer
Author(s): The Cartographer Authors
autogenerated on Thu May 9 2019 02:27:36