syntax = "proto3";

// 规范包名：agv.calibration.chassis
// 设计原则：专门负责底盘最底层机械物理特征的开环标定与体检
package agv.calibration.chassis;

// =========================================================
// 核心服务：AGV 底盘底层硬件自诊与物理运动学标定代理服务
// [部署端 Server]：Windows 车端 (只负责听口令、转电机、报裸数据)
// [调用端 Client]：Linux 车间服务器 (负责发口令、看雷达真值、算误差)
// =========================================================
service AgvCalibChassisService {
  
  // ---------------------------------------------------------
  // 第一步：权限接管与安全熔断 (剥夺车端算法大脑)
  // ---------------------------------------------------------
  // 💻 [Linux 发送 -> Windows]：要求切断底盘运动学逆解，进入纯物理开环直驱模式
  // 🚙 [Windows 返回 -> Linux]：返回接管是否成功的回执
  rpc SetDiagnosticMode(DiagnosticModeRequest) returns (StandardResponse);
  
  // 💻 [Linux 发送 -> Windows]：无视一切状态立刻抱死电机的紧急急停指令
  // 🚙 [Windows 返回 -> Linux]：返回急停执行状态
  rpc HardwareEmergencyBrake(Empty) returns (StandardResponse);

  // ---------------------------------------------------------
  // 第二步：打开体征监控水龙头 (数字孪生健康诊断)
  // ---------------------------------------------------------
  // 💻 [Linux 发送 -> Windows]：发送空请求，触发高频推流开关
  // 🚙 [Windows 持续流式返回 -> Linux]：以 50Hz 频率持续不断地回传原始脉冲与电流
  rpc StreamHardwareTelemetry(Empty) returns (stream HardwareState);

  // ---------------------------------------------------------
  // 第三步：原始物理开环考题下发 (逼迫底盘暴露机械缺陷)
  // ---------------------------------------------------------
  // 💻 [Linux 发送 -> Windows]：绕过算法，直接命令指定驱动轮以固定 RPM 盲跑
  // 🚙 [Windows 返回 -> Linux]：返回电机是否已成功按给定 RPM 运转
  rpc ExecuteRawDriveCommand(RawDriveRequest) returns (StandardResponse);
  
  // 💻 [Linux 发送 -> Windows]：直接对转向机构下发绝对物理角度 (测机械装歪的角度)
  // 🚙 [Windows 返回 -> Linux]：返回舵机是否已开始执行角度指令
  rpc ExecuteRawSteerCommand(RawSteerRequest) returns (StandardResponse);

  // ---------------------------------------------------------
  // 第四步：物理本底参数定稿写值 (标定闭环结束)
  // ---------------------------------------------------------
  // 💻 [Linux 发送 -> Windows]：下发 Linux 结合外部真值算出的绝对物理修正系数
  // 🚙 [Windows 返回 -> Linux]：将系数覆写到本地硬盘/驱动板后，返回成功回执
  rpc CommitKinematicParameters(KinematicParams) returns (StandardResponse);
}

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

// 空消息，通常作为触发类请求发送
// 💻 [流向]：Linux 发送 -> Windows
message Empty {}

// 通用应答载荷
// 🚙 [流向]：Windows 返回 -> Linux
message StandardResponse {
  bool success = 1;
  string message = 2; // 若失败，返回驱动器底层报错详情 (如 "ERR_MOTOR_OVERCURRENT")
}

// =========================================================
// 1. 权限模式请求载荷
// =========================================================
// 💻 [流向]：Linux 发送 -> Windows
message DiagnosticModeRequest {
  enum Mode {
    NORMAL_KINEMATICS = 0; // 正常模式 (底盘接收 V_x, Omega，由车端执行逆解分配)
    DIRECT_RAW_DRIVE = 1;  // 直驱模式 (切断逆解，允许 Linux 直接独立下发左/右轮转速)
  }
  Mode target_mode = 1; 
}

// =========================================================
// 2. 硬件底层遥测推流载荷 (裸数据)
// =========================================================
// 🚙 [流向]：Windows 疯狂上报 -> Linux (50Hz)
message HardwareState {
  // 底层获取到脉冲那一瞬间的高精度单调系统时钟 (绝对微秒数)
  int64 hardware_timestamp_us = 1;     
  
  // --- A. 原始编码器反馈 (Linux 拿它与雷达真值做除法，算真实物理位移与滑移率) ---
  // 🚨 严禁返回平滑后的速度(m/s)，必须返回最原始的累计脉冲 Ticks！
  int64 encoder_ticks_fl = 2;         // 左前轮累计脉冲
  int64 encoder_ticks_fr = 3;         // 右前轮累计脉冲
  int64 encoder_ticks_rl = 4;         
  int64 encoder_ticks_rr = 5;         
  
  // --- B. 物理舵角反馈 (Linux 拿它比对指令响应时间，测定机械死区) ---
  double actual_steer_angle_front_deg = 6; 
  double actual_steer_angle_rear_deg = 7;
  
  // --- C. 动力与负载健康状态 (Linux 防烧毁熔断的判断依据) ---
  // 若维持匀速所需的电流异常激增，说明减速机干涉或刹车未放，Linux 会立刻触发急停
  double current_fl_amp = 8;          // 左前电机实际相电流 (安培)
  double current_fr_amp = 9;          
  double current_rl_amp = 10;         
  double current_rr_amp = 11;         
  double current_steer_front_amp = 12;// 前转向舵机实际电流 (安培)
  
  // --- D. 驱动器硬件报警位 ---
  uint32 driver_error_code = 13;      // 0x00=健康, 0x01=过压, 0x02=堵转过流等
}

// =========================================================
// 3. 原始动作指令请求载荷
// =========================================================
// 💻 [流向]：Linux 发送 -> Windows
message RawDriveRequest {
  string test_case_id = 1;    // 测试流水号 (如 "Slip_Test_0.5m")
  
  // 直接下发给电机的原始指令 (若是两驱车，后轮填 0 即可)
  double fl_motor_rpm = 2;    // 左前轮目标物理转速 (RPM)
  double fr_motor_rpm = 3;    // 右前轮目标物理转速 (RPM)
  double rl_motor_rpm = 4;    
  double rr_motor_rpm = 5;    
  
  // 🚨 断网防飞车底线：若超过该时间未收到新指令，车端底层必须自动刹车
  double duration_sec = 6;    
}

// 💻 [流向]：Linux 发送 -> Windows
message RawSteerRequest {
  string test_case_id = 1;    // 测试流水号 (如 "Deadzone_Sweep_5deg")
  
  // 针对舵机/转向推杆的绝对物理角度指令 (度)
  double front_steer_angle_deg = 2; 
  double rear_steer_angle_deg = 3;  
  
  // 扫频测试参数 (用于测定机械往复间隙 Backlash)
  optional double sweep_amplitude_deg = 4; // 往复抖动幅度 (度)
  optional double sweep_frequency_hz = 5;  // 抖动频率 (Hz)
  
  double duration_sec = 6;
}

// =========================================================
// 4. 物理运动学本底参数定稿载荷
// =========================================================
// 💻 [流向]：Linux 发送 -> Windows
message KinematicParams {
  // (注：全字段使用 optional，Linux 测了哪一项就只下发哪一项要求车端覆盖，未发的不作修改)

  // --- 1. 真实有效物理轮径 (纠正“开环跑偏”与里程计位移误差) ---
  optional double wheel_radius_fl_m = 1; 
  optional double wheel_radius_fr_m = 2;
  optional double wheel_radius_rl_m = 3;
  optional double wheel_radius_rr_m = 4;

  // --- 2. 机械零位绝对偏差补偿 (纠正“指令0度但车子斜着走”) ---
  optional double steer_zero_offset_front_deg = 5; 
  optional double steer_zero_offset_rear_deg = 6;

  // --- 3. 旋转几何协同参数 (纠正“原地打转时车体甩尾晃动”) ---
  optional double effective_track_width_m = 7; // 左右轮真实物理有效轮距 (m)
  optional double effective_wheel_base_m = 8;  // 前后轮真实物理有效轴距 (m)
  
  // 针对多舵轮底盘：瞬时旋转中心(ICR)的物理几何偏移
  optional double icr_offset_x_m = 9;          
  optional double icr_offset_y_m = 10;         
}