当前位置:   article > 正文

在ROS中将点云(PointCloud2)生成Octomap,rviz可视化显示_ros octomap

ros octomap

一个python文件作为publisher,发布点云数据。一个C++项目接收点云数据,引用octomap库,将点云生成octomap的tree,在将tree通过topic发布出去,rviz订阅octomap tree的topic进行可视化显示。

首先创建一个python的点云发布节点,用pycharm开发,在Project Structure中加入ros的package:在C++和Python的项目中使用ROS-CSDN博客

  1. import rospy
  2. from sensor_msgs.msg import PointCloud2
  3. from sensor_msgs import point_cloud2
  4. import numpy as np
  5. # 初始化ROS节点
  6. rospy.init_node('pointcloud_publisher', anonymous=True)
  7. # 创建ROS Publisher
  8. pub = rospy.Publisher('your_pointcloud_topic', PointCloud2, queue_size=10)
  9. rate = rospy.Rate(1) # 设置发布频率为1Hz,你可以根据需要调整
  10. while not rospy.is_shutdown():
  11. # 创建一个NumPy数组,包含点云数据
  12. point_cloud_data = np.array([
  13. [1.0, 2.0, 0.0], # 三个坐标 (x, y, z) 和一个强度值
  14. [2.0, 3.0, 0.0],
  15. [3.0, 4.0, 0.0],
  16. # 添加更多点云数据行
  17. ])
  18. # 创建Pointcloud2消息
  19. header = rospy.Header()
  20. header.stamp = rospy.Time.now()
  21. header.frame_id = 'your_frame_id' # 设置帧ID
  22. cloud_msg = point_cloud2.create_cloud_xyz32(header, point_cloud_data)
  23. pub.publish(cloud_msg)
  24. print(cloud_msg.header.stamp.to_sec())
  25. rate.sleep()

接下来创建一个C++项目,即创建工作空间文件夹,工作空间中包括:include,src,build文件夹,以及CMakeLists.txt,src中创建main.cpp。C++项目包括三个功能,一是订阅点云topic,二是将点云转成octomap的tree,三是将tree发布,让rviz可视化。实现这三个功能,需要做如下的准备:

订阅点云topic功能的准备:

安装pcl

sudo apt install libpcl-dev

再安装pcl_msgs(不知道为什么pcl_msgs不在pcl包里),中间的melodic替换为自己的ros版本。

sudo apt-get install ros-melodic-pcl-msgs

再继续把https://github.com/ros-perception/perception_pcl/blob/melodic-devel/pcl_conversions/include/pcl_conversions/pcl_conversions.h

这个pcl_conversions.h文件放到自己项目的include文件夹中, 后面回用到这个头文件里的一个函数 fromROSMsg,函数 fromROSMsg依赖pcl_msgs,其功能是将ros topic的sensor_msgs::PointCloud2::ConstPtr 数据转化为 pcl::PointCloud<pcl::PointXYZ> 数据。

点云生成octomap的准备:

安装octomap

  1. git clone https://github.com/OctoMap/octomap.git
  2. cd octomap
  3. mkdir build
  4. cd build
  5. cmake ..
  6. make
  7. sudo make install

通过topic发布octomap tree的准备:

下载octomap_msgs项目:https://github.com/OctoMap/octomap_msgs/tree/melodic-devel

 这里要选择自己的ros版本,noetic可以用melodic。(不知道为什么octomap_msgs不继承进octomap)

 下载之后通过cmake编译

  1. cd octomap_msgs
  2. mkdir build
  3. cd build
  4. cmake ..
  5. make

在octomap_msgs/build/devel/share/octomap_msgs/cmake中,有octomap_msgsConfig.cmake,在自己项目的要使用octomap_msgs时,CMakeLists.txt中set这个Config.cmake为 octomap_msgs_DIR,使得cmake在find_packege时,能够找到octomap_msgs。

到这里,准备工作都完成了。

C++代码以及CMakeLists.txt内容:

main.cpp这样写

  1. #include "ros/ros.h"
  2. #include "sensor_msgs/PointCloud2.h"
  3. #include <pcl/io/pcd_io.h>
  4. #include <pcl/point_types.h>
  5. #include <octomap/octomap.h>
  6. #include <octomap/Pointcloud.h>
  7. #include <octomap/ColorOcTree.h>
  8. #include <octomap_msgs/Octomap.h>
  9. #include "pcl_conversions.h"
  10. #include "/home/username/Downloads/octomap_msgs/include/octomap_msgs/conversions.h"
  11. // Create an Octomap message
  12. octomap_msgs::Octomap octomap_msg;
  13. class MapGenerator{
  14. public:
  15. MapGenerator(){
  16. tree = new octomap::OcTree(0.1);
  17. };
  18. ~MapGenerator(){};
  19. void PointCloudCallback(const sensor_msgs::PointCloud2::ConstPtr& msg);
  20. octomap::OcTree* tree;
  21. };
  22. void print_query_info(octomap::point3d query, octomap::OcTreeNode* node) {
  23. if (node != NULL) {
  24. std::cout << "occupancy probability at " << query << ":\t " << node->getOccupancy() << std::endl;
  25. }
  26. else
  27. std::cout << "occupancy probability at " << query << ":\t is unknown" << std::endl;
  28. }
  29. int main(int argc, char **argv)
  30. {
  31. // 初始化ROS节点
  32. ros::init(argc, argv, "pointcloud_subscriber");
  33. // 创建ROS节点句柄
  34. ros::NodeHandle nh;
  35. MapGenerator mg;
  36. // 创建Subscriber来订阅PointCloud2消息
  37. ros::Subscriber sub = nh.subscribe<sensor_msgs::PointCloud2>("your_pointcloud_topic", 10, boost::bind(&MapGenerator::PointCloudCallback, &mg, _1));
  38. // Create a publisher for the Octomap topic
  39. ros::Publisher octomap_pub = nh.advertise<octomap_msgs::Octomap>("octomap_tree", 1);
  40. // Publish the Octomap
  41. ros::Rate loop_rate(1); // Adjust the publishing rate as needed
  42. while (ros::ok()) {
  43. octomap_pub.publish(octomap_msg);
  44. ros::spinOnce();
  45. loop_rate.sleep();
  46. }
  47. return 0;
  48. }
  49. // 回调函数,用于处理接收到的PointCloud2消息
  50. void MapGenerator::PointCloudCallback(const sensor_msgs::PointCloud2::ConstPtr& msg)
  51. {
  52. pcl::PointCloud<pcl::PointXYZ> pcl_cloud;
  53. pcl::fromROSMsg(*msg, pcl_cloud);
  54. for (const auto& point : pcl_cloud) {
  55. // Extract XYZ coordinates and RGB color from the point
  56. float x = point.x;
  57. float y = point.y;
  58. float z = point.z;
  59. // Convert color to octomap::ColorOcTreeNode
  60. octomap::point3d octomap_point(x, y, z);
  61. // Insert the node into the octomap
  62. tree->updateNode(octomap_point, true);
  63. }
  64. // octomap::point3d query = octomap::point3d(1., 2., 0.);
  65. // octomap::OcTreeNode* result = tree->search(query);
  66. // print_query_info(query, result);
  67. // Also publish as an octomap msg for visualization
  68. octomap_msgs::fullMapToMsg(*tree, octomap_msg);
  69. // 在这里可以对OctoMap进行其他操作,如保存地图数据
  70. // tree.writeBinary("your_octomap.ot");
  71. ROS_INFO("OctoMap created and saved.");
  72. }

CMakeLists.txt这样写

  1. cmake_minimum_required(VERSION 2.8)
  2. project(my_map)
  3. set(CMAKE_BUILD_TYPE "Debug")
  4. find_package(catkin REQUIRED COMPONENTS
  5. roscpp
  6. sensor_msgs
  7. std_msgs
  8. pcl_msgs
  9. )
  10. find_package(octomap REQUIRED)
  11. find_package(PCL REQUIRED)
  12. set(octomap_msgs_DIR /home/username/Downloads/octomap_msgs/build/devel/share/octomap_msgs/cmake/octomap_msgsConfig.cmake)
  13. find_package(octomap_msgs REQUIRED)
  14. include_directories(${PCL_INCLUDE_DIRS})
  15. link_directories(${PCL_LIBRARY_DIRS})
  16. add_definitions(${PCL_DEFINITIONS})
  17. include_directories(
  18. ./include
  19. ${catkin_INCLUDE_DIRS}
  20. ${OCTOMAP_INCLUDE_DIRS}
  21. )
  22. set(SRC_LIST
  23. ./src/main.cpp)
  24. add_executable(main ${SRC_LIST})
  25. target_link_libraries( main
  26. ${catkin_LIBRARIES}
  27. ${OCTOMAP_LIBRARIES}
  28. ${PCL_LIBRARIES}
  29. )

因为是使用vscode开发,c_cpp_properties.json这样写,不用vscode就不需要了。

  1. {
  2. "configurations": [
  3. {
  4. "name": "Linux",
  5. "includePath": [
  6. "${workspaceFolder}/**",
  7. "/opt/ros/你的ros版本/include/",
  8. "/usr/include/eigen3",
  9. "/usr/include/pcl-1.10/"
  10. ],
  11. "defines": [],
  12. "compilerPath": "/usr/bin/gcc",
  13. "cStandard": "c17",
  14. "cppStandard": "gnu++14",
  15. "intelliSenseMode": "linux-gcc-x64"
  16. }
  17. ],
  18. "version": 4
  19. }

代码和CMakeLists解释:

回调函数中的

  1. pcl::PointCloud<pcl::PointXYZ> pcl_cloud;
  2. pcl::fromROSMsg(*msg, pcl_cloud);

是在include文件夹中,下载的那个头文件里。

回调函数中

octomap_msgs::fullMapToMsg(*tree, octomap_msg);

这句话是将tree通过topic发布,这个函数在我们下载并编译的octomap_msgs中,为了使用它,在CMakeLists中需要包含如下代码,并且在main.cpp的开头include它的头文件。

  1. set(octomap_msgs_DIR /home/username/Downloads/octomap_msgs/build/devel/share/octomap_msgs/cmake/octomap_msgsConfig.cmake)
  2. find_package(octomap_msgs REQUIRED)

然后就可以编译运行了。

在ubuntu中使用vscode进行C++开发的方法,参考:Ubuntu使用cmake和vscode开发自己的项目,引用自己的头文件和openCV-CSDN博客

 最后一步通过rviz可视化,只要安装一个插件就可以

sudo apt-get install ros-kinetic-octomap-rviz-plugins

kinetic换成你的ubuntu版本。

rosrun rviz rviz

Add OccupancyMap

也可以用octovis进行可视化

sudo apt-get install ros-noetic-octovis
octovis your_octomap.ot

完成!

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

闽ICP备14008679号