ros_stereo_inertial.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /**
  2. * This file is part of ORB-SLAM3
  3. *
  4. * Copyright (C) 2017-2020 Carlos Campos, Richard Elvira, Juan J. Gómez Rodríguez, José M.M. Montiel and Juan D. Tardós, University of Zaragoza.
  5. * Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M. Montiel and Juan D. Tardós, University of Zaragoza.
  6. *
  7. * ORB-SLAM3 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
  8. * License as published by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * ORB-SLAM3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
  12. * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with ORB-SLAM3.
  16. * If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include<iostream>
  19. #include<algorithm>
  20. #include<fstream>
  21. #include<chrono>
  22. #include<vector>
  23. #include<queue>
  24. #include<thread>
  25. #include<mutex>
  26. #include<ros/ros.h>
  27. #include<cv_bridge/cv_bridge.h>
  28. #include<sensor_msgs/Imu.h>
  29. #include<opencv2/core/core.hpp>
  30. #include"../../../include/System.h"
  31. #include"../include/ImuTypes.h"
  32. using namespace std;
  33. class ImuGrabber
  34. {
  35. public:
  36. ImuGrabber(){};
  37. void GrabImu(const sensor_msgs::ImuConstPtr &imu_msg);
  38. queue<sensor_msgs::ImuConstPtr> imuBuf;
  39. std::mutex mBufMutex;
  40. };
  41. class ImageGrabber
  42. {
  43. public:
  44. ImageGrabber(ORB_SLAM3::System* pSLAM, ImuGrabber *pImuGb, const bool bRect, const bool bClahe): mpSLAM(pSLAM), mpImuGb(pImuGb), do_rectify(bRect), mbClahe(bClahe){}
  45. void GrabImageLeft(const sensor_msgs::ImageConstPtr& msg);
  46. void GrabImageRight(const sensor_msgs::ImageConstPtr& msg);
  47. cv::Mat GetImage(const sensor_msgs::ImageConstPtr &img_msg);
  48. void SyncWithImu();
  49. queue<sensor_msgs::ImageConstPtr> imgLeftBuf, imgRightBuf;
  50. std::mutex mBufMutexLeft,mBufMutexRight;
  51. ORB_SLAM3::System* mpSLAM;
  52. ImuGrabber *mpImuGb;
  53. const bool do_rectify;
  54. cv::Mat M1l,M2l,M1r,M2r;
  55. const bool mbClahe;
  56. cv::Ptr<cv::CLAHE> mClahe = cv::createCLAHE(3.0, cv::Size(8, 8));
  57. };
  58. int main(int argc, char **argv)
  59. {
  60. ros::init(argc, argv, "Stereo_Inertial");
  61. ros::NodeHandle n("~");
  62. ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Info);
  63. bool bEqual = false;
  64. if(argc < 4 || argc > 5)
  65. {
  66. cerr << endl << "Usage: rosrun ORB_SLAM3 Stereo_Inertial path_to_vocabulary path_to_settings do_rectify [do_equalize]" << endl;
  67. ros::shutdown();
  68. return 1;
  69. }
  70. std::string sbRect(argv[3]);
  71. if(argc==5)
  72. {
  73. std::string sbEqual(argv[4]);
  74. if(sbEqual == "true")
  75. bEqual = true;
  76. }
  77. // Create SLAM system. It initializes all system threads and gets ready to process frames.
  78. ORB_SLAM3::System SLAM(argv[1],argv[2],ORB_SLAM3::System::IMU_STEREO,true);
  79. ImuGrabber imugb;
  80. ImageGrabber igb(&SLAM,&imugb,sbRect == "true",bEqual);
  81. if(igb.do_rectify)
  82. {
  83. // Load settings related to stereo calibration
  84. cv::FileStorage fsSettings(argv[2], cv::FileStorage::READ);
  85. if(!fsSettings.isOpened())
  86. {
  87. cerr << "ERROR: Wrong path to settings" << endl;
  88. return -1;
  89. }
  90. cv::Mat K_l, K_r, P_l, P_r, R_l, R_r, D_l, D_r;
  91. fsSettings["LEFT.K"] >> K_l;
  92. fsSettings["RIGHT.K"] >> K_r;
  93. fsSettings["LEFT.P"] >> P_l;
  94. fsSettings["RIGHT.P"] >> P_r;
  95. fsSettings["LEFT.R"] >> R_l;
  96. fsSettings["RIGHT.R"] >> R_r;
  97. fsSettings["LEFT.D"] >> D_l;
  98. fsSettings["RIGHT.D"] >> D_r;
  99. int rows_l = fsSettings["LEFT.height"];
  100. int cols_l = fsSettings["LEFT.width"];
  101. int rows_r = fsSettings["RIGHT.height"];
  102. int cols_r = fsSettings["RIGHT.width"];
  103. if(K_l.empty() || K_r.empty() || P_l.empty() || P_r.empty() || R_l.empty() || R_r.empty() || D_l.empty() || D_r.empty() ||
  104. rows_l==0 || rows_r==0 || cols_l==0 || cols_r==0)
  105. {
  106. cerr << "ERROR: Calibration parameters to rectify stereo are missing!" << endl;
  107. return -1;
  108. }
  109. cv::initUndistortRectifyMap(K_l,D_l,R_l,P_l.rowRange(0,3).colRange(0,3),cv::Size(cols_l,rows_l),CV_32F,igb.M1l,igb.M2l);
  110. cv::initUndistortRectifyMap(K_r,D_r,R_r,P_r.rowRange(0,3).colRange(0,3),cv::Size(cols_r,rows_r),CV_32F,igb.M1r,igb.M2r);
  111. }
  112. // Maximum delay, 5 seconds
  113. ros::Subscriber sub_imu = n.subscribe("/imu", 1000, &ImuGrabber::GrabImu, &imugb);
  114. ros::Subscriber sub_img_left = n.subscribe("/camera/left/image_raw", 100, &ImageGrabber::GrabImageLeft,&igb);
  115. ros::Subscriber sub_img_right = n.subscribe("/camera/right/image_raw", 100, &ImageGrabber::GrabImageRight,&igb);
  116. std::thread sync_thread(&ImageGrabber::SyncWithImu,&igb);
  117. ros::spin();
  118. return 0;
  119. }
  120. void ImageGrabber::GrabImageLeft(const sensor_msgs::ImageConstPtr &img_msg)
  121. {
  122. mBufMutexLeft.lock();
  123. if (!imgLeftBuf.empty())
  124. imgLeftBuf.pop();
  125. imgLeftBuf.push(img_msg);
  126. mBufMutexLeft.unlock();
  127. }
  128. void ImageGrabber::GrabImageRight(const sensor_msgs::ImageConstPtr &img_msg)
  129. {
  130. mBufMutexRight.lock();
  131. if (!imgRightBuf.empty())
  132. imgRightBuf.pop();
  133. imgRightBuf.push(img_msg);
  134. mBufMutexRight.unlock();
  135. }
  136. cv::Mat ImageGrabber::GetImage(const sensor_msgs::ImageConstPtr &img_msg)
  137. {
  138. // Copy the ros image message to cv::Mat.
  139. cv_bridge::CvImageConstPtr cv_ptr;
  140. try
  141. {
  142. cv_ptr = cv_bridge::toCvShare(img_msg, sensor_msgs::image_encodings::MONO8);
  143. }
  144. catch (cv_bridge::Exception& e)
  145. {
  146. ROS_ERROR("cv_bridge exception: %s", e.what());
  147. }
  148. if(cv_ptr->image.type()==0)
  149. {
  150. return cv_ptr->image.clone();
  151. }
  152. else
  153. {
  154. std::cout << "Error type" << std::endl;
  155. return cv_ptr->image.clone();
  156. }
  157. }
  158. void ImageGrabber::SyncWithImu()
  159. {
  160. const double maxTimeDiff = 0.01;
  161. while(1)
  162. {
  163. cv::Mat imLeft, imRight;
  164. double tImLeft = 0, tImRight = 0;
  165. if (!imgLeftBuf.empty()&&!imgRightBuf.empty()&&!mpImuGb->imuBuf.empty())
  166. {
  167. tImLeft = imgLeftBuf.front()->header.stamp.toSec();
  168. tImRight = imgRightBuf.front()->header.stamp.toSec();
  169. this->mBufMutexRight.lock();
  170. while((tImLeft-tImRight)>maxTimeDiff && imgRightBuf.size()>1)
  171. {
  172. imgRightBuf.pop();
  173. tImRight = imgRightBuf.front()->header.stamp.toSec();
  174. }
  175. this->mBufMutexRight.unlock();
  176. this->mBufMutexLeft.lock();
  177. while((tImRight-tImLeft)>maxTimeDiff && imgLeftBuf.size()>1)
  178. {
  179. imgLeftBuf.pop();
  180. tImLeft = imgLeftBuf.front()->header.stamp.toSec();
  181. }
  182. this->mBufMutexLeft.unlock();
  183. if((tImLeft-tImRight)>maxTimeDiff || (tImRight-tImLeft)>maxTimeDiff)
  184. {
  185. // std::cout << "big time difference" << std::endl;
  186. continue;
  187. }
  188. if(tImLeft>mpImuGb->imuBuf.back()->header.stamp.toSec())
  189. continue;
  190. this->mBufMutexLeft.lock();
  191. imLeft = GetImage(imgLeftBuf.front());
  192. imgLeftBuf.pop();
  193. this->mBufMutexLeft.unlock();
  194. this->mBufMutexRight.lock();
  195. imRight = GetImage(imgRightBuf.front());
  196. imgRightBuf.pop();
  197. this->mBufMutexRight.unlock();
  198. vector<ORB_SLAM3::IMU::Point> vImuMeas;
  199. mpImuGb->mBufMutex.lock();
  200. if(!mpImuGb->imuBuf.empty())
  201. {
  202. // Load imu measurements from buffer
  203. vImuMeas.clear();
  204. while(!mpImuGb->imuBuf.empty() && mpImuGb->imuBuf.front()->header.stamp.toSec()<=tImLeft)
  205. {
  206. double t = mpImuGb->imuBuf.front()->header.stamp.toSec();
  207. cv::Point3f acc(mpImuGb->imuBuf.front()->linear_acceleration.x, mpImuGb->imuBuf.front()->linear_acceleration.y, mpImuGb->imuBuf.front()->linear_acceleration.z);
  208. cv::Point3f gyr(mpImuGb->imuBuf.front()->angular_velocity.x, mpImuGb->imuBuf.front()->angular_velocity.y, mpImuGb->imuBuf.front()->angular_velocity.z);
  209. vImuMeas.push_back(ORB_SLAM3::IMU::Point(acc,gyr,t));
  210. mpImuGb->imuBuf.pop();
  211. }
  212. }
  213. mpImuGb->mBufMutex.unlock();
  214. if(mbClahe)
  215. {
  216. mClahe->apply(imLeft,imLeft);
  217. mClahe->apply(imRight,imRight);
  218. }
  219. if(do_rectify)
  220. {
  221. cv::remap(imLeft,imLeft,M1l,M2l,cv::INTER_LINEAR);
  222. cv::remap(imRight,imRight,M1r,M2r,cv::INTER_LINEAR);
  223. }
  224. mpSLAM->TrackStereo(imLeft,imRight,tImLeft,vImuMeas);
  225. std::chrono::milliseconds tSleep(1);
  226. std::this_thread::sleep_for(tSleep);
  227. }
  228. }
  229. }
  230. void ImuGrabber::GrabImu(const sensor_msgs::ImuConstPtr &imu_msg)
  231. {
  232. mBufMutex.lock();
  233. imuBuf.push(imu_msg);
  234. mBufMutex.unlock();
  235. return;
  236. }