Factor_ImageReprojCalib.cpp
Go to the documentation of this file.
1 /*
2  * OpenVINS: An Open Platform for Visual-Inertial Research
3  * Copyright (C) 2018-2023 Patrick Geneva
4  * Copyright (C) 2018-2023 Guoquan Huang
5  * Copyright (C) 2018-2023 OpenVINS Contributors
6  * Copyright (C) 2018-2019 Kevin Eckenhoff
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
23 
24 #include "utils/quat_ops.h"
25 
26 using namespace ov_init;
27 
28 Factor_ImageReprojCalib::Factor_ImageReprojCalib(const Eigen::Vector2d &uv_meas_, double pix_sigma_, bool is_fisheye_)
29  : uv_meas(uv_meas_), pix_sigma(pix_sigma_), is_fisheye(is_fisheye_) {
30 
31  // Square root information inverse
32  sqrtQ = Eigen::Matrix<double, 2, 2>::Identity();
33  sqrtQ(0, 0) *= 1.0 / pix_sigma;
34  sqrtQ(1, 1) *= 1.0 / pix_sigma;
35 
36  // Parameters we are a function of
37  set_num_residuals(2);
38  mutable_parameter_block_sizes()->push_back(4); // q_GtoIi
39  mutable_parameter_block_sizes()->push_back(3); // p_IiinG
40  mutable_parameter_block_sizes()->push_back(3); // p_FinG
41  mutable_parameter_block_sizes()->push_back(4); // q_ItoC
42  mutable_parameter_block_sizes()->push_back(3); // p_IinC
43  mutable_parameter_block_sizes()->push_back(8); // focal, center, distortion
44 }
45 
46 bool Factor_ImageReprojCalib::Evaluate(double const *const *parameters, double *residuals, double **jacobians) const {
47 
48  // Recover the current state from our parameters
49  Eigen::Vector4d q_GtoIi = Eigen::Map<const Eigen::Vector4d>(parameters[0]);
50  Eigen::Matrix3d R_GtoIi = ov_core::quat_2_Rot(q_GtoIi);
51  Eigen::Vector3d p_IiinG = Eigen::Map<const Eigen::Vector3d>(parameters[1]);
52  Eigen::Vector3d p_FinG = Eigen::Map<const Eigen::Vector3d>(parameters[2]);
53  Eigen::Vector4d q_ItoC = Eigen::Map<const Eigen::Vector4d>(parameters[3]);
54  Eigen::Matrix3d R_ItoC = ov_core::quat_2_Rot(q_ItoC);
55  Eigen::Vector3d p_IinC = Eigen::Map<const Eigen::Vector3d>(parameters[4]);
56 
57  // order: f_x & f_y & c_x & c_y & k_1 & k_2 & k_3 & k_4
58  Eigen::Matrix<double, 8, 1> camera_vals = Eigen::Map<const Eigen::Matrix<double, 8, 1>>(parameters[5]);
59 
60  // Transform the feature into the current camera frame of reference
61  Eigen::Vector3d p_FinIi = R_GtoIi * (p_FinG - p_IiinG);
62  Eigen::Vector3d p_FinCi = R_ItoC * p_FinIi + p_IinC;
63 
64  // Normalized projected feature bearing
65  Eigen::Vector2d uv_norm;
66  uv_norm << p_FinCi(0) / p_FinCi(2), p_FinCi(1) / p_FinCi(2);
67 
68  // Square-root information and gate
69  Eigen::Matrix<double, 2, 2> sqrtQ_gate = gate * sqrtQ;
70 
71  // Get the distorted raw image coordinate using the camera model
72  // Also if jacobians are requested, then compute derivatives
73  Eigen::Vector2d uv_dist;
74  Eigen::MatrixXd H_dz_dzn, H_dz_dzeta;
75  if (is_fisheye) {
76  ov_core::CamEqui cam(0, 0);
77  cam.set_value(camera_vals);
78  uv_dist = cam.distort_d(uv_norm);
79  if (jacobians) {
80  cam.compute_distort_jacobian(uv_norm, H_dz_dzn, H_dz_dzeta);
81  H_dz_dzn = sqrtQ_gate * H_dz_dzn;
82  H_dz_dzeta = sqrtQ_gate * H_dz_dzeta;
83  }
84  } else {
85  ov_core::CamRadtan cam(0, 0);
86  cam.set_value(camera_vals);
87  uv_dist = cam.distort_d(uv_norm);
88  if (jacobians) {
89  cam.compute_distort_jacobian(uv_norm, H_dz_dzn, H_dz_dzeta);
90  H_dz_dzn = sqrtQ_gate * H_dz_dzn;
91  H_dz_dzeta = sqrtQ_gate * H_dz_dzeta;
92  }
93  }
94 
95  // Compute residual
96  // NOTE: we make this negative ceres cost function is only min||f(x)||^2
97  // NOTE: thus since we have found the derivative of uv_meas = f(x) + n
98  // NOTE: we need to reformulate into a zero error constraint 0 = f(x) + n - uv_meas
99  // NOTE: if it was the other way (0 = uv_meas - f(x) - n) all the Jacobians would need to be flipped
100  Eigen::Vector2d res = uv_dist - uv_meas;
101  res = sqrtQ_gate * res;
102  residuals[0] = res(0);
103  residuals[1] = res(1);
104 
105  // Compute jacobians if requested by ceres
106  if (jacobians) {
107 
108  // Normalized coordinates in respect to projection function
109  Eigen::MatrixXd H_dzn_dpfc = Eigen::MatrixXd::Zero(2, 3);
110  H_dzn_dpfc << 1.0 / p_FinCi(2), 0, -p_FinCi(0) / std::pow(p_FinCi(2), 2), 0, 1.0 / p_FinCi(2), -p_FinCi(1) / std::pow(p_FinCi(2), 2);
111  Eigen::MatrixXd H_dz_dpfc = H_dz_dzn * H_dzn_dpfc;
112 
113  // Jacobian wrt q_GtoIi
114  if (jacobians[0]) {
115  Eigen::Map<Eigen::Matrix<double, 2, 4, Eigen::RowMajor>> jacobian(jacobians[0]);
116  jacobian.block(0, 0, 2, 3) = H_dz_dpfc * R_ItoC * ov_core::skew_x(p_FinIi);
117  jacobian.block(0, 3, 2, 1).setZero();
118  }
119 
120  // Jacobian wrt p_IiinG
121  if (jacobians[1]) {
122  Eigen::Map<Eigen::Matrix<double, 2, 3, Eigen::RowMajor>> jacobian(jacobians[1]);
123  jacobian.block(0, 0, 2, 3) = -H_dz_dpfc * R_ItoC * R_GtoIi;
124  }
125 
126  // Jacobian wrt feature p_FinG
127  if (jacobians[2]) {
128  Eigen::Map<Eigen::Matrix<double, 2, 3, Eigen::RowMajor>> jacobian(jacobians[2]);
129  jacobian.block(0, 0, 2, 3) = H_dz_dpfc * R_ItoC * R_GtoIi;
130  }
131 
132  // Jacbian wrt IMU-camera transform q_ItoC
133  if (jacobians[3]) {
134  Eigen::Map<Eigen::Matrix<double, 2, 4, Eigen::RowMajor>> jacobian(jacobians[3]);
135  jacobian.block(0, 0, 2, 3) = H_dz_dpfc * ov_core::skew_x(R_ItoC * p_FinIi);
136  jacobian.block(0, 3, 2, 1).setZero();
137  }
138 
139  // Jacbian wrt IMU-camera transform p_IinC
140  if (jacobians[4]) {
141  Eigen::Map<Eigen::Matrix<double, 2, 3, Eigen::RowMajor>> jacobian(jacobians[4]);
142  jacobian.block(0, 0, 2, 3) = H_dz_dpfc;
143  }
144 
145  // Jacbian wrt camera intrinsic
146  if (jacobians[5]) {
147  Eigen::Map<Eigen::Matrix<double, 2, 8, Eigen::RowMajor>> jacobian(jacobians[5]);
148  jacobian.block(0, 0, 2, 8) = H_dz_dzeta;
149  }
150  }
151  return true;
152 }
ov_init::Factor_ImageReprojCalib::Evaluate
bool Evaluate(double const *const *parameters, double *residuals, double **jacobians) const override
Error residual and Jacobian calculation.
Definition: Factor_ImageReprojCalib.cpp:46
ov_core::skew_x
Eigen::Matrix< double, 3, 3 > skew_x(const Eigen::Matrix< double, 3, 1 > &w)
quat_ops.h
ov_init::Factor_ImageReprojCalib::pix_sigma
double pix_sigma
Definition: Factor_ImageReprojCalib.h:47
ov_core::CamEqui::compute_distort_jacobian
void compute_distort_jacobian(const Eigen::Vector2d &uv_norm, Eigen::MatrixXd &H_dz_dzn, Eigen::MatrixXd &H_dz_dzeta) override
ov_core::CamRadtan
ov_init::Factor_ImageReprojCalib::gate
double gate
Definition: Factor_ImageReprojCalib.h:54
ov_core::CamEqui
ov_core::CamBase::set_value
virtual void set_value(const Eigen::MatrixXd &calib)
ov_core::CamBase::distort_d
Eigen::Vector2d distort_d(const Eigen::Vector2d &uv_norm)
ov_init
State initialization code.
Definition: Factor_GenericPrior.h:27
ov_init::Factor_ImageReprojCalib::is_fisheye
bool is_fisheye
Definition: Factor_ImageReprojCalib.h:51
ov_core::quat_2_Rot
Eigen::Matrix< double, 3, 3 > quat_2_Rot(const Eigen::Matrix< double, 4, 1 > &q)
ov_init::Factor_ImageReprojCalib::Factor_ImageReprojCalib
Factor_ImageReprojCalib(const Eigen::Vector2d &uv_meas_, double pix_sigma_, bool is_fisheye_)
Default constructor.
Definition: Factor_ImageReprojCalib.cpp:28
ov_init::Factor_ImageReprojCalib::sqrtQ
Eigen::Matrix< double, 2, 2 > sqrtQ
Definition: Factor_ImageReprojCalib.h:48
ov_init::Factor_ImageReprojCalib::uv_meas
Eigen::Vector2d uv_meas
Definition: Factor_ImageReprojCalib.h:44
Factor_ImageReprojCalib.h
ov_core::CamRadtan::compute_distort_jacobian
void compute_distort_jacobian(const Eigen::Vector2d &uv_norm, Eigen::MatrixXd &H_dz_dzn, Eigen::MatrixXd &H_dz_dzeta) override


ov_init
Author(s): Patrick Geneva , Kevin Eckenhoff , Guoquan Huang
autogenerated on Mon Dec 16 2024 03:06:51