40 PRINT_DEBUG(
"=======================================\n");
41 PRINT_DEBUG(
"VISUAL-INERTIAL SIMULATOR STARTING\n");
42 PRINT_DEBUG(
"=======================================\n");
47 this->params = params_;
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());
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());
62 spline = std::make_shared<ov_core::BsplineSE3>();
63 spline->feed_trajectory(traj_data);
66 timestamp = spline->get_start_time();
67 timestamp_last_imu = spline->get_start_time();
68 timestamp_last_cam = spline->get_start_time();
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) {
76 std::exit(EXIT_FAILURE);
80 double distance = 0.0;
81 double distancethreshold = params.sim_distance_threshold;
85 Eigen::Matrix3d R_GtoI;
86 Eigen::Vector3d p_IinG;
87 bool success_pose = spline->get_pose(timestamp, R_GtoI, p_IinG);
91 PRINT_ERROR(
RED "[SIM]: unable to find jolt in the groundtruth data to initialize at\n" RESET);
92 std::exit(EXIT_FAILURE);
96 distance += (p_IinG - p_IinG_init).norm();
100 if (distance > distancethreshold) {
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;
108 PRINT_DEBUG(
"[SIM]: moved %.3f seconds into the dataset where it starts moving\n", timestamp - spline->get_start_time());
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);
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);
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);
142 if (params.sim_do_perturbation) {
145 perturb_parameters(params_);
148 params.print_and_load_noise();
149 params.print_and_load_state();
150 params.print_and_load_simulation();
159 size_t mapsize = featmap.size();
160 PRINT_DEBUG(
"[SIM]: Generating map features at %d rate\n", (
int)(1.0 / dt));
165 for (
int i = 0; i < params.num_cameras; i++) {
168 double time_synth = spline->get_start_time();
174 Eigen::Matrix3d R_GtoI;
175 Eigen::Vector3d p_IinG;
176 bool success_pose = spline->get_pose(time_synth, R_GtoI, p_IinG);
183 std::vector<std::pair<size_t, Eigen::VectorXf>> uvs = project_pointcloud(R_GtoI, p_IinG, i, featmap);
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());
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();
206 std::normal_distribution<double> w(0, 1);
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);
245 bool SimulatorInit::get_state(
double desired_time, Eigen::Matrix<double, 17, 1> &imustate) {
252 Eigen::Matrix3d R_GtoI;
253 Eigen::Vector3d p_IinG, w_IinI, v_IinG;
256 bool success_vel = spline->get_velocity(desired_time, R_GtoI, p_IinG, w_IinI, v_IinG);
259 bool success_bias =
false;
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) {
270 if (!success_vel || !success_bias) {
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);
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;
289 bool SimulatorInit::get_next_imu(
double &time_imu, Eigen::Vector3d &wm, Eigen::Vector3d &am) {
292 if (timestamp_last_cam + 1.0 / params.sim_freq_cam < timestamp_last_imu + 1.0 / params.sim_freq_imu)
296 timestamp_last_imu += 1.0 / params.sim_freq_imu;
297 timestamp = timestamp_last_imu;
298 time_imu = timestamp_last_imu;
301 Eigen::Matrix3d R_GtoI;
302 Eigen::Vector3d 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);
312 if (!success_accel) {
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);
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);
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);
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);
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) {
354 if (timestamp_last_imu + 1.0 / params.sim_freq_imu < timestamp_last_cam + 1.0 / params.sim_freq_cam)
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;
363 Eigen::Matrix3d R_GtoI;
364 Eigen::Vector3d p_IinG;
365 bool success_pose = spline->get_pose(timestamp, R_GtoI, p_IinG);
374 for (
int i = 0; i < params.num_cameras; i++) {
377 std::vector<std::pair<size_t, Eigen::VectorXf>> uvs = project_pointcloud(R_GtoI, p_IinG, i, featmap);
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);
386 if ((
int)uvs.size() > params.init_max_features) {
387 uvs.erase(uvs.begin() + params.init_max_features, uvs.end());
392 for (
size_t f = 0;
f < uvs.size() && !params.use_stereo;
f++) {
393 uvs.at(
f).first += i * featmap.size();
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));
404 feats.push_back(uvs);
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) {
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);
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);
427 std::vector<std::pair<size_t, Eigen::VectorXf>> uvs;
430 for (
const auto &feat : feats) {
433 Eigen::Vector3d p_FinI = R_GtoI * (feat.second - p_IinG);
434 Eigen::Vector3d p_FinC = R_ItoC * p_FinI + p_IinC;
437 if (p_FinC(2) > params.sim_max_feature_gen_distance || p_FinC(2) < 0.1)
441 Eigen::Vector2f uv_norm;
442 uv_norm << (float)(p_FinC(0) / p_FinC(2)), (
float)(p_FinC(1) / p_FinC(2));
445 Eigen::Vector2f uv_dist;
446 uv_dist = camera->distort_f(uv_norm);
449 if (uv_dist(0) < 0 || uv_dist(0) > camera->w() || uv_dist(1) < 0 || uv_dist(1) > camera->h()) {
454 uvs.push_back({feat.first, uv_dist});
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) {
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);
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);
475 for (
int i = 0; i < numpts; i++) {
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);
484 cv::Point2f uv_dist((
float)u_dist, (
float)v_dist);
488 uv_norm = camera->undistort_cv(uv_dist);
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);
495 Eigen::Vector3d bearing;
496 bearing << uv_norm.x, uv_norm.y, 1;
497 Eigen::Vector3d p_FinC;
498 p_FinC = depth * bearing;
501 Eigen::Vector3d p_FinI = R_ItoC.transpose() * (p_FinC - p_IinC);
502 Eigen::Vector3d p_FinG = R_GtoI.transpose() * p_FinI + p_IinG;
505 featmap.insert({id_map, p_FinG});