Cyber-组件需求2

 

demo_base_proto
|-- lasers.proto
|-- BUILD
demo_cc
|-- front_laser.cc
|-- back_laser.cc
|-- BUILD
component_common02
|-- laser_cpt.h
|-- laser_cpt.cc
|-- cpt.dag
|-- cpt.launch
|-- BUILD

 

/*
    需求:
        现无人车前后各安装了一颗雷达,雷达可以发布障碍物信息,需要将两颗雷达发送的消息进行融合

    准备:
        编写两个节点,分别模拟前后雷达发送障碍物消息
        在demo_cc目录下新建文件夹:component_common02,并在component_common02下新建BUILD文件
*/

///////////////////////////proto文件///////////////////////////
// 在demo_base_proto文件夹下新建lasers.proto文件
syntax = "proto2";

package apollo.cyber.demo_base_proto;

message Lasers {
    required uint64 seq = 1; // 第几条消息
    required uint64 count = 2; // 传感器所所感知的障碍物个数
}

 

/////////////////////////////////////////////////////////////

///////////////////////////proto BUILD文件//////////////////////////////////
package (default_visibility = ["//visibility:public"])
proto_library(
    name = "lasers_proto_lib",
    srcs = ["lasers.proto"],
)

cc_proto_library(
    name = "lasers_cc_lib",
    deps = [":lasers_proto_lib"],
)

 

/////////////////////////////////////////////////////////////

// bezal build cyber/demo_base_proto/...
// 

/////////////////////////节点1的cpp///////////////////////////////////

// 在demo_cc文件夹下新建front_laser.cc
#include "cyber/cyber.h"
#include "stdlib.h"
#include "cyber/demo_base_proto/lasers.pb.h"
using apollo::cyber::demo_base_proto::Lasers;

int main(int argc, char* argv[])
{
    // 初始化
    apollo::cyber::Init(argv[0]);
    AINFO << "初始化...";

    // 定义节点1
    auto laser_node = apollo::cyber::CreateNode("front_laser_node");

    // 创建发布方
    auto laser_talker = laser_node->CreateWriter<Lasers>("front_laser");

    uint64_t seq = 0;
    apollo::cyber::Rate rate(0.5); // 循环频率,2s输出一次
    while(apollo::cyber::OK()){
        int obstacle_cnt = rand() % 100;  // 随机100以内数量的障碍
        ++seq;
        // 创建消息
        auto laser_msg = std::make_shared<Lasers>();
        laser_msg->set_seq(seq);
        laser_msg->set_count(obstacle_cnt);
        AINFO << "发布第: " << laser_msg->seq() << " 条消息, 存在" << laser_msg->count() << "个障碍";
        laser_talker->Write(laser_msg);
        rate.Sleep();
    }
    apollo::cyber::WaitForShutdown();

    return 0;
}

 

/////////////////////////节点1的BUILD文件////////////////////////////////////
package(default_visibility = ["//visibility:public"])
cc_binary(

    name = "front_laser_cc_bin",
    srcs = ["front_laser.cc"],
    deps = [
            "//cyber",
            "//cyber/demo_base_proto:lasers_cc_lib"
    ]
)
cc_binary(

    name = "back_laser_cc_bin",
    srcs = ["back_laser.cc"],
    deps = [
            "//cyber",
            "//cyber/demo_base_proto:lasers_cc_lib"
    ]
)

 

////////////////////////组件实现///////////////////////////////////////////////////
/*
    流程
        1.自定义类继承Component类,并重写其Init()与Proc()函数;
        2.编写dag文件与launch文件
        3.编写BUILD文件
        4.编译执行
*/
////////////////////////.h文件/////////////////////////
// component_common02目录下新建.h文件laser_cpt.h
#include "cyber/component/component.h"
#include "cyber/demo_base_proto/lasers.pb.h"

using apollo::cyber::Component;
using apollo::cyber::demo_base_proto::Lasers;

class LaserCpt : public Component<Lasers, Lasers>{ // 有两个发布方
public:
    bool Init() override; // 组件启动时会自动调用Init进行初始化
    // 当组件接收到传感器的消息时,会调用Proc方法对消息进行处理
    bool Proc(const std::shared_ptr<Lasers>& front, const std::shared_ptr<Lasers>& back) override;
private:
    // 定义一个writer,当数据融合后进行发布
    std::shared_ptr<apollo::cyber::Writer<Lasers> > writer = nullptr;
    // 发布次数
    uint64_t seq = 0;
};

CYBER_REGISTER_COMPONENT(LaserCpt); // 注册该组件

 

//////////////////////////////////////////////////////

////////////////////////.cpp文件///////////////////////
// component_common02目录下新建c++文件laser_cpt.cc
#include "cyber/component_common02/laser_cpt.h"

bool LaserCpt::Init()
{
    AINFO << "init...";
    // 每个component都有自己的一个node, 可通过this->node_调用
    writer = this->node_->CreateWriter<Lasers>("laser");
    seq = 0;
    return true;
}

bool LaserCpt::Proc(const std::shared_ptr<Lasers>& front, const std::shared_ptr<Lasers>& back)
{
    ++seq;
    // 数据融合
    uint64_t front_seq = front->seq();
    uint64_t front_count = front->count();
    uint64_t back_seq = back->seq();
    uint64_t back_count = back->count();    
    // 数据写出
    uint64_t count = front_count + back_count; // 感知的障碍物总数量
    AINFO << "front_seq: " << front_seq << " back_seq: " << back_seq << "  merge count: " << count;
    auto laser_msg = std::make_shared<Lasers>();
    laser_msg->set_seq(seq);
    laser_msg->set_count(count);
    writer->Write(laser_msg);
    return true;
}

 

/////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////BUILD///////////////////////////////
package(default_visibility = ["//visibility:public"])
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
load("//tools:cpplint.bzl", "cpplint")
load("//tools/install:install.bzl", "install") # build不会自动导入install,需要手动导入

cc_library(
    name = "laser_cpt_cc_lib",
    srcs = ["laser_cpt.cc"],
    hdrs = ["laser_cpt.h"],
    deps = [
            "//cyber",
            "//cyber/demo_base_proto:lasers_cc_lib",],
    alwayslink = True,
)

cc_binary(
    name = "laser_cpt_cc_bin.so",
    linkshared = True,
    linkstatic = True,
    deps = [":laser_cpt_cc_lib"],
)

# filegroup和install为组件必须的,其中filegroup的作用是将dag文件和launch文件打包
# install的作用是安装dag和launch文件
filegroup(
    name = "conf", # 自定义名称
    # 将dag文件和launch文件打包
    srcs = [
            ":cpt.dag", # dag文件的文件名
            ":cpt.launch", # launch文件的文件名
    ],
)
# 安装dag和launch
install(
    name = "install", # 自定义名称
   
    data = [
            ":conf" # filegroup的名称
    ],
    runtime_dest = "cyber/demo_cc/component_common02", # 当前包相对路径
    targets = [
        "//cyber/demo_cc:front_laser_cc_bin", # 发布方
        "//cyber/demo_cc:back_laser_cc_bin", 
        ":laser_cpt_cc_bin.so", # 组件的动态库,cc_binary的name
    ],
)

 

////////////////////////////////////////dag文件/////////////////////////////////////
// 在component_common02目录下新建cpt.dag文件
module_config {
    module_library : "/apollo/bazel-bin/cyber/component_common02/laser_cpt_cc_bin.so"
    components {
        class_name : "LaserCpt" # 类名
        config {
            name : "my_common" # 自定义名称
            # 该组件监听channel的名称,在本例中为两个传感器的发布channel
            readers {
                channel: "front_laser"
            }
            readers {
                channel: "back_laser"
            }
        }
    }
 }

 

//////////////////////////////////////////////////////////////////////////////

//////////////////////////launch文件//////////////////////////////////////////
// 在component_common02目录下新建cpt.launch文件
<cyber>
    <module>
        <!-- 自定义名称 -->
        <name>my_common</name>
        <!-- dag文件的绝对路径 -->
        <dag_conf>/apollo/cyber/component_common02/cpt.dag</dag_conf>
        <process_name>my_common</process_name>
    </module>
</cyber>

 

////////////////////////////////////////////////////////////////////////////

 

posted @ 2023-09-18 13:44  WTSRUVF  阅读(15)  评论(0编辑  收藏  举报