XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFE.SpaceEngineers.AgentBridge

【SpaceEngineer】AI调试插件

公开
关注 0 Fork 0 Star 0
返回提交历史

SpaceEngineersModDev/XFE.SpaceEngineers.AgentBridge

记录 AMS 实机闭环验证并更新飞行追踪映射

5853015
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

2 个文件 +121 -57
Modified docs/DEBUGGING.md +83 -42
@@ -2,73 +2,114 @@
2 2
3 3 日期:2026-09-14。游戏:Space Engineers 1.210.014,Windows x64。
4 4
5 本次通过 XFE 自研加载器实际加载 `XFE.SeAgent.Plugin.dll`,由 `xfe-se` 访问正在运行的游戏。下面的“实测”来自游戏返回值和连续遥测,不是单元测试中的模拟对象。
5 本报告通过 XFE 自研加载器实际加载 `XFE.SeAgent.Plugin.dll`,由 `xfe-se` 读取正在运行的游戏。实测结论来自连续遥测、编程块实例和游戏返回值;模拟测试另行说明。
6 6
7 7 ## 环境与数据保护
8 8
9 - 自动找到含 13 个 AMS 编程块的存档:1 个舰队主控和 12 台矿机。
10 - 创建 `XFE Agent Debug AMS 20260914-172143` 副本,配置为离线,关闭自动保存,仅将副本路径加入写操作授权列表。
11 - 原始文件摘要、复制路径和编程块清单保存在本地 `artifacts/world-preparation.json`。原始存档不部署脚本、不接收调试命令。
12 - 原始 AMS 工作区存在用户尚未提交的 `FleetController.cs` 修改;本次脚本修复使用独立工作树,保留该修改。
13 - 结束后复核原存档 **25 个文件**:哈希全部一致,没有新增或删除文件。通过插件保存调试副本并退出游戏,加载器确认 `Space Engineers exited normally`。
9 - 测试存档包含 13 个 AMS 编程块:1 个舰队主控、12 台矿机。写操作仅授权调试副本;副本配置为离线、自动保存间隔为零。
10 - 首轮副本为 `XFE Agent Debug AMS 20260914-172143`。结束后复核原存档 25 个文件,哈希全部一致,没有新增或删除文件;通过 `world.exit {"save":true}` 保存副本并正常退出。
11 - 本轮使用新的 `XFE Agent Debug AMS 20260914-182847` 副本;准备记录为 `artifacts/verification-world-preparation.json`。该副本完成探索、两次 7 号返航及后续 2 号捕获修复复测。
12 - 收尾核对 13 个实际 PB 的源码摘要均与最终构建清单相符,均有编译实例且无编译错误。原存档按准备阶段相同范围复核(排除已有 `Backup` 目录),25 个文件哈希及清单完全一致。副本保存成功后正常退出,游戏进程已结束。核对结果保存在 `verification-live-final-programs.json`、`verification-final-audit.json` 和 `verification-game-final-exit.json`。
13 - AMS 原工作区存在用户尚未提交的修改,修复在独立工作树完成,保留原工作区。私人存档、完整实例快照和原始飞行记录保留在本地 `artifacts/`,不随源码提交。
14 14
15 15 ## 已验证的插件能力
16 16
17 17 | 检查 | 实测结果 |
18 18 | --- | --- |
19 | XFE 加载器接入、游戏线程 Update、具有关联 ID 的管道请求 | 插件加载成功,跨多次游戏启动正常建立端点 |
19 | 加载器、游戏线程 Update、带关联 ID 的管道请求 | 实际加载成功,多次启动均正常建立端点 |
20 20 | 授权副本加载 | 从主菜单加载成功,`ready=true`、`onlineMode=OFFLINE`、`canMutate=true` |
21 | PB 枚举、源码、运行实例与编译状态 | 13 个编程块均有实例,基线无编译错误 |
22 | 受限实例字段读取 | 可读取 AMS 状态、任务、飞控、缓存及事件;支持游戏编译器生成的 MemorySafe 集合 |
23 | 设备遥测 | 读取实际相机、推力覆盖、连接器、库存及网格速度;7 号为 85 个方块、16 个推进器、28 个摄像头 |
24 | 停靠状态 | 基线 7 号已对接,16 个推进器全部关闭、推力覆盖为零 |
25 | 执行 AMS 命令 | 主控“继续 深空工业7号”“探索 250”“返航 深空工业7号”在游戏中执行成功 |
26 | 出航 | 7 号从待命切换为离港;样本实际速度 1.72 m/s、指令速度 2 m/s |
27 | 源码部署与备份 | 对已停止的 12 号重新部署相同导出源码,SHA-256 校验通过,生成备份,游戏实际编译成功且无编译错误 |
28 | 引擎截图 | 真实 PNG 输出成功,并人工核对截图中的舰队场景 |
29 | 保存与暂停 | 测试副本保存成功;插件持有和释放暂停均可读取确认 |
30 | 正常退出 | `world.exit {"save":true}` 返回保存成功,随后插件正常 Dispose,游戏进程退出,加载器记录正常退出 |
21 | PB 枚举、源码与编译状态 | 13 个编程块均有实例,基线无编译错误;部署后可核对源码摘要与编译结果 |
22 | 受限实例检查 | 可读 AMS 任务、飞控、事件和游戏编译器生成的 MemorySafe 集合 |
23 | 设备遥测 | 可读相机、推力覆盖、连接器约束点、库存、网格速度以及含装甲的船体完整度 |
24 | 源码部署、备份与命令 | SHA-256 前置校验、持久备份、游戏内编译及继续/探索/返航命令均实测成功 |
25 | 截图、暂停和保存 | 生成并人工核对真实 PNG,暂停状态和副本保存可读取确认 |
26 | 正常退出 | `world.exit` 返回保存成功,随后插件 Dispose、游戏进程退出,加载器记录正常退出 |
31 27
32 ## AMS 发现:探索入口不可达导致反复绕行
28 ## 首轮发现:不可达探索入口反复绕行
33 29
34 基线矿机导出 SHA-256:`2cc105a720ecd1552791816a0edf106cfab91b501a1e8048421b7f23382d333a`。
30 7 号的探索入口距离新鲜的母舰射线命中点仅 **1.54 m**,矿机避碰半径约 **4.88 m**。连续 **52.53 秒、43 个样本**显示约五次局部绕行;脚本时间超过 503 秒时仍执行同一任务。期间实际速度曾从 7.32 降至 0.27 m/s,说明问题包含无法结束任务,不能简单归结为没有制动。
35 31
36 7 号接到 `主控-job-346` 后,探索入口距一个新鲜的母舰射线命中点仅 **1.54 m**;矿机使用的避碰半径约 **4.88 m**。连续 52.53 秒的 43 个样本显示约五次局部绕行,仍在同一任务入口附近。随后脚本时间超过 503 秒时依然执行同一任务。
32 原 `Transit` 超时依赖瞬时 `flight.Blocked`。飞控不断找到局部绕点时,该标志会清除,即使长期没有接近入口也不会报告受阻。修复改为:连续 45 秒没有累计接近入口至少 2 m,先制动,再报告 `Blocked`,等待主控续派;正常缓慢进展和同帧发现小行星仍优先处理。
37 33
38 制动并非完全失效:一次接近过程的实际速度从 7.32 降至 0.27 m/s,显示船体余量 1.3 m 时指令速度为零,选择绕点后才再次加速。记录没有给出发生碰撞的证据,但明确显示任务无法结束。
34 首轮部署后只观察到返航,没有再次进入探索入口,因此当时尚不能确认超时与续派有效。以下新副本记录补上了这项实机验证。
39 35
40 代码原因:`Transit` 原先依赖瞬时 `flight.Blocked` 才触发超时处理;飞控不断找到局部绕点时该标志会清除,即使长期没有接近任务入口,也不会报告任务受阻。不能把绕点之间的移动误判为任务取得进展。
36 ## 本轮探索、避让与返航结果
41 37
42 对应原始证据保存在本地 `seven-survey-navigation.jsonl`、`seven-current.json`,不将整个私人存档和完整实例快照提交到 Git。
38 | 场景 | 实测结果 | 本地证据 |
39 | --- | --- | --- |
40 | 不可达入口超时 | `job-346` 在最后一次有效接近后 **45.016 秒**报告 `Blocked`;报告后 **4.033 秒内**首次采样确认已执行下一任务 | `verify-flight-02.jsonl`、`verification-metrics-stage1.json` |
41 | 同入口任务分组跳过 | 同入口共 **42 个任务**由原来的 2 个已受阻、40 个未完成,变为全部受阻;随后分配 `job-304`,入口移动 **100.778 m** | `verify-group-skip-flight.jsonl`、`verify-group-planner-storage.json` |
42 | 2 号经过暂停的 9 号 | 旧记录反复因 9 号触发避让;船体窄筛修复后,2 号实际通过该位置到达泊位末段,新记录没有再次出现避让 9 号的原因文本 | `verify-two-return-flight.jsonl`、`verify-final-two-flight.jsonl` |
43 | 2 号末段捕获修复 | 新版实际穿过旧标定终点并连接到分配泊位,最终“待命中”;连续记录没有再次进入末段停滞或退让 | `verify-capture-fix-connectors.jsonl`、`verify-capture-fix-two-flight.jsonl` |
44 | 7 号正常探索 | 连续记录包含 **27 个不同任务的 `SurveyEmpty` 报告**,每个都有实际 `Scan` 数据,任务为 `job-304` 至 `job-330`,正常续派 | `verify-final-seven-explore.jsonl` |
45 | 7 号返航与再次出航 | 第一次两端确认 `Connected` 后正常离港并继续探索;探索结束后的第二次返航也由两端确认连接,最终状态为 `Servicing`,原因“待命中” | `verify-final-connectors.jsonl`、`verify-seven-return-connectors.jsonl`、`verify-final-seven-explore.jsonl` |
46 | 停靠后推进器 | 最终版本的 2 号、7 号各 **16 个推进器全部 `enabled=false`**,实际推力和推力覆盖均为零 | `verify-two-docked-hardware-final.json`、`verify-seven-docked-hardware-9553.json` |
43 47
44 ### 对应修复与验证程度
48 **计时口径:**45.016 秒使用 PB 内部进展时间与报告状态时间相减;4.033 秒是报告到首次观察到下一任务的采样上界,不能当作精确的调度耗时。下一任务记录的状态起始时间距报告约 2.783 秒。42 个是整组任务数,其中本次新转为受阻的是 40 个。
45 49
46 修复位于 AMS 的独立分支 `codex/agent-debug-unreachable-entry`,本地提交 `c5f2d22`:Survey 连续 45 秒没有累计接近入口至少 2 m 时,先制动,再通过现有结果消息报告 `Blocked`,进入等待续派流程。正常的短暂绕远和持续缓慢接近仍允许继续;同一帧发现小行星时优先报告发现结果,不伪造已扫描的覆盖区域。
50 上述阶段的矿机源码摘要前缀分别为:超时验证 `b191430cf9ab`,分组跳过验证 `2aed54ad323c`,避让改善和本节返航验证 `1146850d83e9`。不能将不同部署阶段的遥测混为同一版本。
47 51
48 增加六项针对性回归,包含绕圈时 `flight.Blocked=false`、缓慢累计进展、短暂绕远、恢复任务和发现优先。完整 AMS 构建的中英文测试各 **810 项通过**,八份导出通过编译与字符限制检查。
52 ### 2 号与 9 号的球形误判
49 53
50 修复后的中文矿机导出为 **95,590 字符**,SHA-256:`b191430cf9ab7fe2b21569344ebcdc927bfa52847b84632440bdc68f3e5abc73`。通过插件部署到副本中的 7 号,真实游戏返回 `deployed=true`、`compiled=true`、`hasInstance=true`、`compilerErrors=[]`,原源码已有持久备份。
54 旧筛选使用的两船合计球形间距约 **10.263 m**。两船姿态对齐、2 号沿该对接轴直行时,横向中心间隔约 **4.905 m**,由实际船体边界计算的净距约 **0.405 m**,并不存在球体重叠所暗示的船体相交。旧逻辑因此反复让行,妨碍接近。
51 55
52 更新后 43 个实机样本仍处于返航对齐/避让 2 号阶段,**没有重新进入 Survey Transit,因此本轮不能宣称已实机验证 45 秒超时与续派**。`seven-fixed-entry-first.jsonl` 是这次尝试的原始记录,其文件名不代表成功执行了探索入口测试。
56 改进后的筛选使用真实船体边界和连续时间的有向包围盒检查,并保留旋转、遥测年龄和旧版遥测的保守处理。本轮实机证明 2 号能通过这一具体位置;0.405 m 的结论仅适用于所核对的对齐直线路径,不代表转弯、横移或任意姿态均有同样净距。几何输入和来源记录在 `verification-review-stage2.json`。
53 57
54 ## 返航的额外观察与验证边界
58 ### 船体完整度前后核对
55 59
56 7 号响应返航后驶向对接点,途中因 2 号矿机反复触发近距离避让;2 号当时报告三次靠泊失败并进入紧急状态。此段记录尚不能证明 7 号最终完成对接,也不能据此声称末段实际速度始终不低于 0.5 m/s。
60 逐一比较 `verify-final-hull-baseline-predeploy.json` 与 `verify-final-hull-after-survey.json`,并在捕获修复后再次核对 `verify-all-hull-final.json`:**13 个网格的 ID、方块数和完整度对象全部一致**,检查均未截断,包含装甲块。
57 61
58 2 号与母舰连接器均启用、完好、正常供电且属于同一所有者,两接口轴向相反、上方向一致。读取时的约 102 m 间距是失败后退让的结果;屏幕显示的是失败时的距离,不能把两者直接比较来断言航点计算错误。标定中心间距约 2.227 m;游戏实际捕获判定使用连接约束点而非方块中心,现有记录不足以认定捕获距离为根因。此问题仍需在再次进入末段时记录约束点与捕获状态。
62 | 网格 | 数量 | 每个网格方块数 | 每个网格当前/最大完整度 | 损伤与变形 |
63 | --- | --- | --- | --- | --- |
64 | 矿机 | 12 | 85 | 47,056 / 47,056 | 当前伤害、累计待处理伤害、受损块、变形块均为零 |
65 | 母舰 | 1 | 1,310 | 5,389,514 / 5,389,514 | 同上 |
59 66
60 本次未完成整套舰队长时间采矿、发现矿产后钻探分配、多矿小行星显示和所有方向相机布局组合的实机验收。插件已经具备继续验证这些行为所需的源码、状态、命令、相机和遥测接口;接口可用不等于业务场景全部通过。
67 这些记录支持本轮前后没有船体完整度损失或变形;完整度不变本身不能证明绝无任何物理接触。
61 68
62 ## 实测中修正的调试工具问题
69 ## 2 号末段:旧标定终点导致停滞
63 70
64 - 仿真速度改用 `MyPhysics.SimulationRatio`。此前读取的会话累计统计不是实时倍率,不能作为实际仿真速度报告。
65 - 实例检查适配 `VRage.Scripting.MemorySafeTypes` 的受限集合,仍保留节点、深度、元素和字符串上限。
66 - 库存质量按实际游戏接口的 kg 返回,体积为 m³;货物库存单独标记,反应堆燃料不伪装成待卸货物。
67 - 保存后的第一次 Windows 关闭窗口操作触发游戏 IME 卸载异常。改为提供 `world.exit {"save":true}`,调用游戏自身退出 API,避免使用关闭窗口作为可靠的重启步骤。
71 避让修复后,2 号已实际到达泊位末段。`verify-final-connectors.jsonl` 显示两端连接器均启用、正常工作且完好,所有者相同,接口轴向相反、横向偏差约毫米级;然而一直保持 `Unconnected`。
68 72
69 ## 自动检查
73 其约束点间距曾降至 **0.302131 m**,对应连接器方块中心距约 **2.134378 m**,随后回退并稳定在约束点间距约 **0.395 m**、中心距约 **2.228 m**。`verify-final-two-flight.jsonl` 在约一分钟内反复记录“距离 0.0”、指令速度 **0.5 m/s**,而实际速度接近零,最后触发对接超时退让。
70 74
71 - 完整解决方案 Release 构建:零警告、零错误。
72 - .NET 检查:**46 项通过**。覆盖真实 Windows 命名管道、权限、游戏线程队列、过期和断开取消、响应大小、CLI 实际进程、部署参数与连续记录。
73 - Python 检查:**9 项通过**。使用隔离的临时用户目录验证存档选择、复制、原文件保护、授权配置与错误情况。
74 - 上述自动检查不替代真实游戏中的飞行和碰撞验证。
75 代码中旧目标恰好位于标定接触点。飞控到达或越过目标后,位移方向会改变;极近距离还会使用船体前向作为备用方向。对于后置连接器,这会使接近指令在旧终点附近反向。仅提高速度标量的下限,不能保证持续朝接口内侧移动。实测约束点闭合速度曾依次约为 **0.510、0.456、0.147 m/s**,之后间距增大,符合该停滞机制;这些速度由相邻物理帧的约束点间距计算,没有把指令速度当作实际速度。
76
77 作为同一现场的对照,7 号第一次返航在中心距约 **2.009880 m** 时仍未连接,下一样本在约 **1.993233 m** 时已由两端确认连接;当时约束点间距约 **0.160985 m**。第二次返航也成功,最终硬件快照约束点间距约 **0.165789 m**。这些是此现场的观测值,不能推广为所有连接器的固定捕获阈值。
78
79 ### 捕获距离的判定边界
80
81 对本机实际 `Sandbox.Game.dll` 的只读 IL 核对表明:`TryAttach` 中约束点距离平方小于 **0.35** 是后续条件之一;其平方根约 **0.591608 m**,不能直接当作充分的自动捕获半径。
82
83 在检查这一距离之前,引擎还必须通过模型连接探测区域、候选网格和方块搜索找到另一连接器;之后还有工作状态、友好关系、物理状态、连接器类型和相向角度等条件。自动尝试捕获约每 40 个仿真帧进行一次,PB 的 `Connect()` 也不能把一个尚未建立磁性约束的任意连接器强制变为已连接。
84
85 因此,“约束点已近于 0.592 m”或“曾经在这个中心距离保存过标定”都不足以证明新一次接近必定能捕获。现有公开遥测不能确定 2 号具体未通过哪一项内部候选搜索条件;可以确认的是,旧飞控会停在尚未捕获的名义终点,而 7 号在继续靠近后成功连接。
86
87 ### 2 号捕获修复:实机通过
88
89 新修复保留名义接触点用于姿态、误差和诊断,仅在已标定且完成姿态同步的接近阶段,将控制目标沿连接器轴向内延伸 **0.6 m**,避免在旧终点反向。若实际位置越过名义接触点内侧 **0.35 m** 仍未捕获,则先制动并进入退让;每次先检查 `Connectable`,已经磁性吸附时优先锁定。0.35 m 是退让触发线,并非忽略惯性的硬停止边界。方向依据母舰连接器轴线,针对后置、侧置、无捕获退让和 40 帧捕获相位的闭环回归已加入。
90
91 矿机源码摘要 `9553e0ec92de8fc93c814852f37ff088f579c038ca8bdcf6c06b57e0f44d28ab` 部署后的实机复测包含 **539 个连接器快照**及 **242 个 PB 飞行样本**。2 号本次成功锁定分配的母舰连接器,双方 `otherConnectorId` 相互匹配,并进入 `Servicing`、原因“待命中”;记录结束时保持连接。7 号在这段记录中也始终正确连接于自己的泊位。
92
93 | 观测点 | 结果 |
94 | --- | --- |
95 | 穿过旧标定终点 | 连接器中心距连续从 2.283269 → 2.172449 → 2.062360 → 1.952804 m,越过旧标定 2.226946 m,没有在该终点反转停住 |
96 | 穿越前后实际径向闭合速度 | 由约束点距离差与物理帧差计算,依次约 **0.5115、0.5081、0.5056 m/s** |
97 | 最后两个 PB 接近样本 | 实际速度 **0.511136、0.505106 m/s**,指令速度均为 0.5 m/s |
98 | 首次双方确认连接 | **11:21:05.8727451 UTC**,第 312 个连接器样本、物理帧 76233;前一未连接样本为 11:21:05.6561569 UTC,因此转换位于约 0.217 秒的采样区间内 |
99 | 首次 PB 确认待命 | 11:21:05.886378 UTC,`Servicing`、原因“待命中” |
100 | 连接后几何 | 首次连接中心距约 1.829180 m,约束点距离约 **0.003129 m**;这些是当前安装的实际结果,不是通用连接距离 |
101 | 本次复测损伤 | 2 号、7 号和母舰在全部 539 个快照中,方块数与完整度均未下降,无损伤或变形记录 |
102
103 原始证据为 `verify-capture-fix-connectors.jsonl` 与 `verify-capture-fix-two-flight.jsonl`。全部 64 个 `DockApproach` PB 样本的实际速度最小为 **0.505106 m/s**,末段正常持续靠近。紧接锁定前的另一个约束点区间平均闭合速度约 **0.494740 m/s**,跨越锁定的区间约 **0.009169 m/s**,其中可能包含制动、吸附和速度归零;不能据此把指令值当成任意时刻实际速度的硬下限,也不能省略这些较低的区间值。物理帧速度按每秒 60 帧换算,与墙钟采样间隔计算的速度分开。
104
105 这一复测验证了旧终点停滞问题的修复及 2 号实际完成捕获。它不意味着所有安装误差、捕获轮询相位和移动母舰条件都已穷尽验证。
106
107 ## 调试工具修正与自动检查
108
109 本次工具调试同时修正了实时仿真速度读取(使用 `MyPhysics.SimulationRatio`)、MemorySafe 集合检查、库存 kg/m³ 单位和货物库存分类,并增加实际连接约束点、连接器状态及有上限的全船体完整度遥测。第一次 Windows 关闭窗口触发过游戏 IME 卸载异常,后续改为调用游戏自身的 `world.exit`,正常保存并退出已实测。
110
111 现有自动验证记录:完整 AgentBridge 解决方案 Release 构建零警告、零错误;**46 项 .NET 检查**通过,覆盖真实 Windows 管道、权限、队列、取消、响应大小、CLI 进程与记录;**9 项 Python 检查**通过,使用临时用户目录验证存档复制与原始文件保护。这些检查不替代实际飞行验收。
112
113 AMS 最终完整构建中英文各 **856/856 项测试**通过,八份导出逐一通过编译、角色、字符限制及摘要核验。中文矿机 **97002 字符**,摘要 `9553e0ec92de8fc93c814852f37ff088f579c038ca8bdcf6c06b57e0f44d28ab`;中文主控 **97973 字符**,摘要 `8a42840b6e3d73f578814d27e3fc3ccb8bfabc59231bc126b9008781f1122030`。英文矿机、主控分别 99403、99131 字符。完整记录为 `ams-build-9553e0ec-8a42840b.json`。
114
115 本报告尚未证明整套舰队长时间采矿、发现矿产后的钻探分配、多矿小行星显示及所有方向相机布局组合全部通过。27 个 `SurveyEmpty` 证明本轮真实扫描与续派,不代表已经找到矿产或完成采矿。
Modified tools/trace_ams.py +38 -15
@@ -7,15 +7,31 @@ import subprocess
7 7 import sys
8 8 import time
9 9
10 # Both exports have been checked against the minifier output: the fields below
11 # are identical. Do not accept an unreviewed hash after rebuilding AMS.
12 EXPECTED = {
13 "2cc105a720ecd1552791816a0edf106cfab91b501a1e8048421b7f23382d333a",
14 "b191430cf9ab7fe2b21569344ebcdc927bfa52847b84632440bdc68f3e5abc73",
10 # Each mapping is checked against that exact minifier output. Never accept a
11 # new hash merely because a previous build happened to use the same names.
12 BASE = dict(state="Ԙ", flight="أ", job="ا", entry="ŏ", report="ب", progress="ؾ",
13 command="ψ", attitude="χ", clearance="φ", scanIndex="Ͼ", blocked="ϭ",
14 problem="ſ", camera="Ѕ", cameraDetail="І", obstacle="Ї")
15 MAPPINGS = {
16 "2cc105a720ecd1552791816a0edf106cfab91b501a1e8048421b7f23382d333a": BASE,
17 "b191430cf9ab7fe2b21569344ebcdc927bfa52847b84632440bdc68f3e5abc73": BASE,
18 "2aed54ad323c588852f626455df0bb61c0e6565970c173dd5ed7007d832d259f":
19 dict(state="Ԛ", flight="إ", job="ة", entry="Ő", report="ت", progress="ـ",
20 command="ω", attitude="ψ", clearance="χ", scanIndex="Ͽ", blocked="Ϯ",
21 problem="ƀ", camera="І", cameraDetail="Ї", obstacle="Ј"),
22 "1146850d83e9d165d436828c2f526c212aa9e2928abe6eb447102cc4d3e7f2e3":
23 dict(state="Ԝ", flight="ا", job="ث", entry="Ő", report="ج", progress="ق",
24 command="ύ", attitude="ό", clearance="ϋ", scanIndex="Ѓ", blocked="ϲ",
25 problem="ƅ", camera="Њ", cameraDetail="Ћ", obstacle="Ќ"),
15 26 }
16 STATES = {"ï": "Docked", "ð": "Servicing", "ò": "Departing", "ó": "Transit",
17 "ô": "Survey", "ù": "Returning", "ú": "Holding", "û": "DockAlign",
18 "ü": "DockApproach"}
27 # Capture extension changes no inspected declarations; checked against the new export.
28 MAPPINGS["9553e0ec92de8fc93c814852f37ff088f579c038ca8bdcf6c06b57e0f44d28ab"] = MAPPINGS[
29 "1146850d83e9d165d436828c2f526c212aa9e2928abe6eb447102cc4d3e7f2e3"]
30 STATES = {"î": "Boot", "ï": "Docked", "ð": "Servicing", "ñ": "Ready",
31 "ò": "Departing", "ó": "Transit", "ô": "Survey", "õ": "Align",
32 "ö": "Drilling", "ø": "Retreat", "ù": "Returning", "ú": "Holding",
33 "û": "DockAlign", "ü": "DockApproach", "ý": "DockRetreat",
34 "þ": "Paused", "ÿ": "Manual", "u": "Fault"}
19 35
20 36
21 37 def main():
@@ -42,8 +58,9 @@ def main():
42 58 return response["result"]
43 59
44 60 program = call("pb.read", {"entityId": args.block})
45 if program["sha256"] not in EXPECTED:
61 if program["sha256"] not in MAPPINGS:
46 62 raise RuntimeError("Unrecognized AMS export " + program["sha256"] + "; derive a new field mapping for this source before tracing.")
63 mapping = MAPPINGS[program["sha256"]]
47 64 args.out.parent.mkdir(parents=True, exist_ok=True)
48 65 started = time.monotonic()
49 66 samples, previous = 0, None
@@ -52,14 +69,20 @@ def main():
52 69 fields = call("pb.inspect", {"entityId": args.block, "fields": ["E", "H"], "depth": 3})["fields"]
53 70 grid = call("grids.get", {"entityId": args.grid})
54 71 role = fields["H"]
55 flight = role["أ"]
72 flight = role[mapping["flight"]]
73 job = role[mapping["job"]]
74 state = role[mapping["state"]]
56 75 sample = {"utc": dt.datetime.now(dt.timezone.utc).isoformat(), "time": fields["E"],
57 "state": role["Ԙ"], "stateName": STATES.get(role["Ԙ"], role["Ԙ"]),
76 "state": state, "stateName": STATES.get(state, state),
58 77 "sourceSha256": program["sha256"], "reason": role["l"], "position": grid["pose"]["position"],
59 "actualSpeed": grid["speed"], "commandSpeed": flight["ψ"], "clearance": flight["φ"],
60 "attitudeError": flight["χ"], "scanIndex": flight["Ͼ"], "scanBlocked": flight["ϭ"],
61 "problem": flight["ſ"], "camera": flight["Ѕ"], "cameraDetail": flight["І"],
62 "obstacle": flight["Ї"], "fields": fields}
78 "actualSpeed": grid["speed"], "commandSpeed": flight[mapping["command"]],
79 "clearance": flight[mapping["clearance"]], "attitudeError": flight[mapping["attitude"]],
80 "scanIndex": flight[mapping["scanIndex"]], "scanBlocked": flight[mapping["blocked"]],
81 "problem": flight[mapping["problem"]], "camera": flight[mapping["camera"]],
82 "cameraDetail": flight[mapping["cameraDetail"]], "obstacle": flight[mapping["obstacle"]],
83 "jobId": job.get("g") if job else None, "jobEntry": job.get(mapping["entry"]) if job else None,
84 "progressAge": fields["E"] - role[mapping["progress"]],
85 "lastReport": role[mapping["report"]], "integrity": grid.get("integrity"), "fields": fields}
63 86 output.write(json.dumps(sample, ensure_ascii=False, separators=(",", ":")) + "\n")
64 87 output.flush()
65 88 state = (sample["state"], sample["reason"])