NASA Astrobee Robot Software  0.19.1
Flight software for the Astrobee robots operating inside the International Space Station.
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