syntax = "proto3";

// 规范包名，防止与其他业务（如底盘运控调优）的接口冲突
package agv.calibration.sensor;

// =========================================================
// 核心服务：传感器自动化标定代理服务 
// 部署端：Windows车端 (Server) | 调用端：Linux服务器 (Client)
// =========================================================
service SensorCalibrationService {
  // 1. 走位调度：指挥车辆开到特定的观测点并【绝对静止】
  rpc MoveToObservationPose (PoseRequest) returns (StandardResponse);

  // 2. 同步锁存：命令车辆瞬间冻结指定传感器的当前画面/点云到内存
  rpc TriggerSyncCapture (CaptureRequest) returns (CaptureResponse);

  // 3. 大文件下载：通过凭证流式拉取图片和点云（注意：使用 stream 防爆内存）
  rpc DownloadImage (DataFetchRequest) returns (stream FileChunk);
  rpc DownloadPointCloud (DataFetchRequest) returns (stream FileChunk);

  // 4. 标定闭环：Linux算完矩阵后，下发给车端持久化保存（覆写配置文件）
  rpc CommitCalibrationResults (CalibrationPayload) returns (StandardResponse);
}

// =========================================================
// 基础响应
// =========================================================
message StandardResponse {
  bool success = 1;
  string message = 2; // 成功提示或具体的报错原因（如：碰撞急停）
}

// =========================================================
// 1. 物理走位请求 (走)
// =========================================================
message PoseRequest {
  double target_x_m = 1;     // 目标 X 坐标 (米)
  double target_y_m = 2;     // 目标 Y 坐标 (米)
  double target_yaw_deg = 3; // 目标偏航角 (度)
  bool is_relative = 4;      // true: 相对当前位置移动; false: 绝对世界坐标
}

// =========================================================
// 2. 触发同步抓拍请求与响应 (停与拍)
// =========================================================
message CaptureRequest {
  // 告诉车端这次要同时拍哪些传感器，例如 ["cam_front", "lidar_top"]
  repeated string sensor_ids = 1; 
}

message CaptureResponse {
  bool success = 1;
  // 极度关键：车端打上的高精度硬件时间戳(微秒)。
  // 这是提取数据的“取件码”，保证多传感器在物理时间上的绝对对齐！
  int64 capture_timestamp_us = 2; 
  string error_message = 3;
}

// =========================================================
// 3. 大文件下载请求与文件流块 (传)
// =========================================================
message DataFetchRequest {
  int64 capture_timestamp_us = 1; // 阶段2拿到的取件码
  string sensor_id = 2;           // 具体要下载哪个传感器，例如 "cam_front"
}

// 流式文件块 (规避 gRPC 单条消息默认 4MB 的内存限制)
message FileChunk {
  bytes chunk_data = 1;   // 文件的二进制分块（建议每次发 512KB - 1MB）
  bool is_last_chunk = 2; // 是否为最后一块
  string format_ext = 3;  // 格式标注，如 "png", "bmp", "pcd"
}

// =========================================================
// 4. 标定结果载荷（支持内参、外参灵活组合组合发回车端） (写)
// =========================================================
message CameraIntrinsics {
  string camera_id = 1;
  double fx = 2; double fy = 3;
  double cx = 4; double cy = 5;
  repeated double dist_coeffs = 6; // 畸变系数阵列 [k1, k2, p1, p2, k3]
}

message SensorExtrinsics {
  string source_frame = 1; // 源坐标系，如 "lidar_top" 或 "cam_left"
  string target_frame = 2; // 目标坐标系，如 "cam_front" 或 "base_link"
  
  // 平移向量 (强制规定单位为毫米 mm)
  double trans_x_mm = 3; 
  double trans_y_mm = 4; 
  double trans_z_mm = 5;
  
  // 旋转姿态 (强制规定单位为度 degrees)
  double roll_deg = 6; 
  double pitch_deg = 7; 
  double yaw_deg = 8;
}

message CalibrationPayload {
  string task_id = 1; // 标定任务流水号，用于 MES 系统追溯
  // 采用 repeated 数组：Linux 可以一次性下发多个相机的内参和多个外参
  repeated CameraIntrinsics updated_intrinsics = 2;
  repeated SensorExtrinsics updated_extrinsics = 3;
}