当前位置:   article > 正文

ROS消息过滤器之 message_filters::Synchronizer 使用详解_synchronizer sync

synchronizer sync

        在ROS中,当我们有多个传感器发布的数据需要同步时,message_filters::Synchronizer 是一个非常有用的工具。它可以确保多个消息在时间上是同步的,以便更有效地处理数据。

1.什么是ROS消息过滤器?

ROS消息过滤器是一种用于处理ROS消息的工具,允许我们对消息进行过滤、同步和组合。这对于在机器人感知中整合不同传感器数据或在控制中同步多个输入源非常重要。

2.message_filters::Synchronizer 简介

        message_filters::Synchronizer 是ROS中消息过滤器的一部分,专门用于同步多个消息。它可以确保多个发布者发布的消息在时间上是同步的,以便在回调函数中处理这些消息。

3.使用场景

        当你有多个传感器发布的数据,需要确保这些数据在同一时刻可用时,message_filters::Synchronizer 就派上用场了。例如,在处理相机图像和激光雷达扫描数据时,你可能希望它们在相同的时间戳上可用,以便更准确地进行感知。

4.示例代码

工程结构:

4.1 发布者节点 (image_publisher.cpp)

  1. #include <ros/ros.h>
  2. #include <sensor_msgs/Image.h>
  3. #include <cv_bridge/cv_bridge.h>
  4. #include <opencv2/highgui/highgui.hpp>
  5. #include <ros/ros.h>
  6. #include <sensor_msgs/Image.h>
  7. #include <sensor_msgs/PointCloud2.h>
  8. #include <cv_bridge/cv_bridge.h>
  9. #include <pcl_conversions/pcl_conversions.h>
  10. #include <pcl/point_cloud.h>
  11. #include <pcl/point_types.h>
  12. #include <pcl/io/pcd_io.h>
  13. int main(int argc, char** argv)
  14. {
  15. ros::init(argc, argv, "image_and_pointcloud_publisher");
  16. ros::NodeHandle nh;
  17. // 创建一个发布者,发布图像消息到 "/image_topic" 话题,缓存队列大小为 10
  18. ros::Publisher image_pub = nh.advertise<sensor_msgs::Image>("/image_topic", 10);
  19. // 创建一个发布者,发布点云消息到 "/pointcloud_topic" 话题,缓存队列大小为 10
  20. ros::Publisher pcl_pub = nh.advertise<sensor_msgs::PointCloud2>("/pointcloud_topic", 10);
  21. // 创建图像消息
  22. sensor_msgs::Image image_msg;
  23. // 设置图像消息的头部信息
  24. image_msg.header.stamp = ros::Time::now();
  25. image_msg.header.frame_id = "camera_frame";
  26. // 填充图像数据(这里假设你已经有一个图像数据,例如使用OpenCV加载的图像)
  27. cv::Mat image = cv::imread("/home/guo/Pictures/1.png", cv::IMREAD_COLOR);
  28. // 使用cv_bridge将OpenCV图像转换为ROS图像消息
  29. cv_bridge::CvImage cv_image;
  30. cv_image.image = image;
  31. cv_image.encoding = "bgr8"; // 8-bit, 3 channel
  32. image_msg = *cv_image.toImageMsg();
  33. // 创建点云消息
  34. sensor_msgs::PointCloud2 pcl_msg;
  35. // 填充点云数据(这里假设你已经有一个点云数据,例如使用PCL库生成的点云)
  36. pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>);
  37. // Populate your point cloud data here...
  38. pcl::io::loadPCDFile("/home/guo/Downloads/pcd/1.pcd", *cloud);
  39. // 使用PCL库将点云转换为ROS点云消息
  40. pcl::toROSMsg(*cloud, pcl_msg);
  41. pcl_msg.header.stamp = ros::Time::now();
  42. pcl_msg.header.frame_id = "camera_frame";
  43. ros::Rate loop_rate(1); // 发布频率为1Hz
  44. while (ros::ok())
  45. {
  46. // 更新时间戳
  47. image_msg.header.stamp = ros::Time::now();
  48. pcl_msg.header.stamp = ros::Time::now();
  49. // 发布图像消息
  50. image_pub.publish(image_msg);
  51. // 发布点云消息
  52. pcl_pub.publish(pcl_msg);
  53. // 循环等待
  54. ros::spinOnce();
  55. loop_rate.sleep();
  56. }
  57. return 0;
  58. }

4.2 订阅者节点 (synchronized_subscriber.cpp)

  1. #include <ros/ros.h>
  2. #include <sensor_msgs/Image.h>
  3. #include <sensor_msgs/PointCloud2.h>
  4. #include <message_filters/subscriber.h>
  5. #include <message_filters/synchronizer.h>
  6. #include <message_filters/sync_policies/approximate_time.h>
  7. void callback(const sensor_msgs::Image::ConstPtr& image_msg, const sensor_msgs::PointCloud2::ConstPtr& pcl_msg)
  8. {
  9. // 处理同步的消息
  10. // image_msg 和 pcl_msg 在相同时间戳下
  11. ROS_INFO("Received synchronized the message of image_msg at time %f", image_msg->header.stamp.toSec());
  12. ROS_INFO("Received synchronized the message of pcl_msg message at time %f", pcl_msg->header.stamp.toSec());
  13. ROS_INFO("------------------------------------------------------------------------");
  14. }
  15. int main(int argc, char** argv)
  16. {
  17. ros::init(argc, argv, "synchronized_subscriber");
  18. ros::NodeHandle nh;
  19. // 创建两个订阅者
  20. message_filters::Subscriber<sensor_msgs::Image> image_sub(nh, "/image_topic", 1);
  21. message_filters::Subscriber<sensor_msgs::PointCloud2> pcl_sub(nh, "/pointcloud_topic", 1);
  22. // 定义同步策略为 ApproximateTime
  23. typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::PointCloud2> MySyncPolicy;
  24. // 创建同步器对象
  25. message_filters::Synchronizer<MySyncPolicy> sync(MySyncPolicy(10), image_sub, pcl_sub);
  26. // 注册回调函数
  27. sync.registerCallback(boost::bind(&callback, _1, _2));
  28. ros::spin();
  29. return 0;
  30. }

 4.3 CMakeLists.txt

  1. cmake_minimum_required(VERSION 3.0.2)
  2. project(synchronizer)
  3. ## Compile as C++11, supported in ROS Kinetic and newer
  4. # add_compile_options(-std=c++11)
  5. ## Find catkin macros and libraries
  6. ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
  7. ## is used, also find other catkin packages
  8. find_package(catkin REQUIRED COMPONENTS
  9. cv_bridge
  10. roscpp
  11. sensor_msgs
  12. std_msgs
  13. message_filters
  14. pcl_conversions
  15. )
  16. find_package(OpenCV REQUIRED)
  17. include_directories(${OpenCV_INCLUDE_DIRS})
  18. message(STATUS "version: ${OpenCV_VERSION}")
  19. find_package(PCL REQUIRED QUIET)
  20. include_directories(${PCL_INCLUDE_DIRS})
  21. ## System dependencies are found with CMake's conventions
  22. # find_package(Boost REQUIRED COMPONENTS system)
  23. ## Uncomment this if the package has a setup.py. This macro ensures
  24. ## modules and global scripts declared therein get installed
  25. ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
  26. # catkin_python_setup()
  27. ################################################
  28. ## Declare ROS messages, services and actions ##
  29. ################################################
  30. ## To declare and build messages, services or actions from within this
  31. ## package, follow these steps:
  32. ## * Let MSG_DEP_SET be the set of packages whose message types you use in
  33. ## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
  34. ## * In the file package.xml:
  35. ## * add a build_depend tag for "message_generation"
  36. ## * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
  37. ## * If MSG_DEP_SET isn't empty the following dependency has been pulled in
  38. ## but can be declared for certainty nonetheless:
  39. ## * add a exec_depend tag for "message_runtime"
  40. ## * In this file (CMakeLists.txt):
  41. ## * add "message_generation" and every package in MSG_DEP_SET to
  42. ## find_package(catkin REQUIRED COMPONENTS ...)
  43. ## * add "message_runtime" and every package in MSG_DEP_SET to
  44. ## catkin_package(CATKIN_DEPENDS ...)
  45. ## * uncomment the add_*_files sections below as needed
  46. ## and list every .msg/.srv/.action file to be processed
  47. ## * uncomment the generate_messages entry below
  48. ## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
  49. ## Generate messages in the 'msg' folder
  50. # add_message_files(
  51. # FILES
  52. # Message1.msg
  53. # Message2.msg
  54. # )
  55. ## Generate services in the 'srv' folder
  56. # add_service_files(
  57. # FILES
  58. # Service1.srv
  59. # Service2.srv
  60. # )
  61. ## Generate actions in the 'action' folder
  62. # add_action_files(
  63. # FILES
  64. # Action1.action
  65. # Action2.action
  66. # )
  67. ## Generate added messages and services with any dependencies listed here
  68. # generate_messages(
  69. # DEPENDENCIES
  70. # sensor_msgs# std_msgs
  71. # )
  72. ################################################
  73. ## Declare ROS dynamic reconfigure parameters ##
  74. ################################################
  75. ## To declare and build dynamic reconfigure parameters within this
  76. ## package, follow these steps:
  77. ## * In the file package.xml:
  78. ## * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
  79. ## * In this file (CMakeLists.txt):
  80. ## * add "dynamic_reconfigure" to
  81. ## find_package(catkin REQUIRED COMPONENTS ...)
  82. ## * uncomment the "generate_dynamic_reconfigure_options" section below
  83. ## and list every .cfg file to be processed
  84. ## Generate dynamic reconfigure parameters in the 'cfg' folder
  85. # generate_dynamic_reconfigure_options(
  86. # cfg/DynReconf1.cfg
  87. # cfg/DynReconf2.cfg
  88. # )
  89. ###################################
  90. ## catkin specific configuration ##
  91. ###################################
  92. ## The catkin_package macro generates cmake config files for your package
  93. ## Declare things to be passed to dependent projects
  94. ## INCLUDE_DIRS: uncomment this if your package contains header files
  95. ## LIBRARIES: libraries you create in this project that dependent projects also need
  96. ## CATKIN_DEPENDS: catkin_packages dependent projects also need
  97. ## DEPENDS: system dependencies of this project that dependent projects also need
  98. catkin_package(
  99. # INCLUDE_DIRS include
  100. # LIBRARIES synchronizer
  101. # CATKIN_DEPENDS cv_bridge roscpp sensor_msgs std_msgs
  102. # DEPENDS system_lib
  103. # DEPENDS OpenCV
  104. )
  105. ###########
  106. ## Build ##
  107. ###########
  108. ## Specify additional locations of header files
  109. ## Your package locations should be listed before other locations
  110. include_directories(
  111. # include
  112. ${catkin_INCLUDE_DIRS}
  113. )
  114. ## Declare a C++ library
  115. # add_library(image_publisher
  116. # src/image_publisher.cpp
  117. # )
  118. ## Add cmake target dependencies of the library
  119. ## as an example, code may need to be generated before libraries
  120. ## either from message generation or dynamic reconfigure
  121. # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
  122. ## Declare a C++ executable
  123. ## With catkin_make all packages are built within a single CMake context
  124. ## The recommended prefix ensures that target names across packages don't collide
  125. add_executable(image_publisher /home/guo/Downloads/syn_ws/src/synchronizer/src/image_publisher.cpp)
  126. add_executable(synchronized_subscriber /home/guo/Downloads/syn_ws/src/synchronizer/src/synchronized_subscriber.cpp)
  127. ## Rename C++ executable without prefix
  128. ## The above recommended prefix causes long target names, the following renames the
  129. ## target back to the shorter version for ease of user use
  130. ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
  131. # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
  132. ## Add cmake target dependencies of the executable
  133. ## same as for the library above
  134. # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
  135. ## Specify libraries to link a library or executable target against
  136. target_link_libraries(image_publisher
  137. ${catkin_LIBRARIES}
  138. ${OpenCV_INCLUDE_DIRS}
  139. ${PCL_INCLUDE_DIRS}
  140. )
  141. target_link_libraries(synchronized_subscriber
  142. ${catkin_LIBRARIES}
  143. )
  144. #############
  145. ## Install ##
  146. #############
  147. # all install targets should use catkin DESTINATION variables
  148. # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
  149. ## Mark executable scripts (Python etc.) for installation
  150. ## in contrast to setup.py, you can choose the destination
  151. # catkin_install_python(PROGRAMS
  152. # scripts/my_python_script
  153. # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
  154. # )
  155. ## Mark executables for installation
  156. ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
  157. # install(TARGETS ${PROJECT_NAME}_node
  158. # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
  159. # )
  160. ## Mark libraries for installation
  161. ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
  162. # install(TARGETS ${PROJECT_NAME}
  163. # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  164. # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  165. # RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
  166. # )
  167. ## Mark cpp header files for installation
  168. # install(DIRECTORY include/${PROJECT_NAME}/
  169. # DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  170. # FILES_MATCHING PATTERN "*.h"
  171. # PATTERN ".svn" EXCLUDE
  172. # )
  173. ## Mark other files for installation (e.g. launch and bag files, etc.)
  174. # install(FILES
  175. # # myfile1
  176. # # myfile2
  177. # DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
  178. # )
  179. #############
  180. ## Testing ##
  181. #############
  182. ## Add gtest based cpp test target and link libraries
  183. # catkin_add_gtest(${PROJECT_NAME}-test test/test_synchronizer.cpp)
  184. # if(TARGET ${PROJECT_NAME}-test)
  185. # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
  186. # endif()
  187. ## Add folders to be run by python nosetests
  188. # catkin_add_nosetests(test)

4.4 launch文件

  1. <launch>
  2. <!-- Start the image_publisher_node -->
  3. <node name="synchronizer1" pkg="synchronizer" type="image_publisher" output="screen"/>
  4. <!-- Start the synchronized_subscriber_node -->
  5. <node name="synchronizer2" pkg="synchronizer" type="synchronized_subscriber" output="screen"/>
  6. </launch>

4.5 代码解释

  • 引入必要的ROS和消息过滤器头文件。
  • 定义回调函数 callback,用于处理同步的图像和激光雷达数据。
  • main 函数中创建 message_filters::Subscriber 对象,分别订阅相机图像和激光雷达扫描数据。
  • 使用 message_filters::sync_policies::ApproximateTime 创建 message_filters::Synchronizer 对象,设置时间同步策略为近似同步。
  • 注册回调函数到 Synchronizer 对象中,它将在图像和激光雷达数据近似同步时调用。

5. 运行和测试

        确保ROS环境已经启动,然后运行launch文件:

        运行结果:

图像和点云的时间辍实现同步。 

 

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

闽ICP备14008679号