Skip to content
RFrftools.io
Satellite Communications2026년 4월 30일5분 읽기

스카이필드와 함께 지상역 패스 스케줄 작성하기

Ansys STK 일몰 준비 완료: 스카이필드를 사용하여 아마추어 라디오 또는 큐브샛 지상국의 SGP4 통과 예측을 계산합니다.TLE 페치, 엘레베이션 마스크, 도플러 및 iCalendar 익스포트를 포함한 전체 Python 워크스루.

목차

로컬 패스 스케줄러가 필요한 이유

SatNOGS 방송국, AO-91/ISS/NOAA를 추적하는 아마추어 라디오 쉑 또는 초기 단계의 큐브샛 그라운드 구간을 운영하는 경우 자동 패스 예측이 필요합니다.상용 도구 (STK, NOVA) 는 무용지물입니다.무료 웹 예측 변수 (AMSAT, Heavens-Above) 는 스크립트를 제대로 작성하지 못합니다.STK Cloud 서비스가 2026년 3월에 종료되는 지금, 가장 깨끗한 무료 대안은 PyEphem의 최신 파이썬 후속 버전인 Skyfield 입니다.

이 게시물에서는 새 TLE을 가져오고, 위성 목록의 다음 24시간 패스를 계산하고, 최소 고도를 기준으로 필터링하고, 다운링크 주파수에 대해 도플러를 계산하고, 캘린더 앱에 패스가 표시되도록 iCalendar를 내보내는 등 약 80줄의 Python으로 완전한 지상국 스케줄러를 살펴봅니다.

설치

pip install skyfield requests icalendar

그게 다야.스카이필드는 최초 실행 시 자체 에페메리드 (DE421, IERS) 를 가져옵니다. 약 17MB가 로컬에 캐시됩니다.

1단계: 현재 TLE 가져오기

TLE는 드리프트 (drift) — 에포크 후 7일 이내에 사용할 수 있습니다.Celestrak에서 현재 요소 세트를 가져오세요:

from skyfield.api import load

stations_url = 'https://celestrak.org/NORAD/elements/gp.php?GROUP=amateur&FORMAT=tle'
sats = load.tle_file(stations_url)
by_name = {s.name: s for s in sats}
print(f'Loaded {len(sats)} amateur-radio satellites')

이름을 기준으로 대상을 선택하세요 (Celestrak 파일에서는 대소문자를 구분합니다).

targets = [
    by_name['AO-91 (FOX-1B)'],
    by_name['ISS (ZARYA)'],
    by_name['NOAA 19'],
    by_name['GreenCube (IO-117)'],
]

2단계: 그라운드 스테이션 정의

from skyfield.api import wgs84, load

ts = load.timescale()
my_station = wgs84.latlon(40.0150, -105.2705, elevation_m=1624)  # Boulder, CO
min_elevation_deg = 10  # horizon mask to skip low passes
elevation_m파라미터를 사용하십시오. 이는 낮은 고도각에서의 경사 범위에 중대한 영향을 미칩니다.

3단계: 상승/절정/설정 이벤트 찾기

Satellite.find_events()함수는 이벤트의 단순 목록 (0 = 상승, 1 = 절정, 2 = 세트) 을 반환합니다.세 배로 처리하세요.
from datetime import timedelta

t0 = ts.now()
t1 = ts.from_datetime(t0.utc_datetime() + timedelta(hours=24))

for sat in targets:
    t, events = sat.find_events(my_station, t0, t1,
                                altitude_degrees=min_elevation_deg)
    # Group into rise/peak/set triples
    triples = zip(t[0::3], t[1::3], t[2::3])
    for rise, culm, setting in triples:
        # Peak elevation
        topo = (sat - my_station).at(culm)
        alt, az, dist = topo.altaz()
        print(f'{sat.name:30s}  {rise.utc_iso():20s}  peak {alt.degrees:4.1f}°  slant {dist.km:4.0f} km')
t0지평선 위에 이미 있는 위성은 무시하십시오 (이벤트 목록은 절정/설정 쌍으로 시작함).

4단계: 패스 상에서의 도플러 시프트

아마추어 UHF (435MHz) 의 경우 패스 한 번으로 캐리어가 ±10kHz 정도 이동할 수 있으므로 수신기가 추적해야 합니다.레인지레이트로 순시 도플러 계산하기:

import numpy as np

FREQ_HZ = 435_800_000  # AO-91 downlink
C = 299_792_458.0      # m/s

def doppler_shift(sat, observer, t):
    """Positive when satellite approaching (received frequency is higher)."""
    # Numerical range rate from 1s apart
    dt = 1.0  # seconds
    t_next = ts.from_datetime(t.utc_datetime() + timedelta(seconds=dt))
    r0 = (sat - observer).at(t).distance().m
    r1 = (sat - observer).at(t_next).distance().m
    range_rate = (r1 - r0) / dt  # m/s, positive = moving away
    return -FREQ_HZ * range_rate / C  # Hz, positive = approaching

# Sample across a pass
for pct in [0, 25, 50, 75, 100]:
    t_sample = ts.from_datetime(
        rise.utc_datetime() + (setting.utc_datetime() - rise.utc_datetime()) * pct / 100
    )
    d = doppler_shift(sat, my_station, t_sample)
    print(f'  {pct:3d}% pass:  doppler = {d:+8.0f} Hz')

일반적인 6분 AO-91 오버헤드 패스의 경우 약 +10kHz (상승) 에서 0 (제니스) 에서 -10kHz (세트) 까지의 도플러 스위프를 볼 수 있습니다.라디오의 메인 VFO에서 이 내용을 추적하면 신호가 손실되지 않습니다.

5단계: 각 패스의 연결 예산

범위가 기울어지면 rftools 자유 공간 경로 손실 계산기 에 입력하거나 인라인으로 계산하세요.

def fspl_db(distance_m, freq_hz):
    return 20 * np.log10(4 * np.pi * distance_m * freq_hz / C)

# At zenith of an AO-91 pass (~800 km slant at 40° elevation from Boulder)
fspl = fspl_db(800_000, FREQ_HZ)
print(f'FSPL = {fspl:.1f} dB')  # ~143 dB

ITU-R 전파 모델을 사용한 전체 몬테카를로 링크 예산을 확인하려면 위성 링크 예산 분석기 를 사용하고 시나리오 URL을 스테이션 로그북과 공유하십시오.

6단계: 패스가 캘린더에 표시되도록 iCalendar를 내보냅니다.

이렇게 하면 스케줄러가 사람에게 유용하게 쓰일 수 있습니다.

from icalendar import Calendar, Event
from datetime import datetime
import pytz

cal = Calendar()
cal.add('prodid', '-//rftools ground station//')
cal.add('version', '2.0')

for sat in targets:
    t, events = sat.find_events(my_station, t0, t1, altitude_degrees=10)
    triples = zip(t[0::3], t[1::3], t[2::3])
    for rise, culm, setting in triples:
        topo = (sat - my_station).at(culm)
        alt, az, _ = topo.altaz()
        ev = Event()
        ev.add('summary', f'{sat.name} (peak {alt.degrees:.0f}°)')
        ev.add('dtstart', rise.utc_datetime())
        ev.add('dtend', setting.utc_datetime())
        ev.add('description', f'Culminate at {culm.utc_iso()}, AZ {az.degrees:.0f}°')
        cal.add_component(ev)

with open('passes.ics', 'wb') as f:
    f.write(cal.to_ical())
print('Wrote passes.ics — import into Google Calendar / Apple Calendar / Outlook')
passes.ics을 애플 캘린더/구글 캘린더/아웃룩으로 가져오면 모든 패스 5분 전에 푸시 알림을 받을 수 있습니다.

7단계: 크론에서 실행

~/bin/station-passes.py안에 스크립트를 드롭하고 하루에 한 번 크론하십시오:
# Refresh pass schedule nightly at 03:00 local
0 3 * * * /usr/bin/python3 ~/bin/station-passes.py > ~/passes.ics 2>> ~/station.log
curl --upload-file과 함께 webdav 캘린더에 연결하면 휴대폰에 모든 패스가 자동으로 표시됩니다.

STK Cloud를 하나씩 교체하기

아마추어/Cubesat/소규모 커머셜 운영의 경우 통합된 툴킷이 STK Cloud의 일상적인 드라이버 기능을 대체합니다.

STK 클라우드 기능무료 교체
합격 예측스카이필드
링크 버짓rftools 위성 링크 버짓 분석기
도플러/레인지 커브스카이필드 레인지-레이트
엘레베이션 마스크+터레인스카이필드+로컬 DEM (SRTM)
3D 시각화Cesium.js
복합 스크리닝SOCRATES
미션 디자인 무역 연구 또는 기관 프로그램의 경우 여전히 데스크톱 STK 또는 NASA GMAT이 필요합니다.AMSAT 설계 검토를 포함하여 이를 제외한 모든 사항에 대해서는 Skyfield+ rftools 스택이 완성되었습니다.

더 읽어보기

자주 묻는 질문

패스 예측, 도플러 커브, 고도 타임라인, 예정된 다운로드의 경우 — 예.스카이필드는 JPL Horizons에 대해 검증된 에페메리드로 SGP4를 구현하고, 30일 기간 동안 STK의 패스 타임 예측과 몇 초 이내에 일치합니다.STK의 3D 시각화, 통합 보고 또는 결합 분석을 대체하지는 않습니다. 이러한 경우에는 Cesium.js 또는 SOCRATES를 사용하십시오.
LEO 위성의 경우 위치 정확도가 1km 미만인 경우 에포크 후 7일 이내14일이 넘은 TLE는 트랙을 따라 10km 이상 표류할 수 있으며, 이로 인해 통과 시간이 30초 이상 이동하므로 6분의 통과 시간을 놓칠 수 있습니다.각 스케줄링 실행 전에 Celestrak에서 새로운 TLE를 가져오세요.
가능한 세 가지 원인: (1) 지상 관측소 좌표가 수십 미터 이상 떨어져 있음 — GPS로 확인하기, (2) AMSAT의 예측 변수보다 오래된 TLE 시대를 사용하고 있는 경우, (3) 해발 위의 관측소 고도를 고려하지 않은 경우 ( elevation_m in wgs84.latlon 사용).10초 미만의 차이는 예상되며 실제 운영에는 영향을 미치지 않습니다.
수치적으로: 시간 t와 t+1s에서의 기울기 범위를 계산하고, 나눠서 범위 속도 (m/s) 를 구한 다음 doppler_shift_hz = -frequency_hz * range_rate / c (위성이 접근하면 양수).Skyfield에는 도플러 함수가 내장되어 있지 않습니다. 다운링크/업링크 주파수에 따라 달라지므로 직접 계산해 보세요.일반적인 435MHz LEO 패스는 약 6분 동안 ±10kHz를 스위핑합니다.
GEO (정지궤도) 의 경우 그렇습니다. 하지만 SGP4/TLE 정밀도는 약 6000km 이상에서 저하됩니다.GEO에는 케플러리안 요소 솔버 또는 풀 에페메리스 (DE440) 를 사용하십시오.딥 스페이스 미션의 경우 스카이필드의 커널 기반 에페메리드를 NASA SPICE 커널과 함께 사용하십시오.달 궤도의 경우 skyfield.api.load ('de440.bsp') 를 통해 DE440 또는 jup365 에피메리스를 적재하세요.

관련 기사