ROS机器人制作(二)—— ROS话题订阅与发布

(二)ROS话题通信

  • 1:发布话题
  • 2:订阅话题
  • 3:自定义消息数据类型
  • 4:命令行

ROS话题通信:支持一对多的异步通信,发布者发布消息到话题上,订阅者从话题上订阅消息。

1:发布话题

Python

1.初始化ROS节点:命名(唯一)
rospy.init_node("名字")

2.创建发布者 
pub = rospy.Publisher("发布的话题名",发布的话题的消息类型,队列长度)

3.创建消息对象(可以处理消息内容)
msg = 消息类型()

4.将消息发布出去:
pub.publish(msg) 

例如

#! /usr/bin/env python
import rospy
from std_msgs.msg import String

if __name__ == "__main__":
    #2.初始化 ROS 节点:命名(唯一)
    rospy.init_node("talker_p")
    #3.实例化 发布者 对象
    pub = rospy.Publisher("chatter",String,queue_size=10)
    #4.组织被发布的数据,并编写逻辑发布数据
    msg = String()  #创建 msg 对象

    # 设置循环频率
    rate = rospy.Rate(1)
    while not rospy.is_shutdown():

        #代码
        

c++

创建节点句柄:
ros::NodeHandle nh;
              
创建一个发布者:<话题的消息数据类型> <话题名>  <消息缓存长度>
ros::Publisher pub = nh.advertise("topic_name", queue size);	

创建消息数据:  功能包::数据类型  实例
std_msgs::String str ;

消息赋值:
str.data = "hello world" ;

将消息发布出去:
pub.publish(str) ;

例如:

ros::NodeHandle n 

ros::Publisher  voltage_publisher; 

voltage_publisher = n.advertise<std_msgs::Float32>("PowerVoltage", 10);

std_msgs::Float32 voltage_msgs;

voltage_msgs.data = Power_voltage;

voltage_publisher.publish(voltage_msgs);

2:订阅话题

python

1.初始化 ROS 节点:命名(唯一)
rospy.init_node("节点名")

2.实例化 订阅者 对象
sub = rospy.Subscriber("订阅的消息名",消息类型,定义的回调函数名,消息队列长度)

3.定义处理回调函数
def 函数名(订阅的消息对象在回调函数中的名字)

例如

#! /usr/bin/env python
import rospy
from std_msgs.msg import String

#回调函数
def doMsg(msg):
    rospy.loginfo("I heard:%s",msg.data)

if __name__ == "__main__":
    #2.初始化 ROS 节点:命名(唯一)
    rospy.init_node("listener_p")
    #3.实例化 订阅者 对象
    sub = rospy.Subscriber("chatter",String,doMsg,queue_size=10)
    #4.处理订阅的消息(回调函数)
    #5.设置循环调用回调函数
    
    #如果写了消息订阅函数,那一定要写rospy.spin() 
    #不然是得不到另一边发出的消息或者信息  
    #rospy.spin()以下的代码都不会执行,一直等待订阅回调函数
    rospy.spin()

c++
订阅话题:
(1)创建一个订阅者
(2)创建一个回调函数 用来处理订阅话题里面的信息

//订阅的话题有新的消息就会进入回调函数
void callback(const std_msgs::StringConstPtr& str)
{

}

// ("话题名"消息队列长度 , 自定义回调函数的名字)
ros::Subscriber sub = nh.subscribe("my_topic", queue size, callback);

例如:

ros::Subscriber Cmd_Vel_Sub;
Cmd_Vel_Sub = n.subscribe(cmd_vel, 100, &turn_on_robot::Cmd_Vel_Callback);

//1:发布和订阅的话题是基于这个消息类型的    
//2:指针是格式
//3:相当于用akm_ctl暂时在回调函数里面代替
//ackermann_msgs::AckermannDriveStamped
//从而直接用akm_ctl.xxx来代替订阅的话题里面的数据类型
void turn_on_robot::Akm_cmd_Vel_Callback(const ackermann_msgs::AckermannDriveStamped &akm_ctl)
{ 

}

如果用一个节点要订阅和发布多个话题时,把发布话题的函数,写在了订阅回调中即可。订阅多个话题时,ros会一直卡在rospy.spin()等待每个回调函数的响应。

如果要ROS中订阅多个话题并汇聚回调信息处理

import message_filters
#定义回调函数
def call_back(data, image)

#---------------------订阅----------------------
sub1 	= message_filters.Subscriber('/topic1' , msg) 
#message_filters.Subscriber 跟rospy.Subscriber 一样需要传入的函数
sub2	= message_filters.Subscriber('/topic2' , msg) 

#---------------------集合-----------------------
ts = message_filters.TimeSynchronizer([sub1,sub2],1)
ts.registerCallback(call_back)#回调函数名
rospy.spin()
#---------------------END----------------------
#注意
global point_data  # 将点云变为全局变量发出

3:自定义消息数据类型

进入功能包:
(1)自定义msg文件:

创建mgs文件夹,创建.msg文件, 写float32 linex 类似的

(2)功能包下的文件 CMakeLists.txt:中添加编译规则 :

find_package (catkin REQUIRED COMPONENTS message_generation)

//用在catkin_package前面
add_message_files( FILES  定义的.msg )
generate_messages( DEPENDENCIES std_msgs )

//
catkin_package{CATKIN_DEPENDS  message_runtime}

//要在一个节点内,引用生成的自定义消息类型,需添加链接库
add_dependencies(节点名  ${PROJECT_NAME}_generate_messages_cpp)

//节点中去引用自定义消息类型
add_executable(可执行文件  src/文件名.cpp)
target_link_libraries(可执行文件  ${catkin_LIBRARIES})

(3)在package.xml文件中,添加描述规则:

  message_generation
  message_runtime

(4)编译后

在工作空间下的devel中的include中有.h文件  
在cpp中include这个.h文件就可以调用自定义的消息数据类型
(即"功能包的名字/.h文件")

4:命令行

命令行话题指令:

rostopic echo :打印某个话题信息 //数据
rostopic hz :  查看话题发布频率

rostopic info :打印话题的发布者订阅者和消息类型
rostopic type :查看话题的数据类型

rostopic list :列举出所有的话题

rostopic pub 话题  消息结构(tab键补全) :往话题输入信息  
循环发送:rostopic pub  -r  频率   话题    消息结构

rostopic bw :  发布话题占用的带宽
rostopic find :从数据类型寻找话题

消息数据类型:

rosmsg list    列出消息数据类型
rosmsg show 消息数据类型的内容(结构体)
rostopic type 话题名 |rosmsg show 

你可能感兴趣的:(ROS从入门到实践,python,linux,c语言,算法)