Files
FlyShotHost/docs/controller-client-api-reverse-engineering.md
yunxiao.zhu 0724efebed feat(*): 完善 FANUC J519 闭环、MoveJoint 与现场抓包验证
* 划分 J519 发送循环与稠密轨迹循环职责边界,
  FanucJ519Client 负责 UDP 周期发送,
  FanucControllerRuntime 按轨迹时间更新下一帧命令
* 执行时将规划输出 rad 转为 J519 deg 目标,
  并按 speed_ratio 调整 8ms 发送时间尺度
* 补齐 accept_cmd/received_cmd/sysrdy/rbt_inmotion
  状态位解析与启动前闭环检查
* MoveJoint 改为关节空间直线 + smoothstep 进度
  的临时 PTP 稠密轨迹,按 status=15 运动窗口复现
* 新增 UTTC 2026-04-28 三份抓包 golden tests,
  覆盖 0.5/0.7/1.0 speed_ratio 下的 J519 命令、
  IO 脉冲与响应滞后
* 状态通道补充超时重连策略与退避逻辑
* TCP 10012 命令响应统一检查 result_code
* 状态页扩展 J519 状态位与快照诊断信息
* 新增 docs/fanuc-field-runtime-workflow.md 现场工作流
* 补充 LR Mate 200iD 模型、RobotConfig.json 与 workpiece
2026-04-29 01:03:18 +08:00

563 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 发送时间轴上应用当前倍率。实发规则为 `t_traj = k * 0.008 * 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. 最后实现飞拍轨迹相关接口,并把本文档中的“待确认问题”逐项收敛成兼容测试。