目录

一、复习及launch

1.1 深入理解配置信息(非常重要)

1.2 launch文件演示

二、ROS通信机制-----基础

2.1 本节导论

2.2 话题通信

2.2.1 话题通信概述

2.2.2 话题通信理论模型

2.2.3 C++实现话题通信基本操作

2.2.4 python实现话题通信基本操作


一、复习及launch

1.1 深入理解配置信息(非常重要)

温故而知新,可以为师矣。

-----在接触新知识前,回顾才是最重要的!

 catkin_install_python(PROGRAMSscripts/hello_vscode_p.pyDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

还记得这段代码吗?我们是将自定义文件名.py改成了scripts下面的.py文件。

这段代码的作用是:可以正确安装python脚本、定义到合适的python解释器执行python脚本

那么,如果不配置会出什么样的错误呢?笔者替大家尝试了一下并寻找解决办法

我们在scripts目录下建立一个py文件,为区别,起名为 hello_no_config.py,然后在scripts目录下调用终端并为其文件创立可执行文件权限

chmod +x *.py

按照上一章所说,接下来应该在cmakelist进行配置,但我们不进行这步操作,直接刷新环境变量

liuhongwei@liuhongwei-virtual-machine:~/demo02_ws$ source ./devel/setup.bash
rosrun hello_vscode hello_no_config.py

执行后,出现这样一行代码

/usr/bin/env : "python"没有那个文件或目录

于是得出结论:当不配置cmakelist.txt时,抛出异常,报错。

探赜索隐:还记得python前面声明的一行#! /usr/bin/env python吗?这行代码的意思是如果你要执行我这行脚本,那么/usr/bin/env路径下的python解释器去解释这个文件。

当我们不配置时,就去这个目录去找解释器,但是是找不到的,是软件版本问题。但如果配置了之后,配置文件会帮我们找到相应目录完成相应操作。

解决策略:直接修改解释器 #! /usr/bin/env python3(不建议)

通过软链接,将python链接到python3中(建议)

通过命令:

sudo ln -s /usr/bin/python3 /usr/bin/python

这样就可以执行脚本不用配置文件啦!!是不是方便很多

1.2 launch文件演示

1.需求

一个程序中可能需要启动多个节点,比如小乌龟案例要启动多个窗口,分别是rosrun、乌龟界面节点、键盘控制节点,显然效率低下,如何改进?

官方给出的优化是使用launch文件:可以一次启动多个ros节点

2.实现

Ⅰ.选定功能包-----添加launch文件夹

Ⅱ.选定launch文件夹右击-----添加launch文件(xml类型文件)

Ⅲ.编辑launch文件内容

<launch><node pkg = "turtlesim"  type = "turtlesim_node"  name = "turtle_GUI" /><node pkg = "turtlesim"  type = "turtle_teleop_key"  name = "turtle_MOVE" /><node pkg  = "hello_vscode" type ="hello_vscode_c.cpp"  name = "hello" output = "screen"/>
</launch>

对比于之前的三条指令,是不是方便很多!

roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
参数名 作用
node 包含的某个节点
pkg 功能包
type 被运行的节点文件
name 为节点命名
output 设置日志的输出目标

Ⅳ.运行launch文件:  

source ./devel/setup.bash

格式:roslaunch + 功能包名 + launch文件名

roslaunch hello_vscode start_turtle.launch

Ⅴ.结束

二、ROS通信机制-----基础

2.1 本节导论

1.本节主要内容

了解ROS中的基本通信机制的三种实现策略

话题通信(发布订阅模式):发布方与订阅方通过话题链接在一起,发布方发布关于话题的一些内容,接收方接收话题相关的一些内容。类似于今日头条的关注:我关注了美女,接下来就会把美女相关话题、图片发给我

服务通信(请求相应模式):类似C/S模型,客户端访问之后服务端才会相应;类似我输入一个网址才能获得网页内容

参数服务器(参数共享模式):开辟一个容器,容器中有一部分参数共享。有好多节点都可以向容器内存放/取出数据。类似于公司加班给了一些福利(小吃的)都可以吃

2.2 话题通信

2.2.1 话题通信概述

1.话题通信地位

是ROS中使用频率最高的一种通信方式,基于话题订阅模式,也即:一个节点发布消息,另一个节点接收消息。

比如 激光雷达信息采集处理为例:ROS中有一个节点需要时发布当前雷达采集到的数据,导航模块中也有节点会订阅并解析雷达数据。

2.适用范围

适用于不断更新的、少逻辑处理数据传输相关的应用场景

2.2.2 话题通信理论模型

1.话题通信的理论模型

Ⅰ.角色

ROS Master:管理者(管理与匹配话题)

Talker:发布者

Listener:订阅者

Ⅱ.流程

master起到撮合作用,可以根据话题建立发布者和订阅者之间的连接。(大龄青年相亲,master--媒婆 talker--男方 listener--女方)

Ⅲ.实现

①发布者在管理者进行注册操作,提交自己的话题以及RPC(远程调用地址)地址

②订阅者在管理者注册,提交自己关注的话题

③管理者将发布者与订阅者的话题进行比对,如果一致,会将发布者的RPC地址传送给订阅者

④订阅者根据RPC地址远程访问发布者

⑤发布者给订阅者一个响应,响应内容为发布者的TCP地址

⑥订阅者根据TCP地址访问发布者

⑦发布者发送内容通过TCP地址给订阅者

Ⅳ.注意

①使用的协议有RPC和TCP

②第一步和第二步谁先进行无所谓,无顺序关系

③发布方和订阅方都可以存在多个

④发布方和订阅方连接建立后,管理者即可关闭。

⑤上述实现流程已经封装了,直接调用即可。

Ⅴ.话题通信应用时的关注点

①话题设置

②发布者实现

③订阅者实现

④消息载体

2.2.3 C++实现话题通信基本操作

1.需求

编写订阅发布实现,要求发布方以每秒10hz的频率发送文本信息,订阅方订阅消息内容并打印输出。

2.分析

在模型实现中,ROS master不需要实现,而连接的建立已经被封装了,需要关注点有三

①发布方  ②接收方  ③数据(文本)

3.流程

Ⅰ.编写发布方实现

Ⅱ.编写订阅方实现

Ⅲ.编写配置文件

Ⅳ.编译并执行

4.发布方实现

Ⅰ. 建立文件夹 demo03_ws,在里面建立src文件夹,并且调用catkin_make命令(遗忘请翻阅chapter1)

Ⅱ.打开VSCODE,在src目录下面创建功能包 plumbing_pub_sub,导入依赖包rospy roscpp std_msgs(遗忘请翻阅chapter1)

Ⅲ.编写发布者实现,在src的src目录下新建 demo01_pub.cpp 文件

#include "ros/ros.h"
#include "std_msgs/String.h"
/*发布方实现1.包含头文件2.初始化ros节点3.创建节点句柄4.创建发布者对象5.编写发布逻辑并发布数据
*/
int main(int argc ,char * argvs[])
{ros::init(argc,argvs,"erguizi");  //节点名称为erguiziros::NodeHandle nh;                //创建节点句柄ros::Publisher pub = nh.advertise<std_msgs::String>("house",10);    //话题为房子,队列中最多缓存十条数据//5-1.先创建没有被发布的信息std_msgs::String msg;//5-2.编写循环,循环中发布数据while(ros::ok())    //只要节点活着,则循环继续{msg.data = "hello";pub.publish(msg);}return 0;
}

Ⅳ.配置cmakelist.txt文件

add_executable(demo01_pub src/demo01_pub.cpp)## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})## Specify libraries to link a library or executable target againsttarget_link_libraries(demo01_pub${catkin_LIBRARIES})

Ⅴ.编译

Ⅵ.执行

①启动roscore

②进入工作目录

cd demo03_ws/

③配置环境变量

source ./devel/setup.bash

④运行

rosrun plumbing_pub_sub demo01_pub

⑤验证是否成功(下几节会介绍)

rostopic echo house

话题名称是房子,捕获它

⑥成功,发布者对象没有任何问题

5.发布逻辑实现

Ⅰ.要求以10hz实现发布数据,并且文本后添加编号

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
/*发布方实现1.包含头文件2.初始化ros节点3.创建节点句柄4.创建发布者对象5.编写发布逻辑并发布数据
*/
int main(int argc ,char * argvs[])
{setlocale(LC_ALL,"");ros::init(argc,argvs,"erguizi");  //节点名称为erguiziros::NodeHandle nh;ros::Publisher pub = nh.advertise<std_msgs::String>("house",10);    //话题为房子,队列中最多缓存十条数据//5-1.先创建没有被发布的信息std_msgs::String msg;ros::Rate rate(10);        //10hzint count = 0;//5-2.编写循环,循环中发布数据while(ros::ok())    //只要节点活着,则循环继续{count ++;//实现字符串拼接std::stringstream ss;ss << "hello --->"<<count;msg.data = ss.str();//msg.data = "hello";pub.publish(msg);//添加日志ROS_INFO("发布的数据是:%s",ss.str().c_str());rate.sleep();                        //睡觉0.1s}return 0;
}

Ⅱ.解释代码/接口用处

①setlocale:有中文,避免出现输出乱码必须要加的一行代码

②ros::NodeHandle nh; 创建节点句柄,句柄名称为nh

③ros::Publisher pub = nh.advertise<std_msgs::String>("house",10);  创建发布者对象,为文本类型,话题名为house,缓冲区大小为10.

④std_msgs::String msg;   声明string类型数据

⑤ros::rate 初始化rate函数   rate.sleep()睡眠10hz

⑥ros::ok 状态信息,只要节点存在,就声明为真

⑦std::stringstream 处理字符串

⑧msg.data = ss.str(); 将ss转化为string类型赋值给msg.data

⑨pub.publish(msg);  发布者发布信息

Ⅲ.执行

5.订阅方实现

Ⅰ.在src文件下建立 demo02_sub.cpp 文件,编写c++逻辑

#include "ros/ros.h"
#include"std_msgs/String.h"
/*订阅方实现1.包含头文件2.初始化ros节点3.创建节点句柄4.创建订阅者对象5.处理订阅的数据6.spin()函数
*/void domessage(const std_msgs::String::ConstPtr & msg)
{//通过msg获取并操作订阅到的数据ROS_INFO("翠花订阅的数据是:%s",msg->data.c_str());}int main(int argc,char * argv[])
{ros::init(argc,argv,"cuihua");ros::NodeHandle nh;ros::Subscriber sub = nh.subscribe("house",10,domessage);ros::spin();return 0;
}

其中,spin函数的作用是 :

回头,main函数从上向下依次执行,执行到24语句时候,每订阅一次消息都会处理domessage函数。所以,这条语句执行一次是不行的,调用spin可以使其循环执行。

Ⅱ.修改、添加关于sub的配置文件

add_executable(demo01_pub src/demo01_pub.cpp)add_executable(demo02_sub src/demo02_sub.cpp)
## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})## Specify libraries to link a library or executable target againsttarget_link_libraries(demo01_pub${catkin_LIBRARIES})target_link_libraries(demo02_sub${catkin_LIBRARIES})

Ⅲ.编译

Ⅳ.执行

①启动roscore,先发布数据

rosrun plumbing_pub_sub demo01_pub

②更改环境变量

source ./devel/setup.bash

③执行订阅代码

rosrun plumbing_pub_sub demo02_sub

成功!!

Ⅴ.注意

①ros初始化节点不可以重名!

6.案例中的注意事项

补充0:

vscode 中的 main 函数 声明 int main(int argc, char const *argv[]){},默认生成 argv 被 const 修饰,需要去除该修饰符

补充1:

ros/ros.h No such file or directory .....

检查 CMakeList.txt find_package 出现重复,删除内容少的即可

参考资料:fatal error: ros/ros.h: No such file or directory - ROS Answers: Open Source Q&A Forum

补充2:

find_package 不添加一些包,也可以运行啊, ros.wiki 答案如下

You may notice that sometimes your project builds fine even if you did not call find_package with all dependencies. This is because catkin combines all your projects into one, so if an earlier project calls find_package, yours is configured with the same values. But forgetting the call means your project can easily break when built in isolation.

补充3:

订阅时,前几条数据丢失

原因: 发送第一条数据时, publisher 还未在 roscore 注册完毕

解决: 注册后,加入休眠 ros::Duration(3.0).sleep(); 延迟第一条数据的发送

补充4:普通函数与回调函数(个人理解)

类似于操作系统中的信号系统,普通函数执行先函数声明,在main函数中发现调用则立即开辟函数栈并执行;而回调函数不然,在main函数虽然可能出现函数名称,但是不一定调用(不是马上执行),而是等待外部一个时机才会执行。

类比于打鬼子,函数调用相当于看见鬼子就开打,回调函数类似地雷!!


PS:可以使用 rqt_graph 查看节点关系。

修改后的代码----final版本

#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
/*发布方实现1.包含头文件2.初始化ros节点3.创建节点句柄4.创建发布者对象5.编写发布逻辑并发布数据
*/
int main(int argc ,char * argvs[])
{setlocale(LC_ALL,"");ros::init(argc,argvs,"erguizi");  //节点名称为erguiziros::NodeHandle nh;ros::Publisher pub = nh.advertise<std_msgs::String>("house",10);    //话题为房子,队列中最多缓存十条数据//5-1.先创建没有被发布的信息std_msgs::String msg;ros::Rate rate(10);        //10hzint count = 0;//5-2.编写循环,循环中发布数据ros::Duration(3).sleep();   //程序执行到这里休眠三秒钟while(ros::ok())    //只要节点活着,则循环继续{count ++;//实现字符串拼接std::stringstream ss;ss << "hello --->"<<count;msg.data = ss.str();//msg.data = "hello";pub.publish(msg);//添加日志ROS_INFO("发布的数据是:%s",ss.str().c_str());rate.sleep();                        //睡觉0.1s}return 0;
}

7.发布订阅模型

在执行时调用命令行,用图形化显示发布订阅之间的关系。

rqt_graph

2.2.4 python实现话题通信基本操作

1.发布方实现

由于和C++实现大部分一样,这里只给出代码和适当标注

①在src的plumbing_pub_sub中建立存放python脚本的文件夹scripts,建立python的发布者对象 demo01_pub_p.py

#!  /usr/bin/env python
import rospy
from std_msgs.msg import String #发布消息的类型"""
使用python实现消息发布
1.导包
2.初始化ros节点
3.创建发布者对象
4.编写发布逻辑并发布数据
"""if __name__ ==  "__main__":rospy.init_node("lhw")           #传入节点名称pub = rospy.Publisher("car",String,queue_size=10)       #话题名称、类型、缓冲区长度#创建数据msg = String()#使用循环发布数据while not rospy.is_shutdown():msg.data = "hello"pub.publish(msg)

②添加文件的可执行权限:

chmod +x *.py

③修改配置文件:

 catkin_install_python(PROGRAMSscripts/demo01_pub_p.pyDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

④编译

⑤执行

source ./devel/setup.bash
rosrun plumbing_pub_sub demo01_pub_p.py

重点:此处在调试程序时,笔者一直编译不过,错误信息显示

Non-ASCII character '\xe9' in file /home/liuhongwei/demo03_ws/src/plumbing_pub_sub/scripts/demo01_pub_p.py on line 4, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

我搜寻资料:结果如下

于是在前面加上一条宏定义  # coding=UTF-8 即可解决

⑥进行发布逻辑补充:指定发布频率、拼接字符串更有逻辑性:

#1.导包
import rospy
from std_msgs.msg import Stringif __name__ == "__main__":#2.初始化 ROS 节点:命名(唯一)rospy.init_node("lhw")#3.实例化 发布者 对象pub = rospy.Publisher("car",String,queue_size=10)#4.组织被发布的数据,并编写逻辑发布数据msg = String()  #创建 msg 对象msg_front = "hello 你好"count = 0  #计数器 # 设置循环频率rate = rospy.Rate(1)while not rospy.is_shutdown():#拼接字符串msg.data = msg_front + str(count)pub.publish(msg)rate.sleep()rospy.loginfo("写出的数据:%s",msg.data)count += 1

2.订阅方实现

①在scripts下建立 demo02_sub_p.py文件实现订阅方逻辑代码

#! /usr/bin/env python
# coding=UTF-8
import rospy
from std_msgs.msg import String"""
订阅实现流程1.导包2.初始化ros节点3.创建订阅对象4.回调函数处理数据5.spin()"""def domessageing(msg):rospy.loginfo("我订阅的数据:%s",msg.data)if  __name__ == __main__:rospy.init_node("huahua")sub = rospy.Subscriber("car",String,domessageing,queue_size=10)rospy.spin()

②修改配置文件

catkin_install_python(PROGRAMSscripts/demo01_pub_p.pyscripts/demo02_sub_p.pyDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

③编译并添加可执行权限

④执行

source ./devel/setup.bash
rosrun plumbing_pub_sub demo02_sub_p.py

⑤联合执行

先执行发布,再执行订阅,查看结果

3.注意事项(数据丢失处理)

与C++一样,发布之前需要进行休眠,python代码为

在while循环前加入代码,这样就不会缺前几个数据了

rospy.sleep(3)

4. 计算图查看

发送方订阅方启动后,打开终端输入

rqt_graph

5.解耦合

①概念:即使使用不同的语言,也是可以相互交互的(用C++写发布方,python写订阅方)

②方法:
一个窗口启动发送方,一个窗口启动订阅方,也可以实现,类似于黑盒!!!十分好用

Chapter2 ROS通信机制----基础篇(Ⅰ)vs配置及通信基础相关推荐

  1. ROS自主导航学习———ROS通信机制

    前言 前面ROS很多都忘记了 ,现在来重新回顾一下内容 ROS 中的基本通信机制主要有如下三种实现策略: 话题通信(发布订阅模式) 服务通信(请求响应模式) 参数服务器(参数共享模式) Action通 ...

  2. ROS通信机制——发布/订阅者模型

    目录 发布/订阅者模型 (一)发布者 (二)订阅者 (三)综合 参考资料 ROS (Robot Operating System),即机器人操作系统,是为了加快机器人的开发效率,提高机器人软件代码的复 ...

  3. 【ROS理论与实践-赵虚左老师】Chap2 ROS通信机制

    第二章 ROS通信机制 通信是ROS中的核心 Core 机器人是一种高度复杂的系统性实现,在机器人上可能集成各种传感器(雷达.摄像头.GPS-)以及运动控制实现,为了解耦合,在ROS中每一个功能点都是 ...

  4. ROS 通信机制(已整理)

    文章目录 节点与节点管理器 ROS通信机制 1. 话题通信 1.1 基本话题通信 1.1.1 C++实现 发布方 demo01_pub.cpp 订阅方 demo01_sub.cpp 1.1.2 Pyt ...

  5. ROS入门跟着我就够了(二)上 ROS通信机制

    由于这一章东西比较多,我分了上下两篇,下部分可以在< ROS 入门跟着我就够了>专辑中查看 ROS 中的基本通信机制主要有如下三种实现策略: 话题通信(发布订阅模式)服务通信(请求响应模式 ...

  6. ROS通信机制一---话题通信

    文章目录 总述 1. 话题通信模型 2. 话题通信基本实现示例 2.1 发布者 2.1.1 创建发布者topic_pub.cpp文件 2.1.2 修改CMakeLists.txt文件 2.1.3 编译 ...

  7. ROS通信机制--键盘控制乌龟运动线速度角速度XYZ值的解释

    目录 前言 案例实现 线速度角速度X.Y.Z值的取值和作用 (END) 前言 在学习ros之初,想必大家运行的第一个案例就是键盘控制乌龟运动.这是ros内置的小案例,采用的通信机制为话题通信.本文介绍 ...

  8. 6th ROS通信机制概述

    ROS通信是ROS的核心之一. 一.基本概念 节点(Node) 一个节点就表示一个进程 多节点.端到端.分布式通信机制 消息(Message) 节点之间通过订阅和发布传递的数据 可以使用ROS提供的消 ...

  9. ROS通信机制:话题、服务、参数

    目录 话题通信 理论模型 流程 通信样例 自定义消息的通信 服务通信 理论模型 服务通信自定义srv 参数服务器 理论模型 参数操作 话题通信 话题通信是ROS中使用频率最高的一种通信模式,话题通信是 ...

最新文章

  1. Vue 自定义权限指令
  2. 嵌入式开发板设置无密码登录
  3. arm linux嵌入式网络控制系统,基于ARMLinux的嵌入式网络控制系统的研究与设计
  4. IOS-React-Native:unable to find utility instruments, not a developer tool or in PATH
  5. python资料书-史上最全Python从入门到资深书籍资料分享!
  6. php sqlserver扩展,PHP---连接sqlserver扩展配置
  7. RocketMQ各角色介绍
  8. 拯救乳房:乳腺癌AI诊断系统
  9. Spark源码分析之SchedulerBackend分析
  10. PE文件结构及其加载机制(四)
  11. mysql date_default_timezone_set,date_default_timezone_set
  12. JavaWeb请求的重定向与转发:getRequestDispatcher()的forward方法,sendRedirect方法,以及重定向与转发的区别
  13. 计算机桌面墙纸更换,电脑系统教程:win7桌面壁纸怎么换
  14. 双网卡实现内外网同时上网
  15. mysql 没有 myd_MySQL中找不到.myd文件的问题
  16. win7系统无法正常启动
  17. jenkins插件安装失败更改插件源
  18. 纪录片让你开阔眼界、增长见识
  19. 为什么选择软件测试这个岗位?(面经)
  20. 画一手好的架构图是码农进阶的开始

热门文章

  1. 数学之美-读书笔记6-10章
  2. MySQL 零散知识整理~字符编码设置
  3. 简单hashtab的实现
  4. 二维表 转一维表 mysql_Excel二维表转换成一维表(2种方法)
  5. 论文阅读:(NFM)Neural Factorization Machines for Sparse Predictive Analytics
  6. 这一次,卡98%问题终于解决了
  7. 五险一金,你真的懂吗
  8. pyqt5 向 QTableWidget添加元素以及锁定到某行
  9. java poi_Java POI的学习(一)——Word
  10. 0基础学RS(三)路由器基本配置