ROSサービスの通信メカニズム

サービス通信も ROS では非常に一般的な通信モードであり、リクエスト レスポンスモードに基づいた応答メカニズムです。つまり、ノード A が別のノード B にリクエストを送信し、ノード B が処理リクエストを受信して​​応答結果を生成して A に返します。

srvファイル

サービス通信にはsrvファイルを使用する必要があり、srvファイルにはリクエストデータとレスポンスデータの種類が定義されています。

1.srvファイルを定義する

具体的な実装: 関数パッケージの下に新しい srv ディレクトリを作成し、.srv ファイルを追加します。

.srv ファイルの内容は次のとおりです。

# 客户端请求时发送的数据
int8 num
---
# 服务端响应时发送的数据
int32 result

2. 設定ファイルの編集

package.xmlにコンパイルの依存関係と実行の依存関係を追加します。

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>
  <!-- 
  exce_depend 以前对应的是 run_depend 现在非法
  -->

CMakeLists.txt srv 関連の構成を編集する

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
# 需要加入 message_generation,必须有 std_msgs
add_service_files(
  FILES
  AddInts.srv
)
generate_messages(
  DEPENDENCIES
  std_msgs
)

3. コンパイル

コンパイルされた中間ファイルを表示します。

C++ は中間ファイル (.../workspace/devel/include/package name/xxx.h) を呼び出す必要があります。

4. vscodeの設定

c_cpp_properies.json ファイルを構成し、中間ファイルのパスを「incluedePath」にコピーします。

{
    
    
    "configurations": [
        {
    
    
            "browse": {
    
    
                "databaseFilename": "",
                "limitSymbolsToIncludedHeaders": true
            },
            "includePath": [
                "/opt/ros/noetic/include/**",
                "/usr/include/**",
                "/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径 
            ],
            "name": "ROS",
            "intelliSenseMode": "gcc-x64",
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17"
        }
    ],
    "version": 4
}

1. ROS基本データ型のサービス通信実装

1. ROS形式データのサービス通信実装

ケース: クライアントが整数データを送信し、サーバーが整数データの二次演算を実装します。

サーバー側の実装

#include "ros/ros.h"
#include "std_msgs/Int8.h"
#include "int_server_client/int_server_client.h"

bool doReq(int_server_client::int_server_client::Request& req,
            int_server_client::int_server_client::Response& res)
{
    res.result = pow(req.num,2);
    // ROS_INFO("接受到的数据为:%d",req.num);
    // ROS_INFO("处理后的数据为:%d",res.result);
    return true;
} 


int main(int argc, char *argv[])
{
    /* code */
    //解决乱码问题
    setlocale(LC_ALL,"");
    //初始化ros节点
    ros::init(argc,argv,"server");
    //句柄
    ros::NodeHandle nh;
    //创建server对象
    ros::ServiceServer server;
    server = nh.advertiseService("intServer",doReq);
    ros::spin();


    return 0;
}

クライアントの実装

#include "ros/ros.h"
#include "std_msgs/Int8.h"
#include "int_server_client/int_server_client.h"

int main(int argc, char *argv[])
{
    /* code */
    //解决乱码问题
    setlocale(LC_ALL,"");
    //初始化ros节点
    ros::init(argc,argv,"server");
    //句柄
    ros::NodeHandle nh;
    //创建client对象
    ros::ServiceClient client;
    client = nh.serviceClient<int_server_client::int_server_client>("intServer");
    //等待服务端启动
    client.waitForExistence();
    //组织数据
    int_server_client::int_server_client ai;
    ai.request.num = 10;

    //发送请求
    bool flag = client.call(ai);
    if (flag == 1)
    {
        ROS_INFO("处理后的数据为%d",ai.response.result);
    }
    else
    {
        ROS_INFO("请求失败!");
    }


    ros::spin();


    return 0;
}

起動ファイル

<launch>
    <node pkg="int_server_client" type="int_server" name="intServer" output="screen"/>
    <node pkg="int_server_client" type="int_client" name="intClint" output="screen"/>
</launch>

2.パラメータ伝送に動的パラメータ伝送を用いたROS整形データのサービス通信の実装

サーバー側の実装は前のセクションと同じですが、クライアント側の実装が異なります。クライアント側の実装では、端末から入力されたパラメーターを取得し、計算と応答のためにサーバーに渡す必要があります。

クライアントの実装

#include "ros/ros.h"
#include "std_msgs/Int8.h"
#include "int_server_client/int_server_client.h"

int main(int argc, char *argv[])
{
    /* code */
    //  argc 是指命令行输入参数的个数(以空白符分隔),默认包含一个程序名
    if (argc != 2)
    {
        ROS_ERROR("请提交一个整数");
        return 1;
    }
    //ROS_INFO("%s",argv[1]);

    //解决乱码问题
    setlocale(LC_ALL,"");
    //初始化ros节点
    ros::init(argc,argv,"server");
    //句柄
    ros::NodeHandle nh;
    //创建client对象
    ros::ServiceClient client;
    client = nh.serviceClient<int_server_client::int_server_client>("intServer");
    //等待服务端启动
    client.waitForExistence();
    //组织数据
    int_server_client::int_server_client ai;
    
    //atoi()将字符串转换为整形
    ai.request.num = atoi(argv[1]);

    //发送请求
    bool flag = client.call(ai);
    if (flag == 1)
    {
        ROS_INFO("处理后的数据为%d",ai.response.result);
    }
    else
    {
        ROS_INFO("请求失败!");
    }


    ros::spin();


    return 0;
}

走る

前のセクションとは異なり、このセクションでは、クライアントはターミナルに渡されたパラメータを取得する必要があるため、ターミナルでサーバーとクライアントを別々に実行する必要があります。

コマンドは次のとおりです。

rosrun 功能包名 节点名 参数

注: 最初に roscore コマンドを開始する必要があります

3. ros string型データのサービス通信実装

サーバー側の実装

#include "ros/ros.h"
#include "string_server_client/string_srv.h"


bool doReq(string_server_client::string_srvRequest& req,
            string_server_client::string_srvResponse& res)
{
    ROS_INFO("名字:%s",req.name.c_str());
    ROS_INFO("年龄:%s",req.age.c_str());
    ROS_INFO("地址:%s",req.address.c_str());
    std::stringstream ss;
    ss<< req.name.c_str()<<"来自"<<req.address.c_str()<<"今年"<<req.age.c_str()<<"岁";    
    res.msg = ss.str();
}

int main(int argc, char *argv[])
{
    /* code */
    //乱码问题
    setlocale(LC_ALL,"");
    //初始化ros节点
    ros::init(argc,argv,"server");
    //句柄
    ros::NodeHandle nh;
    //创建服务端对象
    ros::ServiceServer server;
    server = nh.advertiseService("stringServerClient",doReq);
    ros::spin();

    return 0;
}

クライアントの実装

#include "ros/ros.h"
#include "string_server_client/string_srv.h"


int main(int argc, char *argv[])
{
    /* code */
    //解决乱码
    setlocale(LC_ALL,"");
    //判断参数数量是否正确
    if (argc!=4)
    {
        ROS_INFO("参数数量不正确,请重新输入");
        return 1;
    }
 
    //初始化ros节点
    ros::init(argc,argv,"server");
    //句柄
    ros::NodeHandle nh;
    //客户端对象
    ros::ServiceClient client;
    client = nh.serviceClient<string_server_client::string_srv>("stringServerClient");
    string_server_client::string_srv clientData;
    clientData.request.name = argv[1];
    clientData.request.age = argv[2];
    clientData.request.address = argv[3];
    //等待服务启动
    client.waitForExistence();
    bool flag = client.call(clientData);
    if (flag==1)
    {
        ROS_INFO("响应的数据为:");
        ROS_INFO("%s",clientData.response.msg.c_str());
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_49216787/article/details/132678297
おすすめ