ケプラー方程式をgo言語を使って反復計算法で解く

Shuntaro
9 min readDec 5, 2020

背景

go言語と宇宙工学の勉強のために、ケプラーの方程式を反復計算法(ニュートン ラフソン法)で解いてみます。

ケプラー方程式

まずケプラー方程式は、離心近点離角をE、平均近点離角をM、離心率e とした時に、

で表される方程式です。

地球を焦点とした衛星の楕円軌道を考えたときに以下の図でMとEを表せます。aは半長軸になります。

この方程式は普通の計算では解けず、ニュートン-ラフソン法のような反復方程式などによって解けます。

さて、この方程式を、

と定義すると、

と書くことができ、反復計算ができる形になります。(細かい導出方法はすっ飛ばしてます。参考文献の本に詳細に記述されています。)

golangで実装

では、ここからは実装していきます。

定数の設定

まずは定数を設定します。

// 地球の重力定数
const gravitationalConstant = 398600.4

平均近点離角Mを計算する関数

MeanAnomalyという名前で関数を作成します。

func MeanAnomaly(a, deltaT float64)float64{
return math.Sqrt(gravitationalConstant/math.Pow(a, 3)) * deltaT
}

aは半長軸(km)を表しており、deltaTは 元期 から求めたい瞬間の時刻の経過時間(秒)になります。

この関数によって平均点離角(radian)をreturnしています。

ケプラー方程式をクロージャとして定義

ケプラー方程式をクロージャとして定義し、後ほど反復法の関数にて利用していきます。

// ケプラー方程式
func KeplerEquation(e, M float64) func(Ebefore float64) float64{
return func(Ebefore float64)float64{
FE := Ebefore - e*math.Sin(Ebefore) - M
Eafter := Ebefore - FE/(1-e*math.Cos(Ebefore))
return Eafter
}
}

それぞれの引数は以下を表しています。

Ebefore:n回目の離心近点離角
M:平均近点離角
e:離心率
Eafter:n+1回目の離心近点離角

これらの引数を入力して宣言することで、return文に書いた関数を都度実行できるようになります。

反復計算法(ニュートン ラフソン法)

では上記で実装したケプラー方程式のクロージャをニュートン-ラフソン法で計算する関数を実装します。

許容誤差(ae)を引数として指定し、計算誤差が許容誤差よりも小さくなったら、forループを抜け、計算結果をreturnするようにしています。

// ケプラー方程式をニュートン-ラフソン法で解く
func NewtonRaphson(e, before, ae float64) float64 {
// ae: allowable error 許容誤差
equation := KeplerEquation(e, before)
var after float64
err := 100.0 // 誤差の初期化(0だとforが回らないため)
count := 0
for ; err > ae; {
after = equation(before)
err = math.Abs(after - before)
fmt.Println("誤差: ", err)
before = after
count = count + 1
fmt.Println("繰り返し:", count, "回目")
fmt.Println("----")
}
return after
}

main関数

ここまでで、必要な関数の定義は終わりです。

あとはmain関数で実際に使ってみて、正しい計算結果が得られるか確認してみます。

半長軸aを2000km、経過時間deltaTを3600秒、離心率eを0.75、許容誤差を0.0001として計算してみます。

func main() {
fmt.Println("ケプラー方程式を使って離心近点離角Eを求めます:")
M := MeanAnomaly(2000, 3600)
Mdigree := int(M * 180 / math.Pi) % 360
E := NewtonRaphson(0.75, M, 0.0001)
Edigree := int(E * 180 / math.Pi) % 360

Mrad := math.Round(M*100)/100
Erad := math.Round(E*100)/100
fmt.Printf("\n平均近点離角Mは %vrad、%v° です。", Mrad, Mdigree)
fmt.Printf("\n離心近点離角Eは %vrad、%v° です。", Erad, Edigree)
}

出力結果は

ケプラー方程式を使って離心近点離角Eを求めます:
誤差: 0.7393437287609679
繰り返し: 1 回目
----
誤差: 0.1667982273838291
繰り返し: 2 回目
----
誤差: 0.016917352484746573
繰り返し: 3 回目
----
誤差: 0.00016185780524580196
繰り返し: 4 回目
----
誤差: 1.4669140568912553e-08
繰り返し: 5 回目
----
平均近点離角Mは 25.41rad、15° です。
離心近点離角Eは 25.97rad、47° です。

となります。

下記のサイトによる計算結果と比較してみると、少しの計算誤差はあるものの、ほぼ正しく計算できていることが分かります。

コード全体

以下にコード全体を残しておきます。

package main
import (
"fmt"
"math"
)
// 地球の重力定数
const gravitationalConstant = 398600.4
// 平均近点離角
func MeanAnomaly(a, deltaT float64)float64{
return math.Sqrt(gravitationalConstant/math.Pow(a, 3)) * deltaT
}
// ケプラー方程式
func KeplerEquation(e, M float64) func(Ebefore float64) float64{
// Ebefore: n回目の離心近点離角
// M: 平均近点離角
// e: 離心率
// Eafter: n+1回目の離心近点離角
return func(Ebefore float64)float64{
FE := Ebefore - e*math.Sin(Ebefore) - M
Eafter := Ebefore - FE/(1-e*math.Cos(Ebefore))
return Eafter
}
}
// ケプラー方程式をニュートン-ラフソン法で解く
func NewtonRaphson(e, before, a float64) float64 {
// M: 平均近点離角
// e: 離心率
// a: allowable error 許容誤差
equation := KeplerEquation(e, before)
var after float64
err := 100.0 // 許容誤差の初期化(0だとforが回らないため)
count := 0
for ; err > a; {
after = equation(before)
err = math.Abs(after - before)
fmt.Println("誤差: ", err)
before = after
count = count + 1
fmt.Println("繰り返し:", count, "回目")
fmt.Println("----")
}
return after
}

func main() {
fmt.Println("ケプラー方程式を使って離心近点離角Eを求めます:")
M := MeanAnomaly(2000, 3600)
Mdigree := int(M * 180 / math.Pi) % 360
E := NewtonRaphson(0.75, M, 0.0001)
Edigree := int(E * 180 / math.Pi) % 360

Mrad := math.Round(M*100)/100
Erad := math.Round(E*100)/100
fmt.Printf("\n平均近点離角Mは %vrad、%v° です。", Mrad, Mdigree)
fmt.Printf("\n離心近点離角Eは %vrad、%v° です。", Erad, Edigree)
}

参考文献

以下の本で理論を参考にしました。

https://www.amazon.co.jp/exec/obidos/ASIN/4768704395/detethcotaf-22/

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response