ROS节点

ROS节点介绍

  • 在ROS的世界里,最小的进程单元就是节点(node)
  • 一个软件包里可以有多个可执行文件,可执行文件在运行之后就成了一个进程(process),这个进程在ROS中就叫做节点
  • 从程序角度来说,node就是一个可执行文件(通常为C++编译生成的可执行文件、Python脚本)被执行,加载到了内存之中
  • 从功能角度来说,通常一个node负责者机器人的某一个单独的功能。由于机器人的功能模块非常复杂,我们往往不会把所有功能都集中到一个node上,而会采用分布式的方式,把鸡蛋放到不同的篮子里
  • 例如有一个node来控制底盘轮子的运动,有一个node驱动摄像头获取图像,有一个node驱动激光雷达,有一个node根据传感器信息进行路径规划,这样做可以降低程序发生崩溃的可能性,试想一下如果把所有功能都写到一个程序中,模块间的通信、异常处理将会很麻烦。
主节点
  • 由于机器人的元器件很多,功能庞大,因此实际运行时往往会运行众多的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(),其函数原型为:
    在这里插入图片描述
ros::Publisher

将节点设置成发布者,并将所发布主题的类型和名称告知节点管理器

ros::Subscriber

将节点设置成接收者,并将所接收主题的类型和名称告知节点管理器

主循环
  • 循环条件 ros::ok(): 当接受到ctrl+c 信号 或者 ros::shutdown() 调用时,为false,终止运行节点
  • 主循环中,使用ros::rate 实现将循环一次的时间控制在一个我们设置的一个周期内
  • ROS_INFO();
操作小记
操作内容

Hello World

  • 节点:
    • 节点talker:包含一个发布者
  • 节点间的通讯:
    • Topic(话题的名称):“chatter”
    • Message(传递的数据类型):std_msgs::String
      • String为 ROS自定义的数据类型
      • String中包含唯一变量为 std::string data
编写节点测试代码

在这里插入图片描述

编译软件包

我们主要需要修改CMakeLists.txt这个编译配置文件
在这里插入图片描述

编译

当修改完CMakeLists.txt文件后 就可以在工作空间的根目录下使用catkin_make进行编译了
在这里插入图片描述

运行节点

当编译过程没有错误时,接下来就可以使用rosrun命令来启动节点了
在这里插入图片描述

如何添加头文件和库文件

如何引用自定义头文件
引用当前软件包内的头文件

在编写代码时我们经常会需要引用头文件,引用公用的头文件很容易,因为它们已经在标准库头文件路径中。但 如果要引用自定义的头文件就稍微麻烦点,我们首先查看软件包的目录结构,需要在正确的目录下创建头文件修改CMakeLists.txt文件这样才能正确编译,下面来举例说明:
在这里插入图片描述
在test_pkg.h内写入以下内容
在这里插入图片描述
修改源码文件,引用自定义头文件
在这里插入图片描述
修改CMakeLists.txt文件
在这里插入图片描述
运行效果
在这里插入图片描述


引用同一工作空间中其他软件包的头文件

在一些情况我们需要引用其他软件包中提供的函数或宏定义,这样可以一定程度上减少我们在两个节点之间需要进行通信的话题个数,下面我们通过举例来进行说明:
创建一个功能包
在这里插入图片描述
新建相关文件及文件夹
在这里插入图片描述
修改源码文件
在这里插入图片描述
修改两个软件包的编译配置文件
在这里插入图片描述
运行效果
在这里插入图片描述

如何引用第三方库文件

我们经常在开发软件包时需要引入第三方的so动态库,但是将其放到系统默认库路径中或者使用绝对路径比较简单省事。但是这样的话我们软件包的移植性就会变差,当需要移植到其他机器上时需要重新配置该软件包的 依赖库路径

手工自己创建测试用的动态库

我们创建一个简单的动态库,里面只有一个简单的函数来计算两个输入整数的乘积并返回,我们首先创建multiply.cpp和multiply.h两个文件
multiply.cpp
在这里插入图片描述
multiply.h
在这里插入图片描述
接下来准备开始将multiply.cpp编译成为动态库libmultiply.so供我们测试用,注意-shared参数和-fPIC参数很重要

  • -shared:告诉gcc要生成的是动态链接库;
  • -fPIC:告诉gcc生成的代码是非位置依赖的,方便用于动态链接。

在这里插入图片描述

将编译好的动态库复制到当前软件包对应的目录下
在这里插入图片描述

编辑代码和配置文件来引用动态库
在这里插入图片描述

修改编译配置文件,编译后运行效果演示
在这里插入图片描述

  • 34
    点赞
  • 152
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值