环境:ubuntu20.04 ,ros-foxy(ros2), vscode

背景:一次需要读取多个velodyne的雷达点云数据,但是ros2知识缺少,一番折腾终有成果.

1.准备

velodyne的ros2版本驱动链接:https://github.com/ros-drivers/velodyne/tree/ros2

2.launch文件编写

2.1 官方launch编写样式

下面python代码是启动一个激光雷达情况,但是同时启动多个,并可分别读取点云数据才是我们考虑重点.
velodyne-all-nodes-VLP16-launch.py:

import os
import yaml

import ament_index_python.packages
import launch
import launch_ros.actions


def generate_launch_description():
    driver_share_dir = ament_index_python.packages.get_package_share_directory('velodyne_driver')
    driver_params_file = os.path.join(driver_share_dir, 'config', 'VLP16-velodyne_driver_node-params.yaml')
    velodyne_driver_node = launch_ros.actions.Node(package='velodyne_driver',
                                                   node_executable='velodyne_driver_node',
                                                   output='both',
                                                   parameters=[driver_params_file])

    convert_share_dir = ament_index_python.packages.get_package_share_directory('velodyne_pointcloud')
    convert_params_file = os.path.join(convert_share_dir, 'config', 'VLP16-velodyne_convert_node-params.yaml')
    with open(convert_params_file, 'r') as f:
        convert_params = yaml.safe_load(f)['velodyne_convert_node']['ros__parameters']
    convert_params['calibration'] = os.path.join(convert_share_dir, 'params', 'VLP16db.yaml')
    velodyne_convert_node = launch_ros.actions.Node(package='velodyne_pointcloud',
                                                    node_executable='velodyne_convert_node',
                                                    output='both',
                                                    parameters=[convert_params])

    laserscan_share_dir = ament_index_python.packages.get_package_share_directory('velodyne_laserscan')
    laserscan_params_file = os.path.join(laserscan_share_dir, 'config', 'default-velodyne_laserscan_node-params.yaml')
    velodyne_laserscan_node = launch_ros.actions.Node(package='velodyne_laserscan',
                                                      node_executable='velodyne_laserscan_node',
                                                      output='both',
                                                      parameters=[laserscan_params_file])


    return launch.LaunchDescription([velodyne_driver_node,
                                     velodyne_convert_node,
                                     velodyne_laserscan_node,

                                     launch.actions.RegisterEventHandler(
                                         event_handler=launch.event_handlers.OnProcessExit(
                                             target_action=velodyne_driver_node,
                                             on_exit=[launch.actions.EmitEvent(
                                                 event=launch.events.Shutdown())],
                                         )),
                                     ])

2.2 多个velodyne激光雷达启动launch文件编写

 

下面代码是实现同时启动两个激光雷达的launch文件,亦可推广到多个传感器在ros2环境启动情形.
想了解更多内容,可参看个人发表在ros社区提问链接:https://answers.ros.org/question/383667/how-to-start-multiple-lidar-in-one-file-in-ros2-environment/

import os
import yaml

import ament_index_python.packages
from launch import LaunchDescription
from launch_ros.actions import Node

#velodyne_1
def generate_launch_description():
    ld = LaunchDescription()

    driver_share_dir_1 = ament_index_python.packages.get_package_share_directory('velodyne_driver')
    driver_params_file_1 = os.path.join(driver_share_dir_1, 'config', 'vlp_1.yaml')
    velodyne_driver_node_1 = Node(
        package="velodyne_driver",
        executable="velodyne_driver_node",
        name="velodyne_driver_node_1",
        parameters=[driver_params_file_1],
        remappings=[
            ("velodyne_packets", "velodyne_packets_1")
        ]
    )

    convert_share_dir_1 = ament_index_python.packages.get_package_share_directory('velodyne_pointcloud')
    convert_params_file_1 = os.path.join(convert_share_dir_1, 'config', 'VLP16-velodyne_convert_node-params.yaml')
    with open(convert_params_file_1, 'r') as f:
        convert_params_1 = yaml.safe_load(f)['velodyne_convert_node']['ros__parameters']
    convert_params_1['calibration'] = os.path.join(convert_share_dir_1, 'params', 'VLP16db.yaml')
    velodyne_convert_node_1 = Node(
        package="velodyne_pointcloud",
        executable="velodyne_convert_node",
        name="velodyne_convert_node_1",
        parameters=[convert_params_1],
        remappings=[
            ("velodyne_packets", "velodyne_packets_1"),
            ("velodyne_points", "velodyne_points_1")
        ]
    )

    laserscan_share_dir_1 = ament_index_python.packages.get_package_share_directory('velodyne_laserscan')
    laserscan_params_file_1 = os.path.join(laserscan_share_dir_1, 'config', 'default-velodyne_laserscan_node-params.yaml')
    velodyne_laserscan_node_1 = Node(
        package="velodyne_laserscan",
        executable="velodyne_laserscan_node",
        name="velodyne_laserscan_node_1",
        parameters=[laserscan_params_file_1],
        remappings=[
            ("velodyne_points", "velodyne_points_1"),
            ("scan", "scan_1")
        ]
    )

    #velodyne_2
    driver_share_dir_2 = ament_index_python.packages.get_package_share_directory('velodyne_driver')
    driver_params_file_2 = os.path.join(driver_share_dir_2, 'config', 'vlp_1.yaml')
    velodyne_driver_node_2 = Node(
        package="velodyne_driver",
        executable="velodyne_driver_node",
        name="velodyne_driver_node_2",
        parameters=[driver_params_file_2],
        remappings=[
            ("velodyne_packets", "velodyne_packets_2")
        ]
    )

    convert_share_dir_2 = ament_index_python.packages.get_package_share_directory('velodyne_pointcloud')
    convert_params_file_2 = os.path.join(convert_share_dir_2, 'config', 'VLP16-velodyne_convert_node-params.yaml')
    with open(convert_params_file_2, 'r') as f:
        convert_params_2 = yaml.safe_load(f)['velodyne_convert_node']['ros__parameters']
    convert_params_2['calibration'] = os.path.join(convert_share_dir_2, 'params', 'VLP16db.yaml')
    velodyne_convert_node_2 = Node(
        package="velodyne_pointcloud",
        executable="velodyne_convert_node",
        name="velodyne_convert_node_2",
        parameters=[convert_params_2],
        remappings=[
            ("velodyne_packets", "velodyne_packets_2"),
            ("velodyne_points", "velodyne_points_2")
        ]
    )

    laserscan_share_dir_2 = ament_index_python.packages.get_package_share_directory('velodyne_laserscan')
    laserscan_params_file_2 = os.path.join(laserscan_share_dir_2, 'config', 'default-velodyne_laserscan_node-params.yaml')
    velodyne_laserscan_node_2 = Node(
        package="velodyne_laserscan",
        executable="velodyne_laserscan_node",
        name="velodyne_laserscan_node_2",
        parameters=[laserscan_params_file_2],
        remappings=[
            ("velodyne_points", "velodyne_points_2"),
            ("scan", "scan_2")
        ]
    )     

    ld.add_action(velodyne_driver_node_1)
    ld.add_action(velodyne_convert_node_1)
    ld.add_action(velodyne_laserscan_node_1)
    ld.add_action(velodyne_driver_node_2)
    ld.add_action(velodyne_convert_node_2)
    ld.add_action(velodyne_laserscan_node_2)
    return ld

rqt_graph效果图:

3.小结

1)python编写的launch文件,具有更强的灵活性,目前个人还比较菜,只会简单的

2)ros2环境下多传感器启动的launch文件编写,可由该样式推广

3)注意node发出的订阅者或发布者topic名字,remapping恰当,即可实现信息流的准确传递

4)注意多看官方文档,这次如:https://docs.ros.org/en/foxy/Guides/Launch-file-different-formats.html

5)一定要多看cmakelists.txt文件,以及源文件,搞清楚,node由哪个.cpp(源文件)生成的,发出的topic又有哪些,其订阅的topic名字以及发布的topic名字是什么;可以借助rqt_graph来梳理快速理解

###############
不积硅步,无以至千里
好记性不如烂笔头
感觉有点收获的话,麻烦大大们点赞收藏哈

来源:https://blog.csdn.net/qq_45701501/article/details/119486110