Вычислительное решение уравнения Кеплера

Я пытаюсь решить уравнение Кеплера в качестве шага в направлении поиск истинной аномалии орбитального тела с учетом времени. Оказывается, уравнение Кеплера трудно решить, а страница Википедии описывает процесс с помощью calculus. Ну, я не знаю исчисления, но я понимаю, что решение уравнения включает бесконечное количество множеств, которые производят все более и более близкие приближения к правильному ответу.

I не могу видеть, глядя на математику, как сделать это вычислительно, поэтому я надеялся, что кто-то с лучшим математическим фоном может помочь мне. Как я могу вычислить этого зверя?

FWIW, я использую F# -- и я могу вычислить другие элементы, необходимые для этого уравнения, это только эта часть, с которой у меня проблемы.

Я также открыт для методов, которые приближаются к истинной аномалии с учетом времени, расстояния периапсиса и эксцентриситета

3 ответов


вы можете проверить это,реализовано в C# by Carl Johansen

Represents a body in elliptical orbit about a massive central body

вот комментарий из кода

истинной аномалией в этом контексте является угол между телом и солнцем. Для эллиптических орбит, это немного хитрый. Процент период завершенный все еще ключевой входной сигнал, но мы также необходимо применить Kepler уравнение (на основе эксцентриситета) чтобы мы были равны области в равных раз. Этот уравнение трансцендентально (т. е. не может решается алгебраически), поэтому мы либо придется использовать аппроксимацию уравнение или решить численным методом. Моя реализация использует Итерация Ньютона-Рафсона, чтобы получить отличный примерный ответ (обычно в 2 или 3 итерации).


эта статья:

практический метод решения уравнения Кеплера
http://murison.alpheratz.net/dynamics/twobody/KeplerIterations_summary.pdf

показывает, как решить уравнение Кеплера с помощью итерационного метода вычисления. Должно быть довольно просто перевести его на язык по вашему выбору.


можно найти это интересно. это программа ocaml, часть который утверждает, что содержит решатель уравнений Кеплера. Поскольку F# находится в семействе языков ML (как и ocaml), это может стать хорошей отправной точкой.


хотел бы оставить ответ здесь, Если эта страница будет найдена кем-либо еще, кто ищет аналогичные материалы.

следующее было написано как "выражение" в программном обеспечении After Effects Adobe, поэтому это javascriptish, хотя у меня есть версия Python для другого приложения (cinema 4d). Идея та же: выполнять метод Ньютона итеративно, пока не будет достигнута некоторая произвольная точность.

обратите внимание, что я не публикую этот код как примерный или значимый эффективный в любой способ, просто разместив код, который мы создали в срок для выполнения конкретной задачи (а именно, переместить планету вокруг фокуса в соответствии с законами Кеплера, и сделать это точно). Мы не пишем код для жизни, и поэтому мы также не публикуем это для критики. Quick & dirty-это то, что соответствует срокам.

в After Effects любой код "выражения" выполняется один раз для каждого кадра в анимации. Это ограничивает то, что можно сделать при реализации многих алгоритмы, из-за невозможности легко обращаться к глобальным данным (другие алгоритмы для движения Кеплера используют взаимно обновленные векторы скорости, подход, который мы не могли использовать). Результат, который оставляет код, - это [x,y] положение объекта в этот момент времени (внутренне это номер кадра), и код предназначен для присоединения к элементу положения слоя объекта на временной шкале.

этот код эволюционировал из материала, найденного в http://www.jgiesen.de/kepler/kepler.html и вот для следующего парня.

pi = Math.PI;
function EccAnom(ec,am,dp,_maxiter) { 
// ec=eccentricity, am=mean anomaly,
// dp=number of decimal places
    pi=Math.PI;
    i=0; 
    delta=Math.pow(10,-dp); 
    var E, F; 

    // some attempt to optimize prediction
    if (ec<0.8) {
        E=am;
    } else {
       E= am + Math.sin(am);
    }
    F = E - ec*Math.sin(E) - am; 
    while ((Math.abs(F)>delta) && (i<_maxiter)) {
        E = E - F/(1.0-(ec* Math.cos(E) )); 
        F = E - ec * Math.sin(E) - am; 
        i = i + 1;
    } 
    return Math.round(E*Math.pow(10,dp))/Math.pow(10,dp);
} 
function TrueAnom(ec,E,dp) { 
    S=Math.sin(E); 
    C=Math.cos(E); 
    fak=Math.sqrt(1.0-ec^2);

    phi = 2.0 * Math.atan(Math.sqrt((1.0+ec)/(1.0-ec))*Math.tan(E/2.0));
    return Math.round(phi*Math.pow(10,dp))/Math.pow(10,dp);
} 
function MeanAnom(time,_period) {
    curr_frame  = timeToFrames(time);
    if (curr_frame <= _period) {
        frames_done = curr_frame;
        if (frames_done < 1) frames_done = 1;
    } else {
        frames_done = curr_frame % _period;
    }
    _fractime = (frames_done * 1.0 ) / _period;
    mean_temp   = (2.0*Math.PI) * (-1.0 * _fractime);
    return mean_temp;
}
//==============================
// a=semimajor axis, ec=eccentricity, E=eccentric anomaly 
// delta = delta digits to exit, period = per., in frames
//----------------------------------------------------------
_eccen      = 0.9;              
_delta      = 14;
_maxiter    = 1000;                 
_period     = 300;          
_semi_a     = 70.0;
_semi_b     = _semi_a * Math.sqrt(1.0-_eccen^2); 
_meananom = MeanAnom(time,_period);
_eccentricanomaly = EccAnom(_eccen,_meananom,_delta,_maxiter);
_trueanomaly = TrueAnom(_eccen,_eccentricanomaly,_delta);
r = _semi_a * (1.0 - _eccen^2) / (1.0 + (_eccen*Math.cos(_trueanomaly)));
x = r * Math.cos(_trueanomaly);
y = r * Math.sin(_trueanomaly);
_foc=_semi_a*_eccen;
[1460+x+_foc,540+y];