# SkyStreak **Repository Path**: manam83/sky-streak ## Basic Information - **Project Name**: SkyStreak - **Description**: 卫星追踪器的逆运算。它不问*这颗卫星在哪里*,而是问**我的视场里是谁**——这样照片上一条来历不明的轨迹就能与星表目录进行匹配。给它一个观测站、一个历元与时间跨度、一个指向(J2000 赤经/赤纬、方位/高度,或从轨道上观察的 LVLH 角)和一个视场。它会找出穿越该视场的每一个已编目对象,并把每条轨迹绘制在真实恒星背景的日晷投影(gnomonic)星图上,可直接与你的照片对比。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 4 - **Created**: 2026-08-24 - **Last Updated**: 2026-08-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SkyStreak 卫星追踪器的逆运算。它不问*这颗卫星在哪里*,而是问**我的视场里是谁**——这样照片上一条来历不明的轨迹就能与星表目录进行匹配。 给它一个观测站、一个历元与时间跨度、一个指向(J2000 赤经/赤纬、方位/高度,或从轨道上观察的 LVLH 角)和一个视场。它会找出穿越该视场的每一个已编目对象,并把每条轨迹绘制在真实恒星背景的日晷投影(gnomonic)星图上,可直接与你的照片对比。 观测站本身也可以是一颗**卫星**(天基空间态势感知):按 NORAD 编号在已加载目录中选择任意对象,扫描就从*它的*传感器出发——从轨道上看,谁穿过了我的视场。 SkyStreak 由 SatIdentifier 升级而来:在“识别视场中的卫星”这一核心之上,新增**条纹匹配、图像叠加配准、多站点并行扫描、观测计划、3D 轨道可视化、众包报告、CLI/API 服务**等一整层能力。 ![SkyStreak — 带预测轨迹的星图、全天背景视图、过境列表与卫星信息](docs/screenshot.png) 本地 Python 后端(星表获取、缓存、持久化——仅标准库)+ 浏览器前端(Web Worker 中的 SGP4、canvas 星图)。[SatObserver-MX](../satobserver) 的姊妹项目,共享其架构与代码风格。 模块 API 见 [CONTRACT.md](CONTRACT.md);构建过程与测量数据见 [DEVLOG.md](DEVLOG.md)。 ## 核心能力 - **逆向轨迹识别**(基础)——扫描视场内的每一次穿越,逐条绘制轨迹,按来源显示 TLE 时效与星等估算方法。 - **条纹匹配(Track Match)**——照片上一条来历不明的条纹,与候选穿越按位置角、角速率、长度、时间重叠四个分量打分匹配,输出 Top-N 候选并标注 TLE 年龄与测光可信度。条纹可手动录入(RA/Dec 或方向角+长度)、在星图上直接绘制,或从图像叠加的端点拾取。 - **图像叠加(Image Overlay)**——把实拍照片(JPG/PNG 拖放,或 FITS 上传由后端纯标准库转 PNG)叠加到星图上,手动(≥2 点仿射)或自动(亮星提取 + 最小二乘)配准,透明度可调;配准状态随设置持久化。 - **多站点并行扫描**——一个观测计划同时覆盖多个地面/轨道站点,Worker 按站点独立跑完整三阶段,结果按站点分组统计。 - **观测计划与提醒(Plan)**——未来 24h/7d 的过境计划表(最大高度、方位、亮度),一键导出 ICS 日历,过境前系统通知提醒。 - **深空星表应用内构建**——Catalogue 窗口一键后台构建 V≤13 深空瓦片(`--vmax` 参数化、可续跑、进度轮询),完成后星图自动重探。 - **3D 轨道可视化**——Three.js 场景:地球、站点、轨道线、视场锥;与星图选择联动,双击轨道线反选对象;未安装时优雅降级。 - **众包报告(Community Reports)**——提交未知目标的观测快照(含图像),用匹配引擎回填候选识别,报告存 `data/reports.json` 本地共享。 - **CLI 批量扫描与 API 服务**——`python3 server.py --scan config.json -o out.csv` 无头批量扫描;`POST /api/scan` 异步作业(并发上限、取消、CORS 可选),可被任意脚本驱动。 - **引擎深度**——增量扫描(参数哈希差分复用阶段缓存,结果与全量一致)、WebGPU 粗扫(WGSL 移植 SGP4,失败自动回退 CPU)、实验性大气阻力修正(F10.7 指数 + BSTAR 一阶外推,默认关闭)。 - **体验层**——中/英双语 i18n、明暗主题、键盘快捷键、TLE 拖放导入、PWA(离线静态壳 + 移动端触控适配)。 ## 环境要求 **打包应用**(位于 `release/`)——无运行时依赖;Python 与恒星目录已内置。获取星表需要联网(缓存数据可离线使用)。完整星表可从 CelesTrak 免账号加载,或——更完整,包含分析对象与新编目对象——从免费的 [space-track.org](https://www.space-track.org) 账号获取(首次使用时保存在本地)。 - **macOS**(`SkyStreak-macOS-arm64.zip`):Apple Silicon。未签名——在其他机器上首次启动需右键 → 打开一次。用户数据位于 `~/Library/Application Support/SatIdentifier/`(数据目录沿用旧名,升级不迁移数据)。 - **Windows**(`SkyStreak-windows-x64.zip`,如有):由 CI 在 Windows runner 上构建,**未在真实硬件上测试**——与 SatObserver-MX 的 Windows 构建存在同样的注意事项。 **从源码运行**(浏览器模式): - Python ≥ 3.10 —— **仅标准库**,无需任何包 - 任意现代浏览器(针对 Chrome 开发;打包应用使用 WKWebView) **重建 .app**: `python3 -m venv .venv-build && .venv-build/bin/pip install pywebview pyinstaller` (重新生成图标额外需要 `pillow`),然后: ```sh .venv-build/bin/pyinstaller --noconfirm --clean --windowed \ --name "SkyStreak" --icon build_icon/SkyStreak.icns \ --add-data "app:app" --osx-bundle-identifier "local.skystreak" desktop.py ``` ## 运行 **macOS 应用**:解压 `release/SkyStreak-macOS-arm64.zip`,双击 `SkyStreak.app`。原生窗口;关闭即退出。 **开发 / 浏览器模式**: ```sh python3 server.py ``` 在 http://127.0.0.1:8476 启动本地服务器并打开浏览器。选项:`--port N`、`--no-browser`、`--scan `(无头批量扫描)、`--max-jobs N`(并发 API 作业上限)、`--api-cors`(跨源 API)。或双击 `SkyStreak.command`。开发模式下数据位于 `./data/`。 **CLI 批量扫描示例**: ```sh python3 server.py --scan scan-config.json -o out.csv ``` ## 工作流程 1. **目录**——从任一来源加载完整星表:*CelesTrak*(批量星表文件,无需账号;旧版 TLE 文件省略 2026-07 之后编目的对象)或 *Space-Track*(完整 GP;需免费账号,保存在本地;完整集合——含分析对象与 6 位编号对象)。可添加 CelesTrak 单对象查询(NORAD / COSPAR / 名称包含,无需账号——同一标签页的 *Fetch SATCAT metadata* 按钮下载的是驱动测光、而非轨道根数的 SATCAT 表)、McCants 保密轨道根数,或粘贴/拖放 TLE 文件——所有数据合并为一个目录,按 NORAD 去重、以最新轨道根数优先,并且**按来源显示根数时效统计**,因为陈旧根数是识别失败的主要原因。 2. **站点**——添加观测站并标记为活动。两种类型:**地面**(经度 / 纬度 / 海拔)或**轨道**(观测卫星,从已加载目录中按 NORAD 编号或名称选取——TLE 实时从目录解析,因此观测者永远不会相对于目标变陈旧)。勾选多个站点即可并行扫描。 3. **指向**——开始时间、时间跨度、指向、视场。 4. **过境列表**——按下 *Scan*(扫描),等待三阶段引擎的结果;进度条按站点并行推进。 5. **星图**——将轨迹与你的照片对比。 6. **条纹匹配**——*Track Match* 窗口录入或绘制照片上的条纹,得到带分数分解的候选列表,点击即定位到对应穿越。 7. **图像叠加**——*Image Overlay* 窗口把照片直接叠到星图上,自动或手动配准后肉眼比对。 8. **计划与分享**——*Plan* 窗口生成观测计划并导出 ICS;导出菜单支持 KML(Google Earth 轨道轨迹)、FITS 头(Astropy 可读)、PDF 报告;*Community Reports* 提交未知目标供本地社区匹配。 ## 从轨道观测(天基空间态势感知) 激活 Orbit 站点后,同一管线为星载仪器回答"谁穿过了我的传感器视场": - **方位/高度变为 LVLH 角**(标记为 AzL/ElL):Az 从沿轨(速度)方向指向轨道法线,El 从当地水平面指向天顶(径向向外;−90° = 天底)。*Mount* 跟踪模式变为 **LVLH**——一台固定在星体上的凝视传感器,以轨道速率漂过星空,正如静止的地面支架以恒星速率漂移。 - **地球临边遮挡取代地平线**:仅当视线穿过地球本身时目标才被剔除,进出场时间以解析视场边缘的同样方式解析目标*从临边后方升起*。在轨道上永远不做折射修正。 - 观测者**永远不会识别出自己**,其自身的 TLE 误差会加入匹配容差——在传感器处它与目标的误差无法区分。 - All-Sky 是地面地平线投影,在 Orbit 站点上会明确说明;星图对两种站点都适用。 健全性证明同样覆盖轨道几何:关闭几何剔除后返回的穿越集合与开启时完全一致,且每个报告位置与独立的二体重算在 ~0.01″ 内吻合(见 `tools/test_scan.js` 第 [o] 节)。 ## 它计算什么 - **穿越**:进入 / 最近接近 / 离开时间、角距、赤经/赤纬(J2000)、方位/高度、距离、距离变化率、角速度与位置角、估计星等、光照/半影/本影、轨道类别、TLE 年龄、所属站点(多站点扫描)。 - **两种角速度**,因为哪一种会让你的照片产生条纹取决于你当时的跟踪方式。相对**恒星**(`d(RA,Dec)/dt`)是恒星跟踪照片上的条纹——注意对地静止对象在这里*并非*静止,它以 ~15″/s 漂移,这正是 GEO 在跟踪图像中呈短划的原因。相对**地平线**(`d(alt,az)/dt`)是静止支架所见的景象,此时 GEO 是固定点而恒星在拖尾——在 Orbit 站点上这第二种速率相对 LVLH 坐标系测量,即星体固定凝视传感器记录到的内容。星图绘制与你的跟踪模式相匹配的轨迹,包括静止支架所见到的视场旋转;跨越视场从进入到离开绘制的轨迹,正是应当拿去与照片比对的东西。 - **条纹匹配分数**:位置角、角速率、长度、时间重叠四个分量各自归一化打分,加权求和并逐项分解显示,附 TLE 年龄与测光方法标注。 - **恒星背景**(Gaia DR3):深度随视场自适应——本地分块数据库达到 **V = 13**,服务于小于 3° 的视野(可在应用内一键构建,或 `python3 tools/make_starcat.py --deep-tiles`;运行时绝不联网);更宽的视野使用内置星表(V ≤ 10.5,549 037 颗恒星),视场越大深度越浅。深度构建是**可选的**:开箱即用、不做深度构建时,每个视场都从内置星表绘制,上限为 **V = 10.5**。星点遵循 Stellarium 的渲染法则,在极限星等处平滑淡出至不可见。太阳/月亮(含月相)、星座叠层、卫星标签与卫星轨迹各有工具栏开关;All-Sky 面板使用亮星集合(V ≤ 4.6)并带有银河辉光。两种视图都没有暮光或日光着色。 **深度是磁盘容量的权衡,而非代码变更。** 分块构建器是星等参数化的——同一个 `--deep-tiles` 构建会写入你要求的任意 `--vmax`,前端从文件头读取星等上限并自动适配。更深的代价是磁盘与构建时间: | 深度 | 文件大小(约) | 恒星数(约) | 适用场景 | | ------- | -------------- | ------------ | ------------------------------- | | V ≤ 11 | ~10 MB | ~1 M | 广域寻星;手机存储 | | V ≤ 13 | ~60 MB | ~6 M | 默认;1° 视场约显示 200 颗恒星 | | V ≤ 15 | ~320 MB | ~30 M | 窄视场成像(≤ 20′ 视场) | | V ≤ 17 | ~1.4 GB | ~150 M | 天体测量级底片;仅限 SSD | 内置 `starcat.js`(V ≤ 10.5)始终加载并填充宽视野,因此深度分块只在大约 3° 以下才开始起作用——如果你从不拍摄比这更窄的视场,V ≤ 13 就是收益递减点。更深的构建耗时也按比例更长(V ≤ 15 大约需要一天左右的 VizieR TAP 拉取;V ≤ 17 需要数天),且可续跑——重跑即继续。请将分块目录排除在版本控制之外(`data/deepstars/` 已在 gitignore 中);`make_starcat.py --deep-tiles --vmax 15 --json-status build.json` 为长时间会话报告进度。 - **时间基准**:UT1−UTC 差(DUT1)可自动从网络获取(软失败回退 0),F10.7 太阳通量指数缓存 6 小时供阻力修正使用。 ## 精度 — 在信任一次识别之前请先阅读 坐标框架处理刻意严谨,因为本工具要把卫星位置与恒星场对比: - 坐标为 **J2000 平春分点**。SGP4 返回 TEME,而 TEME *不是* J2000——自 J2000 以来的岁差在 **2026 年已达 0.36°**,是典型望远镜视场的二十倍。完整的 TEME → J2000 旋转(IAU-1976 岁差、IAU-1980 章动、二分点方程)均已应用。已对照 satellite.js 自身的方位/高度路径,在覆盖 LEO/HEO/GEO 与四个站点的 1102 个样本上验证:符合度 **1.4e-5 角秒**。 - 折射始终施加于方位/高度(El 30° 处 1.7′,El 10° 处 5.4′),且逆运算通过迭代求解,使模式切换完全可逆。 **但坐标框架并非限制性误差——轨道根数才是:** | 项 | 量级 | 是否施加? | | --------------------------------- | ----------------------------------------- | ----------------------------- | | TLE 位置误差(新鲜 → 一周) | ~1–20 km ⇒ 在 500 km 距离上**7′–2°** | 不可消除 | | 默认忽略 UT1−UTC | ≤ 0.9 s ⇒**≤ 2.9′** | 可选`DUT1` 设置(可自动) | | 折射 | El 30° 处 1.7′,El 10° 处 5.4′ | 始终施加 | | 周年光行差 | ≤ 20.5″ | 否——见下文 | | 光行时 + 轨道光行差(Orbit 站点) | 各 ≤ ~5″ | 否——比 TLE 误差低两个数量级 | | 岁差 + 章动 | < 1″ | **是** | 光行差对卫星和恒星都不施加,因此星图与对象保持相互一致;只修正一侧反而会更糟。TLE 年龄逐行显示,也在卫星信息中显示,因为它才是决定一次识别是否可信的数字。 **星等是估算值,且大多为先验。** 方法逐行显示: | 方法 | 含义 | | --------- | ----------------------------------------------------- | | `qsmag` | McCants 标准星等——真实观测值 | | `rcs` | 由 SATCAT 雷达散射截面假定的漫射球体 | | `model` | 有文献记载的星座亮度(Starlink、OneWeb) | | `type` | 由 SATCAT 对象类型得出的尺寸等级(R/B ≫ PAY ≫ DEB) | | `default` | 1 m 球体。属于猜测,并如此标注 | 两个数据事实使低层级成为必需而非可选:**CelesTrak 不发布 NORAD 50000 以上的 RCS**(实测:40000 以下覆盖率 41–97%,40000–49999 为 25.6%,50000 以上为 0.0%),且 **mmccants.org/programs/qsmag.zip 目前返回 HTTP 404**。在现代星表上,大多数对象因此落在一个先验值上,真实离散度有一个星等或更多。请勿把星等列当作测光结果。 ## 仓库结构 ``` server.py Python 3 仅标准库后端:静态文件 + JSON API desktop.py pywebview 原生窗口外壳 SkyStreak.command 双击启动器(开发模式) app/ index.html 按固定顺序加载 CSS 与脚本;PWA 注册 css/app.css 设计系统,暗/亮主题(CSS 变量) manifest.webmanifest PWA 清单;sw.js 网络优先离线静态壳 assets/stars_deep.bin Gaia DR3 至 V=10.5,549 037 颗恒星,5.5 MB(首选) assets/stars_m9.bin Tycho-2 至 V=9.0,130 183 颗恒星,1.3 MB(回退) js/frames.js 坐标框架、岁差/章动、折射、TAN js/propagate.js SGP4 封装与地心视差解 js/scan.js worker 池、合并、预算、增量扫描调度 js/worker/scan-worker.js 三阶段扫描引擎(stage1 筛选/stage2 窗口/stage3 细化) js/worker/gpu.js WebGPU 粗扫(WGSL 移植 SGP4,自动回退 CPU) js/matching.js 条纹匹配评分引擎(PA/速率/长度/时间) js/stars.js 深空恒星目录、锥形查询 js/photometry.js 五层星等模型、地球阴影 js/chart.js 日晷投影星图(主视图),图像叠加层 js/crossings.js 过境列表(主列表),KML/FITS 头/PDF 导出 js/pointing.js 输入窗口 js/allsky.js 带视场足迹的全天背景视图 js/trackmatch.js Track Match 窗口(条纹录入/绘制/匹配) js/imgoverlay.js Image Overlay 窗口(配准/叠加) js/planner.js Plan 窗口(过境计划、ICS、提醒) js/orbit3d.js 3D Orbits 窗口(Three.js) js/reports.js Community Reports 窗口 js/i18n.js 中/英双语字典与 t() 模板 js/state.js util.js clock.js windows.js sources.js locations.js satinfo.js js/vendor/ satellite.js、starcat.js、mwdata.js、three.min.js tools/ make_starcat.py 构建恒星目录资源;--deep-tiles 将本地 V=13 分块集 构建到 data/deepstars/(已 gitignore),--vmax 参数化 scan_cli.js 无头批量扫描(复用 scan-worker 引擎) test_*.js 验证工具——见 DEVLOG test_server.py 后端 API 测试 docs/ 截图 data/ 状态、缓存、凭据、深空恒星分块(已 gitignore) ``` ## 致谢 SkyStreak 的前身 **SatIdentifier**——本文档描述的全部基础能力(逆问题框架、坐标框架、三阶段扫描、星等模型)均由其奠基,构建过程与测量数据见 [DEVLOG.md](DEVLOG.md)。 传播: [satellite.js](https://github.com/shashwatak/satellite-js)(SGP4/SDP4)。恒星:经 VizieR 获取的 Gaia DR3(Gaia Collaboration 2022)与 Tycho-2(Hog+ 2000),以及经由 [d3-celestial](https://github.com/ofrohn/d3-celestial) 的 BSC5/HYG 亮星测光。星表数据:CelesTrak、Space-Track、Mike McCants。扫描的结构——将 SGP4 初始化移出时间循环、旋转指向而非旋转星表、用廉价标量测试为昂贵计算把关——取自 Bill Gray 的 [sat_code](https://github.com/Bill-Gray/sat_code);岁差处理遵循其 `lunar/precess.cpp` 中的思路。问题框架受惠于 [SatSkyMap](https://github.com/lnicastro/SatSkyMap)。