31 std::unordered_map<
size_t, std::unordered_map<double, ClonePose>> &clonesCAM) {
36 size_t anchor_most_meas = 0;
38 for (
auto const &pair : feat->timestamps) {
39 total_meas += (int)pair.second.size();
40 if (pair.second.size() > most_meas) {
41 anchor_most_meas = pair.first;
42 most_meas = pair.second.size();
45 feat->anchor_cam_id = anchor_most_meas;
46 feat->anchor_clone_timestamp = feat->timestamps.at(feat->anchor_cam_id).back();
49 Eigen::Matrix3d A = Eigen::Matrix3d::Zero();
50 Eigen::Vector3d b = Eigen::Vector3d::Zero();
53 ClonePose anchorclone = clonesCAM.at(feat->anchor_cam_id).at(feat->anchor_clone_timestamp);
54 const Eigen::Matrix<double, 3, 3> &R_GtoA = anchorclone.
Rot();
55 const Eigen::Matrix<double, 3, 1> &p_AinG = anchorclone.
pos();
58 for (
auto const &pair : feat->timestamps) {
61 for (
size_t m = 0; m < feat->timestamps.at(pair.first).size(); m++) {
64 const Eigen::Matrix<double, 3, 3> &R_GtoCi = clonesCAM.at(pair.first).at(feat->timestamps.at(pair.first).at(m)).Rot();
65 const Eigen::Matrix<double, 3, 1> &p_CiinG = clonesCAM.at(pair.first).at(feat->timestamps.at(pair.first).at(m)).pos();
68 Eigen::Matrix<double, 3, 3> R_AtoCi;
69 R_AtoCi.noalias() = R_GtoCi * R_GtoA.transpose();
70 Eigen::Matrix<double, 3, 1> p_CiinA;
71 p_CiinA.noalias() = R_GtoA * (p_CiinG - p_AinG);
74 Eigen::Matrix<double, 3, 1> b_i;
75 b_i << feat->uvs_norm.at(pair.first).at(m)(0), feat->uvs_norm.at(pair.first).at(m)(1), 1;
76 b_i = R_AtoCi.transpose() * b_i;
77 b_i = b_i / b_i.norm();
78 Eigen::Matrix3d Bperp =
skew_x(b_i);
81 Eigen::Matrix3d Ai = Bperp.transpose() * Bperp;
88 Eigen::MatrixXd p_f = A.colPivHouseholderQr().solve(b);
91 Eigen::JacobiSVD<Eigen::Matrix3d> svd(A);
92 Eigen::MatrixXd singularValues;
93 singularValues.resize(svd.singularValues().rows(), 1);
94 singularValues = svd.singularValues();
95 double condA = singularValues(0, 0) / singularValues(singularValues.rows() - 1, 0);
104 std::isnan(p_f.norm())) {
110 feat->p_FinG = R_GtoA.transpose() * feat->p_FinA + p_AinG;
115 std::unordered_map<
size_t, std::unordered_map<double, ClonePose>> &clonesCAM) {
120 size_t anchor_most_meas = 0;
121 size_t most_meas = 0;
122 for (
auto const &pair : feat->timestamps) {
123 total_meas += (int)pair.second.size();
124 if (pair.second.size() > most_meas) {
125 anchor_most_meas = pair.first;
126 most_meas = pair.second.size();
129 feat->anchor_cam_id = anchor_most_meas;
130 feat->anchor_clone_timestamp = feat->timestamps.at(feat->anchor_cam_id).back();
131 size_t idx_anchor_bearing = feat->timestamps.at(feat->anchor_cam_id).size() - 1;
138 ClonePose anchorclone = clonesCAM.at(feat->anchor_cam_id).at(feat->anchor_clone_timestamp);
139 const Eigen::Matrix<double, 3, 3> &R_GtoA = anchorclone.
Rot();
140 const Eigen::Matrix<double, 3, 1> &p_AinG = anchorclone.
pos();
143 Eigen::Matrix<double, 3, 1> bearing_inA;
144 bearing_inA << feat->uvs_norm.at(feat->anchor_cam_id).at(idx_anchor_bearing)(0),
145 feat->uvs_norm.at(feat->anchor_cam_id).at(idx_anchor_bearing)(1), 1;
146 bearing_inA = bearing_inA / bearing_inA.norm();
149 for (
auto const &pair : feat->timestamps) {
152 for (
size_t m = 0; m < feat->timestamps.at(pair.first).size(); m++) {
155 if ((
int)pair.first == feat->anchor_cam_id && m == idx_anchor_bearing)
159 const Eigen::Matrix<double, 3, 3> &R_GtoCi = clonesCAM.at(pair.first).at(feat->timestamps.at(pair.first).at(m)).Rot();
160 const Eigen::Matrix<double, 3, 1> &p_CiinG = clonesCAM.at(pair.first).at(feat->timestamps.at(pair.first).at(m)).pos();
163 Eigen::Matrix<double, 3, 3> R_AtoCi;
164 R_AtoCi.noalias() = R_GtoCi * R_GtoA.transpose();
165 Eigen::Matrix<double, 3, 1> p_CiinA;
166 p_CiinA.noalias() = R_GtoA * (p_CiinG - p_AinG);
169 Eigen::Matrix<double, 3, 1> b_i;
170 b_i << feat->uvs_norm.at(pair.first).at(m)(0), feat->uvs_norm.at(pair.first).at(m)(1), 1;
171 b_i = R_AtoCi.transpose() * b_i;
172 b_i = b_i / b_i.norm();
173 Eigen::Matrix3d Bperp =
skew_x(b_i);
176 Eigen::Vector3d BperpBanchor = Bperp * bearing_inA;
177 A += BperpBanchor.dot(BperpBanchor);
178 b += BperpBanchor.dot(Bperp * p_CiinA);
183 double depth = b / A;
184 Eigen::MatrixXd p_f = depth * bearing_inA;
193 feat->p_FinG = R_GtoA.transpose() * feat->p_FinA + p_AinG;
198 std::unordered_map<
size_t, std::unordered_map<double, ClonePose>> &clonesCAM) {
201 double rho = 1 / feat->p_FinA(2);
202 double alpha = feat->p_FinA(0) / feat->p_FinA(2);
203 double beta = feat->p_FinA(1) / feat->p_FinA(2);
211 bool recompute =
true;
212 Eigen::Matrix<double, 3, 3> Hess = Eigen::Matrix<double, 3, 3>::Zero();
213 Eigen::Matrix<double, 3, 1> grad = Eigen::Matrix<double, 3, 1>::Zero();
216 double cost_old =
compute_error(clonesCAM, feat, alpha, beta, rho);
219 const Eigen::Matrix<double, 3, 3> &R_GtoA = clonesCAM.at(feat->anchor_cam_id).at(feat->anchor_clone_timestamp).Rot();
220 const Eigen::Matrix<double, 3, 1> &p_AinG = clonesCAM.at(feat->anchor_cam_id).at(feat->anchor_clone_timestamp).pos();
237 for (
auto const &pair : feat->timestamps) {
240 for (
size_t m = 0; m < feat->timestamps.at(pair.first).size(); m++) {
246 const Eigen::Matrix<double, 3, 3> &R_GtoCi = clonesCAM.at(pair.first).at(feat->timestamps[pair.first].at(m)).Rot();
247 const Eigen::Matrix<double, 3, 1> &p_CiinG = clonesCAM.at(pair.first).at(feat->timestamps[pair.first].at(m)).pos();
249 Eigen::Matrix<double, 3, 3> R_AtoCi;
250 R_AtoCi.noalias() = R_GtoCi * R_GtoA.transpose();
251 Eigen::Matrix<double, 3, 1> p_CiinA;
252 p_CiinA.noalias() = R_GtoA * (p_CiinG - p_AinG);
253 Eigen::Matrix<double, 3, 1> p_AinCi;
254 p_AinCi.noalias() = -R_AtoCi * p_CiinA;
260 double hi1 = R_AtoCi(0, 0) * alpha + R_AtoCi(0, 1) * beta + R_AtoCi(0, 2) + rho * p_AinCi(0, 0);
261 double hi2 = R_AtoCi(1, 0) * alpha + R_AtoCi(1, 1) * beta + R_AtoCi(1, 2) + rho * p_AinCi(1, 0);
262 double hi3 = R_AtoCi(2, 0) * alpha + R_AtoCi(2, 1) * beta + R_AtoCi(2, 2) + rho * p_AinCi(2, 0);
264 double d_z1_d_alpha = (R_AtoCi(0, 0) * hi3 - hi1 * R_AtoCi(2, 0)) / (pow(hi3, 2));
265 double d_z1_d_beta = (R_AtoCi(0, 1) * hi3 - hi1 * R_AtoCi(2, 1)) / (pow(hi3, 2));
266 double d_z1_d_rho = (p_AinCi(0, 0) * hi3 - hi1 * p_AinCi(2, 0)) / (pow(hi3, 2));
267 double d_z2_d_alpha = (R_AtoCi(1, 0) * hi3 - hi2 * R_AtoCi(2, 0)) / (pow(hi3, 2));
268 double d_z2_d_beta = (R_AtoCi(1, 1) * hi3 - hi2 * R_AtoCi(2, 1)) / (pow(hi3, 2));
269 double d_z2_d_rho = (p_AinCi(1, 0) * hi3 - hi2 * p_AinCi(2, 0)) / (pow(hi3, 2));
270 Eigen::Matrix<double, 2, 3> H;
271 H << d_z1_d_alpha, d_z1_d_beta, d_z1_d_rho, d_z2_d_alpha, d_z2_d_beta, d_z2_d_rho;
273 Eigen::Matrix<float, 2, 1> z;
274 z << hi1 / hi3, hi2 / hi3;
275 Eigen::Matrix<float, 2, 1> res = feat->uvs_norm.at(pair.first).at(m) - z;
281 err += std::pow(res.norm(), 2);
282 grad.noalias() += H.transpose() * res.cast<
double>();
283 Hess.noalias() += H.transpose() * H;
289 Eigen::Matrix<double, 3, 3> Hess_l = Hess;
290 for (
size_t r = 0; r < (size_t)Hess.rows(); r++) {
291 Hess_l(r, r) *= (1.0 + lam);
294 Eigen::Matrix<double, 3, 1> dx = Hess_l.colPivHouseholderQr().solve(grad);
298 double cost =
compute_error(clonesCAM, feat, alpha + dx(0, 0), beta + dx(1, 0), rho + dx(2, 0));
316 if (cost <= cost_old) {
333 feat->p_FinA(0) = alpha / rho;
334 feat->p_FinA(1) = beta / rho;
335 feat->p_FinA(2) = 1 / rho;
338 Eigen::HouseholderQR<Eigen::MatrixXd> qr(feat->p_FinA);
339 Eigen::MatrixXd Q = qr.householderQ();
342 double base_line_max = 0.0;
346 for (
auto const &pair : feat->timestamps) {
348 for (
size_t m = 0; m < feat->timestamps.at(pair.first).size(); m++) {
350 const Eigen::Matrix<double, 3, 1> &p_CiinG = clonesCAM.at(pair.first).at(feat->timestamps.at(pair.first).at(m)).pos();
352 Eigen::Matrix<double, 3, 1> p_CiinA = R_GtoA * (p_CiinG - p_AinG);
354 double base_line = ((Q.block(0, 1, 3, 2)).transpose() * p_CiinA).norm();
355 if (base_line > base_line_max)
356 base_line_max = base_line;
368 (feat->p_FinA.norm() / base_line_max) >
_options.
max_baseline || std::isnan(feat->p_FinA.norm())) {
373 feat->p_FinG = R_GtoA.transpose() * feat->p_FinA + p_AinG;
378 std::shared_ptr<Feature> feat,
double alpha,
double beta,
double rho) {
384 const Eigen::Matrix<double, 3, 3> &R_GtoA = clonesCAM.at(feat->anchor_cam_id).at(feat->anchor_clone_timestamp).Rot();
385 const Eigen::Matrix<double, 3, 1> &p_AinG = clonesCAM.at(feat->anchor_cam_id).at(feat->anchor_clone_timestamp).pos();
388 for (
auto const &pair : feat->timestamps) {
390 for (
size_t m = 0; m < feat->timestamps.at(pair.first).size(); m++) {
396 const Eigen::Matrix<double, 3, 3> &R_GtoCi = clonesCAM.at(pair.first).at(feat->timestamps.at(pair.first).at(m)).Rot();
397 const Eigen::Matrix<double, 3, 1> &p_CiinG = clonesCAM.at(pair.first).at(feat->timestamps.at(pair.first).at(m)).pos();
399 Eigen::Matrix<double, 3, 3> R_AtoCi;
400 R_AtoCi.noalias() = R_GtoCi * R_GtoA.transpose();
401 Eigen::Matrix<double, 3, 1> p_CiinA;
402 p_CiinA.noalias() = R_GtoA * (p_CiinG - p_AinG);
403 Eigen::Matrix<double, 3, 1> p_AinCi;
404 p_AinCi.noalias() = -R_AtoCi * p_CiinA;
410 double hi1 = R_AtoCi(0, 0) * alpha + R_AtoCi(0, 1) * beta + R_AtoCi(0, 2) + rho * p_AinCi(0, 0);
411 double hi2 = R_AtoCi(1, 0) * alpha + R_AtoCi(1, 1) * beta + R_AtoCi(1, 2) + rho * p_AinCi(1, 0);
412 double hi3 = R_AtoCi(2, 0) * alpha + R_AtoCi(2, 1) * beta + R_AtoCi(2, 2) + rho * p_AinCi(2, 0);
414 Eigen::Matrix<float, 2, 1> z;
415 z << hi1 / hi3, hi2 / hi3;
416 Eigen::Matrix<float, 2, 1> res = feat->uvs_norm.at(pair.first).at(m) - z;
418 err += pow(res.norm(), 2);