35 #include <opencv2/imgproc/types_c.h>
37 #ifdef RTABMAP_MSCKF_VIO
38 #include <msckf_vio/image_processor.h>
39 #include <msckf_vio/msckf_vio.h>
40 #include <msckf_vio/math_utils.hpp>
41 #include <eigen_conversions/eigen_msg.h>
42 #include <boost/math/distributions/chi_squared.hpp>
43 #include <pcl/common/transforms.h>
48 #ifdef RTABMAP_MSCKF_VIO
49 class ImageProcessorNoROS:
public msckf_vio::ImageProcessor
54 const Transform & imuLocalTransform,
55 const StereoCameraModel &
model,
57 msckf_vio::ImageProcessor(0)
61 if(
model.left().D_raw().cols == 6)
64 cam0_distortion_model =
"equidistant";
65 cam0_distortion_coeffs[0] = rectified?0:
model.left().D_raw().at<
double>(0,0);
66 cam0_distortion_coeffs[1] = rectified?0:
model.left().D_raw().at<
double>(0,1);
67 cam0_distortion_coeffs[2] = rectified?0:
model.left().D_raw().at<
double>(0,4);
68 cam0_distortion_coeffs[3] = rectified?0:
model.left().D_raw().at<
double>(0,5);
73 cam0_distortion_model =
"radtan";
74 cam0_distortion_coeffs[0] = rectified?0:
model.left().D_raw().at<
double>(0,0);
75 cam0_distortion_coeffs[1] = rectified?0:
model.left().D_raw().at<
double>(0,1);
76 cam0_distortion_coeffs[2] = rectified?0:
model.left().D_raw().at<
double>(0,2);
77 cam0_distortion_coeffs[3] = rectified?0:
model.left().D_raw().at<
double>(0,3);
79 if(
model.right().D_raw().cols == 6)
82 cam1_distortion_model =
"equidistant";
83 cam1_distortion_coeffs[0] = rectified?0:
model.right().D_raw().at<
double>(0,0);
84 cam1_distortion_coeffs[1] = rectified?0:
model.right().D_raw().at<
double>(0,1);
85 cam1_distortion_coeffs[2] = rectified?0:
model.right().D_raw().at<
double>(0,4);
86 cam1_distortion_coeffs[3] = rectified?0:
model.right().D_raw().at<
double>(0,5);
91 cam1_distortion_model =
"radtan";
92 cam1_distortion_coeffs[0] = rectified?0:
model.right().D_raw().at<
double>(0,0);
93 cam1_distortion_coeffs[1] = rectified?0:
model.right().D_raw().at<
double>(0,1);
94 cam1_distortion_coeffs[2] = rectified?0:
model.right().D_raw().at<
double>(0,2);
95 cam1_distortion_coeffs[3] = rectified?0:
model.right().D_raw().at<
double>(0,3);
98 cam0_resolution[0] =
model.left().imageWidth();
99 cam0_resolution[1] =
model.left().imageHeight();
101 cam1_resolution[0] =
model.right().imageWidth();
102 cam1_resolution[1] =
model.right().imageHeight();
104 cam0_intrinsics[0] = rectified?
model.left().fx():
model.left().K_raw().at<
double>(0,0);
105 cam0_intrinsics[1] = rectified?
model.left().fy():
model.left().K_raw().at<
double>(1,1);
106 cam0_intrinsics[2] = rectified?
model.left().cx():
model.left().K_raw().at<
double>(0,2);
107 cam0_intrinsics[3] = rectified?
model.left().cy():
model.left().K_raw().at<
double>(1,2);
109 cam1_intrinsics[0] = rectified?
model.right().fx():
model.right().K_raw().at<
double>(0,0);
110 cam1_intrinsics[1] = rectified?
model.right().fy():
model.right().K_raw().at<
double>(1,1);
111 cam1_intrinsics[2] = rectified?
model.right().cx():
model.right().K_raw().at<
double>(0,2);
112 cam1_intrinsics[3] = rectified?
model.right().cy():
model.right().K_raw().at<
double>(1,2);
114 UINFO(
"Local transform=%s",
model.localTransform().prettyPrint().c_str());
115 UINFO(
"imuLocalTransform=%s", imuLocalTransform.prettyPrint().c_str());
116 Transform imuCam =
model.localTransform().inverse() * imuLocalTransform;
117 UINFO(
"imuCam=%s", imuCam.prettyPrint().c_str());
118 cv::Mat T_imu_cam0 = imuCam.dataMatrix();
119 cv::Matx33d R_imu_cam0(T_imu_cam0(cv::Rect(0,0,3,3)));
120 cv::Vec3d t_imu_cam0 = T_imu_cam0(cv::Rect(3,0,1,3));
121 R_cam0_imu = R_imu_cam0.t();
122 t_cam0_imu = -R_imu_cam0.t() * t_imu_cam0;
127 cam0cam1 = Transform(
128 1, 0, 0, -
model.baseline(),
134 cam0cam1 =
model.stereoTransform();
136 UINFO(
"cam0cam1=%s", cam0cam1.prettyPrint().c_str());
138 Transform imuCam1 = cam0cam1 * imuCam;
139 cv::Mat T_imu_cam1 = imuCam1.dataMatrix();
140 cv::Matx33d R_imu_cam1(T_imu_cam1(cv::Rect(0,0,3,3)));
141 cv::Vec3d t_imu_cam1 = T_imu_cam1(cv::Rect(3,0,1,3));
142 R_cam1_imu = R_imu_cam1.t();
143 t_cam1_imu = -R_imu_cam1.t() * t_imu_cam1;
147 uInsert(parameters, parameters_in);
149 Parameters::parse(parameters, Parameters::kOdomMSCKFGridRow(), processor_config.grid_row);
150 Parameters::parse(parameters, Parameters::kOdomMSCKFGridCol(), processor_config.grid_col);
151 Parameters::parse(parameters, Parameters::kOdomMSCKFGridMinFeatureNum(), processor_config.grid_min_feature_num);
152 Parameters::parse(parameters, Parameters::kOdomMSCKFGridMaxFeatureNum(), processor_config.grid_max_feature_num);
153 Parameters::parse(parameters, Parameters::kOdomMSCKFPyramidLevels(), processor_config.pyramid_levels);
154 Parameters::parse(parameters, Parameters::kOdomMSCKFPatchSize(), processor_config.patch_size);
155 Parameters::parse(parameters, Parameters::kOdomMSCKFFastThreshold(), processor_config.fast_threshold);
156 Parameters::parse(parameters, Parameters::kOdomMSCKFMaxIteration(), processor_config.max_iteration);
157 Parameters::parse(parameters, Parameters::kOdomMSCKFTrackPrecision(), processor_config.track_precision);
158 Parameters::parse(parameters, Parameters::kOdomMSCKFRansacThreshold(), processor_config.ransac_threshold);
159 Parameters::parse(parameters, Parameters::kOdomMSCKFStereoThreshold(), processor_config.stereo_threshold);
161 UINFO(
"===========================================");
162 UINFO(
"cam0_resolution: %d, %d",
163 cam0_resolution[0], cam0_resolution[1]);
164 UINFO(
"cam0_intrinscs: %f, %f, %f, %f",
165 cam0_intrinsics[0], cam0_intrinsics[1],
166 cam0_intrinsics[2], cam0_intrinsics[3]);
167 UINFO(
"cam0_distortion_model: %s",
168 cam0_distortion_model.c_str());
169 UINFO(
"cam0_distortion_coefficients: %f, %f, %f, %f",
170 cam0_distortion_coeffs[0], cam0_distortion_coeffs[1],
171 cam0_distortion_coeffs[2], cam0_distortion_coeffs[3]);
173 UINFO(
"cam1_resolution: %d, %d",
174 cam1_resolution[0], cam1_resolution[1]);
175 UINFO(
"cam1_intrinscs: %f, %f, %f, %f",
176 cam1_intrinsics[0], cam1_intrinsics[1],
177 cam1_intrinsics[2], cam1_intrinsics[3]);
178 UINFO(
"cam1_distortion_model: %s",
179 cam1_distortion_model.c_str());
180 UINFO(
"cam1_distortion_coefficients: %f, %f, %f, %f",
181 cam1_distortion_coeffs[0], cam1_distortion_coeffs[1],
182 cam1_distortion_coeffs[2], cam1_distortion_coeffs[3]);
184 std::cout <<
"R_imu_cam0: " << R_imu_cam0 << std::endl;
185 std::cout <<
"t_imu_cam0.t(): " << t_imu_cam0.t() << std::endl;
186 std::cout <<
"R_imu_cam1: " << R_imu_cam1 << std::endl;
187 std::cout <<
"t_imu_cam1.t(): " << t_imu_cam1.t() << std::endl;
189 UINFO(
"grid_row: %d",
190 processor_config.grid_row);
191 UINFO(
"grid_col: %d",
192 processor_config.grid_col);
193 UINFO(
"grid_min_feature_num: %d",
194 processor_config.grid_min_feature_num);
195 UINFO(
"grid_max_feature_num: %d",
196 processor_config.grid_max_feature_num);
197 UINFO(
"pyramid_levels: %d",
198 processor_config.pyramid_levels);
199 UINFO(
"patch_size: %d",
200 processor_config.patch_size);
201 UINFO(
"fast_threshold: %d",
202 processor_config.fast_threshold);
203 UINFO(
"max_iteration: %d",
204 processor_config.max_iteration);
205 UINFO(
"track_precision: %f",
206 processor_config.track_precision);
207 UINFO(
"ransac_threshold: %f",
208 processor_config.ransac_threshold);
209 UINFO(
"stereo_threshold: %f",
210 processor_config.stereo_threshold);
211 UINFO(
"===========================================");
214 detector_ptr = cv::FastFeatureDetector::create(
215 processor_config.fast_threshold);
218 virtual ~ImageProcessorNoROS() {}
220 msckf_vio::CameraMeasurementPtr stereoCallback2(
221 const sensor_msgs::ImageConstPtr& cam0_img,
222 const sensor_msgs::ImageConstPtr& cam1_img) {
234 createImagePyramids();
239 initializeFirstFrame();
242 is_first_img =
false;
282 msckf_vio::CameraMeasurementPtr measurements = publish();
287 cam0_prev_img_ptr = cam0_curr_img_ptr;
288 prev_features_ptr = curr_features_ptr;
289 std::swap(prev_cam0_pyramid_, curr_cam0_pyramid_);
292 curr_features_ptr.reset(
new GridFeatures());
293 for (
int code = 0;
code <
294 processor_config.grid_row*processor_config.grid_col; ++
code) {
295 (*curr_features_ptr)[
code] = std::vector<FeatureMetaData>(0);
301 msckf_vio::CameraMeasurementPtr publish() {
304 msckf_vio::CameraMeasurementPtr feature_msg_ptr(
new msckf_vio::CameraMeasurement);
305 feature_msg_ptr->header.stamp = cam0_curr_img_ptr->header.stamp;
307 std::vector<FeatureIDType> curr_ids(0);
308 std::vector<cv::Point2f> curr_cam0_points(0);
309 std::vector<cv::Point2f> curr_cam1_points(0);
311 for (
const auto& grid_features : (*curr_features_ptr)) {
312 for (
const auto& feature : grid_features.second) {
313 curr_ids.push_back(feature.id);
314 curr_cam0_points.push_back(feature.cam0_point);
315 curr_cam1_points.push_back(feature.cam1_point);
319 std::vector<cv::Point2f> curr_cam0_points_undistorted(0);
320 std::vector<cv::Point2f> curr_cam1_points_undistorted(0);
323 curr_cam0_points, cam0_intrinsics, cam0_distortion_model,
324 cam0_distortion_coeffs, curr_cam0_points_undistorted);
326 curr_cam1_points, cam1_intrinsics, cam1_distortion_model,
327 cam1_distortion_coeffs, curr_cam1_points_undistorted);
329 for (
unsigned int i = 0;
i < curr_ids.size(); ++
i) {
330 feature_msg_ptr->features.push_back(msckf_vio::FeatureMeasurement());
331 feature_msg_ptr->features[
i].id = curr_ids[
i];
332 feature_msg_ptr->features[
i].u0 = curr_cam0_points_undistorted[
i].x;
333 feature_msg_ptr->features[
i].v0 = curr_cam0_points_undistorted[
i].y;
334 feature_msg_ptr->features[
i].u1 = curr_cam1_points_undistorted[
i].x;
335 feature_msg_ptr->features[
i].v1 = curr_cam1_points_undistorted[
i].y;
349 return feature_msg_ptr;
353 class MsckfVioNoROS:
public msckf_vio::MsckfVio
359 const Transform & imuLocalTransform,
360 const StereoCameraModel &
model,
362 msckf_vio::MsckfVio(0)
367 uInsert(parameters_, parameters_in);
372 Parameters::parse(parameters_, Parameters::kOdomMSCKFPositionStdThreshold(), position_std_threshold);
374 Parameters::parse(parameters_, Parameters::kOdomMSCKFRotationThreshold(), rotation_threshold);
375 Parameters::parse(parameters_, Parameters::kOdomMSCKFTranslationThreshold(), translation_threshold);
376 Parameters::parse(parameters_, Parameters::kOdomMSCKFTrackingRateThreshold(), tracking_rate_threshold);
379 Parameters::parse(parameters_, Parameters::kOdomMSCKFOptTranslationThreshold(), msckf_vio::Feature::optimization_config.translation_threshold);
382 Parameters::parse(parameters_, Parameters::kOdomMSCKFNoiseGyro(), msckf_vio::IMUState::gyro_noise);
383 Parameters::parse(parameters_, Parameters::kOdomMSCKFNoiseAcc(), msckf_vio::IMUState::acc_noise);
384 Parameters::parse(parameters_, Parameters::kOdomMSCKFNoiseGyroBias(), msckf_vio::IMUState::gyro_bias_noise);
385 Parameters::parse(parameters_, Parameters::kOdomMSCKFNoiseAccBias(), msckf_vio::IMUState::acc_bias_noise);
386 Parameters::parse(parameters_, Parameters::kOdomMSCKFNoiseFeature(), msckf_vio::Feature::observation_noise);
389 msckf_vio::IMUState::gyro_noise *= msckf_vio::IMUState::gyro_noise;
390 msckf_vio::IMUState::acc_noise *= msckf_vio::IMUState::acc_noise;
391 msckf_vio::IMUState::gyro_bias_noise *= msckf_vio::IMUState::gyro_bias_noise;
392 msckf_vio::IMUState::acc_bias_noise *= msckf_vio::IMUState::acc_bias_noise;
393 msckf_vio::Feature::observation_noise *= msckf_vio::Feature::observation_noise;
407 double gyro_bias_cov, acc_bias_cov, velocity_cov;
408 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovVel(), velocity_cov);
409 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovGyroBias(), gyro_bias_cov);
410 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovAccBias(), acc_bias_cov);
412 double extrinsic_rotation_cov, extrinsic_translation_cov;
413 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovExRot(), extrinsic_rotation_cov);
414 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovExTrans(), extrinsic_translation_cov);
416 state_server.state_cov = Eigen::MatrixXd::Zero(21, 21);
417 for (
int i = 3;
i < 6; ++
i)
418 state_server.state_cov(i, i) = gyro_bias_cov;
419 for (
int i = 6;
i < 9; ++
i)
420 state_server.state_cov(i, i) = velocity_cov;
421 for (
int i = 9;
i < 12; ++
i)
422 state_server.state_cov(i, i) = acc_bias_cov;
423 for (
int i = 15;
i < 18; ++
i)
424 state_server.state_cov(i, i) = extrinsic_rotation_cov;
425 for (
int i = 18;
i < 21; ++
i)
426 state_server.state_cov(i, i) = extrinsic_translation_cov;
429 UINFO(
"Local transform=%s",
model.localTransform().prettyPrint().c_str());
430 UINFO(
"imuLocalTransform=%s", imuLocalTransform.prettyPrint().c_str());
431 Transform imuCam =
model.localTransform().inverse() * imuLocalTransform;
432 UINFO(
"imuCam=%s", imuCam.prettyPrint().c_str());
436 state_server.imu_state.R_imu_cam0 = T_cam0_imu.
linear().transpose();
437 state_server.imu_state.t_cam0_imu = T_cam0_imu.
translation();
441 cam0cam1 = Transform(
442 1, 0, 0, -
model.baseline(),
448 cam0cam1 =
model.stereoTransform();
450 UINFO(
"cam0cam1=%s", cam0cam1.prettyPrint().c_str());
451 msckf_vio::CAMState::T_cam0_cam1 = cam0cam1.toEigen3d().matrix();
452 msckf_vio::IMUState::T_imu_body = imuLocalTransform.toEigen3d().matrix();
455 Parameters::parse(parameters_, Parameters::kOdomMSCKFMaxCamStateSize(), max_cam_state_size);
457 UINFO(
"===========================================");
458 UINFO(
"fixed frame id: %s", fixed_frame_id.c_str());
459 UINFO(
"child frame id: %s", child_frame_id.c_str());
460 UINFO(
"publish tf: %d", publish_tf);
461 UINFO(
"frame rate: %f", frame_rate);
462 UINFO(
"position std threshold: %f", position_std_threshold);
463 UINFO(
"Keyframe rotation threshold: %f", rotation_threshold);
464 UINFO(
"Keyframe translation threshold: %f", translation_threshold);
465 UINFO(
"Keyframe tracking rate threshold: %f", tracking_rate_threshold);
466 UINFO(
"gyro noise: %.10f", msckf_vio::IMUState::gyro_noise);
467 UINFO(
"gyro bias noise: %.10f", msckf_vio::IMUState::gyro_bias_noise);
468 UINFO(
"acc noise: %.10f", msckf_vio::IMUState::acc_noise);
469 UINFO(
"acc bias noise: %.10f", msckf_vio::IMUState::acc_bias_noise);
470 UINFO(
"observation noise: %.10f", msckf_vio::Feature::observation_noise);
471 UINFO(
"initial velocity: %f, %f, %f",
472 state_server.imu_state.velocity(0),
473 state_server.imu_state.velocity(1),
474 state_server.imu_state.velocity(2));
475 UINFO(
"initial gyro bias cov: %f", gyro_bias_cov);
476 UINFO(
"initial acc bias cov: %f", acc_bias_cov);
477 UINFO(
"initial velocity cov: %f", velocity_cov);
478 UINFO(
"initial extrinsic rotation cov: %f",
479 extrinsic_rotation_cov);
480 UINFO(
"initial extrinsic translation cov: %f",
481 extrinsic_translation_cov);
483 std::cout <<
"T_imu_cam0.linear(): " << T_imu_cam0.linear() << std::endl;
484 std::cout <<
"T_imu_cam0.translation().transpose(): " << T_imu_cam0.translation().transpose() << std::endl;
485 std::cout <<
"CAMState::T_cam0_cam1.linear(): " << msckf_vio::CAMState::T_cam0_cam1.linear() << std::endl;
486 std::cout <<
"CAMState::T_cam0_cam1.translation().transpose(): " << msckf_vio::CAMState::T_cam0_cam1.translation().transpose() << std::endl;
487 std::cout <<
"IMUState::T_imu_body.linear(): " << msckf_vio::IMUState::T_imu_body.linear() << std::endl;
488 std::cout <<
"IMUState::T_imu_body.translation().transpose(): " << msckf_vio::IMUState::T_imu_body.translation().transpose() << std::endl;
490 UINFO(
"max camera state #: %d", max_cam_state_size);
491 UINFO(
"===========================================");
497 state_server.continuous_noise_cov =
499 state_server.continuous_noise_cov.block<3, 3>(0, 0) =
500 Eigen::Matrix3d::Identity()*msckf_vio::IMUState::gyro_noise;
501 state_server.continuous_noise_cov.block<3, 3>(3, 3) =
502 Eigen::Matrix3d::Identity()*msckf_vio::IMUState::gyro_bias_noise;
503 state_server.continuous_noise_cov.block<3, 3>(6, 6) =
504 Eigen::Matrix3d::Identity()*msckf_vio::IMUState::acc_noise;
505 state_server.continuous_noise_cov.block<3, 3>(9, 9) =
506 Eigen::Matrix3d::Identity()*msckf_vio::IMUState::acc_bias_noise;
510 for (
int i = 1;
i < 100; ++
i) {
511 boost::math::chi_squared chi_squared_dist(i);
512 chi_squared_test_table[
i] =
513 boost::math::quantile(chi_squared_dist, 0.05);
519 virtual ~MsckfVioNoROS() {}
522 nav_msgs::Odometry featureCallback2(
523 const msckf_vio::CameraMeasurementConstPtr& msg,
524 pcl::PointCloud<pcl::PointXYZ>::Ptr & localMap) {
526 nav_msgs::Odometry odom;
531 UINFO(
"Gravity not set yet... waiting for 200 IMU msgs (%d/200)...", (
int)imu_msg_buffer.size());
539 is_first_img =
false;
540 state_server.imu_state.time =
msg->header.stamp.toSec();
550 batchImuProcessing(
msg->header.stamp.toSec());
557 stateAugmentation(
msg->header.stamp.toSec());
564 addFeatureObservations(msg);
570 removeLostFeatures();
575 pruneCamStateBuffer();
581 odom = publish(localMap);
612 void onlineReset2() {
616 if (position_std_threshold <= 0)
return;
617 static long long int online_reset_counter = 0;
621 double position_x_std =
std::sqrt(state_server.state_cov(12, 12));
622 double position_y_std =
std::sqrt(state_server.state_cov(13, 13));
623 double position_z_std =
std::sqrt(state_server.state_cov(14, 14));
625 if (position_x_std < position_std_threshold &&
626 position_y_std < position_std_threshold &&
627 position_z_std < position_std_threshold)
return;
629 UWARN(
"Start %lld online reset procedure...",
630 ++online_reset_counter);
631 UINFO(
"Stardard deviation in xyz: %f, %f, %f",
632 position_x_std, position_y_std, position_z_std);
635 state_server.cam_states.clear();
641 double gyro_bias_cov, acc_bias_cov, velocity_cov;
642 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovVel(), velocity_cov);
643 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovGyroBias(), gyro_bias_cov);
644 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovAccBias(), acc_bias_cov);
646 double extrinsic_rotation_cov, extrinsic_translation_cov;
647 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovExRot(), extrinsic_rotation_cov);
648 Parameters::parse(parameters_, Parameters::kOdomMSCKFInitCovExTrans(), extrinsic_translation_cov);
651 state_server.state_cov = Eigen::MatrixXd::Zero(21, 21);
652 for (
int i = 3;
i < 6; ++
i)
653 state_server.state_cov(i, i) = gyro_bias_cov;
654 for (
int i = 6;
i < 9; ++
i)
655 state_server.state_cov(i, i) = velocity_cov;
656 for (
int i = 9;
i < 12; ++
i)
657 state_server.state_cov(i, i) = acc_bias_cov;
658 for (
int i = 15;
i < 18; ++
i)
659 state_server.state_cov(i, i) = extrinsic_rotation_cov;
660 for (
int i = 18;
i < 21; ++
i)
661 state_server.state_cov(i, i) = extrinsic_translation_cov;
663 UWARN(
"%lld online reset complete...", online_reset_counter);
667 nav_msgs::Odometry publish(pcl::PointCloud<pcl::PointXYZ>::Ptr & feature_msg_ptr) {
670 const msckf_vio::IMUState& imu_state = state_server.imu_state;
672 T_i_w.
linear() = msckf_vio::quaternionToRotation(imu_state.orientation).transpose();
676 Eigen::Vector3d body_velocity =
677 msckf_vio::IMUState::T_imu_body.
linear() * imu_state.velocity;
688 nav_msgs::Odometry odom_msg;
690 odom_msg.header.frame_id = fixed_frame_id;
691 odom_msg.child_frame_id = child_frame_id;
693 tf::poseEigenToMsg(T_b_w, odom_msg.pose.pose);
694 tf::vectorEigenToMsg(body_velocity, odom_msg.twist.twist.linear);
697 Eigen::Matrix3d P_oo = state_server.state_cov.block<3, 3>(0, 0);
698 Eigen::Matrix3d P_op = state_server.state_cov.block<3, 3>(0, 12);
699 Eigen::Matrix3d P_po = state_server.state_cov.block<3, 3>(12, 0);
700 Eigen::Matrix3d P_pp = state_server.state_cov.block<3, 3>(12, 12);
702 P_imu_pose << P_pp, P_po, P_op, P_oo;
705 H_pose.block<3, 3>(0, 0) = msckf_vio::IMUState::T_imu_body.linear();
706 H_pose.block<3, 3>(3, 3) = msckf_vio::IMUState::T_imu_body.linear();
708 P_imu_pose * H_pose.transpose();
710 for (
int i = 0;
i < 6; ++
i)
711 for (
int j = 0;
j < 6; ++
j)
712 odom_msg.pose.covariance[6*i+j] = P_body_pose(i, j);
715 Eigen::Matrix3d P_imu_vel = state_server.state_cov.block<3, 3>(6, 6);
716 Eigen::Matrix3d H_vel = msckf_vio::IMUState::T_imu_body.linear();
717 Eigen::Matrix3d P_body_vel = H_vel * P_imu_vel * H_vel.transpose();
718 for (
int i = 0;
i < 3; ++
i)
719 for (
int j = 0;
j < 3; ++
j)
720 odom_msg.twist.covariance[i*6+j] = P_body_vel(i, j);
726 feature_msg_ptr.reset(
new pcl::PointCloud<pcl::PointXYZ>());
727 feature_msg_ptr->header.frame_id = fixed_frame_id;
728 feature_msg_ptr->height = 1;
729 for (
const auto& item : map_server) {
730 const auto& feature = item.second;
731 if (feature.is_initialized) {
732 feature_msg_ptr->points.push_back(pcl::PointXYZ(
733 feature.position(0), feature.position(1), feature.position(2)));
736 feature_msg_ptr->width = feature_msg_ptr->points.size();
750 #ifdef RTABMAP_MSCKF_VIO
754 parameters_(parameters),
755 fixPoseRotation_(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0),
765 #ifdef RTABMAP_MSCKF_VIO
766 delete imageProcessor_;
774 #ifdef RTABMAP_MSCKF_VIO
779 delete imageProcessor_;
788 previousPose_.setIdentity();
790 initGravity_ =
false;
803 #ifdef RTABMAP_MSCKF_VIO
806 if(!
data.imu().empty())
808 UDEBUG(
"IMU update stamp=%f acc=%f %f %f gyr=%f %f %f",
data.stamp(),
809 data.imu().linearAcceleration()[0],
810 data.imu().linearAcceleration()[1],
811 data.imu().linearAcceleration()[2],
812 data.imu().angularVelocity()[0],
813 data.imu().angularVelocity()[1],
814 data.imu().angularVelocity()[2]);
815 if(imageProcessor_ && msckf_)
817 sensor_msgs::ImuPtr
msg(
new sensor_msgs::Imu);
818 msg->angular_velocity.x =
data.imu().angularVelocity()[0];
819 msg->angular_velocity.y =
data.imu().angularVelocity()[1];
820 msg->angular_velocity.z =
data.imu().angularVelocity()[2];
821 msg->linear_acceleration.x =
data.imu().linearAcceleration()[0];
822 msg->linear_acceleration.y =
data.imu().linearAcceleration()[1];
823 msg->linear_acceleration.z =
data.imu().linearAcceleration()[2];
824 msg->header.stamp.fromSec(
data.stamp());
825 imageProcessor_->imuCallback(
msg);
826 msckf_->imuCallback(
msg);
830 UWARN(
"Ignoring IMU, waiting for an image to initialize...");
831 lastImu_ =
data.imu();
835 if(!
data.imageRaw().empty() && !
data.rightRaw().empty())
837 UDEBUG(
"Image update stamp=%f",
data.stamp());
838 if(
data.stereoCameraModels().size() == 1 &&
data.stereoCameraModels()[0].isValidForProjection())
842 UINFO(
"Initialization");
845 UWARN(
"Ignoring Image, waiting for imu to initialize...");
848 UINFO(
"Creating ImageProcessorNoROS...");
849 imageProcessor_ =
new ImageProcessorNoROS(
851 lastImu_.localTransform(),
852 data.stereoCameraModels()[0],
853 this->imagesAlreadyRectified());
854 UINFO(
"Creating MsckfVioNoROS...");
855 msckf_ =
new MsckfVioNoROS(
857 lastImu_.localTransform(),
858 data.stereoCameraModels()[0],
859 this->imagesAlreadyRectified());
866 cam1.header.stamp.fromSec(
data.stamp());
868 if(
data.imageRaw().type() == CV_8UC3)
870 cv::cvtColor(
data.imageRaw(), cam0.
image, CV_BGR2GRAY);
876 if(
data.rightRaw().type() == CV_8UC3)
878 cv::cvtColor(
data.rightRaw(),
cam1.image, CV_BGR2GRAY);
885 sensor_msgs::ImagePtr cam0Msg(
new sensor_msgs::Image);
886 sensor_msgs::ImagePtr cam1Msg(
new sensor_msgs::Image);
888 cam1.toImageMsg(*cam1Msg);
892 msckf_vio::CameraMeasurementPtr measurements = imageProcessor_->stereoCallback2(cam0Msg, cam1Msg);
893 pcl::PointCloud<pcl::PointXYZ>::Ptr localMap;
894 nav_msgs::Odometry odom = msckf_->featureCallback2(measurements, localMap);
896 if( odom.pose.pose.orientation.x != 0.0f ||
897 odom.pose.pose.orientation.y != 0.0f ||
898 odom.pose.pose.orientation.z != 0.0f ||
899 odom.pose.pose.orientation.w != 0.0f)
902 odom.pose.pose.position.x,
903 odom.pose.pose.position.y,
904 odom.pose.pose.position.z,
905 odom.pose.pose.orientation.x,
906 odom.pose.pose.orientation.y,
907 odom.pose.pose.orientation.z,
908 odom.pose.pose.orientation.w);
910 p = fixPoseRotation_*
p;
918 if(previousPose_.isIdentity())
925 t = previousPoseInv*
p;
931 info->
features = measurements->features.size();
933 info->reg.covariance = cv::Mat::zeros(6, 6, CV_64FC1);
934 cv::Mat twistCov(6,6,CV_64FC1, odom.twist.covariance.elems);
937 cv::Matx31f covWorldFrame(twistCov.at<
double>(0, 0),
938 twistCov.at<
double>(1, 1),
939 twistCov.at<
double>(2, 2));
940 cv::Matx31f covBaseFrame = cv::Matx33f(previousPoseInv.
rotationMatrix()) * covWorldFrame;
942 info->reg.covariance.at<
double>(0, 0) =
fabs(covBaseFrame.val[0])/10.0;
943 info->reg.covariance.at<
double>(1, 1) =
fabs(covBaseFrame.val[1])/10.0;
944 info->reg.covariance.at<
double>(2, 2) =
fabs(covBaseFrame.val[2])/10.0;
945 if(
info->reg.covariance.at<
double>(0, 0) < 0.0001)
947 info->reg.covariance.at<
double>(0, 0) = 0.0001;
949 if(
info->reg.covariance.at<
double>(1, 1) < 0.0001)
951 info->reg.covariance.at<
double>(1, 1) = 0.0001;
953 if(
info->reg.covariance.at<
double>(2, 2) < 0.0001)
955 info->reg.covariance.at<
double>(2, 2) = 0.0001;
957 info->reg.covariance.at<
double>(3, 3) = msckf_vio::IMUState::gyro_noise*10.0;
958 info->reg.covariance.at<
double>(4, 4) =
info->reg.covariance.at<
double>(3, 3);
959 info->reg.covariance.at<
double>(5, 5) =
info->reg.covariance.at<
double>(3, 3);
963 if(localMap.get() && localMap->size())
966 for(
unsigned int i=0;
i<localMap->size(); ++
i)
969 info->localMap.insert(std::make_pair(
i, cv::Point3f(pt.x, pt.y, pt.z)));
974 info->
newCorners.resize(measurements->features.size());
975 float fx =
data.stereoCameraModels()[0].left().fx();
976 float fy =
data.stereoCameraModels()[0].left().fy();
977 float cx =
data.stereoCameraModels()[0].left().cx();
978 float cy =
data.stereoCameraModels()[0].left().cy();
979 info->reg.inliersIDs.resize(measurements->features.size());
980 for(
unsigned int i=0;
i<measurements->features.size(); ++
i)
982 info->newCorners[
i].x = measurements->features[
i].u0*
fx+
cx;
983 info->newCorners[
i].y = measurements->features[
i].v0*
fy+
cy;
984 info->reg.inliersIDs[
i] =
i;
995 UERROR(
"RTAB-Map is not built with MSCKF_VIO support! Select another visual odometry approach.");