目录
内容大多是一些博主文章或者视频的汇总,如果遇到看不懂的地方建议去参看原链接。
机器人工匠阿杰:机器人工匠阿杰的个人空间-机器人工匠阿杰个人主页-哔哩哔哩视频 (bilibili.com)
ROS机器人入门教程文档:Introduction · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程
下面开始正文:发布者-订阅者话题通信
ros的相关操作都是多个节点完成的,模块化完成代码编写,尽管ros程序的基础单元是节点,但是不可以只安装单个节点,必须以包为单位安装。可以简单的理解为包是节点的容器。
我们编写代码通常是为了完成一个相应的功能(节点),但是节点不能单独存在,所以要创建一个包。
整体流程如下:
1创建工作空间 2创建功能包 3创建ROS节点 4创建发布者 5创建订阅者
1 创建工作空间
ROS程序的编译等工作需要先创建工作空间以及src子目录
在终端输入指令:mkdir -p 自定义工作空间名/src
在主目录的文件夹也会多出来一个名字是learn的文件夹,并且里面有个空的src文件夹。
上面的操作也可以自己直接在主目录直接完成。
2 创建功能包
使用cd指令进入src工作目录,创建ROS包并添加依赖项
依赖项:在创建包时,通常将密切的节点放到一个包里面,但是总会存在一些通用性强的节点,会和其他包的节点发生关联,放在哪个包都不合适,只好把这些资源单独放一个包,谁要用,谁就依赖这个包。
cd 自定义工作空间名/src
catkin_create_pkg 自定义ROS包名 roscpp rospy std_msgs
自定义ROS包名后面的内容就是依赖项
创建完成后的结构如上图所示,导入依赖项的包有include文件夹(里面包含一个自定义ROS包名的空文件夹)、src空文件夹、Cmakelists.txt和package.xml四个。
后续编译的节点都是在这个src目录下创建并编译完成,关于ROS系统的文件架构,我在下方放一个图片,理解结构会更加清楚。
C++文件编写的相关操作,我们都是在第二级src目录下编写的。我们现在来创建一个发布者-订阅者的话题通信来开启自己的第一个ROS流程。(写笔记这个电脑上没安装Ubuntu和ROS,目前的文章也只是方便自己回顾,如有需要请看文章开头附的资源链接)
3 创建ros节点
上文已经创建完成软件包,在自定义ROS包名中进入src目录,并创建节点1.cpp文件
在src目录下右键新建文件,创建发布者节点node_pub1
节点创建完成后我们开始发布者和订阅者代码内容的编写,下方给了一个较为完整的流程
我们先尝试基本的测试,再进行发布者节点具体代码的编写
将Cmakelists.txt文件build章节的executable复制到文件末尾
两个参数,第一个参数为可执行文件名(尽量与节点名保持一致),第二个是文件的编译路径。
在vscode中使用ctrl+shift+B编译失败(转到终端编译)VS中编译快捷键没设置好,很容易出问题
编写完成后在工作空间learn下打开终端窗口,执行catkin_make进行编译
在终端中先启动roscore,之后再使用rosrun启动自己创建的节点,启动中出错无法找到bao1。这是因为没有将环境的配置导入参数空间。之后就可以正常运行了。
source ~/自定义工作空间名/devel/setup.bash
4 创建发布者
上面以及完成了基本的测试,下面开始创建发布者节点
首先将代码文件拷贝到.cpp文件,因为用到了ros的init函数,所以要在Cnakelists.txt文件添加链接库
配置完成后在终端中打开了learn工作空间,执行catkin_make编译
运行结果示例:
发布者模板示例
#include<ros/ros.h>
#include<std_msgs/String.h>
int main(int argc, char *argv[])
{
ros::init(argc,argv,"节点1");
printf("测试1");
//实例化句柄
ros::NodeHandle nh;
/*用上面实例的句柄实现发布者操作,<>内部的参数是消息类型,()里面两个参数,
第一个是发布的话题名称,第二个是最大缓存的消息数目*/
ros::Publisher pub = nh.advertise<std_msgs::String>("话题名",10);
ros::Rate loop_rate(10); //一秒发送10条消息,固定发送频率
while(ros::ok())
{
printf("测试2\n");
std_msgs::String msg;
msg.data = "消息内容";
pub.publish(msg);
loop_rate.sleep(); //调用sleep形成短暂堵塞,保持设置的频率输出
}
return 0;
}
将代码里面可以自定义内容的相关选项进行了加粗操作,在编写自己代码时按功能命名修改,上面就简单实现了发布者的相关代码编写,编写完成后不要忘记保存ctrl+s。
为代码添加编译规则(修改的是对应包的CMakelists.txt文件)
代码编写完成后还需要对编译规则进行配置,打开Cmakelists文件,1 将build章节的最后一行指令复制到文本末尾,2 将specify library 下方的内容同样复制到文件末尾 ,两部分修改完成后Ctrl+S保存。
//add_executeable(自己编辑的节点名 文件的执行路径)
//第一项可执行文件名(尽量和节点名一致,防止错乱) 第二项从那个代码文件编译
add_executeable(节点1 src/节点1.cpp)
//将函数的库文件链接,代码不要遗漏
target_link_libraries(节点1
${catkin_LIBRARIES}
)
Ctrl+shift+B 编译(或者终端执行catkin_make),编译完成后可以尝试运行该节点。
打开终端先启动 roscore
再打开终端将程序送进终端 source ~/自定义工作空间名工作空间/devdl/setup.bash
再打开终端 rosrun 自定义ROS包名 节点1
经过上文的操作就已经完成发布者的节点实现
通过终端开启命令,第一个终端执行roscore,第二个终端执行rosrun bao1 node_pub1
第三个终端执行rostopic list列出目前运行的话题,使用rostopic echo /topic1,查看话题内容。英文的字符串不会存在看不明白输出内容是什么这种问题
第四个终端echo -e 复制第三个终端双引号里面的内容进行解析,可以看到实际内容。
5 创建订阅者
订阅者的实现跟发布者类似,因为节点不能单独存在,所以按照上文的流程在一级src目录下创建软件包再创建发布者节点,也可以在之前的软件包中创建新节点。
在工作空间打开终端执行catkin_make
第一个终端启动roscore,第二个终端rosrun bao1 node_pub1 启动发布者节点1
第三个终端rosrun bao2 node_sub1 启动订阅者节点1
成功接收到发布者节点1的msg消息。
#include<ros/ros.h>
#include<std_msgs/String.h>
//发布者的消息类型
void hui(std_msgs::String msg)
{
//msg的data内容
printf(msg.data.c_str());
}
int main(int argc, char *argv[])
{
ros::init(argc,argv,"节点1");
//实例化句柄
ros::NodeHandle nh;
/*用上面实例的句柄实现订阅操作,()里面三个参数, 第一个是订阅的话题名称,
第二个是最大缓存的消息数目,第三个是回调函数名*/
ros::Subscriber sub = nh.subscribe("话题名",10,回调函数名);
//保持节点运行
while(ros::ok())
{
//新来的消息包内容能够被回调函数接收
ros::spinOnce();
}
return 0;
}
代码的编写完成后Ctrl+S保存,再仿照发布者节点在Cmakelists文件添加编译规则,Ctrl+S保存,Ctrl+shift+B编译。
回调函数中用到data,是因为string消息类型有data,所以在上文.data
到目前为止我们就完成了发布者-订阅者消息通信,发布的消息相关内容可通过下列指令实现
rostopic list 列出当前系统中所有活跃的话题
rostopic echo 主题名称 显示指定话题中发送的消息包内容
rostopic hz 主题名称 统计指定话题中消息包的发送频率
通过上文的操作我新建2个发布者,1个订阅者来接受这两个发布者的消息,在之前接受的消息里,不知道是一直在发送还是终止了,将回调函数的printf改为ROS_INFO,并在ros::init上方加上setlocale(LC_ALL,"") ,这样接受到的消息将会是准确的信息。
订阅2个发布者
两个订阅者不能重名
小技巧
新建的工作空间目录就将下方的设置重新来一遍
1 避免每次都source
在上文运行节点时,如果没有source那条指令,将会出现错误,为了避免每次执行前都执行该指令可以将这条语句写进.bashrc里面,后面再运行节点就可以省略这个语句,需要安装VScode。
code ~/.bashrc (或者gedit ~/.bashrc)
将下面的指令添加到文件末尾
source ~/自定义工作空间名/devel/setup.bash
2 字符等可以使用中文输出
在ros::init的前一行加上
setlocale(LC_ALL,"zh_CN.UTF-8") //英文版Ubuntu
setlocale(LC_ALL,"") //中文版Ubuntu
3 VScode工作空间设置
在VScode中将第一级src目录当根目录导入,后续的具体工程将不会放错src文件夹
操作流程:file——add folder to workspace——主目录———自定义工作空间名—src
4 超级终端
系统自带的终端每次只能执行一个指令,需要多次重复打开,下载terminator更便捷
sudo apt install terminator
常用操作:
Ctrl+shift+E横向分屏 Ctrl+shift+O纵向分屏 Ctrl+shift+W取消分屏
alt+方向键 移动焦点
横向分屏Ctrl+shift+E无法使用:
ibus-setup打开输入法标签窗口,选择表情符号一栏,将表情符号的快捷键修改
5 VScode相关插件安装
中文显示
点击左侧的几个小方块,在搜索栏输入chinese点击下载就可以将vscode设置为中文
ros工具
对vscode的一些设置功能进行扩充,添加一些ros专用的菜单项,并且代码提示和拼写检查都会加入ros的编程接口。
cmake插件
在没安装这个插件前,创建的Camkelists.txt文件编译器不认识。安装的是Cmake tools,安装完这个之后Cmake会自动安装。