32 void UpdaterHelper::get_feature_jacobian_representation(std::shared_ptr<State> state,
UpdaterHelperFeature &feature, Eigen::MatrixXd &H_f,
33 std::vector<Eigen::MatrixXd> &H_x, std::vector<std::shared_ptr<Type>> &x_order) {
43 if (feature.
feat_representation == LandmarkRepresentation::Representation::GLOBAL_FULL_INVERSE_DEPTH) {
46 Eigen::Matrix<double, 3, 1> p_FinG = (state->_options.do_fej) ? feature.
p_FinG_fej : feature.
p_FinG;
49 double g_rho = 1 / p_FinG.norm();
50 double g_phi = std::acos(g_rho * p_FinG(2));
52 double g_theta = std::atan2(p_FinG(1), p_FinG(0));
53 Eigen::Matrix<double, 3, 1> p_invFinG;
54 p_invFinG(0) = g_theta;
59 double sin_th = std::sin(p_invFinG(0, 0));
60 double cos_th = std::cos(p_invFinG(0, 0));
61 double sin_phi = std::sin(p_invFinG(1, 0));
62 double cos_phi = std::cos(p_invFinG(1, 0));
63 double rho = p_invFinG(2, 0);
67 H_f << -(1.0 / rho) * sin_th * sin_phi, (1.0 / rho) * cos_th * cos_phi, -(1.0 / (rho * rho)) * cos_th * sin_phi,
68 (1.0 / rho) * cos_th * sin_phi, (1.0 / rho) * sin_th * cos_phi, -(1.0 / (rho * rho)) * sin_th * sin_phi, 0.0,
69 -(1.0 / rho) * sin_phi, -(1.0 / (rho * rho)) * cos_phi;
81 Eigen::Matrix3d R_ItoC = state->_calib_IMUtoCAM.at(feature.
anchor_cam_id)->Rot();
82 Eigen::Vector3d p_IinC = state->_calib_IMUtoCAM.at(feature.
anchor_cam_id)->pos();
85 Eigen::Vector3d p_FinA = feature.
p_FinA;
89 if (state->_options.do_fej) {
91 Eigen::Vector3d p_FinG_best = R_GtoI.transpose() * R_ItoC.transpose() * (feature.
p_FinA - p_IinC) + p_IinG;
95 p_FinA = (R_GtoI.transpose() * R_ItoC.transpose()).transpose() * (p_FinG_best - p_IinG) + p_IinC;
97 Eigen::Matrix3d R_CtoG = R_GtoI.transpose() * R_ItoC.transpose();
100 Eigen::Matrix<double, 3, 6> H_anc;
101 H_anc.block(0, 0, 3, 3).noalias() = -R_GtoI.transpose() *
skew_x(R_ItoC.transpose() * (p_FinA - p_IinC));
102 H_anc.block(0, 3, 3, 3).setIdentity();
106 H_x.push_back(H_anc);
109 if (state->_options.do_calib_camera_pose) {
110 Eigen::Matrix<double, 3, 6> H_calib;
111 H_calib.block(0, 0, 3, 3).noalias() = -R_CtoG *
skew_x(p_FinA - p_IinC);
112 H_calib.block(0, 3, 3, 3) = -R_CtoG;
113 x_order.push_back(state->_calib_IMUtoCAM.at(feature.
anchor_cam_id));
114 H_x.push_back(H_calib);
124 if (feature.
feat_representation == LandmarkRepresentation::Representation::ANCHORED_FULL_INVERSE_DEPTH) {
127 double a_rho = 1 / p_FinA.norm();
128 double a_phi = std::acos(a_rho * p_FinA(2));
129 double a_theta = std::atan2(p_FinA(1), p_FinA(0));
130 Eigen::Matrix<double, 3, 1> p_invFinA;
131 p_invFinA(0) = a_theta;
132 p_invFinA(1) = a_phi;
133 p_invFinA(2) = a_rho;
136 double sin_th = std::sin(p_invFinA(0, 0));
137 double cos_th = std::cos(p_invFinA(0, 0));
138 double sin_phi = std::sin(p_invFinA(1, 0));
139 double cos_phi = std::cos(p_invFinA(1, 0));
140 double rho = p_invFinA(2, 0);
144 Eigen::Matrix<double, 3, 3> d_pfinA_dpinv;
145 d_pfinA_dpinv << -(1.0 / rho) * sin_th * sin_phi, (1.0 / rho) * cos_th * cos_phi, -(1.0 / (rho * rho)) * cos_th * sin_phi,
146 (1.0 / rho) * cos_th * sin_phi, (1.0 / rho) * sin_th * cos_phi, -(1.0 / (rho * rho)) * sin_th * sin_phi, 0.0,
147 -(1.0 / rho) * sin_phi, -(1.0 / (rho * rho)) * cos_phi;
148 H_f = R_CtoG * d_pfinA_dpinv;
153 if (feature.
feat_representation == LandmarkRepresentation::Representation::ANCHORED_MSCKF_INVERSE_DEPTH) {
156 Eigen::Matrix<double, 3, 1> p_invFinA_MSCKF;
157 p_invFinA_MSCKF(0) = p_FinA(0) / p_FinA(2);
158 p_invFinA_MSCKF(1) = p_FinA(1) / p_FinA(2);
159 p_invFinA_MSCKF(2) = 1 / p_FinA(2);
162 double alpha = p_invFinA_MSCKF(0, 0);
163 double beta = p_invFinA_MSCKF(1, 0);
164 double rho = p_invFinA_MSCKF(2, 0);
167 Eigen::Matrix<double, 3, 3> d_pfinA_dpinv;
168 d_pfinA_dpinv << (1.0 / rho), 0.0, -(1.0 / (rho * rho)) * alpha, 0.0, (1.0 / rho), -(1.0 / (rho * rho)) * beta, 0.0, 0.0,
169 -(1.0 / (rho * rho));
170 H_f = R_CtoG * d_pfinA_dpinv;
175 if (feature.
feat_representation == LandmarkRepresentation::Representation::ANCHORED_INVERSE_DEPTH_SINGLE) {
178 double rho = 1.0 / p_FinA(2);
179 Eigen::Vector3d bearing = rho * p_FinA;
182 Eigen::Vector3d d_pfinA_drho;
183 d_pfinA_drho << -(1.0 / (rho * rho)) * bearing;
184 H_f = R_CtoG * d_pfinA_drho;
192 void UpdaterHelper::get_feature_jacobian_full(std::shared_ptr<State> state,
UpdaterHelperFeature &feature, Eigen::MatrixXd &H_f,
193 Eigen::MatrixXd &H_x, Eigen::VectorXd &res, std::vector<std::shared_ptr<Type>> &x_order) {
198 total_meas += (int)pair.second.size();
203 std::unordered_map<std::shared_ptr<Type>,
size_t> map_hx;
207 std::shared_ptr<PoseJPL> calibration = state->_calib_IMUtoCAM.at(pair.first);
208 std::shared_ptr<Vec> distortion = state->_cam_intrinsics.at(pair.first);
211 if (state->_options.do_calib_camera_pose) {
212 map_hx.insert({calibration, total_hx});
213 x_order.push_back(calibration);
214 total_hx += calibration->size();
218 if (state->_options.do_calib_camera_intrinsics) {
219 map_hx.insert({distortion, total_hx});
220 x_order.push_back(distortion);
221 total_hx += distortion->size();
225 for (
size_t m = 0; m < feature.
timestamps[pair.first].size(); m++) {
228 std::shared_ptr<PoseJPL> clone_Ci = state->_clones_IMU.at(feature.
timestamps[pair.first].at(m));
229 if (map_hx.find(clone_Ci) == map_hx.end()) {
230 map_hx.insert({clone_Ci, total_hx});
231 x_order.push_back(clone_Ci);
232 total_hx += clone_Ci->size();
245 if (map_hx.find(clone_Ai) == map_hx.end()) {
246 map_hx.insert({clone_Ai, total_hx});
247 x_order.push_back(clone_Ai);
248 total_hx += clone_Ai->size();
252 if (state->_options.do_calib_camera_pose) {
254 std::shared_ptr<PoseJPL> clone_calib = state->_calib_IMUtoCAM.at(feature.
anchor_cam_id);
255 if (map_hx.find(clone_calib) == map_hx.end()) {
256 map_hx.insert({clone_calib, total_hx});
257 x_order.push_back(clone_calib);
258 total_hx += clone_calib->size();
268 Eigen::Vector3d p_FinG = feature.
p_FinG;
273 Eigen::Matrix3d R_ItoC = state->_calib_IMUtoCAM.at(feature.
anchor_cam_id)->Rot();
274 Eigen::Vector3d p_IinC = state->_calib_IMUtoCAM.at(feature.
anchor_cam_id)->pos();
279 p_FinG = R_GtoI.transpose() * R_ItoC.transpose() * (feature.
p_FinA - p_IinC) + p_IinG;
284 Eigen::Vector3d p_FinG_fej = feature.
p_FinG_fej;
294 int jacobsize = (feature.
feat_representation != LandmarkRepresentation::Representation::ANCHORED_INVERSE_DEPTH_SINGLE) ? 3 : 1;
295 res = Eigen::VectorXd::Zero(2 * total_meas);
296 H_f = Eigen::MatrixXd::Zero(2 * total_meas, jacobsize);
297 H_x = Eigen::MatrixXd::Zero(2 * total_meas, total_hx);
301 Eigen::MatrixXd dpfg_dlambda;
302 std::vector<Eigen::MatrixXd> dpfg_dx;
303 std::vector<std::shared_ptr<Type>> dpfg_dx_order;
304 UpdaterHelper::get_feature_jacobian_representation(state, feature, dpfg_dlambda, dpfg_dx, dpfg_dx_order);
308 for (
auto &type : dpfg_dx_order) {
309 assert(map_hx.find(type) != map_hx.end());
317 std::shared_ptr<Vec> distortion = state->_cam_intrinsics.at(pair.first);
318 std::shared_ptr<PoseJPL> calibration = state->_calib_IMUtoCAM.at(pair.first);
319 Eigen::Matrix3d R_ItoC = calibration->Rot();
320 Eigen::Vector3d p_IinC = calibration->pos();
323 for (
size_t m = 0; m < feature.
timestamps[pair.first].size(); m++) {
329 std::shared_ptr<PoseJPL> clone_Ii = state->_clones_IMU.at(feature.
timestamps[pair.first].at(m));
330 Eigen::Matrix3d R_GtoIi = clone_Ii->Rot();
331 Eigen::Vector3d p_IiinG = clone_Ii->pos();
334 Eigen::Vector3d p_FinIi = R_GtoIi * (p_FinG - p_IiinG);
337 Eigen::Vector3d p_FinCi = R_ItoC * p_FinIi + p_IinC;
338 Eigen::Vector2d uv_norm;
339 uv_norm << p_FinCi(0) / p_FinCi(2), p_FinCi(1) / p_FinCi(2);
342 Eigen::Vector2d uv_dist;
343 uv_dist = state->_cam_intrinsics_cameras.at(pair.first)->distort_d(uv_norm);
346 Eigen::Vector2d uv_m;
347 uv_m << (double)feature.
uvs[pair.first].at(m)(0), (
double)feature.
uvs[pair.first].at(m)(1);
348 res.block(2 * c, 0, 2, 1) = uv_m - uv_dist;
354 if (state->_options.do_fej) {
355 R_GtoIi = clone_Ii->Rot_fej();
356 p_IiinG = clone_Ii->pos_fej();
359 p_FinIi = R_GtoIi * (p_FinG_fej - p_IiinG);
360 p_FinCi = R_ItoC * p_FinIi + p_IinC;
366 Eigen::MatrixXd dz_dzn, dz_dzeta;
367 state->_cam_intrinsics_cameras.at(pair.first)->compute_distort_jacobian(uv_norm, dz_dzn, dz_dzeta);
370 Eigen::MatrixXd dzn_dpfc = Eigen::MatrixXd::Zero(2, 3);
371 dzn_dpfc << 1 / p_FinCi(2), 0, -p_FinCi(0) / (p_FinCi(2) * p_FinCi(2)), 0, 1 / p_FinCi(2), -p_FinCi(1) / (p_FinCi(2) * p_FinCi(2));
374 Eigen::MatrixXd dpfc_dpfg = R_ItoC * R_GtoIi;
377 Eigen::MatrixXd dpfc_dclone = Eigen::MatrixXd::Zero(3, 6);
378 dpfc_dclone.block(0, 0, 3, 3).noalias() = R_ItoC *
skew_x(p_FinIi);
379 dpfc_dclone.block(0, 3, 3, 3) = -dpfc_dpfg;
385 Eigen::MatrixXd dz_dpfc = dz_dzn * dzn_dpfc;
386 Eigen::MatrixXd dz_dpfg = dz_dpfc * dpfc_dpfg;
389 H_f.block(2 * c, 0, 2, H_f.cols()).noalias() = dz_dpfg * dpfg_dlambda;
392 H_x.block(2 * c, map_hx[clone_Ii], 2, clone_Ii->size()).noalias() = dz_dpfc * dpfc_dclone;
396 for (
size_t i = 0; i < dpfg_dx_order.size(); i++) {
397 H_x.block(2 * c, map_hx[dpfg_dx_order.at(i)], 2, dpfg_dx_order.at(i)->size()).noalias() += dz_dpfg * dpfg_dx.at(i);
404 if (state->_options.do_calib_camera_pose) {
407 Eigen::MatrixXd dpfc_dcalib = Eigen::MatrixXd::Zero(3, 6);
408 dpfc_dcalib.block(0, 0, 3, 3) =
skew_x(p_FinCi - p_IinC);
409 dpfc_dcalib.block(0, 3, 3, 3) = Eigen::Matrix<double, 3, 3>::Identity();
412 H_x.block(2 * c, map_hx[calibration], 2, calibration->size()).noalias() += dz_dpfc * dpfc_dcalib;
416 if (state->_options.do_calib_camera_intrinsics) {
417 H_x.block(2 * c, map_hx[distortion], 2, distortion->size()) = dz_dzeta;
426 void UpdaterHelper::nullspace_project_inplace(Eigen::MatrixXd &H_f, Eigen::MatrixXd &H_x, Eigen::VectorXd &res) {
432 Eigen::JacobiRotation<double> tempHo_GR;
433 for (
int n = 0; n < H_f.cols(); ++n) {
434 for (
int m = (
int)H_f.rows() - 1; m > n; m--) {
436 tempHo_GR.makeGivens(H_f(m - 1, n), H_f(m, n));
440 (H_f.block(m - 1, n, 2, H_f.cols() - n)).applyOnTheLeft(0, 1, tempHo_GR.adjoint());
441 (H_x.block(m - 1, 0, 2, H_x.cols())).applyOnTheLeft(0, 1, tempHo_GR.adjoint());
442 (res.block(m - 1, 0, 2, 1)).applyOnTheLeft(0, 1, tempHo_GR.adjoint());
449 H_x = H_x.block(H_f.cols(), 0, H_x.rows() - H_f.cols(), H_x.cols()).eval();
450 res = res.block(H_f.cols(), 0, res.rows() - H_f.cols(), res.cols()).eval();
453 assert(H_x.rows() == res.rows());
456 void UpdaterHelper::measurement_compress_inplace(Eigen::MatrixXd &H_x, Eigen::VectorXd &res) {
459 if (H_x.rows() <= H_x.cols())
466 Eigen::JacobiRotation<double> tempHo_GR;
467 for (
int n = 0; n < H_x.cols(); n++) {
468 for (
int m = (
int)H_x.rows() - 1; m > n; m--) {
470 tempHo_GR.makeGivens(H_x(m - 1, n), H_x(m, n));
474 (H_x.block(m - 1, n, 2, H_x.cols() - n)).applyOnTheLeft(0, 1, tempHo_GR.adjoint());
475 (res.block(m - 1, 0, 2, 1)).applyOnTheLeft(0, 1, tempHo_GR.adjoint());
481 int r = std::min(H_x.rows(), H_x.cols());
484 assert(r <= H_x.rows());
485 H_x.conservativeResize(r, H_x.cols());
486 res.conservativeResize(r, res.cols());