1. 程式人生 > 其它 >ROS服務與客戶端編寫詳解

ROS服務與客戶端編寫詳解

  • srv檔案
float64 init_x
float64 init_y
float64 init_z
float64 delta_x
float64 delta_y
float64 delta_z
---
float64 x
float64 y
float64 z
  • 服務
// 包括了ROS常用的標頭檔案
#include "ros/ros.h"

// 建立srv檔案時生成的標頭檔案,其中kinematics_demo為軟體包名稱,trans為srv檔名稱,並在其後加上.h副檔名
#include "kinematics_demo/trans.h"

// 軟體包名與srv檔名共同組成一個類名(kinematics_demo::trans),此類包括兩個成員變數request、response和兩個類定義Request、Response
// 服務中執行主要功能的回撥函式的原型 bool trans_pose(kinematics_demo::trans::Request &req, kinematics_demo::trans::Response &res); int main(int argc, char **argv) { // 初始化ROS,並指定節點名稱為kindmatics_sever ros::init(argc, argv, "kinematics_server"); // 為節點建立控制代碼n ros::NodeHandle n;
// 建立名稱是trans_pose的服務,並註冊回撥函式trans_pose // 第一個trans_pose為服務名稱,第二個trans_pose為回撥函式名 ros::ServiceServer service = n.advertiseService("trans_pose", trans_pose); ROS_INFO("Kinematics server"); // 迴圈等待回撥函式 ros::spin(); return 0; } bool trans_pose(kinematics_demo::trans::Request &req, kinematics_demo::trans::Response
&res) { res.x = req.init_x + req.delta_x; res.y = req.init_y + req.delta_y; res.z = req.init_z + req.delta_z; ROS_INFO("Pose before trans: (%f, %f, %f)", (double)req.init_x, (double)req.init_y, (double)req.init_z); ROS_INFO("Pose trans: (%f, %f, %f)", (double)req.delta_x, (double)req.delta_y, (double)req.delta_z); ROS_INFO("Pose after trans: (%f, %f, %f)", (double)res.x, (double)res.y, (double)res.z); return true; }
  • 客戶端
// 包括了ROS常用的標頭檔案
#include "ros/ros.h"
// 建立srv檔案時生成的標頭檔案,其中kinematics_demo為軟體包名稱,trans為srv檔名稱,並在其後加上.h副檔名
#include "kinematics_demo/trans.h"
#include <cstdlib>

// 第一個形參argc(argument counter)表示main函式的引數個數
// 第二個形參argv(argument value)表示main函式的引數值
// 也可寫為int main(int argc, char *argv[]),即由指標組成的陣列,陣列中每個元素都是指向char的指標
// 當不帶引數執行主函式時,作業系統向主函式傳遞的引數argc為1,而argv[0](是一個指標)指向程式的路徑及名稱
// 當帶引數執行主函式時,作業系統向主函式傳遞的引數argc為1加上引數個數,argv[0]意義不變,從arg[1]開始依次指向引數字串

int main(int argc, char **argv)
{
    // 初始化ROS,並指定節點名稱為kindmatics_client
    ros::init(argc, argv, "kinematics_client");

    // 當引數個數不為7(即未傳入6個引數,與預設的1個引數共7個)
    if (argc != 7)
    {
        ROS_INFO("usage: kinematics_client init_x, init_y, init_z, delta_x, delta_y, delta_z");
        return 1;
    }

    // 為節點建立控制代碼n
    ros::NodeHandle n;

    // 為名稱是trans_pose的服務建立客戶端,並賦給名稱為client的ros::ServiceClient的物件
    // 尖括號中為<軟體包名::srv檔名>
    // 此處或為函式模板語法,sericeClient為函式名,尖括號中內容顯式表明函式引數型別,圓括號中為引數值
    ros::ServiceClient client = n.serviceClient<kinematics_demo::trans>("trans_pose");
    
    // 例項化一個自動生成的服務類,即宣告一個kinematics_demo::trans物件srv
    // *注:此處服務的意義與伺服器的服務並不相同,此服務強調服務內容而非動作,與srv檔案所表示的服務相同
    // 即軟體包名與srv檔名二者共同組成一個類名,用此類名宣告一個物件srv 
    kinematics_demo::trans srv;

    // 上面例項化的名為srv的服務類,包括兩個成員變數request、response和兩個類定義Request、Response
    // 為request成員賦值
    srv.request.init_x = atof(argv[1]);
    srv.request.init_y = atof(argv[2]);
    srv.request.init_z = atof(argv[3]);
    srv.request.delta_x = atof(argv[4]);
    srv.request.delta_y = atof(argv[5]);
    srv.request.delta_z = atof(argv[6]);

    // 客戶端呼叫服務
    if(client.call(srv))
    {
        ROS_INFO("Pose after trans: (%f, %f, %f)", (double)srv.response.x, (double)srv.response.y, (double)srv.response.z);
    }
    else
    {
        ROS_ERROR("Failed to call service");
        return 1;
    }
    
    return 0;
}
  • 說明