Kotlin: barycentric states, geocentric moon/EMB

Added geoEmbState: calculates the geocentric
state vector of the Earth/Moon Barycenter (EMB).

Added baryState: calculates the barycentric
state vector of a body.

Unit tests now support parsing JPL Horizons
state vector text files.
This commit is contained in:
Don Cross
2022-04-16 15:31:25 -04:00
parent d5fc878a6a
commit 0ed52f3cea
8 changed files with 332 additions and 1 deletions

View File

@@ -2797,6 +2797,15 @@ internal class BodyState(
}
}
private fun exportState(bodyState: BodyState, time: Time) =
StateVector(
bodyState.r.x, bodyState.r.y, bodyState.r.z,
bodyState.v.x, bodyState.v.y, bodyState.v.z,
time
)
private fun calcVsopPosVel(model: VsopModel, tt: Double): BodyState {
val t = tt / DAYS_PER_MILLENNIUM
@@ -4358,6 +4367,22 @@ fun geoMoonState(time: Time): StateVector {
)
}
/**
* Calculates the geocentric position and velocity of the Earth/Moon barycenter.
*
* Given a time of observation, calculates the geocentric position and velocity vectors
* of the Earth/Moon barycenter (EMB).
* The position (x, y, z) components are expressed in AU (astronomical units).
* The velocity (vx, vy, vz) components are expressed in AU/day.
*
* @param time
* The date and time for which to calculate the EMB vectors.
*
* @return The EMB's position and velocity vectors in geocentric J2000 equatorial coordinates.
*/
fun geoEmbState(time: Time): StateVector =
geoMoonState(time) / (1.0 + EARTH_MOON_MASS_RATIO)
private fun helioEarthPos(time: Time) =
calcVsop(vsopModel(Body.Earth), time)
@@ -4508,6 +4533,63 @@ fun helioState(body: Body, time: Time): StateVector =
else -> throw InvalidBodyException(body)
}
/**
* Calculates barycentric position and velocity vectors for the given body.
*
* Given a body and a time, calculates the barycentric position and velocity
* vectors for the center of that body at that time.
* The vectors are expressed in equatorial J2000 coordinates (EQJ).
*
* @param body
* The celestial body whose barycentric state vector is to be calculated.
* Supported values are `Body.Sun`, `Body.Moon`, `Body.EMB`, `Body.SSB`, and all planets:
* `Body.Mercury`, `Body.Venus`, `Body.Earth`, `Body.Mars`, `Body.Jupiter`,
* `Body.Saturn`, `Body.Uranus`, `Body.Neptune`, `Body.Pluto`.
*
* @param time
* The date and time for which to calculate position and velocity.
*
* @return The barycentric position and velocity vectors of the body.
*/
fun baryState(body: Body, time: Time): StateVector {
// Trival case: the solar system barycenter itself:
if (body == Body.SSB)
return StateVector(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, time)
if (body == Body.Pluto)
return calcPluto(time, false)
// Find the barycentric positions and velocities for the 5 major bodies.
val bary = majorBodyBary(time.tt)
return when (body) {
// If the caller is asking for one of the major bodies, we already have the answer.
Body.Sun -> exportState(bary.sun, time)
Body.Jupiter -> exportState(bary.jupiter, time)
Body.Saturn -> exportState(bary.saturn, time)
Body.Uranus -> exportState(bary.uranus, time)
Body.Neptune -> exportState(bary.neptune, time)
// The Moon and EMB require calculating both the heliocentric Earth and geocentric Moon.
Body.Moon -> exportState(bary.sun, time) + helioEarthState(time) + geoMoonState(time)
Body.EMB -> exportState(bary.sun, time) + helioEarthState(time) + geoEmbState(time)
else -> {
val planet: BodyState = calcVsopPosVel(vsopModel(body), time.tt)
StateVector(
bary.sun.r.x + planet.r.x,
bary.sun.r.y + planet.r.y,
bary.sun.r.z + planet.r.z,
bary.sun.v.x + planet.v.x,
bary.sun.v.y + planet.v.y,
bary.sun.v.z + planet.v.z,
time
)
}
}
}
/**
* Calculates geocentric Cartesian coordinates of a body in the J2000 equatorial system.
*

View File

@@ -106,12 +106,14 @@ these are used in function and type names.
| Name | Summary |
|---|---|
| [angleFromSun](doc/angle-from-sun.md) | [jvm]<br>fun [angleFromSun](doc/angle-from-sun.md)(body: [Body](doc/-body/index.md), time: [Time](doc/-time/index.md)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>Returns the angle between the given body and the Sun, as seen from the Earth. |
| [baryState](doc/bary-state.md) | [jvm]<br>fun [baryState](doc/bary-state.md)(body: [Body](doc/-body/index.md), time: [Time](doc/-time/index.md)): [StateVector](doc/-state-vector/index.md)<br>Calculates barycentric position and velocity vectors for the given body. |
| [constellation](doc/constellation.md) | [jvm]<br>fun [constellation](doc/constellation.md)(ra: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dec: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [ConstellationInfo](doc/-constellation-info/index.md)<br>Determines the constellation that contains the given point in the sky. |
| [degreesToRadians](doc/degrees-to-radians.md) | [jvm]<br>fun [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html).[degreesToRadians](doc/degrees-to-radians.md)(): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>Convert an angle expressed in degrees to an angle expressed in radians. |
| [eclipticGeoMoon](doc/ecliptic-geo-moon.md) | [jvm]<br>fun [eclipticGeoMoon](doc/ecliptic-geo-moon.md)(time: [Time](doc/-time/index.md)): [Spherical](doc/-spherical/index.md)<br>Calculates spherical ecliptic geocentric position of the Moon. |
| [eclipticLongitude](doc/ecliptic-longitude.md) | [jvm]<br>fun [eclipticLongitude](doc/ecliptic-longitude.md)(body: [Body](doc/-body/index.md), time: [Time](doc/-time/index.md)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>Calculates heliocentric ecliptic longitude of a body based on the J2000 equinox. |
| [equator](doc/equator.md) | [jvm]<br>fun [equator](doc/equator.md)(body: [Body](doc/-body/index.md), time: [Time](doc/-time/index.md), observer: [Observer](doc/-observer/index.md), equdate: [EquatorEpoch](doc/-equator-epoch/index.md), aberration: [Aberration](doc/-aberration/index.md)): [Equatorial](doc/-equatorial/index.md)<br>Calculates equatorial coordinates of a celestial body as seen by an observer on the Earth's surface. |
| [equatorialToEcliptic](doc/equatorial-to-ecliptic.md) | [jvm]<br>fun [equatorialToEcliptic](doc/equatorial-to-ecliptic.md)(equ: [Vector](doc/-vector/index.md)): [Ecliptic](doc/-ecliptic/index.md)<br>Converts J2000 equatorial Cartesian coordinates to J2000 ecliptic coordinates. |
| [geoEmbState](doc/geo-emb-state.md) | [jvm]<br>fun [geoEmbState](doc/geo-emb-state.md)(time: [Time](doc/-time/index.md)): [StateVector](doc/-state-vector/index.md)<br>Calculates the geocentric position and velocity of the Earth/Moon barycenter. |
| [geoMoon](doc/geo-moon.md) | [jvm]<br>fun [geoMoon](doc/geo-moon.md)(time: [Time](doc/-time/index.md)): [Vector](doc/-vector/index.md)<br>Calculates equatorial geocentric position of the Moon at a given time. |
| [geoMoonState](doc/geo-moon-state.md) | [jvm]<br>fun [geoMoonState](doc/geo-moon-state.md)(time: [Time](doc/-time/index.md)): [StateVector](doc/-state-vector/index.md)<br>Calculates equatorial geocentric position and velocity of the Moon at a given time. |
| [geoVector](doc/geo-vector.md) | [jvm]<br>fun [geoVector](doc/geo-vector.md)(body: [Body](doc/-body/index.md), time: [Time](doc/-time/index.md), aberration: [Aberration](doc/-aberration/index.md)): [Vector](doc/-vector/index.md)<br>Calculates geocentric Cartesian coordinates of a body in the J2000 equatorial system. |

View File

@@ -0,0 +1,23 @@
//[astronomy](../../index.md)/[io.github.cosinekitty.astronomy](index.md)/[baryState](bary-state.md)
# baryState
[jvm]\
fun [baryState](bary-state.md)(body: [Body](-body/index.md), time: [Time](-time/index.md)): [StateVector](-state-vector/index.md)
Calculates barycentric position and velocity vectors for the given body.
Given a body and a time, calculates the barycentric position and velocity vectors for the center of that body at that time. The vectors are expressed in equatorial J2000 coordinates (EQJ).
#### Return
The barycentric position and velocity vectors of the body.
## Parameters
jvm
| | |
|---|---|
| body | The celestial body whose barycentric state vector is to be calculated. Supported values are `Body.Sun`, `Body.Moon`, `Body.EMB`, `Body.SSB`, and all planets: `Body.Mercury`, `Body.Venus`, `Body.Earth`, `Body.Mars`, `Body.Jupiter`, `Body.Saturn`, `Body.Uranus`, `Body.Neptune`, `Body.Pluto`. |
| time | The date and time for which to calculate position and velocity. |

View File

@@ -0,0 +1,22 @@
//[astronomy](../../index.md)/[io.github.cosinekitty.astronomy](index.md)/[geoEmbState](geo-emb-state.md)
# geoEmbState
[jvm]\
fun [geoEmbState](geo-emb-state.md)(time: [Time](-time/index.md)): [StateVector](-state-vector/index.md)
Calculates the geocentric position and velocity of the Earth/Moon barycenter.
Given a time of observation, calculates the geocentric position and velocity vectors of the Earth/Moon barycenter (EMB). The position (x, y, z) components are expressed in AU (astronomical units). The velocity (vx, vy, vz) components are expressed in AU/day.
#### Return
The EMB's position and velocity vectors in geocentric J2000 equatorial coordinates.
## Parameters
jvm
| | |
|---|---|
| time | The date and time for which to calculate the EMB vectors. |

View File

@@ -7,7 +7,7 @@ fun [helioState](helio-state.md)(body: [Body](-body/index.md), time: [Time](-tim
Calculates heliocentric position and velocity vectors for the given body.
Given a body and a time, calculates the position and velocity vectors for the center of that body at that time, relative to the center of the Sun. The vectors are expressed in equatorial J2000 coordinates (EQJ). If you need the position vector only, it is more efficient to call [helioVector](helio-vector.md). The Sun's center is a non-inertial frame of reference. In other words, the Sun experiences acceleration due to gravitational forces, mostly from the larger planets (Jupiter, Saturn, Uranus, and Neptune). If you want to calculate momentum, kinetic energy, or other quantities that require a non-accelerating frame of reference, consider using baryState instead.
Given a body and a time, calculates the position and velocity vectors for the center of that body at that time, relative to the center of the Sun. The vectors are expressed in equatorial J2000 coordinates (EQJ). If you need the position vector only, it is more efficient to call [helioVector](helio-vector.md). The Sun's center is a non-inertial frame of reference. In other words, the Sun experiences acceleration due to gravitational forces, mostly from the larger planets (Jupiter, Saturn, Uranus, and Neptune). If you want to calculate momentum, kinetic energy, or other quantities that require a non-accelerating frame of reference, consider using [baryState](bary-state.md) instead.
#### Return

View File

@@ -51,12 +51,14 @@
| Name | Summary |
|---|---|
| [angleFromSun](angle-from-sun.md) | [jvm]<br>fun [angleFromSun](angle-from-sun.md)(body: [Body](-body/index.md), time: [Time](-time/index.md)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>Returns the angle between the given body and the Sun, as seen from the Earth. |
| [baryState](bary-state.md) | [jvm]<br>fun [baryState](bary-state.md)(body: [Body](-body/index.md), time: [Time](-time/index.md)): [StateVector](-state-vector/index.md)<br>Calculates barycentric position and velocity vectors for the given body. |
| [constellation](constellation.md) | [jvm]<br>fun [constellation](constellation.md)(ra: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), dec: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [ConstellationInfo](-constellation-info/index.md)<br>Determines the constellation that contains the given point in the sky. |
| [degreesToRadians](degrees-to-radians.md) | [jvm]<br>fun [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html).[degreesToRadians](degrees-to-radians.md)(): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>Convert an angle expressed in degrees to an angle expressed in radians. |
| [eclipticGeoMoon](ecliptic-geo-moon.md) | [jvm]<br>fun [eclipticGeoMoon](ecliptic-geo-moon.md)(time: [Time](-time/index.md)): [Spherical](-spherical/index.md)<br>Calculates spherical ecliptic geocentric position of the Moon. |
| [eclipticLongitude](ecliptic-longitude.md) | [jvm]<br>fun [eclipticLongitude](ecliptic-longitude.md)(body: [Body](-body/index.md), time: [Time](-time/index.md)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)<br>Calculates heliocentric ecliptic longitude of a body based on the J2000 equinox. |
| [equator](equator.md) | [jvm]<br>fun [equator](equator.md)(body: [Body](-body/index.md), time: [Time](-time/index.md), observer: [Observer](-observer/index.md), equdate: [EquatorEpoch](-equator-epoch/index.md), aberration: [Aberration](-aberration/index.md)): [Equatorial](-equatorial/index.md)<br>Calculates equatorial coordinates of a celestial body as seen by an observer on the Earth's surface. |
| [equatorialToEcliptic](equatorial-to-ecliptic.md) | [jvm]<br>fun [equatorialToEcliptic](equatorial-to-ecliptic.md)(equ: [Vector](-vector/index.md)): [Ecliptic](-ecliptic/index.md)<br>Converts J2000 equatorial Cartesian coordinates to J2000 ecliptic coordinates. |
| [geoEmbState](geo-emb-state.md) | [jvm]<br>fun [geoEmbState](geo-emb-state.md)(time: [Time](-time/index.md)): [StateVector](-state-vector/index.md)<br>Calculates the geocentric position and velocity of the Earth/Moon barycenter. |
| [geoMoon](geo-moon.md) | [jvm]<br>fun [geoMoon](geo-moon.md)(time: [Time](-time/index.md)): [Vector](-vector/index.md)<br>Calculates equatorial geocentric position of the Moon at a given time. |
| [geoMoonState](geo-moon-state.md) | [jvm]<br>fun [geoMoonState](geo-moon-state.md)(time: [Time](-time/index.md)): [StateVector](-state-vector/index.md)<br>Calculates equatorial geocentric position and velocity of the Moon at a given time. |
| [geoVector](geo-vector.md) | [jvm]<br>fun [geoVector](geo-vector.md)(body: [Body](-body/index.md), time: [Time](-time/index.md), aberration: [Aberration](-aberration/index.md)): [Vector](-vector/index.md)<br>Calculates geocentric Cartesian coordinates of a body in the J2000 equatorial system. |

View File

@@ -2797,6 +2797,15 @@ internal class BodyState(
}
}
private fun exportState(bodyState: BodyState, time: Time) =
StateVector(
bodyState.r.x, bodyState.r.y, bodyState.r.z,
bodyState.v.x, bodyState.v.y, bodyState.v.z,
time
)
private fun calcVsopPosVel(model: VsopModel, tt: Double): BodyState {
val t = tt / DAYS_PER_MILLENNIUM
@@ -4358,6 +4367,22 @@ fun geoMoonState(time: Time): StateVector {
)
}
/**
* Calculates the geocentric position and velocity of the Earth/Moon barycenter.
*
* Given a time of observation, calculates the geocentric position and velocity vectors
* of the Earth/Moon barycenter (EMB).
* The position (x, y, z) components are expressed in AU (astronomical units).
* The velocity (vx, vy, vz) components are expressed in AU/day.
*
* @param time
* The date and time for which to calculate the EMB vectors.
*
* @return The EMB's position and velocity vectors in geocentric J2000 equatorial coordinates.
*/
fun geoEmbState(time: Time): StateVector =
geoMoonState(time) / (1.0 + EARTH_MOON_MASS_RATIO)
private fun helioEarthPos(time: Time) =
calcVsop(vsopModel(Body.Earth), time)
@@ -4508,6 +4533,63 @@ fun helioState(body: Body, time: Time): StateVector =
else -> throw InvalidBodyException(body)
}
/**
* Calculates barycentric position and velocity vectors for the given body.
*
* Given a body and a time, calculates the barycentric position and velocity
* vectors for the center of that body at that time.
* The vectors are expressed in equatorial J2000 coordinates (EQJ).
*
* @param body
* The celestial body whose barycentric state vector is to be calculated.
* Supported values are `Body.Sun`, `Body.Moon`, `Body.EMB`, `Body.SSB`, and all planets:
* `Body.Mercury`, `Body.Venus`, `Body.Earth`, `Body.Mars`, `Body.Jupiter`,
* `Body.Saturn`, `Body.Uranus`, `Body.Neptune`, `Body.Pluto`.
*
* @param time
* The date and time for which to calculate position and velocity.
*
* @return The barycentric position and velocity vectors of the body.
*/
fun baryState(body: Body, time: Time): StateVector {
// Trival case: the solar system barycenter itself:
if (body == Body.SSB)
return StateVector(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, time)
if (body == Body.Pluto)
return calcPluto(time, false)
// Find the barycentric positions and velocities for the 5 major bodies.
val bary = majorBodyBary(time.tt)
return when (body) {
// If the caller is asking for one of the major bodies, we already have the answer.
Body.Sun -> exportState(bary.sun, time)
Body.Jupiter -> exportState(bary.jupiter, time)
Body.Saturn -> exportState(bary.saturn, time)
Body.Uranus -> exportState(bary.uranus, time)
Body.Neptune -> exportState(bary.neptune, time)
// The Moon and EMB require calculating both the heliocentric Earth and geocentric Moon.
Body.Moon -> exportState(bary.sun, time) + helioEarthState(time) + geoMoonState(time)
Body.EMB -> exportState(bary.sun, time) + helioEarthState(time) + geoEmbState(time)
else -> {
val planet: BodyState = calcVsopPosVel(vsopModel(body), time.tt)
StateVector(
bary.sun.r.x + planet.r.x,
bary.sun.r.y + planet.r.y,
bary.sun.r.z + planet.r.z,
bary.sun.v.x + planet.v.x,
bary.sun.v.y + planet.v.y,
bary.sun.v.z + planet.v.z,
time
)
}
}
}
/**
* Calculates geocentric Cartesian coordinates of a body in the J2000 equatorial system.
*

View File

@@ -1429,5 +1429,123 @@ class Tests {
assertTrue(diff < 1.0e-16, "excessive ecliptic longitude error for $body: $diff degrees")
}
//----------------------------------------------------------------------------------------
// Generic utility function for loading a series of state vectors
// from a JPL Horizons output file.
private class JplStateRecord(
val lnum: Int, // the line number where the state vector ends in the JPL Horizons text file
val state: StateVector // the state vector itself: position, velocity, and time
)
private fun jplHorizonsStateVectors(filename: String): List<JplStateRecord> {
val infile = File(filename)
var lnum = 0
var foundBegin = false
var part = 0
var time: Time? = null
val pos = arrayOf(0.0, 0.0, 0.0)
val vel = arrayOf(0.0, 0.0, 0.0)
var list = ArrayList<JplStateRecord>()
var match: MatchResult?
val regexPos = Regex("""\s*X =\s*(\S+) Y =\s*(\S+) Z =\s*(\S+)""")
val regexVel = Regex("""\s*VX=\s*(\S+) VY=\s*(\S+) VZ=\s*(\S+)""")
for (line in infile.readLines()) {
++lnum
if (!foundBegin) {
if (line == "\$\$SOE")
foundBegin = true
} else {
// Input comes in triplets of lines:
//
// 2444249.500000000 = A.D. 1980-Jan-11 00:00:00.0000 TDB
// X =-3.314860345089456E-01 Y = 8.463418210972562E-01 Z = 3.667227830514760E-01
// VX=-1.642704711077836E-02 VY=-5.494770742558920E-03 VZ=-2.383170237527642E-03
//
// Track which of these 3 cases we are in using the 'part' variable...
when (part) {
0 -> {
if (line == "\$\$EOE") // end-of-data marker: the list is complete.
return list
// 2444249.500000000 = A.D. 1980-Jan-11 00:00:00.0000 TDB
// Convert JD to J2000 TT.
val tt = tokenize(line)[0].toDouble() - 2451545.0
time = Time.fromTerrestrialTime(tt)
}
1 -> {
match = regexPos.matchEntire(line)
assertTrue(match != null, "$filename line $lnum: cannot parse position vector")
pos[0] = groupDouble(match, 1, filename, lnum)
pos[1] = groupDouble(match, 2, filename, lnum)
pos[2] = groupDouble(match, 3, filename, lnum)
}
2 -> {
match = regexVel.matchEntire(line)
assertTrue(match != null, "$filename line $lnum: cannot parse velocity vector")
vel[0] = groupDouble(match, 1, filename, lnum)
vel[1] = groupDouble(match, 2, filename, lnum)
vel[2] = groupDouble(match, 3, filename, lnum)
assertTrue(time != null, "$filename line $lnum: time value was never parsed")
val state = StateVector(pos[0], pos[1], pos[2], vel[0], vel[1], vel[2], time)
list.add(JplStateRecord(lnum, state))
time = null
}
else -> fail("$filename line $lnum: invalid part=$part")
}
part = (part + 1) % 3
}
}
fail("$filename: never found end-of-data marker")
}
private fun stateVectorDiff(relative: Boolean, expected: Vector, calculated: Vector): Double {
val diff = (expected - calculated).length()
return if (relative)
diff / expected.length()
else
diff
}
private fun verifyStateBody(
relativeFileName: String,
rThresh: Double,
vThresh: Double,
func: (Time) -> StateVector
) {
var filename = dataRootDir + relativeFileName
for (rec in jplHorizonsStateVectors(filename)) {
val state = func(rec.state.t)
val rdiff = stateVectorDiff(rThresh > 0.0, rec.state.position(), state.position())
val vdiff = stateVectorDiff(vThresh > 0.0, rec.state.velocity(), state.velocity())
assertTrue(rdiff < abs(rThresh), "$filename line ${rec.lnum}: excessive position error = $rdiff")
assertTrue(vdiff < abs(vThresh), "$filename line ${rec.lnum}: excessive velocity error = $vdiff")
}
}
//----------------------------------------------------------------------------------------
@Test
fun `Barycentric state vectors`() {
verifyStateBody("barystate/Sun.txt", -1.224e-05, -1.134e-07) { time -> baryState(Body.Sun, time) }
verifyStateBody("barystate/Mercury.txt", 1.672e-04, 2.698e-04) { time -> baryState(Body.Mercury, time) }
verifyStateBody("barystate/Venus.txt", 4.123e-05, 4.308e-05) { time -> baryState(Body.Venus, time) }
verifyStateBody("barystate/Earth.txt", 2.296e-05, 6.359e-05) { time -> baryState(Body.Earth, time) }
verifyStateBody("barystate/Mars.txt", 3.107e-05, 5.550e-05) { time -> baryState(Body.Mars, time) }
verifyStateBody("barystate/Jupiter.txt", 7.389e-05, 2.471e-04) { time -> baryState(Body.Jupiter, time) }
verifyStateBody("barystate/Saturn.txt", 1.067e-04, 3.220e-04) { time -> baryState(Body.Saturn, time) }
verifyStateBody("barystate/Uranus.txt", 9.035e-05, 2.519e-04) { time -> baryState(Body.Uranus, time) }
verifyStateBody("barystate/Neptune.txt", 9.838e-05, 4.446e-04) { time -> baryState(Body.Neptune, time) }
verifyStateBody("barystate/Pluto.txt", 4.259e-05, 7.827e-05) { time -> baryState(Body.Pluto, time) }
verifyStateBody("barystate/Moon.txt", 2.354e-05, 6.604e-05) { time -> baryState(Body.Moon, time) }
verifyStateBody("barystate/EMB.txt", 2.353e-05, 6.511e-05) { time -> baryState(Body.EMB, time) }
}
@Test
fun `Geocentric state vectors`() {
verifyStateBody("barystate/GeoMoon.txt", 4.086e-05, 5.347e-05) { time -> geoMoonState(time) }
verifyStateBody("barystate/GeoEMB.txt", 4.076e-05, 5.335e-05) { time -> geoEmbState(time) }
}
//----------------------------------------------------------------------------------------
}