34 #include <opencv2/core/eigen.hpp>
35 #include <opencv2/imgproc/types_c.h>
37 #ifdef RTABMAP_OPENVINS
38 #include "core/VioManager.h"
39 #include "state/Propagator.h"
40 #include "state/State.h"
41 #include "state/StateHelper.h"
48 #ifdef RTABMAP_OPENVINS
51 previousPoseInv_(
Transform::getIdentity())
54 #ifdef RTABMAP_OPENVINS
55 ov_core::Printer::setPrintLevel(ov_core::Printer::PrintLevel(
ULogger::level()+1));
57 std::string left_mask_path, right_mask_path;
58 params_ = std::make_unique<ov_msckf::VioManagerOptions>();
59 Parameters::parse(parameters, Parameters::kOdomOpenVINSUseStereo(), params_->use_stereo);
60 Parameters::parse(parameters, Parameters::kOdomOpenVINSUseKLT(), params_->use_klt);
61 Parameters::parse(parameters, Parameters::kOdomOpenVINSNumPts(), params_->num_pts);
62 Parameters::parse(parameters, Parameters::kFASTThreshold(), params_->fast_threshold);
65 Parameters::parse(parameters, Parameters::kOdomOpenVINSMinPxDist(), params_->min_px_dist);
67 Parameters::parse(parameters, Parameters::kOdomOpenVINSFiTriangulate1d(), params_->featinit_options.triangulate_1d);
68 Parameters::parse(parameters, Parameters::kOdomOpenVINSFiRefineFeatures(), params_->featinit_options.refine_features);
69 Parameters::parse(parameters, Parameters::kOdomOpenVINSFiMaxRuns(), params_->featinit_options.max_runs);
70 Parameters::parse(parameters, Parameters::kVisMinDepth(), params_->featinit_options.min_dist);
71 Parameters::parse(parameters, Parameters::kVisMaxDepth(), params_->featinit_options.max_dist);
72 if(params_->featinit_options.max_dist == 0)
73 params_->featinit_options.max_dist = std::numeric_limits<double>::infinity();
74 Parameters::parse(parameters, Parameters::kOdomOpenVINSFiMaxBaseline(), params_->featinit_options.max_baseline);
75 Parameters::parse(parameters, Parameters::kOdomOpenVINSFiMaxCondNumber(), params_->featinit_options.max_cond_number);
76 Parameters::parse(parameters, Parameters::kOdomOpenVINSUseFEJ(), params_->state_options.do_fej);
77 Parameters::parse(parameters, Parameters::kOdomOpenVINSIntegration(), enum_index);
78 params_->state_options.integration_method = ov_msckf::StateOptions::IntegrationMethod(enum_index);
79 Parameters::parse(parameters, Parameters::kOdomOpenVINSCalibCamExtrinsics(), params_->state_options.do_calib_camera_pose);
80 Parameters::parse(parameters, Parameters::kOdomOpenVINSCalibCamIntrinsics(), params_->state_options.do_calib_camera_intrinsics);
81 Parameters::parse(parameters, Parameters::kOdomOpenVINSCalibCamTimeoffset(), params_->state_options.do_calib_camera_timeoffset);
82 Parameters::parse(parameters, Parameters::kOdomOpenVINSCalibIMUIntrinsics(), params_->state_options.do_calib_imu_intrinsics);
83 Parameters::parse(parameters, Parameters::kOdomOpenVINSCalibIMUGSensitivity(), params_->state_options.do_calib_imu_g_sensitivity);
84 Parameters::parse(parameters, Parameters::kOdomOpenVINSMaxClones(), params_->state_options.max_clone_size);
85 Parameters::parse(parameters, Parameters::kOdomOpenVINSMaxSLAM(), params_->state_options.max_slam_features);
86 Parameters::parse(parameters, Parameters::kOdomOpenVINSMaxSLAMInUpdate(), params_->state_options.max_slam_in_update);
87 Parameters::parse(parameters, Parameters::kOdomOpenVINSMaxMSCKFInUpdate(), params_->state_options.max_msckf_in_update);
88 Parameters::parse(parameters, Parameters::kOdomOpenVINSFeatRepMSCKF(), enum_index);
89 params_->state_options.feat_rep_msckf = ov_type::LandmarkRepresentation::Representation(enum_index);
90 Parameters::parse(parameters, Parameters::kOdomOpenVINSFeatRepSLAM(), enum_index);
91 params_->state_options.feat_rep_slam = ov_type::LandmarkRepresentation::Representation(enum_index);
92 Parameters::parse(parameters, Parameters::kOdomOpenVINSDtSLAMDelay(), params_->dt_slam_delay);
93 Parameters::parse(parameters, Parameters::kOdomOpenVINSGravityMag(), params_->gravity_mag);
95 Parameters::parse(parameters, Parameters::kOdomOpenVINSLeftMaskPath(), left_mask_path);
96 if(!left_mask_path.empty())
99 UWARN(
"OpenVINS: invalid left mask path: %s", left_mask_path.c_str());
101 params_->masks.emplace(0, cv::imread(left_mask_path, cv::IMREAD_GRAYSCALE));
103 Parameters::parse(parameters, Parameters::kOdomOpenVINSRightMaskPath(), right_mask_path);
104 if(!right_mask_path.empty())
107 UWARN(
"OpenVINS: invalid right mask path: %s", right_mask_path.c_str());
109 params_->masks.emplace(1, cv::imread(right_mask_path, cv::IMREAD_GRAYSCALE));
111 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitWindowTime(), params_->init_options.init_window_time);
112 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitIMUThresh(), params_->init_options.init_imu_thresh);
113 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitMaxDisparity(), params_->init_options.init_max_disparity);
114 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitMaxFeatures(), params_->init_options.init_max_features);
115 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynUse(), params_->init_options.init_dyn_use);
116 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynMLEOptCalib(), params_->init_options.init_dyn_mle_opt_calib);
117 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynMLEMaxIter(), params_->init_options.init_dyn_mle_max_iter);
118 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynMLEMaxTime(), params_->init_options.init_dyn_mle_max_time);
119 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynMLEMaxThreads(), params_->init_options.init_dyn_mle_max_threads);
120 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynNumPose(), params_->init_options.init_dyn_num_pose);
121 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynMinDeg(), params_->init_options.init_dyn_min_deg);
122 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynInflationOri(), params_->init_options.init_dyn_inflation_orientation);
123 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynInflationVel(), params_->init_options.init_dyn_inflation_velocity);
124 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynInflationBg(), params_->init_options.init_dyn_inflation_bias_gyro);
125 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynInflationBa(), params_->init_options.init_dyn_inflation_bias_accel);
126 Parameters::parse(parameters, Parameters::kOdomOpenVINSInitDynMinRecCond(), params_->init_options.init_dyn_min_rec_cond);
127 Parameters::parse(parameters, Parameters::kOdomOpenVINSTryZUPT(), params_->try_zupt);
128 Parameters::parse(parameters, Parameters::kOdomOpenVINSZUPTChi2Multiplier(), params_->zupt_options.chi2_multipler);
129 Parameters::parse(parameters, Parameters::kOdomOpenVINSZUPTMaxVelodicy(), params_->zupt_max_velocity);
130 Parameters::parse(parameters, Parameters::kOdomOpenVINSZUPTNoiseMultiplier(), params_->zupt_noise_multiplier);
131 Parameters::parse(parameters, Parameters::kOdomOpenVINSZUPTMaxDisparity(), params_->zupt_max_disparity);
132 Parameters::parse(parameters, Parameters::kOdomOpenVINSZUPTOnlyAtBeginning(), params_->zupt_only_at_beginning);
133 Parameters::parse(parameters, Parameters::kOdomOpenVINSAccelerometerNoiseDensity(), params_->imu_noises.sigma_a);
134 Parameters::parse(parameters, Parameters::kOdomOpenVINSAccelerometerRandomWalk(), params_->imu_noises.sigma_ab);
135 Parameters::parse(parameters, Parameters::kOdomOpenVINSGyroscopeNoiseDensity(), params_->imu_noises.sigma_w);
136 Parameters::parse(parameters, Parameters::kOdomOpenVINSGyroscopeRandomWalk(), params_->imu_noises.sigma_wb);
137 Parameters::parse(parameters, Parameters::kOdomOpenVINSUpMSCKFSigmaPx(), params_->msckf_options.sigma_pix);
138 Parameters::parse(parameters, Parameters::kOdomOpenVINSUpMSCKFChi2Multiplier(), params_->msckf_options.chi2_multipler);
139 Parameters::parse(parameters, Parameters::kOdomOpenVINSUpSLAMSigmaPx(), params_->slam_options.sigma_pix);
140 Parameters::parse(parameters, Parameters::kOdomOpenVINSUpSLAMChi2Multiplier(), params_->slam_options.chi2_multipler);
141 params_->vec_dw << 1, 0, 0, 1, 0, 1;
142 params_->vec_da << 1, 0, 0, 1, 0, 1;
143 params_->vec_tg << 0, 0, 0, 0, 0, 0, 0, 0, 0;
144 params_->q_ACCtoIMU << 0, 0, 0, 1;
145 params_->q_GYROtoIMU << 0, 0, 0, 1;
146 params_->use_aruco =
false;
147 params_->num_opencv_threads = -1;
148 params_->histogram_method = ov_core::TrackBase::HistogramMethod::NONE;
149 params_->init_options.sigma_a = params_->imu_noises.sigma_a;
150 params_->init_options.sigma_ab = params_->imu_noises.sigma_ab;
151 params_->init_options.sigma_w = params_->imu_noises.sigma_w;
152 params_->init_options.sigma_wb = params_->imu_noises.sigma_wb;
153 params_->init_options.sigma_pix = params_->slam_options.sigma_pix;
154 params_->init_options.gravity_mag = params_->gravity_mag;
161 #ifdef RTABMAP_OPENVINS
165 previousPoseInv_.setIdentity();
166 imuLocalTransformInv_.setNull();
168 initGravity_ =
false;
179 #ifdef RTABMAP_OPENVINS
183 if(!
data.imu().empty())
185 imuLocalTransformInv_ =
data.imu().localTransform().inverse();
187 Phi_.block(0,0,3,3) =
data.imu().localTransform().toEigen4d().block(0,0,3,3);
188 Phi_.block(3,3,3,3) =
data.imu().localTransform().toEigen4d().block(0,0,3,3);
191 if(!
data.imageRaw().empty() && !imuLocalTransformInv_.isNull())
194 Eigen::VectorXd left_calib(8), right_calib(8);
195 if(!
data.rightRaw().empty())
197 params_->state_options.num_cameras = params_->init_options.num_cameras = 2;
198 T_imu_left = imuLocalTransformInv_ *
data.stereoCameraModels()[0].localTransform();
203 params_->camera_intrinsics.emplace(0, std::make_shared<ov_core::CamEqui>(
204 data.stereoCameraModels()[0].left().imageWidth(),
data.stereoCameraModels()[0].left().imageHeight()));
205 params_->camera_intrinsics.emplace(1, std::make_shared<ov_core::CamEqui>(
206 data.stereoCameraModels()[0].right().imageWidth(),
data.stereoCameraModels()[0].right().imageHeight()));
210 params_->camera_intrinsics.emplace(0, std::make_shared<ov_core::CamRadtan>(
211 data.stereoCameraModels()[0].left().imageWidth(),
data.stereoCameraModels()[0].left().imageHeight()));
212 params_->camera_intrinsics.emplace(1, std::make_shared<ov_core::CamRadtan>(
213 data.stereoCameraModels()[0].right().imageWidth(),
data.stereoCameraModels()[0].right().imageHeight()));
218 left_calib <<
data.stereoCameraModels()[0].left().fx(),
219 data.stereoCameraModels()[0].left().fy(),
220 data.stereoCameraModels()[0].left().cx(),
221 data.stereoCameraModels()[0].left().cy(), 0, 0, 0, 0;
222 right_calib <<
data.stereoCameraModels()[0].right().fx(),
223 data.stereoCameraModels()[0].right().fy(),
224 data.stereoCameraModels()[0].right().cx(),
225 data.stereoCameraModels()[0].right().cy(), 0, 0, 0, 0;
229 UASSERT(
data.stereoCameraModels()[0].left().D_raw().cols ==
data.stereoCameraModels()[0].right().D_raw().cols);
230 UASSERT(
data.stereoCameraModels()[0].left().D_raw().cols >= 4);
231 UASSERT(
data.stereoCameraModels()[0].right().D_raw().cols >= 4);
232 left_calib <<
data.stereoCameraModels()[0].left().K_raw().at<
double>(0,0),
233 data.stereoCameraModels()[0].left().K_raw().at<
double>(1,1),
234 data.stereoCameraModels()[0].left().K_raw().at<
double>(0,2),
235 data.stereoCameraModels()[0].left().K_raw().at<
double>(1,2),
236 data.stereoCameraModels()[0].left().D_raw().at<
double>(0,0),
237 data.stereoCameraModels()[0].left().D_raw().at<
double>(0,1),
238 data.stereoCameraModels()[0].left().D_raw().at<
double>(0,is_fisheye?4:2),
239 data.stereoCameraModels()[0].left().D_raw().at<
double>(0,is_fisheye?5:3);
240 right_calib <<
data.stereoCameraModels()[0].right().K_raw().at<
double>(0,0),
241 data.stereoCameraModels()[0].right().K_raw().at<
double>(1,1),
242 data.stereoCameraModels()[0].right().K_raw().at<
double>(0,2),
243 data.stereoCameraModels()[0].right().K_raw().at<
double>(1,2),
244 data.stereoCameraModels()[0].right().D_raw().at<
double>(0,0),
245 data.stereoCameraModels()[0].right().D_raw().at<
double>(0,1),
246 data.stereoCameraModels()[0].right().D_raw().at<
double>(0,is_fisheye?4:2),
247 data.stereoCameraModels()[0].right().D_raw().at<
double>(0,is_fisheye?5:3);
252 params_->state_options.num_cameras = params_->init_options.num_cameras = 1;
253 T_imu_left = imuLocalTransformInv_ *
data.cameraModels()[0].localTransform();
258 params_->camera_intrinsics.emplace(0, std::make_shared<ov_core::CamEqui>(
259 data.cameraModels()[0].imageWidth(),
data.cameraModels()[0].imageHeight()));
263 params_->camera_intrinsics.emplace(0, std::make_shared<ov_core::CamRadtan>(
264 data.cameraModels()[0].imageWidth(),
data.cameraModels()[0].imageHeight()));
269 left_calib <<
data.cameraModels()[0].fx(),
270 data.cameraModels()[0].fy(),
271 data.cameraModels()[0].cx(),
272 data.cameraModels()[0].cy(), 0, 0, 0, 0;
277 left_calib <<
data.cameraModels()[0].K_raw().at<
double>(0,0),
278 data.cameraModels()[0].K_raw().at<
double>(1,1),
279 data.cameraModels()[0].K_raw().at<
double>(0,2),
280 data.cameraModels()[0].K_raw().at<
double>(1,2),
281 data.cameraModels()[0].D_raw().at<
double>(0,0),
282 data.cameraModels()[0].D_raw().at<
double>(0,1),
283 data.cameraModels()[0].D_raw().at<
double>(0,is_fisheye?4:2),
284 data.cameraModels()[0].D_raw().at<
double>(0,is_fisheye?5:3);
288 Eigen::Matrix4d T_LtoI = T_imu_left.
toEigen4d();
290 left_eigen.block(0,0,4,1) = ov_core::rot_2_quat(T_LtoI.block(0,0,3,3).transpose());
291 left_eigen.block(4,0,3,1) = -T_LtoI.block(0,0,3,3).transpose()*T_LtoI.block(0,3,3,1);
292 params_->camera_intrinsics.at(0)->set_value(left_calib);
293 params_->camera_extrinsics.emplace(0, left_eigen);
294 if(!
data.rightRaw().empty())
300 1, 0, 0,
data.stereoCameraModels()[0].baseline(),
306 T_left_right =
data.stereoCameraModels()[0].stereoTransform().inverse();
309 Transform T_imu_right = T_imu_left * T_left_right;
310 Eigen::Matrix4d T_RtoI = T_imu_right.
toEigen4d();
312 right_eigen.block(0,0,4,1) = ov_core::rot_2_quat(T_RtoI.block(0,0,3,3).transpose());
313 right_eigen.block(4,0,3,1) = -T_RtoI.block(0,0,3,3).transpose()*T_RtoI.block(0,3,3,1);
314 params_->camera_intrinsics.at(1)->set_value(right_calib);
315 params_->camera_extrinsics.emplace(1, right_eigen);
317 params_->init_options.camera_intrinsics = params_->camera_intrinsics;
318 params_->init_options.camera_extrinsics = params_->camera_extrinsics;
319 vioManager_ = std::make_unique<ov_msckf::VioManager>(*params_);
324 if(!
data.imu().empty())
326 ov_core::ImuData message;
327 message.timestamp =
data.stamp();
328 message.wm <<
data.imu().angularVelocity().val[0],
data.imu().angularVelocity().val[1],
data.imu().angularVelocity().val[2];
329 message.am <<
data.imu().linearAcceleration().val[0],
data.imu().linearAcceleration().val[1],
data.imu().linearAcceleration().val[2];
330 vioManager_->feed_measurement_imu(message);
333 if(!
data.imageRaw().empty())
335 bool covFilled =
false;
338 if(vioManager_->initialized())
339 covFilled = vioManager_->get_propagator()->fast_state_propagate(vioManager_->get_state(),
data.stamp(), state_plus, cov_plus);
342 if(
data.imageRaw().type() == CV_8UC3)
343 cv::cvtColor(
data.imageRaw(), image, CV_BGR2GRAY);
344 else if(
data.imageRaw().type() == CV_8UC1)
345 image =
data.imageRaw().clone();
347 UFATAL(
"Not supported color type!");
348 ov_core::CameraData message;
349 message.timestamp =
data.stamp();
350 message.sensor_ids.emplace_back(0);
351 message.images.emplace_back(image);
352 if(params_->masks.find(0) != params_->masks.end())
354 message.masks.emplace_back(params_->masks[0]);
356 else if(!
data.depthRaw().empty() && params_->use_mask)
359 if(
data.depthRaw().type() == CV_32FC1)
360 cv::inRange(
data.depthRaw(), params_->featinit_options.min_dist,
362 else if(
data.depthRaw().type() == CV_16UC1)
363 cv::inRange(
data.depthRaw(), params_->featinit_options.min_dist*1000,
365 message.masks.emplace_back(255-
mask);
369 message.masks.emplace_back(cv::Mat::zeros(image.size(), CV_8UC1));
371 if(!
data.rightRaw().empty())
373 if(
data.rightRaw().type() == CV_8UC3)
374 cv::cvtColor(
data.rightRaw(), image, CV_BGR2GRAY);
375 else if(
data.rightRaw().type() == CV_8UC1)
376 image =
data.rightRaw().clone();
378 UFATAL(
"Not supported color type!");
379 message.sensor_ids.emplace_back(1);
380 message.images.emplace_back(image);
381 if(params_->masks.find(1) != params_->masks.end())
382 message.masks.emplace_back(params_->masks[1]);
384 message.masks.emplace_back(cv::Mat::zeros(image.size(), CV_8UC1));
386 vioManager_->feed_measurement_camera(message);
388 std::shared_ptr<ov_msckf::State>
state = vioManager_->get_state();
390 (
float)
state->_imu->pos()(1),
391 (
float)
state->_imu->pos()(2),
392 (
float)
state->_imu->quat()(0),
393 (
float)
state->_imu->quat()(1),
394 (
float)
state->_imu->quat()(2),
395 (
float)
state->_imu->quat()(3));
396 if(!
p.isNull() && !
p.isIdentity())
398 p =
p * imuLocalTransformInv_;
406 if(previousPoseInv_.isIdentity())
407 previousPoseInv_ =
p.inverse();
409 t = previousPoseInv_ *
p;
414 std::unordered_map<size_t, Eigen::Vector3d> feat_posinG, feat_tracks_uvd;
415 vioManager_->get_active_tracks(timestamp, feat_posinG, feat_tracks_uvd);
416 auto features_SLAM = vioManager_->get_features_SLAM();
417 auto good_features_MSCKF = vioManager_->get_good_features_MSCKF();
421 info->features = features_SLAM.size() + good_features_MSCKF.size();
422 info->reg.covariance = cv::Mat::eye(6, 6, CV_64FC1);
426 cv::eigen2cv(covariance,
info->reg.covariance);
433 if(!
data.rightRaw().empty())
434 camT =
data.stereoCameraModels()[0].localTransform().inverse() *
t.inverse() * this->
getPose().
inverse() * fixT;
436 camT =
data.cameraModels()[0].localTransform().inverse() *
t.inverse() * this->
getPose().
inverse() * fixT;
438 for(
auto &feature : feat_posinG)
440 cv::Point3f pt3d(feature.second[0], feature.second[1], feature.second[2]);
442 info->localMap.emplace(feature.first, pt3d);
447 for(
auto &feature : features_SLAM)
449 cv::Point3f pt3d(feature[0], feature[1], feature[2]);
452 if(!
data.rightRaw().empty())
453 data.stereoCameraModels()[0].left().reproject(pt3d.x, pt3d.y, pt3d.z, pt.x, pt.y);
455 data.cameraModels()[0].reproject(pt3d.x, pt3d.y, pt3d.z, pt.x, pt.y);
456 info->reg.inliersIDs.emplace_back(
info->newCorners.size());
457 info->newCorners.emplace_back(pt);
460 for(
auto &feature : good_features_MSCKF)
462 cv::Point3f pt3d(feature[0], feature[1], feature[2]);
465 if(!
data.rightRaw().empty())
466 data.stereoCameraModels()[0].left().reproject(pt3d.x, pt3d.y, pt3d.z, pt.x, pt.y);
468 data.cameraModels()[0].reproject(pt3d.x, pt3d.y, pt3d.z, pt.x, pt.y);
469 info->reg.matchesIDs.emplace_back(
info->newCorners.size());
470 info->newCorners.emplace_back(pt);
476 previousPoseInv_ =
p.inverse();
482 UERROR(
"RTAB-Map is not built with OpenVINS support! Select another visual odometry approach.");