feat: integrate cabin CAN and verified dynamic seat modes

This commit is contained in:
vee
2026-08-04 17:51:38 +08:00
parent 155fbb59ba
commit dc7c91800e
99 changed files with 51897 additions and 3618 deletions
@@ -0,0 +1,53 @@
# T2G 座椅与车身双通道 CAN 联动
## 集成基线
- 座椅控制沿用当前仓库的 IAR `Seat_Controller_demo` 协议与闭环回读。
- 车身控制从 `https://git.kendeji.fun/dev-team/project-code` 的 `CAN_DEV` 分支导入,固定基线为提交 `6e7ed04a468dfcde7efda9e30bc15144bf02faf9`。
- 不允许自然语言直接提供 CAN ID 或原始载荷;只有能力目录中命名、经过范围校验的动作可以编译到车身 CAN。
## 适配器和通道
一个 `USBCANFD-200U` 只由一个 32 位桥接进程打开一次,再向应用暴露两个通道视图:
| 通道 | 用途 | 帧格式 | 仲裁速率 | 数据速率 |
|---|---|---|---:|---:|
| CH0 | T2G 副驾座椅控制器 | 11-bit Classic CAN | 500 kbit/s | — |
| CH1 | 空调、车窗、门锁、灯光、遮阳帘和电动风口 | 11-bit ISO CAN FD;按报文选择 BRS | 500 kbit/s | 2 Mbit/s |
车身通道使用 60 MHz CAN 时钟。仲裁段为 `tseg1=14, tseg2=3, sjw=2, smp=0, brp=5`,20 TQ、80% 采样点;数据段为 `tseg1=10, tseg2=2, sjw=2, smp=0, brp=1`,15 TQ、80% 采样点。ZLG 运行时使用驱动内置的 `500000`/`2000000`、80% 参数项,并显式选择 Normal、ISO CAN FD。
## 服务端配置
```powershell
$env:COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED = "true"
$env:COGNITIVE_AGENT_VEHICLE_CAN_ENABLED = "true"
$env:COGNITIVE_AGENT_SEAT_CAN_BACKEND = "zlgcan"
$env:COGNITIVE_AGENT_VEHICLE_CAN_BACKEND = "zlgcan"
$env:COGNITIVE_AGENT_SEAT_CAN_CHANNEL = "0"
$env:COGNITIVE_AGENT_VEHICLE_CAN_CHANNEL = "1"
$env:COGNITIVE_AGENT_VEHICLE_CAN_ARBITRATION_BITRATE = "500000"
$env:COGNITIVE_AGENT_VEHICLE_CAN_DATA_BITRATE = "2000000"
$env:COGNITIVE_AGENT_SEAT_CAN_TERMINATION_ENABLED = "true"
$env:COGNITIVE_AGENT_VEHICLE_CAN_TERMINATION_ENABLED = "false"
$env:COGNITIVE_AGENT_SEAT_FIRMWARE_PROFILES = "combined"
$env:COGNITIVE_AGENT_HARDWARE_APPROVAL_TOKEN = "<bench-only-token>"
```
真实执行会拒绝以下情况:两个逻辑总线配置为同一通道、CAN FD 时序不等于已验证值、ZLG 32 位运行时缺失、座椅固件未通过被动签名检查、车身动作不在可信能力目录内,或需要反馈的车身指令未收到对应状态帧。
## 一句话联动示例
`副驾座椅通风3档,同时打开空调,温度设为24度,风量3档`
该请求生成独立的 `seat` 与 `native_climate` FunctionConfig/CommandPlan。真实执行时,两组执行器在独立线程中使用 CH0/CH1 通道视图;底层桥接仍统一串行化 SDK 调用,并将长时间接收切成不超过 20 ms 的时间片,以便两个通道交替收发。
## 验证要求
1. 先运行 `zlgcan_bridge.py --self-test`,确认经典 CAN 与 CAN FD API 导出及 ABI 结构尺寸。
2. 在 ZCANPRO 确认 CH0/CH1 接线、终端电阻和总线状态正常,然后关闭其在线通道,避免与服务争用设备。
3. 用 dry-run 核对两份计划:座椅报文位于 `seat_can`,车身报文位于 `body_can`;空调控制 ID 为 `0x1DE`。
4. 以 hardware 模式执行低风险联动句,要求座椅板端反馈成功,且车身通道观测到对应状态反馈(空调为 `0x404`)。仅发送成功而无状态帧不能记为通过。
5. 验证完成后关闭座椅热舒适功能、发送座椅 `STOP_ALL`,并按测试前状态恢复车身设备。
相关机器可读配置位于 `platforms/t2g_cabin_bench/` 与 `config/environments/t2g_cabin_bench.example.yaml`。
+16 -2
View File
@@ -42,13 +42,13 @@ powershell -ExecutionPolicy Bypass -File .\tools\build_seat_firmware.ps1
- 热管理命令:`0x29E/0x3CE`;档位反馈:`0x4FA`。
- 移动命令:`0x300`;系统 ACK:`0x301`;归一化位置:`0x302`;Hall/量程:`0x303`。
- 电流诊断:`0x304` 四轴轮询,`0x305` 通风/加热;这些值用于台架可见性,当前保守阈值不能替代外部限流或量产保护。
- 电流诊断:`0x304` 四轴轮询,`0x305` 通风/加热;动态模式:`0x306` 以100 ms周期报告模式、阶段、循环和活动轴。这些诊断值用于台架可见性,当前保守阈值不能替代外部限流或量产保护。
- Opcode 1 的 `ParamA` 为 1–10000 绝对位置;后端显式发送 30 s 超时覆盖值。
- 前端目标 `0%`/“归零”不是普通绝对位置,而是 `HOME_KNOWN_RANGE (0x0B)`;只有收到 `COMPLETE/OK`、Near、Hall≤2 和 PositionValid 才算成功。
- Opcode 3 的 `ParamA` 为持续时间,`ParamB` 为驱动等级×10(默认 90%)。
- `STOP_ALL` 的专用 ACK 为 4;完成/故障 TaskState 分别为 6/7。
新版固件把 `0x304/0x305` 用于电流诊断,不能继续发送旧版身份请求。后端在任何控制帧之前被动观察 `0x301–0x305`、`0x4FA`、四个 MotorID、固件 revision 6 和各轴标称 MaxHall(允许 5% 台架差异);真实硬件执行启用后,未观察到完整签名会自动使用仓库内 IAR 镜像烧写,重新被动验证成功后继续原请求。烧写或复验失败时禁止发送座椅控制帧。
新版固件把 `0x304/0x305` 用于电流诊断,并用`0x306`报告原生动态模式,不能继续发送旧版身份请求。后端在任何控制帧之前被动观察 `0x301–0x306`、`0x4FA`、四个 MotorID、固件 revision 13 和各轴标称 MaxHall(允许 5% 台架差异);真实硬件执行启用后,未观察到完整签名会自动使用仓库内 IAR 镜像烧写,重新被动验证成功后继续原请求。烧写或复验失败时禁止发送座椅控制帧。
## 启用配置
@@ -99,6 +99,20 @@ COGNITIVE_AGENT_SEAT_HOME_TIMEOUT_S=120
2026-08-01 长序列中记录到的 M0/M2 无 Hall、M1 高电流无 Hall 故障,后续确认由水平、坐盆和靠背 Hall 地线断开引起,并非软件标定或堵转阈值问题。2026-08-02 重新接好地线并用手工 HIL GUI 验证后,仓库 revision 6 自动烧写成功,四轴均从机械零位以 `PositionValid=1` 启动;自动前端 HIL 的 33 条热功能、单轴、四轴归零、组合和预设模式用例全部通过。因此测试清单中的临时 `safety_blocked` 已撤销。若以后再次出现同类现象,仍应以命令期间 `0x303` Hall 与 `0x304` 电流联合诊断,不能通过提高 Duty 或阈值掩盖线路故障。
2026-08-03 revision 7加入`START_DYNAMIC_MODE(0x0E)`、`STOP_DYNAMIC_MODE(0x0F)`和`0x306`;revision 8验证了连续循环、循环中停止、堵转/无运动保护和ECU启动累计600 s自动停止的公共动态模式运行时。旧ModeID 1轨迹现已从固件、长期库和前端能力中移除,revision 11复用ModeID 1实现木马模式。
2026-08-04 revision 8复测时,公共动态运行时曾单次连续运行600.024 s并自动返回全零IDLE且无FAULT;循环中`STOP_DYNAMIC`也通过。同期动态摇篮被实台M1坐盆轴的真实STALL阻断,独立单轴复测同样在Hall约169失速;后续已恢复机构运动并保留安全全停,未通过降低目标或屏蔽堵转保护改判。
同日revision 9把摇篮改为位置闭环会合,不再使用固定30 s阶段。M1以`0x0B`从Hall 169连续回近端0且保持MaxHall=374后,Step 1→2实测17.329 s、启动/到位离散0.077/0.338 s;Step 2→3实测15.155 s、离散0.079/0.495 s;目标精确、CycleIndex进入1、下一轮四轴启动离散0.082 s、停止全零,PASS。证据见`artifacts/hil/dynamic_cradle_rev9_20260804.json`。Step 3和Step 1坐标相同,其边界是零位移原子换轮;可观测同步动作是紧随其后的下一轮Step 1→2四轴启动。
同日revision 10移除revision 9中“M1先走10 Hall、等待其他轴预备到位后再单独追赶”的临时避让。正向/返回四轴从阶段开始即全程联动;水平/靠背达到约25%行程时,坐盆已分别完成44.0%/39.0%,启动离散0.070/0.050 s,到位离散0.342/0.339 s,下一轮启动离散0.051 s,无FAULT并可正常停止。证据见`artifacts/hil/dynamic_cradle_rev10_continuous_cruise_20260804.json`。
同日revision 11移除旧ModeID 1轨迹并加入木马模式。入口为`[320,190,500,430]`,连续端点为前俯`[290,220,460,400]`与后仰`[350,160,540,460]`;稳态完整循环约9.0 s。实测两个稳态半周期四轴启动离散0.080/0.079 s、到位离散0.234/0.232 s;水平轴到25%时坐盆已达41.7%/36.7%,目标误差不超过1 Hall,自动续环与循环中停止均PASS。证据见`artifacts/hil/rocking_horse_rev11_20260804.json`。
同日revision 12把木马坐盆端点由`220↔160`扩大为`250↔130` Hall,并把M1巡航占空比由50%提升为90%。峰峰上下行程由60增至120 Hall,折算垂直分量约由9 mm增至18 mm;稳态前俯/后仰启动离散0.054/0.081 s,到位离散0.389/0.182 s,水平轴到25%时坐盆已完成46.6%/35.8%,完整循环约9.2 s。目标误差不超过2 Hall、无FAULT、自动续环与停止全零均PASS。证据见`artifacts/hil/rocking_horse_rev12_cushion_amplitude_20260804.json`。
同日revision 13加入坐盆斜向运动的水平前馈补偿:木马M0端点由`290↔350`扩大为`270↔370` Hall,峰峰行程100 Hall,巡航Duty由50%提升为90%。按台架M0 MaxHall=499换算水平峰峰行程约43.1 mm,扣除M1斜向行程估算的16.4 mm反向水平分量后,净水平摆幅约26.7 mm。稳态前俯/后仰启动离散0.077/0.052 s,到位离散0.337/0.182 s;巡航检查点四轴均持续推进,目标误差不超过1 Hall、无FAULT、自动续环与停止全零均PASS。证据见`artifacts/hil/rocking_horse_rev13_horizontal_compensation_20260804.json`。
2026-08-02 时长/超量程规则完成后,扩充清单的真实回归结果为 161/161 通过、0 失败、0 `safety_blocked`,最终清理和独立物理复核均通过。报告位于 `artifacts/hil/seat_frontend_hil_20260802_full_timed_overflow.json`;复核时加热/通风为 0 档,M0/M1/M2/M3 均为 0%,全部 `Position_Valid=1`。
2026-08-02 增加 GPT-5.6-sol 模糊意图与位置记忆同步后,完整回归为 162/162 通过;“前舱空间太挤了,把座椅调整到舒服的位置”明确记录 `provider_used=openai:gpt-5.6-sol`,物理目标为 M0/M1/M2/M3=`80/30/35/10%`。报告位于 `artifacts/hil/seat_frontend_hil_20260802_full_gpt56_position_sync.json`;最终独立复核仍为热管理关闭、四轴 0% 且全部 `Position_Valid=1`。