syntax = "proto3";

package agv.calibration.control;

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) 控制器明确区分为“横向控制器”和“纵向控制器”
// 4) 本文件已将横向 MPC 与纵向 MPC 参数模型拆开
// =========================================================

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

  // 查询控制服务当前是否具备执行条件
  rpc GetControlReadiness(.agv.calibration.common.AgentReadinessRequest)
      returns (ControlReadinessResponse);

  // 设置调参工作模式
  rpc SetControlWorkMode(ControlWorkModeRequest)
      returns (.agv.calibration.common.StandardResponse);

  // 热加载一版控制参数
  rpc InjectControllerParameters(InjectControllerParametersRequest)
      returns (.agv.calibration.common.StandardResponse);

  // 启动一个控制评估任务
  rpc StartControllerEvaluation(ControllerEvaluationRequest)
      returns (.agv.calibration.common.JobAccepted);

  // 查询控制评估任务状态
  rpc GetControlJobStatus(.agv.calibration.common.JobQuery)
      returns (.agv.calibration.common.JobStatus);

  // 查询控制评估任务结果
  rpc GetControlJobResult(.agv.calibration.common.JobQuery)
      returns (ControlJobResult);

  // 取消控制评估任务
  rpc CancelControlJob(.agv.calibration.common.JobQuery)
      returns (.agv.calibration.common.StandardResponse);

  // 打开控制遥测流
  rpc StreamControlTelemetry(StreamControlTelemetryRequest)
      returns (stream ControlTelemetry);

  // 固化最终控制参数
  rpc CommitControllerParameters(CommitControllerParametersRequest)
      returns (.agv.calibration.common.StandardResponse);

  // 查询当前已生效控制参数
  rpc GetActiveControllerParameters(GetActiveControllerParametersRequest)
      returns (ActiveControllerParametersResponse);

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

// =========================================================
// 运控工作模式
// 作用：切换控制系统到调试、评估、验证等状态
// =========================================================
message ControlWorkModeRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头

  enum Mode {
    CONTROL_MODE_UNSPECIFIED = 0; // 未指定
    NORMAL_MODE = 1;              // 正常模式
    TUNING_READY_MODE = 2;        // 调参准备模式
    EVALUATION_MODE = 3;          // 参数评估模式
    VALIDATION_MODE = 4;          // 参数验证模式
  }

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

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

  bool agent_ready = 4;              // 服务本身是否就绪
  bool trajectory_executor_ready = 5; // 轨迹执行器是否就绪
  bool vehicle_feedback_ready = 6;    // 车辆反馈链路是否就绪
  bool control_output_ready = 7;      // 控制输出链路是否就绪
  bool estop_released = 8;            // 急停是否释放
  bool vehicle_safe_to_move = 9;      // 当前车辆是否允许移动
  repeated .agv.calibration.common.ReadinessIssue issues = 10; // 不满足项
  int64 checked_timestamp_us = 11;    // 检查时间

  bool external_pose_feedback_ready = 12; // 外部真值 / 定位位姿输入是否就绪
  string external_pose_source_name = 13;  // 当前外部位姿源名称
  double external_pose_age_ms = 14;       // 最近一帧外部位姿年龄
  double external_pose_quality_score = 15; // 最近一帧外部位姿质量分数
  string external_pose_transport = 16;    // 外部位姿传输方式，例如 wifi6
}

// =========================================================
// PID 参数
// 作用：PID 控制器参数
// 说明：适用于横向或纵向，但需由 control_axis 配合解释
// =========================================================
message PIDParams {
  string loop_name = 1;               // 回路名，例如 lateral / heading / speed
  double kp = 2;                      // 比例系数
  double ki = 3;                      // 积分系数
  double kd = 4;                      // 微分系数
  optional double integral_limit = 5; // 积分限幅
  optional double output_limit = 6;   // 输出限幅
}

// =========================================================
// 横向 MPC 参数
// 作用：适用于横向控制器的 MPC 参数
// =========================================================
message LateralMPCParams {
  uint32 prediction_horizon = 1;      // 预测步长
  uint32 control_horizon = 2;         // 控制步长
  double model_dt_s = 3;              // 离散时间步长
  double q_lateral = 4;               // 横向误差权重
  double q_heading = 5;               // 航向误差权重
  double r_steering = 6;              // 转向输出权重
  double r_steering_rate = 7;         // 转向变化率权重
  optional double steering_limit_deg = 8; // 转向限幅
}

// =========================================================
// 纵向 MPC 参数
// 作用：适用于纵向控制器的 MPC 参数
// =========================================================
message LongitudinalMPCParams {
  uint32 prediction_horizon = 1;      // 预测步长
  uint32 control_horizon = 2;         // 控制步长
  double model_dt_s = 3;              // 离散时间步长
  double q_speed = 4;                 // 速度误差权重
  double q_accel = 5;                 // 加速度权重
  double r_throttle = 6;              // 油门 / 驱动输出权重
  double r_brake = 7;                 // 制动输出权重
  double r_jerk = 8;                  // jerk 权重
  optional double throttle_limit = 9; // 驱动输出限幅
  optional double brake_limit = 10;   // 制动输出限幅
}

// =========================================================
// LQR 参数
// 作用：LQR 控制器参数
// 说明：通常用于横向控制器
// =========================================================
message LQRParams {
  repeated double q_state_weights = 1; // 状态权重向量 Q
  repeated double r_input_weights = 2; // 输入权重向量 R
  optional double preview_time_s = 3;  // 前视时间
}

// =========================================================
// Pure Pursuit 参数
// 作用：Pure Pursuit 控制器参数
// 说明：仅适用于横向控制器
// =========================================================
message PurePursuitParams {
  double lookahead_m = 1;                // 前瞻距离
  optional double min_lookahead_m = 2;   // 最小前瞻距离
  optional double max_lookahead_m = 3;   // 最大前瞻距离
  optional double curvature_gain = 4;    // 曲率增益
  optional double steering_limit_deg = 5; // 转向限幅
}

// =========================================================
// 单个控制器参数包
// 作用：统一表达“某个控制轴上的某个控制器”的参数
// 说明：
// 1) control_axis 用来明确这是横向控制器还是纵向控制器
// 2) algorithm_type 用来明确该控制器采用哪类算法
// =========================================================
message ControllerParameterPack {
  .agv.calibration.vehicle.profile.ControlAxisType control_axis = 1; // 控制轴类型
  .agv.calibration.vehicle.profile.ControllerAlgorithmType algorithm_type = 2; // 算法类型

  oneof params {
    PIDParams pid = 3;                        // PID 参数
    LateralMPCParams lateral_mpc = 4;         // 横向 MPC 参数
    LongitudinalMPCParams longitudinal_mpc = 5; // 纵向 MPC 参数
    LQRParams lqr = 6;                        // LQR 参数
    PurePursuitParams pure_pursuit = 7;       // Pure Pursuit 参数
  }
}

// =========================================================
// 控制参数集合
// 作用：一版参数里可以同时包含多个控制器参数
// 说明：
// 1) 例如可同时包含“横向 MPC + 纵向 PID”
// 2) 也可包含“横向 PP + 纵向 PID”
// =========================================================
message ControllerParameterSet {
  repeated ControllerParameterPack items = 1; // 参数项列表
}

// =========================================================
// 热注入参数请求
// 作用：将 Linux 计算出的一版参数加载到车端运行内存
// =========================================================
message InjectControllerParametersRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
  string parameter_version = 2;                     // 参数版本号
  ControllerParameterSet parameter_set = 3;         // 参数集合
  bool apply_immediately = 4;                       // 是否立即生效
  string source_iteration_id = 5;                   // 来源迭代号
}

// =========================================================
// 轨迹点
// 作用：控制评估任务中使用的测试轨迹点
// =========================================================
message TrajectoryPoint {
  double x_m = 1;             // 目标 X
  double y_m = 2;             // 目标 Y
  double yaw_rad = 3;         // 目标偏航角
  double target_speed_ms = 4; // 目标速度
}

// =========================================================
// 轨迹跟踪评估任务
// 作用：让车端按当前控制参数跑一条测试轨迹
// =========================================================
message TrajectoryTrackingTask {
  repeated TrajectoryPoint path = 1; // 轨迹点序列
  bool stop_at_end = 2;              // 结束后是否停车
  double timeout_sec = 3;            // 超时时间
  string required_external_pose_source_id = 4; // 要求使用的外部位姿源 ID
  double max_external_pose_age_ms = 5;         // 允许最大外部位姿延迟
  double min_external_pose_quality_score = 6;  // 允许最小外部位姿质量分数
  string trajectory_id = 7;                    // 轨迹 ID，用于分段下发时关联多段轨迹
  uint32 segment_index = 8;                    // 当前轨迹段序号，从 0 开始
  uint32 total_segments = 9;                   // 总段数；0 或 1 表示本请求携带完整轨迹
  bool is_final_segment = 10;                  // 当前段是否为最后一段，作为 total_segments 的冗余校验
}

// =========================================================
// 速度阶跃任务
// 作用：用于评估纵向动态响应
// =========================================================
message VelocityStepTask {
  double target_velocity_ms = 1;     // 目标速度
  double hold_time_sec = 2;          // 保持时长
  double settle_before_step_sec = 3; // 阶跃前静稳时间
}

// =========================================================
// 加减速任务
// 作用：用于评估纵向平顺性、加减速响应和 jerk 表现
// =========================================================
message AccelerationDecelerationTask {
  double start_velocity_ms = 1;      // 起始速度
  double target_velocity_ms = 2;     // 目标速度
  double target_accel_ms2 = 3;       // 目标加速度
  double hold_time_sec = 4;          // 保持时间
}

// =========================================================
// 停车精度任务
// 作用：用于评估停车位置误差与速度收敛情况
// =========================================================
message StopAccuracyTask {
  double target_stop_x_m = 1;        // 目标停车点 X
  double target_stop_y_m = 2;        // 目标停车点 Y
  double target_stop_yaw_rad = 3;    // 目标停车姿态
  double timeout_sec = 4;            // 超时时间
}

// =========================================================
// 控制评估任务请求
// 作用：启动一次参数评估任务
// 发送方：Ubuntu 车间电脑
// 接收方：Windows 车端代理
// =========================================================
message ControllerEvaluationRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
  string test_case_id = 2;                          // 测试用例 ID

  enum TaskPurpose {
    CONTROL_TASK_PURPOSE_UNSPECIFIED = 0; // 未指定
    DATA_COLLECTION = 1;                  // 数据采集
    TUNING_EVALUATION = 2;                // 调参评估
    VALIDATION = 3;                       // 最终验证
  }

  TaskPurpose task_purpose = 3; // 任务目的

  oneof task {
    TrajectoryTrackingTask trajectory_tracking = 4;   // 轨迹跟踪任务
    VelocityStepTask velocity_step = 5;               // 速度阶跃任务
    AccelerationDecelerationTask accel_decel = 6;     // 加减速任务
    StopAccuracyTask stop_accuracy = 7;               // 停车精度任务
  }

  string source_iteration_id = 8; // 来源迭代号
}

// =========================================================
// 控制遥测流请求
// 作用：配置遥测频率和内容
// =========================================================
message StreamControlTelemetryRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
  uint32 expected_hz = 2;                           // 上报频率
  bool include_tracking_error = 3;                  // 是否包含跟踪误差
  bool include_control_output = 4;                  // 是否包含控制器输出
  bool include_vehicle_feedback = 5;                // 是否包含车辆反馈
  bool include_controller_identity = 6;             // 是否包含当前控制器信息
}

// =========================================================
// 控制遥测
// 作用：回传调参评估时的关键数据
// 发送方：Windows 车端代理
// 接收方：Ubuntu 车间电脑
// =========================================================
message ControlTelemetry {
  int64 hardware_timestamp_us = 1; // 时间戳

  double odom_x_m = 2;             // 位置 X
  double odom_y_m = 3;             // 位置 Y
  double odom_yaw_rad = 4;         // 偏航角
  double linear_velocity_ms = 5;   // 实际线速度
  double angular_velocity_rads = 6; // 实际角速度

  double lateral_error_m = 7;      // 横向误差
  double heading_error_rad = 8;    // 航向误差
  double speed_error_ms = 9;       // 速度误差

  double steering_output = 10;     // 横向控制输出
  double throttle_output = 11;     // 纵向驱动输出
  double brake_output = 12;        // 制动输出
  bool saturation_flag = 13;       // 是否发生饱和
  string active_job_id = 14;       // 当前任务 ID

  string parameter_version = 15;   // 当前生效参数版本
  .agv.calibration.vehicle.profile.ControllerAlgorithmType active_lateral_algorithm = 16; // 当前横向算法
  .agv.calibration.vehicle.profile.ControllerAlgorithmType active_longitudinal_algorithm = 17; // 当前纵向算法

  string pose_source_name = 18;     // 本帧控制使用的位姿源名称
  bool pose_from_external_truth = 19; // 本帧位姿是否来自外部真值 / 外部定位
}

// =========================================================
// 控制验证摘要
// 作用：返回运控专项自动验收的关键指标
// =========================================================
message ControlValidationSummary {
  double rms_lateral_error_m = 1;   // 横向误差均方根
  double rms_heading_error_rad = 2; // 航向误差均方根
  double rms_speed_error_ms = 3;    // 速度误差均方根
  double overshoot_ratio = 4;       // 超调比例
  double settle_time_sec = 5;       // 收敛时间
  double stop_position_error_m = 6; // 停车位置误差
  double max_jerk = 7;              // 最大 jerk
  double saturation_ratio = 8;      // 饱和占比
  bool auto_acceptance_passed = 9;  // 自动验收是否通过
}

// =========================================================
// 固化控制参数请求
// 作用：将最终收敛的一版参数写入车端
// =========================================================
message CommitControllerParametersRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
  string parameter_version = 2;                     // 参数版本号
  ControllerParameterSet parameter_set = 3;         // 参数集合
  string commit_reason = 4;                         // 写入原因
  .agv.calibration.common.FileDigest digest = 5;   // 摘要
  bool persistent_write = 6;                        // 是否持久化
}

// =========================================================
// 查询当前控制参数请求
// =========================================================
message GetActiveControllerParametersRequest {
  .agv.calibration.common.RequestHeader header = 1; // 请求头
}

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

// =========================================================
// 控制任务结果
// 作用：返回一次调参评估 / 验证后的结果摘要
// =========================================================
message ControlJobResult {
  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; // 推荐参数版本

  ControlValidationSummary validation_summary = 8; // 验证摘要
  ControllerParameterSet estimated_parameter_set = 9; // 本轮估计参数集
  repeated .agv.calibration.common.FileReference artifacts = 10; // 关联产物
}
