diff --git a/include/msckf_vio/msckf_vio.h b/include/msckf_vio/msckf_vio.h index 032e885..ad20d49 100644 --- a/include/msckf_vio/msckf_vio.h +++ b/include/msckf_vio/msckf_vio.h @@ -236,6 +236,7 @@ class MsckfVio { bool PHOTOMETRIC; // debug flag + bool STREAMPAUSE; bool PRINTIMAGES; bool GROUNDTRUTH; diff --git a/launch/msckf_vio_tum.launch b/launch/msckf_vio_tum.launch index f6602c1..54e6c7e 100644 --- a/launch/msckf_vio_tum.launch +++ b/launch/msckf_vio_tum.launch @@ -18,13 +18,14 @@ output="screen"> - + + - + @@ -71,4 +72,6 @@ + + diff --git a/src/msckf_vio.cpp b/src/msckf_vio.cpp index 977a95b..a6fe1f9 100644 --- a/src/msckf_vio.cpp +++ b/src/msckf_vio.cpp @@ -69,6 +69,7 @@ bool MsckfVio::loadParameters() { //Photometry Flag nh.param("PHOTOMETRIC", PHOTOMETRIC, false); nh.param("PrintImages", PRINTIMAGES, false); + nh.param("StreamPause", STREAMPAUSE, false); nh.param("GroundTruth", GROUNDTRUTH, false); // Frame id @@ -304,10 +305,10 @@ bool MsckfVio::initialize() { // Initialize the chi squared test table with confidence // level 0.95. - for (int i = 1; i < 100; ++i) { + for (int i = 1; i < 1000; ++i) { boost::math::chi_squared chi_squared_dist(i); chi_squared_test_table[i] = - boost::math::quantile(chi_squared_dist, 0.2); + boost::math::quantile(chi_squared_dist, 0.05); } if (!createRosIO()) return false; @@ -407,6 +408,10 @@ void MsckfVio::imageCallback( // Return if the gravity vector has not been set. if (!is_gravity_set) return; + // stop playing bagfile if printing images + if(STREAMPAUSE) + nh.setParam("/play_bag", false); + // Start the system if the first image is received. // The frame where the first image is received will be // the origin. @@ -443,6 +448,7 @@ void MsckfVio::imageCallback( double imu_processing_time = ( ros::Time::now()-start_time).toSec(); + //cout << "1" << endl; // Augment the state vector. start_time = ros::Time::now(); if(PHOTOMETRIC) @@ -455,6 +461,8 @@ void MsckfVio::imageCallback( double state_augmentation_time = ( ros::Time::now()-start_time).toSec(); + + //cout << "2" << endl; // Add new observations for existing features or new // features in the map server. start_time = ros::Time::now(); @@ -462,23 +470,29 @@ void MsckfVio::imageCallback( double add_observations_time = ( ros::Time::now()-start_time).toSec(); + + //cout << "3" << endl; // Add new images to moving window start_time = ros::Time::now(); manageMovingWindow(cam0_img, cam1_img, feature_msg); double manage_moving_window_time = ( ros::Time::now()-start_time).toSec(); + + //cout << "4" << endl; // Perform measurement update if necessary. start_time = ros::Time::now(); removeLostFeatures(); double remove_lost_features_time = ( ros::Time::now()-start_time).toSec(); + //cout << "5" << endl; start_time = ros::Time::now(); - pruneLastCamStateBuffer(); + pruneCamStateBuffer(); double prune_cam_states_time = ( ros::Time::now()-start_time).toSec(); + //cout << "6" << endl; // Publish the odometry. start_time = ros::Time::now(); publish(feature_msg->header.stamp); @@ -509,6 +523,8 @@ void MsckfVio::imageCallback( publish_time, publish_time/processing_time); } + if(STREAMPAUSE) + nh.setParam("/play_bag", true); return; } @@ -1428,15 +1444,7 @@ void MsckfVio::PhotometricFeatureJacobian( MatrixXd& H_x, VectorXd& r) { - // stop playing bagfile if printing images - if(PRINTIMAGES) - { - std::cout << "stopped playpack" << std::endl; - nh.setParam("/play_bag", false); - } - const auto& feature = map_server[feature_id]; - // Check how many camera states in the provided camera // id camera has actually seen this feature. @@ -1538,13 +1546,8 @@ void MsckfVio::PhotometricFeatureJacobian( myfile.close(); cout << "---------- LOGGED -------- " << endl; cvWaitKey(0); + } - } - if(PRINTIMAGES) - { - std::cout << "resume playback" << std::endl; - nh.setParam("/play_bag", true); - } return; } @@ -1619,12 +1622,6 @@ void MsckfVio::featureJacobian( MatrixXd& H_x, VectorXd& r) { // stop playing bagfile if printing images - if(PRINTIMAGES) - { - std::cout << "stopped playpack" << std::endl; - nh.setParam("/play_bag", false); - } - const auto& feature = map_server[feature_id]; @@ -1686,9 +1683,6 @@ void MsckfVio::featureJacobian( H_x = A.transpose() * H_xj; r = A.transpose() * r_j; - - cout << "\nx\n" << H_x.colPivHouseholderQr().solve(r) << endl; - // stop playing bagfile if printing images if(PRINTIMAGES) { @@ -1698,8 +1692,6 @@ void MsckfVio::featureJacobian( myfile << "Hx\n" << H_x << "r\n" << r << "from residual estimated error state: " << H_x.colPivHouseholderQr().solve(r) << endl; myfile.close(); cout << "---------- LOGGED -------- " << endl; - std::cout << "stopped playpack" << std::endl; - nh.setParam("/play_bag", true); } return; @@ -1708,8 +1700,8 @@ void MsckfVio::featureJacobian( void MsckfVio::measurementUpdate(const MatrixXd& H, const VectorXd& r) { - if (H.rows() == 0 || r.rows() == 0) return; - + if (H.rows() == 0 || r.rows() == 0) + return; // Decompose the final Jacobian matrix to reduce computational // complexity as in Equation (28), (29). MatrixXd H_thin; @@ -1718,7 +1710,7 @@ void MsckfVio::measurementUpdate(const MatrixXd& H, const VectorXd& r) { if(PHOTOMETRIC) augmentationSize = 7; - /* + // QR decomposition to make stuff faster if (H.rows() > H.cols()) { // Convert H to a sparse matrix. SparseMatrix H_sparse = H.sparseView(); @@ -1736,29 +1728,24 @@ void MsckfVio::measurementUpdate(const MatrixXd& H, const VectorXd& r) { H_thin = H_temp.topRows(21+state_server.cam_states.size()*augmentationSize); r_thin = r_temp.head(21+state_server.cam_states.size()*augmentationSize); - //HouseholderQR qr_helper(H); - //MatrixXd Q = qr_helper.householderQ(); - //MatrixXd Q1 = Q.leftCols(21+state_server.cam_states.size()*6); - - //H_thin = Q1.transpose() * H; - //r_thin = Q1.transpose() * r; } else { H_thin = H; r_thin = r; } - */ + // Compute the Kalman gain. const MatrixXd& P = state_server.state_cov; - MatrixXd S = H*P*H.transpose() + + MatrixXd S = H_thin*P*H_thin.transpose() + Feature::observation_noise*MatrixXd::Identity( - H.rows(), H.rows()); + H_thin.rows(), H_thin.rows()); //MatrixXd K_transpose = S.fullPivHouseholderQr().solve(H*P); - MatrixXd K_transpose = S.ldlt().solve(H*P); + cout << "inverting: " << S.rows() << ":" << S.cols() << endl; + MatrixXd K_transpose = S.ldlt().solve(H_thin*P); MatrixXd K = K_transpose.transpose(); - // Compute the error of the state. VectorXd delta_x = K * r; + cout << "update: " << delta_x[12] << ", " << delta_x[13] << ", " << delta_x[14] << endl; // Update the IMU state. const VectorXd& delta_x_imu = delta_x.head<21>(); @@ -1800,7 +1787,7 @@ void MsckfVio::measurementUpdate(const MatrixXd& H, const VectorXd& r) { } // Update state covariance. - MatrixXd I_KH = MatrixXd::Identity(K.rows(), H.cols()) - K*H; + MatrixXd I_KH = MatrixXd::Identity(K.rows(), H_thin.cols()) - K*H_thin; //state_server.state_cov = I_KH*state_server.state_cov*I_KH.transpose() + // K*K.transpose()*Feature::observation_noise; state_server.state_cov = I_KH*state_server.state_cov; @@ -1814,7 +1801,6 @@ void MsckfVio::measurementUpdate(const MatrixXd& H, const VectorXd& r) { } bool MsckfVio::gatingTest(const MatrixXd& H, const VectorXd& r, const int& dof) { - return 1; MatrixXd P1 = H * state_server.state_cov * H.transpose(); @@ -1827,7 +1813,7 @@ bool MsckfVio::gatingTest(const MatrixXd& H, const VectorXd& r, const int& dof) chi_squared_test_table[dof] << endl; if (chi_squared_test_table[dof] == 0) - return true; + return false; if (gamma < chi_squared_test_table[dof]) { //cout << "passed" << endl; return true; @@ -1929,11 +1915,6 @@ void MsckfVio::removeLostFeatures() { H_x.block(stack_cntr, 0, H_xj.rows(), H_xj.cols()) = H_xj; r.segment(stack_cntr, r_j.rows()) = r_j; stack_cntr += H_xj.rows(); - cout << "passed" << endl; - } - else - { - cout << "rejected" << endl; } // Put an upper bound on the row size of measurement Jacobian, @@ -1941,6 +1922,8 @@ void MsckfVio::removeLostFeatures() { if (stack_cntr > 1500) break; } + cout << "processed features: " << processed_feature_ids.size() << endl; + H_x.conservativeResize(stack_cntr, H_x.cols()); r.conservativeResize(stack_cntr); @@ -2000,6 +1983,7 @@ void MsckfVio::findRedundantCamStates(vector& rm_cam_state_ids) { void MsckfVio::pruneLastCamStateBuffer() { + if (state_server.cam_states.size() < max_cam_state_size) return; @@ -2058,7 +2042,7 @@ void MsckfVio::pruneLastCamStateBuffer() MatrixXd H_x = MatrixXd::Zero(jacobian_row_size, 21+augmentationSize*state_server.cam_states.size()); VectorXd r = VectorXd::Zero(jacobian_row_size); int stack_cntr = 0; - + int pruned_cntr = 0; for (auto& item : map_server) { auto& feature = item.second; @@ -2077,25 +2061,27 @@ void MsckfVio::pruneLastCamStateBuffer() else featureJacobian(feature.id, involved_cam_state_ids, H_xj, r_j); - if (gatingTest(H_xj, r_j, involved_cam_state_ids.size())) {// involved_cam_state_ids.size())) { + if (gatingTest(H_xj, r_j, r_j.size())) {// involved_cam_state_ids.size())) { H_x.block(stack_cntr, 0, H_xj.rows(), H_xj.cols()) = H_xj; r.segment(stack_cntr, r_j.rows()) = r_j; stack_cntr += H_xj.rows(); - cout << "passed" << endl; - } - else - { - cout << "rejected" << endl; + pruned_cntr++; } for (const auto& cam_id : involved_cam_state_ids) feature.observations.erase(cam_id); } - H_x.conservativeResize(stack_cntr, H_x.cols()); - r.conservativeResize(stack_cntr); - // Perform measurement update. - measurementUpdate(H_x, r); - + if(pruned_cntr != 0) + { + cout << "pruned features: " << pruned_cntr << endl; + + H_x.conservativeResize(stack_cntr, H_x.cols()); + r.conservativeResize(stack_cntr); + + // Perform measurement update. + measurementUpdate(H_x, r); + } + //reduction int cam_sequence = std::distance(state_server.cam_states.begin(), state_server.cam_states.find(rm_cam_state_id)); @@ -2137,6 +2123,7 @@ void MsckfVio::pruneLastCamStateBuffer() void MsckfVio::pruneCamStateBuffer() { + if (state_server.cam_states.size() < max_cam_state_size) return; @@ -2228,11 +2215,6 @@ void MsckfVio::pruneCamStateBuffer() { H_x.block(stack_cntr, 0, H_xj.rows(), H_xj.cols()) = H_xj; r.segment(stack_cntr, r_j.rows()) = r_j; stack_cntr += H_xj.rows(); - cout << "passed" << endl; - } - else - { - cout << "rejected" << endl; } for (const auto& cam_id : involved_cam_state_ids) feature.observations.erase(cam_id);