写点什么

ROS 核心概念解析:从 Node 到 Master,再到 roslaunch 的全面指南

作者:芯动大师
  • 2025-01-10
    四川
  • 本文字数:2413 字

    阅读完需:约 8 分钟

ROS核心概念解析:从Node到Master,再到roslaunch的全面指南

Node

在 ROS 中,最小的进程单元就是节点(node)。一个软件包里可以有多个可执行文件,可执行文件在运行之后就成了一个进程(process),这个进程在 ROS 中就叫做节点。 从程序角度来说,node 就是一个可执行文件(通常为 C++编译生成的可执行文件、Python 脚本)被执行,加载到了内存之中;从功能角度来说,通常一个 node 负责者机器人的某一个单独的功能。由于机器人的功能模块非常复杂,我们往往不会把所有功能都集中到一个 node 上,而会采用分布式的方式,把鸡蛋放到不同的篮子里。

Master

由于机器人的元器件很多,功能庞大,因此实际运行时往往会运行众多的 node,负责感知世界、控制运动、决策和计算等功能。那么如何合理的进行调配、管理这些 node?这就要利用 ROS 提供给我们的节点管理器 master, master 在整个网络通信架构里相当于管理中心,管理着各个 node。node 首先在 master 处进行注册,之后 master 会将该 node 纳入整个 ROS 程序中。node 之间的通信也是先由 master 进行“牵线”,才能两两的进行点对点通信。当 ROS 程序启动时,第一步首先启动 master,由节点管理器处理依次启动 node。

启动 master 和 node

当我们要启动 ROS 时,首先输入命令:

$ roscore
复制代码

此时 ROS master 启动,同时启动的还有rosoutparameter server,其中rosout是负责日志输出的一个节点,其作用是告知用户当前系统的状态,包括输出系统的 error、warning 等等,并且将 log 记录于日志文件中,parameter server即是参数服务器,它并不是一个 node,而是存储参数配置的一个服务器。每一次我们运行 ROS 的节点前,都需要把 master 启动起来,这样才能够让节点启动和注册。

master 之后,节点管理器就开始按照系统的安排协调进行启动具体的节点。节点就是一个进程,只不过在 ROS 中它被赋予了专用的名字—node。我们知道一个 package 中存放着可执行文件,可执行文件是静态的,当系统执行这些可执行文件,将这些文件加载到内存中,它就成为了动态的 node。

具体启动 node 的语句是:

$ rosrun pkg_name node_name
复制代码

通常我们运行 ROS,就是按照这样的顺序启动,有时候节点太多,我们会选择用 launch 文件来启动。 Master、Node 之间以及 Node 之间的关系如下图所示:



rosrun 和 rosnode 命令

rosrun 命令的详细用法如下

$ rosrun [--prefix cmd] [--debug] pkg_name node_name [ARGS]
复制代码

rosrun 将会寻找 PACKAGE 下的名为 EXECUTABLE 的可执行程序,将可选参数 ARGS 传入。

例如在 GDB 下运行 ros 程序:

$ rosrun --prefix 'gdb -ex run --args' pkg_name node_name
复制代码

rosnode 命令的详细作用列表如下



以上命令中常用的为前三个,在开发调试时经常会需要查看当前 node 以及 node 信息,所以请记住这些常用命令。如果想不起来,也可以通过rosnode help来查看rosnode命令的用法。

机器人是一个系统工程,通常一个机器人运行操作时要开启多个 node,对于一个复杂的机器人的启动操作应该怎么做呢?当然,我们并不需要每个节点依次进行 rosrun,ROS 为我们提供了一个命令能一次性启动 master 和多个 node。该命令是:

$ roslaunch pkg_name file_name.launch
复制代码

roslaunch 命令首先会自动进行检测系统的 roscore 有没有运行,也即是确认节点管理器是否在运行状态中,如果 master 没有启动,那么 roslaunch 就会首先启动 master,然后再按照 launch 的规则执行。launch 文件里已经配置好了启动的规则。 所以roslaunch就像是一个启动工具,能够一次性把多个节点按照我们预先的配置启动起来,减少我们在终端中一条条输入指令的麻烦。

launch 文件同样也遵循着 xml 格式规范,是一种标签文本,它的格式包括以下标签:

<launch>    <!--根标签--><node>    <!--需要启动的node及其参数--><include>    <!--包含其他launch--><machine>    <!--指定运行的机器--><env-loader>    <!--设置环境变量--><param>    <!--定义参数到参数服务器--><rosparam>    <!--启动yaml文件参数到参数服务器--><arg>    <!--定义变量--><remap>    <!--设定参数映射--><group>    <!--设定命名空间--></launch>    <!--根标签-->
复制代码

launch 文件的写法和格式看起来内容比较复杂,我们先来介绍一个最简单的例子如下:

<launch><node name="talker" pkg="rospy_tutorials" type="talker" /></launch>
复制代码

文本中的信息是,它启动了一个单独的节点talker,该节点是包rospy_tutorials软件包中的节点。

然而实际中的 launch 文件要复杂很多,我们以Ros-Academy-for-Beginners中的robot_sim_demo为例:

<launch><!--arg是launch标签中的变量声明,arg的name为变量名,default或者value为值--><arg name="robot" default="xbot2"/><arg name="debug" default="false"/><arg name="gui" default="true"/><arg name="headless" default="false"/>
<!-- Start Gazebo with a blank world --><include file="$(find gazebo_ros)/launch/empty_world.launch"> <!--include用来嵌套仿真场景的launch文件--><arg name="world_name" value="$(find robot_sim_demo)/worlds/ROS-Academy.world"/><arg name="debug" value="$(arg debug)" /><arg name="gui" value="$(arg gui)" /><arg name="paused" value="false"/><arg name="use_sim_time" value="true"/><arg name="headless" value="$(arg headless)"/></include>
<!-- Oh, you wanted a robot? --> <!--嵌套了机器人的launch文件--><include file="$(find robot_sim_demo)/launch/include/$(arg robot).launch.xml" />
<!--如果你想连同RViz一起启动,可以按照以下方式加入RViz这个node--><!--node name="rviz" pkg="rviz" type="rviz" args="-d $(find robot_sim_demo)/urdf_gazebo.rviz" /--></launch>
复制代码

这个 launch 文件相比上一个简单的例子来说,内容稍微有些复杂,它的作用是:启动 gazebo 模拟器,导入参数内容,加入机器人模型。

对于初学者,我们不要求掌握每一个标签是什么作用,但至少应该有一个印象。如果我们要进行自己写 launch 文件,可以先从改 launch 文件的模板入手,基本可以满足普通项目的要求。

发布于: 刚刚阅读数: 6
用户头像

芯动大师

关注

凡事预则立,不预则废! 2022-06-01 加入

某公司芯片AE工程师,嵌入式开发工程师,InfoQ签约作者,阿里云专家博主,华为云·云享专家,51CTO专家博主,腾讯云社区优秀共创官。

评论

发布
暂无评论
ROS核心概念解析:从Node到Master,再到roslaunch的全面指南_Node_芯动大师_InfoQ写作社区