节点
节点是机器人工作的基本单元,每个节点都是执行具体任务的进程,是独立运行的可执行文件,本身可以使用不同的编程语言。同时也满足分布式的运行,每个节点可以各自部署在不同的硬件设备,甚至云端,具体通过节点名称来管理。
启动节点的方法为,在命令行内运行完source源码后,通过ros2命令的如下语句启动:
ros2 run <包名> <包内可执行程序>
run为ros2的一个指令。
自行编写节点源码时,需要引入rclpy库(ros2的python接口库),示例代码如下:
import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类
import time
def main(args=None): # ROS2节点主入口main函数
rclpy.init(args=args) # ROS2 Python接口初始化
node = Node("node_helloworld") # 创建ROS2节点对象并进行初始化
while rclpy.ok(): # ROS2系统是否正常运行,ctrl+c中断后返回False
node.get_logger().info("Hello World") # ROS2日志输出
time.sleep(0.5) # 休眠控制循环时间
node.destroy_node() # 销毁节点对象
rclpy.shutdown() # 关闭ROS2 Python接口
核心为rclpy的node类指定节点,并使用rclpy的相关方法运行ros2。
上述代码可以优化为面向对象,直接继承node节点:
import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类
import time
class HelloWorldNode(Node):
def __init__(self, name):
super().__init__(name) # ROS2节点父类初始化
while rclpy.ok(): # ROS2系统是否正常运行
self.get_logger().info("Hello World") # ROS2日志输出
time.sleep(0.5) # 休眠控制循环时间
def main(args=None): # ROS2节点主入口main函数
rclpy.init(args=args) # ROS2 Python接口初始化
node = HelloWorldNode("node_helloworld_class") # 创建ROS2节点对象并进行初始化
node.destroy_node() # 销毁节点对象
rclpy.shutdown() # 关闭ROS2 Python接口
编写完节点的源码后,还需在setup.py文件内配置可执行命令和对应的函数位置,即配置程序入口。
setup.py是编译python包时自动在包内创建的文件(c++包没有)。
在setup.py文件末找到名为entry_points的字典,配置其’console_scripts’元素对应的列表,列表中的每个字符串形如:节点命令名 = 命令对应函数所在的具体位置,位置是从setup.py自己所在的文件夹出发的,并要指明具体哪个.py文件中的哪个函数。具体例子如下:
entry_points={
'console_scripts': [
'node_helloworld = learning_node.node_helloworld:main',
'node_helloworld_class = learning_node.node_helloworld_class:main',
'node_object = learning_node.node_object:main',
'node_object_webcam = learning_node.node_object_webcam:main',
],
}
第一行字符串就表示,node_helloworld节点指令的源码在setup.py同级目录的learning_node中,其中的node_helloworld.py文件定义的main方法即为该节点本体。
在命令行,ros2也有一些管理节点的方法。
查看节点列表:
ros2 node list
查看节点详情:
ros2 node info <node_name>
以及上面提到过的运行单个节点:
ros2 run <package_name> <executable_name>
重命名节点:
ros2 run <package_name> <executable_name> --ros-args --remap __node:=<new_node_name>