# ControllerClient API 全量逆向归档

> 记录时间：2026-04-24
> 适用仓库：`flyshot-replacement`
> 目标：为后续 `50001/TCP+JSON` 兼容网关实现提供只读合同

## 1. 总览

本次归档覆盖 `../FlyingShot/FlyingShot/Include/ControllerClient/ControllerClient.h` 中全部 32 个公开方法。

当前分类结果：

- 29 个 API 可与 `ControllerServer` 公开 `_Xxx` 方法一一映射
- 1 个 API 属于协议分发层行为：`GetServerVersion`
- 2 个 API 属于客户端侧行为：`ConnectServer`、`GetClientVersion`

本文档中的“协议 / 命令线索”有两个层次：

- 命令名：已从头文件、字符串或逆向文档坐实，例如 `SetUpRobot`、`GetIO`
- JSON envelope：请求 JSON 的精确键名、必填规则、整体结构；当前大多仍未完全恢复

因此，除 `GetSpeedRatio` / `SetSpeedRatio` / `GetIO` / `SetIO` 等已在命令通道层坐实字段顺序的接口外，其余接口默认只写“命令名已知，精确 JSON 包结构待确认”。

置信度定义：

- 高：头文件 + 示例/手册 + 字符串/逆向文档三方交叉确认
- 中：头文件 + 示例，或头文件 + 字符串，缺少第三方交叉
- 低：仅有间接线索，未达到本轮归档主结论标准

## 2. 传输与版本

### `ConnectServer`

- C++ 公开签名：`bool ConnectServer(const std::string &server_ip = "127.0.0.1", unsigned port = 50001);`
- Python 包装形态：`c.ConnectServer(server_ip="127.0.0.1", port=50001) -> bool`
- 服务端归属：客户端传输层行为，不进入 `ControllerServer._Xxx` 命令表
- 协议 / 命令线索：建立到 `127.0.0.1:50001` 的 TCP 连接；JSON 负载只发生在连接建立之后
- 返回值与默认值：默认 `server_ip="127.0.0.1"`、`port=50001`；成功返回 `true`
- 典型工作流位置：所有远程 API 的前置步骤
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、`UseRealRobot.py`
- 置信度：高
- 待确认点：重连、超时、握手细节未恢复

### `GetServerVersion`

- C++ 公开签名：`bool GetServerVersion(std::string &version);`
- Python 包装形态：样例中表现为 `controller.GetServerVersion() -> str`
- 服务端归属：协议分发层行为；当前未恢复到显式 `_GetServerVersion`
- 协议 / 命令线索：命令名字符串 `GetServerVersion` 已坐实；服务端存在 `GetServerVersion success: {}.` 日志；精确 JSON envelope 未恢复
- 返回值与默认值：C++ 为 `bool + out string`；Python 样例把结果当作直接字符串使用
- 典型工作流位置：`ConnectServer` 之后、机器人初始化前后均可读取的元信息接口
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、`libControllerClient.so`、`ControllerServer.cpython-37m-x86_64-linux-gnu.so`
- 置信度：高
- 待确认点：Python 失败路径的返回形态未看到样例；请求 JSON 的精确字段未恢复

### `GetClientVersion`

- C++ 公开签名：`bool GetClientVersion(std::string &version);`
- Python 包装形态：未见公开样例；从包装库字符串看接口存在
- 服务端归属：客户端本地行为，不进入服务端命令表
- 协议 / 命令线索：`libControllerClient.so` 与 `PyControllerClient` 都有 `GetClientVersion` 符号；未见 `ControllerServer` 对应 `_Xxx`
- 返回值与默认值：C++ 为 `bool + out string`；Python 侧返回形态待确认
- 典型工作流位置：客户端自检或 SDK 版本上报，不依赖服务端状态
- 证据来源：`ControllerClient.h`、`libControllerClient.so`、`PyControllerClient.cpython-37m-x86_64-linux-gnu.so`
- 置信度：高
- 待确认点：实际版本字符串来源与 Python 包装失败行为未恢复

## 3. 机器人初始化

### `SetUpRobot`

- C++ 公开签名：`bool SetUpRobot(const std::string &robot_name);`
- Python 包装形态：`c.SetUpRobot("FANUC_LR_Mate_200iD") -> bool`
- 服务端归属：`ControllerServer._SetUpRobot`
- 协议 / 命令线索：命令名 `SetUpRobot` 已坐实；参数高概率是 `robot_name`；精确 JSON envelope 未恢复
- 返回值与默认值：成功返回 `true`
- 典型工作流位置：创建客户端并连上 `50001` 后首先调用；旧说明明确它是最先执行的服务端初始化动作
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：请求字段键名是否为 `robot_name` 仍需抓包或 hook 坐实

### `SetUpRobotFromEnv`

- C++ 公开签名：`bool SetUpRobotFromEnv(const std::string &env_file);`
- Python 包装形态：未见公开样例；服务端与客户端字符串均存在
- 服务端归属：`ControllerServer._SetUpRobotFromEnv`
- 协议 / 命令线索：命令名 `SetUpRobotFromEnv` 已坐实；参数高概率是环境文件绝对路径；精确 JSON envelope 未恢复
- 返回值与默认值：成功返回 `true`
- 典型工作流位置：与 `SetUpRobot` 二选一；当现场通过环境文件而不是型号名初始化时使用
- 证据来源：`ControllerClient.h`、`ControllerServer_analysis.md`、`ControllerServer` 字符串、`libControllerClient.so`
- 置信度：高
- 待确认点：环境文件路径是否必须为绝对路径由注释可见，但服务端是否做额外归一化未恢复

### `IsSetUp`

- C++ 公开签名：`bool IsSetUp();`
- Python 包装形态：`c.IsSetUp() -> bool`
- 服务端归属：`ControllerServer._IsSetUp`
- 协议 / 命令线索：命令名 `IsSetUp` 已坐实；精确 JSON envelope 未恢复
- 返回值与默认值：直接返回布尔值
- 典型工作流位置：`SetUpRobot` 或 `SetUpRobotFromEnv` 之后的状态确认
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：服务端返回是否仅受机器人对象存在性控制，还是还依赖模型/控制器更深层状态，当前未完全恢复

### `SetShowTCP`

- C++ 公开签名：`bool SetShowTCP(bool is_show = true, double axis_length = 0.1, size_t axis_size = 2);`
- Python 包装形态：`c.SetShowTCP(is_show=True, axis_length=0.1, axis_size=2) -> bool`
- 服务端归属：`ControllerServer._SetShowTCP`
- 协议 / 命令线索：命令名 `SetShowTCP` 已坐实；字符串中可见 `SetShowTCP is_show success/failed`；精确 JSON envelope 未恢复
- 返回值与默认值：默认 `is_show=true`、`axis_length=0.1`、`axis_size=2`
- 典型工作流位置：初始化完成后、切换控制器前的仿真显示配置
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、`ControllerServer_analysis.md`、`ControllerServer` 字符串
- 置信度：高
- 待确认点：仅仿真控制器生效还是真实控制器也接受该命令，当前未见明确负例

### `GetName`

- C++ 公开签名：`std::string GetName();`
- Python 包装形态：`c.GetName() -> str`
- 服务端归属：`ControllerServer._GetName`
- 协议 / 命令线索：命令名 `GetName` 已坐实；精确 JSON envelope 未恢复
- 返回值与默认值：直接返回机器人名称字符串
- 典型工作流位置：完成机器人初始化后读取名称确认
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：失败时是返回空串还是异常/默认值，Python 样例未覆盖

### `GetDoF`

- C++ 公开签名：`int GetDoF();`
- Python 包装形态：`c.GetDoF() -> int`
- 服务端归属：`ControllerServer._GetDoF`
- 协议 / 命令线索：命令名 `GetDoF` 已坐实；精确 JSON envelope 未恢复
- 返回值与默认值：直接返回自由度整数
- 典型工作流位置：完成机器人初始化后读取自由度
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：失败时的客户端行为未恢复

## 4. 控制器状态

### `SetActiveController`

- C++ 公开签名：`bool SetActiveController(bool sim = true);`
- Python 包装形态：`c.SetActiveController(sim=True) -> bool`；真机样例使用 `sim=False`
- 服务端归属：`ControllerServer._SetActiveController`
- 协议 / 命令线索：命令名 `SetActiveController` 已坐实；字符串中可见 `SetActiveController sim success/failed`
- 返回值与默认值：默认 `sim=true`
- 典型工作流位置：机器人初始化后、`Connect` 前，用于在仿真控制器和真实控制器之间切换
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、`UseRealRobot.py`、SDK 手册、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：切换控制器时是否会隐式断开旧控制器，当前只有 `_DisconnectAll` 的间接线索

### `Connect`

- C++ 公开签名：`bool Connect(const std::string &robot_ip);`
- Python 包装形态：`c.Connect("192.168.10.101") -> bool`
- 服务端归属：`ControllerServer._Connect`
- 协议 / 命令线索：命令名 `Connect` 已坐实；字符串中可见 `Connect ip success/failed`
- 返回值与默认值：成功返回 `true`
- 典型工作流位置：选定活动控制器后，通知服务端连接真实机器人 IP
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、`UseRealRobot.py`、SDK 手册、`ControllerServer_analysis.md`、`FANUC_realtime_comm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：JSON 键名是否为 `ip` 或 `robot_ip` 未恢复；仿真模式下是否接受同一命令仍需实现侧验证

### `Disconnect`

- C++ 公开签名：`bool Disconnect();`
- Python 包装形态：`c.Disconnect() -> bool`
- 服务端归属：`ControllerServer._Disconnect`
- 协议 / 命令线索：命令名 `Disconnect` 已坐实；字符串中可见 `Disconnect success/failed`
- 返回值与默认值：直接返回布尔值
- 典型工作流位置：真实控制器断开或工作流结束时调用
- 证据来源：`ControllerClient.h`、`ControllerServer_analysis.md`、`ControllerServer` 字符串、`libControllerClient.so`
- 置信度：高
- 待确认点：是否同步清理状态通道 / 命令通道 / 伺服通道，当前只在 FANUC 分析文档看到对象链，并未完全坐实释放顺序

### `EnableRobot`

- C++ 公开签名：`bool EnableRobot(unsigned buffer_size = 2);`
- Python 包装形态：`c.EnableRobot() -> bool`
- 服务端归属：`ControllerServer._EnableRobot`
- 协议 / 命令线索：命令名 `EnableRobot` 已坐实；字符串中可见 `EnableRobot success/failed`
- 返回值与默认值：默认 `buffer_size=2`
- 典型工作流位置：`Connect` 后使能机器人；多数运动 API 前置条件
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、`UseRealRobot.py`、`ControllerServer_analysis.md`、`FANUC_realtime_comm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：`buffer_size` 在旧服务端具体如何映射到伺服缓冲区参数，当前未完全恢复

### `DisableRobot`

- C++ 公开签名：`bool DisableRobot();`
- Python 包装形态：`c.DisableRobot() -> bool`
- 服务端归属：`ControllerServer._DisableRobot`
- 协议 / 命令线索：命令名 `DisableRobot` 已坐实；字符串中可见 `DisableRobot success/failed`
- 返回值与默认值：直接返回布尔值
- 典型工作流位置：停机或退出前关闭机器人使能
- 证据来源：`ControllerClient.h`、`ControllerServer_analysis.md`、`FANUC_realtime_comm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：与 `StopMove` 的先后顺序约束未恢复

### `StopMove`

- C++ 公开签名：`bool StopMove();`
- Python 包装形态：`c.StopMove() -> bool`
- 服务端归属：`ControllerServer._StopMove`
- 协议 / 命令线索：命令名 `StopMove` 已坐实；字符串中可见 `StopMove success/failed`
- 返回值与默认值：直接返回布尔值
- 典型工作流位置：当前运动中止；Python 示例中调用后会再次 `EnableRobot()`
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、`ControllerServer_analysis.md`、`FANUC_realtime_comm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：是否会清空控制器执行队列、是否必须重新使能，当前只从示例看到倾向性而非硬约束

## 5. 参数与 IO

### `GetSpeedRatio`

- C++ 公开签名：`double GetSpeedRatio();`
- Python 包装形态：`c.GetSpeedRatio() -> float`
- 服务端归属：`ControllerServer._GetSpeedRatio`
- 协议 / 命令线索：命令通道 `MsgID = 0x2206`；响应字段为 `ratio_int` 与 `result_code`；成功后客户端将 `ratio_int / 100.0`
- 返回值与默认值：直接返回 `0~1` 之间的倍率
- 典型工作流位置：连机并使能后读取当前速度倍率
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、`CommonMsg_protocol_analysis.md`
- 置信度：高
- 待确认点：服务端 JSON 层到命令通道层的参数桥接结构未恢复

### `SetSpeedRatio`

- C++ 公开签名：`bool SetSpeedRatio(double ratio);`
- Python 包装形态：`c.SetSpeedRatio(0.8) -> bool`
- 服务端归属：`ControllerServer._SetSpeedRatio`
- 协议 / 命令线索：命令通道 `MsgID = 0x2207`；请求字段为 `ratio_int_0_100`；输入 `double` 先乘 `100` 并夹到 `[0,100]`
- 返回值与默认值：成功返回 `true`
- 典型工作流位置：连机并使能后修改控制器速度倍率
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、`UseRealRobot.py`、SDK 手册、`ControllerServer_analysis.md`、`CommonMsg_protocol_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：ratio 越界时客户端是裁剪还是直接失败，当前更偏向裁剪，但缺少公开负例

### `GetTCP`

- C++ 公开签名：`bool GetTCP(Pose &tcp);`
- Python 包装形态：`res, tcp = c.GetTCP()`
- 服务端归属：`ControllerServer._GetTCP`
- 协议 / 命令线索：控制器命令通道底层接口 `GetTCP` 已有 `MsgID = 0x2200` 证据，但 `ControllerClient` JSON 层请求结构未完全恢复
- 返回值与默认值：C++ 为 `bool + out Pose`；Python 为 `(bool, Pose)`
- 典型工作流位置：连机后读取当前控制器 TCP
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、`ControllerServer_analysis.md`、`CommonMsg_protocol_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：JSON 层是否支持多个 TCP ID，目前只看到底层命令通道有 `tcp_id`

### `SetTCP`

- C++ 公开签名：`bool SetTCP(const Pose &tcp);`
- Python 包装形态：`c.SetTCP(tcp) -> bool`
- 服务端归属：`ControllerServer._SetTCP`
- 协议 / 命令线索：控制器命令通道底层接口 `SetTCP` 已有 `MsgID = 0x2201` 证据；JSON 层精确字段未恢复
- 返回值与默认值：成功返回 `true`
- 典型工作流位置：连机后修改控制器 TCP
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、`ControllerServer_analysis.md`、`CommonMsg_protocol_analysis.md`、`FANUC_realtime_comm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：JSON 层是否也暴露 `tcp_id` 概念尚未恢复

### `GetIO`

- C++ 公开签名：`bool GetIO(unsigned port, bool &value, IOType type = kIOTypeDI);`
- Python 包装形态：`res, value = c.GetIO(port=1, io_type=IOType.kIOTypeDI)`
- 服务端归属：`ControllerServer._GetIO`
- 协议 / 命令线索：命令通道 `MsgID = 0x2208`；请求字段顺序是 `io_type`、`io_index`；响应字段是 `result_code`、`io_value`
- 返回值与默认值：默认 `type = kIOTypeDI`；C++ 为 `bool + out bool`；Python 为 `(bool, bool)`
- 典型工作流位置：连机后读取 DI/DO/RI/RO 等 IO 值
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、`CommonMsg_protocol_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：高层 JSON 是否把字段命名为 `port` / `value` / `type`，还是 `io_index` / `io_type`，当前未抓到完整包

### `SetIO`

- C++ 公开签名：`bool SetIO(unsigned port, bool value, IOType type = kIOTypeDO);`
- Python 包装形态：`c.SetIO(port=1, value=True, io_type=IOType.kIOTypeDO) -> bool`
- 服务端归属：`ControllerServer._SetIO`
- 协议 / 命令线索：命令通道 `MsgID = 0x2209`；请求字段顺序是 `io_type`、`io_index`、`io_value`
- 返回值与默认值：默认 `type = kIOTypeDO`
- 典型工作流位置：连机后设置数字输出；飞拍链路之外的普通 IO 调试也会用到
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、`CommonMsg_protocol_analysis.md`、`FANUC_realtime_comm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：布尔值在高层 JSON 中是否以 `true/false` 传输、在命令通道中以 `float` 传输，当前只坐实了命令通道层

## 6. 运动与求解

### `GetJointPosition`

- C++ 公开签名：`bool GetJointPosition(JointPositions &joint_position);`
- Python 包装形态：`res, joints = c.GetJointPosition()`
- 服务端归属：`ControllerServer._GetJointPositions`
- 协议 / 命令线索：命令名 `GetJointPositions` 已坐实；客户端公开 API 名与服务端方法名存在单复数差异
- 返回值与默认值：C++ 为 `bool + out JointPositions`；Python 为 `(bool, JointPositions)`
- 典型工作流位置：读取当前关节角，常作为 `GetNearestIK` 的 seed 或 `MoveJoint` 的基准
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：JSON 层返回数组字段键名未恢复

### `GetPose`

- C++ 公开签名：`bool GetPose(Pose &pose);`
- Python 包装形态：`res, pose = c.GetPose()`
- 服务端归属：`ControllerServer._GetPose`
- 协议 / 命令线索：命令名 `GetPose` 已坐实；字符串中可见 `GetPose success/failed`
- 返回值与默认值：C++ 为 `bool + out Pose`；Python 为 `(bool, Pose)`
- 典型工作流位置：读取当前 TCP 位姿，常与 `GetNearestIK` 配套使用
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：位姿坐标系定义虽然在 `Types.h` 中体现为 7 元数组，但 JSON 层字段结构未恢复

### `GetNearestIK`

- C++ 公开签名：`bool GetNearestIK(const Pose &pose, const JointPositions &seed, JointPositions &ik);`
- Python 包装形态：`res, ik = c.GetNearestIK(pose, joint_seed=joints)`
- 服务端归属：`ControllerServer._GetNearestIK`
- 协议 / 命令线索：命令名 `GetNearestIK` 已坐实；字符串中可见 `GetNearestIK success/failed`
- 返回值与默认值：C++ 为 `bool + out JointPositions`；Python 为 `(bool, JointPositions)`
- 典型工作流位置：先 `GetPose` 得到当前位姿，再构造目标位姿，并使用当前关节或邻近关节作为 seed 求最近 IK
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：JSON 层中 seed 参数键名在 Python 里表现为 `joint_seed`，但 C++ 注释写的是 `seed`；高层字段命名仍待确认

### `MoveJoint`

- C++ 公开签名：`bool MoveJoint(const JointPositions &joint_position);`
- Python 包装形态：`c.MoveJoint(home_joint) -> bool`
- 服务端归属：`ControllerServer._MoveJoint`
- 协议 / 命令线索：命令名 `MoveJoint` 已坐实；字符串中可见 `MoveJoint waypoint success/failed`
- 返回值与默认值：成功返回 `true`
- 典型工作流位置：点到点回零或移动到飞拍轨迹起点
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、`ControllerServer_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：移动速度/平滑参数是否固定在服务端内部，公开 API 未暴露

### `ExecuteTrajectory`

- C++ 公开签名：`bool ExecuteTrajectory(const std::vector<JointPositions> &waypoints, const std::string &method = "icsp", bool save_traj = false);`
- Python 包装形态：`c.ExecuteTrajectory(waypoints=[...], method="icsp", save_traj=True) -> bool`
- 服务端归属：`ControllerServer._ExecuteTrajectory`
- 协议 / 命令线索：命令名 `ExecuteTrajectory` 已坐实；`method` 至少支持 `icsp` 与 `doubles`
- 返回值与默认值：默认 `method="icsp"`、`save_traj=false`
- 典型工作流位置：普通多点轨迹执行，不带飞拍 IO；输入是关节空间稀疏 waypoint，而不是笛卡尔点
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、`Trajectory_generation_algorithm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：JSON 中 waypoint 列表的键名和序列化结构未恢复；`doubles` 的失败语义未在公开样例中体现

## 7. 飞拍轨迹

### `UploadFlyShotTraj`

- C++ 公开签名：`bool UploadFlyShotTraj(const std::string &name, const std::vector<JointPositions> &waypoints, const std::vector<bool> &shot_flags, const std::vector<int> &offset_values, const std::vector<std::vector<int>> &addrs);`
- Python 包装形态：`c.UploadFlyShotTraj(name="test_traj", waypoints=..., shot_flags=..., offset_values=..., addrs=...) -> bool`
- 服务端归属：`ControllerServer._UploadFlyShotTraj`
- 协议 / 命令线索：命令名 `UploadFlyShotTraj` 已坐实；客户端字符串中可见 `StartUploadFlyShotTraj` 与 `EndUploadFlyShotTraj`，说明上传阶段很可能分为开始 / 传输 / 结束三个子步骤
- 返回值与默认值：成功返回 `true`；无默认参数
- 典型工作流位置：运行时动态构造飞拍轨迹时，先把轨迹定义登记到服务端
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、`Trajectory_generation_algorithm_analysis.md`、`libControllerClient.so`、`ControllerServer` 字符串
- 置信度：高
- 待确认点：JSON 上传是否一次性发送完整 payload，还是像字符串暗示的那样分片上传，当前未完全恢复

### `DeleteFlyShotTraj`

- C++ 公开签名：`bool DeleteFlyShotTraj(const std::string &name);`
- Python 包装形态：`c.DeleteFlyShotTraj(name="test_traj") -> bool`
- 服务端归属：`ControllerServer._DeleteFlyShotTraj`
- 协议 / 命令线索：命令名 `DeleteFlyShotTraj` 已坐实；字符串中可见 `DeleteFlyShotTraj {} success/failed`
- 返回值与默认值：成功返回 `true`
- 典型工作流位置：删除已上传的临时飞拍轨迹定义
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、SDK 手册、`ControllerServer_analysis.md`、`PyControllerClient` 字符串、`ControllerServer` 字符串
- 置信度：高
- 待确认点：删除配置内固有轨迹名与删除运行时上传轨迹时是否走同一条路径，当前未恢复

### `ListFlyShotTraj`

- C++ 公开签名：`std::vector<std::string> ListFlyShotTraj();`
- Python 包装形态：`c.ListFlyShotTraj() -> list[str]`
- 服务端归属：`ControllerServer._ListFlyShotTraj`
- 协议 / 命令线索：命令名 `ListFlyShotTraj` 已坐实；客户端与服务端字符串都出现 `GetNextListFlyShotTraj`，说明底层列举很可能是迭代式获取，而不是一次性返回整个数组
- 返回值与默认值：直接返回轨迹名称列表
- 典型工作流位置：查看当前服务端已登记的飞拍轨迹
- 证据来源：`ControllerClient.h`、`UseControllerClient.py`、`ControllerServer_analysis.md`、`libControllerClient.so`、`ControllerServer` 字符串
- 置信度：高
- 待确认点：高层 JSON 是否真的直接返回数组，还是客户端内部循环拉取后再拼成数组，当前未完全恢复

### `ExecuteFlyShotTraj`

- C++ 公开签名：`bool ExecuteFlyShotTraj(const std::string &name, const bool move_to_start = false, const std::string &method = "icsp", bool save_traj = false, bool use_cache = false);`
- Python 包装形态：`c.ExecuteFlyShotTraj(name="002", move_to_start=True, method="icsp", save_traj=True, use_cache=False) -> bool`
- 服务端归属：`ControllerServer._ExecuteFlyShotTraj`
- 协议 / 命令线索：命令名 `ExecuteFlyShotTraj` 已坐实；字符串中出现 `move_to_start`、`use_cache`；伪代码级逆向已恢复其主流程
- 返回值与默认值：默认 `move_to_start=false`、`method="icsp"`、`save_traj=false`、`use_cache=false`
- 典型工作流位置：对已存在的飞拍轨迹定义执行“生成 + 挂接 DO 时间轴 + 执行”
- 证据来源：`ControllerClient.h`、`UseControllerClient.cpp`、`UseControllerClient.py`、`UseRealRobot.py`、SDK 手册、`ControllerServer_analysis.md`、`Trajectory_generation_algorithm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：JSON 包结构未恢复；`use_cache` 的缓存键是否只按 `name`，当前从伪代码判断是，但未见更底层证据

### `SaveTrajInfo`

- C++ 公开签名：`bool SaveTrajInfo(const std::string &name, const std::string &method = "icsp");`
- Python 包装形态：未见运行样例，但包装库和服务端都有明确字符串；语义可由手册和分析文档确认
- 服务端归属：`ControllerServer._SaveTrajInfo`
- 协议 / 命令线索：命令名 `SaveTrajInfo` 已坐实；字符串中可见 `SaveTrajInfo {} success/failed`
- 返回值与默认值：默认 `method="icsp"`；`self-adapt-icsp` 在执行时保存分析文件会回落成 `icsp` 导出语义
- 典型工作流位置：按给定 `name + method` 生成并导出轨迹分析文件，例如 `JointTraj.txt`、`CartDetialTraj.txt`
- 证据来源：`ControllerClient.h`、`ControllerServer_analysis.md`、`Trajectory_generation_algorithm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：Python 包装是否直接暴露该方法并返回 `bool`，虽然字符串存在，但公开示例未调用

### `IsFlyShotTrajValid`

- C++ 公开签名：`bool IsFlyShotTrajValid(double &time, const std::string &name, const std::string &method = "icsp", bool save_traj = false);`
- Python 包装形态：`valid, time_sec = c.IsFlyShotTrajValid("EOL9_EAU_90", "icsp", save_traj=True)`
- 服务端归属：`ControllerServer._IsFlyShotTrajValid`
- 协议 / 命令线索：命令名 `IsFlyShotTrajValid` 已坐实；作用是“生成 + 合法性检查 + 返回轨迹总时长”
- 返回值与默认值：默认 `method="icsp"`、`save_traj=false`；C++ 为 `bool + out double`；Python 为 `(bool, float)`
- 典型工作流位置：在执行飞拍轨迹前预校验；也可与 `save_traj=True` 结合导出分析文件
- 证据来源：`ControllerClient.h`、`UseControllerClient.py` 中的注释样例、`ControllerServer_analysis.md`、`Trajectory_generation_algorithm_analysis.md`、二进制字符串
- 置信度：高
- 待确认点：`method="self-adapt-icsp"` 是否被该接口完整支持，分析文档显示公开手册更强调 `icsp` / `doubles`，而示例注释里又出现 `self-adapt-icsp`，这里仍需后续抓包或真环境验证

## 8. 四条旧 SDK 工作流

### 8.1 初始化工作流

```text
ControllerClient()
  -> ConnectServer("127.0.0.1", 50001)
  -> SetUpRobot("FANUC_LR_Mate_200iD") 或 SetUpRobotFromEnv(...)
  -> IsSetUp()
  -> GetName()
  -> GetDoF()
  -> SetShowTCP(...)
```

说明：

- 这是最常见的仿真或真机前置流程。
- `SetUpRobot` 是旧说明里明确要求首先执行的服务端初始化动作。

### 8.2 控制器状态工作流

```text
SetActiveController(sim=True/False)
  -> Connect(robot_ip)
  -> EnableRobot(buffer_size=2)
  -> GetSpeedRatio() / SetSpeedRatio(...)
  -> GetTCP() / SetTCP(...)
  -> GetIO() / SetIO(...)
  -> StopMove()
  -> DisableRobot()
  -> Disconnect()
```

说明：

- 真机样例会使用 `sim=False`。
- `StopMove()` 之后，Python 示例里会再次 `EnableRobot()`，说明停止运动后常伴随重新使能。

### 8.3 普通轨迹工作流

```text
GetJointPosition()
  -> GetPose()
  -> GetNearestIK(pose, seed)
  -> MoveJoint(home_joint)
  -> ExecuteTrajectory(waypoints, method="icsp", save_traj=True)
```

说明：

- 输入是关节空间稀疏 waypoint。
- `ExecuteTrajectory` 至少支持 `icsp` 与 `doubles`。

### 8.4 飞拍轨迹工作流

#### 方案 A：轨迹名已在配置中存在

```text
name
  -> IsFlyShotTrajValid(name, "icsp", save_traj=True)
  -> ExecuteFlyShotTraj(name, move_to_start=True, method="icsp", save_traj=True, use_cache=False)
  -> SaveTrajInfo(name, "icsp")
```

#### 方案 B：客户端动态上传飞拍轨迹

```text
UploadFlyShotTraj(name, waypoints, shot_flags, offset_values, addrs)
  -> ListFlyShotTraj()
  -> IsFlyShotTrajValid(name, "icsp", save_traj=True)
  -> ExecuteFlyShotTraj(name, move_to_start=True, method="self-adapt-icsp", save_traj=True, use_cache=True)
  -> DeleteFlyShotTraj(name)
```

说明：

- `UploadFlyShotTraj` 只负责登记轨迹定义。
- `IsFlyShotTrajValid` 负责“生成 + 合法性检查”。
- `ExecuteFlyShotTraj` 负责“生成 + 挂接 `TrajectoryDO` + 执行”。
- `SaveTrajInfo` 负责导出分析文件。

## 9. 已知高置信协议线索

当前能直接用于后续实现的高置信协议结论如下：

- 传输层为 `TCP + JSON` 风格协议，不是 HTTP/gRPC。
- JSON 层至少存在 `method` 字段，服务端存在 `_ClientCB` 与 `_IsJsonValid`。
- 命令通道字段已确认：
  - `GetSpeedRatio`：`MsgID = 0x2206`
  - `SetSpeedRatio`：`MsgID = 0x2207`
  - `GetIO`：`MsgID = 0x2208`
  - `SetIO`：`MsgID = 0x2209`
- 2026-04-28 `UTTC_MS11` 抓包中，`speed_ratio=0.7` 的效果能从 UDP 60015 主运行段时间尺度反推出来，但机器人侧 `TCP 10012` 未出现 `0x2207 SetSpeedRatio`；兼容实现不能只依赖一次 10012 命令来表达执行倍率，还要在 J519 发送时间轴上应用当前倍率。J519 实发时间为 `t_send = k * 0.008`，原轨迹采样时间为 `t_traj = t_send * speed_ratio`，包数为 `floor(duration / (0.008 * speed_ratio)) + 1`。
- 飞拍轨迹相关额外字符串线索：
  - `StartUploadFlyShotTraj`
  - `EndUploadFlyShotTraj`
  - `GetNextListFlyShotTraj`
  - `move_to_start`
  - `use_cache`
  - `shot_flags`
  - `offset_values`
  - `addr` / `addrs`

## 10. 待确认问题

以下问题本轮故意保留，不冒充已确认结论：

1. `50001/TCP+JSON` 请求 JSON 的精确 envelope 结构、字段必填规则、响应包统一格式。
2. `GetServerVersion` 在高层 JSON 中的完整请求 / 响应字段。
3. `GetClientVersion` 的实际版本字符串来源，以及 Python 包装失败路径。
4. `ListFlyShotTraj` 是高层一次性返回数组，还是客户端内部循环 `GetNextListFlyShotTraj` 后再拼装列表。
5. `UploadFlyShotTraj` 是否采用开始 / 数据 / 结束的多阶段上传协议。
6. `IsFlyShotTrajValid` 对 `self-adapt-icsp` 的真实支持边界。
7. `SetTCP` / `GetTCP` 在高层 JSON 中是否暴露 `tcp_id` 概念。
8. `SetActiveController` 切换控制器时是否会隐式触发 `_DisconnectAll`。

## 11. 后续实现使用方式

等继续扩展 `Flyshot.ControllerClientCompat` 时，建议按以下顺序使用本文档：

1. 先把 32 个 API 按本文档拆成命令表。
2. 先实现高置信、状态简单的接口：
   - `GetServerVersion`
   - `SetUpRobot`
   - `IsSetUp`
   - `GetName`
   - `GetDoF`
   - `GetSpeedRatio`
   - `SetSpeedRatio`
   - `GetIO`
   - `SetIO`
3. 再实现返回复杂结构的接口：
   - `GetTCP`
   - `GetJointPosition`
   - `GetPose`
   - `GetNearestIK`
4. 最后实现飞拍轨迹相关接口，并把本文档中的“待确认问题”逐项收敛成兼容测试。
