前言
在介绍节点之前,先讲一下ROS:
- ROS是机器人操作系统(Robot Operating System)的简称,用于编写机器人的软件程序。
-
ROS是一种具有高度灵活性的软件架构,能够帮助软件开发者快速创建机器人应用软件。
-
ROS提供了一系列程序库和工具,包括:硬件抽象、设备驱动、库函数、可视化、进程间消息传递和软件包管理等
-
ROS是一个分布式的进程(也就是“节点”)框架,这些进程被封装在不同的程序包或功能包中。
-
ROS可以分成两层:底层是操作系统层(通常不需要用户关心),上层则是实现不同功能的软件包,如感知、定位、规划、控制等。
ROS的目录文件结构:
节点(node)、消息(message)、主题(topic)、服务(service),ROS控制器(ROS master)
- 节点(Nodes):节点是使用ROS与其他节点通信的可执行文件。
- 消息(Messages):订阅或发布主题(topic)时使用的ROS数据类型。
- 主题(Topic):节点可以将消息发布到主题,也可以订阅主题以接收消息。
- 节点管理器(Master):ROS的名称服务(即帮助节点相互查找)
- rosout:等效于stdout / stderr的ROS
- roscore:Master + rosout +参数服务器(参数服务器将在以后介绍)
节点
- 在ROS中,最小的进程单元就是节点(node)
- 一个软件包里有多个可执行文件,可执行文件在运行之后就成了一个进程(progress),这个进程在ROS中就叫节点。
- 从程序角度来说,node就是一个可执行文件(通常为C++生成的可执行文件、Python脚本)被执行,加载到了内存之中
- 从功能角度来说,通常一个node负责机器人的某一个单独的功能,由于机器人的功能模块非常复杂,我们往往不会把所有的功能都集中在同一个node,而是采用分布式的方式,把鸡蛋放到不同的篮子里。
- 例如有一个node来控制底盘轮子的运动,有一个node驱动摄像头获取图像,有一个node驱动激光雷达,有一个node根据传感器信息进行路径规划,这样做可以降低程序发生崩溃的可能性,试想一下如果把所有功能都写到一个程序中,模块间的通信、异常处理将会很麻烦。
- 节点之间通过话题(Topic)、服务(Service)、动作(Actions)或者参数(Parameter)实现数据的收发。
主节点
- 由于机器人的元器件很多,功能庞大,因此实际运行时往往会运行众多的node,负责感知世界、控制运动、决策和计算等功能。
- 那么如何合理的进行调配、管理这些node?这就要利用ROS提供给我们的节点管理器master,master在整个网络通信架构里相当于管理中心,管理着各个node
- node首先master处进行注册,之后master会将该node纳入整个ROS程序中
- node之间的通信也是先由master进行“牵线”,才能两两的进行点对点通信
- 当ROS程序启动时,第一步首先启动master,由节点管理器处理依次启动node
节点和主节点之间的关系
基本命令
roscore
- 启动ros主节点,在运行ros程序之前都必须运行该命令启动主节点
- 运行roscore时ROS master启动,同时启动的还有 rosout 和 parameter server ,
- 其中rosout 是负责日志输出的一个节点,其作用是告知用户当前系统的状态,包括输出系统的error、warning等等,并且将log记录于日志文件中
- parameter server 即是参数服务器,它并不是一个node,而是存储参数配置的一个服务器
- 每一次我们运行ROS的节点前,都需要把master启动起来,这样才能够让节点启动和注册
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信息
rosnode list
# 显示出node的详细信息
rosnode info node_name
# 结束某个node
rosnode kill node_name
# 测试连接节点
rosnode ping
# 列出在特定机器或列表机器上运行的节点
rosnode machine
# 清除不可到达节点的注册信息
rosnode cleanup
# 查看rosnode命令的用法
rosnode help
编写和运行ROS节点
# 在home目录下运行以下命令创建一个名字为ros_workspace的工作空间
$ mkdir –p ros_workspace/src
# 切换到工作工件目录
$ cd ros_workspace
# 编译工作空间
$ catkin_make
# 设置环境变量
$ echo “source ~/ros_workspace/devel/setup.bash” >> ~/.bashrc
$ source ~/.bashrc
# 切换到/src目录,创建一个test_pkg的功能包
$ catkin_create_pkg test_pkg std_msgs rospy roscpp
注意:
ROS 包的命名遵循一个命名规范,只允许使用小写字母、数字和下划线,而且首字符必须是一个小写字母。一些 ROS工具,包括 catkin,不支持那些不遵循此命名规范的包
ROS node头文件
- 头文件
- 头文件类型有gencpp模块根据msg定义自动生成
- std_msgs/String.h
- 使用rosmsg 查看具体内容
ROS node 基本结构
ros::init()
:初始化ros::Publisher
:发布消息ros::Subscriber
:订阅消息ros::Rate loop_rate
:循环速率ros::spin()
:事件循环ros::spinOnce()
:单次事件ros::start()
:启动ros::shutdown()
:关闭
ros::init()
- 通过调用
ros::init()
函数来初始化node - 此函数向ROS系统传递命令行参数、定义node名字及其它参数
- 在调用roscpp其它函数前必须先调用
ros::init()
,其函数原型为: -
void ros::init (int &argc,char **argv,const std::string &name,uint32_t options=0)
ros::Publisher
将节点设置成发布者,并将所发布主题的类型和名称告知节点管理器
ros::Subscriber
将节点设置成接收者,并将所接收主题的类型和名称告知节点管理器
主循环
- 循环条件
ros::ok()
: 当接受到ctrl+c 信号 或者ros::shutdown()
调用时,为false,终止运行节点 - 主循环中,使用
ros::rate
实现将循环一次的时间控制在一个我们设置的一个周期内 ROS_INFO()
;
参考: