apollo中两种writer的代码分析

两种writer的代码分析

分析module/perception里面的segmentation和fusion组件都发出了消息,都调用了writer->Write(),但是前者的消息并没有发出来,后者的消息可以在Cyber_monitor中收到。不仅这两个,apollo中凡是channel name带了inner的都属于前者。

两者的writer定义分别如下:

segmentation:

writer_ = node_->CreateWriter<LidarFrameMessage>(output_channel_name_);

 fusion:

writer_ = node_->CreateWriter<PerceptionObstacles>(

comp_config.output_obstacles_channel_name());

可以看到主要区别就在传进去的消息类型模板不同。

消息定义不同

初步分析可以看到这两个模块发出的消息定义是不同的。

segmentation的消息定义如下:

class LidarFrameMessage {

public:

LidarFrameMessage() : lidar_frame_(nullptr) {

type_name_ = "LidarFrameMessage";

}



~LidarFrameMessage() = default;

...

...

};

fusion的消息定义如下:

class PerceptionObstacles : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:apollo.perception.PerceptionObstacles) */ {

public:

PerceptionObstacles();

virtual ~PerceptionObstacles();



PerceptionObstacles(const PerceptionObstacles& from);

...

...

};

可以看到后者继承了protobuf,这是protobuf根据proto文件自动生成的。

 

那么对于这两种不同的消息,Write()函数到底做了什么操作呢。

Write()函数对两种消息的不同处理

可以看到`node_->CreateWriter`这个函数根据不同模板会有不同的定义,最终调用如下:

template <typename MessageT>

auto NodeChannelImpl::CreateWriter(const proto::RoleAttributes& role_attr)

-> std::shared_ptr<Writer<MessageT>> {

...

std::shared_ptr<Writer<MessageT>> writer_ptr = nullptr;

if (!is_reality_mode_) {

writer_ptr = std::make_shared<blocker::IntraWriter<MessageT>>(new_attr);

} else {

writer_ptr = std::make_shared<Writer<MessageT>>(new_attr);

}

...

return writer_ptr;

}

可见决定是否输出的是`is_reality_mode_`,如果为真,则调用else内容,即正常看到的protobuf方法,如果为假,则指向`blocker::IntraWriter<MessageT>`。再追进去看`IntraWriter`干了什么,这个IntraWriter类,里面有Write()函数,即为对inner message实际处理的Writer(),主要调用了publish:

template <typename MessageT>

bool IntraWriter<MessageT>::Write(const MessagePtr& msg_ptr) {

if (!WriterBase::IsInit()) {

return false;

}

return blocker_manager_->Publish<MessageT>(this->role_attr_.channel_name(),

msg_ptr);

}

这个publish是blocker的publish,主要干了两件事,Enqueue和Notify:

template <typename T>

void Blocker<T>::Publish(const MessagePtr& msg) {

Enqueue(msg);

Notify(msg);

}

Notify应该就是记录一下发了哪些msg,Enqueue的作用是向发送队列中加入msg。

template <typename T>

void Blocker<T>::Enqueue(const MessagePtr& msg) {

if (attr_.capacity == 0) {

return;

}

std::lock_guard<std::mutex> lock(msg_mutex_);

published_msg_queue_.push_front(msg);

while (published_msg_queue_.size() > attr_.capacity) {

published_msg_queue_.pop_back();

}

}



template <typename T>

void Blocker<T>::Notify(const MessagePtr& msg) {

std::lock_guard<std::mutex> lock(cb_mutex_);

for (const auto& item : published_callbacks_) {

item.second(msg);

}

}

其中`published_msg_queue_`是一个`MessageQueue`,后者是一列表,如下:

using MessageQueue = std::list<MessagePtr>;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值