From 0075f240469ea0eca19c3998ddf790103e122314 Mon Sep 17 00:00:00 2001 From: nitiantuhao <2062405236@qq.com> Date: Fri, 3 Apr 2026 07:57:47 +0800 Subject: [PATCH] 1.0 --- ARES.zip | Bin 164077 -> 0 bytes CODE_REVIEW.md | 397 --------- HANDOFF.md | 773 ------------------ can通讯协议.md | 23 - 大体方案.md | 507 ------------ ...:B类“马铃薯捡拾机器人竞技”比赛及评审规则.md | 27 - 6 files changed, 1727 deletions(-) delete mode 100644 ARES.zip delete mode 100644 CODE_REVIEW.md delete mode 100644 HANDOFF.md delete mode 100644 can通讯协议.md delete mode 100644 大体方案.md delete mode 100644 附件6:B类“马铃薯捡拾机器人竞技”比赛及评审规则.md diff --git a/ARES.zip b/ARES.zip deleted file mode 100644 index 3f68de25e5e24478bbed5cfa6d56a64020bdac51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164077 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

>^|9sS0UQ9J%K`wP{zsIfjiIigzK!l* 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

B7~F0&F1z$ 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 MfxtC3pcG^N2V-}a@Bjb+ diff --git a/CODE_REVIEW.md b/CODE_REVIEW.md deleted file mode 100644 index c6eb5a6..0000000 --- a/CODE_REVIEW.md +++ /dev/null @@ -1,397 +0,0 @@ -# ARES 项目代码审查报告 - -> **审查日期**: 2025 年 -> **审查范围**: `/App` 目录下全部业务代码(排除 `VL53L0X_API/core` ST 官方库) -> **审查基准**: HANDOFF.md 中的设计描述与已修复 BUG 列表 -> **审查重点**: 残留 BUG、潜在运行时风险、代码质量问题 - ---- - -## 审查总结 - -| 严重等级 | 数量 | 说明 | -|---------|------|------| -| 🔴 严重 (可能导致功能错误/崩溃) | 4 | 运行时会导致错误行为 | -| 🟠 中等 (潜在风险/隐患) | 6 | 特定条件下可能触发问题 | -| 🟡 低 (代码质量/可维护性) | 7 | 不影响功能但应改善 | - -**总体评价**: 项目架构设计清晰,HANDOFF.md 中列出的 9 个严重 BUG 和 7 个质量问题均已正确修复。但仍存在若干残留问题,以下逐一分析。 - ---- - -## 🔴 严重问题 - -### S-1: VL53L0X 卡尔曼滤波 Q/R 参数硬编码,未使用 `robot_params.h` 配置 - -**文件**: `VL53L0X_API/platform/vl53_board.c:84` - -```c -/* 初始化卡尔曼滤波器:默认 Q=1.0, R=9.5 */ // ← 注释过期 -vl53_kalman_init(&board->kf[i], 10.0f, 14.1f); // ← 硬编码值 -``` - -`robot_params.h` 中定义了 `PARAM_VL53_KALMAN_Q = 10.0f` 和 `PARAM_VL53_KALMAN_R = 14.1f`,但 `vl53_board.c` 没有 `#include "robot_params.h"`,而是直接写死了 `10.0f` 和 `14.1f`。虽然当前值恰好与参数一致,但**修改 `robot_params.h` 中的 `PARAM_VL53_KALMAN_Q/R` 不会生效**,与 BUG-2 (EKF 参数硬编码) 属于同类问题。 - -**修复建议**: -```c -#include "robot_params.h" -// ... -vl53_kalman_init(&board->kf[i], PARAM_VL53_KALMAN_Q, PARAM_VL53_KALMAN_R); -``` - ---- - -### S-2: `LASER_SIMPLE_GetSnapshot()` 返回指针无线程安全保护,存在数据撕裂风险 - -**文件**: `laser/laser_manager.c:277-279` - -```c -const laser_simple_snapshot_t *LASER_SIMPLE_GetSnapshot(void) { - return &g_snapshot; // ← 返回原始指针,无拷贝、无临界区保护 -} -``` - -消费者 `AppTasks_RunLaserTestTask_Impl()` 调用此函数获取指针后直接传给 `Blackboard_UpdateLaser(snap)`。由于 `LaserTask`(内部10ms任务)在 `taskENTER_CRITICAL()` 中**逐通道写入** `g_snapshot.ch[i]`,而消费者拿到的是裸指针,读取可能发生在写入的间隙——比如前两个通道已更新、后两个通道还是旧值——构成**部分撕裂**。 - -虽然 `Blackboard_UpdateLaser` 内部有临界区保护,但问题出在**读 g_snapshot 的时候没有保护**。当前架构中 `laserTestTask` 以 50ms 周期读取、`LaserTask` 以 10ms 周期写入,两者优先级相同,可能发生抢占。 - -**影响等级**: 中高。实际撕裂概率取决于临界区外的读取窗口大小。由于 `laser_simple_snapshot_t` 只包含 4 个 `laser_simple_data_t`,单次 `memcpy` 耗时极短,实际风险较低。但从防御性编程角度应修复。 - -**修复建议**: -```c -void LASER_SIMPLE_GetSnapshotCopy(laser_simple_snapshot_t *out) { - taskENTER_CRITICAL(); - *out = g_snapshot; - taskEXIT_CRITICAL(); -} -``` - ---- - -### S-3: `snc_parse_odom_delta()` 在 ISR 中写 `odom_accum` 无临界区保护 - -**文件**: `Can/snc_can_app.c:148-173` (在 `SNC_CAN_RxFifo0Callback` 即 CAN ISR 中被调用) - -```c -static void snc_parse_odom_delta(const uint8_t *d) -{ - // ... 直接写 g_snc_can_app.odom_accum 的各个字段 ... - SNC_OdomDeltaAccum_t *acc = &g_snc_can_app.odom_accum; - acc->fl_accum += (int32_t)snc_read_i16_le(d[0], d[1]); - // ... - if (acc->frame_count < 255U) { - acc->frame_count++; - } -} -``` - -而消费侧 `SNC_CAN_ConsumeOdomDelta()` 使用 `taskENTER_CRITICAL()` 保护读取和清零。问题是:**`taskENTER_CRITICAL()` 在 Cortex-M 上通过 BASEPRI 屏蔽中断,只屏蔽优先级不高于 `configMAX_SYSCALL_INTERRUPT_PRIORITY` 的中断**。如果 CAN FIFO0 中断的优先级高于此阈值(即数值更小),那么 `snc_parse_odom_delta()` 可能在消费者持有临界区期间执行,导致**竞态条件**:消费者清零后,ISR 立刻写入新数据,然后消费者返回的 `snapshot` 中 `frame_count=0` 但 `accum` 值已非零。 - -**影响等级**: 取决于 CAN 中断优先级配置。如果 CAN 中断优先级在 FreeRTOS 管理范围内(优先级数值 ≥ `configMAX_SYSCALL_INTERRUPT_PRIORITY`),则 `taskENTER_CRITICAL()` 可以正确屏蔽它,问题不存在。**需要检查 CubeMX 中 FDCAN1 中断优先级配置**。 - -**修复建议**: 确认 FDCAN1 中断优先级 ≥ `configMAX_SYSCALL_INTERRUPT_PRIORITY`。或在 `snc_parse_odom_delta()` 中也使用 `taskENTER_CRITICAL()`(但 ISR 中应使用 `taskENTER_CRITICAL_FROM_ISR()`)。 - ---- - -### S-4: `corridor_msgs.h` 使用 `#pragma pack(push, 1)` 导致 EKF 矩阵和浮点运算性能损失及潜在对齐异常 - -**文件**: `preproc/corridor_msgs.h:8,61` - -```c -#pragma pack(push, 1) -// ... -typedef struct { - float P[3][3]; // 36 字节的浮点矩阵,被强制 1 字节对齐 - float innovation[3]; // 12 字节 - float mahalanobis_d2; - // ... -} CorridorState_t; -// ... -#pragma pack(pop) -``` - -`CorridorState_t` 包含大量 `float` 和 `float[3][3]` 数组,被 `#pragma pack(push, 1)` 强制 1 字节对齐。在 Cortex-M7 上: -1. **性能损失**: 未对齐的 float 访问会触发硬件 unaligned access 处理,速度比对齐访问慢数倍。这个结构体在 navTask 的 20ms 循环中被高频读写,影响实时性能。 -2. **FPU 指令风险**: 某些 FPU 指令(如 `VLDM`/`VSTM`)**要求 4 字节对齐**,不对齐会触发 UsageFault。虽然 GCC 通常会生成安全的加载指令,但编译器优化可能引入向量化或批量加载指令。 - -`CorridorObs_t` 和 `RawCmd_t` 也受影响,但内部结构更简单,风险较低。 - -**修复建议**: `#pragma pack(push, 1)` 仅用于需要匹配物理总线帧格式的结构体(如 `chassis_can_msg.h` 中的 CAN 帧,那是正确的用法)。`corridor_msgs.h` 中的结构体是内存中的数据传递,**不需要 pack(1)**,应删除。 - ---- - -## 🟠 中等问题 - -### M-1: IMU 帧解析状态机缺少帧类型 0x55 之后的 header byte 校验 - -**文件**: `IMU/hwt101.c:64-68` - -```c -if (s_frame_idx == 0 && byte != 0x55) continue; -s_frame[s_frame_idx++] = byte; -if (s_frame_idx >= 11) { -``` - -当前状态机只检查首字节 `0x55`,然后无条件接收后续 10 字节。如果数据流中出现非帧头的 `0x55`(比如校验和恰好是 `0x55`),会导致帧错位。虽然最后有校验和检查可以过滤错误帧,但会**浪费 10 个字节的解析窗口**,在高频数据流中可能导致短暂的数据更新延迟。 - -**修复建议**: 在 `s_frame_idx == 1` 时检查第二字节是否为有效帧类型 (`0x51`/`0x52`/`0x53`),不匹配则 `s_frame_idx = 0` 重新寻帧。 - ---- - -### M-2: `nav_script.c` 转向方向始终为正,不支持反向 (顺时针) 180° 转弯 - -**文件**: `nav/nav_script.c:202,229` - -```c -float target_delta = s_cfg.turn_target_angle; // 默认 PI (180度) -// ... -float turn_dir = (target_delta > 0.0f) ? 1.0f : -1.0f; -``` - -`turn_target_angle` 在 `app_tasks.c` 中始终被初始化为 `3.14159265f`(正值),所以 `turn_dir` 永远为 `1.0f`(逆时针)。如果因场地布局需要顺时针转弯,当前代码无法支持。更关键的是,**两次 180° 转弯方向相同**——第一次到端逆时针转,第二次到端又逆时针转,结果机器人回到出发方向。这可能是设计意图(转完 180° 后继续正向走),但如果走廊空间不对称,固定转向方向可能导致转弯时撞墙。 - -**修复建议**: 考虑根据当前方向或走廊几何自动选择转向方向,或至少在 `NavScriptConfig_t` 中加一个 `turn_direction` 参数。 - ---- - -### M-3: `Odom_GetSpeed()` 在临界区外读取 `s_odom.vx` 和 `s_odom.wz` - -**文件**: `Contract/robot_odom.c:122-124` - -```c -void Odom_GetSpeed(float *out_vx, float *out_wz, OdomStatus_t *out_status) -{ - if (out_vx != NULL) *out_vx = s_odom.vx; // ← 临界区外 - if (out_wz != NULL) *out_wz = s_odom.wz; // ← 临界区外 - if (out_status != NULL) { - lock_odom(); // ← 只有 status 在临界区内 - // ... - unlock_odom(); - } -} -``` - -`s_odom.vx` 和 `s_odom.wz` 是 `float` 类型,在 Cortex-M7 上 32 位对齐的 float 读写是原子的,所以单独读取不会撕裂。但 `vx` 和 `wz` 之间不是原子的——可能读到旧的 `vx` 和新的 `wz`。不过此函数当前未被任何代码调用(速度通过 `Blackboard_UpdateOdom` 传递),所以实际影响为零。 - -**修复建议**: 将 `vx/wz` 的读取也放入 `lock_odom()` 中,或标注此函数为 `@deprecated`。 - ---- - -### M-4: `SNC_CAN_SendHeartbeat()` 使用零长度数组 - -**文件**: `Can/snc_can_app.c:194` - -```c -HAL_StatusTypeDef SNC_CAN_SendHeartbeat(void) -{ - uint8_t data[0]; // ← 零长度数组,C11 标准未定义行为 - HAL_StatusTypeDef ret = snc_fdcan_add_tx_std(SNC_CAN_ID_HEARTBEAT, data, 0U); -``` - -零长度数组 `uint8_t data[0]` 在 C11 标准中是未定义行为(C99 的 flexible array member 语法是 `[]` 且只能在结构体末尾)。虽然 GCC 作为扩展支持它,且 `snc_fdcan_add_tx_std` 传入 `dlc_bytes=0` 不会实际读取 `data`,但这仍属于未定义行为。 - -**修复建议**: 改为 `uint8_t data[1] = {0};` 或直接传 `NULL`(需确认 HAL 是否接受 NULL data)。 - ---- - -### M-5: 安全状态机 (SegFsm) 在脚本覆盖模式下仍然生效,可能干扰转弯等特殊动作 - -**文件**: `app_tasks.c` navTask 流水线 Step 5-6 - -```c -/* Step 5: 控制律 */ -if (script_out.use_override) { - raw_cmd.v = script_out.override_v; // 脚本指定速度 - raw_cmd.w = script_out.override_w; -} else if (script_out.request_corridor) { - CorridorCtrl_Compute(..., &raw_cmd); -} - -/* Step 6: 段状态机 -> 安全仲裁 */ -SegFsm_Update(&raw_cmd, &obs, &corridor_state, &fsm_out); -``` - -当脚本处于 `TURN_AT_END` 阶段时,`use_override = true`,输出 `v=0, w=turn_omega`(原地转向)。但此时 EKF 因侧墙观测丢失,`conf` 可能降到 `< 0.1`,触发 `SegFsm` 进入 `E-STOP`,**强制将转向角速度归零**,导致机器人无法完成转弯。 - -虽然 `E-STOP` 有自动恢复机制(`conf >= 0.5` 时恢复),但在转弯过程中侧墙持续不可见,`conf` 不会恢复,造成**死锁**:转不了弯 → 永远看不到墙 → 永远 E-STOP。 - -**影响等级**: 实车中度风险。取决于转弯时 EKF 的 IMU 航向观测是否能维持 `conf >= 0.1`。如果 IMU 航向观测能阻止 `conf` 跌破阈值,则不会触发。但这是一个脆弱的依赖。 - -**修复建议**: 在 `SegFsm_Update()` 中增加一个 bypass 标志,当脚本处于 `use_override` 模式时跳过 E-STOP 判定;或仅在 `request_corridor` 为 true 时检查置信度。 - ---- - -### M-6: `process_complementary_laser()` 中 ATK 距离值无上限校验 - -**文件**: `preproc/corridor_preproc.c:30-73` - -```c -static bool process_complementary_laser(const SensorItem_t *stp, const SensorItem_t *atk, float *out_m) -{ - // ... - float atk_m = atk->value / 1000.0f; - // ATK 没有像 VL53 那样的量程校验 (0.02~2.0m) - // 如果 ATK 吐出异常大值 (如 65535mm),会被当作有效数据 -``` - -`process_side_laser()` 对 VL53L0X 数据做了 `[0.02m, 2.0m]` 范围校验,但 `process_complementary_laser()` 对 ATK 和 STP 数据**没有上限校验**。如果 ATK 传感器吐出异常大值(如掉线前最后一帧的乱码),这个值会被当作有效距离传递给安全状态机,可能导致**该停车时不停车**。 - -**修复建议**: 添加 ATK/STP 的量程校验,如 `atk_m > 0.0f && atk_m <= 8.0f` (ATK 标称量程 4m,留双倍余量)。 - ---- - -## 🟡 低优先级 / 代码质量问题 - -### L-1: `PARAM_IMU_YAW_OFFSET` 声明但未使用 - -**文件**: `robot_params.h:100` - -```c -#define PARAM_IMU_YAW_OFFSET 0.0f // 声明了但代码中未使用 -``` - -HANDOFF.md CAL-4 已标注此问题。如果 IMU 安装有固定偏角,此参数应在 `HWT101_Process()` 或 `corridor_filter.c` 中使用。当前为死代码。 - ---- - -### L-2: `corridor_filter.c` 中 `s_imu_yaw_ref_set` 在 Reset/Init 时未重置 - -**文件**: `est/corridor_filter.c:23-24` - -```c -static float s_imu_yaw_ref_rad = 0.0f; -static bool s_imu_yaw_ref_set = false; -``` - -`CorridorFilter_Init()` 不会重置 `s_imu_yaw_ref_set`。如果比赛中途调用 `NavScript_Reset()` → `CorridorFilter_Init()` 重新初始化,旧的 `s_imu_yaw_ref_rad` 会保留,导致 IMU 航向观测使用过时的参考值。 - -**修复建议**: 在 `CorridorFilter_Init()` 末尾添加: -```c -s_imu_yaw_ref_rad = 0.0f; -s_imu_yaw_ref_set = false; -``` - ---- - -### L-3: `retarget.c` 中 `_write()` 的忙等循环可能阻塞调用任务 - -**文件**: `retarget.c:44-64` - -```c -int _write(int file, char *ptr, int len) -{ - while (1) { - result = CDC_Transmit_FS((uint8_t *)ptr, (uint16_t)len); - if (result == USBD_OK) return len; - if ((HAL_GetTick() - start_tick) > 20U) return 0; - if (osKernelGetState() == osKernelRunning) osDelay(1); - } -} -``` - -如果 USB CDC 端口忙碌(Host 未连接或 buffer 满),`printf` 会阻塞当前任务最多 20ms。对于 `navTask`(20ms 周期)和 `canTxTask`(20ms 周期),一次 `printf` 阻塞就可能导致**整个控制周期跳过**。当前 `App_PrintStatus()` 已被注释掉,但如果未来取消注释或在其他任务中添加 `printf`,可能造成问题。 - -**修复建议**: 在实时任务中避免使用 `printf`,或将 `_write` 改为非阻塞(丢弃模式)。 - ---- - -### L-4: 多个模块重复定义 `clampf()` 静态内联函数 - -**文件**: -- `est/corridor_ekf.c:42` -- `nav/corridor_ctrl.c:12` -- `nav/nav_script.c:34` -- `nav/segment_fsm.c:12` - -四个文件各自定义了相同的 `static inline float clampf()`。虽然由于 `static` 链接属性不会导致链接错误,但违反 DRY 原则。 - -**修复建议**: 提取到公共头文件 `robot_params.h` 或新建 `utils.h`。 - ---- - -### L-5: `CorridorObs_t.valid_mask` 类型为 `uint8_t` 但掩码使用 bit 0-5 共 6 位 - -**文件**: `preproc/corridor_msgs.h:31` 和 `corridor_preproc.h:10-15` - -当前 6 个掩码位刚好在 `uint8_t` 范围内(最大 bit 5 = 0x20),但余量很小。如果未来添加更多传感器(如第二组 VL53),很容易溢出。不紧急但值得注意。 - ---- - -### L-6: `vl53_board.c:84` 注释与实际值不一致 - -```c -/* 初始化卡尔曼滤波器:默认 Q=1.0, R=9.5 */ // ← 注释说 Q=1.0, R=9.5 -vl53_kalman_init(&board->kf[i], 10.0f, 14.1f); // ← 实际值 Q=10.0, R=14.1 -``` - -注释是旧版残留,与当前代码不符。 - ---- - -### L-7: `nav_script.c:285` 使用 `exit_start_s == 0.0f` 判断是否已触发,但 `s` 初始值就是 0 - -```c -if (s_internal.exit_start_s == 0.0f) { - s_internal.exit_start_s = state->s; -} -``` - -如果恰好在 `state->s ≈ 0.0` 时进入 EXIT 阶段(理论上不会,因为已经往返走过垄沟),`exit_start_s` 会被设为 0,然后下次循环 `== 0.0f` 再次为 true,重复赋值但不会出错(`state->s` 每次都差不多)。实际上因为 `memset(&s_internal, 0, ...)` 已将其初始化为 0.0,如果 EXIT 阶段被跳过再重入,可能出现意外行为。 - -**修复建议**: 使用 `bool exit_triggered` 标志代替浮点数零值判断。 - ---- - -## 架构设计审查 - -### 优点 - -1. **分层清晰**: 传感器驱动 → 黑板 → 预处理 → EKF → 控制 → 安全 → 指令槽,每层职责明确。 -2. **线程安全设计合理**: 黑板的 `taskENTER_CRITICAL` + snapshot 模式有效防止了数据撕裂。 -3. **传感器互补融合策略** (`process_complementary_laser`): STP+ATK 的互补逻辑考虑了盲区、单体故障、保守防撞等多种场景,设计周到。 -4. **EKF 实现质量高**: 鲁棒 χ² 检验、分级观测更新(1/2/3 DOF)、协方差保护等机制完备。BUG-7(卡尔曼增益矩阵乘法)的修复正确。 -5. **参数集中管理**: `robot_params.h` 作为唯一调参入口,大部分参数已正确引用(除 S-1 遗漏)。 -6. **里程计累加器设计** (BUG-8 修复): ISR 累加 + 原子取走清零的设计有效解决了漏积分/重复积分问题。 - -### 可改进方向 - -1. **缺少 Watchdog**: 系统没有硬件看门狗 (IWDG/WWDG)。如果任何任务死锁或 HardFault,MCU 将永久挂起而不会自动重启。建议在空闲任务中喂看门狗。 -2. **缺少运行时错误日志**: 当前的错误处理主要是"静默忽略"或"返回零值"。建议增加一个轻量级错误计数器或环形日志 buffer,方便赛后分析。 -3. **EKF 和安全状态机没有联动**: 如 M-5 所述,脚本覆盖模式下安全状态机可能干扰正常流程。建议在 `SegFsmOutput_t` 中增加 bypass 机制。 -4. **`laserTestTask` 的 `osDelay(50)` 不精确**: 使用 `osDelay` 而非 `osDelayUntil`,任务执行时间会累加到周期中,导致实际周期 > 50ms。对于激光数据更新频率有影响。 - ---- - -## 已修复 BUG 验证 - -| HANDOFF 编号 | 修复内容 | 验证结果 | -|-------------|---------|---------| -| BUG-1 | IMU wz deg→rad 转换 | ✅ `app_tasks.c:305` 使用 `PARAM_DEG2RAD()` | -| BUG-2 | EKF Q/R/P0 从 params 读取 | ✅ `corridor_filter.c:50-66` 使用 `PARAM_EKF_*` | -| BUG-3 | `SegFsm_Start()` 调用 | ✅ `app_tasks.c:382` | -| BUG-4 | BACKWARD 段使用 d_front | ✅ `nav_script.c:254` | -| BUG-5 | 超时使用配置参数 | ✅ `nav_script.c:157` | -| BUG-6 | EXIT 速度独立参数 | ✅ `nav_script.c:273` 使用 `s_cfg.exit_v` | -| BUG-7 | 完整矩阵乘法 K=PHT*S_inv | ✅ `corridor_ekf.c:576-607` 两步乘法 | -| BUG-8 | 里程计累加器模式 | ✅ `snc_can_app.c` ISR 累加 + `ConsumeOdomDelta` 原子取走 | -| BUG-9 | IMU yaw unwrap + 连续角度 | ✅ `hwt101.c` unwrap 逻辑 + `nav_script.c` 使用 IMU yaw | -| Q-1~Q-7 | 各项代码质量修复 | ✅ 全部验证通过 | - ---- - -## 修复优先级建议 - -| 优先级 | 编号 | 预估工时 | -|--------|------|---------| -| 立即修复 | S-4 (pack 对齐) | 5 分钟 | -| 立即修复 | S-1 (VL53 KF 参数) | 5 分钟 | -| 赛前修复 | M-5 (安全 FSM bypass) | 30 分钟 | -| 赛前修复 | M-6 (ATK 量程校验) | 10 分钟 | -| 赛前修复 | S-2 (快照线程安全) | 15 分钟 | -| 赛前修复 | L-2 (IMU ref 重置) | 5 分钟 | -| 确认配置 | S-3 (CAN 中断优先级) | 10 分钟 | -| 建议改进 | 其余所有 | 按需 | - ---- - -> **审查结论**: 项目整体质量良好,架构设计规范,历史 BUG 修复彻底。上述 S-4 和 S-1 建议在下次烧录前立即修复;M-5 (安全状态机与脚本冲突) 是实车测试中最可能暴露的问题,建议优先验证。 diff --git a/HANDOFF.md b/HANDOFF.md deleted file mode 100644 index 25f55c5..0000000 --- a/HANDOFF.md +++ /dev/null @@ -1,773 +0,0 @@ -# ARES 项目交接文档 - -> **最后更新**: 2025 年 -> **项目性质**: B类"马铃薯捡拾机器人竞技"走廊导航系统 -> **本文目标**: 让任何人 (人类或 AI) 能在 30 分钟内理解整个项目并开始工作 - ---- - -## 目录 - -1. [一句话概述](#1-一句话概述) -2. [比赛规则速览](#2-比赛规则速览) -3. [硬件架构](#3-硬件架构) -4. [软件架构总览](#4-软件架构总览) -5. [代码目录结构](#5-代码目录结构) -6. [数据流水线 (核心)](#6-数据流水线-核心) -7. [各模块详解](#7-各模块详解) -8. [FreeRTOS 任务一览](#8-freertos-任务一览) -9. [CAN 通信协议](#9-can-通信协议) -10. [EKF 算法详解](#10-ekf-算法详解) -11. [控制器与安全层](#11-控制器与安全层) -12. [比赛流程状态机](#12-比赛流程状态机) -13. [全部可调参数](#13-全部可调参数) -14. [已知问题与待办](#14-已知问题与待办) -15. [构建与烧录](#15-构建与烧录) -16. [实车调试流程](#16-实车调试流程) -17. [文件快速索引](#17-文件快速索引) - ---- - -## 1. 一句话概述 - -一个运行在 **STM32H743 (FreeRTOS)** 上的走廊跟踪导航系统——通过 **4 个 VL53L0X 侧向测距** 做横向/航向定位(鲁棒 EKF),**4 个前后激光** 做防撞和到端检测,PD 控制器纠偏,安全状态机兜底,最终通过 **CAN 总线** 将速度指令发给 STM32F407 底盘控制器。 - ---- - -## 2. 比赛规则速览 - -| 项目 | 规格 | -|------|------| -| 场地尺寸 | 390 cm × 300 cm | -| 垄沟(走廊)宽度 | **40 cm**(允许 ±5% 误差) | -| 田垄数量 | 5 条 | -| 垄间模式需遍历 | **6 条垄沟** | -| 机器人尺寸 | **20 cm × 20 cm**(含外壳) | -| 驱动方式 | 四轮差速 | -| 比赛时间 | 5 分钟 | -| 任务 | 在走廊中往返行驶,捡拾目标物 | - -**关键约束**: 走廊 40cm - 车体 20cm = 每边仅 **10cm 余量**。1cm 的传感器偏差就是 10% 的误差。 - -### 2.1 赛道拓扑理解(垄间模式) - -本项目当前最相关的正式比赛模式是 **垄间作业模式**。 - -#### 赛道几何 - -- 整个比赛场地尺寸为 `390cm × 300cm` -- 场地内部共有 **5 条田垄** -- 每条田垄:长 `220cm`、宽 `30cm`、高 `12cm` -- 围栏与田垄之间、以及相邻田垄之间,均形成宽 `40cm` 的可通行垄沟 -- 场地仅有 **1 个出入口**,宽 `40cm` -- 出入口外侧紧邻 **比赛启动区**,尺寸 `40cm × 100cm` - -#### 为什么是 6 条垄沟,不是 5 条 - -虽然场地内只有 **5 条田垄**,但在垄间模式下,机器人实际需要遍历的是 **6 条垄沟**: - -1. 最左侧围栏与第 1 条田垄之间的垄沟 -2. 第 1 条田垄与第 2 条田垄之间的垄沟 -3. 第 2 条田垄与第 3 条田垄之间的垄沟 -4. 第 3 条田垄与第 4 条田垄之间的垄沟 -5. 第 4 条田垄与第 5 条田垄之间的垄沟 -6. 第 5 条田垄与最右侧围栏之间的垄沟 - -也就是说: - -- **田垄数 = 5** -- **垄间可通行垄沟数 = 6** - -这是赛道理解里最容易搞错的地方。若只按“5 条走廊”建模,会与正式比赛要求不一致。 - -#### 垄间模式下的导航任务本质 - -在垄间模式下,导航任务不是“单条走廊往返”,而是: - -1. 从启动区进入场地 -2. 进入某一条垄沟 -3. 沿垄沟稳定行驶并完成作业 -4. 到达端部后完成转向和换沟 -5. 依次遍历 **全部 6 条垄沟** -6. 最终从唯一出入口驶离场地 -7. 自主停在启动区内 - -从导航角度看,赛道是一个 **6 段平行窄走廊 + 端部换沟动作 + 单出入口回停** 的组合问题。 - -#### 对导航系统的直接要求 - -- **窄走廊居中跟踪** - 走廊宽 `40cm`,若车体宽 `20cm`,理论左右余量各仅 `10cm` -- **到端检测** - 能识别走到垄沟尽头,避免撞围栏 -- **端部转向** - 在垄沟末端稳定完成姿态调整 -- **换沟** - 从当前垄沟切换到相邻垄沟,而不是原地掉头后回到同一条垄沟 -- **赛道级状态机** - 知道当前是第几条垄沟、下一条目标是哪条、何时结束遍历 -- **最终退出与停区** - 驶离场地后必须自主停在启动区,否则可能判 0 分 - -#### 当前项目与赛道要求的关系 - -当前 ARES 项目已经具备: - -- 单条走廊内的相对定位 -- 走廊跟踪控制 -- 到端检测 -- 原地转向 -- 安全停车与防撞 - -但当前脚本状态机更接近:进入一条走廊、沿走廊前进、到端后转向、再走一趟、然后退出。 - -它更像 **单垄沟闭环验证系统**,还不是完整的 **6 垄沟遍历赛道导航系统**。 - -后续若要适配正式比赛,重点不是重写 EKF,而是补上: - -- 多垄沟遍历状态机 -- 端部换沟策略 -- 最终出场与启动区停车逻辑 - ---- - -## 3. 硬件架构 - -### 3.1 双 MCU 体系 - -``` -┌─────────────────────────────────┐ CAN Bus ┌─────────────────────────┐ -│ STM32H743 (上位机/主控) │ ◄──────────────► │ STM32F407 (底盘控制器) │ -│ 480MHz Cortex-M7, DP-FPU │ 0x100 TX │ LADRC 电机控制 │ -│ FreeRTOS + 传感器 + 导航算法 │ 0x181/200 RX │ 四路编码器 + 四路电机 │ -└─────────────────────────────────┘ └─────────────────────────┘ -``` - -### 3.2 传感器清单 - -| 传感器 | 数量 | 用途 | 接口 | 量程 | -|--------|------|------|------|------| -| **VL53L0X** ToF | 4 (左前/左后/右前/右后) | 侧向墙壁测距,走廊跟踪 | I2C1 + I2C2 | 2cm ~ 2m | -| **STP-23L** 激光 | 2 (前/后) | 远距离测距,到端检测 | UART2 / UART4 (230400bps) | 7cm ~ 7.5m | -| **ATK-MS53L1M** 激光 | 2 (前/后) | 近距离补盲 (填 STP 的 7cm 盲区) | UART3 / UART6 (115200bps) | ~4m | -| **HWT101** IMU | 1 | 单轴陀螺仪 (航向角速度 wz) | UART7 | ±2000°/s | - -### 3.3 VL53L0X 接线 - -``` -左侧 (I2C2): 右侧 (I2C1): - 左前 LF: XSHUT=PB1, 地址=0x62 右前 RF: XSHUT=PD13, 地址=0x56 - 左后 LR: XSHUT=PC5, 地址=0x64 右后 RR: XSHUT=PD14, 地址=0x58 -``` - -### 3.4 其他 GPIO - -| 引脚 | 功能 | -|------|------| -| PE3 | CAN 活动 LED (100ms 翻转) | - ---- - -## 4. 软件架构总览 - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ FreeRTOS 任务层 │ -│ canTxTask monitorTask navTask laserTestTask vl53Task imuTask │ -│ (20ms) (100ms) (20ms) (50ms) (100ms) (10ms) │ -└──────┬──────────┬──────────┬──────────┬───────────────┬──────────┬─────────┘ - │ │ │ │ │ │ - │ CmdSlot │ │ Blackboard (全局传感器数据中心) │ - │ Pop │ │ taskENTER_CRITICAL 保护 │ - ▼ ▼ ▼ │ - ┌─────────┐ ┌────────┐ ┌───────────────────────────────────┐ │ - │CAN 0x100│ │Odom │ │ 导航流水线 (navTask, 20ms) │ │ - │→ 底盘 │ │积分 │ │ Preproc → EKF → Script │ │ - │ │ │→黑板 │ │ → Ctrl → SafetyFSM → CmdSlot │ │ - └─────────┘ └────────┘ └───────────────────────────────────┘ │ - │ - ┌───────────────────────────────────────────────────────────┘ - │ - 各传感器驱动:hwt101.c / vl53_board.c / laser_manager.c - → Blackboard_Update*() -``` - ---- - -## 5. 代码目录结构 - -``` -D:\ARES\ -├── App/ ← 【所有业务代码在这里】 -│ ├── robot_params.h ← ★ 全局参数配置中心 (唯一的调参入口) -│ ├── app_tasks.c/.h ← 所有 FreeRTOS 任务实现 + 系统初始化 -│ ├── retarget.c/.h ← printf → USB CDC 重定向 -│ │ -│ ├── Can/ -│ │ └── snc_can_app.c/.h ← CAN 协议层 (编解码/CRC8/滤波器)【已冻结,勿动】 -│ │ -│ ├── Contract/ ← 模块间数据契约 -│ │ ├── robot_blackboard.c/.h ← 全局传感器数据黑板 (线程安全) -│ │ ├── robot_odom.c/.h ← 差速里程计积分 -│ │ ├── robot_cmd_slot.c/.h ← 导航→CAN 指令传递槽 -│ │ └── chassis_can_msg.h ← CAN 帧结构体定义 -│ │ -│ ├── est/ ← 状态估计 -│ │ ├── corridor_ekf.c/.h ← ★ 鲁棒 EKF 核心 (3 状态) -│ │ └── corridor_filter.c/.h ← EKF 的兼容包装层 -│ │ -│ ├── nav/ ← 导航与控制 -│ │ ├── corridor_ctrl.c/.h ← PD 走廊控制器 -│ │ ├── segment_fsm.c/.h ← 安全状态机 (防撞/急停) -│ │ └── nav_script.c/.h ← 比赛流程编排 -│ │ -│ ├── preproc/ ← 传感器预处理 -│ │ ├── corridor_preproc.c/.h ← 数据清洗 + 互补融合 -│ │ └── corridor_msgs.h ← 所有模块间消息结构体 -│ │ -│ ├── IMU/ -│ │ └── hwt101.c/.h ← HWT101 IMU 驱动 (UART DMA) -│ │ -│ ├── laser/ -│ │ └── laser_manager.c/.h ← 前后激光驱动 (STP+ATK, UART DMA) -│ │ -│ └── VL53L0X_API/ -│ ├── platform/ -│ │ ├── vl53_board.c/.h ← 多传感器管理 + 卡尔曼滤波 -│ │ └── vl53l0x_platform.c/.h ← ST API HAL 适配 -│ └── core/ ← ST 官方 VL53L0X API (不修改) -│ -├── Core/ ← CubeMX 生成的 HAL 初始化代码 -├── Drivers/ ← STM32H7 HAL 驱动 -├── Middlewares/ ← FreeRTOS + USB -├── USB_DEVICE/ ← CDC 虚拟串口 -├── ARES.ioc ← CubeMX 工程文件 -├── CMakeLists.txt ← 构建入口 -└── STM32H743XX_FLASH.ld ← 链接脚本 -``` - ---- - -## 6. 数据流水线 (核心) - -这是整个系统的心脏,运行在 `navTask` 中,**每 20ms 执行一次**: - -``` -Step 1: Blackboard_GetSnapshot(&board) 拍摄传感器快照 (无撕裂) - │ -Step 2: CorridorPreproc_ExtractObs() 数据清洗 - │ • VL53L0X: mm→m, 范围校验 (0.02~2.0m) - │ • STP+ATK: 互补融合 (ATK 填 STP 的 7cm 盲区) - │ • 前后激光偏移补偿 (d -= PARAM_FRONT_LASER_OFFSET) - │ → 输出: CorridorObs_t {d_lf, d_lr, d_rf, d_rr, d_front, d_back, valid_mask} - │ -Step 3: CorridorFilter_Update() EKF 状态估计 - │ → Predict(odom_vx, imu_wz, dt) 预测步 (IMU wz + 里程计) - │ → Update(obs) 观测步 (VL53 侧向测距) - │ → UpdateIMUYaw(yaw_cont, ref) IMU 航向观测 (独立 1DOF 更新) - │ → 输出: CorridorState_t {e_y, e_th, s, conf} - │ -Step 4: NavScript_Update() 比赛流程编排 - │ → 决定当前阶段: 入口对准/走廊跟踪/转向/退出 - │ → 180° 转弯判定使用 IMU 连续 yaw (非 EKF e_th) - │ → 输出: NavScriptOutput_t {use_override, override_v/w, request_corridor} - │ -Step 5: CorridorCtrl_Compute() PD 控制律 (仅在走廊跟踪模式) - │ → w = kp_theta·e_th + kd_theta·(-wz) + kp_y·e_y - │ → v = v_cruise × (1 - 0.4 × |w/w_max|) - │ → 输出: RawCmd_t {v, w} - │ -Step 6: SegFsm_Update() 安全仲裁 - │ → 前方太近? → 减速/停车 - │ → 置信度太低? → 紧急停车 - │ → 输出: SegFsmOutput_t {safe_v, safe_w} - │ -Step 7: CmdSlot_Push(safe_v, safe_w) 推入指令槽 → canTxTask 取走 -``` - ---- - -## 7. 各模块详解 - -### 7.1 传感器驱动层 - -#### VL53L0X 侧向测距 (`vl53_board.c`) -- 上电时所有 XSHUT 拉低,逐个拉高分配 I2C 地址 -- 测距预算 100ms (100000μs),连续测距模式 -- 每个传感器读数经过独立的 **1D 卡尔曼滤波** (Q=10.0, R=14.1) -- 输出 `Vl53BoardSnapshot_t` → `Blackboard_UpdateVl53()` - -#### 前后激光测距 (`laser_manager.c`) -- DMA 环形缓冲区轮询,内部自有 FreeRTOS 任务 `LaserTsk` (10ms) -- **STP-23L**: 二进制协议,含校验和;3 帧中值滤波去尖刺 -- **ATK-MS53L1M**: ASCII 文本 `"d: 1234\r\n"`;3 帧中值滤波 -- 互补融合策略: - - ATK 距离 < 8cm 时无条件信任 ATK (STP 盲区) - - STP 卡在 7cm 时用 ATK - - 两者都活着取更近的 (保守防撞) - - STP 独活但在盲区 → 报失效 (宁可急停也不信假数据) - -#### IMU (`hwt101.c`) -- UART DMA 11 字节二进制帧 -- 输出: `yaw` (°)、`yaw_continuous` (°) 和 `wz` (°/s) -- `yaw`: 原始偏航角,范围 [-180°, +180°),跨界时跳变 -- `yaw_continuous`: **unwrap 后的连续偏航角**,消除 ±180° 跳变,可直接做差计算任意转角 -- 注意: **输出单位是°/s,不是 rad/s** -- `HWT101_ZeroYaw()` 会同时重置 unwrap 状态 - -### 7.2 数据契约层 - -#### 黑板 (`robot_blackboard.c`) -- 全局结构体 `g_blackboard`,所有传感器数据汇聚于此 -- 所有读写都在 `taskENTER_CRITICAL()` 临界区内 -- 消费者调用 `Blackboard_GetSnapshot()` 获取无撕裂快照 -- IMU 字段: `imu_yaw` (原始°)、`imu_yaw_continuous` (连续°)、`imu_wz` (°/s) - -#### 里程计 (`robot_odom.c`) -- 从 CAN 0x200 获取四轮编码器增量,经 **ISR 侧累加器** 汇聚后由 monitorTask 一次性取走积分 -- 消费链路(BUG-8 修复后): - ``` - CAN Rx ISR → snc_parse_odom_delta() 每帧累加到 odom_accum(不覆盖) - ↓ - monitorTask → SNC_CAN_ConsumeOdomDelta() 原子取走累计值并清零 - ↓ - Odom_Update() 仅在有新帧时调用(杜绝重复积分) - ``` -- 差速运动学: - ``` - v_left = (fl_delta + rl_delta) / 2 × (π × 0.060 / 500) / dt - v_right = (fr_delta + rr_delta) / 2 × (π × 0.060 / 500) / dt - vx = (v_left + v_right) / 2 - wz = (v_right - v_left) / 0.140 - ``` -- 3 帧连续零增量 → 强制 vx=wz=0 (静止检测) - -#### 指令槽 (`robot_cmd_slot.c`) -- 单槽无锁设计,`CmdSlot_Push()` 写入,`CmdSlot_Pop()` 读取 -- 超过 100ms 未更新 → canTxTask 自动发零速指令 (看门狗) - -### 7.3 估计层 - -详见 [第10节 EKF 算法详解](#10-ekf-算法详解)。 - -### 7.4 控制层 - -详见 [第11节 控制器与安全层](#11-控制器与安全层)。 - -### 7.5 导航层 - -详见 [第12节 比赛流程状态机](#12-比赛流程状态机)。 - ---- - -## 8. FreeRTOS 任务一览 - -| 任务名 | 周期 | 优先级 | 栈大小 | 职责 | -|--------|------|--------|--------|------| -| `canTxTask` | 20ms | AboveNormal (28) | 2048B | CAN 0x100 硬实时发送;指令槽看门狗 | -| `navTask` | 20ms | AboveNormal (28) | 4096B | 完整导航流水线 (7步) | -| `LaserTsk` (内部) | 10ms | AboveNormal (28) | 4096B | 4路 UART DMA 解析 | -| `monitorTask` | 100ms | Normal (24) | 4096B | CAN 健康监控;里程计更新 | -| `laserTestTask` | 50ms | Normal (24) | 16384B | 激光轮询 + 推送黑板 | -| `vl53Task` | 100ms | Normal (24) | 4096B | VL53L0X 读取 + 推送黑板 | -| `imuTask` | 10ms | BelowNormal (20) | 2048B | IMU 解析 + 推送黑板 | -| `defaultTask` | — | Normal (24) | 512B | USB CDC 初始化;空闲循环 | - -**全局配置**: Tick 频率 1000Hz, 堆 65536 字节, 最大优先级 56 - ---- - -## 9. CAN 通信协议 - -### 9.1 TX: H743 → F407 - -#### 0x100 — 速度指令 (每 20ms 发送) - -| 字节 | 字段 | 类型 | 编码 | -|------|------|------|------| -| 0-1 | vx | int16 LE | vx (m/s) × 1000 | -| 2-3 | wz | int16 LE | wz (rad/s) × 1000 | -| 4 | ctrl_flags | uint8 | 控制标志位 | -| 5 | reserved | uint8 | 固定 0 | -| 6 | rolling_counter | uint8 | 单调递增 | -| 7 | crc8 | uint8 | CRC8-SAE-J1850 (bytes[0..6]) | - -**硬性约束**: 必须每 ≤150ms 发一次,否则底盘进入 `SAFE_FAULT`。即使停车也要发 vx=0, wz=0。 - -#### 0x080 — 心跳 (每 20ms, DLC=0) - -### 9.2 RX: F407 → H743 - -#### 0x181 — 底盘状态 (20ms) - -| 字节 | 字段 | -|------|------| -| 0 | system_state: 0=BOOTING, 1=OPERATIONAL, 2=SAFE_FAULT | -| 1 | system_health: 0=OK, 1=WARNING, 2=FAULT | -| 2-5 | diag_bits (uint32 LE): 通信超时/CAN BUS OFF/电机堵转等 | -| 6 | cmd_age_10ms: 上次有效指令距今 (×10ms) | -| 7 | status_counter | - -#### 0x200 — 里程计增量 (~60ms) - -| 字节 | 字段 | -|------|------| -| 0-1 | fl_delta_ticks (int16 LE) — 左前轮编码器增量 | -| 2-3 | rl_delta_ticks (int16 LE) — 左后轮 | -| 4-5 | fr_delta_ticks (int16 LE) — 右前轮 | -| 6-7 | rr_delta_ticks (int16 LE) — 右后轮 | - -#### 0x184 — 通信诊断 (100ms) - -CRC 错误计数、计数器拒绝计数、CAN 丢包等统计信息。 - ---- - -## 10. EKF 算法详解 - -### 状态向量 - -``` -x = [e_y, e_th, s]ᵀ -``` - -| 状态 | 含义 | 单位 | -|------|------|------| -| `e_y` | 车体中心相对走廊中心线的横向偏差 | m (左偏为正) | -| `e_th` | 车头相对走廊方向的航向偏差 | rad (左偏为正) | -| `s` | 沿走廊行驶里程 | m | - -### 预测步 (每 20ms) - -``` -输入: odom_vx (m/s), imu_wz (rad/s), dt (s) - -e_y_new = e_y + vx × sin(e_th) × dt -e_th_new = e_th + wz × dt -s_new = s + vx × cos(e_th) × dt - -雅可比矩阵 F: - [1, vx·cos(e_th)·dt, 0] - [0, 1, 0] - [0, -vx·sin(e_th)·dt, 1] - -P_pred = F·P·Fᵀ + Q -``` - -### 观测步 - -``` -d_center = (W - Rw) / 2 + inset - = (0.40 - 0.20) / 2 + 0 = 0.10m (车居中时传感器到墙的距离) - -左侧观测: - z_ey = d_center - (d_lf + d_lr)/2 横向偏差 - z_eth_L = atan2(d_lr - d_lf, L_s) 航向偏差 - -右侧观测: - z_ey = (d_rf + d_rr)/2 - d_center 横向偏差 - z_eth_R = atan2(d_rf - d_rr, L_s) 航向偏差 - -双侧有效时: z_ey 取两侧平均 = (d_right - d_left) / 2 - → d_center 被消掉,结果只取决于左右差值 - -单侧退化时: z_ey = d_center - d_one_side - → d_center 的准确性至关重要! - -IMU 航向观测 (侧墙更新之后独立执行): - z_eth_imu = (imu_yaw_continuous - yaw_ref) × DEG2RAD - yaw_ref 在 EKF 置信度 ≥ 0.5 时首次锁定 - 使用 1DOF 标量 EKF 更新,R 值 (PARAM_EKF_R_ETH_IMU) 远大于侧墙 R - → 侧墙有效时 IMU 影响小;侧墙丢失时 IMU 提供航向约束 -``` - -### 鲁棒拒绝 - -每个观测独立做 **χ² 马氏距离检验**: -- 1 自由度门限 3.84 (95% 置信度) -- 超过门限的观测被标记为异常并跳过更新 - -### 置信度计算 - -``` -conf = f(协方差迹) × 侧面因子 × (1 - 拒绝比例 × 0.5) - 侧面因子: 双侧=1.0, 单侧=0.7 - 两侧全失效: 协方差膨胀,conf 趋向 0 → 触发 E-STOP -``` - ---- - -## 11. 控制器与安全层 - -### 11.1 PD 走廊控制器 - -``` -w_cmd = kp_theta × e_th + kd_theta × (-imu_wz) + kp_y × e_y - ─────────────── ───────────────────── ──────────── - 航向比例纠偏 航向微分阻尼(用IMU) 横向比例纠偏 - -w_cmd = clamp(w_cmd, ±1.5 rad/s) - -v_cmd = v_cruise × (1 - 0.4 × |w/w_max|) 弯道减速 -v_cmd = clamp(v_cmd, 0, 0.3 m/s) - -置信度保护: - conf < 0.3 → v × 0.3 (三折) - conf < 0.6 → v × 0.7 (七折) -``` - -**参数**: kp_theta=2.0, kd_theta=0.1, kp_y=3.0, v_cruise=0.15m/s - -### 11.2 安全状态机 (`segment_fsm.c`) - -``` - conf < 0.1 - ┌──────────────────┐ - ▼ │ - ┌──────┐ Start ┌──────────┐ │ d_front ≤ 0.25m ┌──────────┐ - │ IDLE ├────────►│ CORRIDOR ├──┴──────────────────►│ APPROACH │ - └──────┘ └────┬─────┘ ◄────────────────── └────┬─────┘ - │ d_front > 0.25m │ - │ d_front ≤ 0.08m - conf ≥ 0.5 │ - ┌────┴─────┐ ┌──────▼─────┐ - │ E-STOP │ │ STOP │ - │ v=0,w=0 │ │ v=0,w=0 │ - └──────────┘ └────────────┘ -``` - -| 状态 | 行为 | -|------|------| -| **CORRIDOR** | 放行控制器输出 | -| **APPROACH** | 线性减速: v 从 raw_v 衰减至 0.05m/s (d 从 25cm→8cm) | -| **STOP** | 强制零速 | -| **E-STOP** | 强制零速;conf ≥ 0.5 时自动恢复 | - ---- - -## 12. 比赛流程状态机 - -> 注意:以下状态机描述的是 **当前固件已实现的单垄沟往返流程**,用于验证走廊跟踪、到端检测、转向与退出链路。 -> 它 **不等价于** 正式比赛垄间模式要求的“遍历全部 6 条垄沟”的完整赛道级导航状态机。 - -``` -IDLE → ENTRY_ALIGN → CORRIDOR_FORWARD → TURN_AT_END → CORRIDOR_BACKWARD - ↓ - (pass_count ≥ 2) - ↓ - EXIT → FINISHED -``` - -| 阶段 | 触发条件 | 行为 | 退出条件 | -|------|----------|------|----------| -| **IDLE** | 初始状态 | 零速 | `NavScript_Start()` | -| **ENTRY_ALIGN** | Start() | 慢速前进 0.08m/s,等侧向雷达找到墙 | 双侧有效 + conf≥0.8;或超时 30s | -| **CORRIDOR_FWD** | 入口对准完成 | 走廊控制器跟踪 | d_front ≤ 0.10m (到端) | -| **TURN_AT_END** | 到端 | 原地转 180° (1.0 rad/s, 接近时减速);使用 IMU 连续 yaw 判定转角 | 转角 ≥ π-0.1 rad | -| **CORRIDOR_BWD** | 第1次转完 | 走廊控制器跟踪 | d_back ≤ 0.10m (到端) | -| **EXIT** | 第2次转完 | 0.5m/s 直线冲出 | 双侧 VL53 全丢 + 行驶 ≥ 2m | -| **FINISHED** | 冲出完成 | 零速停车 | 终态 | - ---- - -## 13. 全部可调参数 - -所有参数集中在 **`App/robot_params.h`** 中,修改后需重新编译烧录。 - -### P0 — 几何参数 (必须实测) - -| 参数名 | 当前值 | 单位 | 说明 | -|--------|--------|------|------| -| `PARAM_ROBOT_WIDTH` | **0.200** | m | 车体外轮廓宽度 | -| `PARAM_ROBOT_LENGTH` | **0.200** | m | 车体外轮廓长度 | -| `PARAM_WHEEL_DIAMETER` | **0.060** | m | 驱动轮外径 | -| `PARAM_WHEEL_TRACK` | **0.140** | m | 左右轮中心距 | -| `PARAM_SENSOR_BASE_LENGTH` | **0.120** | m | 同侧前后 VL53 间距 | -| `PARAM_CORRIDOR_WIDTH` | **0.40** | m | 走廊宽度 | -| `PARAM_FRONT_LASER_OFFSET` | **0.0** | m | 前激光到车头前缘的内缩距离 | -| `PARAM_REAR_LASER_OFFSET` | **0.0** | m | 后激光到车尾后缘的内缩距离 | -| `PARAM_VL53_SIDE_INSET` | **0.0** | m | 侧向 VL53 到车体外壳的内缩距离 | -| `PARAM_ENCODER_CPR` | **500** | — | 编码器每转脉冲数 | - -### P2 — EKF 滤波器 - -| 参数名 | 当前值 | 说明 | -|--------|--------|------| -| `PARAM_EKF_Q_EY` | **0.01** | 横向过程噪声 (越大越信观测) | -| `PARAM_EKF_Q_ETH` | **0.001** | 航向过程噪声 | -| `PARAM_EKF_Q_S` | **0.1** | 里程过程噪声 | -| `PARAM_EKF_R_EY` | **0.002** | 横向观测噪声 (越大越不信雷达) | -| `PARAM_EKF_R_ETH` | **0.001** | 航向观测噪声 (侧墙) | -| `PARAM_EKF_R_ETH_IMU` | **0.01** | 航向观测噪声 (IMU yaw),远大于侧墙,用于长时约束 | -| `PARAM_EKF_P0_EY` | **0.1** | e_y 初始不确定度 | -| `PARAM_EKF_P0_ETH` | **0.1** | e_th 初始不确定度 | - -### P3 — 控制器 - -| 参数名 | 当前值 | 单位 | 说明 | -|--------|--------|------|------| -| `PARAM_CTRL_KP_THETA` | **2.0** | — | 航向比例增益 | -| `PARAM_CTRL_KD_THETA` | **0.1** | — | 航向微分增益 | -| `PARAM_CTRL_KP_Y` | **3.0** | — | 横向比例增益 | -| `PARAM_CTRL_V_CRUISE` | **0.15** | m/s | 巡航速度 | -| `PARAM_CTRL_W_MAX` | **1.5** | rad/s | 最大角速度 | -| `PARAM_CTRL_V_MAX` | **0.3** | m/s | 最大线速度 | - -### P4 — 安全与脚本 - -| 参数名 | 当前值 | 单位 | 说明 | -|--------|--------|------|------| -| `PARAM_SAFE_D_FRONT_STOP` | **0.08** | m | 前向强制停车距离 | -| `PARAM_SAFE_D_FRONT_APPROACH` | **0.25** | m | 前向减速预警距离 | -| `PARAM_SAFE_APPROACH_MIN_V` | **0.05** | m/s | 减速区最低速度 | -| `PARAM_SAFE_CONF_ESTOP` | **0.10** | — | E-Stop 置信度阈值 | -| `PARAM_SCRIPT_ENTRY_TIMEOUT` | **30000** | ms | 入口对准超时 | -| `PARAM_SCRIPT_TURN_OMEGA` | **1.0** | rad/s | 转向角速度 | -| `PARAM_SCRIPT_EXIT_RUNOUT` | **2.0** | m | 退出场地后冲距离 | - -### P5 — 传感器驱动 - -| 参数名 | 当前值 | 说明 | -|--------|--------|------| -| `PARAM_VL53_TIMING_BUDGET` | **100000** | VL53L0X 测距预算 (μs) | -| `PARAM_VL53_KALMAN_Q` | **10.0** | VL53 卡尔曼过程噪声 | -| `PARAM_VL53_KALMAN_R` | **14.1** | VL53 卡尔曼观测噪声 | -| `PARAM_IMU_YAW_OFFSET` | **0.0** | IMU 零位偏置 (rad) | - ---- - -## 14. 已知问题与待办 - -### 严重 (已全部修复 ✅) - -| # | 问题 | 状态 | 修复位置 | -|---|------|------|----------| -| **BUG-1** | IMU 输出 `wz` 单位是 **°/s**,但 EKF 预测步按 **rad/s** 使用,导致航向积分放大 57.3 倍 | ✅ 已修复 | `app_tasks.c:305` — 加了 `PARAM_DEG2RAD()` 转换 | -| **BUG-2** | `corridor_filter.c` 中 EKF 的 Q/R/P0 参数全部硬编码,修改 `robot_params.h` 中的 `PARAM_EKF_*` 不生效 | ✅ 已修复 | `corridor_filter.c:40-56` — 改为读取 `PARAM_EKF_*` 宏 | -| **BUG-3** | `AppTasks_Init()` 只调用 `SegFsm_Init()`,未调用 `SegFsm_Start()`,导致安全状态机长期处于 IDLE,输出始终为零速 | ✅ 已修复 | `app_tasks.c:382` — 补加 `SegFsm_Start()` | -| **BUG-4** | `CORRIDOR_BACKWARD` 段转 180° 后正向行驶,但到端检测错误使用 `d_back`(后向雷达),应为 `d_front` | ✅ 已修复 | `nav_script.c:CORRIDOR_BACKWARD` — 改为检查 `d_front` | -| **BUG-5** | `ENTRY_ALIGN` 段超时保护硬编码了 `30000`,`entry_align_timeout` 参数实际不生效 | ✅ 已修复 | `nav_script.c:155` — 改为 `s_cfg.entry_align_timeout` | -| **BUG-6** | `EXIT` 段退出直线速度误用角速度参数 `turn_omega * 0.5f`,调转向速度会意外影响退出速度 | ✅ 已修复 | `nav_script.h` 加 `exit_v` 字段;`nav_script.c:262` 读取它;`app_tasks.c` 传入 `PARAM_SCRIPT_EXIT_V`;`robot_params.h` 加宏 | -| **BUG-7** | EKF 卡尔曼增益计算 `K = P·H^T·S⁻¹` 只乘 `S_inv` 对角项,忽略观测间相关性,增益不正确 | ✅ 已修复 | `corridor_ekf.c:576-607` — 改为完整两步矩阵乘法:先算 `PHT = P·H^T`,再算 `K = PHT·S_inv` | -| **BUG-8** | `0x200 Odom Delta` 按"状态型最新值"消费,实为"事件型增量数据":ISR 直接覆盖旧帧导致**漏积分**(60ms帧率 vs 100ms消费,必然丢帧);monitorTask 无条件调用 `Odom_Update()` 导致**重复积分**(无新帧时同一份 delta 被积分两次) | ✅ 已修复 | `snc_can_app.h` 新增 `SNC_OdomDeltaAccum_t`;`snc_can_app.c` ISR 改为累加并实现 `SNC_CAN_ConsumeOdomDelta()` 原子取走;`app_tasks.c:monitorTask` 改用新 API,仅在有新帧时调用积分 | -| **BUG-9** | IMU `yaw` 输出范围 [-180°, +180°),跨界时跳变,且项目完全未使用 `yaw`;180° 转弯判定纯依赖 EKF `e_th` (无侧墙观测时靠 wz 积分漂移) | ✅ 已修复 | `hwt101.c` 新增 yaw unwrap → `yaw_continuous`;`robot_blackboard.h` 新增 `imu_yaw_continuous`;`nav_script.c` 转弯判定改用 IMU 连续 yaw 差值;`corridor_ekf.c` 新增 `CorridorEKF_UpdateIMUYaw()` 1DOF 标量观测更新;`corridor_filter.c` 管理 yaw_ref 参考值并在侧墙更新后注入 IMU 航向观测 | - -### 需要实车标定 - -| # | 问题 | 说明 | -|---|------|------| -| **CAL-1** | `PARAM_FRONT_LASER_OFFSET = 0.0` | 如果传感器在车体内部,停车距离会比预期偏大 | -| **CAL-2** | `PARAM_REAR_LASER_OFFSET = 0.0` | 同上 | -| **CAL-3** | `PARAM_VL53_SIDE_INSET = 0.0` | 如果传感器内缩,单侧退化时会有系统偏差 | -| **CAL-4** | `PARAM_IMU_YAW_OFFSET = 0.0` | 声明了但代码中未使用 | - -### 设计风险 / 尚未处理 - -| # | 问题 | 当前影响 | 建议方向 | -|---|------|----------|----------| -| **RISK-1** | `TURN_AT_END` 原地转向阶段与 `SegFsm` 前向防撞逻辑存在潜在冲突 | `nav_script` 在到端后会输出 `v=0, w!=0` 的原地转向命令;但 `segment_fsm` 仍按“前向距离过近 → STOP”处理,可能把转向角速度也清零,导致机器人到端后想转却被安全层按住 | 后续应为安全层引入“动作语义”或“模式感知”,区分走廊前进与原地转向;转向阶段允许 `v=0` 时保留受限 `w`,而不是沿用普通前向防撞全停策略 | - -补充说明: - -- 该问题的根因不是传感器噪声,而是 **脚本层与安全层的仲裁语义不一致** -- 侧向 VL53 在端部转向时本来也会偏离正常走廊几何,因此当前已经用 IMU `yaw_continuous` 来判定转角,这部分方向是对的 -- 真正需要补的是:**转向阶段的专用安全策略**,否则后续扩展到多垄沟遍历时,端部动作会成为卡点 - -### 代码质量 (已全部修复 ✅) - -| # | 问题 | 状态 | 修复位置 | -|---|------|------|----------| -| **Q-1** | `PARAM_CTRL_SPEED_REDUCTION` 未被控制器读取,硬编码了 `0.4f` | ✅ 已修复 | `corridor_ctrl.h` 加字段 `speed_reduction_k`;`corridor_ctrl.c:59` 读取它;`app_tasks.c` 传入 `PARAM_CTRL_SPEED_REDUCTION` | -| **Q-2** | `PARAM_SCRIPT_ENTRY_V` 未被脚本读取,硬编码了 `0.08f` | ✅ 已修复 | `nav_script.h` 加字段 `entry_align_v`;`nav_script.c:146` 读取它;`app_tasks.c` 传入 `PARAM_SCRIPT_ENTRY_V` | -| **Q-3** | `PARAM_SCRIPT_EXIT_RUNOUT` 未被脚本读取,硬编码了 `2.0f` | ✅ 已修复 | `nav_script.h` 加字段 `exit_runout_m`;`nav_script.c:275` 读取它;`app_tasks.c` 传入 `PARAM_SCRIPT_EXIT_RUNOUT` | -| **Q-4** | `PARAM_VL53_TIMING_BUDGET` 未被使用,直接传字面量 `100000` | ✅ 已修复 | `app_tasks.c:222,232` 改为传 `PARAM_VL53_TIMING_BUDGET` | -| **Q-5** | `exit_start_s` 是函数内 `static` 局部变量,`NavScript_Reset()` 无法清除它 | ✅ 已修复 | 移入 `s_internal` 结构体,`memset(&s_internal, 0, ...)` 统一清零 | -| **Q-6** | 转向角度通过 EKF 的 `e_th` 差值测量,不是绝对角度。如果 EKF 发散或走廊参照丢失,转向判断可能不准 | ✅ 已修复 | `nav_script.c` — 改用 IMU `yaw_continuous` (unwrap 后的连续偏航角) 判定转角,不再依赖 EKF `e_th` | -| **Q-7** | `g_snc_can_app` 被中断写、被任务读,没有互斥保护 (中等风险) | ✅ 部分修复 | `odom_accum` 的取走/清零已通过 `taskENTER_CRITICAL` 保护(BUG-8 修复);其余字段(status/rpm/diag)仍无保护,但读写均为原子宽度或单次赋值,风险可接受 | - ---- - -## 15. 构建与烧录 - -### 构建 - -```bash -# 确保 gcc-arm-none-eabi 在 PATH 中 -cmake --preset Debug -cmake --build build/Debug -``` - -- 输出: `build/Debug/ARES.elf` -- 工具链: `cmake/gcc-arm-none-eabi.cmake` -- C 标准: C11 -- 浮点 printf: 已开启 (`-u _printf_float`) - -### 烧录 - -使用 **STM32CubeProgrammer** 或 **OpenOCD** 烧录 `.elf` 文件到 STM32H743。 - -### 注意事项 - -- `CMakeLists.txt` 第 38 行有一个大写 `.C` 后缀 (`laser_manager.C`),在大小写敏感的文件系统上可能会构建失败 -- MPU Region 1 配置了 `0x30000000` 32KB 为非缓存区,所有 DMA 缓冲区必须放在此区域 (`.dma_buffer` section) -- USB CDC 用于 `printf` 输出 (通过 `retarget.c`) - ---- - -## 16. 实车调试流程 - -### 建议顺序 - -``` -P0: 几何参数 → 用卷尺实测,填入 robot_params.h - ↓ -P1: 里程计标定 → 直线跑 10m,对比编码器累积距离 - ↓ -P2: EKF 调优 → 从保守 Q/R 开始,观察走廊跟踪稳定性 - ↓ -P3: 控制器调参 → 先调 kp_theta/kd_theta (航向),再调 kp_y (横向) - ↓ -P4: 安全阈值 → 根据实际场地微调停车/减速距离 -``` - -### 常见问题诊断 - -| 现象 | 可能原因 | 调整方法 | -|------|----------|----------| -| 车头左右摆动 | kp_theta 过大 或 kd_theta 过小 | 减小 kp_theta 或增大 kd_theta | -| 横向纠偏太慢 | kp_y 过小 | 增大 kp_y | -| 到端刹不住 | d_front_stop 过小 或 approach 区间太短 | 增大 PARAM_SAFE_D_FRONT_STOP | -| 总是急停 | EKF 置信度低,可能是 VL53 数据不稳定 | 增大 R (降低观测信任) 或检查传感器接线 | -| EKF 发散 | Q 过小 (不信观测) 或 R 过小 (过信噪声数据) | 增大 Q 或增大 R | -| 单侧靠墙走 | PARAM_VL53_SIDE_INSET 未校准 | 实测传感器内缩距离并填入 | - ---- - -## 17. 文件快速索引 - -| 你想做什么 | 去看哪个文件 | -|-----------|-------------| -| 改任何调参数值 | `App/robot_params.h` | -| 理解系统初始化 | `App/app_tasks.c` → `AppTasks_Init()` | -| 理解导航流水线 | `App/app_tasks.c` → `AppTasks_RunNavTask_Impl()` | -| 看 EKF 数学 | `App/est/corridor_ekf.c` | -| 看控制律 | `App/nav/corridor_ctrl.c` | -| 看安全逻辑 | `App/nav/segment_fsm.c` | -| 看比赛编排 | `App/nav/nav_script.c` | -| 看传感器预处理 | `App/preproc/corridor_preproc.c` | -| 看 CAN 协议 | `App/Can/snc_can_app.c` + `App/Contract/chassis_can_msg.h` | -| 看全局数据结构 | `App/Contract/robot_blackboard.c/.h` | -| 看里程计 | `App/Contract/robot_odom.c` | -| 看激光驱动 | `App/laser/laser_manager.c` | -| 看 VL53 驱动 | `App/VL53L0X_API/platform/vl53_board.c` | -| 看 IMU 驱动 | `App/IMU/hwt101.c` | -| 看消息结构定义 | `App/preproc/corridor_msgs.h` | - ---- - -> **给接手者的最后提醒**: -> 1. **先修 BUG-1** (IMU 单位转换),否则 EKF 完全不可用 -> 2. **再修 BUG-2** (EKF 参数硬编码),否则调参改了白改 -> 3. 拿到实车后第一件事:用卷尺量 CAL-1 ~ CAL-3 的三个偏移量 -> 4. CAN 协议层 (`snc_can_app.c`) 已冻结,**不要修改** -> 5. IMU `yaw_continuous` 已接入转弯判定,实车调试时对比 `wz` 积分与 `yaw` 哪个更稳,参见 `IMU_YAW_WZ_ISSUE.md` diff --git a/can通讯协议.md b/can通讯协议.md deleted file mode 100644 index 01243aa..0000000 --- a/can通讯协议.md +++ /dev/null @@ -1,23 +0,0 @@ -FDR-Core 上 位 机 CAN 协 议 说 明 书 ( 当 前 固 件 实 装 版 ) ⽂ 档 状 态 : Internal / Current 适 ⽤ 固 件 : 当 前 上 传 的 f4_can_app.c 实 现 说 明 依 据 : 以 .c 代 码 ⾏ 为为 准 1. ⽬ 标 与 范 围 本 ⽂ 档 定 义上 位 机 与 底 盘 控 制 器 之 间 的 CAN 通 信 协 议 , 覆 盖 以 下 内 容 : 上 位 机 向 底 盘 下 发 速 度 命 令 底 盘 向 上 位 机 上 报 状 态 、 轮 速 、 ⾥ 程 和 通 信 诊 断 命 令 安 全 机 制 : CRC 、 rolling counter 、 命 令 超 时 故 障 / 警 告 状 态 的 上 报 规 则 2. 总 线 与 编 码 约 定 CAN 类 型 : 标 准 帧 ( 11-bit ID ) 帧 类 型 : 数 据 帧 ( RTR=0 ) 字 节 序 : ⼩ 端 缩 放 规 则 : vx 、 wz : int16 = 物理量 * 1000 轮 速 : RPM 直 接按 int16 发 送 ⾥ 程 : 增 量 ticks , 按 int16 发 送 CRC : CRC8-SAE J1850 poly = 0x1D init = 0xFF xorout = 0xFF ⾮ 反 射 当 前 固 件 在 0x100 控 制 帧 上 , 对 前 7 个 字 节 计 算 CRC , 再 放 ⼊ Byte7 。 - -3. 帧 ID 总 览 ⽅ 向 ID 名 称 实 际 周 期 说 明 Rx 0x080 Heartbeat 上 位 机 ⾃ 定 仅 表 ⽰ 链 路 活 着 , 不 刷 新 运 动 看 ⻔ 狗 Rx 0x100 Velocity Command 建 议 20ms 速 度 控 制 命 令 , 必 须 持 续 发 送 Tx 0x181 Status 20ms 状 态 机 / 健 康 等 级 / 诊 断 位 Tx 0x182 Actual RPM 轮 询 , 约 60ms 实 际 轮 速 Tx 0x183 Target RPM 轮 询 , 约 60ms ⽬ 标 轮 速 Tx 0x184 Comm Diag 100ms 通 信 统 计 Tx 0x200 Odom Delta 轮 询 , 约 60ms 四 轮 ⾥ 程 增 量 当 前 固 件 在 CAN_Send_Telemetry_20ms() 中 采 ⽤ 如 下 节 拍 : 0x181 : 每 个 20ms 周 期 都 发 0x182 / 0x183 / 0x200 : 通过 s_telem_slot 三 选 ⼀ 轮 询 发 送 0x184 : 每 5 个 20ms 周 期 发 ⼀ 次 , 即 100ms ⼀ 次 4. 上 位 机 -> 底 盘 4.1 0x080 ⼼ 跳 帧 ⽤ 途 : 仅 表 ⽰ “ 链 路 上 仍 然 有 ⼈ 在 说话 ” - -⾏ 为 : 不 会 刷 新 运 动 看 ⻔ 狗 不 会 延 续 旧 速 度 命 令 当 前 固 件 不 解 析 其 载 荷 内 容 , 也不 使 ⽤ DLC 内 容 建 议 : 可发可 不 发 若 发 , DLC 可 统 ⼀ 为 0 或 8 4.2 0x100 速 度 控 制 帧 ID : 0x100 DLC : 8 数 据 定 义 Byte 类 型 字 段 说 明 0~1 int16 LE vx_x1000 线 速 度 , 单 位 m/s * 1000 2~3 int16 LE wz_x1000 ⻆ 速 度 , 单 位 rad/s * 1000 4 uint8 ctrl_flags 控 制 标 志 位 , 当 前 仅 保 存 , 不 参 与 控 制决 策 5 uint8 reserved 预 留 , 固 定 填 0 6 uint8 rolling_counter 滚 动 计 数 器 7 uint8 crc8 对 Byte0~6 做 CRC8-SAE J1850 固 件 接 收 后 会 把 vx 、 wz 恢 复 成 浮 点 值 , 分别 写 ⼊ : g_robot_ctrl.target_vx g_robot_ctrl.target_wz - -并 保 存 ctrl_flags 与 rolling counter 。 接 收 判 定 规 则 1. DLC 必 须 等 于 8 2. CRC 必 须 正 确 3. rolling counter 必 须 满 ⾜ 下 列 规 则 : 若 尚 未 同 步 , 或 当 前 不 在 SYSTEM_OPERATIONAL , 则 ⾸ 帧 直 接接 受 正 常 运 ⾏ 时 , 新 counter 相 对 上 ⼀ 帧差 值 必 须 在 1..3 之 间 否 则 拒 收 发 送 建 议 推 荐 周 期 : 20ms ( 50Hz ) 最 低 要 求 : 不 要 超 过 150ms 不 发 送 合 法 0x100 即 使你 想 停 ⻋ , 也 建 议 继续 周 期 发 送 : vx = 0 wz = 0 的 合 法 命 令 帧 因 为 当 前 固 件 只 ⽤ “ 合 法 且 新 鲜 ” 的 0x100 喂 命 令 看 ⻔ 狗 , 超 时 阈 值 是 150ms 。 5. 底 盘 -> 上 位 机 5.1 0x181 状 态 帧 ID : 0x181 周 期 : 20ms DLC : 8 Byte 类 型 字 段 说 明 0 uint8 system_state 0=BOOTING , 1=OPERATIONAL , 2=SAFE_FAULT 1 uint8 system_health 0=OK , 1=WARNING , 2=FAULT - -Byte 类 型 字 段 说 明 2~5 uint32 LE diag_bits 当 前 诊 断 位 图 6 uint8 cmd_age_10ms 距 最 近 ⼀ 次 合 法 0x100 已 过 去 多 少 个 10ms tick 7 uint8 status_counter 状 态 帧 发 送 计 数 器 5.2 0x182 实 际 轮 速 帧 ID : 0x182 周 期 : 轮 询 , 约 60ms DLC : 8 Byte 类 型 字 段 0~1 int16 LE FL 实 际 RPM 2~3 int16 LE RL 实 际 RPM 4~5 int16 LE FR 实 际 RPM 6~7 int16 LE RR 实 际 RPM 5.3 0x183 ⽬ 标 轮 速 帧 ID : 0x183 周 期 : 轮 询 , 约 60ms DLC : 8 Byte 类 型 字 段 0~1 int16 LE FL ⽬ 标 RPM 2~3 int16 LE RL ⽬ 标 RPM - -Byte 类 型 字 段 4~5 int16 LE FR ⽬ 标 RPM 6~7 int16 LE RR ⽬ 标 RPM 5.4 0x184 通 信 诊 断 帧 ID : 0x184 周 期 : 100ms DLC : 8 Byte 字 段 说 明 0 valid_cmd_total_lsb 合 法 命 令 累 计 低 8 位 1 crc_error_total_lsb CRC 错 误 累 计 低 8 位 2 counter_reject_total_lsb rolling counter 拒 收 累 计 低 8 位 3 can_tx_drop_total_lsb CAN 发 送 丢 帧 累 计 低 8 位 4 busoff_total_lsb Bus-Off 累 计 低 8 位 5 rx_overrun_total_lsb FIFO overrun 累 计 低 8 位 6 last_accepted_counter 最 近 ⼀ 次 接 受 的 rolling counter 7 err_nibbles ⾼ 4 位 = 连 续 counter 错 误 数 ; 低 4 位 = 连 续 CRC 错 误 数 ; 均 饱 和 到 15 5.5 0x200 ⾥ 程 增 量 帧 ID : 0x200 周 期 : 轮 询 , 约 60ms DLC : 8 - -Byte 类 型 字 段 0~1 int16 LE FL delta ticks 2~3 int16 LE RL delta ticks 4~5 int16 LE FR delta ticks 6~7 int16 LE RR delta ticks 说 明 : 这 是 时 间 窗 内 增 量 不 是 累 计 总 值 上 位 机 如 需 总 ⾥ 程 / 总 编 码 器 计 数 , 需 要 ⾃ ⾏ 累 加 积 分 6. 系 统 状 态 与 健 康 等 级 6.1 system_state 值 名 称 含 义 0 SYSTEM_BOOTING 上 电 后 尚 未 收 到 第 ⼀ 帧 合 法 速 度 命 令 1 SYSTEM_OPERATIONAL 正 常 ⼯ 作 2 SYSTEM_SAFE_FAULT 安 全 保 护 , ⽬ 标 速 度已 强 制 清 零 6.2 system_health 值 名 称 含 义 0 SYSTEM_HEALTH_OK ⽆ 活 动 中 的 警 告 / 故 障 1 SYSTEM_HEALTH_WARNING 有 警 告 , 但仍 可 ⼯ 作 2 SYSTEM_HEALTH_FAULT 有 明 确 故 障 , 通 常已 经 或 应 进 ⼊ 保 护 - -7. diag_bits 诊 断 位 图 定 义 diag_bits 是 ⼀ 个 32 位 ⼩ 端 位 图 , ⽬ 前 定 义 如 下 : bit 宏 名 级 别 含 义 0 DIAG_COMM_TIMEOUT Fatal 速 度 控 制 帧 超 时 1 DIAG_CAN_BUS_OFF Fatal CAN Bus-Off 2 DIAG_CMD_CRC_STORM Fatal 连 续 CRC 错 误 过 多 3 DIAG_CMD_CNT_STORM Fatal 连 续 rolling counter 错 误 过 多 4 DIAG_MOTOR_FL_STALL Fatal 左 前 轮 堵 转 / 失 效 趋 势 5 DIAG_MOTOR_RL_STALL Fatal 左 后 轮 堵 转 / 失 效 趋 势 6 DIAG_MOTOR_FR_STALL Fatal 右 前 轮 堵 转 / 失 效 趋 势 7 DIAG_MOTOR_RR_STALL Fatal 右后 轮 堵 转 / 失 效 趋 势 8 DIAG_CONTROL_SATURATION Warning 控 制 输 出 ⻓ 时 间 顶 满 建 议 上 位 机 把 : bit0 ~ bit7 视 为 故 障 类 bit8 视 为 警 告 类 8. 安 全 策 略 与 故 障 触 发 条 件 8.1 命 令 超 时 命 令 看 ⻔ 狗 超 时 阈 值 : 150ms 只 有 合 法 且 新 鲜 的 0x100 才 会 刷 新 0x080 ⼼ 跳 不 会 刷 新 超 时 后 : 进 ⼊ SAFE_FAULT - -置 位 DIAG_COMM_TIMEOUT 8.2 CRC 错 误 ⻛ 暴 若 连 续 CRC 错 误 计 数 达 到 5 进 ⼊ SAFE_FAULT 置 位 DIAG_CMD_CRC_STORM 8.3 Counter 错 误 ⻛ 暴 若 连 续 counter 错 误 计 数 达 到 5 进 ⼊ SAFE_FAULT 置 位 DIAG_CMD_CNT_STORM 8.4 CAN Bus-Off 若 发 ⽣ Bus-Off 计 数 累 加 进 ⼊ SAFE_FAULT 置 位 DIAG_CAN_BUS_OFF 8.5 电 机 堵 转 固 件 每 10ms 做 ⼀ 次 电 机 堵 转 诊 断 。 若 某 轮 持 续 满 ⾜ 以 下 条 件 : ⽬ 标 RPM >= 40 实 际 RPM <= 8 控 制 输 出 绝 对 值 >= 850 并 持 续 50 个 10ms tick ( 即 500ms ) , 则 : 置 对 应 轮 ⼦ 的 stall 位 - -进 ⼊ SAFE_FAULT 8.6 控 制 饱 和 若 存 在 任 ⼀ 轮 持 续 满 ⾜ : ⽬ 标 RPM >= 30 控 制 输 出 绝 对 值 >= 980 并 持 续 20 个 10ms tick ( 即 200ms ) , 则 : 置 位 DIAG_CONTROL_SATURATION 该 项 属 于 Warning , 不 单 独 强 制 进 ⼊ SAFE_FAULT 。 9. 上 位 机 实 现 建 议 9.1 速 度 命 令 发 送 建 议 上 位 机 按 如 下 ⽅ 式 实 现 : 周 期 : 20ms ID : 0x100 rolling counter : 每 帧 ⾃ 增 1 , uint8 ⾃ 然 回 绕 CRC : 每 次 发 送 前 重 新 计 算 Byte0~6 的 CRC8-SAE J1850 停 ⻋ 时 不 要 停 ⽌ 发命 令 , 继续 发 : vx = 0 wz = 0 推 荐 发 送 频 率 推 荐 : 50Hz ( 20ms ) 可 接 受 : 100Hz ( 10ms ) 不 建 议 低 于 10Hz 绝 不 能 超 过 150ms 不 发合 法 0x100 - -9.2 ⼼ 跳 发 送 ID : 0x080 可 选 仅 ⽤ 于上 位 机 链 路 监 控 不 要 依 赖 它 维 持 运 动 9.3 状 态 接 收 建 议 重 点 订 阅 : 0x181 : 状 态 / 健 康 / 故 障 0x184 : 通 信 统 计 以 及 按 需 订 阅 : 0x182 : 实 际 轮 速 0x183 : ⽬ 标 轮 速 0x200 : ⾥ 程 增 量 建 议 上 位 机 ⾄ 少 显 ⽰ : system_state system_health diag_bits cmd_age_10ms crc_error_total_lsb counter_reject_total_lsb busoff_total_lsb 四 轮 实 际 RPM 四 轮 ⽬ 标 RPM 四 轮 增 量 ticks - -10. 0x100 组 帧 参 考 伪代 码 counter = (counter + 1) & 0xFF vx_i16 = round(vx_mps * 1000) wz_i16 = round(wz_radps * 1000) data[0] = vx_i16 & 0xFF data[1] = (vx_i16 >> 8) & 0xFF data[2] = wz_i16 & 0xFF data[3] = (wz_i16 >> 8) & 0xFF data[4] = ctrl_flags data[5] = 0 data[6] = counter data[7] = crc8_j1850(data[0:7]) send(id=0x100, dlc=8, data=data) \ No newline at end of file diff --git a/大体方案.md b/大体方案.md deleted file mode 100644 index 8c28fd0..0000000 --- a/大体方案.md +++ /dev/null @@ -1,507 +0,0 @@ -# ASER 平台 B 方案走廊相对定位实现与模块化解耦技术报告 - -**执行摘要**:本报告围绕你选择的 **B 方案(走廊相对定位 Corridor-relative Estimation)**,在不破坏现有 ASER 工程结构与 **STM32H743(上位机)↔ STM32F407(底盘)既有 CAN 协议**的前提下,给出一套可落地、可扩展、可“先跑通再变强”的实现路线。核心思想是:不把比赛当作“绝对坐标 SLAM”,而把赛场 40 cm 窄通道视为拓扑段落序列,实时估计 **横向偏差 e_y、航向误差 e_θ、沿通道进度 s**,并用侧向测距闭环实现“居中/偏置行走 + 对齐”,以对抗 **赛场尺寸 ±5% 误差、地毯导致的轮滑、测距偶发失效**(比赛规则明确存在地毯模拟松软路面、且尺寸允许误差 ±5%)。同时,将 **0x100 速度指令 20 ms 周期硬实时发送**作为最高优先级工程约束,任何导航/融合/日志都不得影响其节拍(否则底盘可能进入 SAFE_FAULT)。赛场层面,规则要求 **5 分钟限时**且未完全驶出与未停在启动区内可判 0 分,因此系统优先级必须是 **安全与完赛闭环 > 定位美观 > 路径最优**。(赛事通道/出入口 40 cm、启动区、5 分钟限制、尺寸误差 ±5%:见《附件6…比赛规则》1–3 页与 14 页;上位机 CAN 协议关键帧:见《通讯协议》2–4 页、8–10 页;ASER 工程任务/协议层约束:见《aser》1–5 页。) - -## 系统约束与现状梳理 - -### 赛场与任务约束对算法与工程的“硬约束” -比赛场地为 **390 cm × 300 cm**,共有 5 条田垄;围栏与田垄之间、以及相邻田垄之间均为 **40 cm 通道(垄沟)**,出入口宽 **40 cm**,出入口外侧紧邻 **40 cm × 100 cm 启动区**;比赛 **限时 5 分钟**,且规则强调必须驶离场地并停在启动区,否则可能判 0 分;尺寸允许误差 **±5%**(意味着通道宽可能约 38–42 cm,任何“贴边”策略都必须考虑裕量)。这些约束直接决定控制目标应是“别蹭边、别失控、能跑完”,而非追求全局米级地图的一致性。(《附件6…比赛规则》1–3 页、14 页) - -### 现有硬件与软件约束 -以下为你给定的固定约束(本报告按此设计): - -- 车体:**20×20 cm**,轮厚 **3 cm**;**差速四轮结构**(四电机)。 -- 控制器三块: - - **STM32F407(底盘)**:已实现四轮 **LADRC**,通过 CAN 与上位机通信。 - - **STM32H743(主控/上位机)**:传感器融合、底盘与机械臂控制(现状上位机)。 - - **K230(视觉中枢)**:用于视觉语义/目标等(本报告将其作为增强/降级输入,不进入硬实时链路)。 -- ASER 工程形态(来自你上传的 ASER 文档):基于 STM32CubeMX + FreeRTOS(CMSIS-V2),已建立 **20 ms canTxTask** 与 **100 ms monitorTask**;CAN 协议层在 `App/Can/snc_can_app.c/.h`,并明确要求保持既有协议/中断接收链路,新增功能优先放到 `App/` 目录以避免再生成覆盖;FDCAN 接收链路保持 IRQ→回调→协议解析的单路径。(《aser》1–5 页) - -### 既有 CAN 协议是“不可破坏”的硬边界 -你已确认 H7↔F4 通信协议“已经制定好”,因此本文不再“重新设计协议”,而是把协议当作 **契约(contract)**: -- 0x100 为速度命令,**DLC=8**,包含 `vx_x1000`、`wz_x1000`、rolling counter、CRC8;要求 **建议 20 ms** 周期持续发送,且 **不得超过 150 ms 不发送合法 0x100**,否则底盘进入 SAFE_FAULT;心跳帧 0x080 **不刷新运动看门狗**。(《通讯协议》2–4 页、8–10 页) -这些要求决定:**所有算法模块必须围绕“20 ms 严格出 v/ω”来组织调度与解耦**。 - -## 传感器清单、性能与可观测性分析 - -### 传感器清单(按你给定配置) -- **4 电机编码器**:提供四轮增量/速度,可构造差速里程计,并可用于同侧前后轮差异的 **轮滑检测**(工程上很关键)。 -- **高精度单轴 IMU(ω_z 或 θ)**:你给定“短时漂移可忽略”。这对 B 方案非常有利:可把“短段航向保持/原地转向闭环”做得很稳,同时简化滤波状态维度(但仍需讨论风险与退路,见后文)。 -- **8 个测距模块**:前后左右各 2 个: - - 左右侧向:**VL53L0X V2**(最远 2 m)。ST 官方产品页说明 VL53L0X 为 ToF 测距,最大可到 **2 m**。citeturn2search3 - 同时其官方数据手册给出典型“Range profile”:High speed 20 ms、Long range 33 ms、High accuracy 200 ms 等 timing budget 配置(对你做“关键动作更稳、巡航更快”的动态配置非常实用)。citeturn2search41 - - 前后向(每端 2 个):**STP-23L(7 cm–7.5 m)** + **ATK‑MS53L1M(4 m)**。其中 4 m 量程模块工程上高度可能基于 VL53L1X 类 ToF:ST 官方 VL53L1X 产品页给出“up to 4 m、up to 50 Hz”能力,可作为你对 4 m 级传感器的性能参考上限。citeturn0search0 -- 结构:**差速四轮** → 上位机输出 (v, ω) 即可驱动底盘;底盘闭环已由 F407 LADRC 负责。 - -### B 方案的可观测性:为什么侧向双点能同时观测 e_y 与 e_θ -走廊相对定位的关键是:**只关心“相对墙/垄侧”的横向与航向误差**,不强求全局 (x,y)。只要左右两侧各有前后两个测距点(你是每侧 2 个 VL53L0X),就可以构造两个稳定的派生量测: - -- **航向误差 e_θ(相对走廊方向)**:利用同侧前后距离差与传感器纵向基线 \(L_s\),可用 - \[ - e_{\theta,L} \approx \arctan\left(\frac{d_{Lf}-d_{Lr}}{L_s}\right),\quad - e_{\theta,R} \approx \arctan\left(\frac{d_{Rf}-d_{Rr}}{L_s}\right) - \] - 该构造与你上传的《大体方案》对 B 方案与派生量测的定义一致(《大体方案》4–5 页)。 -- **横向误差 e_y(相对中心线/偏置线)**:用左右平均间隙差得到 - \[ - e_y \approx \frac{1}{2}( \bar d_L - \bar d_R) - y_{\text{offset}} - \] - 其中 \(y_{\text{offset}}\) 是你可以显式引入的“偏置行走”目标(例如机械臂在右侧外凸时令车辆略偏左,降低擦碰风险)。同样与《大体方案》对 B 方案的描述一致(《大体方案》4–5 页)。 - -前后向测距(STP-23L / 4 m 模块)主要用于:**到端触发(段落切换)**、安全制动、以及对沿程 \(s\) 的事件校正(见后文)。 - -## 走廊相对定位与融合算法设计 - -### 问题建模与坐标系 -定义走廊(或垄沟)局部坐标系 \(\{C\}\): -- \(x_C\):沿走廊前进方向; -- \(y_C\):走廊横向(向左为正); -- 车辆车体坐标 \(\{B\}\):\(x_B\) 前、\(y_B\) 左。 - -B 方案输出状态: -\[ -\mathbf{x}_c = [e_y,\ e_\theta,\ s]^T -\] -其中: -- \(e_y\):车辆参考点(建议用车体几何中心或“控制点”)相对走廊目标线(中心线或偏置线)的横向偏差; -- \(e_\theta\):车辆航向相对走廊方向的误差; -- \(s\):沿走廊进度(m),用于段落终止触发/动作编排,不作为“强闭环精确位姿”。 - -### 传感器融合总体策略:分层、分频、强约束 -建议采用“三层融合与控制”: - -- **层 A(硬实时输出层,20 ms)**:必须产出 (v_cmd, ω_cmd) 并发送 CAN 0x100。无论任何模块异常,这层都不能停摆(最多把速度降到 0 并持续发送合法 0x100)。这是由底盘运动看门狗与超时机制决定的:0x080 心跳不刷新看门狗,只有合法 0x100 刷新;超时阈值 150 ms。 (《通讯协议》2–4 页、8–10 页) -- **层 B(相对定位与走廊闭环,建议 50–100 Hz)**:估计 \(e_y,e_\theta,s\),并形成走廊跟随控制律;允许降级(只用单侧、只用 IMU 航向保持等),但必须在可控范围内给出指令。 -- **层 C(段落状态机/任务决策,10–20 Hz)**:执行段脚本(Segment List)、处理到端触发、重定位行为(扫描/后退重试/停车保护)、以及与机械臂/视觉的协同。 - -这样做的目的:**把“安全与完赛”从定位精度中解耦**。 - -### 状态估计实现方案对比:从“极简互补”到“鲁棒 EKF/UKF” -你明确提出希望覆盖 EKF/UKF/粒子滤波。结合 STM32H743 算力与工程风险,本报告建议按阶段实现: - -#### 极简方案:互补滤波 + 鲁棒观测融合(优先推荐做 P0) -利用你给定“短时 IMU 漂移可忽略”,可以先不引入复杂滤波矩阵,直接做: - -- 航向误差 \(e_\theta\): - - 预测:\(e_{\theta,k|k-1}=e_{\theta,k-1} + \omega_z \Delta t\) - - 校正:用侧向差分观测 \(e_{\theta,L}, e_{\theta,R}\) 做加权融合(按健康度/置信度权重),再与预测做互补融合: - \[ - e_\theta \leftarrow \alpha(e_\theta + \omega_z\Delta t) + (1-\alpha)\cdot e_{\theta,\text{meas}} - \] -- 横向误差 \(e_y\): - - 直接由 \(\frac{1}{2}(\bar d_L-\bar d_R)-y_{\text{offset}}\) 给出,并做一阶低通(根据 VL53L0X timing budget 动态调整滤波带宽;20 ms 档噪声较大、200 ms 档更稳但延迟更大,可从数据手册的 profile 及误差差异得到工程依据)。citeturn2search41 -- 沿程 \(s\): - - 用编码器里程计积分为主(来自 CAN 0x200 的轮增量 ticks,你需要在 H743 侧累加积分)。 (《通讯协议》5–7 页) - - 用前向测距做“事件校正”:当 \(d_\text{front}\) 小于阈值(接近端部围栏)触发段切换,并把 \(s\) 校正到“段长 - d_front - 安装偏置”。 - -优点:实现快、数值稳定、适合先把整车跑通;缺点:难以严格输出协方差,也不便于统一做马氏门限。 - -#### 鲁棒 EKF(推荐做 P1) -若你希望更系统地融合并获得一致的健康度/协方差,则做小维 EKF: - -- 状态:\(\mathbf{x}=[e_y,e_\theta,s]^T\) 或扩展为 \([e_y,e_\theta,s,b_g,k_s]\)(陀螺零偏、轮滑比例因子)以吸收轮滑/地毯误差(《大体方案》4 页提到类似扩展思路)。 -- 预测模型(简化差速运动学在走廊局部系下的表达): - \[ - \begin{aligned} - e_{y,k+1} &\approx e_{y,k} + v_k\sin(e_{\theta,k})\Delta t \\ - e_{\theta,k+1} &\approx e_{\theta,k} + (\omega_{z,k}-b_{g,k})\Delta t \\ - s_{k+1} &\approx s_k + v_k\cos(e_{\theta,k})\Delta t - \end{aligned} - \] - 其中 \(v_k\) 来自里程计估计或上一周期命令(两者在轮滑情况下要区别对待)。 -- 量测模型: - - \(z_{e_y}=\frac{1}{2}(\bar d_L-\bar d_R)-y_{\text{offset}}\) - - \(z_{e_\theta}\):由左/右侧差分观测(可单侧/双侧) - - \(z_s\):端部事件约束(触发式更新) -- **异常值剔除(创新门限/χ²)**: - 用马氏距离(innovation 的归一化残差)做门限,d² 超限则拒绝该测距更新、降低该传感器健康度,并触发降级/重定位动作。创新卡方检验型鲁棒 EKF 在导航融合领域是成熟手段;例如武汉大学学报给出“基于创新卡方检验的扩展鲁棒卡尔曼滤波”并说明可有效抑制观测粗差、提高稳定性。citeturn5search1 - 同时马氏距离平方在高斯假设下与 χ² 分布的关系,可作为你选择阈值的理论依据。citeturn5search0 - -#### UKF(备选 P1/P2) -UKF 的优势是减少雅可比推导错误风险,对非线性更稳健;其系统性论述可参考 Julier & Uhlmann 的综述文章(Proceedings of the IEEE, 2004)。citeturn4search8 -但对 MCU 工程而言,UKF 的实现细节(sigma 点、数值稳定、协方差正定维护)仍需严格测试。建议在 EKF 稳定后再引入 UKF,或仅在仿真/离线回放中验证。 - -#### 粒子滤波(不建议作为主线) -粒子滤波更适合多峰分布或强非线性/非高斯,但你这里的走廊状态空间维度小、观测约束强、且 MCU 实时性要求更硬,粒子滤波的收益通常不如鲁棒 EKF/UKF 明显。建议仅在“视觉地标 + 多段拓扑歧义”场景出现时再考虑。 - -### 控制律:走廊闭环优先,轨迹跟踪为辅 -走廊段推荐直接闭环 \(e_y,e_\theta\) 输出角速度: -\[ -\omega_\text{cmd}=k_\theta e_\theta + k_y e_y -\] -线速度: -\[ -v_\text{cmd}=\min(v_\text{ref},\ v_\text{safety}) -\] -其中 \(v_\text{safety}\) 由安全层根据前向距离与最小侧向间隙硬约束裁剪(见下节)。 - -对于“入场对准、退出与停回启动区”等非典型走廊段,可以上层用段脚本触发“短距离轨迹跟踪”(如 Pure Pursuit),但其输出仍应统一进入 **命令仲裁器**,最终被安全层裁剪后送给 CAN 0x100。 - -### 安全层、异常检测与重定位策略 -这是 B 方案能否“比赛不判零”的关键(规则对失控/冲出场地会强制罚下,且未驶出/未停在启动区可能 0 分)。《附件6…比赛规则》1、8–9 页 - -#### 传感器健康度与一致性检查 -建议对每个测距传感器维护 `health_score∈[0,1]` 与 `state∈{OK,SUSPECT,FAIL}`,并用以下规则更新(工程可解释、易调参): - -- **有效性**:超量程/无数据/固定值卡死 → 直接 FAIL(可加 N 次确认)。 -- **跳变**:\(|d_k-d_{k-1}|>\Delta d_\text{max}\) 且与冗余传感器不一致 → SUSPECT。 -- **走廊一致性**: - - 左右平均距离差过大(\(e_y\) 过大)接近阈值 → 触发降速/停车; - - 左右和与走廊宽度模型严重不符(考虑 ±5% 尺寸误差)→ 可能进入入口/出口开阔区或测距误读,切换“入口/开阔区模式”。 - -#### 轮滑检测(地毯场景必须做) -规则明确会在垄沟中随机铺设地毯模拟松软路面(《附件6…比赛规则》2–3 页),强烈建议把轮滑检测当作“安全与融合共同输入”: -- 同侧前后轮编码器差异过大(四轮提供更多冗余) -- \(|\Delta\theta_\text{enc} - \Delta\theta_\text{imu}|\) 超阈值(IMU 短时漂移可忽略时,这个检测更可靠) - -轮滑触发后动作: -- 降低 \(v_\text{max}\)、限制加速度; -- 融合层增大过程噪声 \(Q\) 或降低对里程计的信任; -- 控制层更依赖侧向闭环(\(e_y,e_\theta\)),减少对 \(s\) 的硬依赖。 - -#### 重定位/恢复动作链(建议用段脚本固化) -当“走廊观测不可用”或“误差超过安全阈值”时,不要让系统继续前冲;建议固化为可重复执行的恢复链: - -1. **低速前进 + 侧向对齐**:尝试恢复 \(e_\theta\) 可观测(左右/单侧)。 -2. **原地旋转扫描**:转动寻找两侧墙面,使 \(e_y/e_\theta\) 可观测。 -3. **后退重试或停车保护**:连续失败 N 次后退出(比赛是否允许等待/重试由你们策略决定,但从“避免失控罚下”角度,停车保护是最后底线)。 - -这类恢复链在你上传的《大体方案》中已有雏形(《大体方案》13 页),建议工程化为状态机(NORMAL/DEGRADED/RECOVERY/STOP_SAFE)。 - -### “IMU 短时漂移可忽略”的简化与风险 -你给定该条件,可以显著简化实现(例如可不立刻估计 \(b_g\)),但必须明确风险边界: - -- 风险来源:温漂、振动、饱和、安装误差、长时间累计偏置。短时可忽略 ≠ 全程可忽略。 -- 工程缓解: - - 开机静止校零(估计陀螺零偏); - - 在走廊段用侧向差分观测周期性校正 \(e_\theta\)(即使不用 EKF,也做互补融合); - - 若引入 EKF/UKF,建议把 \(b_g\) 作为可选状态并在“长段/高温漂”时开启。 - -## 通讯协议与硬实时调度约束 - -### CAN 报文契约(按现有协议原样遵守) -你上传的《通讯协议》给出了当前固件实装版协议要点(标准帧 11-bit、DLC、字节序、缩放、CRC8 等),这里整理为“实现必须满足的契约”: - -- **0x100 Velocity Command(H743→F407)** - - DLC=8;`vx,wz` 按 `int16 = 物理量 × 1000`(小端);包含 `rolling_counter` 与 `CRC8-SAE J1850`(对 Byte0~6 计算,放 Byte7)。 - - 推荐周期 **20 ms**;**绝不能超过 150 ms 不发送合法 0x100**(即使停车也继续发 vx=0,wz=0 的合法帧);rolling counter 在正常运行时要求与上一帧差值在 1..3,否则拒收。 - (《通讯协议》2–4 页、8–10 页) - -- **0x080 Heartbeat(H743→F407)**:仅表示链路活着,**不刷新运动看门狗**,不能替代 0x100。 (《通讯协议》2–3 页、8–10 页) -- **0x181 Status(F407→H743,20 ms)**:包含 `system_state、system_health、diag_bits、cmd_age_10ms` 等,用于安全降级决策。 (《通讯协议》4–5 页) -- **0x184 Comm Diag(F407→H743,100 ms)**:统计 CRC 错误、counter 拒收、bus-off 等,必须纳入诊断与回放。 (《通讯协议》6 页) -- **0x200 Odom Delta(F407→H743,轮询约 60 ms)**:四轮增量 ticks;上位机需自行累积。 (《通讯协议》5–7 页) - -> 说明:你已表示协议既有且固定,因此本报告不建议在 H7↔F4 CAN 上新增“破坏兼容”的帧。若未来要加扩展帧,建议在不影响现有 ID/节拍/接收逻辑的前提下做“可选附加 ID”,并通过版本位/能力位协商(但这属于后续扩展,不是当前 P0 必需)。 - -### 优先级、周期与超时处理(工程实现建议) -- **最高优先级**:`can_tx_0x100_task`(20 ms,硬实时,禁止被日志/融合阻塞)。 - ASER 工程现有结构已采用 20 ms 的 canTxTask 且强调绝对节拍(osDelayUntil)与协议层保持(《aser》1、5 页)。 -- **第二优先级**:CAN Rx 中断回调(接收 0x181/0x184/0x200),以“快照/无锁或短临界区”方式写入共享上下文,避免长时间占用 ISR。 -- **第三优先级**:控制/估计(50–100 Hz),必须保证“在下一个 0x100 截止前产出最新命令”,但即便估计超时,也要有“上一帧命令 + 安全裁剪”的保底。 -- **监控任务(100 ms)**:读取 `cmd_age_10ms、diag_bits、comm diag`,若发现异常趋势(例如 DIAG_COMM_TIMEOUT、bus-off、连续 CRC 错误风暴)立即触发上位机 STOP_SAFE 模式并把 (v,ω) 置零,但仍持续发合法 0x100。 (《通讯协议》8–10 页) - -为实现稳定周期,建议使用 FreeRTOS 的 `vTaskDelayUntil()`(按绝对时间唤醒,适合固定频率周期任务)。citeturn3search34 -在 ISR→任务的事件通知上,任务通知(`vTaskNotifyGiveFromISR`)通常比信号量更轻,FreeRTOS 手册亦将其描述为更快的替代机制。citeturn2search42 - -### 关键消息帧示例(十六进制 + 结构体) -下面给出 **0x100** 的一个可复现实例(示例:vx=0.30 m/s,wz=0.80 rad/s,ctrl_flags=0x01,counter=0x10;CRC8=SAE J1850,对 Byte0~6 计算): - -- `vx_x1000 = 300 = 0x012C`(小端:2C 01) -- `wz_x1000 = 800 = 0x0320`(小端:20 03) -- 组合 Byte0~6:`2C 01 20 03 01 00 10` -- 计算得到 `CRC8 = 0xA1` -- 最终 8 字节: - **`2C 01 20 03 01 00 10 A1`** - -对应 C 结构体(注意小端序与打包): - -```c -#pragma pack(push,1) -typedef struct { - int16_t vx_x1000; // Byte0-1, m/s * 1000 - int16_t wz_x1000; // Byte2-3, rad/s * 1000 - uint8_t ctrl_flags; // Byte4 - uint8_t reserved; // Byte5, fixed 0 - uint8_t rolling_counter; // Byte6 - uint8_t crc8; // Byte7, CRC8-SAE J1850 over Byte0..6 -} CanCmdVel_0x100_t; -#pragma pack(pop) -``` - -(0x100 字段定义、CRC 规则、rolling counter 规则、150 ms 超时:见《通讯协议》2–4 页、8–10 页。) - -## 软件模块化与解耦方案 - -### 解耦目标与原则 -在 ASER 现有工程约束下(协议层/中断链路/任务框架尽量不动),解耦的关键是把系统切成三类模块: - -1. **硬实时链路模块**:唯一职责是“稳定发 0x100”,只从一个“命令槽(Command Slot)”读取最新的 (v,ω);不做复杂计算、不打印日志。 -2. **可实时模块**:估计、控制、预处理,允许在极端情况下掉周期,但必须提供保底输出与超时策略。 -3. **非实时模块**:日志、回放、仿真接口、参数调试、统计;永不阻塞硬实时。 - -ASER 文档明确:CAN 协议层位置固定,并建议新功能放 App/ 目录,且 canTxTask/monitorTask 已存在。(《aser》1–5 页) - -### 数据流总览(mermaid) -```mermaid -flowchart LR - subgraph S[传感器/底盘输入] - VL53[VL53L0X x4 侧向测距] - FRONT[前向测距: STP-23L + 4m模块] - BACK[后向测距: STP-23L + 4m模块] - IMU[单轴IMU ωz/θ] - CANRX[CAN Rx IRQ: 0x181/0x184/0x200] - end - - subgraph P[预处理与健康度] - PRE[时间戳对齐/滤波/有效性检测/健康度] - OBS[派生观测构造: e_y_meas, e_theta_meas, d_front, d_back] - end - - subgraph E[估计与控制] - EST[走廊相对定位滤波器\n(x=[e_y,e_θ,s] 或扩展)] - SEG[段脚本解释器 + 拓扑状态机] - CTRL[走廊控制器/原地转向/入口对准] - SAFE[安全监督器/降级状态机/命令仲裁] - end - - subgraph R[硬实时输出] - CANTX[CAN Tx Task\n0x100 @20ms] - end - - subgraph L[工具链] - LOG[日志记录/回放/故障注入] - SIM[仿真/传感器注入接口] - end - - VL53 --> PRE - FRONT --> PRE - BACK --> PRE - IMU --> PRE - CANRX --> PRE - - PRE --> OBS --> EST - CANRX --> EST - - EST --> CTRL - SEG --> CTRL - CTRL --> SAFE --> CANTX - - CANRX --> SAFE - SAFE --> LOG - OBS --> LOG - EST --> LOG - SIM --> PRE -``` - -### 模块清单、接口消息、周期与最大延迟(必须表格) -下表给出“建议模块化拆分”,并明确每个模块 I/O、周期与延迟预算。**注意:开发语言、CPU 负载预算未指定**;下表的资源估计按 STM32H743 “小维滤波 + 50–100 Hz 控制”属于轻量任务的常见工程经验给出,最终应以运行时 profile 校准。STM32H743 的 480 MHz Cortex‑M7 与双精度 FPU、TCM RAM 能力,为小维滤波提供了硬件基础。citeturn1search1 - -| 模块 | 职责 | 输入(消息/接口) | 输出(消息/接口) | 典型周期 | 最大延迟(建议) | 资源估计(H743) | -|---|---|---|---|---|---|---| -| CAN协议适配层(既有) | 按既有协议收发、CRC、上下文维护(禁止破坏兼容) | FDCAN IRQ | `ChassisStatus(0x181)`、`CommDiag(0x184)`、`OdomDelta(0x200)` | IRQ/20ms/轮询 | <2 ms 解析写入 | 低;保持原样 | -| CAN Tx 0x100 硬实时任务 | 固定 20 ms 发送合法 0x100,任何情况下不断流 | `CmdSlot(v,w,flags)` | CAN 0x100 | **20 ms** | **<1 ms 抖动** | 极低;最高优先级 | -| 编码器里程计模块 | ticks 累加、四轮→差速等效、轮滑检测特征 | `OdomDelta(0x200)` | `OdomEst{ds, v, yaw_enc}`、`SlipFeat` | 50–100 Hz(或随0x200) | <20 ms | 低 | -| IMU采集模块 | 采集 ωz/θ、时间戳、静止校零 | SPI/I2C/串口(未指定) | `ImuZ{wz, dt}` | 200–500 Hz(建议) | <5 ms | 低 | -| VL53侧向驱动 | 4 个 VL53L0X 轮询/异步读取、模式切换(20/33/200ms) | I2C | `RangeSideRaw` | 20–50 Hz(视 timing budget) | <40 ms | 低到中(I2C占用) | -| 前后测距驱动 | STP-23L 与 4m 模块读取、冗余校验 | UART/I2C(未指定) | `RangeFrontBackRaw` | 20–50 Hz | <50 ms | 低到中 | -| 预处理与健康度 | 对齐时间戳、滤波、有效性、跳变检测、一致性/走廊模式识别 | Raw ranges、IMU、Odom | `CorridorObs{e_y_meas,e_th_meas,d_front,d_back,valid}`、`SensorHealth` | 50–100 Hz | <20 ms | 低 | -| 走廊相对定位滤波 | 互补/EKF/UKF 输出 e_y/e_θ/s 与置信度 | `CorridorObs`、`ImuZ`、`OdomEst` | `CorridorState{e_y,e_th,s,cov/conf}` | 50–100 Hz | <20–40 ms | 低(小维) | -| 段脚本解释器 | Segment List 执行:走廊段/原地转向/退出停车/失败恢复 | `CorridorState`、`SensorHealth` | `SegmentCmd{mode,v_ref,y_offset,end_trigger}` | 10–20 Hz | <100 ms | 低 | -| 控制器集合 | 走廊闭环、原地转向、入口对准等 | `SegmentCmd`、`CorridorState` | `RawCmd{v,w}` | 50–100 Hz | <20 ms | 低 | -| 安全监督器/仲裁 | 急停/限速/降级/模式切换;融合底盘 diag_bits/cmd_age | `RawCmd`、0x181/0x184、ranges | `CmdSlot(v,w,flags)`、`SafetyState` | 50–100 Hz | **<20 ms**(到0x100) | 低 | -| 日志与回放 | 记录观测/状态/命令/故障;支持离线回放复现实验 | 全部关键消息 | log文件/串口输出 | 5–20 Hz(批量写) | 不得阻塞实时链路 | 中(取决于介质) | -| 测试仿真/注入接口 | PC 仿真或回放注入 ranges/odom/imu;用于HIL | 离线数据/串口/USB | 注入到 PRE | 非实时 | 不影响0x100 | 低 | - -**接口命名建议**:把“CAN 帧”与“内部消息”严格区分,例如 `CanCmdVel_0x100_t` 与 `CmdSlot`,避免上层直接依赖 CAN 打包细节,从而实现解耦与可测试性。 - -## 实现步骤与里程碑 - -### 分阶段实施步骤清单(可操作) -由于赛期时间表“未指定”,下面以“无特定期限”的工程顺序给出建议;若你们有明确赛期,可按周压缩/并行。 - -**阶段 P0:跑通闭环(目标:能稳定走通道、不撞、不中断 0x100)** -1. 固化 **0x100 20 ms** 发送硬实时:把 canTxTask 设为最高优先级,只从 `CmdSlot` 取值;加 watchdog/统计,任何异常也持续发送 vx=0,wz=0 的合法帧。(《通讯协议》2–4 页、8–10 页;《aser》1、5 页) -2. 接入 CAN Rx:0x181/0x184/0x200 解析快照写入上下文,monitorTask 先只做可视化打印与超时报警。(《通讯协议》4–7 页;《aser》1–5 页) -3. 侧向 VL53L0X 驱动:先用固定 profile(例如 33 ms 或 30 ms 档),跑出稳定的 `d_Lf,d_Lr,d_Rf,d_Rr`;必要时在关键动作切换到 200 ms 高精度档(官方数据手册给出 profile 与 timing budget)。citeturn2search41 -4. 前后测距驱动:至少保证一个“前向安全距离”可用,先实现安全限速/急停。 -5. 实现派生观测 \(e_y,e_\theta\) 并闭环:先用互补滤波/低通 + 走廊控制律,让车在 40 cm 通道内稳定跑直线与到端停车。 -6. 段脚本最小集:CorridorFollow / TurnInPlace / ExitAndStop(动作少但可跑完全程)。 - -**阶段 P1:鲁棒性与可调参** -1. 加入健康度、异常检测、降级状态机:单侧可用时切“单侧贴边 + IMU 航向约束”;双侧不可用时低速+停车保护。 -2. 加入轮滑检测与自适应策略(地毯段必需):轮速差与 IMU/里程计不一致触发降速与融合降权。(地毯存在:见《附件6…比赛规则》2–3 页) -3. 引入鲁棒 EKF(或对互补滤波加入创新门限):用 χ²/马氏距离拒绝异常测距,参考创新卡方检验鲁棒 EKF 的工程化做法。citeturn5search1turn5search0 -4. 完善日志与回放:把“每次撞/每次抖动”都能离线复现,支撑快速迭代。 - -**阶段 P2:增强与赛场集成** -1. K230 输出“结构化低带宽特征”作为增强/降级输入:例如走廊中心偏差、地标识别结果;K230 的多核 RISC‑V 与 KPU 能力适合做推理后输出特征量,而不承担 20 ms 硬实时闭环。citeturn6search3 -2. 若需要局部绕障(比赛道具/土块干扰可能导致异常行为),可做“小范围 DWA 风格速度采样”,但务必以安全层为前提;DWA 原始思想是“在速度空间搜索可停、避障、前进最优的 (v,ω)”。citeturn4search0 - -### 仿真工具与场景建议 -未指定你们必须使用 ROS/某仿真器,因此给出三档可选: - -- **轻量快速(推荐 P0/P1)**:Python/Matlab 自建 2D 走廊仿真(差速模型 + 墙面 ToF 测距模型 + 噪声/丢包/跳变),用于调 \(k_y,k_\theta\)、异常门限、降级策略;优点是迭代极快、与 B 方案高度匹配。 -- **中等复杂(可选)**:Webots/Gazebo 的差速车模型 + 简化距离传感器,验证入口/转向等几何行为。 -- **硬件在环 HIL(推荐 P1/P2)**: - - H743 跑真实控制栈; - - 通过“仿真注入接口”把 ranges/imu/odom 注入 PRE 模块(测试编译开关),同时真实发送 CAN 0x100 给 F4,看 F4 是否稳定接受、是否出现 counter/CRC 风暴、cmd_age 是否异常。(《通讯协议》8–10 页) - -### 里程碑甘特图(示例:无特定期限,按 6 周节奏展示) -```mermaid -gantt - title ASER B方案(走廊相对定位)里程碑示例(无特定期限) - dateFormat YYYY-MM-DD - axisFormat %m-%d - - section P0 跑通(先安全后精度) - 0x100 20ms硬实时不掉帧 + 基础安全层 :a1, 2026-03-18, 7d - CAN Rx接入(0x181/0x184/0x200)+里程计 :a2, after a1, 7d - VL53侧向+前后测距驱动 + e_y/e_θ观测 :a3, after a2, 10d - 走廊控制器 + 最小段脚本(走廊/转向/退出) :a4, after a3, 10d - - section P1 稳定与容错 - 健康度/异常检测/降级状态机 :b1, after a4, 7d - 轮滑检测与自适应降速/融合降权 :b2, after b1, 7d - 鲁棒EKF/互补+χ²门限(可选) :b3, after b2, 7d - - section 集成与验证 - 日志回放/自动化测试/故障注入 :c1, after a3, 14d - HIL联调 + 赛场流程演练 + 参数冻结 :c2, after b3, 14d -``` - -## 性能指标与验证方法 - -### 建议性能指标(赛前可再定阈值) -结合 40 cm 通道与车辆 20 cm 外形,工程上建议把“安全裕量”明确成指标: - -- **走廊横向控制**: - - \(e_y\) RMS(直通道匀速 0.2–0.4 m/s):建议目标 < 10–20 mm(取决于传感器安装与轮滑程度); - - \(e_y\) 峰值:不得触发“最小侧向间隙”保护线。 -- **航向对齐**:\(e_\theta\) RMS < 1–2°(入口/转向后重新进入走廊的恢复时间也应记录)。 -- **端到端延迟**:从侧向测距采样到 0x100 生效的闭环延迟建议 < 40 ms(两周期);0x100 发送抖动应远小于 20 ms 周期。 -- **鲁棒性**:单侧 VL53 临时失效(例如 0.5–1 s)仍能保持不碰撞;前向测距失效时必须降速并可安全停车。 -- **完赛相关**:在 5 分钟限制下完成“驶出场地 + 停在启动区”动作(规则强调未完成可 0 分)。 (《附件6…比赛规则》1 页) - -### 数据采集需求(支撑可复现实验) -建议每条日志至少包含: -- 时间戳(单调时钟)、段 ID、模式(NORMAL/DEGRADED/RECOVERY/STOP_SAFE) -- 原始测距(8 路)、有效标志、健康度 -- 派生观测 \(e_y,e_\theta,d_\text{front},d_\text{back}\) -- 估计状态(\(e_y,e_\theta,s\) 与协方差/置信度) -- 输出命令(RawCmd 与最终 CmdSlot)、0x100 counter/CRC 统计 -- 底盘状态(0x181 system_state/health/diag_bits/cmd_age)与 0x184 通信统计 -(这些字段在协议中均可获得:见《通讯协议》4–7 页。) - -### 单元测试与整车测试用例示例 -**单元测试(Host 或 MCU 上跑,推荐“输入→输出可验算”)** -- UT-EST-001:给定理想走廊、已知 \(L_s\)、固定 \(e_\theta\),构造 \(d_{Lf},d_{Lr}\) 并验证 \(e_{\theta,L}\) 反解误差 < 阈值。 -- UT-GATE-001:给定 EKF 创新与协方差,构造离群点,验证 χ² 门限拒绝逻辑;门限选择可参考创新卡方检验鲁棒 EKF 文献。citeturn5search1 -- UT-CAN-001:0x100 打包:vx/wz 缩放、小端序、CRC8-J1850 校验与 rolling counter 递增规则;确保 counter 跳变策略不会触发底盘拒收。(《通讯协议》2–4 页) -- UT-SAFE-001:前向距离 < d_stop → v=0;cmd_age_10ms 超阈值或 diag_bits 出现致命位 → STOP_SAFE 并持续发 0x100=0。(《通讯协议》4–5 页、8–10 页) - -**整车测试(建议可回归)** -- IT-COR-001(入场对准):启动区→40 cm 出入口→进入第一通道;指标:不触碰、最大横向误差、耗时。(赛场尺寸:见《附件6…比赛规则》2 页) -- IT-COR-002(走廊直行):匀速 0.2/0.3/0.4 m/s,统计 \(e_y\) RMS/峰值、\(e_\theta\) RMS。 -- IT-END-001(到端触发):接近端部围栏,验证触发准确率与停车距离一致性。 -- IT-SLIP-001(地毯轮滑):在地毯段运行,验证轮滑检测触发率、降速策略与不碰撞。(地毯:见《附件6…比赛规则》2–3 页) -- IT-DROP-001(侧向遮挡):遮挡一只 VL53 或一侧两只,验证降级切换时间与稳定性。 -- IT-CAN-FAULT-001(CAN 抖动/延迟注入):验证即使系统负载上升也不会超过 150 ms 不发合法 0x100。(《通讯协议》8–10 页) - -## 风险与替代方案 - -### 主要风险点与缓解 -- **通道极窄 + 尺寸误差 ±5%**:通道宽可能缩到约 38 cm,若车辆外廓/轮子外露估计不足,居中也可能刮擦。缓解:把“最小侧向间隙”作为硬安全约束,并支持按段设置 \(y_\text{offset}\)。 (尺寸误差:见《附件6…比赛规则》14 页) -- **测距盲区/遮挡/高反射干扰**:VL53L0X 在高速档噪声更大;缓解:关键动作切高精度 timing budget(200 ms)并降低速度;按 datasheet profile 做“模式-噪声-速度”联动。citeturn2search41 -- **前后测距冗余冲突**:两种前向传感器可能在某些目标材质/角度下给不同值;缓解:做一致性选择(例如取更保守的近距离值)+ 门限剔除。 -- **地毯轮滑导致里程计失真**:规则明确存在地毯(《附件6…比赛规则》2–3 页)。缓解:轮滑检测触发后降低对里程计的信任、降速并强化侧向闭环。 -- **CAN 带宽与实时性**:若日志/调试占用 CPU 或关中断过久,可能导致 0x100 抖动/丢帧;缓解:日志异步队列+独立低优先级 logger task;0x100 发送任务最高优先级,且即使停车也持续发合法帧。(0x100 硬约束:见《通讯协议》2–4 页、8–10 页) -- **计算资源不足**:若引入过重的规划(全局优化/TEB 等),会侵蚀硬实时;缓解:主线坚持 B 方案小维估计+简单控制;局部避障仅做轻量 DWA 风格采样,且可选。citeturn4search0 - -### 替代/增强方案 -- **A 方案度量定位 EKF/UKF 作为评估与恢复辅助**:在不依赖其做走廊闭环的前提下输出 (x,y,θ) 与协方差,用于段落切换一致性检查与日志评估(《大体方案》4 页)。 -- **K230 视觉作为测距降级备份**:K230 的双核 RISC‑V + KPU 适合推理后输出结构化特征,作为走廊偏差/地标观测源之一。citeturn6search3 -- **局部避障(可选)**:若赛场土块/障碍导致必须绕行,可引入 DWA 思想做速度空间采样;其原始工作在 IEEE Robotics and Automation Magazine 1997 年文章中系统阐述。citeturn4search0 - -## 代码生成与 AI 协作建议 - -### 为什么必须“接口契约优先” -你明确提到多数代码将由 AI 生成。要让 AI 代码可控,必须先把系统拆成“可替换模块 + 明确消息契约 + 可回归测试”。否则 AI 很容易在“看似能跑,但破坏实时性/破坏协议/破坏并发安全”的地方踩雷。 - -ASER 文档中已经明确:协议层与接收链路不要随意改动,新逻辑应放 App/ 并遵守现有任务框架。(《aser》1–5 页) - -### 建议的仓库结构与代码模板(示例) -建议在 `App/` 下新增(不动协议层): - -- `App/sensors/`:`vl53_driver.c/.h`、`stp23l_driver.c/.h`、`ms53_driver.c/.h`、`imu_z.c/.h` -- `App/preproc/`:`corridor_obs.c/.h`、`health_monitor.c/.h` -- `App/est/`:`corridor_filter.c/.h`(互补/EKF/UKF 可切换) -- `App/nav/`:`segment_fsm.c/.h`、`corridor_ctrl.c/.h`、`safety_supervisor.c/.h` -- `App/log/`:`logger_task.c/.h`、`replay.c/.h` -- `App/test/`:host 可编译的纯 C 测试(或 Unity/Ceedling/CppUTest) - -**接口契约头文件(强制先写)**:例如 `corridor_msgs.h` - -```c -#pragma pack(push,1) -typedef struct { - uint32_t t_ms; - float d_lf, d_lr, d_rf, d_rr; // meters - float d_front, d_back; // meters - uint8_t valid_mask; // bitfield -} CorridorObs_t; - -typedef struct { - uint32_t t_ms; - float e_y; // meters - float e_th; // radians - float s; // meters - float conf; // 0..1 or covariance proxy -} CorridorState_t; - -typedef struct { - uint32_t t_ms; - float v; // m/s - float w; // rad/s - uint8_t flags; -} RawCmd_t; -#pragma pack(pop) -``` - -### 单元测试规范(让 AI 代码“可验收”) -- **每个模块至少 3 类测试**:正常、边界、异常(离群/丢包/超时)。 -- **所有纯算法模块必须可在 Host 编译运行**(不依赖 HAL),把硬件依赖封装成接口(如 `read_range()` 函数指针或 mock)。 -- **协议相关测试必须比对字节级输出**:0x100 的 CRC/rolling counter/小端序是典型“AI 容易写错但编译不过不报错”的点。(《通讯协议》2–4 页) - -### 自动化生成与审查流程建议 -- 先由你/团队写“模块接口契约 + 时序约束表 + 禁止事项”(如“0x100 发送任务不得阻塞”),再让 AI 生成实现。 -- CI 至少包含: - 1) Host 单元测试; - 2) 静态检查(clang-tidy/cppcheck 任选); - 3) 构建固件; - 4) (可选)HIL 脚本:注入传感器回放数据,检查 0x100 发送间隔最大值与 counter 连续性。 -- Code review checklist(必须人工看): - - 是否出现长时间关中断/在高优先级任务里打印; - - 是否对共享上下文无保护读写导致撕裂; - - 是否更改了 `snc_can_app` 协议定义/接收链路(ASER 文档明确不建议破坏)。 (《aser》1–5 页) - ---- - -**参考资料(你上传的原始文档)** -- 《附件6:B类“马铃薯捡拾机器人竞技”比赛及评审规则》:赛场尺寸、40 cm 通道/出入口、地毯、5 分钟限时、尺寸误差 ±5%(1–3 页、14 页)。 -- 《通讯协议》:现有 H7↔F4 CAN 协议、0x100 20 ms/150 ms 超时、CRC8/rolling counter、0x181/0x184/0x200 定义与诊断位(2–10 页)。 -- 《aser》:ASER 工程结构、FreeRTOS 任务(20 ms/100 ms)、协议层位置与“不要破坏接收链路/协议层”的约束(1–5 页)。 -- 《大体方案》:B 方案状态与派生量测构造、走廊闭环思想、降级/恢复链与实施计划(4–5 页、13–16 页)。 - -**参考资料(官方/原始文档与论文)** -- ST VL53L0X 产品页(最大 2 m):citeturn2search3 -- ST VL53L0X 数据手册(timing budget 与 profile:20 ms/33 ms/200 ms 等):citeturn2search41 -- ST VL53L1X 产品页(up to 4 m、up to 50 Hz):citeturn0search0 -- STM32H743(480 MHz Cortex‑M7、双精度 FPU、TCM 等特性):citeturn1search1 -- FreeRTOS `vTaskDelayUntil()`(固定频率周期任务的绝对时间阻塞):citeturn3search34 -- FreeRTOS `vTaskNotifyGiveFromISR()`(ISR→任务通知):citeturn2search42 -- 创新 χ² 检验鲁棒 EKF(武汉大学学报):citeturn5search1 -- 马氏距离与 χ² 门限关系、鲁棒策略示例:citeturn5search0 -- UKF(Julier & Uhlmann 综述条目):citeturn4search8 -- DWA 原始工作(Fox/Burgard/Thrun 1997):citeturn4search0 -- K230 官方文档(CPU0 Linux/CPU1 RTOS、KPU INT8/INT16 等):citeturn6search3 \ No newline at end of file diff --git a/附件6:B类“马铃薯捡拾机器人竞技”比赛及评审规则.md b/附件6:B类“马铃薯捡拾机器人竞技”比赛及评审规则.md deleted file mode 100644 index 15c67bc..0000000 --- a/附件6:B类“马铃薯捡拾机器人竞技”比赛及评审规则.md +++ /dev/null @@ -1,27 +0,0 @@ -- 1 - “奥凯杯”第十一届国际大学生智能农业装备创新大赛 B 类“马铃薯捡拾机器人竞技”比赛及评审规则 一、比赛规则要点 1 、 马铃薯捡拾机器人可采用垄间作业或跨垄作业模式。 垄间作业模式, 机器人在比赛过程中需遍历所有 6 条垄沟;跨垄作业模式,机器人作业幅宽 只允许跨一个垄背,且比赛过程中需遍历所有 5 个垄背。 2 、比赛需要作业,每支队伍有两次机会,成绩取最优者。参赛机器人需 进行马铃薯捡拾作业,以作业速度和作业效果进行综合成绩评判。比赛中无 作业动作的参赛机器人,比赛成绩以 0 分计。 3 、比赛限时 5 分钟(含违章加罚比赛用时)。从 100 秒预备时间已到 之后,评委发出“起跑”命令后,机器人开始跨越起跑线开始计时,到参赛 机器人所有部位都离开比赛场地出入口终止计时。 在限定时间内未完成比赛 者,比赛成绩以 0 分计。 4 、 比赛结束后, 参赛机器人须驶离场地, 任何部位不得停留在场地内, 否则视为未完成比赛。离开场地后需要自主停在比赛启动区,未自主停止的 视为未完成比赛,自主停止但未完全停在比赛启动区的视为连续超界。 5 、各参赛单位可以派出多支参赛队。但每支参赛队都必须根据比赛要 求,自行设计(或组装)、制作各自的参赛机器人。限定每支参赛队只能有 1 台机器人参赛。 6 、比赛分专本组和硕博组两类,以队伍中学历最高者为分类依据。 - -- 2 - 二、比赛场地及作业要求 1 、 比赛场地 如图 1 所示。比赛场地为 390cm × 300cm 的区域,共有 5 条田垄。 场地四周用高 12cm 的围栏围住,只留有一个宽 40cm 的出入口,围栏 与田垄之间留有宽 40cm 的通道(垄沟),垄长 220cm 、垄宽 30cm 、垄 高 12cm ,相邻田垄之间也留有宽 40cm 的通道(垄沟)。出入口外侧紧 邻比赛场地的 40cm × 100cm 的区域为比赛启动区,尺寸如图 1 所示: 图 1 比赛场地简图 围栏和田垄可采用钢质或木制材料制作, 田垄为灰色, 围栏为黑色; 地面采用爬行垫铺设,爬行垫标准( 1. 颜色:灰色; 2. 材质: PE ; 3. 尺 - -- 3 - 寸:采用 60cm*60cm 标准尺寸进行拼接)。现场比赛时会从 6 条垄 沟中随机抽取两条垄沟,在其中放置宽 40cm 、长 300cm (即与垄沟等 长)的卡其色地毯,以模拟松软路面,地毯材质为丙纶,底部为防滑网 格底,厚度约 5.5mm ,所有场地毛毯布置均相同。如图 2 所示。 图 2 爬行垫及地毯 2 、马铃薯 马铃薯用榉木实心仿真鸽子蛋代替,有棕色和绿色 2 种,分别用 奶黄色和青绿色油漆喷涂,尺寸规格为外径 30mm ,长度 42mm ,重 量约 14g 。具体规格和形状如图 3 所示。 - -- 4 - 图 3 马铃薯示意图(单位 mm ) 3 、土块 土块使用黄色原积木代替, 因现实中有各种颜色土块, 为使比赛 更接近现实,故允许土块有色差,尺寸为 1.5cm 的立方体,具体如 图 4 。 - -- 5 - 图 4 土块 4 、 作业要求 参赛机器人需自行设计马铃薯载运装置,比赛时需将马铃薯从 田垄上捡拾起来放到小车上,比赛结束时将其运到比赛启动区,期 间马铃薯不能掉落。 5 、比赛场地布置 每条田垄放置若干颗马铃薯和若干颗土块, 在靠近出入口侧的田垄 长度中心线上每隔 20cm 做标记点,马铃薯在标记点处放置,方向为其 处长度方向与田垄长度中心线 45 °范围内任一方向;土块围绕马铃薯 随机放置,放置范围为以标记点为中心点,长 70mm 、高 75mm 的矩形 区域内随机放置。具体如下: ①专本组 : 每条田垄放置 2 颗棕色马铃薯、 每颗马铃薯附近随机放 置 4 颗土块,同一级别比赛马铃薯放置标记点位置相同。 - -- 6 - ②硕博组: 每条田垄放置 2 颗棕色马铃薯、 1 颗绿色马铃薯,绿色 马铃薯为干扰组,不得捡拾,每颗马铃薯附近随机放置 4 颗土块,同一 级别比赛马铃薯放置标记点位置相同,角度在规定范围内随机。 赛前组委会会设计 5 种硕博组场地布置方案并进行密封处理,决 赛现场由裁判或参赛队员现场随机抽取 1 种方案进行布置;其中专本 组绿色马铃薯位置不做任何布置,棕色马铃薯放置标记点位置与硕博 组相同。 三、比赛规则 比赛根据参赛队员中最高学历者设置专本组和硕博组 2 个级别, 分开比赛和统计成绩。每支队伍都有两次机会。 1. 比赛规则 ①根据参赛队伍情况, 设置多块比赛场地。 比赛前组委会会随机为 各参赛队分配一块场地, 各比赛场地内的参赛队抽签确定比赛顺序, 同 一队伍两次机会结束后, 下一队伍开始比赛。 各场地同时进行比赛。 同 一级别比赛的每块比赛场地毛毯、马铃薯的放置位置均相同。 ②比赛成绩根据参赛机器人“作业得分” “走过的通道数” “能 否驶出场地”“能否停在启动区”和“比赛用时”等进行评比。 ③限时 5 分钟内(含违章加罚比赛用时)未完全驶出场地的比 赛成绩为 0 分; ④驶出场地但所有部位都未停止在比赛启动区内(不含启动区 标线)的成绩为 0 分; - -- 7 - 2. 相关概念界定 ● 有效作业: 参赛机器人发现某个须捡拾马铃薯,控制作业装置对 其进行作业, 将马铃薯放置到小车上, 且过程中不掉落, 则视为一次有 效作业。 ● 无效作业: 参赛机器人发现某个须捡拾马铃薯,控制作业装置对 其进行作业, 但未将马铃薯放置到小车上, 或者放到小车上但比赛过程 中掉落,则视为一次无效作业。 ● 漏 捡: 参赛机器人在作业过程中未对某个须捡拾马铃薯进行捡拾 作业,则视为一次漏施。 ● 误捡: 参赛机器人在比赛过程中对绿色马铃薯进行作业,致其发 生位移或捡拾成功,则视为一次误捡。 ● 损伤 马铃薯 : 参赛机器人或作业装置的任何动作导致某个马铃薯 上产生划痕(长度≥ 1cm )等肉眼可见损伤 ,视为损伤。 ● 损伤、 损坏 2 颗及以内马铃薯等情况从已得作业分数中扣相应 分数; ● 损坏 马铃薯 : 参赛机器人或作业装置的任何动作导致使马铃薯发 生结构断裂、或使其形状发生严重变形等,视为损坏。 ● 损伤、损坏 3 颗及以上马铃薯,取消比赛成绩,直接罚下。 ● 违章 :在比赛过程中,如果机器人或作业装置的任何部分超出了 围栏边界,触碰到了围栏、垄测,则判为违章。违章次数为超界次数和 触碰次数之和,比赛时由工作人员现场判别并统计。 ● 驶离比赛场地 :在完成作业后,参赛机器人需要从出入口离开比 赛场地, 参赛机器人的任何部位不得停留在场地内 (按照俯视投影方法 判断),否则视为未完成比赛,成绩为 0 分。 - -- 8 - ● 停在比赛启动区 : 参赛机器人从比赛出口驶出后需要停在比赛启 动区内, 未主动停止的视为未完成比赛, 主动停止但未完全停在比赛启 动区的视为 1 次连续超界,按 2 次违章计算惩罚加时 。 ④比赛过程中不允许使用任何形式的遥控装置,如被裁判发现 或被举报查实,立即取消参赛资格。 ⑤如果机器人或作业装置在比赛过程中出现冲出场地、 失控、 部 件损坏、损坏场地(不含马铃薯、土块)等危险情况,则该参赛机器 人将被立即强制罚下,取消所有比赛成绩。 ⑥比赛开始后, 参赛人员不得以任何理由申请重试, 如因机器人 或作业装置故障而无法在规定时间内完成比赛的,本次比赛以失败 论处。 ⑦如果参赛人员不遵守裁判和工作人员的指示、 指令或警告, 或 做出任何有悖于公平竞争精神的行为,裁判有权直接取消该参赛队 的参赛资格。 3 、比赛过程 ①签到: 所有参赛队都必须在规定时间内到赛场签到, 由评委检 查参赛机器人及其作业装置是否符合比赛要求。检查通过后,关闭 参赛机器人电源,并由工作人员将参赛机器人统一放置在备赛区对 应号位。参赛选手之后不得再进行任何调试,违反者以作弊论处, 取消比赛资格。 ②铺设毛毯: 比赛前由裁判随机抽取确定。 同级别赛场的播种板 位置、毛毯铺设位置和铺设方式完全相同。 ③预备: 评委宣布 “ XX 号机器人进行比赛” 后, 工作人员将 XX 号参赛机器人从备赛区取出,放到比赛启动区。评委宣布“预备” - -- 9 - 后,开始预备计时。选手将参赛机器人放到起跑位置,可以给参赛 机器人上电,但参赛机器人的任何部位都不允许超出起跑线。选手 做好起跑准备后告知评委“已就位”。预备时间最长 100 秒。 ④起跑: 评委在参赛选手告知“已就位”之后,评委发出“起 跑”命令后,从小车跨越起始线开始计时;或 100 秒预备时间已到 之后,评委发出“起跑”命令时,开始计时。 参赛选手给参赛机器 人上电(也可提前上电),参赛机器人从比赛启动区出发进入比赛 场地。如在评委发出“起跑”命令之前参赛机器人或其作业装置就 已跨越起跑线则视为抢跑,评委给予警告,并重新起跑。抢跑两次 则比赛以失败论处,计 0 分。 ⑤比赛: 比赛过程中, 由工作人员记录机器人走过的通道数、 作 业得分、违章次数和比赛用时,由裁判确认是否驶出场地和停在启 动区。参赛机器人一旦从出入口驶出,则本次比赛结束。比赛时间 为 5 分钟,参赛机器人超时仍未完成比赛的,比赛也即刻中止。如 果发生机器人冲出场地、部件损坏、损坏场地等情况,裁判有权终 止比赛,且参赛机器人的比赛以失败论处。 ⑥统计和确认成绩: 工作人员统计参赛机器人是否驶出比赛场 地、走过的垄沟 / 垄背数、比赛用时、作业得分 ,参赛选手确认并签 字。如有异议,回放录像确认。 ⑦各参赛队都有两次比赛机会,比赛成绩取最高者。 4 、评分标准 ( 1 )作业得分计分规则 专本组评分标准 - -- 10 - 马铃薯颜色 马铃薯 数量 每颗 分值 评分 标准 棕色马铃薯 10 颗 10 有效作业得 10 分 硕博组评分标准 马铃薯颜色 马铃薯 数量 每颗 分值 评分 标准 棕色马铃薯 10 颗 10 有效作业得 10 分 绿色马铃薯 5 颗 20 绿色为干扰组,不得捡 拾,使其发生位移每颗 扣 5 分,捡拾成功每颗 扣 20 分 土块误捡扣分标准 土块误拾扣分标准 ( 最终误捡土块数量占总土块比例) 0% ≤误捡≤ 10% 10% <误捡≤ 30% 30% 误捡≤ 50% 50% <误捡 不扣分 扣最终作业得分 20 分 扣最终作业得分 40 分 最终作业得分 0 分 ①无效作业、漏捡:不得分也不扣分。 ②误捡: 捡拾成功(将绿色马铃薯捡拾到小车上)每颗扣 20 分 且次数累加,直至最终作业得分 0 分为止。绿色马铃薯发生位移按 5 分 / 颗,从已得作业分中扣除,直至最终作业得分 0 分为止。 ③ 损伤、损坏 2 颗及以内马铃薯 ,按 20 分 / 颗,从已得作业分中 扣除相应分数,直至最终作业得分 0 分为止 。 ④ 损伤、损坏 3 颗 及以上 马铃薯 ,取消比赛成绩,直接罚下。 ⑤ 超出围栏边界或触碰围栏、垄侧,按 10 秒 / 次,加罚比赛用 时。连续刮擦、推行或触碰,都按两次违章计算( 20 秒 / 次)。 ⑥ 触碰垄背不加罚比赛用时。 - -- 11 - ⑦如果连续超出围栏边界按 20 秒 / 边计算加罚比赛用时。 ( 2 )比赛成绩 比赛成绩综合考虑作业用时和作业得分,由两者经归一化处理 后相加得到。选手作业用时为 a ,作业得分为 b ,比赛成绩 S 为: S= max min max min max min 100 0.4 100 0.6 a a b b a a b b − − × × + × × − − 式中: 𝑎𝑎 𝑚𝑚𝑚𝑚𝑚𝑚 —— 所有选手中,作业用时的最大值; 𝑎𝑎 𝑚𝑚𝑖𝑖𝑖𝑖 —— 所有选手中,作业用时的最小值; 𝑏𝑏 𝑚𝑚𝑚𝑚𝑚𝑚 —— 所有选手中,作业得分的最大值; 𝑏𝑏 𝑚𝑚 𝑖𝑖𝑖𝑖 —— 所有选手中,作业得分的最小值。 ( 3 )获奖比例 决赛期间,大赛委员会根据当年参数规模情况决定各档次获奖 作品的数量。 四、参赛要求 1 、参赛机器人 ①参赛机器人应具有自主行走、 垄间穿行、 识别马铃薯和作业的 能力。 ②作业装置可背负在机器人上, 也可由机器人牵引。 机器人和作 业装置的大小和重量不限,但应尽量小巧,以提高作业灵活性。 ③在整个作业过程中,机器人和作业装置的任何部分都不允许 超出围栏边界,也不允许触碰围栏、垄,更不允许破坏比赛场地。 ④比赛场地周围环境无特殊设置,参赛机器人应能承受周围环 境的光线、噪音和电磁干扰。 ⑤同一参赛单位的任意两台参赛机器人都不可以雷同。如被裁 - -- 12 - 判质疑雷同,则对该参赛单位的所有类同参赛机器人的队长进行问 辩测试。如被裁判判定为雷同,则取消所有类同参赛机器人的参赛 资格,并判定成绩无效。 2 、参赛团队 ①参赛队员必须为 2025 年 9 月前(含 9 月)正式注册的全日制 非成人教育的普通高等学校和高职高专院校的在校学生,包括专科 生、本科生、硕博研究生。 ②本科及以上院校每个参赛单位最多可派出 8 支参赛队(承办 单位可以多派 5 支队伍),职业院校每个参赛单位最多可派出 5 支 参赛队伍。每位指导教师最多只能指导一支参赛队。 ③每支参赛队都必须根据比赛要求, 自行设计、 制作各自的参赛 机器人。限定每支参赛队只能有 1 台机器人参赛。 ④参赛队员由 2 ~ 5 名学生组成,须为在校专科生、本科生和硕 博研究生,不限学科专业,并指定学历最高者为队长。 ⑤允许最多 2 名队员在准备区内调试机器人。 五、比赛事宜 1 、 比赛过程 ( 1 )比赛开始前,各队有 100 秒的准备时间,将机器人置于比 赛区域的入口(启动区),并进行必要的调整,机器人可以加电,但 不得运动; ( 2 )比赛开始,机器人从启动区启动。如在指令前启动机器人 则判为抢跑,给予警告,第二次抢跑的机器人将被罚下; ( 3 )比赛过程中冲出场地的机器人将直接被罚下,不得重新进 场比赛, 比赛过程中, 如果出现机器人分离, 该机器人被强制罚下。 - -- 13 - 2 、 重试及断电 ( 1 )比赛开始后,任何机器人不得申请重试,如因故障而不能 运动,则自动退出比赛,为了机器人的安全和保护场地,裁判有权 将机器人断电并拿出场外; ( 2 )如机器人在场上出现故障或失控,裁判有权根据现场情况 要求该机器人断电并拿出场地。 3 、 取消比赛资格 参赛队的下列行为会被取消比赛资格。 ( 1 ) 机器人做出危险动作, 危及场上操作手或裁判、 观众安全; ( 2 )故意损坏比赛场地、道具; ( 3 )不遵守裁判发出的命令和警告; ( 4 )做出任何有悖公平竞争精神的行为。 六、比赛安全 安全是机器人比赛持续发展的最重要问题。 因此, 每位参赛者应 特别重视并有义务按照本节的规定在充分采取安全措施的前提下研 制机器人。 第一,所有机器人的制作不应给队员、裁判、工作人员、观众、 设备和比赛场地造成伤害。如果现场裁判认为机器人的行为对人员 或设备有潜在危险,可以禁止该机器人参赛或随时终止比赛。 第二,机器人的结构设计应该考虑到赛前机器人安全检查的方 便性。 第三,禁止使用燃油驱动的发动机、爆炸物、高压气体(超过 0.8MPa )等。 第四, 在参赛任何时段, 队员都必须充分注意安全问题。 指导教 - -- 14 - 师或教练应该负起安全指导和监督的责任。参赛期间必须考虑工作 人员和场馆内观众的安全。 七、比赛其它事项 第一, 裁判有权对本规则没有规定的任何行为做出裁决。 在有争 议的情况下,裁判长有权做出最终裁决。 第二,比赛场地及道具尺寸的允许误差为 ±5% 。 第三,重要通知和相关附录后续在官方网站发布。 第四, 比赛将根据报名情况确定赛制, 赛制将在比赛前在官方网 站上发布。 第五, 规则如有更新, 比赛将在官方网站上发布, 以比赛开始前 最后发布的规则为准。 第六,鼓励参赛队在规则允许的范围内以自己的方式装饰机器 人。 第七, 比赛过程中不得使用通讯装置操控机器人, 一旦发现, 以 作弊论处。 第八,如果有需要,比赛将在合适的时间要求各参赛队提交机 器人相关资料、进度报告和录像。 第九,规则的最终解释说明权归大赛委员会所有。 第十一届国际大学生智能农业装备创新大赛委员会 2025 年 9 月 10 日 \ No newline at end of file