256 lines
6.7 KiB
Markdown
256 lines
6.7 KiB
Markdown
# Tianwen-1-frame-analysis-v2.py 新手说明
|
||
|
||
这个文件是一个“天问一号遥测帧分析脚本”。如果用新手的话说,它做的事情就是:
|
||
|
||
> 读取一大包二进制遥测数据,把它拆成一帧一帧,再按航天器 ID、虚拟信道和 APID 分类,最后把不同数据字段画成图片保存下来,方便人工观察这些遥测字段怎么变化。
|
||
|
||
## 输入数据
|
||
|
||
脚本读取的数据文件是:
|
||
|
||
```text
|
||
/home/zjz/CCSDS_study/Tianwen/tianwen1_frames_20200730.u8
|
||
```
|
||
|
||
这个文件是一串连续的原始字节。脚本认为每 220 个字节是一帧 AOS frame,所以会把它整理成:
|
||
|
||
```text
|
||
帧数 x 220字节
|
||
```
|
||
|
||
也就是一个二维数组,每一行代表一帧。
|
||
|
||
## 依赖的本地模块
|
||
|
||
脚本主要依赖两个本地文件:
|
||
|
||
```text
|
||
Tianwen/ccsds.py
|
||
Tianwen/tianwen1_tm.py
|
||
```
|
||
|
||
`ccsds.py` 负责解析 CCSDS AOS 帧和 Space Packet。
|
||
|
||
`tianwen1_tm.py` 负责把天问一号的原始时间戳转换成 `numpy.datetime64`,这样 matplotlib 才能按时间画图。
|
||
|
||
## 为什么要设置 matplotlib 的 Agg 后端
|
||
|
||
WSL 下直接调用 `plt.show()` 经常会因为没有图形界面而报错。
|
||
|
||
所以脚本使用:
|
||
|
||
```python
|
||
matplotlib.use("Agg")
|
||
```
|
||
|
||
意思是:不要弹出图形窗口,只把图保存成 PNG 文件。
|
||
|
||
所有图片最后会保存到:
|
||
|
||
```text
|
||
/home/zjz/CCSDS_study/Tianwen/frame_analysis_figures
|
||
```
|
||
|
||
## 脚本整体流程
|
||
|
||
脚本主要分成以下几步:
|
||
|
||
1. 设置路径和 matplotlib 环境。
|
||
2. 读取 `tianwen1_frames_20200730.u8`。
|
||
3. 把原始字节按 220 字节切成 AOS 帧。
|
||
4. 用 `ccsds.AOSFrame.parse(...)` 解析每一帧。
|
||
5. 统计 AOS 主头中的版本号、航天器 ID、虚拟信道 ID。
|
||
6. 分别分析 `Spacecraft 82 / VC 1`、`Spacecraft 245 / VC 3`、`Spacecraft 245 / VC 1`。
|
||
7. 从 AOS 帧中重组 Space Packet。
|
||
8. 按 APID 把 Space Packet 分类。
|
||
9. 对多个 APID 的载荷字段按 `uint8`、`int16` 或 `float64` 解释。
|
||
10. 绘制时间序列图、帧丢失图、APID 热力图。
|
||
11. 用 `savefig(...)` 保存所有图片。
|
||
|
||
## 关键概念解释
|
||
|
||
### AOS Frame
|
||
|
||
AOS Frame 可以理解为“航天器遥测传输的一帧”。每一帧里有头部字段,也有承载的数据。
|
||
|
||
本脚本中每帧固定 220 字节。
|
||
|
||
### Spacecraft ID
|
||
|
||
`spacecraft_id` 用来区分数据属于哪个航天器或数据源。
|
||
|
||
脚本主要关注:
|
||
|
||
```text
|
||
82
|
||
245
|
||
```
|
||
|
||
### Virtual Channel
|
||
|
||
`virtual_channel_id` 是虚拟信道编号。同一个航天器 ID 下可以有多个虚拟信道。
|
||
|
||
脚本重点分析:
|
||
|
||
```text
|
||
Spacecraft 82, Virtual channel 1
|
||
Spacecraft 245, Virtual channel 3
|
||
Spacecraft 245, Virtual channel 1
|
||
```
|
||
|
||
其中 `Spacecraft 245 / VC 1` 是后面 APID 分析的主要数据来源。
|
||
|
||
### Space Packet
|
||
|
||
AOS 帧中承载的是 Space Packet 数据流。一个 Space Packet 可能跨越多个 AOS 帧,所以脚本调用:
|
||
|
||
```python
|
||
ccsds.extract_space_packets(...)
|
||
```
|
||
|
||
把它们重新拼接出来。
|
||
|
||
### APID
|
||
|
||
APID 是 Space Packet 里的应用标识。新手可以先把它理解成“数据类型编号”。
|
||
|
||
不同 APID 里的载荷含义可能不同,所以脚本会按 APID 分组分析。
|
||
|
||
## 图片保存逻辑
|
||
|
||
脚本新增了 `save_all_figures(output_dir)` 函数。
|
||
|
||
它会做这些事:
|
||
|
||
1. 找出当前 matplotlib 里所有还打开的 figure。
|
||
2. 从每张图的标题中生成文件名。
|
||
3. 调用:
|
||
|
||
```python
|
||
fig.savefig(path, dpi=150, bbox_inches="tight")
|
||
```
|
||
|
||
4. 保存成 PNG。
|
||
5. 保存后关闭 figure,释放内存。
|
||
|
||
文件名类似:
|
||
|
||
```text
|
||
figure_001_spacecraft_82_virtual_channel_1_frame_loss.png
|
||
figure_002_apid_1_spacecraft_82_virtual_channel_1.png
|
||
```
|
||
|
||
## 各分析段落在做什么
|
||
|
||
### Spacecraft 82 Virtual channel 1
|
||
|
||
这一段会:
|
||
|
||
- 筛选出 SC 82 / VC 1 的 AOS 帧。
|
||
- 检查帧计数是否连续。
|
||
- 打印插入区时间戳。
|
||
- 重组 Space Packet。
|
||
- 按 APID 分类。
|
||
- 为每个 APID 画载荷热力图。
|
||
|
||
### Spacecraft 245 Virtual channel 3
|
||
|
||
这一段主要检查 VC 3 是否像固定填充数据。
|
||
|
||
它会查看某些字节区间的唯一值,比如是否一直是 `0xaa`。
|
||
|
||
### Spacecraft 245 Virtual channel 1
|
||
|
||
这是主要遥测数据通道。
|
||
|
||
这一段会:
|
||
|
||
- 检查帧计数。
|
||
- 提取时间戳。
|
||
- 重组 Space Packet。
|
||
- 统计所有 APID。
|
||
- 按 APID 分组并画热力图。
|
||
|
||
### APID 1280 / 1281
|
||
|
||
这些 APID 的载荷被按大端 `int16` 解释。
|
||
|
||
也就是说,每两个字节被看成一个 16 位整数,然后画出这些整数随时间的变化。
|
||
|
||
### APID 1288 / 1287
|
||
|
||
这些 APID 的部分载荷被按大端 `float64` 解释。
|
||
|
||
脚本还对这些浮点序列做了 1 阶和 2 阶多项式拟合,并画出“原始值减拟合值”的残差。
|
||
|
||
新手可以理解为:
|
||
|
||
> 先把整体趋势去掉,再看剩下的小变化。
|
||
|
||
### APID 2 / 3
|
||
|
||
原 notebook 这里变量名写了 APID 2 和 APID 3,但代码实际两边都取了 APID 2。
|
||
|
||
脚本保留了原逻辑,并在代码注释里特别说明了这一点。
|
||
|
||
### APID 454 / 462 / 1536
|
||
|
||
这些段落分别按 `uint8` 或 `int16` 查看指定字节位置的变化。
|
||
|
||
目的不是完全解码每个遥测字段,而是先通过画图观察哪些字节像计数器、哪些字节像连续变化的遥测量。
|
||
|
||
## 运行方式
|
||
|
||
在项目根目录下可以运行:
|
||
|
||
```bash
|
||
/home/zjz/CCSDS_study/ccsds/bin/python /home/zjz/CCSDS_study/test/Tianwen-1-frame-analysis-v2.py
|
||
```
|
||
|
||
运行结束后,查看图片目录:
|
||
|
||
```text
|
||
/home/zjz/CCSDS_study/Tianwen/frame_analysis_figures
|
||
```
|
||
|
||
## 常见提示
|
||
|
||
运行时可能看到类似:
|
||
|
||
```text
|
||
Broken stream. Last frame count ..., current frame count ...
|
||
```
|
||
|
||
这是 `ccsds.py` 发出的 warning,意思是帧计数中间不连续,可能有丢帧或数据中断。
|
||
|
||
这不是 Python 程序崩溃,也不影响脚本继续保存图片。
|
||
|
||
## 新手视角总结
|
||
|
||
这个脚本不是一个“完整解码所有遥测含义”的程序,而是一个“探索和观察遥测数据结构”的分析脚本。
|
||
|
||
它先把原始二进制文件拆成 AOS 帧,再把 AOS 帧里的 Space Packet 拼出来,然后按照 APID 分组。分组之后,它把某些字节当成整数或浮点数画出来,让我们通过图片观察这些字段是否有规律。
|
||
|
||
简单说:
|
||
|
||
```text
|
||
原始二进制数据
|
||
-> AOS 帧
|
||
-> Space Packet
|
||
-> APID 分组
|
||
-> 字节/整数/浮点数曲线
|
||
-> PNG 图片
|
||
```
|
||
|
||
如果你是新手,建议先从这几个变量看起:
|
||
|
||
- `frames`:原始帧字节数组。
|
||
- `aos`:解析后的 AOS 帧对象。
|
||
- `sc245_vc1`:筛选出的主要遥测虚拟信道。
|
||
- `sc245_vc1_packets`:从 AOS 帧中重组出来的 Space Packet。
|
||
- `sc245_vc1_by_apid`:按 APID 分类后的 packet 字典。
|
||
- `channels`:某个 APID 的载荷被解释成数值后的矩阵。
|
||
- `timestamps`:每个 packet 对应的时间戳。
|
||
|
||
理解这些变量后,整个脚本的结构就比较清楚了。
|