syntax = "proto3";
package aimdk.protocol;

import "aimdk/protocol/common/pixel_pose.proto";
import "aimdk/protocol/common/se3_pose.proto";
import "aimdk/protocol/common/timestamp.proto";
import "aimdk/protocol/common/header.proto";

// 建图channel推送数据
/**
 * @brief 2D地图信息
 */
message Map2DMapInfo {
  // 地图分辨率 厘米/像素
  double resolution = 1;

  // 地图宽度
  uint32 width = 2;

  // 地图高度
  uint32 height = 3;

  // 地图原点
  PixelPose origin = 4;
}

/**
 * @brief 向客户端推送的实时2D地图数据
 * @note 包含当前位置、地图信息、地图数据、激光点、轨迹等
 */
message Map2DRealtimeMapData {
  // 当前位置
  PixelPose cur_pos = 1;

  // 发送时刻的时间戳
  Timestamp timestamp = 2;

  // 地图信息
  Map2DMapInfo map_info = 3;

  // 雷达点
  repeated Pixel lidar_points = 4;

  // 行走轨迹
  repeated Pixel trajectory = 5;

  // 地图数据
  bytes map_data = 6;
}

/**
 * @brief 向客户端推送保存进度百分比
 */
message MapSavingProcessData {
  ResponseHeader header = 1;

  double saving_percent = 2;
}

/**
 * @brief 推送建图状态 /aima/mm/building_process
 */
message MapBuildProcessData {
  enum MapBuildStage {
    IDLE = 0;
    BUILDING = 1;
    SAVING = 2;
    FAILED = 3;
    DONE = 4;
  }
  MapBuildStage stage = 1; //当前建图任务的Stage
  string map_id = 2; //SAVING以及DONE以后才生成mapid
}

// 建图RPC
/**
 * @brief 建图RPC相关命令
 * @note 需与接口定义保持一致，不一致则会导致RPC调用失败
 */
enum MappingCommand {
  // 开始建图
  MappingCommand_START_MAPPING = 0;

  // 停止建图
  MappingCommand_STOP_MAPPING = 1;

  // 保存地图
  MappingCommand_SAVING_MAP = 2;

  // 删除地图
  MappingCommand_DELETE_MAP = 3;

  // 重命名地图
  MappingCommand_RENAME_MAP = 4;

  // 获取2D全图
  MappingCommand_GET_2D_WHOLE_MAP = 5;

  // 同步区域信息
  MappingCommand_SYNC_REGION = 6;

  // 获取所有保存的地图名称
  MappingCommand_GET_STORED_MAP_NAME = 7;

  // 设置当前的工作地图
  MappingCommand_SET_CURRENT_WORKING_MAP = 8;

  // 获取当前的工作地图
  MappingCommand_GET_CURRENT_WORKING_MAP = 9;

  // 开始增量建图
  MappingCommand_START_INCREMENT_MAPPING = 10;

  // 覆盖建图
  MappingCommand_OVERRIDE_MAPPING = 11;

  // 获取实时建图数据
  MappingCommand_GET_REALTIME_MAP = 12;
}

message StartMappingReq {
  RequestHeader header = 1;
  MappingCommand command = 2;
  bool no_realtime_data = 3;
}

message StartMappingData {}

message StartMappingRsp {
  ResponseHeader header = 1;
  StartMappingData data = 2;
}

message StartIncrementMappingReq {
  RequestHeader header = 1;
  MappingCommand command = 2;
  
  // 地图标识id
  uint64 map_id = 3;

  bool no_realtime_data = 4;
}

message StartIncrementMappingData {}

message StartIncrementMappingRsp {
  ResponseHeader header = 1;
  StartIncrementMappingData data = 2;
}

/**
 * @brief 建图过程中保存的二维码信息
 */
message QRSavePose {
  // 二维码的值
  int32 qr_code = 1;

  // 二维码的名称
  string qr_name = 2;

  // 二维码的6D pose
  SE3Pose pose = 3;
}

message StopMappingReq {
  RequestHeader header = 1;
  // 包含stop, save两种command
  MappingCommand command = 2;

  // 地图名称
  string map_name = 3;

  // 建图过程中保存的二维码信息
  repeated QRSavePose qr_poses = 4;
}

message StopMappingData {
  // 返回地图标识id
  uint64 map_id = 1;
}

message StopMappingRsp {
  ResponseHeader header = 1;
  StopMappingData data = 2;
}

message DeleteMapReq {
  RequestHeader header = 1;
  MappingCommand command = 2;

  // 地图标识id
  uint64 map_id = 3;
}

message DeleteMapData {}

message DeleteMapRsp {
  ResponseHeader header = 1;
  DeleteMapData data = 2;
}

message RenameMapReq {
  RequestHeader header = 1;

  MappingCommand command = 2;

  // 地图标识id
  uint64 map_id = 3;

  // 旧地图名称
  string old_name = 4;

  // 新地图名称
  string new_name = 5;
}

message RenameMapData {}

message RenameMapRsp {
  ResponseHeader header = 1;
  RenameMapData data = 2;
}

message Get2DWholeMapReq {
  RequestHeader header = 1;
  MappingCommand command = 2;

  // 地图标识id
  uint64 map_id = 3;

  // 是否只返回地图信息，不返回 png 数据
  bool is_map_meta = 4;

  bool is_http = 5;
}

message Get2DWholeMapData {
  // 地图标识id
  uint64 map_id = 1;

  // 地图名称
  string map_name = 2;

  // 地图宽度
  uint32 width = 3;

  // 地图高度
  uint32 height = 4;

  // 地图分辨率, 厘米/像素
  double resolution = 5;

  // 地图原点x
  int32 origin_x = 6;

  // 地图原点y
  int32 origin_y = 7;

  // 地图数据
  bytes map_data = 8;

  // 地图旋转角度(客户端用)
  double rotate_angle = 9;

  // 地图 url
  string map_url = 10;
}

message Get2DWholeMapRsp {
  ResponseHeader header = 1;
  Get2DWholeMapData data = 2;
}

enum VerteciesType {
  VerteciesType_UNDEFINED = 0;
  VerteciesType_CLOSURE = 1;
  VerteciesType_LINES = 2;
}

/**
 * @brief 顶点集合的数据格式
 * @note 这个代表一个数据图形(必须为凸的)用到的所有关联顶点。顺序需要是画图形连续的。最终能根据节点绘制出图形。
 */
message Vertecies {
  // 顶点数据list
  repeated PixelPose vertices = 1;

  // 颜色信息
  string color = 2;

  // 图形类型
  VerteciesType type = 3;
}

message SyncRegionReq {
  RequestHeader header = 1;
  MappingCommand command = 2;

  // 地图标识id
  uint64 map_id = 3;

  // 顶点构成的区域
  repeated Vertecies regions = 4;
}

message SyncRegionData {}

message SyncRegionRsp {
  ResponseHeader header = 1;
  SyncRegionData data = 2;
}

message GetStoredMapNamesReq {
  RequestHeader header = 1;
  MappingCommand command = 2;
}

message MapIdNameCombine {
  // 地图标识id
  uint64 map_id = 1;

  // 地图名称
  string map_name = 2;

  // 地图索引
  uint32 map_index = 3;
}

message GetStoredMapNamesData {
  // 地图列表
  repeated MapIdNameCombine map_lists = 1;
}

message GetStoredMapNamesRsp {
  ResponseHeader header = 1;
  GetStoredMapNamesData data = 2;
}

message SetCurrentWorkingMapReq {
  RequestHeader header = 1;
  MappingCommand command = 2;

  // 地图标识id
  uint64 map_id = 3;
}

message SetCurrentWorkingMapData {}

message SetCurrentWorkingMapRsp {
  ResponseHeader header = 1;
  SetCurrentWorkingMapData data = 2;
}

message GetCurrentWorkingMapReq {
  RequestHeader header = 1;
  MappingCommand command = 2;
}

message GetCurrentWorkingMapData {
  uint64 map_id = 1;
}

message GetCurrentWorkingMapRsp {
  ResponseHeader header = 1;
  GetCurrentWorkingMapData data = 2;
}

message SetMappingResultReq {
  RequestHeader header = 1;

  bool is_success = 2;

  string msg = 3;

  // 地图信息
  Map2DMapInfo map_info = 4;
}

message SetMappingResultData {}

message SetMappingResultRsp {
  ResponseHeader header = 1;
  SetMappingResultData data = 2;
}

message SetSavingPercentReq {
  RequestHeader header = 1;

  // 保存进度
  double saving_percent = 2;
}

message SetSavingPercentData {}

message SetSavingPercentRsp {
  ResponseHeader header = 1;
  SetSavingPercentData data = 2;
}

message SetMapRotateAngleReq {
  RequestHeader header = 1;
  uint64 map_id = 2;
  double rotate_angle = 3;
}

message SetMapRotateAngleData {}

message SetMapRotateAngleRsp {
  ResponseHeader header = 1;
  SetMapRotateAngleData data = 2;
}

message CheckUpdateGridMapReq {
  RequestHeader header = 1;
  uint64 map_id = 2;
  bool   is_http = 3;
}

message CheckUpdateGridMapRsp {
  ResponseHeader header = 1;
  Get2DWholeMapData current_map = 2;
  Get2DWholeMapData new_map = 3;
  // 0 - success
  uint64 result = 4;
  string current_map_url = 10;
  string new_map_url = 11;
  bool is_meta = 12;
}

message ConfirmUpdateGridMapReq {
  RequestHeader header = 1;
  uint64 map_id = 2;
  // 0 - 取消, 1 - 确认
  uint64 command = 3;
}

message ConfirmUpdateGridMapRsp {
  ResponseHeader header = 1;
  // 0 - success
  uint64 result = 2;
}

message GetRealtimeMapDataReq {
  RequestHeader header = 1;
  MappingCommand command = 2;
}

message GetRealtimeMapDataRsp {
  ResponseHeader header = 1;
  Map2DRealtimeMapData data = 2;
}

service MappingService {
  /**
   * @brief 开始建图rpc接口
   * @note
   * 1. 客户端调用该接口，服务端开始建图
   * 2. 服务端接收到req后，校验成功会启动建图算法，并且不停的推送建图数据给客户端，实时数据:Map2DRealtimeMapData
   * 3. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg,建图状态status
   */
  rpc StartMapping(StartMappingReq) returns (StartMappingRsp);

  /**
   * @brief 开始增量建图rpc接口
   * @note
   * 1. 客户端调用该接口，服务端开始增量建图
   * 2. 服务端接收到req后，校验成功会启动增量建图算法，并且不停的推送建图数据给客户端，实时数据:Map2DRealtimeMapData
   * 3. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg,建图状态status
   */
  rpc StartIncrementMapping(StartIncrementMappingReq) returns (StartIncrementMappingRsp);

  /**
   * @brief 停止建图rpc接口
   * @note
   * 1. 客户端调用该接口，服务端停止建图
   * 2. 停止建图有两种形式，通过command进行区分：
   *     a. 停止建图，并保存地图，此时需要将需要保存的地图名称及相关的二维码信息发送给服务端，增量创建时，新增对应改模式。保存过程中会推送保存进度:MapSavingProcessData
   *     b. 停止建图，但不保存地图, 此时不会解析其他信息直接关闭算法。
   *     c. 停止建图，覆盖地图, 用于增量地图中的覆盖模式，保存过程中会推送保存进度:MapSavingProcessData
   * 3. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg,建图状态status，如果是成功保存了地图，会返回保存的地图id
   */
  rpc StopMapping(StopMappingReq) returns (StopMappingRsp);

  /**
   * @brief 删除地图rpc接口
   * @note
   * 1. 客户端调用该接口，服务端根据map_id删除地图。
   * 2. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg,建图状态status
   */
  rpc DeleteMap(DeleteMapReq) returns (DeleteMapRsp);

  /**
   * @brief 重命名地图rpc接口
   * @note
   * 1. 客户端调用该接口，服务端根据map_id重命名相应的地图。
   * 2. 服务端会检测old_name是否为当前地图名称，是则会重名为new_name，否则返回错误。
   * 3. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg,建图状态status
   */
  rpc RenameMap(RenameMapReq) returns (RenameMapRsp);

  /**
   * @brief 获取2D地图rpc
   * @note
   * 1. 客户端调用该接口，服务端根据map_id获取对应的地图。
   * 2. 服务端会将地图相关的所有info都传给客户端用以显示
   * 3. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg,以及对应的map_info
   */
  rpc Get2DWholeMap(Get2DWholeMapReq) returns (Get2DWholeMapRsp);

  /**
   * @brief 同步底图接口rpc
   * @note
   * 1. 客户端调用该接口，将用户操作的底图区域信息同步给服务端。区域会带有顶点信息以及颜色。
   * 2. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg，以及建图状态status
   */
  rpc SyncRegion(SyncRegionReq) returns (SyncRegionRsp);

  /**
   * @brief 获取地图列表rpc
   * @note
   * 1. 客户端调用该接口，获取服务端存储的地图列表。
   * 2. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg，以及在数据库中缓存的所有地图列表以（id--name）的形式传给客户端。
   */
  rpc GetStoredMapNames(GetStoredMapNamesReq) returns (GetStoredMapNamesRsp);

  /**
   * @brief 设置当前工作地图rpc
   * @note
   * 1. 客户端调用该接口，设置当前的工作地图。
   * 2. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg，以及建图状态status。
   */
  rpc SetCurrentWorkingMap(SetCurrentWorkingMapReq) returns (SetCurrentWorkingMapRsp);

  /**
   * @brief 获取当前工作地图rpc
   * @note
   * 1. 客户端调用该接口，获取当前的工作地图。
   * 2. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg，当前工作地图的id。
   */
  rpc GetCurrentWorkingMap(GetCurrentWorkingMapReq) returns (GetCurrentWorkingMapRsp);

  /* 给SLAM模块的接口 */
  /**
   * @brief 设置建图结果的rpc
   * @note
   * 1. SLAM模块调用该接口，将建图结果发送给map manager。
   * 2. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg。
   */
  rpc SetMappingResult(SetMappingResultReq) returns (SetMappingResultRsp);

  /**
   * @brief 设置建图保存进度rpc
   * @note
   * 1. SLAM模块调用该接口，将建图实时的保存进度给map manager。
   * 2. 服务端会返回rsp，表示接口调用是否成功code，相关信息msg。
   */
  rpc SetSavingPercent(SetSavingPercentReq) returns (SetSavingPercentRsp);

  /**
   * @brief 地图旋转角度接口
   * @note
   * 1. 此接口仅给客户端使用
   * 2. 设置地图旋转角度，后端在数据库中进行保存，在Get2DWholeMap接口会返回旋转角度信息。
   */
  rpc SetMapRotateAngle(SetMapRotateAngleReq) returns (SetMapRotateAngleRsp);

  /**
   * @brief 检查栅格地图更新
   * @note
   * 1. 此接口仅给客户端使用
   * 2. 发送栅格地图更新请求，如果可以更新，返回新旧图给客户端。
   */
  rpc CheckUpdateGridMap(CheckUpdateGridMapReq) returns (CheckUpdateGridMapRsp);

  /**
   * @brief 确认栅格地图更新
   * @note
   * 1. 此接口仅给客户端使用
   * 2. 发送栅格地图确认更新请求，如果更新，更新地图文件，如果取消，删除临时文件。
   */
  rpc ConfirmUpdateGridMap(ConfirmUpdateGridMapReq) returns (ConfirmUpdateGridMapRsp);

  /**
   * @brief 获取实时建图数据
   * @note
   * 1. 此接口仅给客户端使用
   */
  rpc GetRealtimeMapData(GetRealtimeMapDataReq) returns (GetRealtimeMapDataRsp);
}
