# ControllerClient API 兼容逆向约束

> 记录时间：2026-04-24
> 适用仓库：`flyshot-replacement`
> 当前阶段：已落地 HTTP-only `ControllerClientCompat` 服务，并已将轨迹执行接入规划、触发时间轴和最小运行时骨架；不实现 `50001/TCP+JSON` 监听

## 1. 当前目标

本轮目标不是直接实现 `50001/TCP+JSON` 兼容网关，而是先把旧 `ControllerClient` 暴露的公开 API 做成可执行的逆向合同。

本轮交付物固定为两份文档：

- `docs/controller-client-api-compatibility-requirements.md`
- `docs/controller-client-api-reverse-engineering.md`

后续继续扩展 `Flyshot.ControllerClientCompat` 的方法覆盖、兼容测试矩阵或真实控制器联动时，必须以这两份文档为准，不再重新口头约定接口语义。

## 2. 范围边界

本轮只覆盖 `../FlyingShot/FlyingShot/Include/ControllerClient/ControllerClient.h` 中的 32 个公开方法。

分组如下：

- 传输与版本：`ConnectServer`、`GetServerVersion`、`GetClientVersion`
- 机器人初始化：`SetUpRobot`、`SetUpRobotFromEnv`、`IsSetUp`、`SetShowTCP`、`GetName`、`GetDoF`
- 控制器状态：`SetActiveController`、`Connect`、`Disconnect`、`EnableRobot`、`DisableRobot`、`StopMove`
- 参数与 IO：`GetSpeedRatio`、`SetSpeedRatio`、`GetTCP`、`SetTCP`、`GetIO`、`SetIO`
- 运动与求解：`GetJointPosition`、`GetPose`、`GetNearestIK`、`MoveJoint`、`ExecuteTrajectory`
- 飞拍轨迹：`UploadFlyShotTraj`、`DeleteFlyShotTraj`、`ListFlyShotTraj`、`ExecuteFlyShotTraj`、`SaveTrajInfo`、`IsFlyShotTrajValid`

明确不在本轮范围内：

- `ControllerServer` 内部所有未公开 `_Xxx` 方法的完整实现复原
- `50001` 网关代码、TCP server、JSON parser、命令路由实现
- 真机 `10010 / 10012 / 60015` 联调
- 抓包、hook、反汇编级协议完全坐实
- 把当前 replacement 仓库的实现约束误写成旧系统事实

## 3. 证据源优先级

逆向结论必须按以下优先级交叉确认：

1. `../FlyingShot/FlyingShot/Include/ControllerClient/ControllerClient.h`
2. `../FlyingShot/FlyingShot/Example/UseControllerClient.cpp`
3. `../FlyingShot/FlyingShot/Example/UseControllerClient.py`
4. `../FlyingShot/FlyingShot/Example/UseRealRobot.py`
5. `../FlyingShot/FlyingShot/Docs/用户手册/FANUC飞拍软件及SDK用户手册.md`
6. `../analysis/ControllerServer_analysis.md`
7. `../analysis/CommonMsg_protocol_analysis.md`
8. `../analysis/Trajectory_generation_algorithm_analysis.md`
9. `../FlyingShot/FlyingShot/Lib/libControllerClient.so` 与 `../FlyingShot/FlyingShot/Python/ControllerServer/ControllerServer.cpython-37m-x86_64-linux-gnu.so` 的字符串证据

使用规则：

- 头文件负责定义“公开合同”：方法名、参数名、默认值、返回类型。
- 示例和手册负责定义“典型调用方式”：调用顺序、Python 包装形态、用户侧常见用法。
- 逆向分析文档和二进制字符串负责定义“服务端映射”和“协议线索”：`_Xxx` 方法名、错误文本、命令名、部分字段顺序。
- 不能从当前 replacement 仓库的未来设计反推旧系统事实。

## 4. 文档填写规则

主归档文档 `docs/controller-client-api-reverse-engineering.md` 对每个 API 必须固定填写以下项目：

- C++ 公开签名
- Python 包装形态
- 服务端归属
- 协议 / 命令线索
- 返回值与默认值
- 典型工作流位置
- 证据来源
- 置信度
- 待确认点

填写约束：

- 只要精确 JSON 包结构还未恢复，就明确写成“命令名已知，JSON envelope 未恢复”。
- 只要 Python 失败路径没有样例，就不能假装已经确认失败时的返回形态。
- `GetServerVersion` 这类没有显式 `_GetServerVersion` 的接口，必须标成“协议分发层行为”，不能伪造一个服务端实现名。
- `ConnectServer` 与 `GetClientVersion` 必须明确标成客户端侧行为，不写进服务端命令表。
- 对 `GetJointPosition -> _GetJointPositions` 这种命名不一致，要单独注明。
- 当同一结论同时来自头文件、示例和字符串时，置信度可标为“高”；只有示例间接体现时，最多“中”。

## 5. 验收条件

本轮逆向归档完成时，至少满足：

- 32 个公开方法全部覆盖，且每个方法只出现一次
- 29 个服务端相关 API 有明确映射或明确写成协议分发层行为
- `ConnectServer`、`GetClientVersion` 两个客户端侧行为被明确排除在服务端命令表外
- 四条工作流附录完整：
  - 初始化工作流
  - 控制器状态工作流
  - 普通轨迹工作流
  - 飞拍轨迹工作流
- 已知高置信协议字段至少记录：
  - `GetSpeedRatio`
  - `SetSpeedRatio`
  - `GetIO`
  - `SetIO`
- 仍未恢复的部分必须进入“待确认问题”清单，不能被静默略过

## 6. 当前已确认摘要

当前已确认的高价值结论如下：

- `ControllerClient.h` 中共有 32 个公开方法。
- 其中 29 个方法可与 `ControllerServer` 的公开 `_Xxx` 方法一一对齐。
- `GetServerVersion` 能看到明确字符串证据，但未恢复到显式 `_GetServerVersion` 实现，更接近 `_ClientCB` / `_IsJsonValid` 所在的协议分发层。
- `ConnectServer` 是客户端建立到 `127.0.0.1:50001` 的传输层动作。
- `GetClientVersion` 更像客户端库自身版本查询，不进入服务端命令表。
- `GetSpeedRatio` / `SetSpeedRatio`、`GetIO` / `SetIO` 已有较高置信度的底层字段顺序与 `MsgID` 证据。
- `UploadFlyShotTraj`、`ListFlyShotTraj` 存在额外字符串线索：
  - `StartUploadFlyShotTraj`
  - `EndUploadFlyShotTraj`
  - `GetNextListFlyShotTraj`
- `ExecuteFlyShotTraj`、`IsFlyShotTrajValid`、`SaveTrajInfo` 在工作流上有清晰分工，不能混成一个“执行轨迹”接口。

## 7. 下轮实现约束

当前 HTTP-only 兼容层已经可以承接公开 API 的主要服务端语义，并且 `ExecuteTrajectory` / `ExecuteFlyShotTraj` 已经进入 replacement 自身的规划与运行时链路。后续扩展必须遵守：

- 先以逆向合同建命令表，再写 `TCP + JSON` 入口
- 先做兼容测试矩阵，再补最小命令桩
- 区分“旧系统事实”和“replacement 当前策略”
- 真机未接通前，允许实现层返回稳定错误或模拟状态，但不能反过来污染逆向文档
- `50001/TCP+JSON` 抓包已经覆盖 `SetSpeedRatio` 与 `ExecuteFlyShotTraj(save_traj=true,use_cache=false)`，请求中没有显式 `JointLimits / acc_limit / jerk_limit / velocity / acceleration / jerk` 字段；因此规划限制的补齐必须作为 replacement-only 策略记录，不能写成旧公开 API 合同。

## 8. 当前 replacement 实现状态

以下内容是当前新实现的状态，不反推为旧系统事实：

- `Flyshot.ControllerClientCompat` 继续作为 HTTP 控制器后端兼容服务，不启动 `50001/TCP+JSON` 监听。
- `ExecuteTrajectory` 会先通过 `ICspPlanner` 规划普通轨迹，再把 `TrajectoryResult` 和最终关节位置交给 `IControllerRuntime`。
- `ExecuteFlyShotTraj` 会从上传轨迹目录取出轨迹，通过 `SelfAdaptIcspPlanner` 规划并用 `ShotTimelineBuilder` 生成 `ShotEvent` / `TrajectoryDoEvent`。
- HTTP 控制器已经按公开文档和抓包补齐 `ExecuteTrajectory(method, save_traj)` 与 `ExecuteFlyShotTraj(move_to_start, method, save_traj, use_cache, wait)` 参数，并继续兼容旧的裸 waypoint 数组和只传 `name` 的请求体。
- 规划阶段会继续消费旧配置中的 `acc_limit / jerk_limit`。如果现场需要复现旧服务端不可见的保守约束，replacement 设计上使用内部 `planning_acceleration_scale` 限制规划加速度；该字段不属于旧 `ControllerClient` 公开 API，也不会通过 `50001` JSON 下发。
- `method="icsp"` 与 `method="self-adapt-icsp"` 已接入当前规划器；`method="doubles"` 会被识别但返回显式未实现，不会静默降级成 ICSP。
- `Flyshot.Runtime.Fanuc.Protocol` 已经固化 `10010` 状态帧、`10012` 命令帧和 `60015` J519 数据包的基础编解码，并使用逆向抓包样本覆盖最小测试；`10010` 当前现场确认固定 90B。
- `Flyshot.Runtime.Fanuc` 已具备基础 Socket 客户端、程序启停、速度倍率/TCP/IO 参数命令和 J519 状态包驱动发送链路；稠密轨迹下发已按 `speed_ratio` 推进轨迹时间，并在收到机器人 UDP status 后按该 status sequence 回发命令。真实 R30iB 全流程现场联调仍需执行。
- 2026-04-28 `UTTC_MS11` 抓包确认 J519 命令目标为 `deg`、导出 `JointDetialTraj.txt` 为 `rad`，`speed_ratio=0.5/0.7/1.0` 分别形成 `1851/1322/926` 个主运行 J519 包；实际执行不发送 464 行导出点，而是在 8ms 实发周期上按 `t_traj = t_send * speed_ratio` 采样，包数为 `floor(duration / (0.008 * speed_ratio)) + 1`。
- 宿主已经提供只读 Web 状态页 `/status` 和状态快照 API `/api/status/snapshot`，用于查看兼容层初始化、机器人元数据和运行时快照。
- `MoveJoint` 仍保持旧兼容语义中的直接运动接口，但状态写入已经统一经过运行时，而不是由兼容服务自己维护关节数组。
- `GetNearestIK`、`SetUpRobotFromEnv` 当前已经暴露完整参数形状，但后端求解器 / 环境文件解析仍返回显式未实现。
