科学と家事とプログラミング (python を中心に)

python 温度計測 湿度計測 DS18B20 USB9097

座標変換ルーチンの爆発的な増殖は、なんとしても避けたいのです

問題設定

天文宇宙に関連したアプリケーションでは、多くの座標系が登場します。 黄道座標系、地球赤道座標系、地球固定座標系、月固定座標系、などなど。 さらに、赤道座標系や黄道座標系には、分点の違いによって、 基準エポック、平均分点(MOD)、真分点(TOD) といった区別もあります。

いくつも座標系がある状況で、相互の座標変換ルーチンを場当たり的に用意しはじめると、 座標変換ルーチンばかりが増えていきます。いわゆる、組み合わせ論的に爆発ですね。 こういう事態は、なんとしても避けねばなりません。

解決案

こういうときは、以下の指針が有効です。

  • 基準座標を定める
  • 各座標系と基準座標系との変換だけ用意する
  • 相互の変換は必ず基準座標経由で実施する

以下、オブジェクト指向的な実装の例を示します。 (座標系 R を基準座標として、座標系 A, B, を実装する)

class Frame:
    def __init__(self, t):
        """ 生成時に時刻を指定して座標変換行列を固定する """
        self.sys_fm_ref = None # sys_fm_ref は、基準座標からの座標変換行列
        
    def _from(self, other):                  # self が A, other が B なら
         """ 座標系 other から self への座標変換行列 """
        sys_fm_ref = self.sys_fm_ref         # A <== R
        ref_fm_oth = other.sys_fm_ref.tran() # R <== B  (B<==R を転置)
        sys_fm_oth = sys_fm_ref*ref_fm_oth
        return sys_fm_oth
        
class R:
    def __init__(self):
        # 基準座標から基準座標への変換は、単位行列
        self.sys_fm_ref = mat([[1, 0, 0], [0, 1, 0], [0, 0, 1]])

class A:
    def __init__(self, t):
        """ 基準座標からの座標変換行列 """
        self.sys_fm_ref = rotx(1.0*t) # 適当

class B:
    def __init__(self, t):
        """ 基準座標からの座標変換行列 """
        self.sys_fm_ref = roty(1.0*t) # 適当

def test():
    t = 0.0
    a_fm_b = A(t)._from(B(t)) # A <== B  座標回転行列

新たに座標系 C を追加したいときは、class C を準備するだけで、 すでに存在する全ての座標系との変換行列が手に入ります。

c_fm_a = C(t)._from(A(t))
c_fm_b = C(t)._from(B(t))
c_fm_r = C(t)._from(R())
a_fm_c = A(t)._from(C(t)) 
b_fm_c = B(t)._from(C(t)) 
r_fm_c = R()._from(C(t)) 

利点

これで、座標変換ルーチンの組み合わせ論的な爆発を防ぐことができます。 検証の面でも有利でしょう。

欠点

倍精度の限界のような高精度が求められる場合には、こういう方式では対応できない 場合があります。性能(実行速度)面は、まったく考慮していません。

捕捉

基準座標の R は、例えば J2000.0 EQ や ICRF などを割り当てます。 座標系の数が増えれば増えるほど、この設計の有難味が増します。 時刻系の変換ルーチンについても、同じような方針を適用できます。

f:id:sken20k:20180324202958j:plain

コード中、fm は from の略です。 座標回転の結合は、a_fm_c = a_fm_b * b_fm_c という感じ記述できます。何がよいかというと、 * の前後に現れる座標系が同じである確認した上で(斜線で)消去する操作を、プログラムコードで直接表現できます。 座標系の変換でよくある変換の向きの間違いを、ソースコードの形式的な工夫によって減らすことを狙ってます。