标签: DBC

  • Palisade 只读 CAN 解码器:9 条报文、28 信号与三条边界

    结论:这份 Palisade 2020 解码器不是通用 DBC 解析器,而是被压缩到 9 条报文、28 个信号的窄口径只读实现:未知帧静默忽略,已知报文的 payload 长度不符则直接返回错误。决定它可用性的不是那张报文表,而是三条边界——它是 opendbc 的 MIT 授权只读子集、不引入上游任何车辆控制与发送代码、未用实车日志按年款与市场确认前不得把新信号提升为 canonical 状态。

    解码授权清单:只有 9 条报文

    解码器被固定在 dbc 仓库的 HYUNDAI_PALISADE_2020 provenance manifest 上,只直接解析下表中的报文,其余一律视为未知帧。六条报文在素材里给出了十六进制 ID,另外三条以 DBC 报文名引用。用途分两类:少数信号进入 canonical 状态(车速、转向角、纵向加速度、挡位、轮速、SCC 状态),其余只作为 raw diagnostics 呈现。

    DBC 报文 CAN ID 信号 解码后用途
    CLU11 未给出 CF_Clu_Vanz、CF_Clu_SPEED_UNIT 仪表车速与单位,canonical
    SAS11 未给出 SAS_Angle 转向角,canonical
    TCS13 未给出 ACCEL_REF_ACC、DriverOverride 纵向加速度与驾驶员制动状态,canonical
    CGW1 0x541 近光、驾驶席车门、前排安全带、雨刮与灯光开关 近光映射为 night_mode,其余为 raw diagnostics
    GW_DDM_PE 0x521 四门状态 raw diagnostics
    DATC12 0x042 驾驶席/副驾摄氏设定温度 raw diagnostics
    LVR12 0x367 CF_Lvr_Gear 换挡杆挡位状态,canonical
    WHL_SPD11 0x386 WHL_SPD_FL/FR/RL/RR 四轮轮速,canonical
    SCC14 0x389 ACCMode SCC 激活状态,canonical

    raw diagnostics:可以读,不能判定

    素材明确写明当前没有实车捕获,因此这组信号以 manifest 固定版本的 DBC 所载 message ID、bit 位置与 scale 为唯一依据。数值以 MESSAGE.SIGNAL 为键写入 VehicleState.raw_signals,在 HMI Diagnostics 中只读展示。硬规则是:不得自行解释 DBC 枚举值的含义,也不得把这些值用于车门、安全带、空调的 canonical 状态或任何车辆控制。

    raw 键 DBC 物理值 换算
    CGW1.CF_Gway_DrvDrSw 驾驶席车门开关 原始枚举,不解释
    CGW1.CF_Gway_DrvSeatBeltSw、CGW1.CF_Gway_AstSeatBeltSw 前排安全带开关 原始枚举,不解释
    GW_DDM_PE.C_DRVDoorStatus、C_ASTDoorStatus、C_RLDoorStatus、C_RRDoorStatus 四门状态 原始枚举,不解释
    DATC12.CR_Datc_DrTempDispC、CR_Datc_PsTempDispC 驾驶席/副驾摄氏设定温度 raw × 0.5 + 14

    唯一给出换算式的只有空调温度这一组,其余全部停在「原始枚举」层级。这不是偷懒,而是把「DBC 说有这个信号」和「这个枚举在这个年款上代表开或关」两件事分开——后者只能由实车日志证明。

    0x541 近光位的实车验证判据

    CF_Gway_HeadLampLow 只表示近光是否点亮,既推断不出自动灯光设置,也推断不出环境照度。因此批准这条映射前,必须在停车、点火 ON 状态下逐条记录,并核对日志 payload 第四个字节的最高位是否与下表一致;不一致就不发布该映射,而是回到 DBC 与车辆年款、配置的核对上。

    条件 期望 0x541 bit 31 期望 night_mode
    灯光 OFF 0 false
    近光 ON 1 true
    AUTO 模式 与实际近光点亮状态相同 与实际近光点亮状态相同

    采集与回放必须走两条不同的路:设备以 SocketCAN can0 接入后只做接收,用带时间戳的日志记录 0x541;捕获内容绝不向物理 can0 回发,开发环境只在 vcan0 上回放。每次切换条件时单独记录时刻与观察到的灯光状态。回归 fixture 中不得放入车辆识别信息、位置、时间等敏感原始日志,只保留已验证的 0x541 帧与必要的最小状态帧。

    三条边界与当前证据状态

    把散落在 NOTICE 与源说明里的约束收拢成一张表,才能看清这份解码器能承担什么。

    边界 具体要求 落地动作
    只读 文件与解码器均为接收专用,上游的车辆控制与发送代码不引入 工程上只允许 candump 侧记录,禁止任何向实车总线的写入
    未验证不提升 在车辆年款、市场、配置上用实车日志确认 frame 与 signal 之前,不把新信号加入 canonical state 新增信号先进 raw_signals,验证通过后再提级
    权利与适配 派生自 opendbc 的 MIT 授权内容,须保留原始通知;须核对车型年款与市场适配性 分发时保留上游 MIT 声明,逐车型做适配核对

    证据状态同样要如实标注:源说明指出实车信号验证仍在进行中,且该 DBC 的 BU_ 列表缺少若干被其报文与信号引用的节点名,严格解析器可能需要先做清理;文件本身按字节原样保留。子集规模为 9 条报文、28 个信号,固定版本的上游修订与 MIT 归属均记录在 NOTICE 中。

    常见问题

    这份解码器能当作完整 DBC 解析器使用吗?

    不能。它是已批准 schema 的窄口径只读实现,只解码 9 条报文、28 个信号;未知帧按正常流程忽略,已知报文的 payload 长度不一致时返回错误。要做全量解析应使用通用 DBC 解析器,而不是这份子集。

    raw diagnostics 里的枚举值可以直接当车门或安全带状态用吗?

    不可以。素材明确要求不得自行解释 DBC 枚举的含义,也不得把这些值用于车门、安全带、空调的 canonical 状态或车辆控制。它们在 VehicleState.raw_signals 中以 MESSAGE.SIGNAL 为键只供 HMI Diagnostics 只读查看,只有空调温度给出了 raw × 0.5 + 14 的换算。

    0x541 的近光位要怎么在实车上确认?

    在停车、点火 ON 状态下,对灯光 OFF、近光 ON、AUTO 三种条件分别记录时刻与观察到的灯光状态,并核对日志 payload 第四个字节的最高位是否与判据表一致:OFF 为 0、ON 为 1、AUTO 与实际点亮状态相同。不一致则不得发布该映射,需重新核对 DBC 与车辆年款、配置。

    采集到的车辆日志可以回放到车上总线吗?

    不可以。素材规定捕获内容不向物理 can0 回发,开发环境只在 vcan0 上回放。回放前需加载 vcan 模块并创建 vcan0 接口,再用日志回放工具把 can0 映射到 vcan0。回归 fixture 中也不得保留车辆识别信息、位置与时间等敏感原始日志。

    这份 DBC 子集的权利与适配边界是什么?

    它是 opendbc 中 Hyundai CAN DBC 的只读子集,沿用上游 MIT 授权,分发时必须保留原始通知与归属声明;同时源说明要求在使用前核对车型年款、市场与配置适配性。此外该文件的 BU_ 列表缺少若干被引用的节点名,严格解析器可能需要先清理,实车验证也仍在进行中。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/oas-ai-palisade-read-only/decoder-guide.md(9 条报文解码清单、raw diagnostics 目录与 0x541 验证判据)
    • 项目 01 —— public-can-dbc-datasets/additional/oas-ai-palisade-read-only/NOTICE.md(只读子集的上游修订、MIT 归属声明与只读使用限制)
    • 项目 01 —— public-can-dbc-datasets/additional/oas-ai-palisade-read-only/SOURCE.md(9 报文/28 信号的版本固定、BU_ 缺失提示与年款适配提醒)

    免责声明

    本文所述解码器与 DBC 子集为社区逆向工程与公开派生产物,不代表车辆制造商的官方数据。素材中的使用限制已如实转述:该子集为接收专用,不引入上游车辆控制与发送代码;在按车辆年款、市场、配置用实车日志确认 frame 与 signal 之前,不得将新信号纳入 canonical 状态;分发时须保留上游 MIT 授权通知。文中所有 ID、位定义与换算均来自上述公开文件,未经独立实车验证,不同年款与市场可能存在差异,涉及安全相关用途时仅作参考。

    更新记录

    • 2026-10-14 初稿

  • 学生方程式车队的 CAN 调试工具链:10 ms–10 s 周期与 63 报文夹具

    结论:这套面向学生方程式车队的 CAN 调试工具,价值不在界面而在「逐报文可控」:发送侧支持单发与周期发送,周期可在 10 ms 到 10 s 之间逐条设定,每条报文既能单独停止也能整体停止;接收侧按 DBC 自动抽取并解释信号。但它的硬前提是 SocketCAN——必须运行在 Linux 或等效模拟器(如 WSL)上,Windows 虽有预编译包,却绕不过这一层。

    两种模式的能力边界

    工具以 Go 的 Bubble Tea 构建终端界面(TUI),核心是加载并解析 DBC 后同时管理多条报文。发送侧与接收侧的能力并不对称:发送侧提供单发与连续发送两类选项,连续发送按自定义周期运行,周期范围的默认值在源码 internal/ui/types.go 的 rangeMs 中定义,可按需修改;接收侧则由使用者挑选要监听的报文,并依据 DBC 定义自动完成信号抽取与数值解释。

    模式 能力 参数 约束
    发送 单发(single-shot) 单次触发 须先建立 SocketCAN 接口
    发送 连续发送 逐报文独立频率,范围 10 ms – 10 s 范围由 rangeMs 决定,改源码可调
    发送 停止控制 单条停止或全部停止 多条并发时逐条管理
    接收 选择性实时监听 指定要监控的报文 未选中的报文不展开
    接收 信号自动解释 依赖已加载的 DBC 定义 DBC 未覆盖的报文只能看原始字节

    平台与分发物:能装上不等于能跑通

    发布页提供四个预编译包,覆盖 Linux x86_64、macOS Intel、macOS Apple Silicon 与 Windows x86_64。但 README 在需求一节写得很直接:需要 SocketCAN 接口(vcan0 或真实 CAN 接口),因此要有 Linux 或类似 WSL 的模拟器。换句话说,Windows 包只是把二进制带过去,真正的总线层仍然要落在 Linux 内核的 SocketCAN 上。

    平台 分发文件名 说明
    Linux x86_64 can-debug_Linux_x86_64.tar.gz 解压后 chmod +x 即可运行,原生支持 SocketCAN
    macOS Intel can-debug_Darwin_x86_64.tar.gz macOS 无 SocketCAN,需借助 Linux 环境
    macOS Apple Silicon can-debug_Darwin_arm64.tar.gz 同上,总线层依赖外部 Linux 环境
    Windows x86_64 can-debug_Windows_x86_64.zip 需配合 WSL 等模拟器使用
    任意(源码构建) Go 1.19 及以上 go build -o can-debug,可按需改周期范围

    命令行只有三种形态:带接口名启动后用文件选择器挑 DBC、带接口名与 DBC 路径直接加载、以及 -h 或 --help 查看完整帮助。启动前必须先建好 can 或 vcan 网络,这是文档里反复强调的一条。

    测试夹具 MCB.dbc 的量级与证据边界

    随工具提供的样例 DBC 位于 internal/test/MCB.dbc,包含 63 条报文与 300 条信号定义,覆盖电池、显示、IMU 与牵引系统等车队自研部件节点。它足够用来验证工具本身,但不足以当作车辆信号研究成果:上游并未确立这份额外夹具对应的具体车辆、赛季、总线,也没有实车验证记录。

    文件 报文数 信号数 证据边界
    internal/test/MCB.dbc 63 300 样例测试文件,未确立车辆、赛季、总线与实车验证
    同车队另一份已归档 Main_CAN_Bus.dbc 61 293 相关车队数据,但报文与信号定义不同,不可互相替代
    归档库中的既有 DBC — — SHA-256 与已归档的 2258 份 DBC 均不匹配,属新增条目

    这张表给出一个实用的判断方法:两份报文数相近(63 与 61)、信号数只差 7 的 DBC,并不构成互为佐证的关系。源说明特别提示,不能把这份夹具当作独立的车辆信号研究来引用;仓库为 MIT 许可,但其中任何厂商部件信号的原始权利并未被独立确认。

    从 vcan 到实车接口的启动顺序

    快速路径是运行仓库内的 TestVcanSetUp.sh 脚本,一键创建 vcan 接口并启动程序,然后在另一个终端用 candump vcan0 观察程序发出的帧、用 cansend vcan0 123#DEADBEEF 向程序注入一帧;Ctrl+C 结束抓包。手动路径则依次加载 can、can-raw、vcan 模块,安装 can-utils,创建并拉起 vcan0,再用 ip a show vcan0 确认。

    接真实接口时把创建命令换成设置波特率的形式:先用 ip link set 把目标接口设为 CAN 类型并指定 bitrate,再拉起接口,然后用 ip a show 确认状态,最后以接口名(可选带 DBC 路径)启动程序。文档命令中的接口名与波特率均为占位符,需按实际硬件替换。

    常见问题

    这套工具能在 Windows 上直接连实车 CAN 吗?

    不能。README 明确要求 SocketCAN 接口(vcan0 或真实 CAN 接口),也就是需要 Linux 或类似 WSL 的模拟器。Windows 的预编译包只是可执行文件的分发形态,总线层仍需落在 Linux 环境的 SocketCAN 上。

    每条报文的发送周期能设到多少?

    连续发送支持逐报文独立设定频率,默认范围是 10 ms 到 10 s;这个范围由源码 internal/ui/types.go 中的 rangeMs 决定,需要更长或更短周期时修改该值即可。每条报文既能单独停止,也能一次性全部停止。

    随包的 MCB.dbc 能不能当作车队的正式总线定义?

    不能。它是随调试工具提供的样例测试文件,含 63 条报文、300 条信号,覆盖电池、显示、IMU 与牵引系统等节点,但上游未确立其对应的具体车辆、赛季、总线,也没有实车验证记录;同车队的另一份 Main_CAN_Bus.dbc 有 61 条报文、293 条信号,定义并不相同,两者不可互相替代。

    为什么它的 SHA-256 要单独登记?

    因为去重口径依赖哈希:这份 MCB.dbc 的 SHA-256 与已归档的 2258 份 DBC 都不相同,才被判定为新增条目。若只比对文件名或报文数,很容易把 63 条报文的夹具与 61 条报文的同车队文件误判为同一份。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/squadracorsepolito-can-debug/README.md(TUI 能力、发送/接收模式、平台分发物与 vcan/实车接口启动步骤)
    • 项目 01 —— public-can-dbc-datasets/additional/squadracorsepolito-can-debug/SOURCE.md(MCB.dbc 的 63 报文/300 信号、哈希登记与证据边界)

    免责声明

    本文所述内容来自公开开源仓库的说明文件,涉及的报文与信号数量仅为该测试夹具自身的规模,不代表具体车辆、赛季或总线的定义,也未经实车验证。仓库为 MIT 许可,但夹具中任何厂商部件信号的原始权利并未被独立确认。发送类工具一旦接入真实总线即具备主动写入能力,请在隔离环境或虚拟总线上完成验证,并遵守所在赛事与场地的安全规定。

    更新记录

    • 2026-10-14 初稿

  • TrevCAN 树莓派节点:347 条报文定义与 460 种载荷布局

    结论:TrevCAN 的树莓派节点是一个纯发送端:它只读 SocketCAN 原始帧,按 100 ms、最多 500 帧一批推给服务端的 /ingest/can,本身不做任何 DBC 解码,也从不向物理总线发帧。它的仿真模式覆盖 7 份 DBC 里的全部 347 条报文定义、共 460 种载荷布局,但生成的是合成覆盖数据,不是物理自洽的车辆模型。

    车端与服务端的职责切分

    这个项目的设计取舍非常明确:车上那台树莓派上不需要 TREVCAN-Explorer 检出目录里的任何文件。DBC 解码、InfluxDB 写入与前端全部跑在车下的服务器上。车端只剩一个瘦发送器,负责把 SocketCAN 上收到的原始帧打包送走。

    这样切分带来两个直接后果。好处是车端依赖少、故障面小,换 DBC 不必动车上的部署;代价是车端无法做本地语义判断——它不知道自己送走的是电池单压还是转向角,任何与信号含义相关的逻辑都必须放到服务端。

    环节 运行位置 职责 是否接触总线
    SocketCAN 帧读取 树莓派 从 can0 读取原始帧 只收不发
    批处理与 HTTP 上报 树莓派 按 100 ms、最多 500 帧一批推到 /ingest/can 否
    DBC 解码 车下服务器 用已启用且已排序的 DBC 解码收到的帧 否
    InfluxDB 与前端 车下服务器 落库与展示 否

    启动前必须先做的一件事

    按车辆实际波特率配置并拉起 can0,再启动发送器。这一步在文档里被放在显眼位置,而且与另一条约束互为补充:发送器只接收 CAN 流量,不会向物理总线发送。也就是说它天然是只听(listen-only)的,不可能因为软件缺陷把帧打进整车网络——前提是 can0 本身配置正确。

    如果车上用的不是原生 SocketCAN 设备,可用 --interface 与 --channel 选择其它 python-can 接口,无需改动代码。

    仿真模式:347 条报文与 460 种布局

    带 --simulate-rate 启动时,程序不会打开任何 CAN 接口,也绝不在物理总线上发送。它用 cantools 把 trevcan_pi/dbcs/ 里 7 份当前 DBC 的定义编码成原始帧,全部 347 条报文定义都会被覆盖,包括每一个多路复用分支——完整一轮是 460 种载荷布局。

    460 对 347 这个差值本身就是信息:平均每 3 条报文里就有 1 条带多路复用,多出来的 113 种布局全部来自复用分支。如果解码端只按报文 ID 取第一个布局,这部分帧一定会被解错。

    参数 取值 含义
    覆盖报文定义 347 7 份 DBC 的全部报文定义
    每轮载荷布局 460 含每个多路复用分支
    速率语义 总帧率 --simulate-rate 是每秒总帧数,不是每条报文的帧率
    20 Hz 一轮耗时 约 23 秒 460 帧除以 20
    460 Hz 一轮耗时 约 1 秒 不含处理开销

    数值在后续轮次中会变化,但始终落在每个信号在 DBC 内可表示的上下限之内;枚举值则在已定义的值之间轮转。命令与配置类报文只作为网络遥测计入,不代表车辆真的执行了这些命令。

    交付语义:批处理、队列与不保证送达

    这一段是整个项目里最需要在使用前读明白的部分。它把「尽力而为」写得很具体,而不是含糊带过。

    机制 取值 溢出或失败时的行为
    批处理窗口 100 ms 窗口内最多打包 500 帧
    队列容量 10,000 帧 溢出时丢弃最旧的帧,并在日志中计数
    HTTP 批次失败 不重放 失败或不确定的批次不做重放
    中断恢复 自动恢复传输 但中断期间无磁盘积压,也无送达保证
    停止方式 SIGTERM 与 Ctrl-C 未发送的帧可能被丢弃

    把这些数字连起来看,缓冲深度是可以估出来的:批处理窗口为 100 ms、每批上限 500 帧,对应每秒 5000 帧的处理上限;队列 10,000 帧约等于 2 秒的缓冲。总线负载一旦持续超过这个量级,丢的就是最老的数据,而不是最新的——对事后分析来说这个取舍需要提前想清楚。

    安全侧也有明确要求:共享令牌和数据必须用私有网络、VPN 或 HTTPS 保护;INFLUXDB_TOKEN 只留在服务端,不上车。

    开机自启与仿真切换

    车上部署的关键不是写服务文件,而是把秘密与路径分开管理:服务文件里只留用户名与检出路径,令牌与服务端地址放进单独的 env 文件并收紧权限。这样既避免了令牌进版本库,也让同一份服务定义能在不同车上复用。

    步骤 操作 要点
    改服务文件 编辑 systemd/trevcan-pi.service,填入自己的用户名与检出路径 服务文件本身不含令牌
    写环境变量 在 /etc/trevcan-pi.env 写入 CAN_INGEST_TOKEN 与 TREVCAN_SERVER 地址形如 http 加主机名再加 8000 端口
    收紧权限 sudo chmod 600 /etc/trevcan-pi.env 仅 root 可读
    安装并启动 复制到 /etc/systemd/system/,执行 daemon-reload 与 systemctl enable --now trevcan-pi --now 同时完成开机自启与立即启动
    看日志 sudo journalctl -u trevcan-pi -f 队列溢出计数也在这里
    切换仿真 把 ExecStart 里的 --channel can0 换成 --simulate-rate 20 迁移时须先停掉并禁用旧的全栈服务

    两点值得单独记:CAN 接口的配置由系统单独管理,不由这个服务负责;测试用 python -m unittest discover -s tests 即可跑完,测试用 cantools 对每条报文与每个复用布局做编解码往返、校验信号覆盖与取值边界,并 mock HTTP 上报,不需要硬件、InfluxDB 或网络监听。

    归档取舍:保留 2 份、剔除 5 份

    归档最终只保留了两份字节互异的 BMS 与 DAQ 固件 DBC 快照,合计 277 行 BO_ 报文定义与 1,373 行 SG_ 信号定义。其余五份各有各的去向,理由不完全相同。

    文件 处置 理由
    trevcan_pi/dbcs/BMS-Firmware-RTOS-Complete.dbc 保留 与已有归档无重复;Git blob 94d4168a43352804615ae7659ac04475d09c43a8
    trevcan_pi/dbcs/DAQ-Firmware.dbc 保留 与已有归档无重复;Git blob 45ee363c49bdeeea30d0824bc0243529e118bf99
    Baby_MOBO.dbc 剔除 CRLF 归一化后与同批次已有归档中的文件完全相同
    VCU.dbc 剔除 CRLF 归一化后与同批次已有归档中的文件完全相同
    can9-database-01.09.dbc 剔除 CRLF 归一化后与同批次已有归档中的文件完全相同
    Inverter.dbc、hvc.dbc 剔除 已与同批次已有归档中的文件字节完全相同
    examples/simulation.dbc 说明为合成示例 仅用于演示的最小样例

    需要注意:这里被剔除的文件只是不重复归档,不代表它们在工程上被弃用。仿真模式仍然按 7 份当前 DBC 覆盖 347 条报文定义。

    两个 ID 撞车:0xC0

    文档点出了一个原始 CAN 的结构性限制:逆变器的 Command_Message 与 VCU 的 VCU_INV_Command 共用标准 ID 0xC0。两份定义都会被仿真并打印告警,但服务端解码时用的是第一个匹配的已启用 DBC,无法按 ID 区分这两条定义。后果很直接:同一 ID 的帧解出来是命令还是状态,取决于你在服务端启用了哪份 DBC、以及它的排序。测试某个仪表盘前,必须确认启用并排好的是目标那份。

    常见问题

    这个树莓派节点会往车上发 CAN 帧吗?

    不会。文档写明发送器只接收 CAN 流量,不向物理总线发送;仿真模式下更是完全不打开 CAN 接口、绝不在物理总线上发送。启动前还需按车辆实际波特率配置并拉起 can0,配置正确时它对整车网络是只听的。

    仿真生成的 460 种布局能当真实车辆数据用吗?

    不能。它覆盖 7 份 DBC 中全部 347 条报文定义、含每个多路复用分支共 460 种布局,但数值只是在 DBC 可表示范围内变化、枚举按定义值轮转,属合成覆盖数据而非物理自洽的车辆模型。命令与配置类报文也仅作为网络遥测计入。

    为什么 0xC0 这个 ID 会解出两种含义?

    因为原始 CAN 不携带 DBC 身份。逆变器的 Command_Message 与 VCU 的 VCU_INV_Command 共用标准 ID 0xC0,服务端按第一个匹配的已启用 DBC 解码,无法靠 ID 区分。因此要在服务端启用并排好你实际要测的那份 DBC,否则解出来的是另一条定义。

    断网期间采集到的报文会补传吗?

    不会。批处理最多 500 帧、窗口 100 ms;队列容量 10,000 帧,溢出时丢弃最旧帧并在日志计数;失败或不确定的 HTTP 批次不重放。传输会自动恢复,但中断期间没有磁盘积压,也不保证送达;SIGTERM 或 Ctrl-C 停止时未发送的帧同样可能被丢弃。

    归档只留了两份 DBC,其余五份为什么没有?

    原因分两类:Baby_MOBO.dbc、VCU.dbc 与 can9-database-01.09.dbc 在 CRLF 归一化后与同批次已有归档中的文件完全相同;Inverter.dbc 与 hvc.dbc 则已字节完全相同;examples/simulation.dbc 是合成示例。剔除只是避免重复归档,不代表这些文件在工程上被弃用。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/elidresnin-trevcan-pi/UPSTREAM_README.md(纯发送端定位与车端不依赖 Explorer 检出文件、venv 与 requirements 安装流程、CAN_INGEST_TOKEN 与 –server 参数、can0 需按车辆波特率预配置、只收不发、–interface 与 –channel、–simulate-rate 的总帧率语义、347 条报文定义与 460 种布局、0xC0 ID 冲突与服务端按首个匹配 DBC 解码、–dbc 顶层目录扫描规则、systemd 开机自启与 /etc/trevcan-pi.env、500 帧 / 100 ms 批处理与 10,000 帧队列及不保证送达、unittest 测试范围)
    • 项目 01 —— public-can-dbc-datasets/additional/elidresnin-trevcan-pi/SOURCE.md(保留两份 BMS 与 DAQ 固件 DBC 快照、277 行 BO_ 与 1,373 行 SG_ 合计、快照修订 684065b99b79ae2748fe061ccd70aaabf2f94337 与采集日期 2026-10-04、三份文件因 CRLF 归一化重复被剔除、两份已字节相同、examples/simulation.dbc 为合成示例、两份文件各自的 Git blob 与 SHA-256、未找到仓库许可证与原始组件归属故仅作私有离线研究副本)

    免责声明

    本文所述批处理参数、队列容量、报文与布局数量、命令与路径均来自公开开源仓库的说明文档,属第三方工程产物,未经独立实车核验。归档方已声明仿真数据为合成覆盖数据而非物理自洽的车辆模型,硬件适配与信号正确性未经检查,且该快照未找到仓库许可证与原始组件归属,仅应作为私有离线研究副本保留。涉及安全相关用途时请以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • 标致 207 仪表 IPC:4 根线与一份种子 DBC

    结论:这份 Peugeot 207 IPC 资料的价值不在信号清单,而在可复现的最小实验台:一块 STM32G431KB 板、一只零件号 A2C53065549 的仪表、4 根线(14 脚 CAN_H、15 脚 CAN_L、16 脚 12 V、18 脚 GND)即可把收发、抓包、写 DBC 串起来。需要提前说清的是,README 本身没有列出任何 CAN ID 或位定义,逐信号内容只存在于仓库里的 peugeot_207.dbc 种子文件。

    硬件构成与引脚定义

    仪表端只需要接 4 个脚。CAN_H 与 CAN_L 在第 14、15 脚,供电在第 16 脚、接地在第 18 脚。这个排列意味着改制时不需要拆开整个连接器去猜线序,也给实验台留出了一致的接线基准。

    供电这一项有个有用的细节:第 16 脚标称 12 V,但文档注明「works with 9 V」,即 9 V 下也能工作。对台架供电来说这拓宽了电源选择,但同时也意味着在整车电压偏低时仪表未必会立刻掉线,排查供电问题不能只看仪表是否点亮。

    引脚 信号 / 电源 接线要点
    14 CAN_H 与 CAN_L 构成差分对,不可单独引出长线
    15 CAN_L 同上
    16 12 V(9 V 亦可工作) 标称 12 V,实测下限可到 9 V
    18 GND 与收发器、MCU 共地

    拆开仪表可以看到里面的 CAN 收发器是 TJA1054AT,厂商标注为 Philips / NXP,状态为 End of life。同系列里状态为 Active 的是 TJA1055,被描述为 enhanced fault-tolerant CAN transceiver。对台架来说这不是致命问题,但对要长期供货的项目,选型阶段就要考虑换代。

    器件 角色 厂商标注状态
    TJA1054AT(仪表内置) Fault-tolerant CAN transceiver End of life
    TJA1055(换代参考) Enhanced fault-tolerant CAN transceiver Active
    STM32G431KB(MCU 侧) 演示用主控,配合 ST HAL 使用 未标注状态

    为什么偏偏是这只 IPC

    作者在选型理由里把「可获得性」放在了首位,这和多数逆向项目按技术参数选件的思路不同,也更贴近教学场景的实际约束。

    维度 本资料所用变体 Peugeot 207 其他版本 IPC
    零件号 A2C53065549 未给出具体零件号
    显示特征 带挡位模式显示与机油温度表 配置各异
    市场存量 不常见,较难买到 保有量大
    价格 可能偏高 部分低于 10 EUR
    教学可用性 信号更丰富,适合演示 适合批量采购做实验台

    支撑这个选择的是保有量:2007 到 2010 年仅欧洲就售出接近 150 万台 207。庞大的存量意味着二手件价格低、容错空间大——学生焊坏了不心疼,这是实验台能持续运转的前提。

    对教学场景而言,带挡位模式显示与机油温度表这件事本身是有意义的:它比纯转速/车速表多出两类语义不同的信号,一类是离散枚举(挡位模式),一类是连续测量量(油温)。学生在同一块仪表上就能遇到两种完全不同的解码思路,而不必为了示范枚举再去接第二个节点。

    从收发到写 DBC:一条完整的教学路径

    这个仓库定位是 barebone demo,重点不是把仪表功能做全,而是把四件事串成一条可走的路线:发送与接收报文、嗅探总线、创建 DBC 文件,以及由此入门汽车逆向工程。

    工具链的选择也体现了递进关系:先用 Arduino IDE 加 ESP32-S3 入门,再用这个仓库演示 ST 的 HAL 同样易用,下一步是 STM32CubeIDE 与 CCStudio IDE。对已经熟悉 Arduino 生态的人来说,这条路径把「换到 ST 平台」的心理门槛拆成了两步。

    类别 资料 / 工具 在教学链中的作用
    入门硬件 Arduino IDE + ESP32-S3 进入嵌入式世界的第一步
    主控演示 STM32G431KB + ST HAL 证明 ST 的 HAL 同样易用
    后续 IDE STM32CubeIDE、CCStudio IDE 下一步工具环境
    DBC 编辑 SavvyCAN(含 DBC 文件编辑器) 编写与调试 DBC
    参考资料 CSS Electronics DBC 入门与在线编辑器、Kvaser J1939 与 DBC 介绍、Social Ledge DBC Format 理解 DBC 语法与字段含义
    总线工具 Vector CANdb++、Makerbase CANable 2.0、PEAK-System PCAN-USB 与 PCAN-USB FD 专业级网络定义与 USB 转 CAN 适配
    体系资料 PSA CAN bus PSA 平台总线背景

    DBC 种子文件的位置与作用

    仓库在 /Assets/DBC/peugeot_207.dbc 提供了一份示例种子文件,配套的截图展示了它在 SavvyCAN 中加载与编辑的效果。也就是说,CAN ID 与位定义的实际内容在 .dbc 文件里,README 只负责指向它并给出工具与流程。若要做逐字节比对,应以这份种子文件和自己的抓包结果为准。

    四步路径:从收发报文到写出 DBC

    这个仓库的主线不是把仪表驱动做完整,而是让初学者在最短路径上走完一次完整的「看—抓—猜—记」循环。四个环节依次推进,每一步都有可验证的产出,不容易在中间卡死。

    步骤 动作 可验证的产出
    1 发送与接收报文 仪表指针或显示有响应,证明物理层与波特率正确
    2 嗅探总线 抓到一组稳定的 ID 与周期,得到候选报文清单
    3 创建 DBC 文件 把候选 ID 与位段写成可加载的定义,在工具里能解出数值
    4 进入汽车逆向工程 用改动反推含义,形成可复核的信号假设

    这套顺序的关键在于第一步必须先成立。如果波特率或接线不对,后面抓到的只是一堆噪声,很容易让人误判为「协议加密」而放弃。因此台架阶段应优先确认第 16 脚供电正常、第 14 与 15 脚差分连接无误、第 18 脚与 MCU 共地。

    工程文件缺失时的重建方式

    仓库没有随附 /Drivers/ 下的两个目录。文档给出的重建办法是:登录 MyST,按 Alt-K 依据 .ioc 文件生成 /Drivers/CMCIS/ 与 /Drivers/STM32G4xx_HAL_Driver/,几秒后工程即可编译。

    这个约定的意义在于把「生成物」与「源文件」分开:.ioc 是引脚与外设配置的唯一真源,Drivers 目录是可再生的产物。好处是仓库体积小、不会因 HAL 版本漂移而失配;代价是新环境必须先有能生成代码的 IDE,否则工程无法直接构建。对新接手的人来说,第一条要做的不是找缺失文件,而是确认自己有可用的生成工具。

    常见问题

    这份资料里有 Peugeot 207 的完整 CAN ID 与位定义吗?

    README 里没有。文档只给出引脚定义、内置收发器型号与工具链,逐报文、逐信号的内容在仓库的 /Assets/DBC/peugeot_207.dbc 种子文件中,README 仅指向它并展示在 SavvyCAN 中加载与编辑的效果。要做逐字节比对,请以该种子文件与自己的抓包结果为准。

    仪表第 16 脚能不能用 9 V 供电?

    可以。引脚表把第 16 脚标注为 12 V,并注明 9 V 也能工作。这对台架供电是便利,但也意味着整车电压跌到 9 V 时仪表可能仍然正常显示,排查供电故障时不能把「仪表还亮着」当作电压正常的证据。

    为什么资料特别提到 TJA1054AT 已停产?

    因为它是仪表内置的容错 CAN 收发器,厂商(Philips / NXP)标注状态为 End of life,且文档同时给出状态为 Active 的增强型容错收发器 TJA1055 作为换代参考。对教学台架影响不大,但对需要长期供货或做量产适配的项目,选型阶段就应把换代考虑进去。

    仓库缺少 Drivers 目录时该怎么办?

    不需要另外找文件。登录 MyST 后按 Alt-K,依据工程里的 .ioc 文件即可生成 /Drivers/CMCIS/ 与 /Drivers/STM32G4xx_HAL_Driver/,几秒后工程就能构建。这背后的约定是 .ioc 为配置真源、Drivers 为可再生产物,因此新环境必须备有可生成代码的 IDE。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/peugeot-207-ipc/README.md(STM32G431KB barebone demo 定位与零件号 A2C53065549、仪表变体差异与 2007 至 2010 年欧洲近 150 万台的保有量、14/15/16/18 脚的 CAN_H、CAN_L、12 V 与 GND 定义及 9 V 可用、内置 TJA1054AT 容错收发器的 End of life 状态与 TJA1055 换代参考、收发与嗅探及编写 DBC 的教学路径、Arduino IDE 加 ESP32-S3 到 ST HAL 再到 STM32CubeIDE 与 CCStudio 的工具链递进、/Assets/DBC/peugeot_207.dbc 种子文件位置、Drivers 目录缺失时通过 MyST 与 Alt-K 依据 .ioc 重新生成的方式、DBC 工具与 PSA 总线资料清单)

    免责声明

    本文所述引脚定义、器件型号与状态、零件号、工具链与工程约定均来自公开开源仓库的说明文档,属第三方教学与逆向工程产物,未经独立实车核验,也不代表车辆制造商的官方数据。不同车型年款、市场与 ECU 版本可能存在差异,文中未涉及具体 CAN ID 与位定义,相关内容请以仓库内种子文件与实际抓包为准。涉及安全相关用途时请仅作参考。

    更新记录

    • 2026-10-14 初稿

  • Daybreak 与 HighNoon:105 条报文与 493 条信号

    结论:太阳能车队两代车的 CAN 定义是 7 份按功能域切开的 DBC,而非一份整车文件。Daybreak 三份合计 23 条报文、58 条信号,HighNoon 四份合计 82 条报文、435 条信号。决定复用方式的不是总量,而是信号密度:bps.dbc 平均每条报文只挂 1.47 条信号,LightingCAN.dbc 则高达 9.50 条。

    七份 DBC 的目录划分与规模落差

    归档保留了 7 份字节互不相同的 DBC,分别位于上游 can/dbc/Daybreak/ 与 can/dbc/HighNoon/ 两个目录,并随附上游 docs/README.md 与顶层 MIT LICENSE。目录结构本身就是第一条信息:两代车并不共用一份网络定义,而是各自维护一整套,跨代之间没有版本继承关系。

    按单文件看落差极大。最小的两份是 Daybreak/contactor.dbc 与 HighNoon/SteeringCAN.dbc,各只有 2 条报文;最大的 HighNoon/CarCAN.dbc 有 55 条报文、305 条信号,单份就占全部 105 条报文的一半以上、全部 493 条信号的 61.9%。把它当「车队 CAN 数据集」整体引用会严重失真——重心几乎全在一份文件上。

    文件 所属代次 报文数 信号数 平均信号 / 报文
    can/dbc/Daybreak/bps.dbc Daybreak 15 22 1.47
    can/dbc/Daybreak/contactor.dbc Daybreak 2 11 5.50
    can/dbc/Daybreak/controls.dbc Daybreak 6 25 4.17
    can/dbc/HighNoon/CarCAN.dbc HighNoon 55 305 5.55
    can/dbc/HighNoon/BPSCAN.dbc HighNoon 19 63 3.32
    can/dbc/HighNoon/LightingCAN.dbc HighNoon 6 57 9.50
    can/dbc/HighNoon/SteeringCAN.dbc HighNoon 2 10 5.00

    两代车的量级对比

    Daybreak 侧三份共 23 条报文、58 条信号;HighNoon 侧四份共 82 条报文、435 条信号。后者的报文数约为前者的 3.6 倍,信号数约为 7.5 倍。也就是说,代次更替不只是加了几个节点,而是单位报文承载的信号量整体翻了一倍(2.52 对 5.30)。

    代次 保留文件数 报文合计 信号合计 功能域
    Daybreak 3 23 58 电池包(BPS)、接触器、整车控制
    HighNoon 4 82 435 整车(CarCAN)、电池(BPSCAN)、灯光、转向
    合计 7 105 493 七份文件,互不覆盖

    信号密度决定了每份 DBC 的读法

    把信号数除以报文数得到的密度,是这几份文件里最实用的判据。它不需要打开文件就能告诉你:这份定义主要承载的是离散状态位,还是打包好的连续测量量。密度小于 2 的文件基本是「一条报文一个状态」,读数容易但信息量有限;密度大于 9 的文件则几乎必然是位域打包,必须逐位拆解才能用。

    密度档位 平均信号 / 报文 落在档位内的文件 典型形态 使用建议
    稀疏(小于 2) 1.47 Daybreak/bps.dbc 单条报文只承载少量状态或告警位 逐位确认含义,不宜当作连续测量量使用
    中等(3 到 6) 3.32、4.17、5.00、5.50、5.55 HighNoon/BPSCAN.dbc、Daybreak/controls.dbc、HighNoon/SteeringCAN.dbc、Daybreak/contactor.dbc、HighNoon/CarCAN.dbc 状态位与测量量混合 先抓运行日志看取值分布,再定缩放与偏移
    密集(大于 9) 9.50 HighNoon/LightingCAN.dbc 位域打包大量开关与枚举 按位拆解,逐位与实车现象对齐

    需要强调一点:密度是归档方统计出的 BO_ 与 SG_ 行数之比,它反映的是文件的组织方式,不代表信号已被验证。归档说明写得很清楚——具体车辆修订版本、组件固件与信号准确性均未独立核验。

    另一个不该忽略的落差在命名口径上。Daybreak 这一侧按功能块命名(bps、contactor、controls),HighNoon 这一侧则按物理总线命名(CarCAN、BPSCAN、LightingCAN、SteeringCAN)。两套口径不同,意味着不能靠文件名去推断两代车信号的对应关系,跨代比对只能落到逐信号的位与缩放上。

    被拦下的文件与权利边界

    这一批有五类文件没有进入归档,理由分两种,处理方式也不同。区分清楚很重要,因为「内容为空」与「权利未定」在工程上的后果完全不一样:前者是这份定义本来就没有可用信息,后者是信息可能存在但你不能用。

    对象 拦下理由 性质 处理动作
    HighNoon/DAqCAN.dbc 不含任何报文与信号定义 内容为空 不收录
    Prohelion 组件文件 待原始厂商数据权利审查 权利未定 暂缓收录
    TPEE MPPT 组件文件 待原始厂商数据权利审查 权利未定 暂缓收录
    Elcon 组件文件 待原始厂商数据权利审查 权利未定 暂缓收录
    电机控制器组件文件 待原始厂商数据权利审查 权利未定 暂缓收录

    DAqCAN.dbc 值得单独记录:DAQ 这样的名字很容易让人以为它提供采集通道的完整定义,实际上归档时它是空文件。此外,保留下来的 CarCAN.dbc 是一份聚合文件,其中引用了 BPS、MPPT 等组件的信号,但这些信号的原始来源并未独立确认。

    校验值与去重:怎样确认拿到的是同一份文件

    归档为每份 DBC 都登记了 Git blob 与 SHA-256,快照修订为 04d2b3286f50d8f4119d4dc11b7344140f449d15。两者用途不同:Git blob 用于在仓库内部定位文件版本,SHA-256 用于在仓库之外确认取到的字节是否一致。做二次分发或长期存档时,两个值都该留。

    文件 Git blob SHA-256
    Daybreak/bps.dbc 27f2385d0e3d316841e73db2b51631cdaad25637 b84a9d61eb276587241b39d24792c6cb1c42eb3b6efaad3ecfa727d279f8de32
    Daybreak/contactor.dbc 11745daca9b071eb933a59471ed630c79510eaaf 58ae79db80cb0d20e3dd2b585231b72f8a50bf41800fdd0d0f1878200a134672
    Daybreak/controls.dbc db2678346ce5e7ded982f56ecfa1971a87cfc96d 5484aa7a1ea8e4cc3925d5e714d5f37e58bd022569a4a106fa28ce5d1e06ae32
    HighNoon/CarCAN.dbc 175bc244c2a250857d393a27db6ffff1451bb906 fdd068b71ee3c891e3733d716c8ab4b8df211187892f5ed351dfe4f6f3076fbd
    HighNoon/BPSCAN.dbc 56048d7c6f5d0fad5c655be31f00af5516717a6c 4619aa34e75767a5e05557fa092fa883f90045147cb5e875ac352e7d9f95031f
    HighNoon/LightingCAN.dbc bcae89e10bf3dcb9088465061ceaf4eefcfac5de 0a5fdefcc7f4bdbe5fa23161b544561704600e0fb7675360551381872d2d06ed
    HighNoon/SteeringCAN.dbc a6548a3e1ea4e5ba12af333e622be03efd10f121 64e87d4458729fed6b3d9e8866e26d95d20d113be29dc117fe57fd449e37f6cb

    比对时还有一个容易踩的坑:同一份逻辑文件在不同检出环境下可能呈现 CRLF 与 LF 两种字节序,直接按字节比较会把同一份文件误判成两份。归档方在其他项目上正是用 CRLF 归一化来识别重复的,这里同样应当先归一化再比对。

    工程侧:MCU 端口移植的四项硬要求

    随附的上游文档描述的是一套面向定制 STM32 PCB 的共享嵌入式代码仓库,本身不是 CAN 数据集。它与 DBC 的关联在于:DBC 里定义的报文最终由这些 MCU 上的固件收发,端口是否移植完整,直接决定某条报文在车上有没有对应的实现。

    顶层 Makefile 编译 STM32 所需的全部文件,但设计上不打算被直接调用,而应由另一个 Makefile 调用。测试统一放在 test/ 目录,测试文件以 _test.c 结尾,命令形如 make TEST=blinky PROJECT_TARGET=stm32g473xx,烧录用 make flash。CI 侧提供 makeAllTests.py,支持 -v、-t TESTS、-p PORTS、-h 四个选项,默认对所有端口编译全部测试。

    一个合法端口必须齐备的四样东西

    要素 命名规则 文档给出的示例
    端口目录 位于 stm/stm32f4xx、stm/stm32l4xx 或 stm/stm32g4xx 之下,用 MCU 通用名命名 stm32f413、stm32l431
    链接脚本 形如 STM32*_FLASH.ld,须包含处理器全名 STM32F413RHTx_FLASH.ld、STM32L431CBTx_FLASH.ld
    启动汇编 startup_stm32 加四位系列与线别再加 xx,含向量表与基础异常处理(最关键的是 Reset_Handler) startup_stm32f413xx.s
    配置文件 以精确 MCU 名命名,空格分隔列出要禁用的 BSP 模块 stm32l432kcu.cfg,内容 BSP_DISABLE=CAN UART ADC

    文档特别提醒:请核对 MCU 上实际存在的外设再填写 BSP_DISABLE,否则会遇到奇怪的构建错误。对 CAN 相关项目来说这条尤其重要——如果误把 CAN 写进禁用列表,DBC 里定义得再完整,固件侧也发不出对应的帧。

    常见问题

    两代车的 DBC 能不能按文件名直接对齐?

    不能。Daybreak 侧的命名偏功能块(bps、contactor、controls),HighNoon 侧则偏物理总线(CarCAN、BPSCAN、LightingCAN、SteeringCAN),两套命名口径不同。加上 CarCAN.dbc 是聚合文件,其中引用的 BPS、MPPT 等组件信号的原始来源并未独立确认,跨代只能逐信号比对位与缩放,不能靠文件名推导。

    为什么 bps.dbc 有 15 条报文却只有 22 条信号?

    它平均每条报文只挂 1.47 条信号,是 7 份文件里最稀疏的一份。这种密度通常意味着报文主要承载状态或告警位,而不是连续测量量。在拿它做趋势分析之前,需要逐条确认每个位的含义与有效性,不能假定它自带完整的物理量定义。

    DAqCAN.dbc 与四类组件文件为什么没被收录?

    理由不同。DAqCAN.dbc 在归档时不含任何报文与信号定义,属于内容为空,因此不收录;Prohelion、TPEE MPPT、Elcon 与电机控制器这四类组件文件,则是因为原始厂商数据权利尚待审查而暂缓收录,属于权利未定。前者没有可用信息,后者可能有但你不能用。

    CarCAN.dbc 有 305 条信号,能当作整车信号全集吗?

    不能。归档说明指出它是聚合文件,引用了 BPS、MPPT 等组件的信号,而这些信号的原始来源未经独立确认;同时归档方明确写明,车辆修订版本、组件固件与信号准确性均未核验。它适合作为总线结构的索引,不能直接当作已验证的信号全集使用。

    这些 DBC 对应的 MCU 端口移植要准备什么?

    四样东西:一是在 stm/stm32f4xx、stm/stm32l4xx 或 stm/stm32g4xx 下以 MCU 通用名建立端口目录;二是形如 STM32*_FLASH.ld 且含处理器全名的链接脚本;三是 startup_stm32 加四位系列名加 xx 的启动汇编,内含向量表与 Reset_Handler;四是以精确 MCU 名命名的配置文件,用空格分隔列出要禁用的 BSP 模块,例如 BSP_DISABLE=CAN UART ADC。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/lhr-solar-daybreak-highnoon/SOURCE.md(7 份字节互异 DBC 的目录归属、逐文件报文与信号数、各文件 Git blob 与 SHA-256、DAqCAN.dbc 为空故不收录、四类组件文件待厂商数据权利审查、CarCAN.dbc 为聚合文件且信号来源未独立确认、车辆修订与固件未核验的说明)
    • 项目 01 —— public-can-dbc-datasets/additional/lhr-solar-daybreak-highnoon/README.md(顶层 Makefile 需由另一 Makefile 调用、test 目录与 _test.c 命名约定、make TEST 与 PROJECT_TARGET 用法、make flash、makeAllTests.py 的四个 CI 选项、STM32 端口四要素与 BSP_DISABLE 配置格式)

    免责声明

    本文所述报文数、信号数与文件路径均来自公开开源仓库的说明文档,属第三方逆向工程与团队自建产物,未经独立实车核验,也不代表车辆制造商的官方数据。不同车辆修订版本、组件固件与市场可能存在差异。涉及安全相关用途时请仅作参考,并以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • MARV 无人车的 CAN 集成层:35 报文与 115 信号

    结论:MARV 无人车的 CAN 集成层只有一份 marv.dbc,规模是 35 条 BO_ 报文、115 行 SG_ 信号,平均每条报文 3.29 条信号。它落在 marv_driver 包的 resource/ 目录里,与自定义消息包、场景包、惯导驱动并列。真正限制复用的是三处未核验:平台硬件、DBC 信号校验、以及它并非量产车型定义。

    集成层的落点:一份 DBC 与四个 ROS 包

    归档只保留了一个文件:colcon_ws/src/marv_driver/resource/marv.dbc。把它放在 driver 包的 resource/ 下,说明这个项目把报文定义当作驱动的一部分来管理,而不是外部配置文件。这个位置决定了 DBC 的更新节奏与驱动代码同步,改信号定义等于改驱动包。

    同一工作空间里并列着四个包。理解它们的分工,才能判断一条 CAN 信号从总线到控制回路之间要穿过几层。

    包 上游说明 在集成链中的位置
    marv_driver Basic system functions 归档的 marv.dbc 位于该包 resource/ 目录,是报文定义的落点
    marv_msgs Custom messages package 自定义消息类型定义,说明文档未给出消息清单
    marv_scenarios 用户实现的场景,例如 waypoint_navigation 场景层,说明文档仅举了航点导航一例
    sbg_ros2 The SBG INS driver 惯性导航数据源,与总线信号并行

    规模与统计口径

    35 条报文与 115 行信号是归档方统计 BO_ 与 SG_ 行数得出的。这个口径只说明文件里定义了多少条报文、多少行信号,不代表每一条都已被实车验证。作为对照,同为车队级归档的水冷式方程式项目通常在 50 到 115 条报文的量级,MARV 属于偏小的一侧。

    指标 数值 口径说明
    报文定义(BO_) 35 按 BO_ 行数统计
    信号定义(SG_) 115 按 SG_ 行数统计
    平均信号 / 报文 3.29 由上述两项相除得出
    归档文件数 1 marv_driver/resource/marv.dbc

    归档说明还给出了该文件的完整性校验值:Git blob 182c2fb5f6c02d8ef26c26b2adaa564174f1c2f1,SHA-256 4aab0907c9c43435b11c8729c725c092f98667deb868cc7c6356ed5eb8f3dddc,快照修订为 5b7ed5f6a5547a63407562572b31243f9c5a35a7,采集日期 2026-10-04。

    构建、运行与开机自启

    构建链路相当固定:先在 REACH 车载计算机上按「reach setup」文档装齐依赖,再 source ROS 2 galactic,最后在 colcon_ws 目录内执行 colcon build --symlink-install。这里没有给出依赖清单,意味着环境不可复现——换一台机器时,第一步的「装齐依赖」只能靠文档之外的信息完成。

    运行方式有三套,分别对应调试、常规与部署。测试用途下 ./marv_start.sh 会启动一个 screen 终端会话,适合现场看输出;常规使用则依赖服务在开机时自动拉起,需要人工干预时另有 ./marv_restart、./marv_stop、./marv_start 三个脚本。

    场景 命令 说明
    测试用途 ./marv_start.sh 启动一个 screen 终端会话,便于直接观察节点输出
    常规使用 开机自动启动;./marv_restart、./marv_stop、./marv_start 需先在 reach setup 文档中完成服务配置
    服务管理 sudo systemctl enable marv_package、start、stop、systemctl status marv_package enable 用于开机自启,start 与 stop 用于手动控制,status 查状态
    会话清理 screen -r 重新接入;killall screen 接入后用 ctrl + C、ctrl + D 逐个关闭终端

    读这份文档时有一处需要自己纠正:上游把「禁用服务」的命令也写成了 sudo systemctl enable marv_package,与启用命令完全相同。按字面执行达不到禁用效果,正确做法应是对应的 disable。这类笔误在自维护文档里很常见,抄命令之前先确认语义,不要照单全收。

    日志与仿真这两套机制合起来,覆盖了从录制到回放再到脚本自检的完整链路,但它们的边界都写在文档里而没有含糊处理。使用时最容易犯的错误是把「跑通了」当成「跑对了」。

    两套 rosbag 与 scenario_starter 的仿真边界

    日志侧提供两套 rosbag:一套记录全部 topic,另一套只记录指定 topic(如导航数据),具体 topic 可在 start_specific_ros_bah.sh 脚本中修改。这种「全量 + 定向」的双轨设计很实用——全量用于事后回溯,定向用于长时间跑车时控制数据量。

    仿真侧则由 scenario_starter 这个额外的 ROS 节点承担,用来模拟 MARV 系统其余部分的行为。它模拟 12V Auto 状态,以及 OCU 发出的 start scenario 命令。文档对它的边界写得很克制:它不模拟任何传感器数据,作用只是在正式路试前先在「陆地」上验证场景脚本能否正常启动。

    手段 覆盖 明确不覆盖
    rosbag(全量) 每一个 topic 说明文档未涉及落盘策略与容量限制
    specific rosbag 指定 topic,例如导航数据 其余 topic 不记录;需手工维护脚本内的 topic 列表
    scenario_starter 节点 12V Auto 状态、OCU 的 start scenario 命令 任何传感器数据;只能给出脚本是否启动正确的指示

    把这三行放在一起看,结论很直接:这套工具链能验证「脚本会不会崩」,但不能验证「车会不会开对」。传感器数据必须来自真实车辆或另行搭建的仿真。

    归档快照与权利状态

    归档只保留了一个文件,因此完整性校验相对简单:路径 colcon_ws/src/marv_driver/resource/marv.dbc,Git blob 182c2fb5f6c02d8ef26c26b2adaa564174f1c2f1,SHA-256 4aab0907c9c43435b11c8729c725c092f98667deb868cc7c6356ed5eb8f3dddc,快照修订 5b7ed5f6a5547a63407562572b31243f9c5a35a7,采集日期 2026-10-04。归档方确认保留字节与所钉住的 Git blob 一致,且在本地存档中没有字节相同或经 CRLF 归一化后相同的重复项。

    权利侧的表述需要读仔细:归档保留了仓库的 MIT 许可证与上游 README,同时写明各组件数据的独立来源并未确立。这两句话不矛盾,但含义差别很大——MIT 覆盖的是仓库自身携带的内容,不等于覆盖项目所引用的第三方组件数据。把它并入闭源产品或对外再分发之前,组件部分仍需单独确认。

    常见问题

    marv.dbc 的 35 条报文分别对应哪些硬件?

    归档说明没有给出逐条映射。文件位于 colcon_ws/src/marv_driver/resource/marv.dbc,规模为 35 条 BO_ 报文与 115 行 SG_ 信号;归档方同时写明具体平台硬件与 DBC 信号校验均未独立检查,且这不是量产车型定义。要确定报文与硬件的对应关系,需要结合 marv_driver 的源码自行核对。

    为什么构建步骤要固定 ROS 2 galactic?

    因为构建与运行步骤是按这个发行版写的:构建前需 source ROS2 galactic,相关脚本按 /opt/ros/galactic/setup.bash 的路径组织。换成其他发行版时这些路径与包名需同步调整,而说明文档没有提供其他发行版下的验证记录。

    两套 rosbag 应该怎么选?

    按用途分:一套记录全部 topic,适合事后完整回溯;另一套只记录指定 topic(例如导航数据),适合长时间跑车时压住数据量。定向那套的 topic 列表写在 start_specific_ros_bah.sh 脚本里,改场景时要记得同步维护,否则关键信息不会被记录。

    scenario_starter 能不能代替实车路试?

    不能。它只模拟 12V Auto 状态与 OCU 发出的 start scenario 命令,用于在正式路试前验证场景脚本能否正常启动。上游说明明确指出它不模拟任何传感器数据,因此只能给出「脚本是否启动正确」的指示,无法验证控制行为是否正确。

    这份归档的权利状态如何?

    归档方保留了仓库的 MIT 许可证与上游 README,同时说明各组件数据的独立来源并未确立。MIT 覆盖的是仓库本身携带的内容,不等于覆盖随项目引用的第三方组件数据;再分发前需要单独确认各组件部分的权利。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/case-lab-marv-ros/SOURCE.md(marv.dbc 的路径、35 条 BO_ 报文与 115 行 SG_ 信号、Git blob 与 SHA-256、快照修订与采集日期、平台硬件与信号校验未核验的声明、保留 MIT 许可证与上游 README 的权利说明)
    • 项目 01 —— public-can-dbc-datasets/additional/case-lab-marv-ros/UPSTREAM_README.md(colcon_ws 内四个包的分工、依赖与 galactic 环境下的 colcon build –symlink-install 构建、两套 rosbag 与 start_specific_ros_bah.sh 的 topic 配置、marv_start.sh 与 screen 会话、systemd 服务命令、scenario_starter 节点的仿真覆盖范围与不模拟传感器数据的边界)

    免责声明

    本文所述报文与信号数量、包结构、命令与运行方式均来自公开开源仓库的说明文档,属第三方工程产物,未经独立实车核验。归档方已明确声明平台硬件与 DBC 信号校验未独立检查,且该定义并非量产车型模型。不同平台版本与组件固件可能存在差异。涉及安全相关用途时请仅作参考,并以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • sygnal_dbc 前缀契约:cb_niro_dcan 不是原厂帧

    结论:sygnal_dbc 最容易被误读的一点是目录名叫 niro。归档说明明确指出:cb_niro_dcan/ 里的四个单报文文件描述的是 Sygnal 项目自己的 UserApplication 到 MCM 接口,其 CAN ID 与位布局不能被假定为 Kia Niro 的原厂诊断帧。而真正属于 Hyundai/Kia 整车定义的是另一个文件——140 条报文、1,301 个信号的 hyundai_kia_generic.dbc,它同样没有标定到具体年款。

    包结构与前缀规则

    这个仓库的做法是把每个子系统目录都做成一个独立的 ament_cmake 包,用 dbc_gen_cpp 从目录里的 .dbc 生成并导出 C/C++ 报文类型。七个目录对应七个包,每个包有固定的库前缀。

    目录 包名 库前缀
    mcm/ dbc_sygnal_mcm mcm_
    io/ dbc_sygnal_io io_
    cb/ dbc_sygnal_cb cb_
    cb_niro_dcan/ dbc_sygnal_cb_niro_dcan cb_niro_dcan_
    hpo/ dbc_sygnal_hpo hpo_
    vehicles/ dbc_sygnal_vehicles vehicles_
    sygnal_dbc/ sygnal_dbc 伞形包,无前缀

    命名规则是「<前缀>_<dbc 文件名主干,小写>」,并且这一串字符串同时是库名、C++ 命名空间、C 符号前缀与头文件目录。例如 mcm/Control.dbc 产出库 mcm_control、头文件 mcm_control/mcm_control.h 与 .hpp、命名空间 mcm_control、C 符号 mcm_control_*。

    C 用法的关键是:这些库以命名空间化的 imported target 导出,写作 dbc_sygnal_mcm::mcm_control。跨子系统同名的 DBC 不会冲突,因为包名已经把作用域隔开了。

    为什么必须有前缀

    前缀不是洁癖,而是被 colcon 与链接器逼出来的。有六个文件名在 cb/、hpo/、io/、mcm/ 四个子系统中同时存在:Control.dbc、Heartbeat.dbc、Identify.dbc、Configuration.dbc、Error.dbc、Commissioning.dbc。

    若按主干直接命名 后果
    四个库都叫 Control 同时链接其中任意两个即出现重复符号错误
    C 符号均为 control_* 静态链接阶段冲突,且无法按子系统区分版本
    头文件都装到 include/Control/Control.hpp 安装阶段互相覆盖,包含路径失去区分度

    还有一个目录结构的细节值得记住:cb_niro_dcan/ 是 cb/ 的兄弟目录,而不是 cb/niro_dcan/ 子目录。原因是 colcon 不会进入一个它已经识别为包的目录的子目录。但在安装产物里,database 树仍然把它摆回 cb/niro_dcan/ 的位置——也就是说源码布局与安装布局故意不一致,这是构建系统约束的结果,不是笔误。

    新增一份 DBC 不需要改 CMake

    每个包的 CMakeLists.txt 都只是一个薄壳,真正干活的是共享的 cmake/dbc_package.cmake 里的 dbc_package() 函数:它 glob 目录里的每一个 *.dbc,为每个文件生成一个导出库。因此新增一份 DBC 只需把文件丢进目录,无需改任何构建脚本。

    需要跑到原始文件时,find_package(sygnal_dbc) 会把 SYGNAL_DBC_DIR 指向 <install-prefix>/share/sygnal_dbc/database,并保留 <子系统>/<名称>.dbc 的原始布局;每个子系统包也会把自己的 DBC 装到 share/<包名>/database 下。要用哪一层,取决于你是想按子系统引用还是想按整车打包。

    向后兼容也做得干净:以前这个包会编译出一个名为 sygnal_dbc 的聚合库,并把头文件安装成 sygnal_dbc/<前缀>_<名称>.h。拆分之后两种方式都还能用——聚合库变成一个链接了所有生成库的 INTERFACE 库,转发头文件位于 include/sygnal_dbc/<库名>.h。关键在于旧的构建本来就给 cantools 传 --database-name <前缀>_<名称>,正好等于新的库名,因此 C 符号完全没变,老代码无需改动。新代码则应包含 "<库名>/<库名>.hpp",直接链接 dbc_sygnal_<子系统>::<库名>。

    两个必须核对的事实点

    第一,cb_niro_dcan 的四个文件——batterySOC.dbc、door_seatbelt_state.dbc、dtc.dbc、tpms.dbc——每个只有一条报文,合起来描述的是 SOC、车门与安全带状态、DTC 状态与胎压。它们是工程接口定义,不是车型 niro 的诊断帧;把它当作 Kia Niro 的原厂数据去对接,方向一开始就错了。

    第二,hyundai_kia_generic.dbc 虽然有 140 条报文、1,301 个信号,但它的问题恰恰藏在规模里。归档对比发现,这份文件相对于一份较早的 OpenDBC 派生副本修改或移除了多条报文与信号布局;而仓库既没有固定上游修订版,也不解释每一处改动,更没有说明对应的车型年款,也不提供匹配的抓包数据。这五个 Git blob 在归档收录时都不在已有存档里,Niro 那些文件还保留着原始的 CRLF 行尾。

    结论很直接:Apache-2.0 许可对仓库代码成立,但整车数据的来源与权利链并没有被记录下来。若要把这份 140 报文的文件用在项目里,需要先回溯原始许可链,并用真实抓包做车型适配验证——规模大不等于证据强。

    常见问题

    cb_niro_dcan 里的四个文件是 Kia Niro 的原厂 CAN 定义吗?

    不是。归档说明明确写道,这四个单报文文件描述的是 Sygnal 项目中 UserApplication 到 MCM 的接口,涵盖电池 SOC、车门与安全带状态、DTC 状态与胎压;其 CAN ID 与位布局不能被假定为工厂 Kia Niro 的诊断帧。

    为什么库名必须带子系统前缀?

    因为文件名在多个子系统里重复。Control、Heartbeat、Identify、Configuration、Error、Commissioning 六个文件名在 cb、hpo、io、mcm 中都存在,按主干命名会产生四个同名库、四份同名 control_* 符号与四条相同的安装路径,同时链接其中两个即报重复符号错误。

    新增一份 DBC 需要改 CMakeLists 吗?

    不需要。每个包的 CMakeLists 只是薄壳,实际调用共享的 cmake/dbc_package.cmake 里的 dbc_package() 函数,该函数 glob 目录内的所有 dbc 文件并为每个文件生成一个导出库。把新文件放进目录即可。

    hyundai_kia_generic.dbc 有 140 报文,能直接用吗?

    不建议直接用。归档对比发现它修改或移除了多条报文与信号布局,而仓库既没有固定上游修订版,也没有解释改动、标注车型年款或提供匹配的抓包数据。使用前需回溯 OpenDBC 的许可链并用真实抓包验证车型适配。规模大不等于证据充分。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/polymathrobotics-sygnal-niro/sygnal_dbc/README.md(七个子系统与七个 ament_cmake 包及其库前缀、dbc_package() 与 cmake/dbc_package.cmake 的 glob 机制、mcm/Control.dbc 到 mcm_control 的命名规则、同名文件在四个子系统中重复导致的重复符号问题、cb_niro_dcan 作为兄弟目录的 colcon 原因、命名空间化 imported target、向后兼容的 INTERFACE 库与转发头文件、SYGNAL_DBC_DIR 与安装布局)
    • 项目 01 —— public-can-dbc-datasets/additional/polymathrobotics-sygnal-niro/SOURCE.md(仓库与快照 commit、采集日期 2026-10-04、四个 Niro 接口文件的性质与「不得假定为原厂帧」的断言、140 报文 1,301 信号的 hyundai_kia_generic.dbc 及其与 OpenDBC 派生副本的差异、五个 blob 的 sha 记录、Apache-2.0 保留与整车数据权利链未记录)

    免责声明

    本文所述包结构、命名规则与文件规模均来自公开开源仓库的说明与归档文件,未经实车独立验证,也不代表任何车辆制造商的官方数据。涉及车辆定义的文件并未标注适配年款,也无匹配抓包可供核验。涉及行车安全的功能请以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • 东风 E70:23 个已验证信号与 7 报文种子 DBC

    结论:东风 E70 这个项目的核心落差是数量级的:作为唯一真源的 production/e70_current.dbc 只有 7 条报文、7 行信号定义,而由它生成、也是唯一部署物的 RealDash XML 有 21 个 frame 元素与 46 个 value 元素。46 个值里只有 23 个是作者认证过的 validated,其余 20 个为 plausible、另有 partial、suspect、unverified 各一。把 XML 当作 46 个已验证信号来用,是最容易踩的坑。

    采集条件与产物分工

    所有数据的来源是 ESP8266 加 MCP2515 组成的 SLCAN 桥,在 500 kbit/s 上做只听抓取。这个硬件前提决定了它的能力边界:MCP2515 是经典 CAN 控制器,这套装置看不到 FD 帧,也不具备任何主动请求能力,因此 UDS 一类的按需数据完全不在范围内。

    产物 路径 规模 用途
    唯一部署的 RealDash 配置 production/e70_all_signals_merged2.xml 21 个 frame、46 个 value 以 CAN/Custom XML 输入方式加入 RealDash
    信号定义的唯一真源 production/e70_current.dbc 7 条报文、7 行信号 每个信号的 bit、scale、offset 以此为准
    验证报告 reports/validation_report.txt 对 46 个值逐条判定 23 validated / 20 plausible / 各 1 的 partial、suspect、unverified
    抓包与工具 capture/、analysis/ 含 SLCAN 回放模拟器 生成新日志、跑事后分析与报告

    production/ 目录的原则是「每种只有一个」:当前配置与当前 DBC 各一份,其余全部进 archive/ 且永不删除。这条约定比它看起来重要——看到 archive/xml/ 里还有老的 merged 与 probe XML、archive/dbc/ 里还有自动解码的临时 DBC 时,如果不看这组约定,很容易把过期文件当成候选版本。

    而 XML 与 DBC 的关系是单向的:XML 由 DBC 生成,改信号只能改 DBC,绝不能手改 XML。这条规则一旦破掉,DBC 就不再是唯一真源,两份文件会各自漂移。

    23 个 validated 与 20 个 plausible 的分界线

    作者给出的分级标准非常明确,这也是这份资料最值得学习的地方。

    等级 判据 数量 能不能用于判断
    VALIDATED 场景已确认,且在全部 167 份日志中都保持一致 23 可以
    PLAUSIBLE 存在且落在物理量程内,但含义与缩放仍需实车确认 20 只能观察趋势
    PARTIAL / SUSPECT 多为位运算符定义的枚举,观测分布不全 各 1 不能,需补抓
    UNVERIFIED 未在作者抓包中验证 1 不能

    已验证的 23 个信号覆盖面其实相当完整:整车与轮速、制动与加速踏板、挡位、里程、车门与灯光及远近光、转向灯、电子驻车(EPB)、SOC(0x397 与 0x380)、充电状态与握手信号。它们的验证强度来源于「场景确认 + 全部 167 份日志一致性」双重条件,合计约 2400 万条匹配帧(原文记为 ~24M matched frames)。

    仍在 plausible 里的则肯定是那些该小心的人:电池包电压(0x0D3)、高压电流(0x0EF)、转向角、若干温度、扭矩与功率。它们的共同特点是「读数落在合理区间」,但没人证明这个换算系数是对的。

    而电池相关的锚定之所以卡住,原因写得一清二楚:完整的包电压、SOC、电流缩放系数标定,需要一份从接近空到充满的真实充电抓包,让 SOC 沿单调充电曲线变化才能把 scale 与 offset 钉住。现存的充电日志跨越的 SOC 区间不够宽,钉不住。

    自动化评分会误报,这是已知缺陷

    这一条必须单独说,否则看到报告里的 PARTIAL 会做出错误判断。凡 RealDash 的 conversion 里用到了位移或按位与的枚举/位域信号,自动评分器可能把它报成 PARTIAL 或 SUSPECT,即便它在 RealDash 里渲染完全正常。

    原因是评分器看的是原始字段的分布:只要某一次挡位或充电状态在抓包里从未出现,它就会认为这个枚举缺状态而报警。正确的读法是把 >> 或 & 定义出来的枚举上的 PARTIAL/SUSPECT 理解为「该事件没有被抓到」,而不是「解码坏了」;确认方式是在车上把缺失的状态实际执行一次再抓。

    这两条命令的实际用法也值得抄:validate_profile.py 针对单份日志打印每个信号的 min/max/mean 与可用性/量程状态,配合 --expect expects.json 可以做物理量断言,越界即 FAIL;analysis/validate_xml.py 则把整份 XML 对全部日志跑一遍,把逐信号判据表写回 reports/。前者适合改完 DBC 立刻自检,后者适合入库前的整体复核。

    权利状态

    最后一个必须写在使用之前的约束:归档方在这个修订版上没有找到仓库总体许可证;仓库里那份 .claude/skills/LICENSE 只覆盖随仓库携带的一个 skill,并没有明确延伸到整车研究数据。归档说明因此要求把它作为私有离线研究副本保留,发布或再分发之前先确认权利。

    常见问题

    那份 RealDash XML 里的 46 个值都是已验证信号吗?

    不是。归档保留的验证报告把这 46 个值划分为 23 个 validated、20 个 plausible,以及 partial、suspect、unverified 各 1 个。只有 validated 那 23 个通过了「场景确认且在全部 167 份日志中保持一致」的双重条件,其余不能用于判断。

    为什么当前 DBC 只有 7 条报文却有 46 个 XML 值?

    因为 DBC 与 XML 承担的角色不同。production/e70_current.dbc 是一份小而规范的种子文件,只有 7 条报文与 7 行信号定义,是所有位、缩放与偏移的唯一真源;XML 是由它生成并扩展配置后的部署物,含 21 个 frame 与 46 个 value。二者不可混为一谈,且改信号只能改 DBC。

    报告里的 PARTIAL 一定说明解码有问题吗?

    不一定。凡是 conversion 里用位移或与运算定义的枚举或位域,评分器可能报 PARTIAL 或 SUSPECT,即使它在 RealDash 中渲染正常;因为评分器按原始字段分布判断,某个状态在抓包中未出现就会被认为缺状态。应理解为事件未被抓到,补抓确认即可。

    电池 SOC 和包电压的缩放系数为什么一直没有定下来?

    作者说明:完整的包电压、SOC 与电流缩放标定需要一份从接近空到充满的真实充电抓包,让 SOC 沿单调充电曲线变化才能锚定 scale 与 offset。现有充电日志跨越的 SOC 区间不够宽,因此这三项仍停留在候选状态,不能当作已标定量使用。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/ali-roohy-dongfeng-e70/UPSTREAM_README.md(ESP8266 加 MCP2515 的 SLCAN 桥与 500 kbit/s 只听抓取、production 目录原则与产物分工、RealDash 的 CAN/Custom XML 加载方式、XML 由 DBC 生成且不可手改、23 个 validated 信号清单与 167 份日志约 2400 万条匹配帧、约 20 个 plausible 候选与 SOC 标定等待充电抓包的原因、验证 commands 与 –expect 断言、枚举位运算被误报为 PARTIAL/SUSPECT 的已知缺陷)
    • 项目 01 —— public-can-dbc-datasets/additional/ali-roohy-dongfeng-e70/SOURCE.md(production/e70_current.dbc 的 7 报文 7 信号行、XML 的 21 个 frame 与 46 个 value、46 个值的 23/20/1/1/1 分级、三个文件的 blob 与 SHA-256、未找到仓库许可且 skill 许可不覆盖整车数据的说明)

    免责声明

    本文所述报文 ID、信号数量与分级结果均来自公开开源仓库的说明与归档文件,属第三方逆向工程产物,未经独立实车核验,也不代表车辆制造商的官方数据。不同车型年款、市场与 ECU 版本可能存在差异。该数据当前缺少明确的仓库许可,不宜直接集成或再分发。涉及行车安全的判断请以实际测量与官方资料为准。

    更新记录

    • 2026-10-14 初稿

  • CANedge 到 InfluxDB:两种解码口径与 200 信号上限

    结论:把 CANedge 的 MF4 日志变成 Grafana 面板,第一步不是装软件,而是先定「何时解码」:数据量很大且只偶尔看图,用按需求解码、不需要数据库的 Grafana Backend;看板加载速度是硬指标、愿意为没人看的信号也付存储成本,才用预先解码写库的 InfluxDB Writer。而第二条路有一个不可协商的硬限制——免费版 InfluxDB Cloud 单设备最多 200 个 unique signals。

    两种口径:先按此表选型

    这个项目自己就把取舍讲清楚了,两者不是新旧关系,而是「解码时机」的不同。

    维度 CANedge Grafana Backend CANedge InfluxDB Writer
    解码时机 终端用户需要时才处理 提前批量处理,可周期触发或随文件上传触发
    是否需要数据库 不需要 需要,解码结果写入 InfluxDB
    适合场景 数据量庞大,只处理要看的那部分 看板加载速度是关键指标
    主要代价 每次打开面板都要算一遍 没人看的信号也被解码、也被存储
    本文分析对象 否 是,本仓库属于后者(已标为 LEGACY)

    值得注意的是仓库顶部已经把这条路标为 LEGACY 且不再支持,官方推荐转向 Grafana-Athena 集成。把它当作教学材料而不是生产依赖更合适:它的配置方式很清晰地暴露了一个 DBC 解码入库管线的全部接缝——把它的结构读明白之后迁移到新方案,比直接啃新方案要快。

    Writer 路径的六项能力与两个硬约束

    这条写在 features 列表里的能力清单,实际决定了能从 MF4 里榨出什么。

    能力/约束 取值 影响
    日志来源 本地磁盘或 S3 服务器上的 MF4 S3 场景把 devices 写成 your_bucket/device_id 形式,并设 s3 = True
    时间区间 可写死固定区间,也可用动态周期 固定区间需配合 days_offset = None 才能按真实日期写入
    解码 DBC 解码,可选择性抽取指定信号 这是规避信号上限的主要手段
    重采样 可选,重采样到指定频率 显著降低时序点数,但要留意 aliasing 掩盖峰值
    多帧协议 tp_type 支持 j1939、uds、nmea 需要配套 DBC,示例为 dbc_files/nissan_uds.dbc
    InfluxDB Cloud 免费版 单设备最多 200 个 unique signals 超限必须加信号过滤列表或缩减 DBC

    200 这个数字是这套方案最容易踩的暗桩。它的单位是 unique signals per device,而不是总行数——一份看上去很「全面」的整车 DBC 动辄上百个信号,多设备同时入库就会比分片更快地顶到上限。可行做法只有两个:在 inputs.py 里加过滤后的信号列表,或者把 DBC 本身裁剪到 200 个信号以内。补一句:仓库里的删除函数是 delete_influx(name),传入的是 measurement 名即设备 ID,例如 influx.delete_influx("958D2219"),测试污染要用它清理。

    目录契约:数据怎么放比怎么跑更重要

    绝大多数「跑不通」的问题出在这一步,而不是 Python 依赖。本地磁盘模式下,LOG/ 目录必须按 CANedge SD 卡的原样结构组织:[device_id]/[session]/[split].MF4。作者的建议是直接用自己 SD 卡上的 LOG/ 替换示例的 LOG 文件夹,而不是自己拼层级。

    DBC 文件统一放 dbc_files 文件夹,然后在 inputs.py 里更新 devices 与 dbc_paths。这三个复数形式不是装饰:设备、DBC 与时间偏移是一一对应的配置三元组,漏改任何一项都会导致「跑起来了但图上是空的」。

    标准流程建议严格按顺序走:先装 Python 3.9.13(Windows 记得勾 Add to PATH)、用 install.bat 建虚拟环境装依赖;然后用示例数据跑 main.bat,在 Grafana Cloud 里装 TrackMap 插件、导入 dashboard-template-sample-data.json,把时间范围设为最近 7 天——示例数据的落点是写完那一刻,不看最近 7 天就是空图。确认看到有效曲线之后,再替换成自己的数据并导入 dashboard-template-simple.json。

    走向生产之前要做的两件事

    第一件是自动化。路径验证完成后,仓库里的 deploy-aws-lambda/ 目录给了以 AWS Lambda 自动运行的 README,配合 S3 侧的上传触发,可以把「插卡倒入服务器」这步彻底去掉。

    第二件是成本。作者在文档里明确提醒:如果用的是付费的 InfluxDB Cloud 加付费 S3 服务器,建议在测试早期就盯着用量,避免意外的成本增长。实践上更好的做法是把写入点数与读取请求量各自做成独立指标长期观察,而不是等账单。

    常见问题

    该选 Grafana Backend 还是 InfluxDB Writer?

    看解码时机需求:数据量大且只有偶尔看图时选 Backend,它按终端用户需要时才处理且不需要数据库,代价是每次开面板都要算;看板加载速度是硬指标时选 Writer,它提前处理并写库,代价是没人看的信号也会被解码存储。

    免费版 InfluxDB Cloud 的信号数超限怎么办?

    作者给出的两个办法是:在 inputs.py 里加过滤后的信号列表,或者把 DBC 文件裁剪到 200 个信号以内。限制的单位是单设备 200 个 unique signals,不是总行数,所以多设备入库会更快触顶。

    为什么管道跑通了但 Grafana 面板是空的?

    先看时间范围,再看 days_offset。示例数据的落点是写入那一刻,需要把时间浏览器设到最近 7 天;换成自己的数据时必须把 days_offset 设为 None,否则数据会按偏移后的日期写入,落在当前查询窗口之外。

    能不能处理 UDS 或 J1939 这类多帧数据?

    可以。把 tp_type 设为 uds、j1939 或 nmea,并配上对应的 DBC 文件。仓库里给的验证方式是加 dbc_files/nissan_uds.dbc 并把 tp_type 设为 uds,用示例数据即可试通。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/css-canedge-influxdb/README.md(LEGACY 状态与 Grafana-Athena 推荐、Backend 与 Writer 的 pros and cons 对照、六项 features、Python 3.9.13 与 Windows/Linux 安装步骤、本地与 S3 两种数据加载路径、LOG/ 的 [device_id]/[session]/[split].MF4 目录契约、200 unique signals 上限、tp_type 的 j1939/uds/nmea 取值、dashboard-template-sample-data.json 与最近 7 天查看窗口、delete_influx(name)、AWS Lambda 自动化与云成本提醒)

    免责声明

    本文所述能力、参数与配置方式均来自公开开源仓库的说明文件。该仓库已被上游标记为 LEGACY 且不再支持,文中 200 unique signals 等限制为 InfluxDB Cloud 免费版在其文档成文时的声明值,实际额度与价格可能已调整。涉及付费云服务与生产部署请以官方最新文档与实际用量为准。

    更新记录

    • 2026-10-14 初稿

  • canlab-zn6:四层只读约束与 9 个受限诊断查询

    结论:canlab-zn6 的「只读」不是一个 UI 设计选择,而是四层各自独立的关:固件跑控制器 listen-only 并持续拉住收发器的 silent 引脚、wire protocol 里根本没有发帧命令、Host 只在 decode-only 门面后面用 can_decode、 contributing scope 直接把写诊断与 ECU 仿真列为不接受。它的价值恰恰在于这套自限——看懂这四层,就知道为什么它是稳妥的上车第一步,也知道它当前拿不到什么。

    四层只读约束分别拦住了什么

    大多数「只读工具」只在应用层藏了一个按钮。这份 Rust 工具链把约束下沉到了四个不同层次,每一层的失效模式都不一样,因此值得逐层拆开看。

    层次 机制 拦住的动作 残余风险
    固件 控制器 listen-only 模式,并持续把收发器硬件 silent 输入保持在有效状态 ESP32-S3 / ESP32-C6 板卡自发帧 依赖电气连接正确,官方要求接车前用电表验证 silent 引脚
    协议 主机 CLI、Web 应用、SocketCAN 适配器、wire protocol、MCP server 均无任意发送命令 来自上位机的单帧注入 与本工具同栈协作时才成立;换成其他 CAN stack 自行接入则不受此约束
    解码 Host 通过 decode-only 门面调用 can_decode,其编码方法不暴露给采集、诊断、固件、Web 服务与 MCP 构造并编码报文的能力 无;但若有人 fork 后改动门面,需重新审计
    社区 贡献指南明确不接受增加在车控制、刷写、写诊断或 ECU 仿真的改动 通过 PR 把写能力带进来 fork 版本不受此约束

    这四层里真正悬而未决的是第二层的物理版本落差:受保护的状态机与 Wokwi 诊断仿真器都已就位,但实体板卡的诊断发送仍处于关闭状态,要等板级的 ARM 与 fail-silent 电气测试完成。也就是说,当前 S3 与 C6 的实体发布包是采集专用(capture-only),诊断只能通过 Linux 上的 receive-only SocketCAN 之外的路径得到 仿真,不能指望在真车上读 Mode 21。

    值得把这句警告当回事:作者在文档里明确写了这不是车规产品,而是实验性研究设备。把它接上一台日常代步车之前,先读完安全边界那一章并用电表验证 silent 引脚,是唯一负责任的顺序。

    为什么自动变速箱的 DBC 是空的

    这份工具的 ZN6 DBC 定义被拆成 common / manual / automatic 三层 profile,每层显式声明它叠加哪些 DBC 文件、以及是否加载 candidate 条目。空文件是有意保留的一种状态。

    层/文件 内容 是否加载 证据状态
    zn6_gen1_common.dbc 已发布信号,基于 MIT 授权的 FT86 Gen1 map 与 RaceChrono 映射 三个 profile 共同底层 published,含测试向量
    zn6_gen1_mt.dbc 手动挡专有部分 由 MT profile 叠加加载 published
    zn6_gen1_at.dbc 自动挡专有部分 由 AT profile 叠加加载 目前为空,刻意不出表
    zn6_gen1_at_inventory.toml 仅登记存在性与标称速率,不断言任何位布局 独立引用,来源为 Toyobaru CAN ID map 6 个 ID:328/329/330 均 100 Hz、872 为 20 Hz、977 为 8 Hz、1218 为 1 Hz
    evidence.toml 13 条逐信号证据,含来源 URL、车型变体、观测量与测试向量 始终随定义引用 12 条 published + 1 条 candidate

    AT DBC 空着不是因为没人做,而是源于一条明确写进文档的原则:看起来合理却是编造出来的字段,比明确标注「未知」更糟。因此 include_candidates 默认 false,candidate 级别的条目(例如 ID 865 那个未经验证的三位挡位字段)不会被加载,除非显式要求。

    这套结构的直接推论是:evidence.toml 里的每一行都带车型变体限定,比如车门与尾箱的标志位分配只在右舵车上验证过、安全带只有驾驶员侧测过而乘客侧行为未知。把 published 当成「全变体通用」而不加甄别地套用,左舵车的车门信号就会错位。

    九个诊断查询的参数与限速

    诊断目录是整套工具里最容易被低估的部分:它把每个请求的预算写死了,包括超时与轮询上限,而不是靠调用方自觉。

    查询 service / 参数 解码方式 timeout / max_hz 置信度
    车速 1 / PID 13 linear_u8,offset 2,factor 1.0 250 ms / 2.0 Hz published
    发动机转速 1 / PID 12 linear_u16_be,factor 0.25 250 ms / 2.0 Hz published
    冷却液温度 1 / PID 5 linear_u8,bias −40 250 ms published
    节气门位置 1 / PID 17 linear_u8,factor 0.3921568627 250 ms / 2.0 Hz published
    控制模块电压 1 / PID 66 linear_u16_be,factor 0.001 250 ms / 1.0 Hz published
    VIN 9 / PID 2 ascii,offset 3,length 17 750 ms / 0.2 Hz published
    存储故障码 3 / 无参数 trouble_codes,offset 1 750 ms / 0.2 Hz published
    机油温度 33(Mode 21)/ PID 1 linear_u8,bias −40 400 ms / 1.0 Hz candidate,opt_in
    变速箱油温裸值 33(Mode 21)/ PID 130 raw,offset 2 400 ms / 1.0 Hz candidate,opt_in

    请求 ID 统一为 2016、响应为 2024,即 0x7E0 / 0x7E8 这一对标准 OBD 地址。真正的判别价值在中间两列:四个 PID 用 250 ms 超时、400 ms 给 Mode 21,而 VIN 与故障码给到 750 ms 并把轮询压到 0.2 Hz。这个分配隐含一个判断—— identification 类请求慢且贵,只能偶尔问;物理量类请求便宜,但也不能无上限。自己做轮询调度时,这份表是最省事的初始值。

    另外两个 Toyota Mode 21 查询都带 opt_in = true 且标记 candidate。它们的 expected_prefix 是十进制的 [97, 1] 与 [97, 130],正响应前缀落在 Mode 21 的规则内;但把 raw 类型的 ATT 温度直接做成仪表读数是不合适的,它连缩放系数都没有。

    常见问题

    这套工具能在实车上发送 CAN 帧吗?

    不能。固件跑控制器 listen-only 模式并保持收发器 silent 引脚有效,主机 CLI、Web 应用、SocketCAN 适配器、wire protocol 与 MCP server 都没有任意发送命令,且 Host 只用 can_decode 的解码面。当前 S3/C6 实体发布包是采集专用,实体诊断发送要等板级 ARM 与 fail-silent 电气测试。

    为什么自动挡的 DBC 文件是空的?

    这是一个刻意的选择。作者认为看起来合理却是编造的字段比明确标注未知更危险,因此 zn6_gen1_at_inventory.toml 只登记自动挡报文的存在性与标称速率(328/329/330 为 100 Hz、872 为 20 Hz、977 为 8 Hz、1218 为 1 Hz),不断言位布局;真正的信号定义要等到有可辩护的定义与测试向量再进 DBC。

    candidate 级别的信号默认会参与解码吗?

    不会。三个 profile 的 include_candidates 都是 false,Candidate 条目需要显式请求才加载。目前 evidence.toml 的 13 条里只有 1 条是 candidate——ID 865 那个未经验证的三位挡位字段,其余 12 条为 published。

    贡献一份新的信号定义需要提供什么?

    来源、车型变体、观测记录与测试向量,四项缺一不可。并且面向在车控制、刷写、写诊断或 ECU 仿真的改动明确不在接收范围内——这条贡献禁令与前述四层只读约束是一致的。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/dimitri-canlab-zn6/README.md(read-first 定位、ESP32-S3/C6 与 TJA1051T/3 收发器、listen-only 与 silent 引脚、无任意发送命令、capture-only 实体发布、诊断 TX 待测试、capture 的四种输入源、Rust 1.96 与 2024 edition、MIT OR Apache-2.0)
    • 项目 01 —— public-can-dbc-datasets/additional/dimitri-canlab-zn6/docs/definitions.md(common/manual/automatic 三层 profile、candidate 不默认加载、AT 清单仅登记存在与速率、AT DBC 保持为空的原则、Host 只用 decode-only 门面)
    • 项目 01 —— public-can-dbc-datasets/additional/dimitri-canlab-zn6/definitions/zn6_gen1_at_inventory.toml、definitions/evidence.toml、definitions/diagnostics.toml(6 个 AT ID 与标称速率、13 条证据的置信分布、9 个诊断查询的 service、参数、解码器、timeout_ms 与 max_hz)

    免责声明

    本文所述工具行为、定义分层与诊断参数均来自公开开源仓库的说明与配置文件,属社区研究产物,未经实车独立验证,也不代表车辆制造商的官方数据。该项目自我定位为实验性研究设备而非车规产品。涉及在用车接入的操作请以官方资料与实际测量为准。

    更新记录

    • 2026-10-14 初稿