SimulatorInit.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 "SimulatorInit.h"
23 
24 #include "cam/CamBase.h"
25 #include "cam/CamEqui.h"
26 #include "cam/CamRadtan.h"
27 #include "sim/BsplineSE3.h"
28 #include "utils/colors.h"
29 #include "utils/dataset_reader.h"
30 
31 using namespace ov_core;
32 using namespace ov_init;
33 
34 SimulatorInit::SimulatorInit(InertialInitializerOptions &params_) {
35 
36  //===============================================================
37  //===============================================================
38 
39  // Nice startup message
40  PRINT_DEBUG("=======================================\n");
41  PRINT_DEBUG("VISUAL-INERTIAL SIMULATOR STARTING\n");
42  PRINT_DEBUG("=======================================\n");
43 
44  // Store a copy of our params
45  // NOTE: We need to explicitly create a copy of our shared pointers to the camera objects
46  // NOTE: Otherwise if we perturb it would also change our "true" parameters
47  this->params = params_;
48  params.camera_intrinsics.clear();
49  for (auto const &tmp : params_.camera_intrinsics) {
50  auto tmp_cast = std::dynamic_pointer_cast<ov_core::CamEqui>(tmp.second);
51  if (tmp_cast != nullptr) {
52  params.camera_intrinsics.insert({tmp.first, std::make_shared<ov_core::CamEqui>(tmp.second->w(), tmp.second->h())});
53  params.camera_intrinsics.at(tmp.first)->set_value(params_.camera_intrinsics.at(tmp.first)->get_value());
54  } else {
55  params.camera_intrinsics.insert({tmp.first, std::make_shared<ov_core::CamRadtan>(tmp.second->w(), tmp.second->h())});
56  params.camera_intrinsics.at(tmp.first)->set_value(params_.camera_intrinsics.at(tmp.first)->get_value());
57  }
58  }
59 
60  // Load the groundtruth trajectory and its spline
61  DatasetReader::load_simulated_trajectory(params.sim_traj_path, traj_data);
62  spline = std::make_shared<ov_core::BsplineSE3>();
63  spline->feed_trajectory(traj_data);
64 
65  // Set all our timestamps as starting from the minimum spline time
66  timestamp = spline->get_start_time();
67  timestamp_last_imu = spline->get_start_time();
68  timestamp_last_cam = spline->get_start_time();
69 
70  // Get the pose at the current timestep
71  Eigen::Matrix3d R_GtoI_init;
72  Eigen::Vector3d p_IinG_init;
73  bool success_pose_init = spline->get_pose(timestamp, R_GtoI_init, p_IinG_init);
74  if (!success_pose_init) {
75  PRINT_ERROR(RED "[SIM]: unable to find the first pose in the spline...\n" RESET);
76  std::exit(EXIT_FAILURE);
77  }
78 
79  // Find the timestamp that we move enough to be considered "moved"
80  double distance = 0.0;
81  double distancethreshold = params.sim_distance_threshold;
82  while (true) {
83 
84  // Get the pose at the current timestep
85  Eigen::Matrix3d R_GtoI;
86  Eigen::Vector3d p_IinG;
87  bool success_pose = spline->get_pose(timestamp, R_GtoI, p_IinG);
88 
89  // Check if it fails
90  if (!success_pose) {
91  PRINT_ERROR(RED "[SIM]: unable to find jolt in the groundtruth data to initialize at\n" RESET);
92  std::exit(EXIT_FAILURE);
93  }
94 
95  // Append to our scalar distance
96  distance += (p_IinG - p_IinG_init).norm();
97  p_IinG_init = p_IinG;
98 
99  // Now check if we have an acceleration, else move forward in time
100  if (distance > distancethreshold) {
101  break;
102  } else {
103  timestamp += 1.0 / params.sim_freq_cam;
104  timestamp_last_imu += 1.0 / params.sim_freq_cam;
105  timestamp_last_cam += 1.0 / params.sim_freq_cam;
106  }
107  }
108  PRINT_DEBUG("[SIM]: moved %.3f seconds into the dataset where it starts moving\n", timestamp - spline->get_start_time());
109 
110  // Append the current true bias to our history
111  hist_true_bias_time.push_back(timestamp_last_imu - 1.0 / params.sim_freq_imu);
112  hist_true_bias_accel.push_back(true_bias_accel);
113  hist_true_bias_gyro.push_back(true_bias_gyro);
114  hist_true_bias_time.push_back(timestamp_last_imu);
115  hist_true_bias_accel.push_back(true_bias_accel);
116  hist_true_bias_gyro.push_back(true_bias_gyro);
117 
118  // Our simulation is running
119  is_running = true;
120 
121  //===============================================================
122  //===============================================================
123 
124  // Load the seeds for the random number generators
125  gen_state_init = std::mt19937(params.sim_seed_state_init);
126  gen_state_init.seed(params.sim_seed_state_init);
127  gen_state_perturb = std::mt19937(params.sim_seed_preturb);
128  gen_state_perturb.seed(params.sim_seed_preturb);
129  gen_meas_imu = std::mt19937(params.sim_seed_measurements);
130  gen_meas_imu.seed(params.sim_seed_measurements);
131 
132  // Create generator for our camera
133  for (int i = 0; i < params.num_cameras; i++) {
134  gen_meas_cams.push_back(std::mt19937(params.sim_seed_measurements));
135  gen_meas_cams.at(i).seed(params.sim_seed_measurements);
136  }
137 
138  //===============================================================
139  //===============================================================
140 
141  // Perturb all calibration if we should
142  if (params.sim_do_perturbation) {
143 
144  // Do the perturbation
145  perturb_parameters(params_);
146 
147  // Debug print simulation parameters
148  params.print_and_load_noise();
149  params.print_and_load_state();
150  params.print_and_load_simulation();
151  }
152 
153  //===============================================================
154  //===============================================================
155 
156  // We will create synthetic camera frames and ensure that each has enough features
157  // double dt = 0.25/freq_cam;
158  double dt = 0.25;
159  size_t mapsize = featmap.size();
160  PRINT_DEBUG("[SIM]: Generating map features at %d rate\n", (int)(1.0 / dt));
161 
162  // Loop through each camera
163  // NOTE: we loop through cameras here so that the feature map for camera 1 will always be the same
164  // NOTE: thus when we add more cameras the first camera should get the same measurements
165  for (int i = 0; i < params.num_cameras; i++) {
166 
167  // Reset the start time
168  double time_synth = spline->get_start_time();
169 
170  // Loop through each pose and generate our feature map in them!!!!
171  while (true) {
172 
173  // Get the pose at the current timestep
174  Eigen::Matrix3d R_GtoI;
175  Eigen::Vector3d p_IinG;
176  bool success_pose = spline->get_pose(time_synth, R_GtoI, p_IinG);
177 
178  // We have finished generating features
179  if (!success_pose)
180  break;
181 
182  // Get the uv features for this frame
183  std::vector<std::pair<size_t, Eigen::VectorXf>> uvs = project_pointcloud(R_GtoI, p_IinG, i, featmap);
184  // If we do not have enough, generate more
185  if ((int)uvs.size() < params.init_max_features) {
186  generate_points(R_GtoI, p_IinG, i, featmap, params.init_max_features - (int)uvs.size());
187  }
188 
189  // Move forward in time
190  time_synth += dt;
191  }
192 
193  // Debug print
194  PRINT_DEBUG("[SIM]: Generated %d map features in total over %d frames (camera %d)\n", (int)(featmap.size() - mapsize),
195  (int)((time_synth - spline->get_start_time()) / dt), i);
196  mapsize = featmap.size();
197  }
198 
199  // Nice sleep so the user can look at the printout
200  sleep(1);
201 }
202 
203 void SimulatorInit::perturb_parameters(InertialInitializerOptions &params_) {
204 
205  // One std generator
206  std::normal_distribution<double> w(0, 1);
207 
208  // Perturb our bias
209  true_bias_accel(0) = 0.08 * w(gen_state_perturb);
210  true_bias_accel(1) = 0.08 * w(gen_state_perturb);
211  true_bias_accel(2) = 0.08 * w(gen_state_perturb);
212  true_bias_gyro(0) = 0.01 * w(gen_state_perturb);
213  true_bias_gyro(1) = 0.01 * w(gen_state_perturb);
214  true_bias_gyro(2) = 0.01 * w(gen_state_perturb);
215 
216  // Camera IMU offset
217  // params_.calib_camimu_dt = 0.005 * w(gen_state_perturb) + params.calib_camimu_dt;
218 
219  // Camera intrinsics and extrinsics
220  for (int i = 0; i < params_.num_cameras; i++) {
221 
222  // Camera intrinsic properties (k1, k2, p1, p2, r1, r2, r3, r4)
223  // Eigen::MatrixXd intrinsics = params_.camera_intrinsics.at(i)->get_value();
224  // for (int r = 0; r < 4; r++) {
225  // intrinsics(r) += 1.0 * w(gen_state);
226  //}
227  // for (int r = 4; r < 8; r++) {
228  // intrinsics(r) += 0.005 * w(gen_state);
229  //}
230  // params_.camera_intrinsics.at(i)->set_value(intrinsics);
231 
232  // Our camera extrinsics transform (orientation)
233  // Eigen::Vector3d w_vec;
234  // w_vec << 0.001 * w(gen_state_perturb), 0.001 * w(gen_state_perturb), 0.001 * w(gen_state_perturb);
235  // params_.camera_extrinsics.at(i).block(0, 0, 4, 1) =
236  // rot_2_quat(exp_so3(w_vec) * quat_2_Rot(params.camera_extrinsics.at(i).block(0, 0, 4, 1)));
237 
238  // Our camera extrinsics transform (position)
239  // for (int r = 4; r < 7; r++) {
240  // params_.camera_extrinsics.at(i)(r) = 0.005 * w(gen_state_perturb) + params.camera_extrinsics.at(i)(r);
241  // }
242  }
243 }
244 
245 bool SimulatorInit::get_state(double desired_time, Eigen::Matrix<double, 17, 1> &imustate) {
246 
247  // Set to default state
248  imustate.setZero();
249  imustate(4) = 1;
250 
251  // Current state values
252  Eigen::Matrix3d R_GtoI;
253  Eigen::Vector3d p_IinG, w_IinI, v_IinG;
254 
255  // Get the pose, velocity, and acceleration
256  bool success_vel = spline->get_velocity(desired_time, R_GtoI, p_IinG, w_IinI, v_IinG);
257 
258  // Find the bounding bias values
259  bool success_bias = false;
260  size_t id_loc = 0;
261  for (size_t i = 0; i < hist_true_bias_time.size() - 1; i++) {
262  if (hist_true_bias_time.at(i) < desired_time && hist_true_bias_time.at(i + 1) >= desired_time) {
263  id_loc = i;
264  success_bias = true;
265  break;
266  }
267  }
268 
269  // If failed, then that means we don't have any more spline or bias
270  if (!success_vel || !success_bias) {
271  return false;
272  }
273 
274  // Interpolate our biases (they will be at every IMU timestep)
275  double lambda = (desired_time - hist_true_bias_time.at(id_loc)) / (hist_true_bias_time.at(id_loc + 1) - hist_true_bias_time.at(id_loc));
276  Eigen::Vector3d true_bg_interp = (1 - lambda) * hist_true_bias_gyro.at(id_loc) + lambda * hist_true_bias_gyro.at(id_loc + 1);
277  Eigen::Vector3d true_ba_interp = (1 - lambda) * hist_true_bias_accel.at(id_loc) + lambda * hist_true_bias_accel.at(id_loc + 1);
278 
279  // Finally lets create the current state
280  imustate(0, 0) = desired_time;
281  imustate.block(1, 0, 4, 1) = rot_2_quat(R_GtoI);
282  imustate.block(5, 0, 3, 1) = p_IinG;
283  imustate.block(8, 0, 3, 1) = v_IinG;
284  imustate.block(11, 0, 3, 1) = true_bg_interp;
285  imustate.block(14, 0, 3, 1) = true_ba_interp;
286  return true;
287 }
288 
289 bool SimulatorInit::get_next_imu(double &time_imu, Eigen::Vector3d &wm, Eigen::Vector3d &am) {
290 
291  // Return if the camera measurement should go before us
292  if (timestamp_last_cam + 1.0 / params.sim_freq_cam < timestamp_last_imu + 1.0 / params.sim_freq_imu)
293  return false;
294 
295  // Else lets do a new measurement!!!
296  timestamp_last_imu += 1.0 / params.sim_freq_imu;
297  timestamp = timestamp_last_imu;
298  time_imu = timestamp_last_imu;
299 
300  // Current state values
301  Eigen::Matrix3d R_GtoI;
302  Eigen::Vector3d p_IinG, w_IinI, v_IinG, alpha_IinI, a_IinG;
303 
304  // Get the pose, velocity, and acceleration
305  // NOTE: we get the acceleration between our two IMU
306  // NOTE: this is because we are using a constant measurement model for integration
307  // bool success_accel = spline->get_acceleration(timestamp+0.5/freq_imu, R_GtoI, p_IinG, w_IinI, v_IinG, alpha_IinI, a_IinG);
308  bool success_accel = spline->get_acceleration(timestamp, R_GtoI, p_IinG, w_IinI, v_IinG, alpha_IinI, a_IinG);
309 
310  // If failed, then that means we don't have any more spline
311  // Thus we should stop the simulation
312  if (!success_accel) {
313  is_running = false;
314  return false;
315  }
316 
317  // Transform omega and linear acceleration into imu frame
318  Eigen::Vector3d omega_inI = w_IinI;
319  Eigen::Vector3d gravity;
320  gravity << 0.0, 0.0, params.gravity_mag;
321  Eigen::Vector3d accel_inI = R_GtoI * (a_IinG + gravity);
322 
323  // Now add noise to these measurements
324  double dt = 1.0 / params.sim_freq_imu;
325  std::normal_distribution<double> w(0, 1);
326  wm(0) = omega_inI(0) + true_bias_gyro(0) + params.sigma_w / std::sqrt(dt) * w(gen_meas_imu);
327  wm(1) = omega_inI(1) + true_bias_gyro(1) + params.sigma_w / std::sqrt(dt) * w(gen_meas_imu);
328  wm(2) = omega_inI(2) + true_bias_gyro(2) + params.sigma_w / std::sqrt(dt) * w(gen_meas_imu);
329  am(0) = accel_inI(0) + true_bias_accel(0) + params.sigma_a / std::sqrt(dt) * w(gen_meas_imu);
330  am(1) = accel_inI(1) + true_bias_accel(1) + params.sigma_a / std::sqrt(dt) * w(gen_meas_imu);
331  am(2) = accel_inI(2) + true_bias_accel(2) + params.sigma_a / std::sqrt(dt) * w(gen_meas_imu);
332 
333  // Move the biases forward in time
334  true_bias_gyro(0) += params.sigma_wb * std::sqrt(dt) * w(gen_meas_imu);
335  true_bias_gyro(1) += params.sigma_wb * std::sqrt(dt) * w(gen_meas_imu);
336  true_bias_gyro(2) += params.sigma_wb * std::sqrt(dt) * w(gen_meas_imu);
337  true_bias_accel(0) += params.sigma_ab * std::sqrt(dt) * w(gen_meas_imu);
338  true_bias_accel(1) += params.sigma_ab * std::sqrt(dt) * w(gen_meas_imu);
339  true_bias_accel(2) += params.sigma_ab * std::sqrt(dt) * w(gen_meas_imu);
340 
341  // Append the current true bias to our history
342  hist_true_bias_time.push_back(timestamp_last_imu);
343  hist_true_bias_gyro.push_back(true_bias_gyro);
344  hist_true_bias_accel.push_back(true_bias_accel);
345 
346  // Return success
347  return true;
348 }
349 
350 bool SimulatorInit::get_next_cam(double &time_cam, std::vector<int> &camids,
351  std::vector<std::vector<std::pair<size_t, Eigen::VectorXf>>> &feats) {
352 
353  // Return if the imu measurement should go before us
354  if (timestamp_last_imu + 1.0 / params.sim_freq_imu < timestamp_last_cam + 1.0 / params.sim_freq_cam)
355  return false;
356 
357  // Else lets do a new measurement!!!
358  timestamp_last_cam += 1.0 / params.sim_freq_cam;
359  timestamp = timestamp_last_cam;
360  time_cam = timestamp_last_cam - params.calib_camimu_dt;
361 
362  // Get the pose at the current timestep
363  Eigen::Matrix3d R_GtoI;
364  Eigen::Vector3d p_IinG;
365  bool success_pose = spline->get_pose(timestamp, R_GtoI, p_IinG);
366 
367  // We have finished generating measurements
368  if (!success_pose) {
369  is_running = false;
370  return false;
371  }
372 
373  // Loop through each camera
374  for (int i = 0; i < params.num_cameras; i++) {
375 
376  // Get the uv features for this frame
377  std::vector<std::pair<size_t, Eigen::VectorXf>> uvs = project_pointcloud(R_GtoI, p_IinG, i, featmap);
378 
379  // If we do not have enough, generate more
380  if ((int)uvs.size() < params.init_max_features) {
381  PRINT_WARNING(YELLOW "[SIM]: cam %d was unable to generate enough features (%d < %d projections)\n" RESET, (int)i, (int)uvs.size(),
382  params.init_max_features);
383  }
384 
385  // If greater than only select the first set
386  if ((int)uvs.size() > params.init_max_features) {
387  uvs.erase(uvs.begin() + params.init_max_features, uvs.end());
388  }
389 
390  // Append the map size so all cameras have unique features in them (but the same map)
391  // Only do this if we are not enforcing stereo constraints between all our cameras
392  for (size_t f = 0; f < uvs.size() && !params.use_stereo; f++) {
393  uvs.at(f).first += i * featmap.size();
394  }
395 
396  // Loop through and add noise to each uv measurement
397  std::normal_distribution<double> w(0, 1);
398  for (size_t j = 0; j < uvs.size(); j++) {
399  uvs.at(j).second(0) += params.sigma_pix * w(gen_meas_cams.at(i));
400  uvs.at(j).second(1) += params.sigma_pix * w(gen_meas_cams.at(i));
401  }
402 
403  // Push back for this camera
404  feats.push_back(uvs);
405  camids.push_back(i);
406  }
407 
408  // Return success
409  return true;
410 }
411 
412 std::vector<std::pair<size_t, Eigen::VectorXf>>
413 SimulatorInit::project_pointcloud(const Eigen::Matrix3d &R_GtoI, const Eigen::Vector3d &p_IinG, int camid,
414  const std::unordered_map<size_t, Eigen::Vector3d> &feats) {
415 
416  // Assert we have good camera
417  assert(camid < params.num_cameras);
418  assert((int)params.camera_intrinsics.size() == params.num_cameras);
419  assert((int)params.camera_extrinsics.size() == params.num_cameras);
420 
421  // Grab our extrinsic and intrinsic values
422  Eigen::Matrix<double, 3, 3> R_ItoC = quat_2_Rot(params.camera_extrinsics.at(camid).block(0, 0, 4, 1));
423  Eigen::Matrix<double, 3, 1> p_IinC = params.camera_extrinsics.at(camid).block(4, 0, 3, 1);
424  std::shared_ptr<ov_core::CamBase> camera = params.camera_intrinsics.at(camid);
425 
426  // Our projected uv true measurements
427  std::vector<std::pair<size_t, Eigen::VectorXf>> uvs;
428 
429  // Loop through our map
430  for (const auto &feat : feats) {
431 
432  // Transform feature into current camera frame
433  Eigen::Vector3d p_FinI = R_GtoI * (feat.second - p_IinG);
434  Eigen::Vector3d p_FinC = R_ItoC * p_FinI + p_IinC;
435 
436  // Skip cloud if too far away
437  if (p_FinC(2) > params.sim_max_feature_gen_distance || p_FinC(2) < 0.1)
438  continue;
439 
440  // Project to normalized coordinates
441  Eigen::Vector2f uv_norm;
442  uv_norm << (float)(p_FinC(0) / p_FinC(2)), (float)(p_FinC(1) / p_FinC(2));
443 
444  // Distort the normalized coordinates
445  Eigen::Vector2f uv_dist;
446  uv_dist = camera->distort_f(uv_norm);
447 
448  // Check that it is inside our bounds
449  if (uv_dist(0) < 0 || uv_dist(0) > camera->w() || uv_dist(1) < 0 || uv_dist(1) > camera->h()) {
450  continue;
451  }
452 
453  // Else we can add this as a good projection
454  uvs.push_back({feat.first, uv_dist});
455  }
456 
457  // Return our projections
458  return uvs;
459 }
460 
461 void SimulatorInit::generate_points(const Eigen::Matrix3d &R_GtoI, const Eigen::Vector3d &p_IinG, int camid,
462  std::unordered_map<size_t, Eigen::Vector3d> &feats, int numpts) {
463 
464  // Assert we have good camera
465  assert(camid < params.num_cameras);
466  assert((int)params.camera_intrinsics.size() == params.num_cameras);
467  assert((int)params.camera_extrinsics.size() == params.num_cameras);
468 
469  // Grab our extrinsic and intrinsic values
470  Eigen::Matrix<double, 3, 3> R_ItoC = quat_2_Rot(params.camera_extrinsics.at(camid).block(0, 0, 4, 1));
471  Eigen::Matrix<double, 3, 1> p_IinC = params.camera_extrinsics.at(camid).block(4, 0, 3, 1);
472  std::shared_ptr<ov_core::CamBase> camera = params.camera_intrinsics.at(camid);
473 
474  // Generate the desired number of features
475  for (int i = 0; i < numpts; i++) {
476 
477  // Uniformly randomly generate within our fov
478  std::uniform_real_distribution<double> gen_u(0, camera->w());
479  std::uniform_real_distribution<double> gen_v(0, camera->h());
480  double u_dist = gen_u(gen_state_init);
481  double v_dist = gen_v(gen_state_init);
482 
483  // Convert to opencv format
484  cv::Point2f uv_dist((float)u_dist, (float)v_dist);
485 
486  // Undistort this point to our normalized coordinates
487  cv::Point2f uv_norm;
488  uv_norm = camera->undistort_cv(uv_dist);
489 
490  // Generate a random depth
491  std::uniform_real_distribution<double> gen_depth(params.sim_min_feature_gen_distance, params.sim_max_feature_gen_distance);
492  double depth = gen_depth(gen_state_init);
493 
494  // Get the 3d point
495  Eigen::Vector3d bearing;
496  bearing << uv_norm.x, uv_norm.y, 1;
497  Eigen::Vector3d p_FinC;
498  p_FinC = depth * bearing;
499 
500  // Move to the global frame of reference
501  Eigen::Vector3d p_FinI = R_ItoC.transpose() * (p_FinC - p_IinC);
502  Eigen::Vector3d p_FinG = R_GtoI.transpose() * p_FinI + p_IinG;
503 
504  // Append this as a new feature
505  featmap.insert({id_map, p_FinG});
506  id_map++;
507  }
508 }
ov_core::DatasetReader::load_simulated_trajectory
static void load_simulated_trajectory(std::string path, std::vector< Eigen::VectorXd > &traj_data)
ov_init::InertialInitializerOptions::camera_intrinsics
std::unordered_map< size_t, std::shared_ptr< ov_core::CamBase > > camera_intrinsics
Map between camid and camera intrinsics (fx, fy, cx, cy, d1...d4, cam_w, cam_h)
Definition: InertialInitializerOptions.h:249
ov_init::InertialInitializerOptions
Struct which stores all options needed for state estimation.
Definition: InertialInitializerOptions.h:49
SimulatorInit.h
YELLOW
YELLOW
PRINT_DEBUG
#define PRINT_DEBUG(x...)
ov_init::InertialInitializerOptions::num_cameras
int num_cameras
Number of distinct cameras that we will observe features in.
Definition: InertialInitializerOptions.h:237
BsplineSE3.h
PRINT_ERROR
#define PRINT_ERROR(x...)
f
f
CamRadtan.h
ov_init
State initialization code.
Definition: Factor_GenericPrior.h:27
ov_core::rot_2_quat
Eigen::Matrix< double, 4, 1 > rot_2_quat(const Eigen::Matrix< double, 3, 3 > &rot)
ov_core::quat_2_Rot
Eigen::Matrix< double, 3, 3 > quat_2_Rot(const Eigen::Matrix< double, 4, 1 > &q)
CamEqui.h
colors.h
RESET
#define RESET
dataset_reader.h
CamBase.h
ov_core
RED
RED
PRINT_WARNING
#define PRINT_WARNING(x...)


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