ROS實踐筆記3
阿新 • • 發佈:2022-02-12
ROS話題通訊模型
角色:
1. master---->管理者
2. talker---->釋出者
3. listener---->訂閱者
流程:
管理者可以通過話題建立釋出者與訂閱者之間的連線
流程實現:
1. 釋出者將話題與RPC地址傳送給管理者進行註冊。 2. 訂閱者在管理者處註冊自己關注的話題。 3. 將釋出者和訂閱者的話題進行對比,如果二者一致,則將釋出者的RPC地址傳送給訂閱者。 4. 訂閱者根據RPC地址訪問釋出者 5. 釋出者對訂閱者的訪問進行響應,並將自己的TCP地址傳送給訂閱者。 6. 訂閱者根據TCP地址訪問釋出者。 7. 釋出者將訊息傳送至訂閱者
注意:
1. 使用的協議有RPC和TCP
2. 步驟1和步驟2沒有順序關係
3. talker 和listener 都可以存在很多個
4. talker 和listener 建立連線後,master就可以關閉
話題通訊應用時的關注點:
1. 大部分實現已經被封裝
2. 話題設計
3. 釋出者實現
4. 訂閱者實現
5. 訊息載體
ROS中文字訊息需要使用標頭檔案
std_msgs/String.h
c++
建立一個釋出者的流程:
- 包含標頭檔案。
ros/ros.h //訊息型別的標頭檔案,下面是文字檔案的訊息型別 std_msgs/String.h
- 初始化ROS節點
- 建立節點控制代碼 NodeHandle
- 建立釋出者物件,使用advertise函式需要範型,話題名稱和佇列長度為函式的引數
- 建立釋出的訊息內容併發布
程式碼如下
# include"ros/ros.h" # include"std_msgs/String.h" int main(int argc, char *argv[]) { ros::init(argc,argv,"pub"); ros::NodeHandle nh; ros::Publisher pub=nh.advertise<std_msgs::String>("topic",10); std_msgs::String msg; ros::Duration(3).sleep(); while(ros::ok()) { msg.data="hello"; pub.publish(msg); } return 0; }
其中
ros::Duration(3).sleep();
用來延遲第一條資料的傳送三秒鐘
使用rostopic echo 話題名稱,可以打印出釋出者釋出的資訊
rostopic echo topic
訂閱方實現
- 包含標頭檔案,其中需要包含訂閱的訊息型別
- 初始化ROS節點
- 建立節點控制代碼
- 建立訂閱者物件
- 處理訂閱到的資料 需要手寫函式
- spin()函式(回頭,呼叫回撥函式);
程式碼如下:
# include"ros/ros.h"
# include"std_msgs/String.h"
# include<sstream>
void Domsg(const std_msgs::String::ConstPtr &msg)
{
ROS_INFO("topic is %s",msg->data.c_str());
return ;
}
int main(int argc, char *argv[])
{
ros::init(argc,argv,"sub");
ros::NodeHandle nh;
ros::Subscriber sub=nh.subscribe("topic",10,Domsg);
ros::spin();
return 0;
}
使用rqt_graph命令,可以畫出通訊圖
rqt_graph
python
釋出者實現:
#! /usr/bin/env python
from ast import While
import rospy
from std_msgs.msg import String #釋出訊息的型別
if __name__=="__main__":
rospy.init_node("pub") #傳入節點名稱
pub=rospy.Publisher("topic",String,queue_size=10) #建立釋出者物件
msg=String() #建立訊息物件
rate=rospy.Rate(1) #制定釋出頻率
count=1 #計數器
rospy.sleep(3)
while not rospy.is_shutdown():
msg.data="topic"+str(count) #將數字轉化為字串
pub.publish(msg)
rospy.loginfo("topic is %s---->",msg.data)
rate.sleep()
count+=1
#建立併發布訊息
訂閱者實現:
#! /usr/bin/env python
import rospy
from std_msgs.msg import String
def DoMsg(msg):# 回撥函式
rospy.loginfo("topic is -----> %s",msg.data)
if __name__=="__main__":
rospy.init_node("sub") #初始化節點
sub=rospy.Subscriber("topic",String,DoMsg,queue_size=10)
rospy.spin()
其中 python 釋出者中的
rospy.sleep(3)
與 c++ 釋出者中的
ros::Duration(3).sleep();
作用都是讓程式在釋出第一條資訊之前休眠3秒,使其完成註冊後再發布資訊,防止訂閱者錯過資訊。