Cyber RT 组件

场景

无人车上的传感器数据可能需要被融合,比如在车辆上安装了多颗雷达,不同雷达由于安装位置与自身参数差异,可探测的角度、范围、距离等都是不尽相同的,现在需要将不同雷达感知到的数据融合在一起以建立车辆所处的完整环境,可以使用组件实现数据融合。

概念

组件是 Cyber RT 提供的用于构建应用程序模块的基类,

作用

可用于实现数据过滤、融合。

实例1

需求:启动之前的消息发布节点,对订阅到的数据进行过滤,只获取其中的姓名和年龄信息并输出到终端

准备:保证之前话题通信中的发布方可以正常运行;在 demo_cc 目录下新建文件夹:component_common01,并在 component_common01 下新建BUILD文件。

实现流程
上述需求可以通过组件实现只要包括如下步骤:
1.自定义类继承 Component类,并重写其 Init()与 Proc() 函数;
2.编写 dag 文件声 launch 文件;
3.编辑BUILD文件;
4.编译执行。

1.继承并重写 Component 类

component_common01 目录下新建 C++ 文件 common_cpt.h,输入如下内容:

/*
    编写一个Student学生信息过滤组件
    实现:
    1 包含被依赖的其他头文件
    2 自定义继承 compoenent
    3 在 cyberRT 中 注册组建
*/
//1 包含被依赖的其他头文件
#include "cyber/component/component.h"
#include "cyber/demo_base_proto/student.pb.h"

using apollo::cyber::Component;
using apollo::cyber::demo_base_proto::Student;

//2 自定义继承 compoenent

/*
    1. Component 模板需要与处理的消息类型一致;
    2.最多支持四种通道数据
*/

class CommonCpt : public  Component<Student> {
    public:
        bool Init() override;
        bool Proc(const std::shared_ptr<Student> & stu) override;
};
    //3 在 cyberRT 中 注册组建

CYBER_REGISTER_COMPONENT(CommonCpt)

component_common01 目录下新建 C++ 文件 common_cpt.cc,输入如下内容:

#include "cyber/demo_cc/component_common01/common_cpt.h"

//初始化函数
bool CommonCpt::Init(){
    AINFO<<"-----------Init-------------";
    return true;
}

//消息处理,订阅到 Student 消息时,会调用该函数
bool CommonCpt::Proc(const std::shared_ptr<Student> & stu){
    //处理逻辑
    AINFO<<"name = "<<stu->name()<<"; age = "<<stu->age();
    return true;
}

BUILD 文件

cc_library(
    name="common_cpt_lib",
    srcs=["common_cpt.cc"],
    hdrs=["common_cpt.h"],
    deps=[
        "//cyber",
        "//cyber/demo_base_proto:student_cc"
        ]
)

cc_binary(
    name = "lib_common_cpt.so",
    deps = [":common_cpt_lib"],
    linkshared = True,
    linkstatic = False,

)

使用的模板与订阅的消息类型一致,
Init()函数是用于初始化的,只会执行一次。
proc()函数在订阅到消息时就会被回调执行。

2.编写 dag 文件与 launch 文件
在 component_common01 目录下创建 cpt.dag 文件,内容如下:

module_config{
    module library: "/apollo/bazel-bin/cyber/demo_cc/component_common01/lib_common_cpt.so"
    components {
        class_name:"CommonCpt"
        config{
            name : "my_common"
            readers{
                channel: "chatter"
            }
        }
    }
}

在 component_common01 目录下创建 cpt.launch 文件,内容如下:

<cyber>
    <module>
        <name>my_module</name>
        <dag_config>/apollo/cyber/demo_cc/component_common01/cpt.dag</dag_config>
        <process_name>my_cpt</process_name>
    </module>

</cyber>

实例2

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

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

模拟雷达消息发布实现如下:
1.定义雷达消息
demo_base_proto 目录下新建 laser.proto,输入如下内容:

// 1 声明版本
syntax = "proto2";
// 2 声明包
package apollo.cyber.demo_base_proto;

// 3 创建消息
message Laser {
    //雷达消息编号
    optional int64 seq = 1;
    //障碍物个数
    optional int64 count = 2;

}

配置文件添加如下内容:

#############组件
proto_library(
    name="laser_proto",
    srcs=["laser.proto"]
)

cc_proto_library(
    name = "laser_cc",
    deps = [":laser_proto"],
)

然后编译,生成 laser.pb.cc 等文件。

2.分别编写前后雷达消息发送节点
component_common2 目录下新建C++文件 front_laser.cc,输入如下内容:

/*
    需求:模拟雷达发布节点,发布laser 消息
    实现:
                1 包含头文件;
                2 初始化 cyber 框架;
                3 创建节点
                4 创建发布方
                5 组织并发布数据
                6 等待关闭,释放资源
*/
#include "cyber/cyber.h"
#include "cyber/demo_base_proto/laser.pb.h"

using apollo::cyber::demo_base_proto::Laser;

int main(int argc, char const *argv[])
{
    /* code */
    apollo::cyber::Init(argv[0]);
    AINFO<<"前雷达节点———";
    auto front_laser_node = apollo::cyber::CreateNode("front_bode");

    auto front_laser = front_laser_node->CreateWriter<Laser>("/front/laser");
    apollo::cyber::Rate rate(0.5);
    uint64_t seq=0;
    while(apollo::cyber::OK()){
        seq++;
        auto laser_ptr=std::make_shared<Laser>();
        laser_ptr->set_seq(seq);
        laser_ptr->set_count(2);
        front_laser->Write(laser_ptr);
        rate.Sleep();
    }

    apollo::cyber::WaitForShutdown();

    return 0;
}

BUILD 文件:

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

编译执行
在这里插入图片描述

back_laser.cc 内容与 front_laser.cc 类似。

3.重写组件
laser_cpt.h:

/*
    组件相关的头文件
    1 包含其他相关头文件
    2 自定义继承组件,重写 Init() 和 Proc() 函数
    3 在 cyber 中注册组件
*/

#include "cyber/component/component.h"
#include "cyber/demo_base_proto/laser.pb.h"

using apollo::cyber::Component;
using apollo::cyber::demo_base_proto::Laser;

class LaserCpt: public Component<Laser,Laser>{
    public:
        bool Init() override;
        bool Proc(const std::shared_ptr<Laser>& front, const std::shared_ptr<Laser>& back) override;
    private:
        std::shared_ptr<apollo::cyber::Writer<Laser>> writer = nullptr;
        uint64_t seq;
};

CYBER_REGISTER_COMPONENT(LaserCpt)

laser_cpt.cc:

#include "cyber/demo_cc/component_common02/laser_cpt.h"

bool LaserCpt::Init(){
    AINFO<<"-----------------初始化发布方-----------------";
    //初始化一个发布者
    //this->node_->CreateWriter
    writer = this->node_->CreateWriter<Laser>("laser");
    seq=0;
    return true;
}

bool LaserCpt::Proc(const std::shared_ptr<Laser>& front, const std::shared_ptr<Laser>& 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 sum = front_count + back_count;

    AINFO << "front_seq="<<front_seq <<"   ----   back_seq="<<back_seq;
    AINFO<<"sum = "<<sum;
    //数据写出

    auto laser_ptr = std::make_shared<Laser>();
    laser_ptr->set_count(sum);
    laser_ptr->set_seq(seq);

    writer->Write(laser_ptr);


    return true;
}

4.dag 文件与launch 文件
dag:

module_config{
    module library: "/apollo/bazel-bin/cyber/demo_cc/component_common02/liblaser_cpt.so"
    components {
        class_name:"LaserCpt"
        config{
            name : "my_laser"
            readers{
                channel: "/front/laser"
            }
            readers{
                channel: "/back/laser"
            }
        }
    }
}

launch:

<cyber>
    <module>
        <name>my_laser</name>
        <dag_config>/apollo/cyber/demo_cc/component_common02/cpt2.dag</dag_config>
        <process_name>my_laser</process_name>
    </module>

</cyber>

5.编译运行
在这里插入图片描述

实例3

需求:周期性的执行某种操作
准备:在demo_cc 目录下新建文件夹:component_timer下新建BUILD文件

实现流程:
上述需求可以通过定时器组件实现,只需包括以下步骤:
1.自定义类继承 TimerComponent 类,并重写其 Init() 与 Proc() 函数;
2.编写 dag 文件与 launch文件;
3.编辑 BUILD 文件;
4.编译执行。

1.继承并重写 TimerComponent 类
component_timer 目录下新建 C++ 文件 timer_cpt.h,输入如下内容:

/*
    需求:实现定时器,循环控制台打印出语句
    实现:
        1 包含头文件
        2 自定义继承 TimerComponent 重写 Init() 与 Proc()
        3 在 Cyber 中注册组件
*/

#include "cyber/component/timer_component.h"
#include "cyber/component/component.h"

using apollo::cyber::TimerComponent;

class MyTimer: public TimerComponent{
    public:
        bool Init() override;
        bool Proc() override;
    private:
        uint64_t seq;
};

CYBER_REGISTER_COMPONENT(MyTimer)


component_timer 目录下新建 C++ 文件 timer_cpt.cc,输入如下内容:

#include "cyber/demo_cc/component_timer/timer_cpt.h"

bool MyTimer::Init(){
    AINFO <<"-----------------------timer Component Init";
    seq=0;
    return true;
}

bool MyTimer::Proc(){
    seq++;
    AINFO<<"-------------------"<<seq;
    return true;
}

新建 BUILD 文件,输入如下内容:

# load("//tools/install:install.bzl","install")

# 配合组件
cc_library(
    name = "timer_cpt_lib",
    deps = [
        "//cyber",
    ],
    srcs = ["timer_cpt.cc"],
    hdrs = ["timer_cpt.h"],
)

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

# 将 dag 与 launch 划分在 同一文件组
filegroup(
    name="conf",
    srcs=[
        ":timer.dag",
        ":timer.launch",
    ],
)
# 安装函数安装
install(
    name="install",
    data=[
        ":conf",
    ],
    runtime_dest="cyber/demo_cc/component_timer",
    targets=[
        ":libtimer_cpt.so",
    ],
)

2.dag 文件 与 launch 文件:
dag:

module_config{
    module library: "/apollo/bazel-bin/cyber/demo_cc/component_timer/libtimer_cpt.so"
    components {
        class_name:"MyTimer"
        config{
            name : "timer"
            interval: 10
        }
    }
}

launch:

<cyber>
    <module>
        <name>MyTimer</name>
        <dag_config>/apollo/cyber/demo_cc/component_timer/timer.dag</dag_config>
        <process_name>MyTimer</process_name>
    </module>

</cyber>
  • 26
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞大圣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值