syntax = "proto3";

package agv.calibration.chassis;

import "calibration_common.proto";
import "vehicle_profile.proto";

// =========================================================
// 单位约定：
// 1) 所有“状态量、结果量、误差量、位姿量”中的角度统一使用 rad
// 2) 所有“人工输入更直观的命令量、限幅量、目标角度”允许使用 deg
// 3) 字段名必须显式带单位后缀，例如 _rad / _deg / _m / _ms
// 4) 服务端与客户端都必须严格按字段后缀做单位转换，禁止隐式假定
// =========================================================

// =========================================================
// 文件作用：底盘标定执行代理协议
// 运行关系：
// Ubuntu 车间电脑(Linux) -> Windows 车端代理
// 说明：
// 1) Linux 负责底盘参数求解、误差分析、自动验收、验证判断
// 2) Windows 车端只负责执行动作、回传原始状态、写入参数
// 3) 该协议同时覆盖：底盘预检 / 数据采集 / 参数验证 / 参数写入
// =========================================================

// =========================================================
// 服务：底盘标定服务
// 运行位置：Windows 车端电脑
// 调用方：Ubuntu 车间电脑
// =========================================================
service AgvCalibChassisService {
  // 心跳保活
  rpc Heartbeat(.agv.calibration.common.HeartbeatRequest)
      returns (.agv.calibration.common.HeartbeatResponse);

  // 查询底盘服务当前是否具备执行条件
  rpc GetChassisReadiness(.agv.calibration.common.AgentReadinessRequest)
      returns (ChassisReadinessResponse);

  // 设置底盘标定工作模式
  rpc SetChassisWorkMode(ChassisWorkModeRequest)
      returns (.agv.calibration.common.StandardResponse);

  // 查询车端底盘能力
  rpc GetChassisCapability(ChassisCapabilityRequest)
      returns (ChassisCapabilityResponse);

  // 启动一个底盘动作原语任务
  rpc StartMotionPrimitive(MotionPrimitiveRequest)
      returns (.agv.calibration.common.JobAccepted);

  // 查询底盘任务状态
  rpc GetChassisJobStatus(.agv.calibration.common.JobQuery)
      returns (.agv.calibration.common.JobStatus);

  // 查询底盘任务结果
  rpc GetChassisJobResult(.agv.calibration.common.JobQuery)
      returns (ChassisJobResult);

  // 取消底盘任务
  rpc CancelChassisJob(.agv.calibration.common.JobQuery)
      returns (.agv.calibration.common.StandardResponse);

  // 打开底盘遥测流
  rpc StreamChassisTelemetry(StreamChassisTelemetryRequest)
      returns (stream ChassisTelemetry);

  // 写入底盘标定结果
  rpc CommitChassisCalibrationParameters(CommitChassisCalibrationParametersRequest)
      returns (.agv.calibration.common.StandardResponse);

  // 查询当前已生效底盘标定参数
  rpc GetAppliedChassisCalibrationParameters(GetAppliedChassisCalibrationParametersRequest)
      returns (AppliedChassisCalibrationParametersResponse);

  // 紧急刹停
  rpc EmergencyBrake(.agv.calibration.common.Empty)
      returns (.agv.calibration.common.StandardResponse);
}

// =========================================================
// 底盘工作模式
// 作用：切换底盘到标定准备、直接执行、验证等模式
// =========================================================
message ChassisWorkModeRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头

  enum Mode {
    CHASSIS_MODE_UNSPECIFIED = 0; // 未指定
    NORMAL_MODE = 1;              // 正常业务模式
    CALIBRATION_READY_MODE = 2;   // 标定准备模式
    DIRECT_EXECUTION_MODE = 3;    // 允许直接执行原始动作命令
    VALIDATION_MODE = 4;          // 底盘参数验证模式
  }

  Mode target_mode = 2; // 目标模式
  string reason = 3;    // 切换原因
}

// =========================================================
// 底盘服务就绪响应
// 作用：返回当前底盘服务是否满足执行条件
// =========================================================
message ChassisReadinessResponse {
  bool success = 1;                                  // 是否成功
  .agv.calibration.common.ErrorCode error_code = 2; // 错误码
  string message = 3;                                // 说明

  bool agent_ready = 4;              // 服务本身是否就绪
  bool chassis_driver_online = 5;    // 底盘驱动是否在线
  bool motion_control_ready = 6;     // 运控链路是否可执行动作
  bool estop_released = 7;           // 急停是否释放
  bool vehicle_safe_to_move = 8;     // 当前车辆是否允许移动
  bool telemetry_available = 9;      // 是否可回传遥测
  repeated .agv.calibration.common.ReadinessIssue issues = 10; // 不满足项
  int64 checked_timestamp_us = 11;   // 检查时间
}

// =========================================================
// 查询底盘能力请求
// 作用：运行前确认当前车辆支持哪些动作
// =========================================================
message ChassisCapabilityRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
}

// =========================================================
// 查询底盘能力响应
// 作用：返回当前车辆底盘形式和支持的动作原语
// =========================================================
message ChassisCapabilityResponse {
  bool success = 1;                                      // 是否成功
  .agv.calibration.common.ErrorCode error_code = 2;     // 错误码
  string message = 3;                                    // 说明
  .agv.calibration.vehicle.profile.ChassisType chassis_type = 4; // 底盘类型

  bool supports_straight_line = 5;        // 是否支持直线动作
  bool supports_arc = 6;                  // 是否支持圆弧动作
  bool supports_in_place_rotation = 7;    // 是否支持原地旋转
  bool supports_steer_sweep = 8;          // 是否支持舵角扫动
  bool supports_reverse_motion = 9;       // 是否支持倒车动作

  bool supports_lateral_translation = 10; // 是否支持横移动作
  bool supports_diagonal_motion = 11;     // 是否支持斜移动作
  bool supports_module_alignment_check = 12; // 是否支持模块零位检查
  bool supports_coordinated_steering = 13;   // 是否支持模块协同转向
}

// =========================================================
// 直线动作命令
// 作用：用于验证直线行驶能力和线速度误差
// =========================================================
message StraightLineCommand {
  double target_speed_ms = 1;   // 目标线速度（m/s）
  double target_distance_m = 2; // 目标距离（m）
  bool reverse = 3;             // 是否倒车
}

// =========================================================
// 圆弧动作命令
// 作用：用于验证曲线行驶能力和曲率误差
// =========================================================
message ArcCommand {
  double target_speed_ms = 1;  // 目标线速度（m/s）
  double radius_m = 2;         // 目标半径（m）
  double sweep_angle_deg = 3;  // 圆弧扫角（度）
  bool clockwise = 4;          // 是否顺时针
}

// =========================================================
// 原地旋转动作命令
// 作用：用于差速、多舵轮等底盘的旋转能力测试
// =========================================================
message InPlaceRotationCommand {
  double target_yaw_deg = 1;           // 目标旋转角（度）
  double target_angular_vel_deg_s = 2; // 目标角速度（度/秒）
}

// =========================================================
// 舵角扫动命令
// 作用：用于阿克曼、单舵轮、多舵轮的转向零位和转向响应测试
// =========================================================
message SteeringSweepCommand {
  double target_angle_deg = 1;    // 目标舵角（度）
  double sweep_amplitude_deg = 2; // 扫动幅值（度）
  double sweep_frequency_hz = 3;  // 扫动频率（Hz）
  double duration_sec = 4;        // 持续时长（秒）
}

// =========================================================
// 横移动作命令
// 作用：用于多舵轮底盘横向平移能力测试
// =========================================================
message LateralTranslationCommand {
  double target_speed_ms = 1;     // 目标横移速度（m/s）
  double target_distance_m = 2;   // 目标横移距离（m）
  bool move_left = 3;             // 是否向左移动
}

// =========================================================
// 斜移动作命令
// 作用：用于多舵轮底盘斜向运动能力测试
// =========================================================
message DiagonalMotionCommand {
  double target_speed_ms = 1;     // 目标速度（m/s）
  double target_distance_m = 2;   // 目标距离（m）
  double heading_deg = 3;         // 目标运动方向角（度）
}

// =========================================================
// 模块零位检查命令
// 作用：用于多舵轮每个舵轮模块零位与安装状态检查
// =========================================================
message ModuleAlignmentCheckCommand {
  repeated string module_ids = 1; // 待检查模块 ID 列表
  double target_zero_deg = 2;     // 目标零位角（度）
  double tolerance_deg = 3;       // 允许误差（度）
}

// =========================================================
// 模块协同转向命令
// 作用：用于多舵轮模块协同转向与一致性测试
// =========================================================
message CoordinatedSteeringCommand {
  repeated string module_ids = 1; // 参与测试的模块 ID 列表
  double target_angle_deg = 2;    // 目标舵角（度）
  double hold_time_sec = 3;       // 保持时长（秒）
}

// =========================================================
// 底盘动作原语请求
// 作用：让车端执行一个标准化动作
// 发送方：Ubuntu 车间电脑
// 接收方：Windows 车端代理
// =========================================================
message MotionPrimitiveRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
  string test_case_id = 2;                          // 测试用例 ID

  enum TaskPurpose {
    CHASSIS_TASK_PURPOSE_UNSPECIFIED = 0; // 未指定
    DATA_COLLECTION = 1;                  // 数据采集
    VALIDATION = 2;                       // 参数验证
    DIRECT_CHECK = 3;                     // 直接检查
  }

  TaskPurpose task_purpose = 3; // 任务目的

  oneof primitive {
    StraightLineCommand straight_line = 4;            // 直线动作
    ArcCommand arc = 5;                               // 圆弧动作
    InPlaceRotationCommand in_place_rotation = 6;     // 原地旋转
    SteeringSweepCommand steering_sweep = 7;          // 舵角扫动
    LateralTranslationCommand lateral_translation = 8; // 横移
    DiagonalMotionCommand diagonal_motion = 9;         // 斜移
    ModuleAlignmentCheckCommand module_alignment = 10; // 模块零位检查
    CoordinatedSteeringCommand coordinated_steering = 11; // 模块协同转向
  }

  bool brake_when_finished = 12; // 结束后是否刹停
  double timeout_sec = 13;       // 任务超时时间
  string source_iteration_id = 14; // 来源迭代号
}

// =========================================================
// 底盘遥测流请求
// 作用：指定底盘遥测内容和频率
// =========================================================
message StreamChassisTelemetryRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
  uint32 expected_hz = 2;                           // 期望上报频率
  bool include_odom = 3;                            // 是否包含里程计
  bool include_wheel_state = 4;                     // 是否包含轮组状态
  bool include_driver_state = 5;                    // 是否包含驱动器状态
  bool include_module_state = 6;                    // 是否包含模块级状态
}

// =========================================================
// 单个轮 / 舵模块状态
// 作用：兼容差速、单舵轮、多舵轮、阿克曼等形式
// =========================================================
message WheelModuleState {
  string module_id = 1;         // 模块 ID，例如 fl / fr / drive_center
  int64 encoder_ticks = 2;      // 编码器累计脉冲
  double wheel_speed_rpm = 3;   // 当前轮速（RPM）
  double steer_angle_deg = 4;   // 当前舵角（度），无舵角则可置 0
  double motor_current_amp = 5; // 电机电流（A）
}

// =========================================================
// 底盘遥测数据
// 作用：回传原始底盘状态供 Linux 做误差分析
// 发送方：Windows 车端代理
// 接收方：Ubuntu 车间电脑
// =========================================================
message ChassisTelemetry {
  int64 hardware_timestamp_us = 1; // 硬件时间戳
  .agv.calibration.vehicle.profile.ChassisType chassis_type = 2; // 当前底盘类型

  double odom_x_m = 3;           // 车端里程计 X（m）
  double odom_y_m = 4;           // 车端里程计 Y（m）
  double odom_yaw_rad = 5;       // 车端里程计偏航角（rad）
  double linear_velocity_ms = 6; // 实际线速度（m/s）
  double angular_velocity_rads = 7; // 实际角速度（rad/s）

  repeated WheelModuleState modules = 8; // 所有轮 / 舵模块状态

  bool estop_engaged = 9;        // 是否急停
  uint32 driver_error_code = 10; // 驱动器错误码
  string active_job_id = 11;     // 当前任务 ID

  double lateral_slip_estimate = 12; // 估计横向滑移
  double curvature_estimate = 13;    // 估计曲率
}

// =========================================================
// 通用底盘参数
// 作用：不同底盘形式都可能共用的几何 / 补偿参数
// =========================================================
message CommonChassisCalibrationParams {
  optional double effective_wheel_base_m = 1;  // 有效轴距（m）
  optional double effective_track_width_m = 2; // 有效轮距（m）
  optional double longitudinal_scale = 3;      // 纵向里程比例补偿
  optional double lateral_scale = 4;           // 横向里程比例补偿
  optional double yaw_scale = 5;               // 航向比例补偿
  optional double straight_line_bias = 6;      // 直线跑偏补偿
}

// =========================================================
// 阿克曼专属参数
// 作用：适用于阿克曼车
// =========================================================
message AckermannCalibrationParams {
  optional double front_left_steer_zero_offset_deg = 1;  // 左前舵角零偏
  optional double front_right_steer_zero_offset_deg = 2; // 右前舵角零偏
  optional double rear_left_wheel_radius_m = 3;          // 左后轮有效半径
  optional double rear_right_wheel_radius_m = 4;         // 右后轮有效半径
  optional double steering_ratio = 5;                    // 转向传动比
}

// =========================================================
// 差速专属参数
// 作用：适用于差速 AGV
// =========================================================
message DifferentialCalibrationParams {
  optional double left_wheel_radius_m = 1;  // 左轮有效半径
  optional double right_wheel_radius_m = 2; // 右轮有效半径
  optional double axle_track_width_m = 3;   // 驱动轮间距
  optional double left_encoder_scale = 4;   // 左编码器比例系数
  optional double right_encoder_scale = 5;  // 右编码器比例系数
}

// =========================================================
// 单舵轮专属参数
// 作用：适用于单舵轮 AGV
// =========================================================
message SingleSteerWheelCalibrationParams {
  optional double drive_wheel_radius_m = 1;  // 驱动轮有效半径
  optional double steer_zero_offset_deg = 2; // 舵角零偏
  optional double steering_ratio = 3;        // 转向比
  optional double drive_encoder_scale = 4;   // 驱动编码器比例
}

// =========================================================
// 多舵轮单模块参数
// 作用：用于多舵轮车每个模块的独立参数
// =========================================================
message SteeringModuleCalibrationParam {
  string module_id = 1;                      // 模块 ID
  optional double wheel_radius_m = 2;        // 模块轮半径
  optional double steer_zero_offset_deg = 3; // 模块舵角零偏
  optional double module_pos_x_m = 4;        // 模块在 base_link 下的 X
  optional double module_pos_y_m = 5;        // 模块在 base_link 下的 Y
}

// =========================================================
// 多舵轮专属参数
// 作用：适用于多舵轮 AGV
// =========================================================
message MultiSteerWheelCalibrationParams {
  repeated SteeringModuleCalibrationParam modules = 1; // 各舵轮模块参数
}

// =========================================================
// 底盘标定参数总包
// 作用：统一表达不同底盘类型的标定结果
// =========================================================
message ChassisCalibrationParameterSet {
  .agv.calibration.vehicle.profile.ChassisType chassis_type = 1; // 底盘类型
  CommonChassisCalibrationParams common = 2;                     // 通用参数

  oneof specific_params {
    AckermannCalibrationParams ackermann = 3;        // 阿克曼参数
    DifferentialCalibrationParams differential = 4;  // 差速参数
    SingleSteerWheelCalibrationParams single_steer = 5; // 单舵轮参数
    MultiSteerWheelCalibrationParams multi_steer = 6;   // 多舵轮参数
  }
}

// =========================================================
// 底盘验证摘要
// 作用：返回底盘专项自动验收的关键指标
// =========================================================
message ChassisValidationSummary {
  double max_lateral_error_m = 1;     // 最大横向误差
  double max_yaw_error_rad = 2;       // 最大航向误差
  double rms_lateral_error_m = 3;     // 横向误差均方根
  double rms_yaw_error_rad = 4;       // 航向误差均方根
  double repeatability_error_m = 5;   // 重复性误差
  double curvature_error = 6;         // 曲率误差
  double module_consistency_error = 7; // 模块一致性误差
  bool auto_acceptance_passed = 8;    // 自动验收是否通过
}

// =========================================================
// 写入底盘标定参数请求
// 作用：将 Linux 求解结果写入车端
// =========================================================
message CommitChassisCalibrationParametersRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
  string parameter_version = 2;                     // 参数版本号
  ChassisCalibrationParameterSet params = 3;        // 参数总包
  string commit_reason = 4;                         // 写入原因
  .agv.calibration.common.FileDigest digest = 5;   // 参数摘要
  bool persistent_write = 6;                        // 是否持久化
}

// =========================================================
// 查询当前已生效底盘参数请求
// =========================================================
message GetAppliedChassisCalibrationParametersRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
}

// =========================================================
// 查询当前已生效底盘参数响应
// =========================================================
message AppliedChassisCalibrationParametersResponse {
  bool success = 1;                                  // 是否成功
  .agv.calibration.common.ErrorCode error_code = 2; // 错误码
  string message = 3;                                // 说明
  string parameter_version = 4;                      // 当前版本
  ChassisCalibrationParameterSet params = 5;         // 当前生效参数
  int64 applied_timestamp_us = 6;                    // 生效时间
}

// =========================================================
// 底盘任务结果
// 作用：返回底盘动作执行后的分析摘要，供编排器判断是否可进入下一步
// =========================================================
message ChassisJobResult {
  bool success = 1;                                  // 是否成功
  .agv.calibration.common.ErrorCode error_code = 2; // 错误码
  string message = 3;                                // 说明
  string job_id = 4;                                 // 任务 ID

  bool data_quality_passed = 5;             // 数据质量是否达标
  bool suitable_for_commit = 6;             // 是否适合写入参数
  string recommended_parameter_version = 7; // 推荐参数版本

  double estimated_straight_line_bias = 8;  // 估计的直线跑偏
  ChassisValidationSummary validation_summary = 9; // 验证摘要
  ChassisCalibrationParameterSet estimated_params = 10; // 本轮估计参数
  repeated .agv.calibration.common.FileReference artifacts = 11; // 关联产物
}