# 底盘标定算法模板合同

本文档固定底盘标定算法实现边界。算法同事只需要填充四个底盘专属文件，不应改 node、gateway、orchestrator、report 或现场采集工具。

## 填充文件

- `src/core/agv_calib_core/chassis_calibration_service/src/ackermann_chassis_algorithm.cpp`
- `src/core/agv_calib_core/chassis_calibration_service/src/differential_chassis_algorithm.cpp`
- `src/core/agv_calib_core/chassis_calibration_service/src/single_steer_wheel_chassis_algorithm.cpp`
- `src/core/agv_calib_core/chassis_calibration_service/src/multi_steer_wheel_chassis_algorithm.cpp`

## 统一输入

四类算法都从 `ChassisCalibrationInput` 读取输入：

- `input.request`：动作原语请求、`request_id`、任务目的、速度、距离、超时等。
- `input.vehicle_profile`：车辆静态画像、底盘类型、车辆 ID、基础几何和能力配置。
- `input.chassis_type`：算法分发后的底盘类型。
- `input.chassis_capability`、`input.chassis_readiness`、`input.chassis_work_mode`：底盘能力和状态。
- `input.applied_chassis_parameters`：当前已生效底盘参数，作为拟合初值或对照基线。
- `input.latest_chassis_telemetry`、`input.chassis_telemetry_history`：轻量在线遥测。
- `input.latest_external_localization_telemetry`、`input.external_localization_telemetry_history`：轻量外部真值状态。
- `input.data_window_start_timestamp_us`、`input.data_window_end_timestamp_us`：本次数据窗口。
- `input.chassis_motion_data_files`：底盘遥测 CSV。
- `input.actuator_command_files`：执行器命令 CSV。
- `input.truth_trajectory_files`：外部真值轨迹 CSV。

真实标定优先读取三类 CSV。CSV 字段协议见 `src/site_deployment/workshop_chassis_calibration_real/chassis_csv_contract.md`。

## 动作原语输入

通用模板入口已经放行并校验这些动作原语：

- `STRAIGHT_LINE`：要求 `target_distance_m > 0`、`target_speed_ms > 0`。
- `ARC`：要求 `target_speed_ms > 0`、`radius_m > 0`、`sweep_angle_deg != 0`。
- `IN_PLACE_ROTATION`：要求 `target_yaw_deg != 0`、`target_angular_vel_deg_s > 0`。
- `STEERING_SWEEP`：要求目标角为有效数字，且幅值、频率、持续时间都大于 0。
- `LATERAL_TRANSLATION`：要求 `target_speed_ms > 0`、`target_distance_m > 0`。
- `DIAGONAL_MOTION`：要求 `target_speed_ms > 0`、`target_distance_m > 0`，运动方向角为有效数字。
- `MODULE_ALIGNMENT`：要求模块 ID 非空，零位角为有效数字，容差大于 0。
- `COORDINATED_STEERING`：要求模块 ID 非空，目标角为有效数字，保持时间大于 0。

所有动作原语还要求 `timeout_sec > 0`。通用模板只做字段合法性检查，不在这一层强行限制“某种底盘只能跑哪些动作”；具体算法可以按底盘类型和现场能力继续做更严格的组合检查。

现场动作序列的默认模板见 `src/site_deployment/workshop_chassis_calibration_real/config/chassis_action_profile.yaml`。该文件用于固定四类底盘各自要跑的动作组合，算法实现方可以按 `task_code` 或 `primitive_type` 区分不同数据段。

## 统一输出

四类算法都必须回填 `output.response.result`：

- `success`：算法是否完成。
- `error_code`：成功为 OK，失败必须写非 OK 错误码。
- `message`：简短结果说明。
- `job_id`：沿用 `input.request.goal.header.request_id`。
- `data_quality_passed`：输入数据是否满足求解条件。
- `suitable_for_commit`：是否建议进入参数提交或人工确认。
- `recommended_parameter_version`：本轮结果版本号。
- `estimated_straight_line_bias`：直线跑偏估计。
- `validation_summary`：验收指标。
- `estimated_params`：本轮估计底盘参数。
- `artifacts`：结果 YAML、诊断 JSON、拟合残差 CSV、图表等产物引用。

算法完成但质量不达标时，允许 `success=true`、`data_quality_passed=true`、`suitable_for_commit=false`。采集数据不足、时间同步不可靠、真值缺失、底盘状态不安全时，应返回 `false` 并写清楚 `failure_reason`。

## 验收指标

`validation_summary` 至少要填：

- `max_lateral_error_m`
- `max_yaw_error_rad`
- `rms_lateral_error_m`
- `rms_yaw_error_rad`
- `repeatability_error_m`
- `curvature_error`
- `module_consistency_error`
- `auto_acceptance_passed`

这些指标用于总控 stage result 和最终 report。真实算法不能只写默认 0 值后直接声明可提交。

## 阿克曼底盘

目标参数：

- `estimated_params.selected_specific_params.value = ACKERMANN`
- `estimated_params.ackermann.front_left_steer_zero_offset_deg`
- `estimated_params.ackermann.front_right_steer_zero_offset_deg`
- `estimated_params.ackermann.rear_left_wheel_radius_m`
- `estimated_params.ackermann.rear_right_wheel_radius_m`
- `estimated_params.ackermann.steering_ratio`
- 可选通用参数：`common.effective_wheel_base_m`、`common.longitudinal_scale`、`common.yaw_scale`、`common.straight_line_bias`

建议输入动作：直线、圆弧、舵角扫动。

## 差速轮底盘

已确认目标参数：

- `estimated_params.selected_specific_params.value = DIFFERENTIAL`
- `estimated_params.differential.left_wheel_radius_m`
- `estimated_params.differential.right_wheel_radius_m`
- `estimated_params.differential.axle_track_width_m`
- 可选：`left_encoder_scale`、`right_encoder_scale`
- 可选通用参数：`common.longitudinal_scale`、`common.yaw_scale`、`common.straight_line_bias`

建议输入动作：直线、原地旋转、左右转弯。只用直线数据通常不足以稳定估计轮距。

## 单舵轮底盘

预留目标参数：

- `estimated_params.selected_specific_params.value = SINGLE_STEER`
- `estimated_params.single_steer.drive_wheel_radius_m`
- `estimated_params.single_steer.steer_zero_offset_deg`
- `estimated_params.single_steer.steering_ratio`
- `estimated_params.single_steer.drive_encoder_scale`
- 可选通用参数：`common.effective_wheel_base_m`、`common.longitudinal_scale`、`common.yaw_scale`

建议输入动作：直线、舵角扫动、圆弧。

## 多舵轮底盘

预留目标参数：

- `estimated_params.selected_specific_params.value = MULTI_STEER`
- `estimated_params.multi_steer.modules[].module_id`
- `estimated_params.multi_steer.modules[].wheel_radius_m`
- `estimated_params.multi_steer.modules[].steer_zero_offset_deg`
- `estimated_params.multi_steer.modules[].module_pos_x_m`
- `estimated_params.multi_steer.modules[].module_pos_y_m`
- 可选通用参数：`common.longitudinal_scale`、`common.lateral_scale`、`common.yaw_scale`

建议输入动作：直线、横移、斜移、模块零位检查、模块协同转向。

## 产物要求

建议每次真实算法至少输出两个产物：

- 参数结果 YAML：记录车辆 ID、会话 ID、算法版本、输入文件、估计参数、是否建议提交。
- 诊断 JSON：记录样本数、时间窗口、有效运动距离、真值质量、残差摘要、失败原因或质量警告。

产物通过 `output.response.result.artifacts` 返回，最终 report 会引用这些文件。

## 参数提交边界

算法不直接写车端参数。真实算法完成后，应先输出底盘参数 YAML，字段模板见 `src/site_deployment/workshop_chassis_calibration_real/config/chassis_estimated_params_template.yaml`。

现场侧再调用：

```bash
python3 src/site_deployment/workshop_chassis_calibration_real/stage_chassis_parameter_commit.py \
  --dataset-index /data/agv_calib/site_a/session_001/dataset_index.yaml \
  --estimated-params /data/agv_calib/site_a/session_001/chassis/estimated_params.yaml
```

该工具只生成待审批/待提交参数包，不假装写入真实车端。真正的持久化写入由后续车端参数写入适配器完成，并以待提交包中的摘要和版本作为输入。

现场会话推荐统一走收尾入口：

```bash
python3 src/deployment/tools/finalize_site_session.py \
  --session-dir /data/agv_calib/site_a/session_001 \
  --dataset-index /data/agv_calib/site_a/session_001/dataset_index.yaml \
  --chassis-estimated-params /data/agv_calib/site_a/session_001/chassis/estimated_params.yaml
```

该入口会把底盘待提交包路径、参数版本、审批状态和算法输出参数文件写回 `dataset_index.yaml` 的 `metadata`。总控最终 report 会读取这些字段，把 `estimated_params.yaml` 和 `pending_chassis_commit.yaml` 放入 `report_files`，并在 report metadata 中给出底盘待提交状态。

人工审批后，车间电脑侧再调用：

```bash
python3 src/site_deployment/workshop_chassis_calibration_real/approve_chassis_pending_parameters.py \
  /data/agv_calib/site_a/session_001/chassis/pending_chassis_commit.yaml \
  --operator-id operator_001
```

该工具只在车间电脑侧完成审批、摘要复核和交接包生成，不调用车端写参服务。最终链路固定为：车端执行动作，车间电脑采集数据并运行算法，车间电脑生成待提交包和已审批交接包；车端写入适配器后续再消费这个交接包。
