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,如下图所示(应该是移植成功):

相关推荐
we1998989839 分钟前
Ubuntu最新版本(Ubuntu22.04LTS)安装nfs服务器
linux·服务器·ubuntu
、我是男生。41 分钟前
Linux、Ubuntu、虚拟机三者的关系和角色
linux·运维·ubuntu
ghie90903 小时前
Ubuntu编译ffmpeg解决错误:ERROR: avisynth/avisynth_c.h not found
c语言·ubuntu·ffmpeg
Stuild Stuil5 小时前
Ubuntu 多网卡安全路由配置(SSH 不断线版)
安全·ubuntu·ssh
Y_3_77 小时前
Netty实战:从核心组件到多协议实现(超详细注释,udp,tcp,websocket,http完整demo)
linux·运维·后端·ubuntu·netty
昵称什么的不存在8 小时前
腾讯云轻量级服务器Ubuntu系统与可视化界面
服务器·ubuntu·腾讯云
Fireworkitte13 小时前
Ubuntu 和 CentOS 中配置静态 IP
tcp/ip·ubuntu·centos
Stuild Stuil15 小时前
自动恢复网络路由配置的安全脚本说明
linux·网络·ubuntu
RedMapleGI1 天前
ubuntu 22.04 安装部署kibana 7.10.0详细教程
ubuntu·elk·kibana