VioManagerHelper.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 
22 #include "VioManager.h"
23 
24 #include "feat/Feature.h"
25 #include "feat/FeatureDatabase.h"
28 #include "utils/print.h"
29 
31 
32 #include "state/Propagator.h"
33 #include "state/State.h"
34 #include "state/StateHelper.h"
35 
36 using namespace ov_core;
37 using namespace ov_type;
38 using namespace ov_msckf;
39 
40 void VioManager::initialize_with_gt(Eigen::Matrix<double, 17, 1> imustate) {
41 
42  // Initialize the system
43  state->_imu->set_value(imustate.block(1, 0, 16, 1));
44  state->_imu->set_fej(imustate.block(1, 0, 16, 1));
45 
46  // Fix the global yaw and position gauge freedoms
47  // TODO: Why does this break out simulation consistency metrics?
48  std::vector<std::shared_ptr<ov_type::Type>> order = {state->_imu};
49  Eigen::MatrixXd Cov = std::pow(0.02, 2) * Eigen::MatrixXd::Identity(state->_imu->size(), state->_imu->size());
50  Cov.block(0, 0, 3, 3) = std::pow(0.017, 2) * Eigen::Matrix3d::Identity(); // q
51  Cov.block(3, 3, 3, 3) = std::pow(0.05, 2) * Eigen::Matrix3d::Identity(); // p
52  Cov.block(6, 6, 3, 3) = std::pow(0.01, 2) * Eigen::Matrix3d::Identity(); // v (static)
53  StateHelper::set_initial_covariance(state, Cov, order);
54 
55  // Set the state time
56  state->_timestamp = imustate(0, 0);
57  startup_time = imustate(0, 0);
58  is_initialized_vio = true;
59 
60  // Cleanup any features older then the initialization time
61  trackFEATS->get_feature_database()->cleanup_measurements(state->_timestamp);
62  if (trackARUCO != nullptr) {
63  trackARUCO->get_feature_database()->cleanup_measurements(state->_timestamp);
64  }
65 
66  // Print what we init'ed with
67  PRINT_DEBUG(GREEN "[INIT]: INITIALIZED FROM GROUNDTRUTH FILE!!!!!\n" RESET);
68  PRINT_DEBUG(GREEN "[INIT]: orientation = %.4f, %.4f, %.4f, %.4f\n" RESET, state->_imu->quat()(0), state->_imu->quat()(1),
69  state->_imu->quat()(2), state->_imu->quat()(3));
70  PRINT_DEBUG(GREEN "[INIT]: bias gyro = %.4f, %.4f, %.4f\n" RESET, state->_imu->bias_g()(0), state->_imu->bias_g()(1),
71  state->_imu->bias_g()(2));
72  PRINT_DEBUG(GREEN "[INIT]: velocity = %.4f, %.4f, %.4f\n" RESET, state->_imu->vel()(0), state->_imu->vel()(1), state->_imu->vel()(2));
73  PRINT_DEBUG(GREEN "[INIT]: bias accel = %.4f, %.4f, %.4f\n" RESET, state->_imu->bias_a()(0), state->_imu->bias_a()(1),
74  state->_imu->bias_a()(2));
75  PRINT_DEBUG(GREEN "[INIT]: position = %.4f, %.4f, %.4f\n" RESET, state->_imu->pos()(0), state->_imu->pos()(1), state->_imu->pos()(2));
76 }
77 
78 bool VioManager::try_to_initialize(const ov_core::CameraData &message) {
79 
80  // Directly return if the initialization thread is running
81  // Note that we lock on the queue since we could have finished an update
82  // And are using this queue to propagate the state forward. We should wait in this case
83  if (thread_init_running) {
84  std::lock_guard<std::mutex> lck(camera_queue_init_mtx);
85  camera_queue_init.push_back(message.timestamp);
86  return false;
87  }
88 
89  // If the thread was a success, then return success!
90  if (thread_init_success) {
91  return true;
92  }
93 
94  // Run the initialization in a second thread so it can go as slow as it desires
95  thread_init_running = true;
96  std::thread thread([&] {
97  // Returns from our initializer
98  double timestamp;
99  Eigen::MatrixXd covariance;
100  std::vector<std::shared_ptr<ov_type::Type>> order;
101  auto init_rT1 = boost::posix_time::microsec_clock::local_time();
102 
103  // Try to initialize the system
104  // We will wait for a jerk if we do not have the zero velocity update enabled
105  // Otherwise we can initialize right away as the zero velocity will handle the stationary case
106  bool wait_for_jerk = (updaterZUPT == nullptr);
107  bool success = initializer->initialize(timestamp, covariance, order, state->_imu, wait_for_jerk);
108 
109  // If we have initialized successfully we will set the covariance and state elements as needed
110  // TODO: set the clones and SLAM features here so we can start updating right away...
111  if (success) {
112 
113  // Set our covariance (state should already be set in the initializer)
114  StateHelper::set_initial_covariance(state, covariance, order);
115 
116  // Set the state time
117  state->_timestamp = timestamp;
118  startup_time = timestamp;
119 
120  // Cleanup any features older than the initialization time
121  // Also increase the number of features to the desired amount during estimation
122  // NOTE: we will split the total number of features over all cameras uniformly
123  trackFEATS->get_feature_database()->cleanup_measurements(state->_timestamp);
124  trackFEATS->set_num_features(std::floor((double)params.num_pts / (double)params.state_options.num_cameras));
125  if (trackARUCO != nullptr) {
126  trackARUCO->get_feature_database()->cleanup_measurements(state->_timestamp);
127  }
128 
129  // If we are moving then don't do zero velocity update4
130  if (state->_imu->vel().norm() > params.zupt_max_velocity) {
131  has_moved_since_zupt = true;
132  }
133 
134  // Else we are good to go, print out our stats
135  auto init_rT2 = boost::posix_time::microsec_clock::local_time();
136  PRINT_INFO(GREEN "[init]: successful initialization in %.4f seconds\n" RESET, (init_rT2 - init_rT1).total_microseconds() * 1e-6);
137  PRINT_INFO(GREEN "[init]: orientation = %.4f, %.4f, %.4f, %.4f\n" RESET, state->_imu->quat()(0), state->_imu->quat()(1),
138  state->_imu->quat()(2), state->_imu->quat()(3));
139  PRINT_INFO(GREEN "[init]: bias gyro = %.4f, %.4f, %.4f\n" RESET, state->_imu->bias_g()(0), state->_imu->bias_g()(1),
140  state->_imu->bias_g()(2));
141  PRINT_INFO(GREEN "[init]: velocity = %.4f, %.4f, %.4f\n" RESET, state->_imu->vel()(0), state->_imu->vel()(1), state->_imu->vel()(2));
142  PRINT_INFO(GREEN "[init]: bias accel = %.4f, %.4f, %.4f\n" RESET, state->_imu->bias_a()(0), state->_imu->bias_a()(1),
143  state->_imu->bias_a()(2));
144  PRINT_INFO(GREEN "[init]: position = %.4f, %.4f, %.4f\n" RESET, state->_imu->pos()(0), state->_imu->pos()(1), state->_imu->pos()(2));
145 
146  // Remove any camera times that are order then the initialized time
147  // This can happen if the initialization has taken a while to perform
148  std::lock_guard<std::mutex> lck(camera_queue_init_mtx);
149  std::vector<double> camera_timestamps_to_init;
150  for (size_t i = 0; i < camera_queue_init.size(); i++) {
151  if (camera_queue_init.at(i) > timestamp) {
152  camera_timestamps_to_init.push_back(camera_queue_init.at(i));
153  }
154  }
155 
156  // Now we have initialized we will propagate the state to the current timestep
157  // In general this should be ok as long as the initialization didn't take too long to perform
158  // Propagating over multiple seconds will become an issue if the initial biases are bad
159  size_t clone_rate = (size_t)((double)camera_timestamps_to_init.size() / (double)params.state_options.max_clone_size) + 1;
160  for (size_t i = 0; i < camera_timestamps_to_init.size(); i += clone_rate) {
161  propagator->propagate_and_clone(state, camera_timestamps_to_init.at(i));
162  StateHelper::marginalize_old_clone(state);
163  }
164  PRINT_DEBUG(YELLOW "[init]: moved the state forward %.2f seconds\n" RESET, state->_timestamp - timestamp);
165  thread_init_success = true;
166  camera_queue_init.clear();
167 
168  } else {
169  auto init_rT2 = boost::posix_time::microsec_clock::local_time();
170  PRINT_DEBUG(YELLOW "[init]: failed initialization in %.4f seconds\n" RESET, (init_rT2 - init_rT1).total_microseconds() * 1e-6);
171  thread_init_success = false;
172  std::lock_guard<std::mutex> lck(camera_queue_init_mtx);
173  camera_queue_init.clear();
174  }
175 
176  // Finally, mark that the thread has finished running
177  thread_init_running = false;
178  });
179 
180  // If we are single threaded, then run single threaded
181  // Otherwise detach this thread so it runs in the background!
182  if (!params.use_multi_threading_subs) {
183  thread.join();
184  } else {
185  thread.detach();
186  }
187  return false;
188 }
189 
190 void VioManager::retriangulate_active_tracks(const ov_core::CameraData &message) {
191 
192  // Start timing
193  boost::posix_time::ptime retri_rT1, retri_rT2, retri_rT3;
194  retri_rT1 = boost::posix_time::microsec_clock::local_time();
195 
196  // Clear old active track data
197  assert(state->_clones_IMU.find(message.timestamp) != state->_clones_IMU.end());
198  active_tracks_time = message.timestamp;
199  active_image = cv::Mat();
200  trackFEATS->display_active(active_image, 255, 255, 255, 255, 255, 255, " ");
201  if (!active_image.empty()) {
202  active_image = active_image(cv::Rect(0, 0, message.images.at(0).cols, message.images.at(0).rows));
203  }
204  active_tracks_posinG.clear();
205  active_tracks_uvd.clear();
206 
207  // Current active tracks in our frontend
208  // TODO: should probably assert here that these are at the message time...
209  auto last_obs = trackFEATS->get_last_obs();
210  auto last_ids = trackFEATS->get_last_ids();
211 
212  // New set of linear systems that only contain the latest track info
213  std::map<size_t, Eigen::Matrix3d> active_feat_linsys_A_new;
214  std::map<size_t, Eigen::Vector3d> active_feat_linsys_b_new;
215  std::map<size_t, int> active_feat_linsys_count_new;
216  std::unordered_map<size_t, Eigen::Vector3d> active_tracks_posinG_new;
217 
218  // Append our new observations for each camera
219  std::map<size_t, cv::Point2f> feat_uvs_in_cam0;
220  for (auto const &cam_id : message.sensor_ids) {
221 
222  // IMU historical clone
223  Eigen::Matrix3d R_GtoI = state->_clones_IMU.at(active_tracks_time)->Rot();
224  Eigen::Vector3d p_IinG = state->_clones_IMU.at(active_tracks_time)->pos();
225 
226  // Calibration for this cam_id
227  Eigen::Matrix3d R_ItoC = state->_calib_IMUtoCAM.at(cam_id)->Rot();
228  Eigen::Vector3d p_IinC = state->_calib_IMUtoCAM.at(cam_id)->pos();
229 
230  // Convert current CAMERA position relative to global
231  Eigen::Matrix3d R_GtoCi = R_ItoC * R_GtoI;
232  Eigen::Vector3d p_CiinG = p_IinG - R_GtoCi.transpose() * p_IinC;
233 
234  // Loop through each measurement
235  assert(last_obs.find(cam_id) != last_obs.end());
236  assert(last_ids.find(cam_id) != last_ids.end());
237  for (size_t i = 0; i < last_obs.at(cam_id).size(); i++) {
238 
239  // Record this feature uv if is seen from cam0
240  size_t featid = last_ids.at(cam_id).at(i);
241  cv::Point2f pt_d = last_obs.at(cam_id).at(i).pt;
242  if (cam_id == 0) {
243  feat_uvs_in_cam0[featid] = pt_d;
244  }
245 
246  // Skip this feature if it is a SLAM feature (the state estimate takes priority)
247  if (state->_features_SLAM.find(featid) != state->_features_SLAM.end()) {
248  continue;
249  }
250 
251  // Get the UV coordinate normal
252  cv::Point2f pt_n = state->_cam_intrinsics_cameras.at(cam_id)->undistort_cv(pt_d);
253  Eigen::Matrix<double, 3, 1> b_i;
254  b_i << pt_n.x, pt_n.y, 1;
255  b_i = R_GtoCi.transpose() * b_i;
256  b_i = b_i / b_i.norm();
257  Eigen::Matrix3d Bperp = skew_x(b_i);
258 
259  // Append to our linear system
260  Eigen::Matrix3d Ai = Bperp.transpose() * Bperp;
261  Eigen::Vector3d bi = Ai * p_CiinG;
262  if (active_feat_linsys_A.find(featid) == active_feat_linsys_A.end()) {
263  active_feat_linsys_A_new.insert({featid, Ai});
264  active_feat_linsys_b_new.insert({featid, bi});
265  active_feat_linsys_count_new.insert({featid, 1});
266  } else {
267  active_feat_linsys_A_new[featid] = Ai + active_feat_linsys_A[featid];
268  active_feat_linsys_b_new[featid] = bi + active_feat_linsys_b[featid];
269  active_feat_linsys_count_new[featid] = 1 + active_feat_linsys_count[featid];
270  }
271 
272  // For this feature, recover its 3d position if we have enough observations!
273  if (active_feat_linsys_count_new.at(featid) > 3) {
274 
275  // Recover feature estimate
276  Eigen::Matrix3d A = active_feat_linsys_A_new[featid];
277  Eigen::Vector3d b = active_feat_linsys_b_new[featid];
278  Eigen::MatrixXd p_FinG = A.colPivHouseholderQr().solve(b);
279  Eigen::MatrixXd p_FinCi = R_GtoCi * (p_FinG - p_CiinG);
280 
281  // Check A and p_FinCi
282  Eigen::JacobiSVD<Eigen::Matrix3d> svd(A);
283  Eigen::MatrixXd singularValues;
284  singularValues.resize(svd.singularValues().rows(), 1);
285  singularValues = svd.singularValues();
286  double condA = singularValues(0, 0) / singularValues(singularValues.rows() - 1, 0);
287 
288  // If we have a bad condition number, or it is too close
289  // Then set the flag for bad (i.e. set z-axis to nan)
290  if (std::abs(condA) <= params.featinit_options.max_cond_number && p_FinCi(2, 0) >= params.featinit_options.min_dist &&
291  p_FinCi(2, 0) <= params.featinit_options.max_dist && !std::isnan(p_FinCi.norm())) {
292  active_tracks_posinG_new[featid] = p_FinG;
293  }
294  }
295  }
296  }
297  size_t total_triangulated = active_tracks_posinG.size();
298 
299  // Update active set of linear systems
300  active_feat_linsys_A = active_feat_linsys_A_new;
301  active_feat_linsys_b = active_feat_linsys_b_new;
302  active_feat_linsys_count = active_feat_linsys_count_new;
303  active_tracks_posinG = active_tracks_posinG_new;
304  retri_rT2 = boost::posix_time::microsec_clock::local_time();
305 
306  // Return if no features
307  if (active_tracks_posinG.empty() && state->_features_SLAM.empty())
308  return;
309 
310  // Append our SLAM features we have
311  for (const auto &feat : state->_features_SLAM) {
312  Eigen::Vector3d p_FinG = feat.second->get_xyz(false);
313  if (LandmarkRepresentation::is_relative_representation(feat.second->_feat_representation)) {
314  // Assert that we have an anchor pose for this feature
315  assert(feat.second->_anchor_cam_id != -1);
316  // Get calibration for our anchor camera
317  Eigen::Matrix3d R_ItoC = state->_calib_IMUtoCAM.at(feat.second->_anchor_cam_id)->Rot();
318  Eigen::Vector3d p_IinC = state->_calib_IMUtoCAM.at(feat.second->_anchor_cam_id)->pos();
319  // Anchor pose orientation and position
320  Eigen::Matrix3d R_GtoI = state->_clones_IMU.at(feat.second->_anchor_clone_timestamp)->Rot();
321  Eigen::Vector3d p_IinG = state->_clones_IMU.at(feat.second->_anchor_clone_timestamp)->pos();
322  // Feature in the global frame
323  p_FinG = R_GtoI.transpose() * R_ItoC.transpose() * (feat.second->get_xyz(false) - p_IinC) + p_IinG;
324  }
325  active_tracks_posinG[feat.second->_featid] = p_FinG;
326  }
327 
328  // Calibration of the first camera (cam0)
329  std::shared_ptr<Vec> distortion = state->_cam_intrinsics.at(0);
330  std::shared_ptr<PoseJPL> calibration = state->_calib_IMUtoCAM.at(0);
331  Eigen::Matrix<double, 3, 3> R_ItoC = calibration->Rot();
332  Eigen::Matrix<double, 3, 1> p_IinC = calibration->pos();
333 
334  // Get current IMU clone state
335  std::shared_ptr<PoseJPL> clone_Ii = state->_clones_IMU.at(active_tracks_time);
336  Eigen::Matrix3d R_GtoIi = clone_Ii->Rot();
337  Eigen::Vector3d p_IiinG = clone_Ii->pos();
338 
339  // 4. Next we can update our variable with the global position
340  // We also will project the features into the current frame
341  for (const auto &feat : active_tracks_posinG) {
342 
343  // For now skip features not seen from current frame
344  // TODO: should we publish other features not tracked in cam0??
345  if (feat_uvs_in_cam0.find(feat.first) == feat_uvs_in_cam0.end())
346  continue;
347 
348  // Calculate the depth of the feature in the current frame
349  // Project SLAM feature and non-cam0 features into the current frame of reference
350  Eigen::Vector3d p_FinIi = R_GtoIi * (feat.second - p_IiinG);
351  Eigen::Vector3d p_FinCi = R_ItoC * p_FinIi + p_IinC;
352  double depth = p_FinCi(2);
353  Eigen::Vector2d uv_dist;
354  if (feat_uvs_in_cam0.find(feat.first) != feat_uvs_in_cam0.end()) {
355  uv_dist << (double)feat_uvs_in_cam0.at(feat.first).x, (double)feat_uvs_in_cam0.at(feat.first).y;
356  } else {
357  Eigen::Vector2d uv_norm;
358  uv_norm << p_FinCi(0) / depth, p_FinCi(1) / depth;
359  uv_dist = state->_cam_intrinsics_cameras.at(0)->distort_d(uv_norm);
360  }
361 
362  // Skip if not valid (i.e. negative depth, or outside of image)
363  if (depth < 0.1) {
364  continue;
365  }
366 
367  // Skip if not valid (i.e. negative depth, or outside of image)
368  int width = state->_cam_intrinsics_cameras.at(0)->w();
369  int height = state->_cam_intrinsics_cameras.at(0)->h();
370  if (uv_dist(0) < 0 || (int)uv_dist(0) >= width || uv_dist(1) < 0 || (int)uv_dist(1) >= height) {
371  // PRINT_DEBUG("feat %zu -> depth = %.2f | u_d = %.2f | v_d = %.2f\n",(*it2)->featid,depth,uv_dist(0),uv_dist(1));
372  continue;
373  }
374 
375  // Finally construct the uv and depth
376  Eigen::Vector3d uvd;
377  uvd << uv_dist, depth;
378  active_tracks_uvd.insert({feat.first, uvd});
379  }
380  retri_rT3 = boost::posix_time::microsec_clock::local_time();
381 
382  // Timing information
383  PRINT_ALL(CYAN "[RETRI-TIME]: %.4f seconds for triangulation (%zu tri of %zu active)\n" RESET,
384  (retri_rT2 - retri_rT1).total_microseconds() * 1e-6, total_triangulated, active_feat_linsys_A.size());
385  PRINT_ALL(CYAN "[RETRI-TIME]: %.4f seconds for re-projection into current\n" RESET, (retri_rT3 - retri_rT2).total_microseconds() * 1e-6);
386  PRINT_ALL(CYAN "[RETRI-TIME]: %.4f seconds total\n" RESET, (retri_rT3 - retri_rT1).total_microseconds() * 1e-6);
387 }
388 
389 cv::Mat VioManager::get_historical_viz_image() {
390 
391  // Return if not ready yet
392  if (state == nullptr || trackFEATS == nullptr)
393  return cv::Mat();
394 
395  // Build an id-list of what features we should highlight (i.e. SLAM)
396  std::vector<size_t> highlighted_ids;
397  for (const auto &feat : state->_features_SLAM) {
398  highlighted_ids.push_back(feat.first);
399  }
400 
401  // Text we will overlay if needed
402  std::string overlay = (did_zupt_update) ? "zvupt" : "";
403  overlay = (!is_initialized_vio) ? "init" : overlay;
404 
405  // Get the current active tracks
406  cv::Mat img_history;
407  trackFEATS->display_history(img_history, 255, 255, 0, 255, 255, 255, highlighted_ids, overlay);
408  if (trackARUCO != nullptr) {
409  trackARUCO->display_history(img_history, 0, 255, 255, 255, 255, 255, highlighted_ids, overlay);
410  // trackARUCO->display_active(img_history, 0, 255, 255, 255, 255, 255, overlay);
411  }
412 
413  // Finally return the image
414  return img_history;
415 }
416 
417 std::vector<Eigen::Vector3d> VioManager::get_features_SLAM() {
418  std::vector<Eigen::Vector3d> slam_feats;
419  for (auto &f : state->_features_SLAM) {
420  if ((int)f.first <= 4 * state->_options.max_aruco_features)
421  continue;
422  if (ov_type::LandmarkRepresentation::is_relative_representation(f.second->_feat_representation)) {
423  // Assert that we have an anchor pose for this feature
424  assert(f.second->_anchor_cam_id != -1);
425  // Get calibration for our anchor camera
426  Eigen::Matrix<double, 3, 3> R_ItoC = state->_calib_IMUtoCAM.at(f.second->_anchor_cam_id)->Rot();
427  Eigen::Matrix<double, 3, 1> p_IinC = state->_calib_IMUtoCAM.at(f.second->_anchor_cam_id)->pos();
428  // Anchor pose orientation and position
429  Eigen::Matrix<double, 3, 3> R_GtoI = state->_clones_IMU.at(f.second->_anchor_clone_timestamp)->Rot();
430  Eigen::Matrix<double, 3, 1> p_IinG = state->_clones_IMU.at(f.second->_anchor_clone_timestamp)->pos();
431  // Feature in the global frame
432  slam_feats.push_back(R_GtoI.transpose() * R_ItoC.transpose() * (f.second->get_xyz(false) - p_IinC) + p_IinG);
433  } else {
434  slam_feats.push_back(f.second->get_xyz(false));
435  }
436  }
437  return slam_feats;
438 }
439 
440 std::vector<Eigen::Vector3d> VioManager::get_features_ARUCO() {
441  std::vector<Eigen::Vector3d> aruco_feats;
442  for (auto &f : state->_features_SLAM) {
443  if ((int)f.first > 4 * state->_options.max_aruco_features)
444  continue;
445  if (ov_type::LandmarkRepresentation::is_relative_representation(f.second->_feat_representation)) {
446  // Assert that we have an anchor pose for this feature
447  assert(f.second->_anchor_cam_id != -1);
448  // Get calibration for our anchor camera
449  Eigen::Matrix<double, 3, 3> R_ItoC = state->_calib_IMUtoCAM.at(f.second->_anchor_cam_id)->Rot();
450  Eigen::Matrix<double, 3, 1> p_IinC = state->_calib_IMUtoCAM.at(f.second->_anchor_cam_id)->pos();
451  // Anchor pose orientation and position
452  Eigen::Matrix<double, 3, 3> R_GtoI = state->_clones_IMU.at(f.second->_anchor_clone_timestamp)->Rot();
453  Eigen::Matrix<double, 3, 1> p_IinG = state->_clones_IMU.at(f.second->_anchor_clone_timestamp)->pos();
454  // Feature in the global frame
455  aruco_feats.push_back(R_GtoI.transpose() * R_ItoC.transpose() * (f.second->get_xyz(false) - p_IinC) + p_IinG);
456  } else {
457  aruco_feats.push_back(f.second->get_xyz(false));
458  }
459  }
460  return aruco_feats;
461 }
Propagator.h
ov_core::skew_x
Eigen::Matrix< double, 3, 3 > skew_x(const Eigen::Matrix< double, 3, 1 > &w)
ov_core::CameraData::images
std::vector< cv::Mat > images
LandmarkRepresentation.h
YELLOW
YELLOW
InertialInitializer.h
PRINT_DEBUG
#define PRINT_DEBUG(x...)
FeatureInitializer.h
ov_msckf
Extended Kalman Filter estimator.
Definition: VioManager.h:46
ov_core::CameraData
StateHelper.h
PRINT_ALL
#define PRINT_ALL(x...)
f
f
ov_core::CameraData::sensor_ids
std::vector< int > sensor_ids
ov_core::CameraData::timestamp
double timestamp
VioManager.h
GREEN
GREEN
ov_type::LandmarkRepresentation::is_relative_representation
static bool is_relative_representation(Representation feat_representation)
print.h
PRINT_INFO
#define PRINT_INFO(x...)
ov_type
RESET
#define RESET
Feature.h
FeatureDatabase.h
State.h
ov_core
CYAN
CYAN


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