spa_cost_function_2d.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2018 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 #include <array>
20 
21 #include "Eigen/Core"
22 #include "Eigen/Geometry"
27 #include "ceres/jet.h"
28 
29 namespace cartographer {
30 namespace mapping {
31 namespace optimization {
32 namespace {
33 
34 class SpaCostFunction2D {
35  public:
36  explicit SpaCostFunction2D(
37  const PoseGraphInterface::Constraint::Pose& observed_relative_pose)
38  : observed_relative_pose_(observed_relative_pose) {}
39 
40  template <typename T>
41  bool operator()(const T* const start_pose, const T* const end_pose,
42  T* e) const {
43  const std::array<T, 3> error =
46  start_pose, end_pose),
47  observed_relative_pose_.translation_weight,
48  observed_relative_pose_.rotation_weight);
49  std::copy(std::begin(error), std::end(error), e);
50  return true;
51  }
52 
53  private:
54  const PoseGraphInterface::Constraint::Pose observed_relative_pose_;
55 };
56 
57 class AnalyticalSpaCostFunction2D
58  : public ceres::SizedCostFunction<3 /* number of residuals */,
59  3 /* size of start pose */,
60  3 /* size of end pose */> {
61  public:
62  explicit AnalyticalSpaCostFunction2D(
63  const PoseGraphInterface::Constraint::Pose& constraint_pose)
64  : observed_relative_pose_(transform::Project2D(constraint_pose.zbar_ij)),
65  translation_weight_(constraint_pose.translation_weight),
66  rotation_weight_(constraint_pose.rotation_weight) {}
67  virtual ~AnalyticalSpaCostFunction2D() {}
68 
69  bool Evaluate(double const* const* parameters, double* residuals,
70  double** jacobians) const override {
71  double const* start = parameters[0];
72  double const* end = parameters[1];
73 
74  const double cos_start_rotation = cos(start[2]);
75  const double sin_start_rotation = sin(start[2]);
76  const double delta_x = end[0] - start[0];
77  const double delta_y = end[1] - start[1];
78 
79  residuals[0] =
81  (observed_relative_pose_.translation().x() -
82  (cos_start_rotation * delta_x + sin_start_rotation * delta_y));
83  residuals[1] =
85  (observed_relative_pose_.translation().y() -
86  (-sin_start_rotation * delta_x + cos_start_rotation * delta_y));
87  residuals[2] =
90  observed_relative_pose_.rotation().angle() - (end[2] - start[2]));
91  if (jacobians == NULL) return true;
92 
93  const double weighted_cos_start_rotation =
94  translation_weight_ * cos_start_rotation;
95  const double weighted_sin_start_rotation =
96  translation_weight_ * sin_start_rotation;
97 
98  // Jacobians in Ceres are ordered by the parameter blocks:
99  // jacobian[i] = [(dr_0 / dx_i)^T, ..., (dr_n / dx_i)^T].
100  if (jacobians[0] != NULL) {
101  jacobians[0][0] = weighted_cos_start_rotation;
102  jacobians[0][1] = weighted_sin_start_rotation;
103  jacobians[0][2] = weighted_sin_start_rotation * delta_x -
104  weighted_cos_start_rotation * delta_y;
105  jacobians[0][3] = -weighted_sin_start_rotation;
106  jacobians[0][4] = weighted_cos_start_rotation;
107  jacobians[0][5] = weighted_cos_start_rotation * delta_x +
108  weighted_sin_start_rotation * delta_y;
109  jacobians[0][6] = 0;
110  jacobians[0][7] = 0;
111  jacobians[0][8] = rotation_weight_;
112  }
113  if (jacobians[1] != NULL) {
114  jacobians[1][0] = -weighted_cos_start_rotation;
115  jacobians[1][1] = -weighted_sin_start_rotation;
116  jacobians[1][2] = 0;
117  jacobians[1][3] = weighted_sin_start_rotation;
118  jacobians[1][4] = -weighted_cos_start_rotation;
119  jacobians[1][5] = 0;
120  jacobians[1][6] = 0;
121  jacobians[1][7] = 0;
122  jacobians[1][8] = -rotation_weight_;
123  }
124  return true;
125  }
126 
127  private:
129  const double translation_weight_;
130  const double rotation_weight_;
131 };
132 
133 } // namespace
134 
135 ceres::CostFunction* CreateAutoDiffSpaCostFunction(
136  const PoseGraphInterface::Constraint::Pose& observed_relative_pose) {
137  return new ceres::AutoDiffCostFunction<SpaCostFunction2D, 3 /* residuals */,
138  3 /* start pose variables */,
139  3 /* end pose variables */>(
140  new SpaCostFunction2D(observed_relative_pose));
141 }
142 
143 ceres::CostFunction* CreateAnalyticalSpaCostFunction(
144  const PoseGraphInterface::Constraint::Pose& observed_relative_pose) {
145  return new AnalyticalSpaCostFunction2D(observed_relative_pose);
146 }
147 
148 } // namespace optimization
149 } // namespace mapping
150 } // namespace cartographer
const PoseGraphInterface::Constraint::Pose observed_relative_pose_
ceres::CostFunction * CreateAutoDiffSpaCostFunction(const PoseGraphInterface::Constraint::Pose &observed_relative_pose)
const double translation_weight_
Rigid2< T > Project2D(const Rigid3< T > &transform)
Definition: transform.h:103
Rigid2< double > Rigid2d
const double rotation_weight_
ceres::CostFunction * CreateAnalyticalSpaCostFunction(const PoseGraphInterface::Constraint::Pose &observed_relative_pose)
std::array< T, 3 > ScaleError(const std::array< T, 3 > &error, double translation_weight, double rotation_weight)
T NormalizeAngleDifference(T difference)
Definition: math.h:62
static std::array< T, 3 > ComputeUnscaledError(const transform::Rigid2d &relative_pose, const T *const start, const T *const end)


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58