ROS2-第一个节点和功能包
1、节点学习
节点可视作一个单独的模块化功能(比如一个节点负责控制车轮转动、一个节点负责定位等)。
节点和节点间有四种通信方式:
- 话题(topics)
- 服务(services)
- 动作(Action)
- 参数(parameters)
启动一个节点
# 启动包package_name中的可执行文件executable_name
ros2 run <package_name> <executable_name>
如 ros2 run turtlesim turtlesim_node
其中package在某工作空间(文件夹)内,一个工作空间下可以有多个功能包,一个功能包可以有多个节点存在
查看节点列表
ros2 node list
查看节点信息
# 查看节点node_name的信息
ros2 node info <node_name>
2、创建第一个节点
新建一个文件夹和python文件(如ROS2/first_node.py),输入以下代码:
# !/usr/bin/env python3
# 导入rclpy库
import rclpy
from rclpy.node import Node
# 调用初始化函数
rclpy.init()
# 创建节点“first_node”并循环运行
rclpy.spin(Node("first_node"))
新建两个终端(A、B),终端A运行first_node.py
python3 first_node.py
终端B运行命令查看当前ROS2系统中的节点
ros2 node list
可看到成功创建了一个名为first_node的节点

3、创建第一个包
- 创建一个名字叫做 my_package 的功能包
# 创建一个名为my_package的功能包,使用ament编译,依赖rclpy库
ros2 pkg create my_package --build-type ament_python --dependencies rclpy

当前目录下自动生成了一个名为my_package的功能包文件夹
- 在my_package/my_package/目录下创建一个python文件(如second_node.py),并输入以下代码:
import rclpy
from rclpy.node import Node
def main(args=None):
"""
ros2运行该节点的入口函数
编写ROS2节点的一般步骤
1. 导入库文件
2. 初始化客户端库
3. 新建节点对象
4. spin循环节点
5. 关闭客户端库
"""
rclpy.init(args=args) # 初始化rclpy
node = Node("node_02") # 新建一个节点
node.get_logger().info("大家好,我是node_02.") # 输出日志信息
rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
rclpy.shutdown() # 关闭rclpy
- 然后声明该节点:在my_package/setup.py文件中修改entry_points入口参数:
entry_points={
'console_scripts': [
"node2 = my_package.second_node:main"
],
},
其中 node2即为 executable_name,my_package.second_node:main为该节点的入口函数路径(即my_package/my_package/second_node.py文件中的main函数)
- 在工作空间(第一层my_package/)下编译功能包
colcon build
colcon是ROS2推荐的构建工具,通过调用CMake或Python的setuptools等工具进行构建,支持多包构建和依赖管理

- 编译完成后,source安装目录下的setup.bash文件以加载环境
source install/setup.bash
- 运行程序
ros2 run my_package node2
可看到终端输出了日志信息

- 面向对象编程方式创建节点
节点的概念很适合面向对象编程,我们可以将节点封装成一个类,继承自Node类,并在类中定义节点的功能和行为
my_package/my_package/third_node.py
import rclpy
from rclpy.node import Node
class Node03(Node):
"""
创建一个名为Node03的节点类,继承自Node类
初始化时输出一句日志信息
"""
def __init__(self,name):
super().__init__(name) # 初始化父类Node
self.get_logger().info(f"大家好,我是{name}.") # 输出日志信息
def main(args=None):
rclpy.init(args=args) # 初始化rclpy
node = Node03("node_03") # 新建一个节点对象,传入节点名称参数
rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
rclpy.shutdown() # 关闭rclpy,正常无法到达该语句
声明该节点
entry_points={
'console_scripts': [
"node2 = my_package.second_node:main",
"node3 = my_package.third_node:main"
],
},
按上述步骤编译运行
