节点
ROS2中,节点是一个抽象的实体,可以代表某类特定功能的抽象集合体,可以存在于进程或线程中
是ROS2的基础功能的载体,所有通信都需要通过节点来实现
节点和节点执行器
节点执行器executor是协调和调度节点运作的实体,并响应各类通信的回调结果
每个进程有一个或多个节点执行器,每个节点执行器有一个或多个节点
节点执行器有以下几种
- 单线程节点执行器
将所有已添加到维护队列的节点限制在一个线程内处理,占用一个线程资源,并根据其指定的规则对回调顺序和优先级进行设定 - 多线程节点执行器
负责管理的回调函数可以占用多个线程,根据设备性能,动态分配线程数,为队列中的节点处理回调,默认为CPU核心数
std::thread::hardware_concurrency()
获取线程最大数量
线程回调的内容均来自于通信和等待任务,通信包含着订阅、服务、客户端和等待任务 - 静态单线程节点执行器
仅存在于rclcpp中,相对于普通单线程节点执行器可以有更低的CPU和内存占用率
ROS discourse社区的工程师每年在ROS论坛都会讨论新的节点执行器,为了提高其实效率和确定性等指标
建立节点
C++项目中,需要继承rclcpp::Node
基类,Python项目中,需要继承rclcpp.Node
基类
rclcpp默认方式是单线程节点执行器
节点命名规则
- 不能为空
- 第一个字符必须是字母、下划线、波浪号或斜杠
- 后面的字符可以是字母、数字、下划线或斜杠
- 使用下划线开头的节点是隐藏节点
节点执行器不会直接运行,需要通过节点执行器的spin()
函数完成节点的所有回调工作
在rclcpp中提供了多种节点执行器的回调操作模式,常用的spin
,spin_all
和spin_some
等
spin()
该函数会阻塞其他操作,节点执行器会完全并持续地执行回调工作直到被中断
通常在其后面的内容都是结束进程的回收工作spin_all()
该函数不会阻塞其他操作,节点执行器会持续执行所有回调工作,直到超时或无其他工作可做spin_some()
该函数不会阻塞其他操作,节点执行器会完成执行所有在调用spin_some()
时已准备就绪的回调,直到超时或无其他工作可做
与spin_all()
的区别是spin_some()
不会执行在执行过程中产生的回调spin_once()
该函数不会阻塞其他操作,只会执行已准备就绪的第一个回调,直到超时或无其他工作可做spin_node_once()
该函数会令节点执行器临时添加节点,执行一次spin_once()
后,移除节点spin_node_some()
该函数会令节点执行器临时添加节点,执行一次spin_once()
后,移除节点spin_until_future_complete()
该函数会令节点执行器执行回调直到future
的内容完成,或超时,或被中断
调试节点
ros2 node list
ros2 node info
进程、线程与节点的关系
按线程数量分为:单线程节点执行器和多线程节点执行器
使用命令行参数,指定节点数量和使用的执行器
s
表示单线程执行器
m
表示多线程执行器
ros2 run multi_node_cpp multinode 5 s
ros2 run multi_node_cpp multinode 2 m
若不增加节点数量,只增加回调函数和定时器数量,在多线程执行器的维护下,会不会产生更多线程?
创建节点文件
ros2 pkg create test --build-type ament_cmake
--node-name lifecycle --dependencies std_msgs rclcpp
ros2 pkg create node_cpp --node-name node2go
在命令中ros2 pkg create
可选--node-name
参数创建节点文件
或在功能包的src
下手动新建节点文件
发布者节点
修改package.xml
若想发布功能包,需修改package.xml
文件中的description,license标签
在ament_cmake
下边添加
<buildtool_depend>rclcpp</buildtool_depend>
<buildtool_depend>std_msgs</buildtool_depend>
添加依赖
<depend>rclcpp</depend>
修改CMakeLists.txt
find_package(rclcpp)
获取依赖软件包,用于查找当前环境已有的软件包,后期构建使用
会引入一系列变量,如头文件路径和库文件路径等
新增依赖项,用于动态链接和关系导出
ament_target_dependencies
是ament
构建体系中快速动态链接的方法
是ament构建体系中用于快速动态链接的方法,所有通过ament_cmake
构建的软件包都可以通过其进行链接
导出依赖关系
为了其他依赖当前功能包的项目
导出ament依赖项可以使基于ament_cmake
构建的功能包具备递归依赖的能力
添加软件包
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
设置编译规则
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
设置安装规则,这样ros2 run
命令才能找到可执行文件
install(TARGETS
talker
DESTINATION lib/${PROJECT_NAME})
编译运行
确认功能包依赖项
在工作空间dev_ws
下运行rosdep install -i --from-path src --rosdistro eloquent -y
在工作空间目录dev_ws
下使用colcon build
编译
若只想编译指定的包时,可使用colcon build --packages-select <my_package>
在工作空间目录下,使用. install/setup.bash
命令,将工作空间添加到路径
ros2 run my_package my_node