課程總覽
Smallsat — 立方衛星設計與實作 STK 課程教材
清華大學太空科學與工程研究所「立方衛星設計與實作」課程的 STK / Python 實驗教材。
以單一 FIREYE 火山觀測 CubeSat 任務貫穿 16 週,STK Enterprise 主導、Python 開源工具補位。
完整說明見 handbook/CubeSat_Course_Handbook.md。
資料夾結構
| 資料夾 | 週次 | 內容 |
|---|---|---|
handbook/ |
— | 課程總手冊(Word + Markdown) |
primers/ |
— | 各週基礎知識導論(觀念、公式、外部參考連結) |
reference/ |
— | AGIPCEXP / Connect 指令速查 |
tools/ |
— | 跨週共用工具(驗證段 stk_verify.py、記錄器積分) |
week01_intro/ |
1 | 導論:eSatellite FIREYE 場景與物件模型 |
week02_architecture/ |
2 | 系統架構:通訊、地面站與 access |
week03_budgets/ |
3 | 系統工程:質量/功率/鏈路/資料預算(Python) |
week04_orbit/ |
4 | 軌道選擇 + 完整 FIREYE 場景(STK Connect + Python) |
week05_fea/ |
5 | 結構 FEA + 發射振動(CalculiX + Python) |
week06_thermal/ |
6 | 節點熱網路(Python,吃 STK 日照時間線) |
week07_power/ |
7 | 太陽能發電 + 儲存曲線(STK Solar Panel Tool) |
week08_adcs/ |
8 | B-dot detumbling + STK 3D 姿態串接 |
week09_midterm/ |
9 | 期中考(無實驗,附考前自我檢核清單) |
week10_propulsion/ |
10 | Astrogator MCS 機動(STK 主軌)+ Python 驗證 |
week11_comm/ |
11 | 通訊鏈路預算(STK Comm) |
week12_payload_data/ |
12 | 資料預算 / 記錄器填充 / 成像速率上限(吃 Week 4 的 STK 報告) |
week13_automation/ |
13 | STK Python 物件模型自動化 |
week14_operations/ |
14 | 地面站通聯排程(sgp4,與 STK 交叉驗證) |
week15_launch/ |
15 | Aviator 發射 trade study(STK 主軌,含 AGI 原版範例)+ Python 驗證 |
week16_constellation/ |
16 | Walker 星座 + Coverage/FOM 整合展示 + Python 規模掃描 |
工具需求
- STK:Enterprise(Astrogator / Aviator / Comm / Analyzer)+ Integration(Python API)。
- Python:numpy, scipy, matplotlib, pandas, sgp4;選配 pyIGRF/ppigrf、agi.stk12 / ansys.stk.core。
- 結構週:CalculiX(ccx)+ cgx / PrePoMax / ParaView。
安裝 Python 相依:pip install -r requirements.txt(STK API 與 CalculiX 需另裝,見該檔註解)。
執行前注意
- Connect 腳本的報告輸出資料夾要先存在(寫檔失敗為靜默失敗)。
路徑由tools/stk_paths.py統一定義(預設C:\STK_Reports\);建起來:python -c "import sys;sys.path.insert(0,'tools');import stk_paths;print(stk_paths.ensure_reports_dir())"。
tools/check_stk_report_paths.py會盯著寫入方(Connect)與讀取方(Python)用的是同一組報告。 - STK Connect 距離預設公尺,腳本開頭需
SetUnits / km;物件模型多數屬性預設公里。 - 部分範例路徑(
F:\STK\等)為原作者機器路徑,需改為自己的環境。
Jupyter Notebook 版本
16 週各一本獨立 notebook,放在對應的週次資料夾(如 week03_budgets/week03_budgets.ipynb),
內容由該週的 .py / .txt 轉出。原始腳本保留不動,notebook 是它們的教學呈現版。
每一本的結構:
- 週次說明:對應資料夾、實驗單、附帶資料。
- 基礎知識導論:該週的觀念底稿,見下。
- STK Connect 腳本(需要 STK 的週次):以 Python API 逐行送出並回報 ACK/NACK。
接續型腳本會自動先跑前置,並在上方標明相依關係。 - Python Lab:依原有分節切成 cell,圖表 inline 顯示。
- 驗證段:見下。
需要 STK 的 notebook(week 1、2、4、7、10、11、13、16)請先開啟 STK 12 桌面版,
不能用無介面的 STK Engine —— Animate、Graphics ... SetColor、VO ... SolarPanel、
OrbitWizard ... Color、ReportCreate ... Type Display 共 18 條指令在 Engine 上會被拒絕。
獨立章節(不屬於 16 週課程)
五個獨立主題,借用同一套方法論(STK 主導、Python 補位、ACK 不等於生效),
但題材不是立方衛星。每章各有導論、實驗單、Connect 腳本、Python 分析、
驗證段、notebook,以及一份 HTML 展示頁。
| 資料夾 | 主題 | 驗證段 | 招牌發現 |
|---|---|---|---|
radar_bistatic/ |
地面雙基地雷達:干擾、雜波與航跡穩定度 | 62/62 | 20 W 干擾機打斷 100 kW 雷達的航跡;定位誤差變 4.9 倍 |
eoir_earlywarning/ |
地面望遠鏡追蹤探空火箭尾焰:大氣站在哪一邊(EOIR,含動畫) | 202/205(0 FAIL,3 SKIP) | 天基的黃金波段 4.3 µm,從地面看天頂穿透率 5.2e−6、5° 仰角 3.3e−55 |
launch_conjunction/ |
雙節運載火箭入軌 + AdvCAT 交會迴避 | 26/26 | 均勻粗掃找不到 1.8 km 的交會;500 km 比 800 km 擁擠 59 倍 |
tirem_coastal/ |
岸際雷達:TIREM 地形傳播與四種靜默失敗 | 52/52 | 地表電性寫得進去、通過範圍檢查、回讀正確,對輸出差 0.000000000 dB |
spaceport_suborbital/ |
太空港次軌道任務:屏東旭海 → 休士頓 KEFD 的工程概念設計 | 65/65 | 升阻比夠低時機翼會變成淨負擔;到 5.62 時模擬工具的接縫消失 |
每章的 HTML 展示頁包含場景設定、模擬重點、結果圖表與程式碼,可獨立閱讀。
eoir_earlywarning/ 的 3 個 SKIP 不是失敗,是標示出來的無知:
EOIR_R 沒有回讀目標清單的選項(實測 NACK),以及 IntegrationTime 的單位
在 STK 裡找不到任何內部錨可以釘死 —— 本章取 ms,並把這個假設寫成
兩項具名的 SKIP,再用 NEI 的絕對量級當旁證。
這一項和 tirem_coastal/ 的招牌發現剛好是一對:
一個是知道自己不知道(標示成 SKIP),一個是以為自己知道
(回讀正確、範圍檢查通過,實際上對輸出毫無影響)。
驗證段能處理前者;後者只能靠「改動它並觀察輸出」抓出來。
tirem_coastal/ 的主角是一個會通過驗證的錯誤結論:
「TIREM 在這台機器上算不出結果」—— 那是錯的,而它通過了 41 項全綠的驗證。
該章把查證的方法本身變成教材:四種性質不同、沒有一種會給你錯誤訊息的
靜默失敗。詳見該章導論第 5 節。
spaceport_suborbital/ 的兩個特別之處
一、沒有單一 STK 物件能涵蓋全程。 這一章的結論之一是工具邊界本身:
| 飛行階段 | 可用模型 | 狀態 |
|---|---|---|
| 動力上升 1,570 km | Aircraft + 外部星曆 | 已實作並驗證 |
| 助推真空弧 2,400 km | Missile + Ballistic | 已實作並驗證 |
| 高超音速滑翔 + TAEM 9,139 km | Aircraft + 外部星曆 | 已實作並驗證 |
| 跑道進場與降落 30 km 走廊 | Aircraft + Aviator | 已實作並驗證 |
滑翔段改用外部星曆是第二次架構更正:同一條航線交給 Aviator 飛,
航跡長度是直線距離的 5.32 倍 —— 載具在繞圈,而當時 32 項驗證全過。
改用外部星曆後是 1.00 倍。
第三次更正把上面那個「3,765 km 無物件涵蓋」拿掉了。
它原本被當成工具限制寫進對外文件,實際上是記帳錯誤:熄火速度被定義成
「從熄火起一路平衡滑翔全程」,但熄火後那段約 1,200 km 的真空弧幾乎沒有阻力,
把它也算進滑翔射程等於同一段路算了兩次。改成解自洽閉合條件之後,
熄火速度由 6,335 降到 6,118 m/s,航程接縫歸零(閉合殘差 0.000 m)。
第四次更正把動力上升段的沿程也算了進來 —— 它要飛 1,300 km 才到得了
熄火點,而任務幾何一直把它當成一個點,照原本的幾何飛會飛過休士頓
1,259 km。現在是三段自洽閉合。
第五次更正把設計點從 L/D 4.0 改成 3.2 —— 4.0 是查文獻來的,
3.2 是算出來的(SU2 無黏裸翼 5.55,加上由實際網格算出的濕面積的平板摩擦,
整機剩 3.21)。熄火速度因此升到 6,298 m/s。
第六次更正把它再降到 2.2。 3.2 那個算法有一個沒被講出來的假設:
它把裸翼的無黏升阻比套在整機上,等於假設機身貢獻升力與阻力的比例
和機翼一樣。機身主要是阻力,所以那是偏樂觀的。改成在整機網格上算
牛頓流(含遮蔽測試),再套 SU2 在裸翼量到的修正,加上整機摩擦:
2.33 @ α 14°。
但 2.33 本身還不是答案 —— 它是在 L/D 3.2 所隱含的進入條件(6,338 m/s)
下算的。摩擦係數是 Re* 的函數,Re* 由弧終點的速度與高度決定,
而那個條件又由升阻比決定:升阻比降低 → 熄火速度升高 → 弧終點速度升高
→ Re* 降低 → C_f 升高 → 升阻比又更低。這就是本章第 06 節那條設計迴圈,
在這裡變成一個真的數值問題。接到 2.3 自己的弧終點 6,798 m/s 之後只剩 2.21。
阻尼迭代五次收斂到 2.20 @ α 16° —— 那才是自洽的設計點,取 2.2。
熄火速度因此升到 6,819 m/s。2.3 與 2.2 只差 4%,遠在外插修正的
±10% 之內,但「設計點必須是不動點」不是 4% 的問題,是方法上的:
把摩擦釘在固定速度上算出來的升阻比屬於別的設計點。
先跑敏感度再改(這是這一章第二次用同一個流程):掃描 L/D 2.0–3.4,
一路到 2.0 都還可行 —— 質量比最高 16.1,低於「20:1 難以實現」那條線,
酬載分數仍為正。2.2 時質量比 15.5、酬載 3.09%(比 3.2 少 25%),
遠地點與機腹壁溫幾乎不動。全章的招牌結論全部存活。
2.2 仍是估算:三個環節只有第一個是直接算的,第二個從裸翼外插。
要釘死它需要整機的 SU2 解,那件事沒有做。
這次更正還帶出一個新的物理限制:降到 2.3 之後,750 m/s 交棒時
交棒給終端能量管理時,載具比直線進場能吸收的還高 ——
以 750 m/s 交棒的話下滑道要 42°,那不是進場,是俯衝。
後來查清楚:那不是物理限制,是同一個錯誤的第三次。
「用設計下滑道降得完」的交棒速度是升阻比的函數(L/D 4.0 時是
743 m/s、2.2 時是 1,055),而常數寫的是 750 —— 又一個在舊設計點
L/D 4.0 下「剛好對」的值。和進場走廊、摩擦的參考速度是同一類錯。
改成由設計點解出來之後,每個升阻比的下滑道都回到設計值以內,
而代價只是 TAEM 段由星曆的 0.34% 變成 0.97%。
順帶更正:當時寫「往下要動的是翼負荷或 TAEM 進入速度」,
翼負荷那一半是錯的 —— 它方向對但效果很弱,
750 m/s 時由 150 kg/m² 的 45.3° 只能壓到 400 kg/m² 的 39.3°。
第七次更正把設計點從 2.2 再降到 1.74 —— 這一次不是模型換了,
是發現那一環本身算錯了。設計點鏈上唯一直接算的是整機的修正牛頓流,
而它的遮蔽測試有兩個方向相反、互相掩護的錯:零面積三角形參與了遮蔽
(它沒有面積、擋不住東西,但投影足跡可能很長),以及光柵化用的是投影的
「包圍盒」而不是三角形本身(細長的斜三角形會霸佔整個盒子)。
第二個錯的「過度宣稱」剛好補了「佔用集合會漏」的洞,所以先前的解析度
掃描看起來很穩定。
改成深度緩衝 + 可見比例加權之後才真的收斂(80 到 800 格之間穩在
1.73)。新的遮蔽碼有三項驗證:解析度收斂、凸體加不加遮蔽結果相同、
球體的牛頓流阻力對上解析解(差 0.11%)。整機 L/D 因此由 2.90 改為
1.78 @ α 20°,解不動點得到 1.74。熄火速度升到 7,074 m/s。
先跑敏感度再改:掃 L/D 1.4–2.2,一路到 1.4 都還可行(質量比最高 18.0,
仍低於 20:1;酬載分數仍為正)。招牌結論全部存活 —— 但有一件事變了:
設計點 1.74 距離「機翼是淨負擔」的損益平衡點只剩 8%。
後續更正:上面那個 8% 是錯的。那條門檻先前寫成 1.61,
但它是 L/D 4.0 時代的數字,而且程式裡從來沒有函式在算它。新增的
wing_break_even_ld()把三種記帳方式都算出來,而只有一種
是對的:純彈道基準的假設是「起點與落點同半徑、無阻力」——
它根本沒有熄火高度,動力上升段被當成發射點的一個點事件。
所以助推滑翔那一側也要用同一個理想化層級。門檻是 0.81,
設計點 1.74 的餘裕 +116%。「無法排除機翼是淨負擔」收回。(只在滑翔側加上真實的 1,570 km 上升段沿程會把門檻壓到 0.60 ——
那是不一致的比較,網頁先前畫的就是那一條,已改。)
在 4.0 的時候那是一個遙遠的教學用門檻,現在它是迫近的設計約束。
剩下的是工具邊界而不是航程缺口:弧終點 7,103 m/s 仍高於 Aviator 的
求解上限 5,400 m/s(實機量測),所以那一段要用外部星曆播放。
升阻比提高到 5.62 時弧終點速度降到該上限以下,整條任務可在 Aviator 內
端對端模擬 —— 工具邊界因此不是一條事後才浮現的限制,而是可以寫進規格的設計指標。
這七次更正有個共同點:大多數時候每一次的中間數字都是對的,錯的是組合起來的
形狀、帳、或是那個數字的來源。詳見 程式架構.md。
本章還記錄了一次架構層級的更正:初版用最小能量彈道當彈道段,
算出的遠地點 1,130 km(卡門線的 11 倍)—— 每個數字都對,
組合起來卻是一條沒有有翼載具會飛的軌跡。
現在改為淺角度(γ = 2°)熄火於卡門線,遠地點 117 km。
這個錯誤是從軌跡形狀看出來的,不是數值檢查抓到的。
二、附一個互動式教學工作單。 web/suborbital_workbench.html 是單檔
HTML,所有計算在瀏覽器端完成。移動任一設計變數,射程 → 所需速度 →
Δv → 質量比 → 分離時刻整條鏈會一起動。頁面同時顯示四層狀態:
數學可算 / 模型適用 / 模擬工具 / 工程可行(最後一層恆為「未驗證」)。
程式本身的架構、模組相依、執行順序與已知的坑寫在 程式架構.md。
公式的假設、適用範圍與失準處寫在 web/設計與計算原理.md,
並記錄了兩個在撰寫該文件時查出來的數值錯誤
(地球半徑常數與分析模組不一致、機翼損益平衡點畫在永遠不會相交的曲線上)。
Streamlit 部署
工作單可部署到 Streamlit Community Cloud 取得公開網址:
Main file path streamlit_app.py
Dependencies requirements-streamlit.txt ← 不是根目錄的 requirements.txt
requirements.txt 是課程 Lab 用的(numpy / scipy / matplotlib / pandas /
sgp4 / ppigrf),Streamlit app 一項都不需要 —— 所有運算在瀏覽器端,
伺服器只送出靜態檔。用錯會拖慢建置。
本機試跑:
pip install -r requirements-streamlit.txt
streamlit run streamlit_app.py
streamlit_app.py 只是部署外殼,不是原生 Streamlit app ——
它把同一份 HTML 包進 iframe,而不是把滑桿改寫成 st.slider。
這樣 HTML 版與 Streamlit 版共用同一套公式,不會各自演化。
理由與取捨寫在該檔的 docstring 裡。
基礎知識導論 (primers/)
原本的教材是「實驗單 + 腳本 + 驗證段」—— 學生會做,但不一定知道為什麼這樣做、
以及這個數字憑什麼可信。primers/weekNN_primer.md 補的就是這一段。
每一份的結構固定:
- 這一週在解什麼問題 — 把週次主題還原成一個具體的工程問題
- 核心觀念 — 帶公式與典型數值,不只是名詞解釋
- 名詞與符號 — 一張表,含單位與本課典型值
- 觀念 → 本週實驗對照 — 每個觀念對應到哪一支腳本的哪一段
- 常見誤解 — 含本教材實測踩過的真實坑
- 延伸閱讀 — 外部連結,全部經過連線驗證
- 課前自我檢核 — 5 題
導論已收進各週 notebook(在標題之後、實驗之前)與課程 PDF 的每一章開頭,
primers/README.md 另有全課程通用的外部資源彙整。
驗證段:ACK 不等於生效
STK Connect 對絕大多數指令只回「收到」。本教材實測 396 條指令全部 ACK,
但真正能證明生效的只有一部分。學生若養成「送指令 → 沒報錯 → 相信成功了」的習慣,
在工程上是危險的。
因此每一週都附了 weekNN_verify.py(共用工具在 tools/stk_verify.py):
- 需要 STK 的週次:把腳本設過的每個值用
*_RM ... GetValue讀回來比對,
再加上結構檢查(物件、約束、MCS 段序、修正器是否收斂)與該週的物理判準。 - 純 Python 的週次:把實驗單寫死的基準數字變成可執行的斷言,
例如 Week 5 的第一模態 71 Hz(基準 FAIL)、Week 6 的電池低於 0°C。
結果分三類:PASS(讀回值符合意圖)、FAIL(ACK 了卻沒生效)、
SKIP(沒有回讀路徑,需另行確認)。離開碼 0/1,可直接進 CI。
python week11_comm/week11_verify.py # 37 項:回讀 + 結構 + 最差 Eb/No 餘裕
python week10_propulsion/week10_verify.py # 42 項:MCS 段序 + 修正器收斂 + 三次 delta-V
導入驗證段的過程中,它在既有教材裡抓出數個 0-NACK 的靜默失敗,包括
Model.DesignFrequency 屬性不存在、設定天線型別會沖掉先前寫的設計頻率、
Week 11 沿用 Lab1 掃描起點導致鏈路完全沒有 access、以及 Week 4 的
SolarPanel DeleteData 會讓 Week 7 的發電計算產出空報告。
Python Lab 快速執行
python week03_budgets/week3_mission_budgets.py # 四大預算 + 圖
python week05_fea/week5_fea_launch_vibe.py # FEA 模態 + 隨機振動
python week06_thermal/week6_thermal_network.py # 節點溫度曲線
python week08_adcs/week8_detumble_stk_integrated.py # B-dot 消旋 + .a 姿態檔(約 18 s)
python week12_payload_data/week12_data_budget.py # 資料預算 + 記錄器 + 速率上限
python week14_operations/week14_pass_scheduler.py # 地面站通聯排程
python week16_constellation/week16_constellation_tradeoff.py # 星座規模 vs 重訪
python week11_comm/week11_verify.py # 驗證段:確認參數真的生效(需 STK)