syntax = "proto3";

// 规范包名，确保与传感器外参标定业务（agv.calibration.sensor）严格物理与逻辑隔离
package agv.calibration.control;

// =========================================================
// 核心服务：AGV 运控大脑（PID/MPC）参数自动化寻优调教代理
// [部署端 Server]：Windows车端 (满血保留自身算法，负责执行闭环追踪与高频汇报)
// [调用端 Client]：Linux标定服务器 (上帝视角，负责发轨迹、看误差、AI打分与发新参数)
// =========================================================
service AgvCalibControlService {

  // ---------------------------------------------------------
  // 第一步：权限接管与生命周期安全管控
  // ---------------------------------------------------------
  // 💻 [Linux 发送 -> Windows]：要求切断避障，但保留底层 PID/MPC 算法就绪
  // 🚙 [Windows 返回 -> Linux]：回复模式切换成功，准备好接考题
  rpc SetControlMode(ModeRequest) returns (StandardResponse);
  
  // 💻 [Linux 发送 -> Windows]：断网或飞车时的最高级别急停，无视一切直接刹车
  // 🚙 [Windows 返回 -> Linux]：返回底层抱死结果
  rpc EmergencyStop(Empty) returns (StandardResponse);

  // ---------------------------------------------------------
  // 第二步：运动考题下发 (开环排雷 / 闭环寻优 / 波峰对齐)
  // ---------------------------------------------------------
  // 【场景A: 纯物理开环备用】
  // 💻 [Linux 发送 -> Windows]：要求切断算法盲跑，多用于摸底或辅助验证
  // 🚙 [Windows 返回 -> Linux]：确认已按指定 RPM/PWM 运转
  rpc ExecuteOpenLoopCmd(OpenLoopRequest) returns (StandardResponse);
  
  // 【场景B: 算法闭环调优】
  // 💻 [Linux 发送 -> Windows]：下发一条由几百个点组成的测试轨迹(如 S型贝塞尔曲线)
  // 🚙 [Windows 返回 -> Linux]：收到轨迹后，车端立刻使用它自带的 PID/MPC 算法努力贴合轨迹跑圈
  rpc FollowTestTrajectory(TrajectoryRequest) returns (StandardResponse);

  // 【场景C: 波峰时序对齐】
  // 💻 [Linux 发送 -> Windows]：下发极短促的阶跃加速指令，人为制造绝对速度波峰
  // 🚙 [Windows 返回 -> Linux]：确认加速。(Linux 借此波峰算出网络的绝对 Time Offset)
  rpc ExecuteStepResponse(StepResponseRequest) returns (StandardResponse);

  // ---------------------------------------------------------
  // 第三步：运控参数 AI 寻优：动态热注入与最终固化
  // ---------------------------------------------------------
  // 💻 [Linux 发送 -> Windows]：Linux 发现上一圈跑得差，AI算出了新的 PID/前瞻距离，要求立即热注入
  // 🚙 [Windows 返回 -> Linux]：车端将新参数瞬间覆写进运行内存(不重启系统)，随时准备用新参数重跑
  rpc InjectTuningParameters(ControlParams) returns (StandardResponse);
  
  // 💻 [Linux 发送 -> Windows]：Linux 判定误差极小，调优结束，命令固化目前内存里的最高分参数
  // 🚙 [Windows 返回 -> Linux]：车端将这组完美参数永久覆写进硬盘的 config.yaml 或系统注册表
  rpc CommitControlParameters(Empty) returns (StandardResponse);

  // ---------------------------------------------------------
  // 第四步：高频数字孪生体感上报 (50Hz)
  // ---------------------------------------------------------
  // 💻 [Linux 发送 -> Windows]：空包触发，命令车端开始疯狂推流
  // 🚙 [Windows 持续流式返回 -> Linux]：以 50Hz 频率，持续上报自己的里程计坐标、速度和单调时间戳
  rpc StreamTelemetry(Empty) returns (stream TelemetryData);
}

// =========================================================
// 基础通用消息结构
// =========================================================

// 💻 [流向]：Linux 发送 -> Windows (通常用作触发信号)
message Empty {}

// 🚙 [流向]：Windows 返回 -> Linux (通用应答)
message StandardResponse {
  bool success = 1;
  string message = 2; // 包含执行成功的回执，或底盘卡死/驱动器报错等异常原因
}

// =========================================================
// 1. 模式控制结构体
// =========================================================

// 💻 [流向]：Linux 发送 -> Windows
message ModeRequest {
  enum Mode {
    NORMAL_MODE = 0;       // 正常业务模式（打开避障和导航，出厂默认状态）
    OPEN_LOOP_MODE = 1;    // 物理开环标定模式（切断所有算法纠偏，提线木偶状态）
    TUNING_MODE = 2;       // 闭环调优模式（切断环境避障，但必须保留原生 PID/MPC 追踪算法）
  }
  Mode target_mode = 1;
}

// =========================================================
// 2. 动作指令请求载荷
// =========================================================

// 💻 [流向]：Linux 发送 -> Windows
message OpenLoopRequest {
  double left_motor_cmd = 1;   // 左驱动轮目标转速 (RPM) 或占空比
  double right_motor_cmd = 2;  // 右驱动轮目标转速 (RPM) 或占空比
  double steering_angle = 3;   // 针对单/多舵轮底盘的绝对舵角指令 (度，差速轮忽略)
  
  // 🚨 极度关键的安全设计：指令超时时间
  // 业务潜台词：车端若失去网络连接，超时后必须由底层代码强制将速度归零，严防撞墙！
  double duration_sec = 4;     
}

// 💻 [流向]：Linux 发送 -> Windows (组成考卷的一小步)
message TrajectoryPoint {
  double x_m = 1;              // 目标点 X 坐标 (米)
  double y_m = 2;              // 目标点 Y 坐标 (米)
  double yaw_rad = 3;          // 目标点 偏航角 (弧度)
  double target_speed_ms = 4;  // 到达该点时的期望线速度 (米/秒)
  double curvature = 5;        // 该点处的轨迹曲率 (可选项，用于辅助前瞻距离映射)
}

// 💻 [流向]：Linux 发送 -> Windows (下发整张考卷)
message TrajectoryRequest {
  string test_case_id = 1;           // 考题名称，如 "Bezier_Curve_S_Speed_1.2"
  repeated TrajectoryPoint path = 2; // 组成考题曲线的稠密坐标点阵列
}

// 💻 [流向]：Linux 发送 -> Windows (制造波峰)
message StepResponseRequest {
  double target_velocity_ms = 1; // 极速阶跃的目标线速度 (如猛烈加速到 1.5 m/s)
  double duration_sec = 2;       // 阶跃维持时间 (极短，如 1~2 秒即可，用于产生绝对波峰)
}

// =========================================================
// 3. 待调优运控参数载荷 (支持增量式热更新)
// =========================================================

// 💻 [流向]：Linux 发送 -> Windows
message ControlParams {
  // 🚨 业务潜台词：采用 optional 关键字，允许 Linux 每次只下发需要修改的个别参数。
  // 没下发的参数，Windows 必须保持内存中的原样，千万不能清零！
  
  // --- 底盘物理运动学修正系数 (由第一阶段开环算得) ---
  optional double wheel_radius_left_ratio = 1;   // 左侧真实有效轮径补偿乘数 (如 1.002)
  optional double wheel_radius_right_ratio = 2;  // 右侧真实有效轮径补偿乘数 (如 0.998)
  optional double effective_track_width_m = 3;   // 有效轮距 (m)
  optional double steering_zero_offset_deg = 4;  // 舵角机械零位静态偏差 (度)

  // --- 经典 PID 控制增益 ---
  optional double pid_kp_lateral = 5;  
  optional double pid_ki_lateral = 6;  
  optional double pid_kd_lateral = 7;  // 用于提供阻尼，抑制高频画龙震荡
  
  optional double pid_kp_heading = 8;
  optional double pid_ki_heading = 9;
  optional double pid_kd_heading = 10;
  
  // --- 先进算法核心参数 ---
  optional double pure_pursuit_lookahead_m = 11; // 纯追踪前瞻距离 Ld (m)
  optional double mpc_weight_q_lateral = 12;     // MPC Q矩阵：对横向误差的惩罚权重
  optional double mpc_weight_r_steering = 13;    // MPC R矩阵：对转向电机发力剧烈度的惩罚权重 (控制平顺性)
}

// =========================================================
// 4. 高频遥测推流载荷 (数字孪生状态汇报)
// =========================================================

// 🚙 [流向]：Windows 疯狂上报 -> Linux (50Hz)
message TelemetryData {
  // 🚨 互相关对齐的核心依据：
  // 必须使用 Windows 底层高精度单调时钟 (如 QueryPerformanceCounter) 的绝对微秒数。
  // 绝对禁止在车端人为做时序平滑或使用受 NTP 影响的系统时间！
  int64 hardware_timestamp_us = 1;     
  
  // --- A. 车端推算的内部里程计位姿 (Odom) ---
  // 业务潜台词：Linux 拿这个跟外面上帝视角的雷达真值相减，就算出了算法的实际追踪误差(RMSE)
  double odom_x_m = 2;          
  double odom_y_m = 3;          
  double odom_yaw_rad = 4;        
  
  // --- B. 底层执行器真实物理反馈 (用于提取波峰) ---
  // 业务潜台词：用于跟指令速度比对，提取波峰，并计算 Jerk (加加速度/平顺性)
  double feedback_linear_vel_ms = 5;   // 编码器解算的真实线速度 (m/s)
  double feedback_angular_vel_rads = 6;// 陀螺仪或编码器解算的真实角速度 (rad/s)
  
  // --- C. 硬件健康与功耗监控 (用于 Linux 诊断干涉卡死) ---
  // 业务潜台词：如果遇到急弯时电流长期满载，Linux 判定该考题超出了这台车的物理极限。
  double left_motor_current_amp = 7;     // 左驱动电机实时电流 (A)
  double right_motor_current_amp = 8;    // 右驱动电机实时电流 (A)
  double steering_motor_current_amp = 9; // 转向舵机实时电流 (A)
  
  // --- D. 算法控制输出量 (用于 Linux 识别死区或物理饱和) ---
  // 业务潜台词：观察 PID 算出的期望舵角，看是否长期顶在软件限幅上 (如打满死舵)
  double cmd_steering_output = 10;       // 控制算法计算出的期望底层舵角指令 (度/弧度)
}