ROS2移植【激光点云】(hdl_localization)

移植源码:koide3/hdl_localization: Real-time 3D localization using a (velodyne) 3D LIDAR

移植后的代码:https://github.com/XzLuckh/hdl_localization

一、ROS2介绍

ROS 1 和 ROS 2 是机器人操作系统(Robot Operating System)的两个主要版本,ROS 2 是对 ROS 1 的全面升级,解决了 ROS 1 的许多架构缺陷,并引入了现代机器人开发所需的新特性。下面对ROS1和ROS2进行对比:

|------|------------------|--------------------------|
| | ROS1 | ROS2 |
| 通信机制 | 依赖 Master,TCPROS | DDS,去中心化 |
| 实时性 | 较差 | 支持 QoS,更实时 |
| 跨平台 | 主要 Linux | Linux/Windows/macOS/RTOS |
| 编程语言 | C++03/Python 2 | C++17/Python 3 |
| 构建系统 | catkin | ament/colcon |

我在ROS1中部署了该项目,实现效果如下:

二、hdl_localization代码移植

首先得安装一个ROS2系统(可参考以下博客):

Ubuntu安装ROS(2) ------ 安装ROS2 humble(最新、超详细图文教程,包含配置rosdep)_ros2安装-CSDN博客

首先查看hdl_localization包的结构,直接查看其CMakeLists.txt文件

我们需要在ROS2 系统中创建一个新的工作空间

bash 复制代码
mkdir -p ros2_ws_test/src

将hdl_localization项目克隆到src文件目录下

bash 复制代码
git clone https://github.com/koide3/hdl_localization

准备工作完成后,首先应该对CMakeLists.txt文件进行修改。下面先给出ROS1和ROS2的主要区别。

ROS1与ROS2的CMakeLists.txt文件在构建系统设计上存在显著差异,主要体现在架构理念和实现方式上。ROS1基于传统的catkin构建系统,采用集中式的依赖管理方式,通过catkin_package()宏统一处理包信息和依赖关系,其语法相对简单但灵活性较低。而ROS2采用现代化的ament_cmake构建系统,遵循更模块化的设计原则,每个依赖项需独立声明,使用面向目标的现代CMake特性(如命名空间目标和接口库),使得依赖关系更清晰、包隔离性更好。在安装部署方面,ROS2简化了安装规则但增加了导出控制的显式声明,同时引入标准化的测试框架集成方式。这些改进使ROS2的构建系统在跨平台支持、依赖管理和可维护性方面具有明显优势,但也要求开发者掌握更复杂的CMake编写规范。总体而言,从ROS1到ROS2的CMake配置转变反映了构建系统从简单统一向灵活精确的设计演进趋势。

基础框架对比:

ROS1

cs 复制代码
cmake_minimum_required(VERSION 2.8.3)
project(my_pkg)
 
find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)
 
catkin_package()

ROS2

cs 复制代码
cmake_minimum_required(VERSION 3.5)
project(my_pkg)
 
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
 
ament_package()

对于package.xml:ROS1 采用分层次的依赖声明(如 build_depend、exec_depend),需单独处理消息生成的编译/运行时依赖(message_generation 和 message_runtime),格式支持 version 1 或 2;而 ROS2 强制使用 version 3 格式,大幅简化依赖分类,用统一的 <depend> 替代 ROS1 的多类依赖,合并消息生成工具为 rosidl_default_generators,并强制显式声明构建工具(如 ament_cmake)。此外,ROS2 更频繁使用 <export> 标签定义组件插件,体现其模块化设计理念。这些改动使 ROS2 的依赖管理更简洁,但要求更严格的规范遵循。

依赖包的区别

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ROS1 | ROS2 |
| find_package(catkin REQUIRED COMPONENTS nodelet tf2 tf2_ros tf2_eigen tf2_geometry_msgs eigen_conversions pcl_ros roscpp rospy sensor_msgs geometry_msgs message_generation ndt_omp fast_gicp hdl_global_localization ) | find_package(rclcpp REQUIRED) find_package(rcl REQUIRED) find_package(std_msgs REQUIRED) find_package(sensor_msgs REQUIRED) find_package(geometry_msgs REQUIRED) find_package(tf2 REQUIRED) find_package(tf2_ros REQUIRED) find_package(tf2_eigen REQUIRED) find_package(tf2_geometry_msgs REQUIRED) find_package(pluginlib REQUIRED) find_package(pcl_conversions REQUIRED) find_package(statistics_msgs REQUIRED) |

rclcpp 替代了 roscpp 作为 C++ 客户端库,tf2 系列包(如 tf2_ros)在 ROS2 中保留了相同功能但实现更现代化,而 pluginlib 仍然用于插件机制但集成更标准化。此外,ROS2 新增了 rcl 作为底层客户端库,不再需要 message_generation,并将 nodelet 替换为 Component 机制。对于点云处理,pcl_ros 的功能在 ROS2 中主要通过 pcl_conversions 和原生 PCL 实现。整体上,ROS2 的依赖管理更模块化,许多 ROS1 包在 ROS2 中仍保持同名但接口可能略有调整,部分功能包(如 ndt_omp)则需要寻找 ROS2 兼容版本或自行移植。

下面给出部分ROS2版本的CMakeLists.txt文件代码:

然后对package.xml进行修改

对于hdl_localization包中的.msg文件,ROS2与ROS1不同:

  • ROS 1 允许将 .msg 文件放在功能包的 msg/ 目录下,通过 add_message_files() 生成。
  • ROS 2 要求自定义消息必须放在 独立的接口包(如 ros2_msgs)中,通过 rosidl_generate_interfaces() 生成。

因此需要在ROS2中创建一个ros2_msgs接口包。

ros2_msg编译成功

接下来要对cpp文件进行修改:

1.头文件更改

#include <ros/ros.h> 改为 #include "rclcpp/rclcpp.hpp"

#include<ros/time.h> 改为 #include "rclcpp/time.hpp"

#include <pcl_ros/point_cloud.h>

改为:

#include <pcl_conversions/pcl_conversions.hpp> // 用于PCL和ROS2消息的转换

#include <sensor_msgs/msg/point_cloud2.hpp> // ROS2的PointCloud2消息

  1. 显式转换

ROS1的pcl_ros/point_cloud.h 定义了pcl::Pointcloud<T>到sensor_msgs::PointCloud2的便捷转换,而 ROS2 需要显式转换:

ROS1风格:

cs 复制代码
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::Pointcloud<pcl::PointXYZ>);
sensor_msgs::PointCloud2 output;
pcl::toROSMsg(*cloud, output):

ROS2风格:

cs 复制代码
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl: :PointXYZ>);
auto output = std::make_shared<sensor_msgs::msg::Pointcloud2>();
pcl::toRoSMsg(*cloud, *output);
  1. 更换时间API

hd1_1ocalization 中的代码使用了ROS 1的时间API(ros::Time),但ROS 2中使用的是rclcpp::Time ,API有所不同

替换所有的time.is_zero()为:time == rclcpp::Time(0, 0, time.get_clock_type())

替换所有的duration.toSec()为:duration.seconds()

ROS1和ROS2的启动launch文件也存在较大的差异:

ROS1的.launch文件是基于XML格式,使用<launch>作为根标签,通过标签定义节点和参数。典型示例如下:

cs 复制代码
<launch>
  <node pkg="turtlesim" type="turtlesim_node" name="sim"/>
  <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
   
  <param name="scale_linear" value="2" type="double"/>
  <param name="scale_angular" value="2" type="double"/>
   
  <rosparam file="$(find pkg)/config/params.yaml" command="load"/>
</launch>

ROS2的launch.py文件是基于Python脚本使用LaunchDescription类,通过函数和对象定义启动行为。典型示例如下:

cs 复制代码
from launch import LaunchDescription
from launch_ros.actions import Node
 
def generate_launch_description():
    return LaunchDescription([
        Node(
            package='turtlesim',
            executable='turtlesim_node',
            name='sim'
        ),
        Node(
            package='turtlesim',
            executable='turtle_teleop_key',
            name='teleop',
            output='screen'
        )
    ])

所有的cpp文件和hpp文件修改完成后,还需要修改对应的CMakeList.txt和Package.xml文件然后对工作空间进行编译。在此编译过程间会遇到很多报错问题,需要逐个解决,这里没有记录,不再叙述。

最终改完所有报错信息。如上图所示,编译成功

导入data/map.pcd文件启动rviz,如下图所示(应该是移植成功):

相关推荐
欧云服务器4 天前
怎么让脚本命令可以同时在centos、debian、ubuntu执行?
ubuntu·centos·debian
智渊AI4 天前
Ubuntu 20.04/22.04 下通过 NVM 安装 Node.js 22(LTS 稳定版)
ubuntu·node.js·vim
The️4 天前
Linux驱动开发之Read_Write函数
linux·运维·服务器·驱动开发·ubuntu·交互
再战300年5 天前
Samba在ubuntu上安装部署
linux·运维·ubuntu
qwfys2005 天前
How to install golang 1.26.0 to Ubuntu 24.04
ubuntu·golang·install
木尧大兄弟5 天前
Ubuntu 系统安装 OpenClaw 并接入飞书记录
linux·ubuntu·飞书·openclaw
小虾爬滑丫爬5 天前
ubuntu上设置Tomcat 开机启动
ubuntu·tomcat·开机启动
老师用之于民5 天前
【DAY25】线程与进程通信:共享内存、同步机制及实现方案
linux·c语言·ubuntu·visual studio code
小虾爬滑丫爬5 天前
Ubuntu 上设置防火墙
ubuntu·防火墙
林开落L5 天前
解决云服务器内存不足:2 分钟搞定 Ubuntu swap 交换区配置(新手友好版)
运维·服务器·ubuntu·swap交换区