apollo模块信道数据

在本例中,主要讲解如何查看apollo系统中各模块之间的信道数据,这里主要查看perception信道数据,以查看感知信道的数据为例。

使用CyberMonitor查看Channel数据

在播放数据包后,打开新的终端,在 Apollo Docker 环境中输入以下命令,启动 cyber_monitor

root@in-dev-docker:/apollo_workspace#  cyber_monitor

cyber_monitor 启动之后,会在终端中显示一个交互界面。cyber_monitor 自动从拓扑中收集所有 channel 信息并分两列显示:分别为 Channels(channel 名称)和 FrameRatio(数据频率)。

channel 信息默认显示为红色,当有数据流经 channel 时,对应的行就会显示成绿色。
请添加图片描述

常用命令

ESC | q key ---- 退出
Backspace ---- 后退
h | H ---- 显示帮助页
PageDown | Ctrl+d ---- 上一页
PageUp | Ctrl+u ---- 下一页
Up, down or w, s keys ---- 上下移动当前的高亮行
Right arrow or d key ---- 进入高亮行, 显示高亮行数据的详细信息
Left arrow or a key ---- 从当前界面返回上一层界面
Enter key ---- 与 d 键相同
f | F ---- 显示数据帧频率
t | T ---- 显示 channel 消息类型
Space ---- 关闭|开启 channel (仅在 channel 有数据到达时有效;channel 关闭后会变成黄色)
i | I ---- 显示 channel 的 Reader 和 Writer 信息
b | B ---- 显示 channel 消息内容
n | N ---- 显示消息中 RepeatedField 的下一条数据
m | M ---- 显示消息中 RepeatedField 的上一条数据
  • 使用CyberVisualizer查看原始感知数据
    在播放数据包后,重新打开一个终端,在 Apollo Docker 环境中执行如下命令运行 cyber_visualizer
root@in-dev-docker:/apollo_workspace# cyber_visualizer

cyber_visualizer 会收到所有活动 channel 的信息(来自回放数据)并显示出来。当有数据流经 channel 时,在 ChannelNames 下会显示 channel 列表。您可以查看点云和相机数据。
请添加图片描述
请添加图片描述

使用cyber record包解析工具解析Recoder包

当前解析cyber record包需要在docker中进行,并且依赖cyber和编译好的proto文件。实际上cyber_record录制好之后就是按照一定的格式保存的文件,对用户来说,拿到录制好的文件之后,用更少的依赖进行解析是最好的。

pip3 install cyber_record record_msg

项目地址:
https://cyber-record.readthedocs.io/en/latest/#​cyber-record.readthedocs.io/en/latest/#

原理

由于cyber record本身能够进行自解析,因此从理论上来说也是可行的,首先是分析cyber record的格式,然后调用protobuf进行反序列化。cyber record的格式在上面几篇文章中已经介绍过了,我们这里重点介绍下如何进行自解析。
protobuf的原理实际上是根据用户定义好的proto文件,来对消息进行解析,实际使用的时候,protobuf采用了descriptor来描述proto文件,而descriptor_pb则是proto文件的proto,这里有点绕口,你可以理解为“描述文件”的“描述文件”,通过上述2个定义,我们就可以知道消息的结构,有哪些字段,也就能够解析消息了。
但问题没那么简单,我们知道一个proto文件中可能会引入另外的proto文件,也就是说一个proto文件的descriptor_pb只能描述它自己,但并没有包含它引用的消息的格式,这有点类似c++的头文件。但解析整个消息,我们必须知道所有消息的格式才行,包括它们的引用。好在cyber record中都保存了这些信息。
把自身的消息描述descriptor和它依赖的所有消息的descriptor,都放入descriptor_pool,之后就可以根据消息类型来创建消息了。
以上就是具体的实现原理,简单来说,由于每个bag包中的消息种类有限,例如有5种,那么把这5种消息的descriptor都存入bag包中,体积也不会占用太大,而最后我们可以根据这些描述信息,去解析保存在bag中对应类型的消息。

安装

只需要通过pip安装cyber_record库,就可以在本地解析record文件了,不需要其它任何依赖。

pip3 install cyber_record

1. 命令行

  • Info
    通过cyber_record info来获取record文件的统计信息
$ cyber_record info -f example.record.00000
record_file: example.record.00000
version:     1.0
begin_time:  2021-07-23 17:12:15.114944
end_time:    2021-07-23 17:12:15.253911
duration:    0.14 s
size:        477.55 KByte
message_number: 34
channel_number: 8

/apollo/planning                      , apollo.planning.ADCTrajectory         , 1
/apollo/routing_request               , apollo.routing.RoutingRequest         , 0
/apollo/monitor                       , apollo.common.monitor.MonitorMessage  , 0
/apollo/routing_response              , apollo.routing.RoutingResponse        , 0
/apollo/routing_response_history      , apollo.routing.RoutingResponse        , 1
/apollo/localization/pose             , apollo.localization.LocalizationEstimate, 15
/apollo/canbus/chassis                , apollo.canbus.Chassis                 , 15
/apollo/prediction                    , apollo.prediction.PredictionObstacles , 2
  • Echo
    通过cyber_record echo打印指定topic的消息到命令行,打印"/apollo/canbus/chassis"下的所有消息到命令行
$ cyber_record echo -f example.record.00000 -t /apollo/canbus/chassis
engine_started: true
speed_mps: 0.0
throttle_percentage: 0.0
brake_percentage: 0.0
driving_mode: COMPLETE_AUTO_DRIVE
gear_location: GEAR_DRIVE
header {
  timestamp_sec: 1627031535.112813
  module_name: "SimControl"
  sequence_num: 76636
}

你也可以用以下命令输出到文件

cyber_record echo -f example.record.00000 -t /apollo/canbus/chassis > 1.txt

2. 读取消息

安装之后,可以参考以下例子读取消息

  • 读取所有消息
from cyber_record.record import Record


file_name = "20210521122747.record.00000"
record = Record(file_name)
for topic, message, t in record.read_messages():
  print("{}, {}, {}".format(topic, message, t))
  • 根据topic过滤
def read_filter_by_topic():
  record = Record(file_name)
  for topic, message, t in record.read_messages('/apollo/sensor/rs32/Scan'):
    print("{}, {}, {}".format(topic, type(message), t))
  • 根据时间过滤
def read_filter_by_time():
  record = Record(file_name)
  for topic, message, t in record.read_messages(start_time=1627031535164278940,\
      end_time=1627031535215164773):
    print("{}, {}, {}".format(topic, type(message), t))
  • 根据Topic和时间过滤
def read_filter_by_both():
  record = Record(file_name)
  for topic, message, t in record.read_messages('/apollo/canbus/chassis', \
      start_time=1627031535164278940, end_time=1627031535215164773):
    print("{}, {}, {}".format(topic, type(message), t))

3. 保存消息

获取到消息类型之后,你可以根据不同的topic来处理和保存消息,你只需要知道消息的结构就行了,也不需要添加编译好的proto文件依赖。
为了方便处理消息,通过安装record_msg,可以帮助我们快速的读取和保存消息。

pip3 install record_msg

record_msg提供了3种不同类型的接口

  • csv格式
    通过to_csv可以把消息的属性展开为数组,减轻了手动一个个枚举属性的问题。下面的例子中to_csv会把pose的所有属性都输出为一个数组。
import csv
from record_msg.parser import to_csv

f = open("message.csv", 'w')
writer = csv.writer(f)

def parse_pose(pose):
  '''
  save pose to csv file
  '''
  line = to_csv([pose.header.timestamp_sec, pose.pose])
  writer.writerow(line)

f.close()

如果你要有选择的输出属性,可以自己构建数组然后传递给to_csv展开属性 ,例如pose.position实际上包含x,y,z3个属性,我们不必一个个构造,通过to_csv(pose.position)会自动输出

[pose.position.x, pose.position.y, pose.position.z] 
  • 保存图像
    你可以通过ImageParser来解析和保存record包中的图像。
from record_msg.parser import ImageParser

image_parser = ImageParser(output_path='../test')
for topic, message, t in record.read_messages():
  if topic == "/apollo/sensor/camera/front_6mm/image":
    image_parser.parse(image)
    # or use timestamp as image file name
    # image_parser.parse(image, t) 

通过output_path指定图像输出的路径,默认情况下图像编号从0-n,也可以自定义图像名称,例如输出时间戳为图像的名称。

  • 保存点云
    可以通过PointCloudParser来解析和保存record包中的点云。
pointcloud_parser = PointCloudParser('../test')
for topic, message, t in record.read_messages():
  if topic == "/apollo/sensor/lidar32/compensator/PointCloud2":
    pointcloud_parser.parse(message)
    # other modes, default is 'ascii'
    # pointcloud_parser.parse(message, mode='binary')
    # pointcloud_parser.parse(message, mode='binary_compressed')

通过output_path指定点云文件的保存路径,默认情况下图像编号从0-n,也可以自定义点云名称,例如输出时间戳为图像的名称,根据不同的点云消息格式,你需要传入不同的mode,默认点云为ascii格式。

3. 写入消息

当缺少数据包,或者想通过数据集来自己构造数据包的时候,cyber_record也提供了写入消息,并且保存为Record包的能力。

import time

from cyber_record.record import Record
from modules.map.proto import map_pb2

write_file_name = "example_w.record.00000"

def write_message():
  pb_map = map_pb2.Map()
  pb_map.header.version = 'hello'.encode()

  with Record(write_file_name, mode='w') as record:
    record.write('/apollo/map', pb_map, int(time.time() * 1e9))

构造好的record文件保存为write_file_name。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值