この記事は「ソニックガーデン 若手プログラマ Advent Calendar 2024」の17日目の記事です。
はじめに
みなさん宇宙はお好きですか?100km上空からは宇宙らしいので割と身近だったりしますよね。人工衛星のニュースなどを見聞きすると、どんな軌道なんだろうかと気になることも多いかと思います。
地球の周りを回っている人工衛星はほとんど、CelestrakというサイトでTLE(Two Line Elements)という形式の軌道要素が公開されています。このTLEを使って自分で色々と遊べるgemがあったら面白そうだなということで作ってみました。
gemの作り方は、以下の記事を参考にさせていただきました。
gemの作り方自体は参考記事からの差分がないので、この記事ではどんなgemを作ったかにフォーカスします。
どんなgem?
TLEをインプットに別の軌道要素を計算するようなgemです。
具体的には以下の機能を作ってみました。
- TLEのテキストデータ1を読み込んで軌道要素にパース
- TLEのJSONデータ2を読み込んで軌道要素にパース
- TLEから作った軌道のKeplerianのオブジェクトを作成
- TLEの軌道要素から高度を算出
- Cartesianのオブジェクトを作成
なんか物足りないですが、今後に期待です。。
TLEのテキストデータを読み込んで軌道要素にパース
ISS(国際宇宙ステーション)のTLEを例にします。
https://celestrak.org/NORAD/elements/table.php?GROUP=stations&FORMAT=tle
このページの一番上のLatest Data
を使ってみます。
irb(main):001> require 'korba'
irb(main):002> tle = Korba::Tle.new(<<~TLE)
ISS (ZARYA)
1 25544U 98067A 24347.95246197 .00018784 00000+0 32977-3 0 9991
2 25544 51.6388 149.7053 0007501 335.8963 160.2029 15.50536434486275
TLE
# コピペしたい人がいるかもしれないので、ヒアドキュメント部分のirbプロンプトは消してます。
=>
#<Korba::Tle:0x0000000129b75230
...
irb(main):003> tle
=>
#<Korba::Tle:0x0000000129b75230
@arg_of_pericenter=335.8963, # 近地点引数
@eccentricity=0.0007501, # 離心率
@epoch="2024-12-12T22:51:32.714207",
@inclination=51.6388, # 傾斜角
@mean_anomaly=160.2029, # 平均近点角
@mean_motion=15.50536434486275, # 平均運動
@object_name="ISS (ZARYA) ",
@ra_of_asc_node=149.7053, # 昇交点赤経
@tle_string="ISS (ZARYA) \n1 25544U 98067A 24347.95246197 .00018784 00000+0 32977-3 0 9991\n2 25544 51.6388 149.7053 0007501 335.8963 160.2029 15.50536434486275">
TLEの、なに書いてあるかわからない状態から各要素がどんな値なのか一目瞭然になりました!便利!
(単位は距離はm
、角度はdegrees
です)
TLEのJSONデータを読み込んで軌道要素にパース
irb(main):001> require 'korba'
irb(main):002> tle_json = {"OBJECT_NAME":"ISS (ZARYA)","OBJECT_ID":"1998-067A","EPOCH":"2024-12-12T22:51:32.714208","MEAN_MOTION":15.50536434,"ECCENTRICITY":0.0007501,"INCLINATION":51.6388,"RA_OF_ASC_NODE":149.7053,"ARG_OF_PERICENTER":335.8963,"MEAN_ANOMALY":160.2029,"EPHEMERIS_TYPE":0,"CLASSIFICATION_TYPE":"U","NORAD_CAT_ID":25544,"ELEMENT_SET_NO":999,"REV_AT_EPOCH":48627,"BSTAR":0.00032977,"MEAN_MOTION_DOT":0.00018784,"MEAN_MOTION_DDOT":0}
=>
{:OBJECT_NAME=>"ISS (ZARYA)",
...
irb(main):003> tle = Korba::Tle.new(tle_json, type: :json)
=>
#<Korba::Tle:0x000000011fe7b7e0
...
irb(main):004> tle
=>
#<Korba::Tle:0x000000011fe7b7e0
@arg_of_pericenter=335.8963,
@eccentricity=0.0007501,
@epoch="2024-12-12T22:51:32.714208",
@inclination=51.6388,
@mean_anomaly=160.2029,
@mean_motion=15.50536434,
@object_id="1998-067A",
@object_name="ISS (ZARYA)",
@ra_of_asc_node=149.7053,
@tle_json=
{:OBJECT_NAME=>"ISS (ZARYA)",
:OBJECT_ID=>"1998-067A",
:EPOCH=>"2024-12-12T22:51:32.714208",
:MEAN_MOTION=>15.50536434,
:ECCENTRICITY=>0.0007501,
:INCLINATION=>51.6388,
:RA_OF_ASC_NODE=>149.7053,
:ARG_OF_PERICENTER=>335.8963,
:MEAN_ANOMALY=>160.2029,
:EPHEMERIS_TYPE=>0,
:CLASSIFICATION_TYPE=>"U",
:NORAD_CAT_ID=>25544,
:ELEMENT_SET_NO=>999,
:REV_AT_EPOCH=>48627,
:BSTAR=>0.00032977,
:MEAN_MOTION_DOT=>0.00018784,
:MEAN_MOTION_DDOT=>0}>
JSONあるんかい、わかりやすいの落ちてるやんと思った人は鋭いですね。その通りなんですが一旦横に置いときます。TLEをわかりやすくしたいんじゃなく、軌道で遊ぶのが目的なので。
TLEから作った軌道のKeplerianのオブジェクトを作成
さっきのやつをこう
irb(main):005> tle.to_kep
=>
#<Korba::Kep:0x0000000129d17a48
@arg_of_pericenter=335.8963,
@eccentricity=0.0007501,
@epoch="2024-12-12T22:51:32.714208",
@inclination=51.6388,
@mean_anomaly=160.2029,
@object_name="ISS (ZARYA)",
@ra_of_asc_node=149.7053,
@semi_major_axis=6793295.781644506> # 軌道長半径
軌道を特定するために必要な6要素のうち、1個変わっただけなんですけど、やっぱり軌道長半径がわかると軌道のイメージがよりつきやすいですね。
地球の半径が頭にあれば、なんとなくの高度もわかってISSって近いんだなーとか思うかもですが、地球の半径を覚えてる必要もないので高度の計算機能も作りました。
TLEの軌道要素から高度を算出
irb(main):006> tle.height_at_perigee # 近地点高度
=> 410063.13047869503
irb(main):007> tle.height_at_apogee # 遠地点高度
=> 420254.43281031866
人工衛星の軌道は楕円なので近地点(地球に最も近くなるところ)と遠地点(地球から最も遠くなるところ)の2つの高度があるとわかりやすいですね。
Cartesian(地球中心慣性系)のオブジェクトを作成
TLEからでもKeplerianからでも
irb(main):008> tle.to_car
=>
#<Korba::Car:0x000000012bb540b0
@epoch="2024-12-12T22:51:32.714207",
@object_name="ISS (ZARYA) ",
@vx=6308.89485150973,
@vy=279.4748703287188,
@vz=-4325.798068923932,
@x=2756480.692923069,
@y=-4996823.877996226,
@z=3694266.1741632815>
いまいち、ピンと来ない軌道要素ではあるんですが、これを元に座標系変えてとかすると役に立つやつなので算出できるようにしました。(このピンと来ないやつが一番手がかかってます。。)
Newton法で方程式の解を数値解析してくれるNewton.nlsolve
とVector
を初めて使いました。
注意
計算の確からしさはCelestrakや本などの例題と照らし合わせて、大体合ってるから計算方法は間違ってないだろうなというのを確かめたくらいで精緻には検証していません
ついでにgemを使ったRailsアプリも作った
gem作ったら使いたいなと思い、簡素なRailsアプリも作りました。
fly.ioで動いてるRailsアプリです。
初めてmvp.cssを使ってみました。読み込むだけ、ただHTML書くだけでよしなにスタイルをつけてくれます。(逆にいうと調整はほぼ効かない)
機能はシンプルです。TLE入力、read tle
押す。高度、TLE、Keplerian、Cartesianが表示される。
ちなみに画像はひまわり9号の軌道です。今日も元気に3万6千km先で日本のみんなのために観測してくれてます。ありがたや
まとめ
軌道で遊びたい人向けのgemを作って、それを使ったRailsアプリを作ってみた、という紹介記事でした。
ただ、まだまだ遊ぶには機能不足なので、今後成長させていきたいなと思っています。
やっぱり、伝播したいし、軌道座標とかでの速度とか気になりますよね。あとはRailsアプリも可視化とか、、乞うご期待。
明日の「ソニックガーデン 若手プログラマ Advent Calendar 2024」は、@yappu00 です。お楽しみに!
リンク集
- https://qiita.com/advent-calendar/2024/sonicgarden-junior
- https://qiita.com/harashoo/items/1284fd5362c1a4f6c8a8
- https://earth.jaxa.jp/gpr/ProductsOperations/docs/GCOM-W/W1TLE_ja.pdf
- https://celestrak.org/NORAD/elements/gp.php?CATNR=25544&FORMAT=tle
- https://rubygems.org/gems/korba
- https://docs.ruby-lang.org/ja/latest/class/Newton.html
- https://docs.ruby-lang.org/ja/latest/class/Vector.html
- https://korbas-misty-sun-4798.fly.dev
- https://fly.io/
- https://andybrewer.github.io/mvp/
-
こういうデータ https://celestrak.org/NORAD/elements/gp.php?CATNR=25544&FORMAT=tle ↩
-
こういうデータ https://celestrak.org/NORAD/elements/gp.php?CATNR=25544&FORMAT=json
(昔はこんな使いやすいのはなかったので、便利になっている) ↩