From 7ade492a40e33483f944ccf6a9ae7cbd3f685aa6 Mon Sep 17 00:00:00 2001 From: Helge Eichhorn Date: Thu, 19 Dec 2024 10:19:57 +0100 Subject: [PATCH] refactor: prefer `Result` over `Option` for `Origin` props --- crates/lox-bodies/src/generated.rs | 544 +++++++++--------- crates/lox-bodies/src/lib.rs | 107 ++-- crates/lox-bodies/src/python.rs | 71 ++- crates/lox-orbits/src/analysis.rs | 4 +- crates/lox-orbits/src/elements.rs | 18 +- crates/lox-orbits/src/frames/iau.rs | 4 +- crates/lox-orbits/src/ground.rs | 14 +- .../src/propagators/semi_analytical.rs | 12 +- crates/lox-orbits/src/python.rs | 4 +- crates/lox-orbits/src/states.rs | 15 +- tools/lox-gen/src/common.rs | 13 +- tools/lox-gen/src/origins.rs | 69 ++- 12 files changed, 486 insertions(+), 389 deletions(-) diff --git a/crates/lox-bodies/src/generated.rs b/crates/lox-bodies/src/generated.rs index 521adbd0..1535812d 100644 --- a/crates/lox-bodies/src/generated.rs +++ b/crates/lox-bodies/src/generated.rs @@ -10,10 +10,6 @@ use crate::DynOrigin; use crate::Elements; -use crate::MaybeMeanRadius; -use crate::MaybePointMass; -use crate::MaybeSpheroid; -use crate::MaybeTriaxialEllipsoid; use crate::MeanRadius; use crate::NaifId; use crate::NutationPrecessionCoefficients; @@ -25,8 +21,12 @@ use crate::RotationalElementType; use crate::RotationalElements; use crate::Spheroid; use crate::TriaxialEllipsoid; +use crate::TryMeanRadius; +use crate::TryPointMass; use crate::TryRotationalElements; -use crate::UndefinedRotationalElementsError; +use crate::TrySpheroid; +use crate::TryTriaxialEllipsoid; +use crate::UndefinedOriginPropertyError; use std::fmt::Display; use std::fmt::Formatter; #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -8725,277 +8725,283 @@ const NUTATION_PRECESSION_NEPTUNE: NutationPrecessionCoefficients<17usize> = 8.21777806326018f64, ], }; -impl MaybePointMass for DynOrigin { - fn maybe_gravitational_parameter(&self) -> Option { +impl TryPointMass for DynOrigin { + fn try_gravitational_parameter(&self) -> Result { match self { - DynOrigin::Sun => Some(132712440041.27942f64), - DynOrigin::Mercury => Some(22031.868551400003f64), - DynOrigin::Venus => Some(324858.592f64), - DynOrigin::Earth => Some(398600.43550702266f64), - DynOrigin::Mars => Some(42828.37362069909f64), - DynOrigin::Jupiter => Some(126686531.9003704f64), - DynOrigin::Saturn => Some(37931206.23436167f64), - DynOrigin::Uranus => Some(5793951.256527211f64), - DynOrigin::Neptune => Some(6835103.145462294f64), - DynOrigin::Pluto => Some(869.6138177608748f64), - DynOrigin::SolarSystemBarycenter => Some(132712440041.27942f64), - DynOrigin::MercuryBarycenter => Some(22031.868551400003f64), - DynOrigin::VenusBarycenter => Some(324858.592f64), - DynOrigin::EarthBarycenter => Some(403503.2356254802f64), - DynOrigin::MarsBarycenter => Some(42828.3758157561f64), - DynOrigin::JupiterBarycenter => Some(126712764.09999998f64), - DynOrigin::SaturnBarycenter => Some(37940584.8418f64), - DynOrigin::UranusBarycenter => Some(5794556.3999999985f64), - DynOrigin::NeptuneBarycenter => Some(6836527.100580399f64), - DynOrigin::PlutoBarycenter => Some(975.5f64), - DynOrigin::Moon => Some(4902.80011845755f64), - DynOrigin::Phobos => Some(0.0007087546066894452f64), - DynOrigin::Deimos => Some(0.00009615569648120313f64), - DynOrigin::Io => Some(5959.915466180539f64), - DynOrigin::Europa => Some(3202.712099607295f64), - DynOrigin::Ganymede => Some(9887.832752719638f64), - DynOrigin::Callisto => Some(7179.283402579837f64), - DynOrigin::Amalthea => Some(0.1645634534798259f64), - DynOrigin::Himalia => Some(0.1515524299611265f64), - DynOrigin::Thebe => Some(0.030148f64), - DynOrigin::Adrastea => Some(0.000139f64), - DynOrigin::Metis => Some(0.002501f64), - DynOrigin::Mimas => Some(2.503488768152587f64), - DynOrigin::Enceladus => Some(7.210366688598896f64), - DynOrigin::Tethys => Some(41.21352885489587f64), - DynOrigin::Dione => Some(73.11607172482067f64), - DynOrigin::Rhea => Some(153.9417519146563f64), - DynOrigin::Titan => Some(8978.137095521046f64), - DynOrigin::Hyperion => Some(0.3704913747932265f64), - DynOrigin::Iapetus => Some(120.5151060137642f64), - DynOrigin::Phoebe => Some(0.5547860052791678f64), - DynOrigin::Janus => Some(0.1265765099012197f64), - DynOrigin::Epimetheus => Some(0.03512333288208074f64), - DynOrigin::Helene => Some(0.0004757419551776972f64), - DynOrigin::Atlas => Some(0.0003718871247516475f64), - DynOrigin::Prometheus => Some(0.0107520800100761f64), - DynOrigin::Pandora => Some(0.009290325122028795f64), - DynOrigin::Ariel => Some(83.46344431770477f64), - DynOrigin::Umbriel => Some(85.09338094489388f64), - DynOrigin::Titania => Some(226.9437003741248f64), - DynOrigin::Oberon => Some(205.3234302535623f64), - DynOrigin::Miranda => Some(4.3195168992321f64), - DynOrigin::Triton => Some(1428.495462910464f64), - DynOrigin::Naiad => Some(0.008530281246540886f64), - DynOrigin::Thalassa => Some(0.0235887319799217f64), - DynOrigin::Despina => Some(0.1167318403814998f64), - DynOrigin::Galatea => Some(0.189898503906069f64), - DynOrigin::Larissa => Some(0.2548437405693583f64), - DynOrigin::Proteus => Some(2.583422379120727f64), - DynOrigin::Charon => Some(105.8799888601881f64), - DynOrigin::Nix => Some(0.00304817564816976f64), - DynOrigin::Hydra => Some(0.003211039206155255f64), - DynOrigin::Kerberos => Some(0.001110040850536676f64), - DynOrigin::Styx => Some(0f64), - DynOrigin::Ceres => Some(62.62888864440993f64), - DynOrigin::Pallas => Some(13.665878145967422f64), - DynOrigin::Vesta => Some(17.288232879171513f64), - DynOrigin::Psyche => Some(1.5896582441709424f64), - DynOrigin::Eros => Some(0.0004463f64), - DynOrigin::Davida => Some(3.8944831481705644f64), - _ => None, + DynOrigin::Sun => Ok(132712440041.27942f64), + DynOrigin::Mercury => Ok(22031.868551400003f64), + DynOrigin::Venus => Ok(324858.592f64), + DynOrigin::Earth => Ok(398600.43550702266f64), + DynOrigin::Mars => Ok(42828.37362069909f64), + DynOrigin::Jupiter => Ok(126686531.9003704f64), + DynOrigin::Saturn => Ok(37931206.23436167f64), + DynOrigin::Uranus => Ok(5793951.256527211f64), + DynOrigin::Neptune => Ok(6835103.145462294f64), + DynOrigin::Pluto => Ok(869.6138177608748f64), + DynOrigin::SolarSystemBarycenter => Ok(132712440041.27942f64), + DynOrigin::MercuryBarycenter => Ok(22031.868551400003f64), + DynOrigin::VenusBarycenter => Ok(324858.592f64), + DynOrigin::EarthBarycenter => Ok(403503.2356254802f64), + DynOrigin::MarsBarycenter => Ok(42828.3758157561f64), + DynOrigin::JupiterBarycenter => Ok(126712764.09999998f64), + DynOrigin::SaturnBarycenter => Ok(37940584.8418f64), + DynOrigin::UranusBarycenter => Ok(5794556.3999999985f64), + DynOrigin::NeptuneBarycenter => Ok(6836527.100580399f64), + DynOrigin::PlutoBarycenter => Ok(975.5f64), + DynOrigin::Moon => Ok(4902.80011845755f64), + DynOrigin::Phobos => Ok(0.0007087546066894452f64), + DynOrigin::Deimos => Ok(0.00009615569648120313f64), + DynOrigin::Io => Ok(5959.915466180539f64), + DynOrigin::Europa => Ok(3202.712099607295f64), + DynOrigin::Ganymede => Ok(9887.832752719638f64), + DynOrigin::Callisto => Ok(7179.283402579837f64), + DynOrigin::Amalthea => Ok(0.1645634534798259f64), + DynOrigin::Himalia => Ok(0.1515524299611265f64), + DynOrigin::Thebe => Ok(0.030148f64), + DynOrigin::Adrastea => Ok(0.000139f64), + DynOrigin::Metis => Ok(0.002501f64), + DynOrigin::Mimas => Ok(2.503488768152587f64), + DynOrigin::Enceladus => Ok(7.210366688598896f64), + DynOrigin::Tethys => Ok(41.21352885489587f64), + DynOrigin::Dione => Ok(73.11607172482067f64), + DynOrigin::Rhea => Ok(153.9417519146563f64), + DynOrigin::Titan => Ok(8978.137095521046f64), + DynOrigin::Hyperion => Ok(0.3704913747932265f64), + DynOrigin::Iapetus => Ok(120.5151060137642f64), + DynOrigin::Phoebe => Ok(0.5547860052791678f64), + DynOrigin::Janus => Ok(0.1265765099012197f64), + DynOrigin::Epimetheus => Ok(0.03512333288208074f64), + DynOrigin::Helene => Ok(0.0004757419551776972f64), + DynOrigin::Atlas => Ok(0.0003718871247516475f64), + DynOrigin::Prometheus => Ok(0.0107520800100761f64), + DynOrigin::Pandora => Ok(0.009290325122028795f64), + DynOrigin::Ariel => Ok(83.46344431770477f64), + DynOrigin::Umbriel => Ok(85.09338094489388f64), + DynOrigin::Titania => Ok(226.9437003741248f64), + DynOrigin::Oberon => Ok(205.3234302535623f64), + DynOrigin::Miranda => Ok(4.3195168992321f64), + DynOrigin::Triton => Ok(1428.495462910464f64), + DynOrigin::Naiad => Ok(0.008530281246540886f64), + DynOrigin::Thalassa => Ok(0.0235887319799217f64), + DynOrigin::Despina => Ok(0.1167318403814998f64), + DynOrigin::Galatea => Ok(0.189898503906069f64), + DynOrigin::Larissa => Ok(0.2548437405693583f64), + DynOrigin::Proteus => Ok(2.583422379120727f64), + DynOrigin::Charon => Ok(105.8799888601881f64), + DynOrigin::Nix => Ok(0.00304817564816976f64), + DynOrigin::Hydra => Ok(0.003211039206155255f64), + DynOrigin::Kerberos => Ok(0.001110040850536676f64), + DynOrigin::Styx => Ok(0f64), + DynOrigin::Ceres => Ok(62.62888864440993f64), + DynOrigin::Pallas => Ok(13.665878145967422f64), + DynOrigin::Vesta => Ok(17.288232879171513f64), + DynOrigin::Psyche => Ok(1.5896582441709424f64), + DynOrigin::Eros => Ok(0.0004463f64), + DynOrigin::Davida => Ok(3.8944831481705644f64), + _ => Err(UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "gravitational parameter".to_string(), + }), } } } -impl MaybeMeanRadius for DynOrigin { - fn maybe_mean_radius(&self) -> Option { +impl TryMeanRadius for DynOrigin { + fn try_mean_radius(&self) -> Result { match self { - DynOrigin::Mercury => Some(2439.4f64), - DynOrigin::Venus => Some(6051.8f64), - DynOrigin::Earth => Some(6371.0084f64), - DynOrigin::Mars => Some(3389.5f64), - DynOrigin::Jupiter => Some(69911f64), - DynOrigin::Saturn => Some(58232f64), - DynOrigin::Uranus => Some(25362f64), - DynOrigin::Neptune => Some(24622f64), - DynOrigin::Pluto => Some(1188.3f64), - DynOrigin::Moon => Some(1737.4f64), - DynOrigin::Phobos => Some(11.08f64), - DynOrigin::Deimos => Some(6.2f64), - DynOrigin::Io => Some(1821.49f64), - DynOrigin::Europa => Some(1560.8f64), - DynOrigin::Ganymede => Some(2631.2f64), - DynOrigin::Callisto => Some(2410.3f64), - DynOrigin::Amalthea => Some(83.5f64), - DynOrigin::Himalia => Some(85f64), - DynOrigin::Elara => Some(40f64), - DynOrigin::Pasiphae => Some(18f64), - DynOrigin::Sinope => Some(14f64), - DynOrigin::Lysithea => Some(12f64), - DynOrigin::Carme => Some(15f64), - DynOrigin::Ananke => Some(10f64), - DynOrigin::Leda => Some(5f64), - DynOrigin::Thebe => Some(49.3f64), - DynOrigin::Adrastea => Some(8.2f64), - DynOrigin::Metis => Some(21.5f64), - DynOrigin::Mimas => Some(198.2f64), - DynOrigin::Enceladus => Some(252.1f64), - DynOrigin::Tethys => Some(531f64), - DynOrigin::Dione => Some(561.4f64), - DynOrigin::Rhea => Some(763.5f64), - DynOrigin::Titan => Some(2575f64), - DynOrigin::Hyperion => Some(135f64), - DynOrigin::Iapetus => Some(734.3f64), - DynOrigin::Phoebe => Some(106.5f64), - DynOrigin::Janus => Some(89.2f64), - DynOrigin::Epimetheus => Some(58.2f64), - DynOrigin::Helene => Some(18f64), - DynOrigin::Telesto => Some(12.4f64), - DynOrigin::Calypso => Some(9.6f64), - DynOrigin::Atlas => Some(15.1f64), - DynOrigin::Prometheus => Some(43.1f64), - DynOrigin::Pandora => Some(40.6f64), - DynOrigin::Pan => Some(14f64), - DynOrigin::Methone => Some(1.45f64), - DynOrigin::Pallene => Some(2.23f64), - DynOrigin::Polydeuces => Some(1.3f64), - DynOrigin::Daphnis => Some(3.8f64), - DynOrigin::Anthe => Some(0.5f64), - DynOrigin::Aegaeon => Some(0.33f64), - DynOrigin::Ariel => Some(578.9f64), - DynOrigin::Umbriel => Some(584.7f64), - DynOrigin::Titania => Some(788.9f64), - DynOrigin::Oberon => Some(761.4f64), - DynOrigin::Miranda => Some(235.8f64), - DynOrigin::Cordelia => Some(13f64), - DynOrigin::Ophelia => Some(15f64), - DynOrigin::Bianca => Some(21f64), - DynOrigin::Cressida => Some(31f64), - DynOrigin::Desdemona => Some(27f64), - DynOrigin::Juliet => Some(42f64), - DynOrigin::Portia => Some(54f64), - DynOrigin::Rosalind => Some(27f64), - DynOrigin::Belinda => Some(33f64), - DynOrigin::Puck => Some(77f64), - DynOrigin::Triton => Some(1352.6f64), - DynOrigin::Nereid => Some(170f64), - DynOrigin::Naiad => Some(29f64), - DynOrigin::Thalassa => Some(40f64), - DynOrigin::Despina => Some(74f64), - DynOrigin::Galatea => Some(79f64), - DynOrigin::Larissa => Some(96f64), - DynOrigin::Proteus => Some(208f64), - DynOrigin::Charon => Some(606f64), - DynOrigin::Gaspra => Some(6.1f64), - DynOrigin::Ida => Some(15.65f64), - DynOrigin::Ceres => Some(470f64), - DynOrigin::Psyche => Some(113f64), - DynOrigin::Lutetia => Some(52.5f64), - DynOrigin::Eros => Some(8.45f64), - DynOrigin::Davida => Some(150f64), - DynOrigin::Mathilde => Some(26.5f64), - DynOrigin::Steins => Some(2.7f64), - _ => None, + DynOrigin::Mercury => Ok(2439.4f64), + DynOrigin::Venus => Ok(6051.8f64), + DynOrigin::Earth => Ok(6371.0084f64), + DynOrigin::Mars => Ok(3389.5f64), + DynOrigin::Jupiter => Ok(69911f64), + DynOrigin::Saturn => Ok(58232f64), + DynOrigin::Uranus => Ok(25362f64), + DynOrigin::Neptune => Ok(24622f64), + DynOrigin::Pluto => Ok(1188.3f64), + DynOrigin::Moon => Ok(1737.4f64), + DynOrigin::Phobos => Ok(11.08f64), + DynOrigin::Deimos => Ok(6.2f64), + DynOrigin::Io => Ok(1821.49f64), + DynOrigin::Europa => Ok(1560.8f64), + DynOrigin::Ganymede => Ok(2631.2f64), + DynOrigin::Callisto => Ok(2410.3f64), + DynOrigin::Amalthea => Ok(83.5f64), + DynOrigin::Himalia => Ok(85f64), + DynOrigin::Elara => Ok(40f64), + DynOrigin::Pasiphae => Ok(18f64), + DynOrigin::Sinope => Ok(14f64), + DynOrigin::Lysithea => Ok(12f64), + DynOrigin::Carme => Ok(15f64), + DynOrigin::Ananke => Ok(10f64), + DynOrigin::Leda => Ok(5f64), + DynOrigin::Thebe => Ok(49.3f64), + DynOrigin::Adrastea => Ok(8.2f64), + DynOrigin::Metis => Ok(21.5f64), + DynOrigin::Mimas => Ok(198.2f64), + DynOrigin::Enceladus => Ok(252.1f64), + DynOrigin::Tethys => Ok(531f64), + DynOrigin::Dione => Ok(561.4f64), + DynOrigin::Rhea => Ok(763.5f64), + DynOrigin::Titan => Ok(2575f64), + DynOrigin::Hyperion => Ok(135f64), + DynOrigin::Iapetus => Ok(734.3f64), + DynOrigin::Phoebe => Ok(106.5f64), + DynOrigin::Janus => Ok(89.2f64), + DynOrigin::Epimetheus => Ok(58.2f64), + DynOrigin::Helene => Ok(18f64), + DynOrigin::Telesto => Ok(12.4f64), + DynOrigin::Calypso => Ok(9.6f64), + DynOrigin::Atlas => Ok(15.1f64), + DynOrigin::Prometheus => Ok(43.1f64), + DynOrigin::Pandora => Ok(40.6f64), + DynOrigin::Pan => Ok(14f64), + DynOrigin::Methone => Ok(1.45f64), + DynOrigin::Pallene => Ok(2.23f64), + DynOrigin::Polydeuces => Ok(1.3f64), + DynOrigin::Daphnis => Ok(3.8f64), + DynOrigin::Anthe => Ok(0.5f64), + DynOrigin::Aegaeon => Ok(0.33f64), + DynOrigin::Ariel => Ok(578.9f64), + DynOrigin::Umbriel => Ok(584.7f64), + DynOrigin::Titania => Ok(788.9f64), + DynOrigin::Oberon => Ok(761.4f64), + DynOrigin::Miranda => Ok(235.8f64), + DynOrigin::Cordelia => Ok(13f64), + DynOrigin::Ophelia => Ok(15f64), + DynOrigin::Bianca => Ok(21f64), + DynOrigin::Cressida => Ok(31f64), + DynOrigin::Desdemona => Ok(27f64), + DynOrigin::Juliet => Ok(42f64), + DynOrigin::Portia => Ok(54f64), + DynOrigin::Rosalind => Ok(27f64), + DynOrigin::Belinda => Ok(33f64), + DynOrigin::Puck => Ok(77f64), + DynOrigin::Triton => Ok(1352.6f64), + DynOrigin::Nereid => Ok(170f64), + DynOrigin::Naiad => Ok(29f64), + DynOrigin::Thalassa => Ok(40f64), + DynOrigin::Despina => Ok(74f64), + DynOrigin::Galatea => Ok(79f64), + DynOrigin::Larissa => Ok(96f64), + DynOrigin::Proteus => Ok(208f64), + DynOrigin::Charon => Ok(606f64), + DynOrigin::Gaspra => Ok(6.1f64), + DynOrigin::Ida => Ok(15.65f64), + DynOrigin::Ceres => Ok(470f64), + DynOrigin::Psyche => Ok(113f64), + DynOrigin::Lutetia => Ok(52.5f64), + DynOrigin::Eros => Ok(8.45f64), + DynOrigin::Davida => Ok(150f64), + DynOrigin::Mathilde => Ok(26.5f64), + DynOrigin::Steins => Ok(2.7f64), + _ => Err(UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "mean radius".to_string(), + }), } } } -impl MaybeTriaxialEllipsoid for DynOrigin { - fn maybe_radii(&self) -> Option { +impl TryTriaxialEllipsoid for DynOrigin { + fn try_radii(&self) -> Result { match self { - DynOrigin::Sun => Some((695700f64, 695700f64, 695700f64)), - DynOrigin::Mercury => Some((2440.53f64, 2440.53f64, 2438.26f64)), - DynOrigin::Venus => Some((6051.8f64, 6051.8f64, 6051.8f64)), - DynOrigin::Earth => Some((6378.1366f64, 6378.1366f64, 6356.7519f64)), - DynOrigin::Mars => Some((3396.19f64, 3396.19f64, 3376.2f64)), - DynOrigin::Jupiter => Some((71492f64, 71492f64, 66854f64)), - DynOrigin::Saturn => Some((60268f64, 60268f64, 54364f64)), - DynOrigin::Uranus => Some((25559f64, 25559f64, 24973f64)), - DynOrigin::Neptune => Some((24764f64, 24764f64, 24341f64)), - DynOrigin::Pluto => Some((1188.3f64, 1188.3f64, 1188.3f64)), - DynOrigin::Moon => Some((1737.4f64, 1737.4f64, 1737.4f64)), - DynOrigin::Phobos => Some((13f64, 11.4f64, 9.1f64)), - DynOrigin::Deimos => Some((7.8f64, 6f64, 5.1f64)), - DynOrigin::Io => Some((1829.4f64, 1819.4f64, 1815.7f64)), - DynOrigin::Europa => Some((1562.6f64, 1560.3f64, 1559.5f64)), - DynOrigin::Ganymede => Some((2631.2f64, 2631.2f64, 2631.2f64)), - DynOrigin::Callisto => Some((2410.3f64, 2410.3f64, 2410.3f64)), - DynOrigin::Amalthea => Some((125f64, 73f64, 64f64)), - DynOrigin::Himalia => Some((85f64, 85f64, 85f64)), - DynOrigin::Elara => Some((40f64, 40f64, 40f64)), - DynOrigin::Pasiphae => Some((18f64, 18f64, 18f64)), - DynOrigin::Sinope => Some((14f64, 14f64, 14f64)), - DynOrigin::Lysithea => Some((12f64, 12f64, 12f64)), - DynOrigin::Carme => Some((15f64, 15f64, 15f64)), - DynOrigin::Ananke => Some((10f64, 10f64, 10f64)), - DynOrigin::Leda => Some((5f64, 5f64, 5f64)), - DynOrigin::Thebe => Some((58f64, 49f64, 42f64)), - DynOrigin::Adrastea => Some((10f64, 8f64, 7f64)), - DynOrigin::Metis => Some((30f64, 20f64, 17f64)), - DynOrigin::Mimas => Some((207.8f64, 196.7f64, 190.6f64)), - DynOrigin::Enceladus => Some((256.6f64, 251.4f64, 248.3f64)), - DynOrigin::Tethys => Some((538.4f64, 528.3f64, 526.3f64)), - DynOrigin::Dione => Some((563.4f64, 561.3f64, 559.6f64)), - DynOrigin::Rhea => Some((765f64, 763.1f64, 762.4f64)), - DynOrigin::Titan => Some((2575.15f64, 2574.78f64, 2574.47f64)), - DynOrigin::Hyperion => Some((180.1f64, 133f64, 102.7f64)), - DynOrigin::Iapetus => Some((745.7f64, 745.7f64, 712.1f64)), - DynOrigin::Phoebe => Some((109.4f64, 108.5f64, 101.8f64)), - DynOrigin::Janus => Some((101.7f64, 93f64, 76.3f64)), - DynOrigin::Epimetheus => Some((64.9f64, 57.3f64, 53f64)), - DynOrigin::Helene => Some((22.5f64, 19.6f64, 13.3f64)), - DynOrigin::Telesto => Some((16.3f64, 11.8f64, 9.8f64)), - DynOrigin::Calypso => Some((15.3f64, 9.3f64, 6.3f64)), - DynOrigin::Atlas => Some((20.5f64, 17.8f64, 9.4f64)), - DynOrigin::Prometheus => Some((68.2f64, 41.6f64, 28.2f64)), - DynOrigin::Pandora => Some((52.2f64, 40.8f64, 31.5f64)), - DynOrigin::Pan => Some((17.2f64, 15.4f64, 10.4f64)), - DynOrigin::Methone => Some((1.94f64, 1.29f64, 1.21f64)), - DynOrigin::Pallene => Some((2.88f64, 2.08f64, 1.8f64)), - DynOrigin::Polydeuces => Some((1.5f64, 1.2f64, 1f64)), - DynOrigin::Daphnis => Some((4.6f64, 4.5f64, 2.8f64)), - DynOrigin::Anthe => Some((0.5f64, 0.5f64, 0.5f64)), - DynOrigin::Aegaeon => Some((0.7f64, 0.25f64, 0.2f64)), - DynOrigin::Ariel => Some((581.1f64, 577.9f64, 577.7f64)), - DynOrigin::Umbriel => Some((584.7f64, 584.7f64, 584.7f64)), - DynOrigin::Titania => Some((788.9f64, 788.9f64, 788.9f64)), - DynOrigin::Oberon => Some((761.4f64, 761.4f64, 761.4f64)), - DynOrigin::Miranda => Some((240.4f64, 234.2f64, 232.9f64)), - DynOrigin::Cordelia => Some((13f64, 13f64, 13f64)), - DynOrigin::Ophelia => Some((15f64, 15f64, 15f64)), - DynOrigin::Bianca => Some((21f64, 21f64, 21f64)), - DynOrigin::Cressida => Some((31f64, 31f64, 31f64)), - DynOrigin::Desdemona => Some((27f64, 27f64, 27f64)), - DynOrigin::Juliet => Some((42f64, 42f64, 42f64)), - DynOrigin::Portia => Some((54f64, 54f64, 54f64)), - DynOrigin::Rosalind => Some((27f64, 27f64, 27f64)), - DynOrigin::Belinda => Some((33f64, 33f64, 33f64)), - DynOrigin::Puck => Some((77f64, 77f64, 77f64)), - DynOrigin::Triton => Some((1352.6f64, 1352.6f64, 1352.6f64)), - DynOrigin::Nereid => Some((170f64, 170f64, 170f64)), - DynOrigin::Naiad => Some((29f64, 29f64, 29f64)), - DynOrigin::Thalassa => Some((40f64, 40f64, 40f64)), - DynOrigin::Despina => Some((74f64, 74f64, 74f64)), - DynOrigin::Galatea => Some((79f64, 79f64, 79f64)), - DynOrigin::Larissa => Some((96f64, 96f64, 96f64)), - DynOrigin::Proteus => Some((218f64, 208f64, 201f64)), - DynOrigin::Charon => Some((606f64, 606f64, 606f64)), - DynOrigin::Gaspra => Some((9.1f64, 5.2f64, 4.4f64)), - DynOrigin::Ida => Some((26.8f64, 12f64, 7.6f64)), - DynOrigin::Ceres => Some((487.3f64, 487.3f64, 446f64)), - DynOrigin::Vesta => Some((289f64, 280f64, 229f64)), - DynOrigin::Psyche => Some((139.5f64, 116f64, 94.5f64)), - DynOrigin::Lutetia => Some((62f64, 50.5f64, 46.5f64)), - DynOrigin::Eros => Some((17f64, 5.5f64, 5.5f64)), - DynOrigin::Davida => Some((180f64, 147f64, 127f64)), - DynOrigin::Mathilde => Some((33f64, 24f64, 23f64)), - DynOrigin::Steins => Some((3.24f64, 2.73f64, 2.04f64)), - DynOrigin::Toutatis => Some((2.13f64, 1.015f64, 0.85f64)), - DynOrigin::Itokawa => Some((0.268f64, 0.147f64, 0.104f64)), - _ => None, + DynOrigin::Sun => Ok((695700f64, 695700f64, 695700f64)), + DynOrigin::Mercury => Ok((2440.53f64, 2440.53f64, 2438.26f64)), + DynOrigin::Venus => Ok((6051.8f64, 6051.8f64, 6051.8f64)), + DynOrigin::Earth => Ok((6378.1366f64, 6378.1366f64, 6356.7519f64)), + DynOrigin::Mars => Ok((3396.19f64, 3396.19f64, 3376.2f64)), + DynOrigin::Jupiter => Ok((71492f64, 71492f64, 66854f64)), + DynOrigin::Saturn => Ok((60268f64, 60268f64, 54364f64)), + DynOrigin::Uranus => Ok((25559f64, 25559f64, 24973f64)), + DynOrigin::Neptune => Ok((24764f64, 24764f64, 24341f64)), + DynOrigin::Pluto => Ok((1188.3f64, 1188.3f64, 1188.3f64)), + DynOrigin::Moon => Ok((1737.4f64, 1737.4f64, 1737.4f64)), + DynOrigin::Phobos => Ok((13f64, 11.4f64, 9.1f64)), + DynOrigin::Deimos => Ok((7.8f64, 6f64, 5.1f64)), + DynOrigin::Io => Ok((1829.4f64, 1819.4f64, 1815.7f64)), + DynOrigin::Europa => Ok((1562.6f64, 1560.3f64, 1559.5f64)), + DynOrigin::Ganymede => Ok((2631.2f64, 2631.2f64, 2631.2f64)), + DynOrigin::Callisto => Ok((2410.3f64, 2410.3f64, 2410.3f64)), + DynOrigin::Amalthea => Ok((125f64, 73f64, 64f64)), + DynOrigin::Himalia => Ok((85f64, 85f64, 85f64)), + DynOrigin::Elara => Ok((40f64, 40f64, 40f64)), + DynOrigin::Pasiphae => Ok((18f64, 18f64, 18f64)), + DynOrigin::Sinope => Ok((14f64, 14f64, 14f64)), + DynOrigin::Lysithea => Ok((12f64, 12f64, 12f64)), + DynOrigin::Carme => Ok((15f64, 15f64, 15f64)), + DynOrigin::Ananke => Ok((10f64, 10f64, 10f64)), + DynOrigin::Leda => Ok((5f64, 5f64, 5f64)), + DynOrigin::Thebe => Ok((58f64, 49f64, 42f64)), + DynOrigin::Adrastea => Ok((10f64, 8f64, 7f64)), + DynOrigin::Metis => Ok((30f64, 20f64, 17f64)), + DynOrigin::Mimas => Ok((207.8f64, 196.7f64, 190.6f64)), + DynOrigin::Enceladus => Ok((256.6f64, 251.4f64, 248.3f64)), + DynOrigin::Tethys => Ok((538.4f64, 528.3f64, 526.3f64)), + DynOrigin::Dione => Ok((563.4f64, 561.3f64, 559.6f64)), + DynOrigin::Rhea => Ok((765f64, 763.1f64, 762.4f64)), + DynOrigin::Titan => Ok((2575.15f64, 2574.78f64, 2574.47f64)), + DynOrigin::Hyperion => Ok((180.1f64, 133f64, 102.7f64)), + DynOrigin::Iapetus => Ok((745.7f64, 745.7f64, 712.1f64)), + DynOrigin::Phoebe => Ok((109.4f64, 108.5f64, 101.8f64)), + DynOrigin::Janus => Ok((101.7f64, 93f64, 76.3f64)), + DynOrigin::Epimetheus => Ok((64.9f64, 57.3f64, 53f64)), + DynOrigin::Helene => Ok((22.5f64, 19.6f64, 13.3f64)), + DynOrigin::Telesto => Ok((16.3f64, 11.8f64, 9.8f64)), + DynOrigin::Calypso => Ok((15.3f64, 9.3f64, 6.3f64)), + DynOrigin::Atlas => Ok((20.5f64, 17.8f64, 9.4f64)), + DynOrigin::Prometheus => Ok((68.2f64, 41.6f64, 28.2f64)), + DynOrigin::Pandora => Ok((52.2f64, 40.8f64, 31.5f64)), + DynOrigin::Pan => Ok((17.2f64, 15.4f64, 10.4f64)), + DynOrigin::Methone => Ok((1.94f64, 1.29f64, 1.21f64)), + DynOrigin::Pallene => Ok((2.88f64, 2.08f64, 1.8f64)), + DynOrigin::Polydeuces => Ok((1.5f64, 1.2f64, 1f64)), + DynOrigin::Daphnis => Ok((4.6f64, 4.5f64, 2.8f64)), + DynOrigin::Anthe => Ok((0.5f64, 0.5f64, 0.5f64)), + DynOrigin::Aegaeon => Ok((0.7f64, 0.25f64, 0.2f64)), + DynOrigin::Ariel => Ok((581.1f64, 577.9f64, 577.7f64)), + DynOrigin::Umbriel => Ok((584.7f64, 584.7f64, 584.7f64)), + DynOrigin::Titania => Ok((788.9f64, 788.9f64, 788.9f64)), + DynOrigin::Oberon => Ok((761.4f64, 761.4f64, 761.4f64)), + DynOrigin::Miranda => Ok((240.4f64, 234.2f64, 232.9f64)), + DynOrigin::Cordelia => Ok((13f64, 13f64, 13f64)), + DynOrigin::Ophelia => Ok((15f64, 15f64, 15f64)), + DynOrigin::Bianca => Ok((21f64, 21f64, 21f64)), + DynOrigin::Cressida => Ok((31f64, 31f64, 31f64)), + DynOrigin::Desdemona => Ok((27f64, 27f64, 27f64)), + DynOrigin::Juliet => Ok((42f64, 42f64, 42f64)), + DynOrigin::Portia => Ok((54f64, 54f64, 54f64)), + DynOrigin::Rosalind => Ok((27f64, 27f64, 27f64)), + DynOrigin::Belinda => Ok((33f64, 33f64, 33f64)), + DynOrigin::Puck => Ok((77f64, 77f64, 77f64)), + DynOrigin::Triton => Ok((1352.6f64, 1352.6f64, 1352.6f64)), + DynOrigin::Nereid => Ok((170f64, 170f64, 170f64)), + DynOrigin::Naiad => Ok((29f64, 29f64, 29f64)), + DynOrigin::Thalassa => Ok((40f64, 40f64, 40f64)), + DynOrigin::Despina => Ok((74f64, 74f64, 74f64)), + DynOrigin::Galatea => Ok((79f64, 79f64, 79f64)), + DynOrigin::Larissa => Ok((96f64, 96f64, 96f64)), + DynOrigin::Proteus => Ok((218f64, 208f64, 201f64)), + DynOrigin::Charon => Ok((606f64, 606f64, 606f64)), + DynOrigin::Gaspra => Ok((9.1f64, 5.2f64, 4.4f64)), + DynOrigin::Ida => Ok((26.8f64, 12f64, 7.6f64)), + DynOrigin::Ceres => Ok((487.3f64, 487.3f64, 446f64)), + DynOrigin::Vesta => Ok((289f64, 280f64, 229f64)), + DynOrigin::Psyche => Ok((139.5f64, 116f64, 94.5f64)), + DynOrigin::Lutetia => Ok((62f64, 50.5f64, 46.5f64)), + DynOrigin::Eros => Ok((17f64, 5.5f64, 5.5f64)), + DynOrigin::Davida => Ok((180f64, 147f64, 127f64)), + DynOrigin::Mathilde => Ok((33f64, 24f64, 23f64)), + DynOrigin::Steins => Ok((3.24f64, 2.73f64, 2.04f64)), + DynOrigin::Toutatis => Ok((2.13f64, 1.015f64, 0.85f64)), + DynOrigin::Itokawa => Ok((0.268f64, 0.147f64, 0.104f64)), + _ => Err(UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "radii".to_string(), + }), } } } -impl MaybeSpheroid for DynOrigin {} +impl TrySpheroid for DynOrigin {} impl TryRotationalElements for DynOrigin { - fn try_rotational_elements( - &self, - t: f64, - ) -> Result { + fn try_rotational_elements(&self, t: f64) -> Result { match self { DynOrigin::Sun => Ok(( RIGHT_ASCENSION_SUN.angle::<0usize>(None, t), @@ -9352,13 +9358,16 @@ impl TryRotationalElements for DynOrigin { DECLINATION_ITOKAWA.angle::<0usize>(None, t), ROTATION_ITOKAWA.angle::<0usize>(None, t), )), - _ => Err(UndefinedRotationalElementsError(self.name().to_string())), + _ => Err(UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "rotational elements".to_string(), + }), } } fn try_rotational_element_rates( &self, t: f64, - ) -> Result { + ) -> Result { match self { DynOrigin::Sun => Ok(( RIGHT_ASCENSION_SUN.angle_dot::<0usize>(None, t), @@ -9723,7 +9732,10 @@ impl TryRotationalElements for DynOrigin { DECLINATION_ITOKAWA.angle_dot::<0usize>(None, t), ROTATION_ITOKAWA.angle_dot::<0usize>(None, t), )), - _ => Err(UndefinedRotationalElementsError(self.name().to_string())), + _ => Err(UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "rotational element rates".to_string(), + }), } } } diff --git a/crates/lox-bodies/src/lib.rs b/crates/lox-bodies/src/lib.rs index e305c7ab..8c9cdb7c 100644 --- a/crates/lox-bodies/src/lib.rs +++ b/crates/lox-bodies/src/lib.rs @@ -35,19 +35,26 @@ pub trait Origin { fn name(&self) -> &'static str; } +#[derive(Clone, Debug, Error, Eq, PartialEq)] +#[error("undefined property '{prop}' for origin '{origin}'")] +pub struct UndefinedOriginPropertyError { + origin: String, + prop: String, +} + pub type Radii = (f64, f64, f64); -pub trait MaybeTriaxialEllipsoid: Origin { - fn maybe_radii(&self) -> Option; +pub trait TryTriaxialEllipsoid: Origin { + fn try_radii(&self) -> Result; } pub trait TriaxialEllipsoid: Origin { fn radii(&self) -> Radii; } -impl MaybeTriaxialEllipsoid for T { - fn maybe_radii(&self) -> Option { - Some(self.radii()) +impl TryTriaxialEllipsoid for T { + fn try_radii(&self) -> Result { + Ok(self.radii()) } } @@ -55,20 +62,6 @@ fn flattening(equatorial_radius: f64, polar_radius: f64) -> f64 { (equatorial_radius - polar_radius) / equatorial_radius } -pub trait MaybeSpheroid: MaybeTriaxialEllipsoid { - fn maybe_polar_radius(&self) -> Option { - self.maybe_radii().map(|radii| radii.0) - } - - fn maybe_equatorial_radius(&self) -> Option { - self.maybe_radii().map(|radii| radii.2) - } - - fn maybe_flattening(&self) -> Option { - self.maybe_radii().map(|radii| flattening(radii.0, radii.2)) - } -} - pub trait Spheroid: TriaxialEllipsoid { fn equatorial_radius(&self) -> f64 { self.radii().0 @@ -83,31 +76,45 @@ pub trait Spheroid: TriaxialEllipsoid { } } -impl MaybeSpheroid for T { - fn maybe_polar_radius(&self) -> Option { - Some(self.polar_radius()) +pub trait TrySpheroid: TryTriaxialEllipsoid { + fn try_equatorial_radius(&self) -> Result { + self.try_radii().map(|radii| radii.2) } - fn maybe_equatorial_radius(&self) -> Option { - Some(self.equatorial_radius()) + fn try_polar_radius(&self) -> Result { + self.try_radii().map(|radii| radii.0) } - fn maybe_flattening(&self) -> Option { - Some(self.flattening()) + fn try_flattening(&self) -> Result { + self.try_radii().map(|radii| flattening(radii.0, radii.2)) } } -pub trait MaybeMeanRadius: Origin { - fn maybe_mean_radius(&self) -> Option; +impl TrySpheroid for T { + fn try_equatorial_radius(&self) -> Result { + Ok(self.equatorial_radius()) + } + + fn try_polar_radius(&self) -> Result { + Ok(self.polar_radius()) + } + + fn try_flattening(&self) -> Result { + Ok(self.flattening()) + } +} + +pub trait TryMeanRadius: Origin { + fn try_mean_radius(&self) -> Result; } pub trait MeanRadius: Origin { fn mean_radius(&self) -> f64; } -impl MaybeMeanRadius for T { - fn maybe_mean_radius(&self) -> Option { - Some(self.mean_radius()) +impl TryMeanRadius for T { + fn try_mean_radius(&self) -> Result { + Ok(self.mean_radius()) } } @@ -115,13 +122,13 @@ pub trait PointMass: Origin { fn gravitational_parameter(&self) -> f64; } -pub trait MaybePointMass: Origin { - fn maybe_gravitational_parameter(&self) -> Option; +pub trait TryPointMass: Origin { + fn try_gravitational_parameter(&self) -> Result; } -impl MaybePointMass for T { - fn maybe_gravitational_parameter(&self) -> Option { - Some(self.gravitational_parameter()) +impl TryPointMass for T { + fn try_gravitational_parameter(&self) -> Result { + Ok(self.gravitational_parameter()) } } @@ -273,56 +280,48 @@ pub trait RotationalElements: Origin { } } -#[derive(Clone, Debug, Error, Eq, PartialEq)] -#[error("no rotational elements defined for origin `{0}`")] -pub struct UndefinedRotationalElementsError(String); - pub trait TryRotationalElements: Origin { - fn try_rotational_elements(&self, t: f64) - -> Result; + fn try_rotational_elements(&self, t: f64) -> Result; fn try_rotational_element_rates( &self, t: f64, - ) -> Result; + ) -> Result; - fn try_right_ascension(&self, t: f64) -> Result { + fn try_right_ascension(&self, t: f64) -> Result { self.try_rotational_elements(t).map(|r| r.0) } - fn try_right_ascension_rate(&self, t: f64) -> Result { + fn try_right_ascension_rate(&self, t: f64) -> Result { self.try_rotational_element_rates(t).map(|r| r.0) } - fn try_declination(&self, t: f64) -> Result { + fn try_declination(&self, t: f64) -> Result { self.try_rotational_elements(t).map(|r| r.1) } - fn try_declination_rate(&self, t: f64) -> Result { + fn try_declination_rate(&self, t: f64) -> Result { self.try_rotational_element_rates(t).map(|r| r.1) } - fn try_rotation_angle(&self, t: f64) -> Result { + fn try_rotation_angle(&self, t: f64) -> Result { self.try_rotational_elements(t).map(|r| r.2) } - fn try_rotation_rate(&self, t: f64) -> Result { + fn try_rotation_rate(&self, t: f64) -> Result { self.try_rotational_element_rates(t).map(|r| r.2) } } impl TryRotationalElements for T { - fn try_rotational_elements( - &self, - t: f64, - ) -> Result { + fn try_rotational_elements(&self, t: f64) -> Result { Ok(self.rotational_elements(t)) } fn try_rotational_element_rates( &self, t: f64, - ) -> Result { + ) -> Result { Ok(self.rotational_element_rates(t)) } } diff --git a/crates/lox-bodies/src/python.rs b/crates/lox-bodies/src/python.rs index 1b5b2f8a..220ace67 100644 --- a/crates/lox-bodies/src/python.rs +++ b/crates/lox-bodies/src/python.rs @@ -5,12 +5,25 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, you can obtain one at https://mozilla.org/MPL/2.0/. */ -use pyo3::exceptions::{PyTypeError, PyValueError}; +use crate::dynamic::{DynOrigin, UnknownOriginId, UnknownOriginName}; +use crate::{ + Elements, Origin, TryMeanRadius, TryPointMass, TryRotationalElements, TrySpheroid, + TryTriaxialEllipsoid, +}; +use crate::{Radii, UndefinedOriginPropertyError as RsUndefinedPropertyError}; +use lox_math::types::units::Seconds; +use pyo3::create_exception; +use pyo3::exceptions::{PyException, PyTypeError, PyValueError}; use pyo3::prelude::*; use std::str::FromStr; -use crate::dynamic::{DynOrigin, UnknownOriginId, UnknownOriginName}; -use crate::Origin; +create_exception!(lox_space, UndefinedOriginPropertyError, PyException); + +impl From for PyErr { + fn from(err: RsUndefinedPropertyError) -> Self { + UndefinedOriginPropertyError::new_err(err.to_string()) + } +} impl From for PyErr { fn from(err: UnknownOriginId) -> Self { @@ -62,4 +75,56 @@ impl PyOrigin { pub fn name(&self) -> &'static str { self.0.name() } + + pub fn gravitational_parameter(&self) -> PyResult { + Ok(self.0.try_gravitational_parameter()?) + } + + pub fn mean_radius(&self) -> PyResult { + Ok(self.0.try_mean_radius()?) + } + + pub fn radii(&self) -> PyResult { + Ok(self.0.try_radii()?) + } + + pub fn equatorial_radius(&self) -> PyResult { + Ok(self.0.try_equatorial_radius()?) + } + + pub fn polar_radius(&self) -> PyResult { + Ok(self.0.try_polar_radius()?) + } + + pub fn rotational_elements(&self, et: Seconds) -> PyResult { + Ok(self.0.try_rotational_elements(et)?) + } + + pub fn rotational_element_rates(&self, et: Seconds) -> PyResult { + Ok(self.0.try_rotational_element_rates(et)?) + } + + pub fn right_ascension(&self, et: Seconds) -> PyResult { + Ok(self.0.try_right_ascension(et)?) + } + + pub fn right_ascension_rate(&self, et: Seconds) -> PyResult { + Ok(self.0.try_right_ascension_rate(et)?) + } + + pub fn declination(&self, et: Seconds) -> PyResult { + Ok(self.0.try_declination(et)?) + } + + pub fn declination_rate(&self, et: Seconds) -> PyResult { + Ok(self.0.try_declination_rate(et)?) + } + + pub fn rotation_angle(&self, et: Seconds) -> PyResult { + Ok(self.0.try_rotation_angle(et)?) + } + + pub fn rotation_rate(&self, et: Seconds) -> PyResult { + Ok(self.0.try_rotation_rate(et)?) + } } diff --git a/crates/lox-orbits/src/analysis.rs b/crates/lox-orbits/src/analysis.rs index 4d1be8e6..5d70b0a2 100644 --- a/crates/lox-orbits/src/analysis.rs +++ b/crates/lox-orbits/src/analysis.rs @@ -7,7 +7,7 @@ use std::f64::consts::PI; * License, v. 2.0. If a copy of the MPL was not distributed with this * file, you can obtain one at https://mozilla.org/MPL/2.0/. */ -use lox_bodies::{MaybeSpheroid, Origin, RotationalElements, Spheroid}; +use lox_bodies::{Origin, RotationalElements, Spheroid, TrySpheroid}; use lox_math::roots::Brent; use lox_math::series::{Series, SeriesError}; use lox_math::types::units::Radians; @@ -115,7 +115,7 @@ pub fn visibility_dyn + Clone, P: FrameTransfor pub fn elevation< T: TimeLike + TryToScale + Clone, - O: Origin + MaybeSpheroid + RotationalElements + Clone, + O: Origin + TrySpheroid + RotationalElements + Clone, P: FrameTransformationProvider, >( time: T, diff --git a/crates/lox-orbits/src/elements.rs b/crates/lox-orbits/src/elements.rs index 80644261..473ec7ae 100644 --- a/crates/lox-orbits/src/elements.rs +++ b/crates/lox-orbits/src/elements.rs @@ -11,7 +11,7 @@ use std::f64::consts::TAU; use float_eq::float_eq; use glam::{DMat3, DVec3}; -use lox_bodies::{DynOrigin, MaybePointMass, PointMass}; +use lox_bodies::{DynOrigin, PointMass, TryPointMass, UndefinedOriginPropertyError}; use lox_time::deltas::TimeDelta; use lox_time::TimeLike; @@ -29,7 +29,7 @@ pub(crate) struct KeplerianElements { } #[derive(Debug, Clone, PartialEq)] -pub struct Keplerian { +pub struct Keplerian { time: T, origin: O, frame: R, @@ -87,10 +87,8 @@ where longitude_of_ascending_node: f64, argument_of_periapsis: f64, true_anomaly: f64, - ) -> Result { - if origin.maybe_gravitational_parameter().is_none() { - return Err("undefined gravitational parameter"); - } + ) -> Result { + let _ = origin.try_gravitational_parameter()?; Ok(Self { time, origin, @@ -108,7 +106,7 @@ where impl Keplerian where T: TimeLike, - O: MaybePointMass, + O: TryPointMass, R: ReferenceFrame, { pub fn origin(&self) -> O @@ -127,7 +125,7 @@ where pub fn gravitational_parameter(&self) -> f64 { self.origin - .maybe_gravitational_parameter() + .try_gravitational_parameter() .expect("gravitational parameter should be available") } @@ -182,7 +180,7 @@ where } } -impl CoordinateSystem +impl CoordinateSystem for Keplerian { fn reference_frame(&self) -> R { @@ -193,7 +191,7 @@ impl CoordinateSystem impl Keplerian where T: TimeLike + Clone, - O: MaybePointMass + Clone, + O: TryPointMass + Clone, R: ReferenceFrame + Clone, { pub(crate) fn to_cartesian(&self) -> State { diff --git a/crates/lox-orbits/src/frames/iau.rs b/crates/lox-orbits/src/frames/iau.rs index 475f0ebe..07bc6b32 100644 --- a/crates/lox-orbits/src/frames/iau.rs +++ b/crates/lox-orbits/src/frames/iau.rs @@ -7,7 +7,7 @@ */ use crate::rotations::Rotation; use glam::{DMat3, DVec3}; -use lox_bodies::{TryRotationalElements, UndefinedRotationalElementsError}; +use lox_bodies::{TryRotationalElements, UndefinedOriginPropertyError}; use lox_time::julian_dates::JulianDate; use lox_time::time_scales::Tdb; use lox_time::transformations::{OffsetProvider, TryToScale}; @@ -18,7 +18,7 @@ use thiserror::Error; #[derive(Clone, Debug, Error)] pub enum IcrfToBodyFixedError { #[error(transparent)] - UndefinedRotationalElements(#[from] UndefinedRotationalElementsError), + UndefinedRotationalElements(#[from] UndefinedOriginPropertyError), #[error("time error: {0}")] TimeError(String), } diff --git a/crates/lox-orbits/src/ground.rs b/crates/lox-orbits/src/ground.rs index 60458901..8b5aae7f 100644 --- a/crates/lox-orbits/src/ground.rs +++ b/crates/lox-orbits/src/ground.rs @@ -11,7 +11,7 @@ use std::f64::consts::FRAC_PI_2; use glam::{DMat3, DVec3}; use thiserror::Error; -use lox_bodies::{DynOrigin, MaybeSpheroid, RotationalElements, Spheroid}; +use lox_bodies::{DynOrigin, RotationalElements, Spheroid, TrySpheroid}; use lox_math::types::units::Radians; use lox_time::prelude::Tdb; use lox_time::transformations::TryToScale; @@ -61,7 +61,7 @@ impl Observables { } #[derive(Clone, Debug)] -pub struct GroundLocation { +pub struct GroundLocation { longitude: f64, latitude: f64, altitude: f64, @@ -88,7 +88,7 @@ impl DynGroundLocation { altitude: f64, body: DynOrigin, ) -> Result { - if body.maybe_equatorial_radius().is_none() { + if body.try_equatorial_radius().is_err() { return Err("no spheroid"); } Ok(GroundLocation { @@ -100,7 +100,7 @@ impl DynGroundLocation { } } -impl GroundLocation { +impl GroundLocation { pub fn origin(&self) -> B where B: Clone, @@ -122,13 +122,13 @@ impl GroundLocation { fn equatorial_radius(&self) -> f64 { self.body - .maybe_equatorial_radius() + .try_equatorial_radius() .expect("equatorial radius should be available") } fn flattening(&self) -> f64 { self.body - .maybe_flattening() + .try_flattening() .expect("flattening should be available") } @@ -198,7 +198,7 @@ pub enum GroundPropagatorError { IcrfToBodyFixedError(#[from] IcrfToBodyFixedError), } -pub struct GroundPropagator { +pub struct GroundPropagator { location: GroundLocation, frame: R, // FIXME: We should not take ownership of the provider here diff --git a/crates/lox-orbits/src/propagators/semi_analytical.rs b/crates/lox-orbits/src/propagators/semi_analytical.rs index 24ebd7ba..f5c34a5f 100644 --- a/crates/lox-orbits/src/propagators/semi_analytical.rs +++ b/crates/lox-orbits/src/propagators/semi_analytical.rs @@ -8,7 +8,7 @@ use thiserror::Error; -use lox_bodies::{DynOrigin, MaybePointMass, Origin, PointMass}; +use lox_bodies::{DynOrigin, Origin, PointMass, TryPointMass}; use lox_time::TimeLike; use crate::frames::{CoordinateSystem, DynFrame, Icrf, ReferenceFrame}; @@ -44,13 +44,13 @@ where impl Vallado where T: TimeLike, - O: MaybePointMass + Clone, + O: TryPointMass + Clone, R: ReferenceFrame, { fn gravitational_parameter(&self) -> f64 { self.initial_state .origin() - .maybe_gravitational_parameter() + .try_gravitational_parameter() .expect("gravitational parameter should be available") } @@ -88,8 +88,8 @@ where pub fn with_dynamic(initial_state: DynState) -> Result { if initial_state .origin() - .maybe_gravitational_parameter() - .is_none() + .try_gravitational_parameter() + .is_err() || initial_state.reference_frame() != DynFrame::Icrf { return Err("invalid frame or origin"); @@ -104,7 +104,7 @@ where impl Propagator for Vallado where T: TimeLike + Clone, - O: MaybePointMass + Clone, + O: TryPointMass + Clone, R: ReferenceFrame + Clone, { type Error = ValladoError; diff --git a/crates/lox-orbits/src/python.rs b/crates/lox-orbits/src/python.rs index b951f1d7..1d341c89 100644 --- a/crates/lox-orbits/src/python.rs +++ b/crates/lox-orbits/src/python.rs @@ -245,9 +245,7 @@ impl PyState { "only inertial frames are supported for conversion to Keplerian elements", )); } - Ok(PyKeplerian( - self.0.try_to_keplerian().map_err(PyValueError::new_err)?, - )) + Ok(PyKeplerian(self.0.try_to_keplerian()?)) } fn rotation_lvlh<'py>(&self, py: Python<'py>) -> PyResult>> { diff --git a/crates/lox-orbits/src/states.rs b/crates/lox-orbits/src/states.rs index 78f23302..9e1b156f 100644 --- a/crates/lox-orbits/src/states.rs +++ b/crates/lox-orbits/src/states.rs @@ -8,7 +8,8 @@ use glam::{DMat3, DVec3}; use itertools::Itertools; use lox_bodies::{ - DynOrigin, MaybePointMass, MaybeSpheroid, Origin, PointMass, RotationalElements, Spheroid, + DynOrigin, Origin, PointMass, RotationalElements, Spheroid, TryPointMass, TrySpheroid, + UndefinedOriginPropertyError, }; use lox_ephem::{path_from_ids, Ephemeris}; use lox_math::glam::Azimuth; @@ -179,9 +180,9 @@ impl DynState { } let r = self.position(); // TODO: Check/transform frame - let (Some(r_eq), Some(f)) = ( - self.origin.maybe_equatorial_radius(), - self.origin.maybe_flattening(), + let (Ok(r_eq), Ok(f)) = ( + self.origin.try_equatorial_radius(), + self.origin.try_flattening(), ) else { return Err(StateToDynGroundError::UndefinedSpheroid(self.origin)); }; @@ -420,10 +421,8 @@ impl DynState where T: TimeLike + Clone, { - pub fn try_to_keplerian(&self) -> Result, &'static str> { - let Some(mu) = self.origin.maybe_gravitational_parameter() else { - return Err("no gravitational parameter"); - }; + pub fn try_to_keplerian(&self) -> Result, UndefinedOriginPropertyError> { + let mu = self.origin.try_gravitational_parameter()?; let r = self.position(); let v = self.velocity(); diff --git a/tools/lox-gen/src/common.rs b/tools/lox-gen/src/common.rs index 537698ae..314c8878 100644 --- a/tools/lox-gen/src/common.rs +++ b/tools/lox-gen/src/common.rs @@ -1,6 +1,7 @@ use proc_macro2::TokenStream; use std::fs; use std::path::Path; +use std::process::Command; pub const COPYRIGHT_NOTICE: &str = "/* * Copyright (c) 2024. Helge Eichhorn and the LOX contributors @@ -12,16 +13,16 @@ pub const COPYRIGHT_NOTICE: &str = "/* pub const AUTO_GENERATION_NOTICE: &str = "// Auto-generated by `lox-gen`. Do not edit!\n\n"; -pub fn format(ts: TokenStream) -> String { - let file = syn::parse2(ts).unwrap(); - prettyplease::unparse(&file) -} - pub fn write_file(dir: &Path, file: &str, code: TokenStream) { let mut module = String::from(COPYRIGHT_NOTICE); module.push_str(AUTO_GENERATION_NOTICE); - module.push_str(&format(code)); + module.push_str(code.to_string().as_str()); let out = dir.join(file); fs::write(&out, module).expect("file should be writeable"); + + Command::new("rustfmt") + .args([out.to_str().unwrap()]) + .status() + .expect("formatting should work"); } diff --git a/tools/lox-gen/src/origins.rs b/tools/lox-gen/src/origins.rs index eb6468f5..ad550073 100644 --- a/tools/lox-gen/src/origins.rs +++ b/tools/lox-gen/src/origins.rs @@ -1007,10 +1007,6 @@ pub fn generate_bodies(path: &Path, pck: &Kernel, gm: &Kernel) { let mut code = quote! { use crate::DynOrigin; use crate::Elements; - use crate::MaybeMeanRadius; - use crate::MaybePointMass; - use crate::MaybeSpheroid; - use crate::MaybeTriaxialEllipsoid; use crate::MeanRadius; use crate::NaifId; use crate::NutationPrecessionCoefficients; @@ -1022,8 +1018,12 @@ pub fn generate_bodies(path: &Path, pck: &Kernel, gm: &Kernel) { use crate::RotationalElements; use crate::Spheroid; use crate::TriaxialEllipsoid; + use crate::TryMeanRadius; + use crate::TryPointMass; use crate::TryRotationalElements; - use crate::UndefinedRotationalElementsError; + use crate::TrySpheroid; + use crate::TryTriaxialEllipsoid; + use crate::UndefinedOriginPropertyError; use std::fmt::Display; use std::fmt::Formatter; }; @@ -1088,7 +1088,7 @@ pub fn generate_bodies(path: &Path, pck: &Kernel, gm: &Kernel) { }); point_mass_match_arms.extend(quote! { - DynOrigin::#ident => Some(#gm), + DynOrigin::#ident => Ok(#gm), }); }; @@ -1107,7 +1107,7 @@ pub fn generate_bodies(path: &Path, pck: &Kernel, gm: &Kernel) { }); mean_radius_match_arms.extend(quote! { - DynOrigin::#ident => Some(#mean_radius), + DynOrigin::#ident => Ok(#mean_radius), }) } @@ -1130,7 +1130,7 @@ pub fn generate_bodies(path: &Path, pck: &Kernel, gm: &Kernel) { } ellipsoid_match_arms.extend(quote! { - DynOrigin::#ident => Some((#(#radii),*)), + DynOrigin::#ident => Ok((#(#radii),*)), }) } @@ -1291,47 +1291,72 @@ pub fn generate_bodies(path: &Path, pck: &Kernel, gm: &Kernel) { code.extend(nut_prec_constants); code.extend(quote! { - impl MaybePointMass for DynOrigin { - fn maybe_gravitational_parameter(&self) -> Option { + impl TryPointMass for DynOrigin { + fn try_gravitational_parameter(&self) -> Result { match self { #point_mass_match_arms - _ => None, + _ => Err( + UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "gravitational parameter".to_string(), + } + ), } } } - impl MaybeMeanRadius for DynOrigin { - fn maybe_mean_radius(&self) -> Option { + impl TryMeanRadius for DynOrigin { + fn try_mean_radius(&self) -> Result { match self { #mean_radius_match_arms - _ => None, + _ => Err( + UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "mean radius".to_string(), + } + ), } } } - impl MaybeTriaxialEllipsoid for DynOrigin { - fn maybe_radii(&self) -> Option { + impl TryTriaxialEllipsoid for DynOrigin { + fn try_radii(&self) -> Result { match self { #ellipsoid_match_arms - _ => None, + _ => Err( + UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "radii".to_string(), + } + ), } } } - impl MaybeSpheroid for DynOrigin {} + impl TrySpheroid for DynOrigin {} impl TryRotationalElements for DynOrigin { fn try_rotational_elements(&self, t: f64) - -> Result { + -> Result { match self { #rotational_elements_match_arms - _ => Err(UndefinedRotationalElementsError(self.name().to_string())), + _ => Err( + UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "rotational elements".to_string(), + } + ), } } fn try_rotational_element_rates( &self, t: f64, - ) -> Result { + ) -> Result { match self { #rotational_element_rates_match_arms - _ => Err(UndefinedRotationalElementsError(self.name().to_string())), + _ => Err( + UndefinedOriginPropertyError { + origin: self.to_string(), + prop: "rotational element rates".to_string(), + } + ), } } }