1. 程式人生 > 其它 >ROS實踐筆記3

ROS實踐筆記3

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++

建立一個釋出者的流程:

  1. 包含標頭檔案。
    ros/ros.h
    //訊息型別的標頭檔案,下面是文字檔案的訊息型別
     std_msgs/String.h
    
  2. 初始化ROS節點
  3. 建立節點控制代碼 NodeHandle
  4. 建立釋出者物件,使用advertise函式需要範型,話題名稱和佇列長度為函式的引數
  5. 建立釋出的訊息內容併發布
    程式碼如下
# 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

訂閱方實現

  1. 包含標頭檔案,其中需要包含訂閱的訊息型別
  2. 初始化ROS節點
  3. 建立節點控制代碼
  4. 建立訂閱者物件
  5. 處理訂閱到的資料 需要手寫函式
  6. 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秒,使其完成註冊後再發布資訊,防止訂閱者錯過資訊。