1. 程式人生 > 其它 >2.5 通訊機制實操

2.5 通訊機制實操

2.5 通訊機制實操

本節主要是通過ROS內建的turtlesim案例,結合已經介紹ROS命令獲取節點、話題、話題訊息、服務、服務訊息與引數的資訊,最終再以編碼的方式實現烏龜運動的控制、烏龜位姿的訂閱、烏龜生成與烏龜窗體背景顏色的修改。

目的:熟悉、強化通訊模式應用


2.5.1 實操01_話題釋出

需求描述:編碼實現烏龜運動控制,讓小烏龜做圓周運動。

結果演示:

實現分析:

  1. 烏龜運動控制實現,關鍵節點有兩個,一個是烏龜運動顯示節點 turtlesim_node,另一個是控制節點,二者是訂閱釋出模式實現通訊的,烏龜運動顯示節點直接呼叫即可,運動控制節點之前是使用的 turtle_teleop_key通過鍵盤 控制,現在需要自定義控制節點。
  2. 控制節點自實現時,首先需要了解控制節點與顯示節點通訊使用的話題與訊息,可以使用ros命令結合計算圖來獲取。
  3. 瞭解了話題與訊息之後,通過 C++ 或 Python 編寫運動控制節點,通過指定的話題,按照一定的邏輯釋出訊息即可。

實現流程:

  1. 通過計算圖結合ros命令獲取話題與訊息資訊。
  2. 編碼實現運動控制節點。
  3. 啟動 roscore、turtlesim_node 以及自定義的控制節點,檢視執行結果。

1.話題與訊息獲取

準備:先啟動鍵盤控制烏龜運動案例。

1.1話題獲取

獲取話題:/turtle1/cmd_vel

通過計算圖檢視話題,啟動計算圖:

rqt_graph

或者通過 rostopic 列出話題:

rostopic list
1.2訊息獲取

獲取訊息型別:geometry_msgs/Twist

rostopic type /turtle1/cmd_vel

獲取訊息格式:

rosmsg info geometry_msgs/Twist

響應結果:

geometry_msgs/Vector3 linear
  float64 x
  float64 y
  float64 z
geometry_msgs/Vector3 angular
  float64 x
  float64 y
  float64 z

linear(線速度) 下的xyz分別對應在x、y和z方向上的速度(單位是 m/s);

angular(角速度)下的xyz分別對應x軸上的翻滾、y軸上俯仰和z軸上偏航的速度(單位是rad/s)。

詳情請檢視補充資料。


2.實現釋出節點

建立功能包需要依賴的功能包: roscpp rospy std_msgs geometry_msgs

實現方案A:C++

/*
    編寫 ROS 節點,控制小烏龜畫圓

    準備工作:
        1.獲取topic(已知: /turtle1/cmd_vel)
        2.獲取訊息型別(已知: geometry_msgs/Twist)
        3.執行前,注意先啟動 turtlesim_node 節點

    實現流程:
        1.包含標頭檔案
        2.初始化 ROS 節點
        3.建立釋出者物件
        4.迴圈釋出運動控制訊息
*/

#include "ros/ros.h"
#include "geometry_msgs/Twist.h"

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    // 2.初始化 ROS 節點
    ros::init(argc,argv,"control");
    ros::NodeHandle nh;
    // 3.建立釋出者物件
    ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",1000);
    // 4.迴圈釋出運動控制訊息
    //4-1.組織訊息
    geometry_msgs::Twist msg;
    msg.linear.x = 1.0;
    msg.linear.y = 0.0;
    msg.linear.z = 0.0;

    msg.angular.x = 0.0;
    msg.angular.y = 0.0;
    msg.angular.z = 2.0;

    //4-2.設定傳送頻率
    ros::Rate r(10);
    //4-3.迴圈傳送
    while (ros::ok())
    {
        pub.publish(msg);

        ros::spinOnce();
    }
    return 0;
}

配置檔案此處略

實現方案B:Python

#! /usr/bin/env python
"""
    編寫 ROS 節點,控制小烏龜畫圓

    準備工作:
        1.獲取topic(已知: /turtle1/cmd_vel)
        2.獲取訊息型別(已知: geometry_msgs/Twist)
        3.執行前,注意先啟動 turtlesim_node 節點

    實現流程:
        1.導包
        2.初始化 ROS 節點
        3.建立釋出者物件
        4.迴圈釋出運動控制訊息

"""

import rospy
from geometry_msgs.msg import Twist

if __name__ == "__main__":
    # 2.初始化 ROS 節點
    rospy.init_node("control_circle_p")
    # 3.建立釋出者物件
    pub = rospy.Publisher("/turtle1/cmd_vel",Twist,queue_size=1000)
    # 4.迴圈釋出運動控制訊息
    rate = rospy.Rate(10)
    msg = Twist()
    msg.linear.x = 1.0
    msg.linear.y = 0.0
    msg.linear.z = 0.0
    msg.angular.x = 0.0
    msg.angular.y = 0.0
    msg.angular.z = 0.5

    while not rospy.is_shutdown():
        pub.publish(msg)
        rate.sleep()

許可權設定以及配置檔案此處略

3.執行

首先,啟動 roscore;

然後啟動烏龜顯示節點;

最後執行運動控制節點;

最終執行結果與演示結果類似。


補充資料1:

弧度:單位弧度定義為圓弧長度等於半徑時的圓心角。

補充資料2:偏航、翻滾與俯仰

座標系圖解:

偏航:

俯仰:

翻滾:


2.5.2 實操02_話題訂閱

需求描述:已知turtlesim中的烏龜顯示節點,會發布當前烏龜的位姿(窗體中烏龜的座標以及朝向),要求控制烏龜運動,並時時列印當前烏龜的位姿。

結果演示:

實現分析:

  1. 首先,需要啟動烏龜顯示以及運動控制節點並控制烏龜運動。
  2. 要通過ROS命令,來獲取烏龜位姿釋出的話題以及訊息。
  3. 編寫訂閱節點,訂閱並列印烏龜的位姿。

實現流程:

  1. 通過ros命令獲取話題與訊息資訊。
  2. 編碼實現位姿獲取節點。
  3. 啟動 roscore、turtlesim_node 、控制節點以及位姿訂閱節點,控制烏龜運動並輸出烏龜的位姿。

1.話題與訊息獲取

獲取話題:/turtle1/pose

rostopic list

獲取訊息型別:turtlesim/Pose

rostopic type  /turtle1/pose

獲取訊息格式:

rosmsg info turtlesim/Pose

響應結果:

​float32 x
float32 y
float32 theta
float32 linear_velocity
float32 angular_velocity

2.實現訂閱節點

建立功能包需要依賴的功能包: roscpp rospy std_msgs turtlesim

實現方案A:C++

/*  
    訂閱小烏龜的位姿: 時時獲取小烏龜在窗體中的座標並列印
    準備工作:
        1.獲取話題名稱 /turtle1/pose
        2.獲取訊息型別 turtlesim/Pose
        3.執行前啟動 turtlesim_node 與 turtle_teleop_key 節點

    實現流程:
        1.包含標頭檔案
        2.初始化 ROS 節點
        3.建立 ROS 控制代碼
        4.建立訂閱者物件
        5.回撥函式處理訂閱的資料
        6.spin
*/

#include "ros/ros.h"
#include "turtlesim/Pose.h"

void doPose(const turtlesim::Pose::ConstPtr& p){
    ROS_INFO("烏龜位姿資訊:x=%.2f,y=%.2f,theta=%.2f,lv=%.2f,av=%.2f",
        p->x,p->y,p->theta,p->linear_velocity,p->angular_velocity
    );
}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    // 2.初始化 ROS 節點
    ros::init(argc,argv,"sub_pose");
    // 3.建立 ROS 控制代碼
    ros::NodeHandle nh;
    // 4.建立訂閱者物件
    ros::Subscriber sub = nh.subscribe<turtlesim::Pose>("/turtle1/pose",1000,doPose);
    // 5.回撥函式處理訂閱的資料
    // 6.spin
    ros::spin();
    return 0;
}

配置檔案此處略

實現方案B:Python

#! /usr/bin/env python
"""
    訂閱小烏龜的位姿: 時時獲取小烏龜在窗體中的座標並列印
    準備工作:
        1.獲取話題名稱 /turtle1/pose
        2.獲取訊息型別 turtlesim/Pose
        3.執行前啟動 turtlesim_node 與 turtle_teleop_key 節點

    實現流程:
        1.導包
        2.初始化 ROS 節點
        3.建立訂閱者物件
        4.回撥函式處理訂閱的資料
        5.spin

"""

import rospy
from turtlesim.msg import Pose

def doPose(data):
    rospy.loginfo("烏龜座標:x=%.2f, y=%.2f,theta=%.2f",data.x,data.y,data.theta)

if __name__ == "__main__":

    # 2.初始化 ROS 節點
    rospy.init_node("sub_pose_p")

    # 3.建立訂閱者物件
    sub = rospy.Subscriber("/turtle1/pose",Pose,doPose,queue_size=1000)
    #     4.回撥函式處理訂閱的資料
    #     5.spin
    rospy.spin()

許可權設定以及配置檔案此處略

3.執行

首先,啟動 roscore;

然後啟動烏龜顯示節點,執行運動控制節點;

最後啟動烏龜位姿訂閱節點;

最終執行結果與演示結果類似。


2.5.3 實操03_服務呼叫

需求描述:編碼實現向 turtlesim 傳送請求,在烏龜顯示節點的窗體指定位置生成一烏龜,這是一個服務請求操作。

結果演示:

實現分析:

  1. 首先,需要啟動烏龜顯示節點。
  2. 要通過ROS命令,來獲取烏龜生成服務的服務名稱以及服務訊息型別。
  3. 編寫服務請求節點,生成新的烏龜。

實現流程:

  1. 通過ros命令獲取服務與服務訊息資訊。
  2. 編碼實現服務請求節點。
  3. 啟動 roscore、turtlesim_node 、烏龜生成節點,生成新的烏龜。

1.服務名稱與服務訊息獲取

獲取話題:/spawn

rosservice list

獲取訊息型別:turtlesim/Spawn

rosservice type /spawn

獲取訊息格式:

rossrv info turtlesim/Spawn

響應結果:

float32 x
float32 y
float32 theta
string name
---
string name
 

2.服務客戶端實現

建立功能包需要依賴的功能包: roscpp rospy std_msgs turtlesim

實現方案A:C++