cost_helpers_impl.h
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 
17 #ifndef CARTOGRAPHER_MAPPING_INTERNAL_OPTIMIZATION_COST_FUNCTIONS_COST_HELPERS_IMPL_H_
18 #define CARTOGRAPHER_MAPPING_INTERNAL_OPTIMIZATION_COST_FUNCTIONS_COST_HELPERS_IMPL_H_
19 
20 #include "Eigen/Core"
23 
24 namespace cartographer {
25 namespace mapping {
26 namespace optimization {
27 
28 template <typename T>
29 static std::array<T, 3> ComputeUnscaledError(
30  const transform::Rigid2d& relative_pose, const T* const start,
31  const T* const end) {
32  const T cos_theta_i = cos(start[2]);
33  const T sin_theta_i = sin(start[2]);
34  const T delta_x = end[0] - start[0];
35  const T delta_y = end[1] - start[1];
36  const T h[3] = {cos_theta_i * delta_x + sin_theta_i * delta_y,
37  -sin_theta_i * delta_x + cos_theta_i * delta_y,
38  end[2] - start[2]};
39  return {{T(relative_pose.translation().x()) - h[0],
40  T(relative_pose.translation().y()) - h[1],
42  T(relative_pose.rotation().angle()) - h[2])}};
43 }
44 
45 template <typename T>
46 std::array<T, 3> ScaleError(const std::array<T, 3>& error,
47  double translation_weight, double rotation_weight) {
48  // clang-format off
49  return {{
50  error[0] * translation_weight,
51  error[1] * translation_weight,
52  error[2] * rotation_weight
53  }};
54  // clang-format on
55 }
56 
57 template <typename T>
58 static std::array<T, 6> ComputeUnscaledError(
59  const transform::Rigid3d& relative_pose, const T* const start_rotation,
60  const T* const start_translation, const T* const end_rotation,
61  const T* const end_translation) {
62  const Eigen::Quaternion<T> R_i_inverse(start_rotation[0], -start_rotation[1],
63  -start_rotation[2],
64  -start_rotation[3]);
65 
66  const Eigen::Matrix<T, 3, 1> delta(end_translation[0] - start_translation[0],
67  end_translation[1] - start_translation[1],
68  end_translation[2] - start_translation[2]);
69  const Eigen::Matrix<T, 3, 1> h_translation = R_i_inverse * delta;
70 
71  const Eigen::Quaternion<T> h_rotation_inverse =
72  Eigen::Quaternion<T>(end_rotation[0], -end_rotation[1], -end_rotation[2],
73  -end_rotation[3]) *
74  Eigen::Quaternion<T>(start_rotation[0], start_rotation[1],
75  start_rotation[2], start_rotation[3]);
76 
77  const Eigen::Matrix<T, 3, 1> angle_axis_difference =
79  h_rotation_inverse * relative_pose.rotation().cast<T>());
80 
81  return {{T(relative_pose.translation().x()) - h_translation[0],
82  T(relative_pose.translation().y()) - h_translation[1],
83  T(relative_pose.translation().z()) - h_translation[2],
84  angle_axis_difference[0], angle_axis_difference[1],
85  angle_axis_difference[2]}};
86 }
87 
88 template <typename T>
89 std::array<T, 6> ScaleError(const std::array<T, 6>& error,
90  double translation_weight, double rotation_weight) {
91  // clang-format off
92  return {{
93  error[0] * translation_weight,
94  error[1] * translation_weight,
95  error[2] * translation_weight,
96  error[3] * rotation_weight,
97  error[4] * rotation_weight,
98  error[5] * rotation_weight
99  }};
100  // clang-format on
101 }
102 
103 // Eigen implementation of slerp is not compatible with Ceres on all supported
104 // platforms. Our own implementation is used instead.
105 template <typename T>
106 std::array<T, 4> SlerpQuaternions(const T* const start, const T* const end,
107  double factor) {
108  // Angle 'theta' is the half-angle "between" quaternions. It can be computed
109  // as the arccosine of their dot product.
110  const T cos_theta = start[0] * end[0] + start[1] * end[1] +
111  start[2] * end[2] + start[3] * end[3];
112  // Avoid using ::abs which would cast to integer.
113  const T abs_cos_theta = ceres::abs(cos_theta);
114  // If numerical error brings 'cos_theta' outside [-1 + epsilon, 1 - epsilon]
115  // interval, then the quaternions are likely to be collinear.
116  T prev_scale(1. - factor);
117  T next_scale(factor);
118  if (abs_cos_theta < T(1. - 1e-5)) {
119  const T theta = acos(abs_cos_theta);
120  const T sin_theta = sin(theta);
121  prev_scale = sin((1. - factor) * theta) / sin_theta;
122  next_scale = sin(factor * theta) / sin_theta;
123  }
124  if (cos_theta < T(0.)) {
125  next_scale = -next_scale;
126  }
127  return {{prev_scale * start[0] + next_scale * end[0],
128  prev_scale * start[1] + next_scale * end[1],
129  prev_scale * start[2] + next_scale * end[2],
130  prev_scale * start[3] + next_scale * end[3]}};
131 }
132 
133 template <typename T>
134 std::tuple<std::array<T, 4> /* rotation */, std::array<T, 3> /* translation */>
135 InterpolateNodes3D(const T* const prev_node_rotation,
136  const T* const prev_node_translation,
137  const T* const next_node_rotation,
138  const T* const next_node_translation,
139  const double interpolation_parameter) {
140  return std::make_tuple(
141  SlerpQuaternions(prev_node_rotation, next_node_rotation,
142  interpolation_parameter),
143  std::array<T, 3>{
144  {prev_node_translation[0] +
145  interpolation_parameter *
146  (next_node_translation[0] - prev_node_translation[0]),
147  prev_node_translation[1] +
148  interpolation_parameter *
149  (next_node_translation[1] - prev_node_translation[1]),
150  prev_node_translation[2] +
151  interpolation_parameter *
152  (next_node_translation[2] - prev_node_translation[2])}});
153 }
154 
155 template <typename T>
156 std::tuple<std::array<T, 4> /* rotation */, std::array<T, 3> /* translation */>
157 InterpolateNodes2D(const T* const prev_node_pose,
158  const Eigen::Quaterniond& prev_node_gravity_alignment,
159  const T* const next_node_pose,
160  const Eigen::Quaterniond& next_node_gravity_alignment,
161  const double interpolation_parameter) {
162  // The following is equivalent to (Embed3D(prev_node_pose) *
163  // Rigid3d::Rotation(prev_node_gravity_alignment)).rotation().
164  const Eigen::Quaternion<T> prev_quaternion(
165  (Eigen::AngleAxis<T>(prev_node_pose[2], Eigen::Matrix<T, 3, 1>::UnitZ()) *
166  prev_node_gravity_alignment.cast<T>())
167  .normalized());
168  const std::array<T, 4> prev_node_rotation = {
169  {prev_quaternion.w(), prev_quaternion.x(), prev_quaternion.y(),
170  prev_quaternion.z()}};
171 
172  // The following is equivalent to (Embed3D(next_node_pose) *
173  // Rigid3d::Rotation(next_node_gravity_alignment)).rotation().
174  const Eigen::Quaternion<T> next_quaternion(
175  (Eigen::AngleAxis<T>(next_node_pose[2], Eigen::Matrix<T, 3, 1>::UnitZ()) *
176  next_node_gravity_alignment.cast<T>())
177  .normalized());
178  const std::array<T, 4> next_node_rotation = {
179  {next_quaternion.w(), next_quaternion.x(), next_quaternion.y(),
180  next_quaternion.z()}};
181 
182  return std::make_tuple(
183  SlerpQuaternions(prev_node_rotation.data(), next_node_rotation.data(),
184  interpolation_parameter),
185  std::array<T, 3>{
186  {prev_node_pose[0] + interpolation_parameter *
187  (next_node_pose[0] - prev_node_pose[0]),
188  prev_node_pose[1] + interpolation_parameter *
189  (next_node_pose[1] - prev_node_pose[1]),
190  T(0)}});
191 }
192 
193 } // namespace optimization
194 } // namespace mapping
195 } // namespace cartographer
196 
197 #endif // CARTOGRAPHER_MAPPING_INTERNAL_OPTIMIZATION_COST_FUNCTIONS_COST_HELPERS_IMPL_H_
Eigen::Matrix< T, 3, 1 > RotationQuaternionToAngleAxisVector(const Eigen::Quaternion< T > &quaternion)
Definition: transform.h:60
const Quaternion & rotation() const
const Vector & translation() const
std::tuple< std::array< T, 4 >, std::array< T, 3 > > InterpolateNodes3D(const T *const prev_node_rotation, const T *const prev_node_translation, const T *const next_node_rotation, const T *const next_node_translation, const double interpolation_parameter)
std::array< T, 3 > ScaleError(const std::array< T, 3 > &error, double translation_weight, double rotation_weight)
const Vector & translation() const
std::tuple< std::array< T, 4 >, std::array< T, 3 > > InterpolateNodes2D(const T *const prev_node_pose, const Eigen::Quaterniond &prev_node_gravity_alignment, const T *const next_node_pose, const Eigen::Quaterniond &next_node_gravity_alignment, const double interpolation_parameter)
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)
std::array< T, 4 > SlerpQuaternions(const T *const start, const T *const end, double factor)


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