NASA Astrobee Robot Software  Astrobee Version:
Flight software for the Astrobee robots operating inside the International Space Station.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
residuals.h
Go to the documentation of this file.
1 /* Copyright (c) 2017, United States Government, as represented by the
2  * Administrator of the National Aeronautics and Space Administration.
3  *
4  * All rights reserved.
5  *
6  * The Astrobee platform is licensed under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with the
8  * License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations
16  * under the License.
17  */
18 #ifndef OPTIMIZATION_COMMON_RESIDUALS_H_
19 #define OPTIMIZATION_COMMON_RESIDUALS_H_
20 
22 
23 #include <Eigen/Core>
24 
25 #include <ceres/problem.h>
26 #include <ceres/jet.h>
27 #include <ceres/ceres.h>
28 #include <ceres/solver.h>
29 #include <ceres/cost_function.h>
30 #include <ceres/loss_function.h>
31 #include <ceres/autodiff_cost_function.h>
32 
33 namespace optimization_common {
35  public:
36  PointToPointError(const Eigen::Vector3d& source_t_point, const Eigen::Vector3d& target_t_point)
37  : source_t_point_(source_t_point), target_t_point_(target_t_point) {}
38 
39  template <typename T>
40  bool operator()(const T* target_T_source_data, T* point_to_point_error) const {
41  const auto target_T_source = Isometry3<T>(target_T_source_data);
42  // Compute error
43  const Eigen::Matrix<T, 3, 1> estimated_target_t_point = target_T_source * source_t_point_.cast<T>();
44  point_to_point_error[0] = estimated_target_t_point[0] - target_t_point_[0];
45  point_to_point_error[1] = estimated_target_t_point[1] - target_t_point_[1];
46  point_to_point_error[2] = estimated_target_t_point[2] - target_t_point_[2];
47  return true;
48  }
49 
50  static void AddCostFunction(const Eigen::Vector3d& source_t_point, const Eigen::Vector3d& target_t_point,
51  Eigen::Matrix<double, 6, 1>& target_T_source, ceres::Problem& problem) {
52  ceres::LossFunction* huber_loss = new ceres::HuberLoss(1.345);
53  ceres::CostFunction* point_to_point_cost_function =
54  new ceres::AutoDiffCostFunction<PointToPointError, 3, 6>(new PointToPointError(source_t_point, target_t_point));
55  problem.AddResidualBlock(point_to_point_cost_function, huber_loss, target_T_source.data());
56  }
57 
58  private:
59  Eigen::Vector3d source_t_point_;
60  Eigen::Vector3d target_t_point_;
61 };
62 
64  public:
65  PointToPlaneError(const Eigen::Vector3d& source_t_point, const Eigen::Vector3d& target_t_point,
66  const Eigen::Vector3d& target_normal)
67  : source_t_point_(source_t_point), target_t_point_(target_t_point), target_normal_(target_normal) {}
68 
69  template <typename T>
70  bool operator()(const T* target_T_source_data, T* point_to_plane_error) const {
71  const auto target_T_source = Isometry3<T>(target_T_source_data);
72  // Compute error
73  const Eigen::Matrix<T, 3, 1> estimated_target_t_point = target_T_source * source_t_point_.cast<T>();
74  const Eigen::Matrix<T, 3, 1> target_F_point_t_estimated_point =
75  estimated_target_t_point - target_t_point_.cast<T>();
76  point_to_plane_error[0] = target_F_point_t_estimated_point.dot(target_normal_.cast<T>());
77  return true;
78  }
79 
80  static void AddCostFunction(const Eigen::Vector3d& source_t_point, const Eigen::Vector3d& target_t_point,
81  const Eigen::Vector3d& target_normal, Eigen::Matrix<double, 6, 1>& target_T_source,
82  ceres::Problem& problem) {
83  ceres::LossFunction* huber_loss = new ceres::HuberLoss(1.345);
84  ceres::CostFunction* point_to_plane_cost_function = new ceres::AutoDiffCostFunction<PointToPlaneError, 1, 6>(
85  new PointToPlaneError(source_t_point, target_t_point, target_normal));
86  problem.AddResidualBlock(point_to_plane_cost_function, huber_loss, target_T_source.data());
87  }
88 
89  private:
90  Eigen::Vector3d source_t_point_;
91  Eigen::Vector3d target_t_point_;
92  Eigen::Vector3d target_normal_;
93 };
94 
96  public:
97  SymmetricPointToPlaneError(const Eigen::Vector3d& source_t_point, const Eigen::Vector3d& target_t_point,
98  const Eigen::Vector3d& source_normal, const Eigen::Vector3d& target_normal)
99  : source_t_point_(source_t_point),
100  target_t_point_(target_t_point),
101  source_normal_(source_normal),
102  target_normal_(target_normal) {}
103 
104  template <typename T>
105  bool operator()(const T* target_T_source_data, T* symmetric_point_to_plane_error) const {
106  const auto target_T_source = Isometry3<T>(target_T_source_data);
107  // Compute error
108  const Eigen::Matrix<T, 3, 1> estimated_target_t_point = target_T_source * source_t_point_.cast<T>();
109  const Eigen::Matrix<T, 3, 1> target_F_point_t_estimated_point =
110  estimated_target_t_point - target_t_point_.cast<T>();
111  const Eigen::Matrix<T, 3, 1> estimated_source_t_point = target_T_source.inverse() * target_t_point_.cast<T>();
112  const Eigen::Matrix<T, 3, 1> source_F_point_t_estimated_point =
113  estimated_source_t_point - source_t_point_.cast<T>();
114  symmetric_point_to_plane_error[0] = source_F_point_t_estimated_point.dot(source_normal_.cast<T>());
115  symmetric_point_to_plane_error[1] = target_F_point_t_estimated_point.dot(target_normal_.cast<T>());
116  return true;
117  }
118 
119  static void AddCostFunction(const Eigen::Vector3d& source_t_point, const Eigen::Vector3d& target_t_point,
120  const Eigen::Vector3d& source_normal, const Eigen::Vector3d& target_normal,
121  Eigen::Matrix<double, 6, 1>& target_T_source, ceres::Problem& problem) {
122  ceres::LossFunction* huber_loss = new ceres::HuberLoss(1.345);
123  ceres::CostFunction* symmetric_point_to_plane_cost_function =
124  new ceres::AutoDiffCostFunction<SymmetricPointToPlaneError, 2, 6>(
125  new SymmetricPointToPlaneError(source_t_point, target_t_point, source_normal, target_normal));
126  problem.AddResidualBlock(symmetric_point_to_plane_cost_function, huber_loss, target_T_source.data());
127  }
128 
129  private:
130  Eigen::Vector3d source_t_point_;
131  Eigen::Vector3d target_t_point_;
132  Eigen::Vector3d source_normal_;
133  Eigen::Vector3d target_normal_;
134 };
135 
136 template <typename DISTORTER>
138  public:
139  AffineReprojectionError(const Eigen::Vector2d& image_point, const Eigen::Vector3d& depth_cloud_F_point_3d)
140  : image_point_(image_point), depth_cloud_F_point_3d_(depth_cloud_F_point_3d) {}
141 
142  template <typename T>
143  bool operator()(const T* depth_image_A_depth_cloud_data, const T* intrinsics_data, const T* distortion_data,
144  T* reprojection_error) const {
145  // Handle type conversions
146  const auto intrinsics = Intrinsics<T>(intrinsics_data);
147  const auto depth_image_A_depth_cloud = Affine3<T>(depth_image_A_depth_cloud_data);
148 
149  // Compute error
150  const Eigen::Matrix<T, 3, 1> depth_image_F_point_3d = depth_image_A_depth_cloud * depth_cloud_F_point_3d_.cast<T>();
151  const Eigen::Matrix<T, 2, 1> undistorted_reprojected_point_3d = (intrinsics * depth_image_F_point_3d).hnormalized();
152  const Eigen::Matrix<T, 2, 1> distorted_reprojected_point_3d =
153  distorter_.Distort(distortion_data, intrinsics, undistorted_reprojected_point_3d);
154 
155  reprojection_error[0] = image_point_[0] - distorted_reprojected_point_3d[0];
156  reprojection_error[1] = image_point_[1] - distorted_reprojected_point_3d[1];
157  return true;
158  }
159 
160  static void AddCostFunction(const Eigen::Vector2d& image_point, const Eigen::Vector3d& point_3d,
161  Eigen::Matrix<double, 7, 1>& depth_image_A_depth_cloud_vector,
162  Eigen::Matrix<double, 4, 1>& intrinsics_vector, Eigen::VectorXd& distortion,
163  ceres::Problem& problem) {
164  ceres::LossFunction* huber_loss = new ceres::HuberLoss(1.345);
165  ceres::CostFunction* reprojection_cost_function =
166  new ceres::AutoDiffCostFunction<AffineReprojectionError<DISTORTER>, 2, 7, 4, DISTORTER::kNumParams>(
167  new AffineReprojectionError<DISTORTER>(image_point, point_3d));
168  problem.AddResidualBlock(reprojection_cost_function, huber_loss, depth_image_A_depth_cloud_vector.data(),
169  intrinsics_vector.data(), distortion.data());
170  }
171 
172  private:
173  Eigen::Vector2d image_point_;
174  Eigen::Vector3d depth_cloud_F_point_3d_;
175  DISTORTER distorter_;
176 };
177 
178 template <typename DISTORTER>
180  public:
181  ReprojectionError(const Eigen::Vector2d& image_point, const Eigen::Vector3d& target_t_point_3d)
182  : image_point_(image_point), target_t_point_3d_(target_t_point_3d) {}
183 
184  template <typename T>
185  bool operator()(const T* camera_T_target_data, const T* focal_lengths_data, const T* principal_points_data,
186  const T* distortion_data, T* reprojection_error) const {
187  // Handle type conversions
188  const auto intrinsics = Intrinsics<T>(focal_lengths_data, principal_points_data);
189  const auto camera_T_target = Isometry3<T>(camera_T_target_data);
190  // Compute error
191  const Eigen::Matrix<T, 3, 1> camera_t_point_3d = camera_T_target * target_t_point_3d_.cast<T>();
192  const Eigen::Matrix<T, 2, 1> undistorted_reprojected_point_3d = (intrinsics * camera_t_point_3d).hnormalized();
193  const Eigen::Matrix<T, 2, 1> distorted_reprojected_point_3d =
194  distorter_.Distort(distortion_data, intrinsics, undistorted_reprojected_point_3d);
195 
196  reprojection_error[0] = image_point_[0] - distorted_reprojected_point_3d[0];
197  reprojection_error[1] = image_point_[1] - distorted_reprojected_point_3d[1];
198  return true;
199  }
200 
201  static void AddCostFunction(const Eigen::Vector2d& image_point, const Eigen::Vector3d& point_3d,
202  Eigen::Matrix<double, 6, 1>& camera_T_target, Eigen::Vector2d& focal_lengths,
203  Eigen::Vector2d& principal_points, Eigen::VectorXd& distortion, ceres::Problem& problem,
204  const double scale_factor = 1, const double huber_threshold = 1.345) {
205  ceres::LossFunction* huber_loss = new ceres::HuberLoss(huber_threshold);
206  ceres::LossFunction* scaled_huber_loss = new ceres::ScaledLoss(huber_loss, scale_factor, ceres::TAKE_OWNERSHIP);
207  ceres::CostFunction* reprojection_cost_function =
208  new ceres::AutoDiffCostFunction<ReprojectionError<DISTORTER>, 2, 6, 2, 2, DISTORTER::kNumParams>(
209  new ReprojectionError<DISTORTER>(image_point, point_3d));
210  problem.AddResidualBlock(reprojection_cost_function, scaled_huber_loss, camera_T_target.data(),
211  focal_lengths.data(), principal_points.data(), distortion.data());
212  }
213 
214  private:
215  Eigen::Vector2d image_point_;
216  Eigen::Vector3d target_t_point_3d_;
217  DISTORTER distorter_;
218 };
219 } // namespace optimization_common
220 
221 #endif // OPTIMIZATION_COMMON_RESIDUALS_H_
optimization_common::PointToPointError
Definition: residuals.h:34
optimization_common::SymmetricPointToPlaneError
Definition: residuals.h:95
optimization_common::AffineReprojectionError::AddCostFunction
static void AddCostFunction(const Eigen::Vector2d &image_point, const Eigen::Vector3d &point_3d, Eigen::Matrix< double, 7, 1 > &depth_image_A_depth_cloud_vector, Eigen::Matrix< double, 4, 1 > &intrinsics_vector, Eigen::VectorXd &distortion, ceres::Problem &problem)
Definition: residuals.h:160
optimization_common::SymmetricPointToPlaneError::AddCostFunction
static void AddCostFunction(const Eigen::Vector3d &source_t_point, const Eigen::Vector3d &target_t_point, const Eigen::Vector3d &source_normal, const Eigen::Vector3d &target_normal, Eigen::Matrix< double, 6, 1 > &target_T_source, ceres::Problem &problem)
Definition: residuals.h:119
optimization_common::PointToPointError::PointToPointError
PointToPointError(const Eigen::Vector3d &source_t_point, const Eigen::Vector3d &target_t_point)
Definition: residuals.h:36
optimization_common::SymmetricPointToPlaneError::operator()
bool operator()(const T *target_T_source_data, T *symmetric_point_to_plane_error) const
Definition: residuals.h:105
optimization_common::ReprojectionError::operator()
bool operator()(const T *camera_T_target_data, const T *focal_lengths_data, const T *principal_points_data, const T *distortion_data, T *reprojection_error) const
Definition: residuals.h:185
optimization_common::AffineReprojectionError::AffineReprojectionError
AffineReprojectionError(const Eigen::Vector2d &image_point, const Eigen::Vector3d &depth_cloud_F_point_3d)
Definition: residuals.h:139
optimization_common::PointToPlaneError::operator()
bool operator()(const T *target_T_source_data, T *point_to_plane_error) const
Definition: residuals.h:70
optimization_common::PointToPointError::AddCostFunction
static void AddCostFunction(const Eigen::Vector3d &source_t_point, const Eigen::Vector3d &target_t_point, Eigen::Matrix< double, 6, 1 > &target_T_source, ceres::Problem &problem)
Definition: residuals.h:50
optimization_common::SymmetricPointToPlaneError::SymmetricPointToPlaneError
SymmetricPointToPlaneError(const Eigen::Vector3d &source_t_point, const Eigen::Vector3d &target_t_point, const Eigen::Vector3d &source_normal, const Eigen::Vector3d &target_normal)
Definition: residuals.h:97
optimization_common::PointToPointError::operator()
bool operator()(const T *target_T_source_data, T *point_to_point_error) const
Definition: residuals.h:40
point_cloud_common::Vector3d
Eigen::Vector3d Vector3d(const PointType &point)
Definition: utilities.h:328
optimization_common::AffineReprojectionError::operator()
bool operator()(const T *depth_image_A_depth_cloud_data, const T *intrinsics_data, const T *distortion_data, T *reprojection_error) const
Definition: residuals.h:143
optimization_common::ReprojectionError::ReprojectionError
ReprojectionError(const Eigen::Vector2d &image_point, const Eigen::Vector3d &target_t_point_3d)
Definition: residuals.h:181
optimization_common
Definition: optimization_params.h:23
optimization_common::PointToPlaneError::AddCostFunction
static void AddCostFunction(const Eigen::Vector3d &source_t_point, const Eigen::Vector3d &target_t_point, const Eigen::Vector3d &target_normal, Eigen::Matrix< double, 6, 1 > &target_T_source, ceres::Problem &problem)
Definition: residuals.h:80
optimization_common::AffineReprojectionError
Definition: residuals.h:137
utilities.h
optimization_common::ReprojectionError
Definition: residuals.h:179
optimization_common::PointToPlaneError::PointToPlaneError
PointToPlaneError(const Eigen::Vector3d &source_t_point, const Eigen::Vector3d &target_t_point, const Eigen::Vector3d &target_normal)
Definition: residuals.h:65
optimization_common::ReprojectionError::AddCostFunction
static void AddCostFunction(const Eigen::Vector2d &image_point, const Eigen::Vector3d &point_3d, Eigen::Matrix< double, 6, 1 > &camera_T_target, Eigen::Vector2d &focal_lengths, Eigen::Vector2d &principal_points, Eigen::VectorXd &distortion, ceres::Problem &problem, const double scale_factor=1, const double huber_threshold=1.345)
Definition: residuals.h:201
optimization_common::PointToPlaneError
Definition: residuals.h:63