闲话卫星轨道预测
0. 毫无意义的引子
贵校的天文社长来找您做一件事情。
对方希望您可以为他们做一个程序,告诉您一些卫星,他们的观测地点,时间,希望您能够给出那个时候这些卫星在天空中的位置与相对速度,列成一个表格,并且预测过境时间
我又不是学天文的,为啥让我算
于是您丢给他了一个orbitron
的指南
对方发现不能生成表格,他很懒,希望您写一个一键生成的程序。
于是我们开始找轮子
1.前置技能
首先,请先安装Python 3.7 + ,我们将使用Python,所以学习一些基础知识很有必要,你谷有[链接登录后可见],大佬们应该学学就会。
安装一些需要的库,本文主要需要pyephem
库,运行以下命令,当然可以使用国内Pypi
源
pip install pyephem
由于需要爬虫,自行安装一些相关库,本文使用requests+BeautifulSoup
然后学习一些天文知识
2.搞到数据
请搞到您要预测的卫星的NORAD Catalog Number
的数据,可以在[链接登录后可见]通过名字搜索。
我们可以在<https://celestrak.com/satcat/tle.php?CATNR={NORAD Catalog Number}>
搞到数据。我们以ISS(国际空间站)为例,NORAD Catalog Number
是25544,进入[链接登录后可见]。
我们可以看到一坨文本,大概是这样
可能和您的不一样,那是因为时间不一样,因为本文分批完成,所以全文TLE也不一样。
这串是Two-line_element_set(TLE)
数据。TLE?中文译名两行式轨道根数,由于记录卫星轨道。
不说格式了,自行百度。
可以用requests
库下载数据,没有被robots.txt
拦截(本来就是需要边爬边算的,如果不给API连爬网站都不让……站长素质可见一般)
代码
import requests #引入库
r = requests.get('https://celestrak.com/satcat/tle.php?CATNR=25544') #进行爬取
s=r.text
print (s) #得到内容并输出
这时,我们可以看到以下内容
<!doctype html>
<html>
<head>
<title>TLE for NORAD Catalog Number 25544</title>
</head>
<body>
<pre>
ISS (ZARYA)
1 25544U 98067A 19309.26609277 .00005709 00000-0 10697-3 0 9998
2 25544 51.6434 21.7673 0005860 232.6569 232.3132 15.50258596197147
</pre>
</body>
</html>
我们发现,TLE数据位于pre
块中,我们用Beautiful soup
进行解析
代码接上
from bs4 import BeautifulSoup #引入库
soup = BeautifulSoup(s, 'html.parser') #创建Soup对象
s=soup.pre.get_text() #得到第一个(唯一的一个)pre块的文本内容
s
我们得到以下内容
'\r\nISS (ZARYA) \r\n1 25544U 98067A 19309.26609277 .00005709 00000-0 10697-3 0 9998\r\n2 25544 51.6434 21.7673 0005860 232.6569 232.3132 15.50258596197147\r\n\r\n'
我们发现有一些没必要的换行,搞掉,同时\r\n
变\n
(代码接上)
s=s.replace ('\r','') #把\r变为空,即去掉
s=s[1:-2] # 抛弃第一个字符和后两个字符
print (s)
我们得到
ISS (ZARYA)
1 25544U 98067A 19309.26609277 .00005709 00000-0 10697-3 0 9998
2 25544 51.6434 21.7673 0005860 232.6569 232.3132 15.50258596197147
一个可以使用的TLE字符串
一个问题:对于没有TLE的卫星(一般是不在轨道,如坠落等),怎么办?
我们发现,其内容为No TLE found
,操作后为'No TLE foun'
特判一下就好了(代码接上)
if s=='No TLE foun':
raise ValueError ("This NORAD catalog number don't have TLE data on celestrak.com") #这里抛出了异常,调用时可以捕捉
我们将以上代码包装成函数,使其可以用于任意NORAD Catalog Number
的TLE数据
import requests
from bs4 import BeautifulSoup
def get_TLE (num):
r = requests.get('https://celestrak.com/satcat/tle.php?CATNR={}'.format(num))
s=r.text
soup = BeautifulSoup(s, 'html.parser')
s=soup.pre.get_text()
s=s.replace ('\r','')
s=s[1:-2]
if s=='No TLE foun':
raise ValueError ("This NORAD catalog number don't have TLE data on celestrak.com")
return s
3. 预测过境
我们得到了一个获取TLE的函数,现在我们尝试计算
假如说您想使用代码自行计算,我可以给您一张图片

本图来自CSDN
我们可以看到大量变量,您要写的代码不少呀!
所以,我们用一个别人写好的轮子——pyephem
,我们可以看一下它的官方文档[链接登录后可见],全英语
我们如何用它呢?
当然,第一步import
首先,我们要实例化一个观察者小人对象(ephem.Observer
)me
,设置观察者的位置(经纬度),海拔(这是与观察结果有关的,假设您在114514km海拔,肯定和在地面上不一样),时间(如果您想,还可以提供气压以及温度)。
import ephem
me=ephem.Observer() #将观察者对象实例化
me.lat='40.250025' #纬度
me.lon='116.260367' #经度
#上方两行填您的坐标,注意一定是字符串
me.elevation =50 #海拔(大概就好了,不用很精准,单位米)
me.date = ephem.Date('2019/11/10 05:16:30') #这里是时间,详细内容看下文
对于时间,有若干种表示方法,推荐使用
ephem.Date('2019/11/10 05:16:30') #注意是格林威治时间,也就是不考虑时区,所以请自行把时间-8h(左边的例子应该是北京时间13时16分30秒)
ephem.Date(ephem.Date('2019/11/10 13:16:30') - 1/3) #如果您非要用北京时间不可的话
ephem.now() #当前时间,简单暴力
当我们把观察者对象准备就绪后,需要创建一个卫星对象(ephem.EarthSatellite) sat
,然后使用readtle
方法(代码接上上)
TLE=get_TLE(25544) #用上面的函数搞来TLE数据
TLE=TLE.split('\n') #因为readtle方法只能有三个单行的字符串,所以要切开
sat = ephem.readtle(TLE[0], TLE[1],TLE[2]) #用TLE数据生成sat对象
现在所有数据都就绪了,直接开始计算!
sat.compute(me) #就是这么简单,ephem真强
这时候,我也不知道程序做了多少奇怪的操作,但是可以肯定的是一般我们能用得上的数据,都已经算好了
如果我们只是需要确定卫星当前位置的话,方位角,仰角和相对速度,只需要从sat
当中取出来就好了
值得一提的是,sat中默认的方位角和仰角是弧度,需要化为角度,\text{角度}=\dfrac{\text{弧度}\times 180}{\pi},代码接上
print(sat.az * 180.0 / 3.1416) #卫星的方位角
print(sat.alt * 180.0 / 3.1416 ) #卫星的仰角
print(sat.range_velocity) #卫星的相对速度
如果我们要预测下次过境的话,还需要再运行一次运算
me.next_pass(sat)
这玩意返回一个六元组
(升起的时间,升起时的方位角,达到最高点的时间,最高点的仰角,落下地平线的时间,落下地平线时的方位角)
不要问我为什么没有最高点的方位角
4.生成表格
咕咕咕