当前位置:   article > 正文

R3LIVE源码解析(10) — R3LIVE中r3live_vio.cpp文件

r3live

目录

1 r3live_vio.cpp简介

2 r3live_vio.cpp源码解析


1 r3live_vio.cpp简介

R3LIVE主要的公式推导在VIO上,所以我们来细细的分析这部分的功能。R3LIVE将VIO分成了两步,一是直接通过帧间的光流来追踪地图点,并且通过最小化追踪到的地图点的PNP投影误差来获取系统状态;二是通过这些地图点的出现的帧到地图的光度误差来优化状态。

2 r3live_vio.cpp源码解析

首先r3live_vio.cpp中,我们会先通过一个线程来获取图像的信息

  1. void R3LIVE::image_comp_callback( const sensor_msgs::CompressedImageConstPtr &msg )
  2. {
  3. std::unique_lock< std::mutex > lock2( mutex_image_callback );
  4. if ( sub_image_typed == 1 )
  5. {
  6. return; // Avoid subscribe the same image twice.
  7. }
  8. sub_image_typed = 2;
  9. g_received_compressed_img_msg.push_back( msg );
  10. // 如果是第一次收到图片,则启动一个线程
  11. if ( g_flag_if_first_rec_img )
  12. {
  13. g_flag_if_first_rec_img = 0;
  14. // 通过线程池k方法调用service_process_img_buffer函数来处理图像
  15. // 内部其实在循环调用process_image()函数
  16. m_thread_pool_ptr->commit_task( &R3LIVE::service_process_img_buffer, this );
  17. }
  18. return;
  19. }
  20. // ANCHOR - image_callback
  21. void R3LIVE::image_callback( const sensor_msgs::ImageConstPtr &msg )
  22. {
  23. std::unique_lock< std::mutex > lock( mutex_image_callback );
  24. if ( sub_image_typed == 2 )
  25. {
  26. return; // Avoid subscribe the same image twice.
  27. }
  28. sub_image_typed = 1;
  29. // 与上面的函数相同
  30. if ( g_flag_if_first_rec_img )
  31. {
  32. g_flag_if_first_rec_img = 0;
  33. m_thread_pool_ptr->commit_task( &R3LIVE::service_process_img_buffer, this );
  34. }
  35. // 将图像消息转opencv格式
  36. cv::Mat temp_img = cv_bridge::toCvCopy( msg, sensor_msgs::image_encodings::BGR8 )->image.clone();
  37. // 图像预处理,然后保存到m_queue_image_with_pose队列
  38. process_image( temp_img, msg->header.stamp.toSec() );
  39. }

 这里面通过 m_thread_pool_ptr->commit_task线程池的方式完成了图像buffer的压入与处理。在这个函数的末尾,会调用process_image函数

  1. void R3LIVE::service_process_img_buffer()
  2. {
  3. while ( 1 )
  4. {
  5. // To avoid uncompress so much image buffer, reducing the use of memory.
  6. // 如果m_queue_image_with_pose队列内的数据>4,表示这些数据还没被处理,暂时挂起预处理线程(丢一些数据)
  7. if ( m_queue_image_with_pose.size() > 4 )
  8. {
  9. while ( m_queue_image_with_pose.size() > 4 )
  10. {
  11. ros::spinOnce();
  12. std::this_thread::sleep_for( std::chrono::milliseconds( 2 ) );
  13. std::this_thread::yield();
  14. }
  15. }
  16. cv::Mat image_get;
  17. double img_rec_time;
  18. // sub_image_typed == 2,表示接收的是压缩图像格式
  19. if ( sub_image_typed == 2 )
  20. {
  21. // 如果队列中没有数据,暂停当前线程1s,以减少CPU的使用
  22. while ( g_received_compressed_img_msg.size() == 0 )
  23. {
  24. ros::spinOnce();
  25. std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
  26. std::this_thread::yield();
  27. }
  28. // 从队列的前端获取一个压缩图像消息msg
  29. sensor_msgs::CompressedImageConstPtr msg = g_received_compressed_img_msg.front();
  30. try
  31. {
  32. // 将压缩图像消息转换为cv::Mat类型的图像数据
  33. cv_bridge::CvImagePtr cv_ptr_compressed = cv_bridge::toCvCopy( msg, sensor_msgs::image_encodings::BGR8 );
  34. // 存储获取的时间和图像
  35. img_rec_time = msg->header.stamp.toSec();
  36. image_get = cv_ptr_compressed->image;
  37. // 释放内存
  38. cv_ptr_compressed->image.release();
  39. }
  40. catch ( cv_bridge::Exception &e )
  41. {
  42. printf( "Could not convert from '%s' to 'bgr8' !!! ", msg->format.c_str() );
  43. }
  44. mutex_image_callback.lock();
  45. g_received_compressed_img_msg.pop_front();
  46. mutex_image_callback.unlock();
  47. }
  48. else
  49. {
  50. // 如果队列中没有数据,暂停当前线程1s,以减少CPU的使用
  51. while ( g_received_img_msg.size() == 0 )
  52. {
  53. ros::spinOnce();
  54. std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
  55. std::this_thread::yield();
  56. }
  57. // 与前面的流程类似,区别在于需要将接受的最前的图像pop
  58. sensor_msgs::ImageConstPtr msg = g_received_img_msg.front();
  59. image_get = cv_bridge::toCvCopy( msg, sensor_msgs::image_encodings::BGR8 )->image.clone();
  60. img_rec_time = msg->header.stamp.toSec();
  61. mutex_image_callback.lock();
  62. g_received_img_msg.pop_front();
  63. mutex_image_callback.unlock();
  64. }
  65. process_image( image_get, img_rec_time );
  66. }
  67. }

process_image函数主要做了三件事情,分别是检测时间戳,初始化参数,并启动service_pub_rgb_mapsservice_VIO_update线程,以及去畸变与图像处理。

void R3LIVE::process_image( cv::Mat &tem
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/420998
推荐阅读
相关标签
  

闽ICP备14008679号