Week 1 — 導論

資料夾:week01_intro/

基礎知識導論

Week 1 基礎知識導論 — 立方衛星與 STK 的世界觀

這一頁是進實驗室之前的觀念底稿。目的不是取代教科書,而是讓你在按下第一條
Connect 指令之前,知道螢幕上那些物件各自代表什麼物理意義。

1. 這一週在解什麼問題

STK 打開來是一個 3D 地球加一堆選單。真正要學的不是選單位置,而是:
一個太空任務可以被拆成哪些物件,物件之間的關係是什麼,以及「看得到/看不到」
這件事怎麼被算出來。
本課 16 週都建立在這個物件模型上。

2. 核心觀念

2.1 CubeSat 是一種「規格」,不是一種「衛星」

CubeSat 的定義來自 Cal Poly 的 CubeSat Design Specification (CDS)。它規範的是
外形與介面,不是任務:

這件事的意義:很多設計限制(質量、外形、第一模態頻率、去軌時限)不是物理決定的,
是規格與發射服務合約決定的。工程判斷要先分清楚哪些是物理極限、哪些是可談判的介面。

2.2 任務生命週期與本課的位置

ESA/NASA 的相位劃分(Pre-Phase A → Phase F)裡,本課涵蓋的是 Phase A/B 的可行性與初步設計:
畫 CONOPS、開預算表、做 trade study、驗證關鍵子系統可行。不做飛行硬體驗證。
所以本課所有數字的定位是「設計決策的依據」,不是「飛行驗收值」。

2.3 STK 的物件模型

STK 的一切都掛在一個場景(Scenario)底下,是一棵樹:

Scenario                      分析時間窗、單位、中心天體
├── Satellite                 有一個 Propagator(軌道從哪來)
│   ├── Sensor                視野錐(Simple Conic / Rectangular / SAR ...)
│   ├── Transmitter/Receiver  通訊(Week 11)
│   ├── Attitude              姿態(Week 8)
│   └── SolarPanel            發電(Week 7)
├── Facility / Target / Place 地面點(地面站、火山)
│   └── Sensor                地面站天線的仰角遮罩
└── Chain / Coverage / …      物件之間的關係(Week 12/16)

關鍵心法:STK 不是「畫圖軟體」,是幾何與動力學計算引擎。3D 視窗只是結果的呈現。
所有你要交的作業數字,都來自 Report / Data Provider,不是來自看圖。

2.4 Access:本課最重要的一個原始量

Access 是「在什麼時間區間內,A 看得到 B」。它是幾何(視線是否被地球擋住)
加上約束條件(仰角下限、距離、太陽角、感測器錐角……)的交集。

Access 之所以重要,是因為它是後面所有週次的共同輸入:

一個常犯的錯:分析時間窗設太短,access 是 0,結論卻寫成「這條鏈路不可行」。
本教材的 Week 2 就踩過這個坑(原本 2.5 小時窗 → 成像 access 為 0)。

2.5 時間與座標系

兩個系差在地球自轉(約 15°/hr)。軌道面在慣性系裡幾乎不動,地面軌跡卻會西移,
這就是為什麼同一顆衛星每一圈飛過的地表位置不同 —— 這件事是 Week 4 選軌道的根基。

2.6 傳播器 (Propagator):同一組根數,不同的未來

傳播器 物理內容 用在哪
TwoBody 只有質點重力 手算驗證、量級估計
J2Perturbation 加地球扁率 J2 快速看昇交點漂移
SGP4 配合 TLE 的專用模型 追蹤既有衛星(Week 14)
HPOP 高階重力場+大氣阻力+三體+太陽輻射壓 需要精度時(Week 4, 10)

不能混用:TLE 只能餵 SGP4;把 TLE 的數字當成瞬時根數丟給 HPOP 是常見的初學錯誤
(TLE 是 SGP4 專用的平均根數)。

3. 名詞與符號

名詞 意義 備註
U CubeSat 單位體積 10 × 10 × 11.35 cm
CDS CubeSat Design Specification Cal Poly 發布的外形規格
CONOPS Concept of Operations 任務怎麼運作的敘事
Access 可見時間區間 幾何 + 約束的交集
Epoch 軌道根數的參考時刻 換曆元必須重算
UTCG UTC Gregorian STK 預設時間格式
ICRF / Fixed 慣性系 / 地固系 差一個地球自轉
TLE Two-Line Element 只搭配 SGP4 使用
FOV Field of View 感測器視野
TRL Technology Readiness Level 1–9,決定風險

4. 觀念 → 本週實驗對照

觀念 出現在本週的哪裡
物件樹 week01_eSatellite_scenario.txt 的 New / */Satellite/... 建立順序
傳播器選擇 腳本裡的 SetPropagator / SetState Classical
感測器錐角 Define ... Sensor ... SimpleConic
Access Access */Satellite/... */Facility/...
ACK ≠ 生效 week01_verify.py 把設過的值讀回來比對

5. 常見誤解

  1. 「指令沒報錯就是設定成功了。」 — 錯。STK Connect 對大多數指令只回「收到」。
    本教材實測 396 條指令全部 ACK,但真正能證明生效的只有一部分。這是全課程的主軸之一。
  2. 「3D 看起來對就是對。」 — 3D 是渲染結果,數字要從 Report 出來。
  3. 「CubeSat 比較簡單。」 — CubeSat 便宜,不簡單。體積與功率的限制反而讓
    子系統之間的耦合更緊,預算表更容易一改全崩(Week 3 會實際看到)。
  4. 「距離單位應該是公里。」 — Connect 指令的距離預設是公尺,物件模型多數屬性
    卻是公里。單位陷阱在本課會反覆出現。

6. 延伸閱讀

先看這些(入門,免費)

工具文件

想深入

7. 課前自我檢核

  1. 1U CubeSat 的外形尺寸與質量上限是多少?這個上限是誰規定的?
  2. 為什麼軌道面在慣性系裡幾乎不動,地面軌跡卻會一直西移?
  3. 一顆衛星對地面站的 access 為 0,可能有哪三種完全不同的原因?
  4. TLE 為什麼不能直接丟給 HPOP?
  5. 「指令回了 ACK」證明了什麼?沒有證明什麼?

程式碼

week01_intro/week01_eSatellite_scenario.txt
# ============================================================
# Week 1 導論 — eSatellite (FIREYE) 場景導覽
#
# 本週目標:認識 STK 的物件模型與時間軸。建出任務主角 FIREYE
# 與它的成像酬載,在 2D/3D 視窗裡看軌道、姿態與感測器足跡。
# 通訊、地面站、火點與 access 分析留到 Week 2(系統架構)。
#
# 由原本的 eSatellite_STK_Connect.txt 拆分而來(前半)。
# 驗證段:week01_verify.py
# ============================================================
# ============================================================

# ---- Scenario + analysis window (tutorial Target Planner: 22 Jul 2020) ----
New / Scenario eSatellite_FIREYE
# 分析窗:原本沿用教學手冊 Target Planner 的 2.5 小時(16:00-18:30),
# 但那太短 —— 700 km SSO 配 30 度錐角在 2.5 小時內看不到任何火點,
# 成像 access 是 0,Week 2 的「coverage 換 volume」就沒有輸入可用。
# 改為整天,讓成像與下傳都有足夠樣本。
SetAnalysisTimePeriod * "22 Jul 2020 00:00:00.000" "23 Jul 2020 00:00:00.000"
SetTimePeriod        * "22 Jul 2020 00:00:00.000" "23 Jul 2020 00:00:00.000"
Animate * Reset
SetUnits / km

# ============================================================
# FIREYE 6U CubeSat  (SSO ~700 km) [ASSUME orbit]
# ============================================================
New / */Satellite FIREYE
OrbitWizard */Satellite/FIREYE SunSynchronous Altitude 700 Color yellow

# Nadir attitude: +Z faces nadir (tutorial Nadir Point Vector [0 0 1]).
# If this token isn't accepted in your STK version, set it in the GUI:
#   FIREYE > Basic > Attitude > "Nadir alignment with ECF velocity constraint"
SetAttitude */Satellite/FIREYE Profile NadirECFVel Offset 0.0

# ---- Imager payload sensor (nadir cone, boresight = body +Z = nadir) ----
New / */Satellite/FIREYE/Sensor Imager
# [ASSUME] half-angle
Define */Satellite/FIREYE/Sensor/Imager SimpleCone 30
Graphics */Satellite/FIREYE/Sensor/Imager SetColor red
week01_intro/week01_verify.py
# -*- coding: utf-8 -*-
# ================================================================
# Week 1 驗證段 — 場景與 FIREYE 主角是否真的建起來了
#
# 導論週的指令不多,但每一條都是後面十五週的地基。姿態設錯、錐角設錯,
# 到 Week 12 算資料預算時才會發現 access 數字不對 —— 那時已經很難回頭追。
#
# 執行:python week01_verify.py
#   離開碼 0 = 全部通過,1 = 有項目對不上
# ================================================================

import os
import sys

# notebook 的 kernel 沒有 __file__。而且啟動 STK Engine 會改變 process 的
# 工作目錄,所以不能事後才靠 os.getcwd() —— notebook 開頭的 bootstrap cell
# 會先把週次目錄釘在 WEEK_DIR。
HERE = (os.path.dirname(os.path.abspath(__file__)) if "__file__" in globals()
        else globals().get("WEEK_DIR") or os.path.abspath(os.getcwd()))
REPO = os.path.abspath(os.path.join(HERE, os.pardir))
sys.path.insert(0, os.path.join(REPO, "tools"))

from stk_verify import Verifier, load_lab
from agi.stk12.stkdesktop import STKDesktop
from stk_verify import run_script      # noqa: E402


def main():
    app = STKDesktop.AttachToApplication()
    root = app.Root
    if root.CurrentScenario is not None:
        root.CloseScenario()
    ack, nack = run_script(root, os.path.join(HERE, "week01_eSatellite_scenario.txt"))

    v = Verifier(root)
    v.expect_true("場景名稱", root.CurrentScenario.InstanceName == "eSatellite_FIREYE",
                  root.CurrentScenario.InstanceName)
    v.object_exists("*/Satellite/FIREYE")
    v.object_exists("*/Satellite/FIREYE/Sensor/Imager")
    v.cone_angle("*/Satellite/FIREYE/Sensor/Imager", 30.0)

    # 姿態:SetAttitude 的正確語法是 Profile NadirECFVel,而且 Offset 參數必填。
    # 寫成 "Basic Nadir ECFVelocity" 會被拒,衛星就停在預設姿態 —— 這是本教材
    # 原本的錯誤,而且 access 數字會因此少一半。
    sat = root.GetObjectFromPath("*/Satellite/FIREYE")
    prof = int(sat.Attitude.Basic.ProfileType)
    v.expect_true("姿態為 Nadir alignment with ECF velocity", prof == 8,
                  f"ProfileType = {prof}(8 = NadirECFVel)")

    v.expect_true("腳本沒有 NACK", nack == 0, f"{ack} ACK / {nack} NACK")

    ok = v.report("Week 1 驗證段")
    return 0 if ok else 1


if __name__ == "__main__":
    _rc = main()
    if "ipykernel" not in sys.modules:
        raise SystemExit(_rc)