Apollo下的Cyber RT通信

目录结构: 在这里插入图片描述

|-- BUILD
|-- proto
|   |-- BUILD
|   `-- examples.proto
`-- talker.cc

proto文件下:

BUILD
(bazel配置proto)

package(default_visibility = ["//visibility:public"])

#生成两种库,examples_cc_proto和examples_proto
#依赖中冒号是什么意思
cc_proto_library(
    name = "examples_cc_proto",
    deps = [
        ":examples_proto",
    ],
)

proto_library(
    name = "examples_proto",
    srcs = ["examples.proto"],
)

过程:
源文件examples.proto生成库文件examples_proto,
依赖于库文件examples_proto又生成了examples_cc_proto(推测就是examples.pb.cc和examples.pb.h)。且这个examples.pb.h路径可以通过
zxj_example/proto/examples.pb.h这个路径与zxj_example相对于apollo文件夹的路径有关

#include "zxj_example/proto/examples.pb.h"

即仿佛examples.pb.h时在本工程zxj_example/proto/下,但是其实并不是,实际在
/home/e301-ai/.cache/bazel/_bazel_e301-ai/540135163923dd7d5820f3ee4b306b32/execroot/apollo/bazel-out/local-fastbuild/genfiles/zxj_example/proto/examples.pb.h
后来的实验事实证明,examples.pb.h这个名字之和proto源文件examples.proto名字有关,和库名字“examples_cc_proto”无关

examples.proto

syntax = "proto2";

package apollo.cyber.examples.proto;

message Chatter
{
    optional uint64 timestamp = 1;
    optional uint64 lidar_timestamp = 2;
    optional uint64 seq = 3;
    optional bytes content = 4;
};

这里的

package apollo.cyber.examples.proto;

非常重要
根据Protocol Buffer的官方文档

package foo.bar;
message Open { ... }

在C ++中,生成的类包装在C ++命名空间中。例如,类Open将在命名空间foo::bar中
同理,Chatter类将在examples.pb.h中apollo::cyber::examples::proto命名空间下

namespace appolo {
namespace cyber {
namespace examples {
namespace proto {
...

与talker.cc并列的BUILD:

load("//tools:cpplint.bzl","cpplint")

package(default_visibility = ["//visibility:public"])

# https://docs.bazel.build/versions/master/be/c-cpp.html#cc_binary
cc_binary(
    name = "talker",
    srcs = ["talker.cc"],
    deps = [
        "//cyber",
        "//zxj_example/proto:examples_cc_proto",
    ],
)

cpplint()

通过源文件talker.cc和zxj_example路径下的examples_cc_proto库生成目标talker

talker.cc:

#include "cyber/cyber.h"
#include "zxj_example/proto/examples.pb.h"
#include "cyber/time/rate.h"
#include "cyber/time/time.h"
#include <iostream>

using apollo::cyber::Rate;
using apollo::cyber::Time;
using apollo::cyber::examples::proto::Chatter;

int main(int argc,char** argv)
{
  apollo::cyber::Init(argv[0]);
  auto talker_node = apollo::cyber::CreateNode("talker");
  auto talker = talker_node->CreateWriter<Chatter>("channel/chatter");
  Rate rate(1.0);
  uint64_t seq = 0;
  while (apollo::cyber::OK())
  {
    auto msg = std::make_shared<Chatter>();
    msg->set_timestamp(Time::Now().ToNanosecond());
    msg->set_lidar_timestamp(Time::Now().ToNanosecond());
    msg->set_seq(seq);
    msg->set_content("Hello,apollo!");
    talker->Write(msg);
    std::cout << "talker sent a message!No. " << seq << std::endl;
    seq++;
    rate.Sleep();
  }
  return 0;
}

步骤:
1.初始化

apollo::cyber::Init(argv[0]);
cyber/init.cc
bool Init(const char* binary_name) {
  std::lock_guard<std::mutex> lg(g_mutex);
  if (GetState() != STATE_UNINITIALIZED) {
    return false;
  }

  InitLogger(binary_name);
  auto thread = const_cast<std::thread*>(async_logger->LogThread());
  scheduler::Instance()->SetInnerThreadAttr("async_log", thread);
  std::signal(SIGINT, OnShutdown);
  // Register exit handlers
  if (!g_atexit_registered) {
    if (std::atexit(ExitHandle) != 0) {
      AERROR << "Register exit handle failed";
      return false;
    }
    AINFO << "Register exit handle succ.";
    g_atexit_registered = true;
  }
  SetState(STATE_INITIALIZED);
  return true;
}

2.创建发送节点,并指定节点名称

auto talker_node = apollo::cyber::CreateNode("talker");

这里的autoclass std::unique_ptr<apollo::cyber::Node>
apollo::cyber::CreateNode()cyber/cyber.cc文件中定义,参数是节点的名字,返回一个指向apollo::cyber::Node的指针(unique_ptr)。

#include "cyber/cyber.h"

#include <memory>
#include <string>
#include <utility>

#include "cyber/common/global_data.h"
#include "cyber/proto/run_mode_conf.pb.h"

namespace apollo {
namespace cyber {

using apollo::cyber::common::GlobalData;
using apollo::cyber::proto::RunMode;

std::unique_ptr<Node> CreateNode(const std::string& node_name,
                                 const std::string& name_space) {
  bool is_reality_mode = GlobalData::Instance()->IsRealityMode();
  if (is_reality_mode && !OK()) {
    // add some hint log
    AERROR << "please initialize cyber firstly.";
    return nullptr;
  }
  std::unique_ptr<Node> node(new Node(node_name, name_space));
  return std::move(node);
}

}  // namespace cyber
}  // namespace apollo

3.利用发送节点定义发送器,并指定话题名称

  auto talker = talker_node->CreateWriter<Chatter>("channel/chatter");

这里的auto是class std::shared_ptr<apollo::cyber::Writer<apollo::cyber::examples::proto::Chatter>>
CreateWriter()函数在apollo/cyber/node/node.h中

template <typename MessageT>
auto Node::CreateWriter(const std::string& channel_name)
    -> std::shared_ptr<Writer<MessageT>> {
  return node_channel_impl_->template CreateWriter<MessageT>(channel_name);
}

4.根据proto文件的message类,定义消息msg

auto msg = std::make_shared<Chatter>();

这里的autoclass std::shared_ptr<apollo::cyber::examples::proto::Chatter>(指向Chatter的一个指针)
然后msg可以通过msg->set_xxx()调用set_xxx()一系列API
5.利用Write()函数,通过发送器将消息发送出去

talker->Write(msg);

listener.cc:

#include "cyber/cyber.h"
#include "zxj_example/proto/examples.pb.h"

void MessageCallback(
    const std::shared_ptr<apollo::cyber::examples::proto::Chatter> &msg)
{
    std::cout << "Received message seq-> " << msg->seq() << ",";
    std::cout << "msgcontent->" << msg->content() << std::endl;
}

int main(int argc,char** argv)
{
    apollo::cyber::Init(argv[0]);
    auto listener_node = apollo::cyber::CreateNode("listener");
    auto listener =
        listener_node->CreateReader<apollo::cyber::examples::proto::Chatter>(
            "channel/chatter",MessageCallback
        );
    apollo::cyber::WaitForShutdown();
    return 0;
}

现象:
在这里插入图片描述
ToDo:
研究智能指针原理

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值