有趣的Hack-A-Sat黑掉衛星挑戰賽——跟蹤衛星
國家太空安全是國家安全在空間領域的表現。隨著太空技術在政治、經濟、軍事、文化等各個領域的應用不斷增加,太空已經成為國家賴以生存與發展的命脈之一,凝聚著巨大的國家利益,太空安全的重要性日益凸顯[1]。而在信息化時代,太空安全與信息安全緊密地結合在一起。
2020年9月4日,美國白宮發布了首份針對太空網絡空間安全的指令——《航天政策第5號令》,其為美國首個關于衛星和相關系統網絡安全的綜合性政策,標志著美國對太空網絡安全的重視程度達到新的高度。在此背景下,美國自2020年起,連續兩年舉辦太空信息安全大賽“黑掉衛星(Hack-A-Sat)”,在《Hack-A-Sat太空信息安全挑戰賽深度解析》一書中有詳細介紹,本文介紹了Hack-A-Sat黑掉衛星挑戰賽的跟蹤衛星這道賽題的解題過程。
題目介紹
You're in charge of controlling our hobbyist antenna. The antenna is controlled by two servos, one for azimuth and the other for elevation. Included is an example file from a previous control pattern. Track the satellite requested so we can see what it is broadcasting.
主辦方假定參賽者已經獲得了地面站衛星天線的控制系統的權限。天線控制是通過兩個舵機控制的,分別控制方位角和仰角。題目要求參賽者通過控制天線的方位角和仰角跟蹤衛星。
給出的資料有examples.tar.gz,解壓后包含4個文件:
(1)README.txt:描述了題目更加詳細的信息。方位角舵機和仰角舵機由來自控制器的PWM信號控制(關于PWM的知識會在下文介紹)。已知舵機的占空比(Duty Circles)為2457~7372,對應天線的0°~180°。要求得出控制舵機信號在觀測的720s內每一秒的占空比來控制天線,從而成功跟蹤衛星。
(2)challenge[0-4].txt、solution[0-4].txt:這兩個文件告訴我們最終要輸入的格式。題目沒有給出關于解決方案格式的信息,但我們察看其中一個示例解決方案,以challenge[0].txt和 solution[0].txt為例,如下所示,challenge[0].txt給出地面站的位置、要跟蹤的衛星、開始跟蹤衛星的時刻、要跟蹤的時長。查看solution[0].txt得知我們最終要輸入的文件格式如下,要輸入720行,每一行對應1s:包括3個要素,分別為時間戳、控制地面站衛星天線方位、俯仰的舵機PWM值。
<timestamp>,<PWM0>,<PWM1>
challenge[0].txt內容:
Track-a-sat control system
Latitude: 52.5341
Longitude: 85.18
Satellite: PERUSAT 1
Start time GMT: 1586789933.820023
720 observations, one every 1 second
Waiting for your solution followed by a blank line...
solution[0].txt內容:
1586789933.820023, 6001, 2579
1586789934.820023, 5999, 2581
1586789935.820023, 5997, 2583
1586789936.820023, 5995, 2585
1586789937.820023, 5994, 2587
1586789938.820023, 5992, 2589
1586789939.820023, 5990, 2591
1586789940.820023, 5988, 2593
1586789941.820023, 5987, 2594
1586789942.820023, 5985, 2596
1586789943.820023, 5983, 2598
1586789944.820023, 5981, 2600
1586789945.820023, 5979, 2602
1586789946.820023, 5977, 2604
1586789947.820023, 5976, 2606
……
(3)active.txt:地面站使用的TLE。如下所示,該文件包含許多公共衛星,通過某顆衛星的TLE可以計算該衛星在后續某一時刻的位置。
CALSPHERE 1
1 00900U 64063C 20101.19586769 .00000241 00000-0 24890-3 0 9996
2 00900 90.1576 27.2823 0024882 263.3747 232.8474 13.73355076761081
CALSPHERE 2
1 00902U 64063E 20101.07898481 .00000023 00000-0 20957-4 0 9991
2 00902 90.1686 29.8886 0016745 309.6664 60.7009 13.52681717551296
LCS 1
1 01361U 65034C 20101.48494378 .00000021 00000-0 16643-2 0 9996
2 01361 32.1376 139.9201 0004925 231.9284 128.0769 9.89297118986548
TEMPSAT 1
1 01512U 65065E 20101.13158021 .00000007 00000-0 -51836-5 0 9992
2 01512 89.8739 226.9331 0071605 111.6801 301.3452 13.33427200658976
CALSPHERE 4A
1 01520U 65065H 20101.19568728 .00000042 00000-0 65250-4 0 9998
2 01520 90.0331 128.8999 0069815 356.3666 119.2980 13.35809885661087
OPS 5712 (P/L 160)
1 02826U 67053A 20101.49397074 .00000535 00000-0 15707-3 0 9992
2 02826 69.9298 358.0006 0004382 11.4117 348.7115 14.49027125737592
……
另外,主辦方給出了一個鏈接地址,使用netcat連接到題目給的鏈接后,會給出進一步提示,如圖4-1所示(其中的坐標、觀察時間和需要跟蹤的衛星都是隨機的)。

圖4-1 antenna題目的提示信息
連接后,會告訴參賽者需要跟蹤的衛星,以及地面站的位置、開始跟蹤衛星的時刻,要求參賽者輸入天線控制舵機在觀測的720s內每一秒的占空比來控制天線,從而成功跟蹤衛星,全部720s的占空比都正確后,會返回flag值。
題目編譯及測試
該挑戰題的代碼位于antenna目錄下,查看challenge、solver目錄下的Dockerfile,發現其中用到的是python:3.7-slim,為了加快題目的編譯進度,在antenna目錄下新建一個文件sources.list,內容如下:
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free
將sources.list復制到antenna、challenge、solver目錄下,修改challenge、solver目錄下的Dockerfile,在所有的FROM python:3.7-slim下方添加:
ADD sources.list /etc/apt/sources.list
打開終端,進入antenna所在目錄,執行命令:
sudo make build
使用make test命令進行測試,會順利通過,其輸出信息如圖4-2所示。

圖4-2 antenna挑戰題測試輸出
相關背景知識
1.衛星星歷TLE文件介紹
TLE是兩行軌道根數(TLE),覆蓋了氣象衛星、海洋衛星、地球資源衛星、教育衛星等應用衛星。以北斗的某顆衛星TLE數據為例,如下:
BEIDOU 2A
1 30323U 07003A 07067.68277059 .00069181 13771-5 44016-2 0 587
2 30323 025.0330 358.9828 7594216 197.8808 102.7839 01.92847527 650
第一行主要元素解析如下:
(1)30323U:30323是北美防空司令部給出的衛星編號,U代表不保密,我們看到的都是U,否則我們就不會看到這組TLE了。
(2)07003A:國際編號,07表示2007年,003表示這一年的第3次發射,A表示這次發射編號為A的物體,其他還有B、C、D等。國際編號就是2007-003A。
(3)07067.68277059:表示這組軌道數據的時間點,07表示2007年,067表示第67天,即3月8日。
(4)68277059:表示這一天里的時刻,大約是16時22分左右。
(5)58:表示關于這個空間物體的第58組TLE。
(6)7:最后一位是校驗位。
第二行主要元素解析如下:
(1)30323:北美防空司令部給出的衛星編號。
(2)025.0330:軌道傾角。
(3)358.9828:升交點赤經。
(4)7594216:軌道偏心率。
(5)197.8808:近地點幅角。
(6)102.7839:平近點角,表示在給出這組TLE時,衛星在軌道的什么位置。
(7)01.92847527:每天環繞地球的圈數。其倒數就是周期。可以看出,該北斗衛星目前的周期大約是12h。
(8)65:發射以來飛行的圈數。
(9)0:校驗位。
2.GMT、UTC和UNIX時間戳
GMT的全名是格林威治標準時間(Greenwich Mean Time)。十七世紀,格林威治皇家天文臺進行了天體觀測。1675年,舊皇家觀測所(Old Royal Observatory)正式成立,到了1884年決定以通過格林威治的子午線作為劃分地球東西兩半球的經度零度。觀測所門口墻上有一個標志24h的時鐘,顯示當下的時間,對全球而言,這里所設定的時間是世界時間參考點,全球都以格林威治的時間作為標準來設定時間。
UTC(Universal Time Coordinated,協調世界時),又稱世界標準時間、世界統一時間,是經過平均太陽時(以GMT為準)、地軸運動修正后的新時標,以及以秒為單位的國際原子時所綜合精算而成的時間,計算過程相當嚴謹精密,因此若以“世界標準時間”的角度來說,UTC比GMT更加精準,其誤差值必須保持在0.9s以內,若大于0.9s,則由位于巴黎的國際地球自轉事務中央局發布閏秒,使UTC與地球自轉周期一致。所以UTC的本質強調的是比GMT更為精確的世界時間標準。GMT和UTC均用秒數來計算,對于大多數用途來說,我們可以認為GMT就是UTC,GMT=UTC。
在計算機中看到的UNIX時間戳(UNIX epoch或UNIX timestamp)都是從1970年01月01日0:00:00(GMT/UTC)開始計算秒數的,即從1970年這個時間點起到具體時間共有多少秒。這個秒數就是UNIX時間戳。例如,UTC時間2022年3月21日下午2點58分轉換成UNIX時間戳為1647874701。
3.方位角(Azimuth)和仰角(Elevation)
方位角:是從觀察者的指北方向線起,依順時針方向到目標方向線之間的水平夾角。也就是說,0°方位角表示正北,90°方位角表示正東,180°方位角表示正南,270°方位角表示正西,360°方位角表示角度回歸,依然是正北。
仰角:當方位角測量完畢后,需要用仰角來描述被觀察物體相對于觀察者的高度。如果被觀察物體在觀察者上方,那么仰角范圍為0°~90°,有時仰角范圍還為-90°~90°,這是因為被觀察物體在觀察者下方。
如圖4-3所示,以觀察者為中心建立坐標系,3個坐標軸分別指向相互垂直的東向、北向和天向,可以計算出衛星在此坐標系中的仰角和方位角,以及衛星到觀察者的距離。

圖4-3 方位角和仰角示意圖
要進行衛星信號收發,關鍵點是地面站天線的指向,天線必須準確可靠地對準衛星,天線的方位角和仰角是天線指向的重要參數。當衛星處于地平線下方時,處于衛星天線盲區,因此,地面站天線的仰角范圍為0°~90°,方位角范圍為0°~360°。
4.PWM信號和占空比
脈沖寬度調制(Pulse Width Modulation,PWM),是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術,廣泛應用在從測量、通信到功率控制與變換的許多領域中。PWM信號通過周期性跳變的高低電平組成方波來進行連續數據的輸出。
PWM在合適的信號頻率下,通過一個周期內改變占空比的方式來改變輸出的有效電壓。例如,具有30%占空比的PWM信號波形如圖4-4所示。

圖4-4 30%占空比的PWM信號波形
占空比是射頻、微波電路、低頻交流和直流電流等領域的一個概念,最普遍的含義是表示在一個周期內,工作時間與總時間的比值。以單片機為例,單片機的I/O口輸出的是數字信號,I/O口只能輸出高電平和低電平。
假設高電平為5V,低電平為0V,那么要輸出不同的模擬電壓,就要用到PWM,通過改變I/O口輸出的方波的占空比,從而獲得使用數字信號模擬成的模擬電壓信號。如圖4-5所示,占空比為50%即高電平時間一半,低電平時間一半,在一定的頻率下,就可以得到模擬的2.5V輸出電壓,那么75%的占空比,得到的電壓就是3.75V。依此類推,20%的占空比,得到的電壓就是1V。PWM的調節作用來源于對“占周期”的寬度控制,“占周期”變寬,輸出的平均電壓值就會上升,“占周期”變窄,輸出的平均電壓值就會下降。

圖4-5 不同占空比的模擬電壓示意圖
具體在本題中,題目給出天線的舵機接收的占空比為2457~7372,這里占空比可以理解為天線控制舵機轉動一定角度所需的值。
5.舵機控制原理和結構
舵機,其學名為伺服電機,是一種帶有輸出軸的裝置。當我們向伺服器發送一個控制信號時,輸出軸就可以轉到特定的位置。只要控制信號持續不變,伺服機構就會保持軸的位置不改變。如果控制信號發生變化,輸出軸的位置也會相應發生變化。

圖4-6 舵機的內部結構
一種簡單的舵機的內部結構如圖4-6所示,有控制電路、電機、一組減速齒輪和外殼等。控制電路由PWM進行控制。PWM信號對舵機的控制通過一個固定的頻率,給其不同的占空比,來控制舵機不同的轉角。
因此,我們很容易理解,題目中“舵機的占空比為2457~7372,對應天線的0°~180°。”這句話的含義。本題目中,控制方位角的舵機和控制仰角的舵機分別接收不同的占空比,來控制天線朝向。
6.pyorbital.orbital模塊
pyorbital.orbital模塊是用于計算衛星軌道參數的模塊。本題目需要用到以下函數:
pyorbital.orbital.get_observer_look(utc_time, lon, lat, alt)
Return: (Azimuth, Elevation)
參數如下:
- utc_time:觀察時間,其時間格式為UTC。
- lon:地面站的經度,以東經為單位。
- lat:地面站的緯度,以北緯為單位。
- alt:地面站的海拔高度,以km為單位。
調用本函數,返回地面站天線的方位角和仰角。
題目解析
本題目的解法還是比較直觀的,使用Python提供的pyorbital.orbital函數,可以分為3步:
(1)知道要跟蹤的衛星名稱,依據此信息,從給出的active.txt文件中找到目標衛星對應的TLE。
(2)獲取了目標衛星的TLE、開始觀察時間和地面站的位置后,調用前文介紹過的orb.get_observer_look函數,返回方位角和仰角。
(3)方位角和仰角換算成驅動舵機轉動的PWM占空比。
關鍵代碼如下:
from pyorbital.orbital import Orbital
import datetime
# 加載TLE文件,讀出CALSPHERE 1衛星,保存在orb 中
orb = Orbital(' CALSPHERE 1', tle_file='active.txt')
# time為開始觀察目標衛星的那個時刻
time = 1587057945.165157
# 角度和舵機占空比換算函數
def angle_to_servos(angle):
val = angle / 180.0
val = int(val * (7372 - 2457))
val += 2457
return val
# 輸入觀察時間、地面站的位置、要跟蹤的衛星的TLE,調用orb.get_observer_look函數,返回方位角和仰角
for i in range(720):
ts = time+i
t = datetime.datetime.utcfromtimestamp(ts)
angles = orb.get_observer_look(t,-91.43, 17.4804, 0)
# 將方位角和仰角的角度分別換算成控制方位角舵機和控制仰角舵機的占空比
a0 = angle_to_servos(angles[0])
a1 = angle_to_servos(angles[1])
# 打印720行格式為<timestamp>,<PWM0>,<PWM1>的輸出
print(f"{ts}, {a0}, {a1}")
其中角度和舵機占空比換算具體過程是:0°用2457表示,180°用7372表示。由(7372-2457)/180°≈ 27.31/°,那么天線占空比和度數關系為: