Apollo Cyber RT下服务通信的实现

什么叫服务通信

        定义:以请求响应的方式实现不同节点间的数据交互通信模式,用于偶然触发,高实时性要求的场景。

        俗解:不同于前面的不间断收发假设存在客户端与服务端,他们之间是通过话题通信链接起来,此时客户端产生了新的需求并发送给服务端,服务端进行内部响应,响应完成后在传送回客户端。

        实列分析:自动驾驶过程中,客户端通过手机发出修改目的地的请求,服务端接收请求,并进行路径的规划,规划完毕后再返还给服务端,服务端在发送结果给客户端。

 案例分析以及解决方案

        案例需求

        需求:客户端发送数字,服务端接收数据并进行数据的求和处理,将结果响应并返还至客户端。

         流程思路:该流程适用于CPP与PY的程序编写

        •编写消息载体protobuf文件并进行配置

        •编写服务端代码

        •编写客户端代码

        •编译并执行

Protobuf文件的编写

        新建一个demo_pro的文件夹,这个文件夹是用来存放protobuf的相关文件,且在该文件夹下面创建昊BUILD文件和protobuf文件。

 创建proto文件

// 申明版本号
syntax = "proto2";
//申明包
package apollo.cyber.demo_SC.demo_SC_pro;

//创建请求消息
message AddInts_Request {
    //两个整形数据
    required int64 num1 =1;
    required int64 num2 =2;
}
//创建响应消息
message AddInts_Response {
    //一个整形数据
    required int64 sum =1;
}

        他的主要功能是创建一个发布方与响应方的变量名

        Build的内容如下:

load ("//tools:python_rules.bzl", "py_proto_library")
package (default_visibility = ["//visibility:public"])

proto_library(
    name = "addints_proto",
    srcs = ["SC_addinits.proto"]
)

cc_proto_library(
   name = "addints_cc",
    deps = [":addints_proto"]
)

py_proto_library(
    name = "addints_py",
   deps = [":addints_proto"]
)

         Protobuf编写完成,编译执行(bazel build 目录/…)后,会生成 addints.pb.h、addints.pb.cc、addints.pb2.py。我们主要使用到其中的SC_addinits_pb.cc和SC_addinits.pb.h

 客户端代码分析

        客户端主要由BUILD文件demo_cc_SC.cpp组成

        其中核心部分是demo_cc_SC.cpp其详细代码如下

/**
 * @file demo_cc_SC.cpp
 * @author bobo
 * @brief 客户端发送请求,提交两个整数,服务端接收请求,提取数字相加后将结果响应回客户端
 * @version 0.1
 * @date 2022-07-05
 * 
 *      实现流程
 *      头文件包含
 *      初始化
 *      创建节点
 *      创建服务方
 *      数据处理
 *      等待关闭
 */

#include "cyber/cyber.h"
#include "cyber/demo_SC/demo_SC_pro/SC_addinits.pb.h"

//调用了proto中的两个message
using apollo::cyber::demo_SC::demo_SC_pro::AddInts_Request;
using apollo::cyber::demo_SC::demo_SC_pro::AddInts_Response;

void cb(const std::shared_ptr<AddInts_Request>&request , const std::shared_ptr<AddInts_Response>&response){

    int64_t num1 =request ->num1();
    int64_t num2 =request ->num2();
    
    AINFO << "客户请求num1 = "<< num1 << "num2 = "<<num2;
    //设置求和并响应
    int16_t sum = num1 +num2;

    response ->set_sum(sum);
}

int main(int argc, char*argv[]){
    //初始化
    apollo::cyber::Init(argv[0]);
    AINFO << "初始化完成";
    //创建节点
    auto server_node = apollo::cyber::CreateNode("server_node");
    //设置服务方                               提交的数据类型       响应的数据类型     字符串(话题)通过话题服务方和客户端关联在一起
    auto server = server_node ->CreateService<AddInts_Request, AddInts_Response>("addints",cb);

    //数据处理

    //等待关闭
    apollo::cyber::WaitForShutdown();

    return 0;
}

服务端代码分析 

         服务端主要实现接收数据并进行计算的功能,其主要流程本质上是与客户端代码一致的

/**
 * @file demo_cc_CS.cc
 * @author bobo
 * @brief 
 * @version 0.1
 * @date 2022-07-05
 * 包含头文件
 * 初始化cyber
 * 创建客户端节点
 * 创建发布方
 * 发送数据
 * 等待关闭 
 */
#include "cyber/cyber.h"
#include "cyber/demo_SC/demo_SC_pro/SC_addinits.pb.h"

using apollo::cyber::demo_SC::demo_SC_pro::AddInts_Request;
using apollo::cyber::demo_SC::demo_SC_pro::AddInts_Response;

int main(int argc, char* argv[]){

    apollo::cyber::Init(argv[0]);
    //处理输入的参数
        if(argc != 3){
            AINFO<<"执行程序时请输入两个数字作为参数";
            return 1;
        }

        AINFO<<"客户端。。。。。。。。。。。。。。。。。。";
        //创建客户端节点
        auto client_node = apollo::cyber::CreateNode("client_node");
        //创建发布方
        auto client =client_node->CreateClient<AddInts_Request,AddInts_Response>("addints");
        //发送数据
        AINFO <<"等待服务启动";

        auto request = std::make_shared<AddInts_Request>();

        request ->set_num1(atoll(argv[1]));
        request ->set_num2(atoll(argv[2]));

        AINFO<<"发送num1"<<request ->num1() <<"num2 = " << request ->num2() ;
        auto response = client ->SendRequest(request);
        //处理响应
        AINFO << "响应结果: sum = "<<response ->sum() ;

        //等待关闭
        apollo::cyber::WaitForShutdown();

        return 0;
}

         BUILD的内容如下所示:

# https://docs.bazel.build/versions/master/be/c-cpp.html#cc_binary
#***********************服务通信************************ #
cc_binary(
    name = "demo_SC",
    srcs = ["demo_cc_SC.cc"],
    deps = ["//cyber",
                "//cyber/demo_SC/demo_SC_pro:addints_cc",
               ],
)

cc_binary(
    name = "demo_CS",
    srcs = ["demo_cc_CS.cc"],
    deps = ["//cyber",
                "//cyber/demo_SC/demo_SC_pro:addints_cc",
               ],
)

编译上述程序得到如下文件

        执行可执行文件 demo_SC与demo_CS,这里需要注意,要先执行服务端,再执行客户端,要不然会产生错误,这种错误是因为代码本身的执行逻辑就不支持这两者调换顺序,此外执行demo_CS时需要给定 两个 int64的参数,这样demo_SC才能有显示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值