-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for orbital element based calculations
- Loading branch information
Showing
6 changed files
with
175 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/** | ||
* @file | ||
* | ||
* @date Created on Nov 13, 2024 | ||
* @author Attila Kovacs | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <errno.h> | ||
|
||
#define __NOVAS_INTERNAL_API__ ///< Use definitions meant for internal use by SuperNOVAS only | ||
#include "novas.h" | ||
|
||
/// \cond PRIVATE | ||
|
||
/// Required precision for the eccentric anomaly | ||
#define EPREC 1e-12 | ||
|
||
/// \endcond | ||
|
||
/** | ||
* Calculates a rectangular equatorial position and velocity vector for the given orbital elements for the | ||
* specified time of observation. | ||
* | ||
* REFERENCES: | ||
* <ol> | ||
* <li>https://en.wikipedia.org/wiki/Orbital_elements</li> | ||
* <li>https://downloads.rene-schwarz.com/download/M001-Keplerian_Orbit_Elements_to_Cartesian_State_Vectors.pdf</li> | ||
* <li>https://orbitalofficial.com/</li> | ||
* </ol> | ||
* | ||
* @param jd_tdb [day] Barycentric Dynamic Time (TDB) based Julian date | ||
* @param orb Orbital parameters | ||
* @param[out] pos [AU] Output position vector, or NULL if not required | ||
* @param[out] vel [AU/day] Output velocity vector, or NULL if not required | ||
* @return 0 if successful, or else -1 if the orbital parameters are NULL | ||
* or if the position and velocity output vectors are the same (errno set to EINVAL), | ||
* or if the calculation did not converge (errno set to ECANCELED). | ||
*/ | ||
int novas_orbit_posvel(double jd_tdb, const novas_orbital_elements *orb, double *pos, double *vel) { | ||
static const char *fn = "novas_orbit_posvel"; | ||
extern int novas_inv_max_iter; | ||
|
||
double dt, M, E, nu, r; | ||
double cO, sO, ci, si, co, so; | ||
double xx, yx, zx, xy, yy, zy; | ||
int i = novas_inv_max_iter; | ||
|
||
if(!orb) | ||
return novas_error(-1, EINVAL, fn, "input orbital elements is NULL"); | ||
|
||
if(pos == vel) | ||
return novas_error(-1, EINVAL, fn, "output pos = vel (@ %p)", pos); | ||
|
||
dt = jd_tdb - orb->jd_tdb; | ||
E = M = orb->M0 + orb->n * dt; | ||
|
||
while(--i >= 0) { | ||
double s = sin(E); | ||
double c = cos(E); | ||
double dE = (E - s - M) / (1.0 - c); | ||
E -= dE; | ||
|
||
if(fabs(dE) < EPREC) break; | ||
} | ||
|
||
if(i < 0) | ||
return novas_error(-1, ECANCELED, fn, "Eccentric anomaly convergence failure"); | ||
|
||
nu = 2.0 * atan2(sqrt(1.0 + orb->e) * sin(0.5 * E), sqrt(1.0 - orb->e) * cos(0.5 * E)); | ||
r = orb->a * (1.0 - orb->e * E); | ||
|
||
// pos = Rz(-Omega) . Rx(-i) . Rz(-omega) . orb | ||
cO = cos(orb->Omega); | ||
sO = sin(orb->Omega); | ||
ci = cos(orb->i); | ||
si = sin(orb->i); | ||
co = cos(orb->omega); | ||
so = sin(orb->omega); | ||
|
||
// Rotation matrix | ||
// See https://en.wikipedia.org/wiki/Euler_angles | ||
// (note the Wikipedia has opposite sign convention for angles...) | ||
xx = cO * co - sO * ci * so; | ||
yx = sO * co + cO * ci * so; | ||
zx = si * so; | ||
xy = -cO * so - sO * ci * co; | ||
yy = -sO * so + cO * ci * co; | ||
zy = si * co; | ||
|
||
if(pos) { | ||
double x = cos(nu); | ||
double y = sin(nu); | ||
|
||
// Perform rotation | ||
pos[0] = xx * x + xy * y; | ||
pos[1] = yx * x + yy * y; | ||
pos[2] = zx * x + zy * y; | ||
} | ||
|
||
if(vel) { | ||
double vt = orb->n / r; | ||
double x = -vt * sin(E); | ||
double y = vt * sqrt(1.0 - orb->e * orb->e) * cos(E); | ||
|
||
// Perform rotation | ||
vel[0] = xx * x + xy * y; | ||
vel[1] = yx * x + yy * y; | ||
vel[2] = zx * x + zy * y; | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters