Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleaning up Nyx in prep for 2.0.0 #391

Merged
merged 14 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,65 +32,56 @@ exclude = [

[badges]
maintenance = { status = "actively-developed" }
gitlab = { repository = "nyx-space/nyx", branch = "master" }
github = { repository = "nyx-space/nyx", branch = "master" }

[dependencies]
nalgebra = "0.33"
log = "0.4"
hifitime = "4.0.0"
anise = "0.5.0"
anise = "0.5.2"
flate2 = { version = "1.0", features = [
"rust_backend",
], default-features = false }
serde = "1.0"
serde_derive = "1.0"
csv = "1"
hyperdual = "1.3.0"
bytes = "1.0"
rand = "0.8"
rand_distr = "0.4"
regex = "1.5"
rayon = "1.6"
lazy_static = "1.4.0"
approx = "0.5"
rand_pcg = "0.3"
indicatif = { version = "0.17", features = ["rayon"] }
indicatif = { version = "0.17", features = ["rayon"], default-features = false }
rstats = "2.0.1"
parquet = { version = "53.0.0", default-features = false, features = [
parquet = { version = "54.0.0", default-features = false, features = [
"arrow",
"zstd",
] }
arrow = "53.0.0"
shadow-rs = { version = "0.36.0", default-features = false }
arrow = "54.0.0"
shadow-rs = { version = "0.37.0", default-features = false }
serde_yml = "0.0.12"
whoami = "1.3.0"
either = { version = "1.8.1", features = ["serde"] }
num = "0.4.0"
enum-iterator = "2.0.0"
getrandom = { version = "0.2", features = ["js"] }
typed-builder = "0.20.0"
snafu = { version = "0.8.3", features = ["backtrace"] }
serde_dhall = "0.12"
indexmap = {version = "2.6.0", features = ["serde"]}
indexmap = { version = "2.6.0", features = ["serde"] }


[dev-dependencies]
polars = { version = "0.43.1", features = ["parquet"] }
polars = { version = "0.45.1", features = ["parquet"] }
rstest = "0.23.0"
pretty_env_logger = "0.5"
toml = "0.8.14"

[build-dependencies]
shadow-rs = "0.36.0"
shadow-rs = "0.37.0"

[features]
default = []
# python = ["pyo3", "pyo3-log", "hifitime/python", "numpy", "pythonize"]
python = []

[lib]
crate-type = ["cdylib", "rlib"]
name = "nyx_space"
# Uncomment to speed up local builds
# [profile.dev.package."*"]
# opt-level = 3

[target.x86_64-unknown-linux-gnu]
# For flamegraph -- https://github.com/flamegraph-rs/flamegraph
Expand Down
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[**Empowering flight dynamics engineers with open-source software**][website]

Nyx is revolutionizing the field of flight dynamics engineering as a powerful, open-source tool for mission design and orbit determination. From trajectory optimization to orbit estimation, Nyx is built for speed, automation, and scalability. It dramatically reduces simulation time compared to commercial products, and integrates seamlessly into automated workflows across various platforms.
Nyx is revolutionizing the field of flight dynamics engineering as a powerful, open-source tool for mission design and orbit determination. From trajectory optimization to orbit estimation, Nyx is built for speed, automation, and scalability.

**Nyx has proven mission-critical reliability, already contributing to the success of three lunar missions.**

Expand All @@ -13,6 +13,28 @@ Nyx is revolutionizing the field of flight dynamics engineering as a powerful, o
[![nyx-space on docs.rs][docsrs-image]][docsrs]
[![codecov](https://codecov.io/gh/nyx-space/nyx/graph/badge.svg?token=gEiAvwzwh5)](https://codecov.io/gh/nyx-space/nyx)

# Showcase

[The website has the latest use cases][showcase]

## GEO Low Thrust Orbit Raising & StationKeeping

[Click for description](https://nyxspace.com/nyxspace/showcase/03_geo_analysis/?utm_source=readme-showcase)

[![RAAN, AOP, INC over time](./examples/03_geo_analysis/plots/raise-traj-3d.png)](https://nyxspace.com/nyxspace/showcase/03_geo_analysis/?utm_source=readme-showcase)

## James Webb Space Telescope Monte Carlo Simulation

[Click for description](https://nyxspace.com/nyxspace/showcase/02_jwst_covar_monte_carlo/?utm_source=readme-showcase)

[![RAAN, AOP, INC over time](./examples/02_jwst_covar_monte_carlo/plots/jwst_mc_inc_deg.png)](https://nyxspace.com/nyxspace/showcase/02_jwst_covar_monte_carlo/?utm_source=readme-showcase)

## Orbit Determination of the Lunar Reconnaissance Orbiter

[Click for description](https://nyxspace.com/nyxspace/showcase/04_lro_od/?utm_source=readme-showcase)

[![RAAN, AOP, INC over time](./examples/04_lro_od/plots/doppler-resid.png)](https://nyxspace.com/nyxspace/showcase/04_lro_od/?utm_source=readme-showcase)

# Documentation

The documentation is currently being updated. If you have specific use cases you would like to see documented, please [open a Github issue](https://github.com/nyx-space/nyx/issues/new?assignees=&labels=Documentation&projects=&template=documentation.md&title=) or [use the contact form][contact]
Expand Down Expand Up @@ -49,8 +71,10 @@ Nyx is provided under the [AGPLv3 License](./LICENSE). By using this software, y
[contact]: https://7ug5imdtt8v.typeform.com/to/neFvVW3p
[nyxspace-image]: https://img.shields.io/badge/Nyx_Space-Website-orange
[website]: https://nyxspace.com/?utm_source=readme
[showcase]: https://nyxspace.com/nyxspace/showcase/?utm_source=readme

# Author information

> Chris Rabotin is a GNC and flight dynamics engineer with a heavy background in software.

I currently work for Rocket Lab USA as the lead flight dynamics engineer on both Blue Ghost lunar lander missions. -- Find me on [LinkedIn](https://www.linkedin.com/in/chrisrabotin/).
8 changes: 6 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
fn main() -> shadow_rs::SdResult<()> {
shadow_rs::new()
use shadow_rs::ShadowBuilder;

fn main() {
ShadowBuilder::builder()
.build()
.expect("shadow init for nyx_space failed");
}
10 changes: 6 additions & 4 deletions data/tests/config/spacecraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ orbit:
frame: EME2000
epoch: 2018-09-15T00:15:53.098 UTC
srp:
cr: 1.0
coeff_reflectivity:1.0
area_m2: 2.0
drag:
cd: 2.2
coeff_drag: 2.2
area_m2: 0.95
dry_mass_kg: 50.0
fuel_mass_kg: 50.0
mass:
dry_mass_kg: 50.0
prop_mass_kg: 50.0
extra_mass_kg: 0.0
thruster:
thrust_N: 1e-5
isp_s: 300.0
21 changes: 15 additions & 6 deletions examples/01_orbit_prop/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ use anise::{
use hifitime::{Epoch, Unit};
use log::warn;
use nyx::{
cosmic::{MetaAlmanac, Orbit, SrpConfig},
cosmic::{Mass, MetaAlmanac, Orbit, SRPData},
dynamics::{Harmonics, OrbitalDynamics, SolarPressure, SpacecraftDynamics},
io::{gravity::HarmonicsMem, ExportCfg},
od::GroundStation,
propagators::Propagator,
Spacecraft, State,
};
use polars::{df, series::ChunkCompare};
use polars::{
frame::column::ScalarColumn,
prelude::{df, AnyValue, ChunkCompareIneq, Column, DataType, Scalar},
};

use std::{error::Error, sync::Arc};

Expand Down Expand Up @@ -91,10 +94,10 @@ fn main() -> Result<(), Box<dyn Error>> {
// Let's build a cubesat sized spacecraft, with an SRP area of 10 cm^2 and a mass of 9.6 kg.
let sc = Spacecraft::builder()
.orbit(orbit)
.dry_mass_kg(9.60)
.srp(SrpConfig {
.mass(Mass::from_dry_mass(9.60))
.srp(SRPData {
area_m2: 10e-4,
cr: 1.1,
coeff_reflectivity: 1.1,
})
.build();
println!("{sc:x}");
Expand Down Expand Up @@ -274,7 +277,13 @@ fn main() -> Result<(), Box<dyn Error>> {
)?;

// Finally, let's see when the spacecraft is visible, assuming 15 degrees minimum elevation.
let mask = aer_df.column("elevation (deg)")?.gt(15.0)?;
let mask = aer_df
.column("elevation (deg)")?
.gt(&Column::Scalar(ScalarColumn::new(
"elevation mask (deg)".into(),
Scalar::new(DataType::Float64, AnyValue::Float64(15.0)),
offset_s.len(),
)))?;
let cubesat_visible = aer_df.filter(&mask)?;

println!("{cubesat_visible}");
Expand Down
8 changes: 4 additions & 4 deletions examples/02_jwst_covar_monte_carlo/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use anise::{
};
use hifitime::{TimeUnits, Unit};
use nyx::{
cosmic::{eclipse::EclipseLocator, Frame, MetaAlmanac, SrpConfig},
cosmic::{eclipse::EclipseLocator, Frame, Mass, MetaAlmanac, SRPData},
dynamics::{guidance::LocalFrame, OrbitalDynamics, SolarPressure, SpacecraftDynamics},
io::ExportCfg,
mc::MonteCarlo,
Expand Down Expand Up @@ -62,11 +62,11 @@ fn main() -> Result<(), Box<dyn Error>> {
// SRP Coefficient of reflectivity assumed to be that of Kapton, i.e. 2 - 0.44 = 1.56, table 1 from https://amostech.com/TechnicalPapers/2018/Poster/Bengtson.pdf
let jwst = Spacecraft::builder()
.orbit(jwst_orbit)
.srp(SrpConfig {
.srp(SRPData {
area_m2: 21.197 * 14.162,
cr: 1.56,
coeff_reflectivity: 1.56,
})
.dry_mass_kg(6200.0)
.mass(Mass::from_dry_mass(6200.0))
.build();

// Build up the spacecraft uncertainty builder.
Expand Down
6 changes: 3 additions & 3 deletions examples/03_geo_analysis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ To build the following plots, use the `plot_3d_traj.py` script and the `plot_orb

![Orbital elements during orbit raise](./plots/raise-keplerian-oe.png)

In the two follow plots, the colors correspond to the remaining fuel mass, thereby showing the fuel depletion over the orbit raise.
In the two follow plots, the colors correspond to the remaining prop mass, thereby showing the prop depletion over the orbit raise.

![3D traj raise](./plots/raise-traj-3d.png)

Expand All @@ -112,7 +112,7 @@ To run the [station keeping Monte Carlo](./stationkeeping.rs) example, just exec
RUST_LOG=info cargo run --example 03_geo_sk --release
```

Over a two week period, this two-ton spacecraft would need roughly 0.8 kg of fuel (if using the _NEXT-STEP_ engine, cf. the comments in the drift analysis code) +/- 0.1 kg for station keeping.
Over a two week period, this two-ton spacecraft would need roughly 0.8 kg of prop (if using the _NEXT-STEP_ engine, cf. the comments in the drift analysis code) +/- 0.1 kg for station keeping.

![Fuel mass](./plots/sk-fuel-mass.png)

Expand All @@ -123,4 +123,4 @@ The inclination plot shows when the guidance law turns on, and shows that we mai

### Further analysis

Additional analysis would run this Monte Carlo for longer and with many more spacecraft (upward of 100), and crucially ensure that the Ruggiero guidance law bounds correspond to the GEO box. Subsequently, one should implement the Q-Law guidance law for more fuel economy. Finally, the analysis should also include a variation on the tightness of the box, especially if the vehicle is equipped with a variable thrust engine as one may wish to drift less out of the SK box and keep the engine at a lower thrust level, or vice versa.
Additional analysis would run this Monte Carlo for longer and with many more spacecraft (upward of 100), and crucially ensure that the Ruggiero guidance law bounds correspond to the GEO box. Subsequently, one should implement the Q-Law guidance law for more prop economy. Finally, the analysis should also include a variation on the tightness of the box, especially if the vehicle is equipped with a variable thrust engine as one may wish to drift less out of the SK box and keep the engine at a lower thrust level, or vice versa.
8 changes: 4 additions & 4 deletions examples/03_geo_analysis/drift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use anise::{
};
use hifitime::{Epoch, Unit};
use nyx::{
cosmic::{eclipse::EclipseLocator, MetaAlmanac, Orbit, SrpConfig},
cosmic::{eclipse::EclipseLocator, Mass, MetaAlmanac, Orbit, SRPData},
dynamics::{Harmonics, OrbitalDynamics, SolarPressure, SpacecraftDynamics},
io::{gravity::HarmonicsMem, ExportCfg},
propagators::Propagator,
Expand Down Expand Up @@ -61,10 +61,10 @@ fn main() -> Result<(), Box<dyn Error>> {
// Let's build a cubesat sized spacecraft, with an SRP area of 10 cm^2 and a mass of 9.6 kg.
let sc = Spacecraft::builder()
.orbit(orbit)
.dry_mass_kg(9.60)
.srp(SrpConfig {
.mass(Mass::from_dry_mass(9.60))
.srp(SRPData {
area_m2: 10e-4,
cr: 1.1,
coeff_reflectivity: 1.1,
})
.build();
println!("{sc:x}");
Expand Down
4 changes: 2 additions & 2 deletions examples/03_geo_analysis/plot_3d_traj.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def build_sphere(size, num_points=500, opacity=1.0):

def plot_traj(
df: pl.DataFrame,
colored_by="fuel_mass (kg)",
color_descr="fuel mass (kg)",
colored_by="prop_mass (kg)",
color_descr="prop mass (kg)",
scale=1.0
):
"""
Expand Down
2 changes: 1 addition & 1 deletion examples/03_geo_analysis/plot_sk_mc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"ta (deg)",
"aol (deg)",
"tlong (deg)",
"fuel_mass (kg)",
"prop_mass (kg)",
]

for col in columns:
Expand Down
11 changes: 5 additions & 6 deletions examples/03_geo_analysis/raise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use anise::{
};
use hifitime::{Epoch, TimeUnits, Unit};
use nyx::{
cosmic::{eclipse::EclipseLocator, GuidanceMode, MetaAlmanac, Orbit, SrpConfig},
cosmic::{eclipse::EclipseLocator, GuidanceMode, Mass, MetaAlmanac, Orbit, SRPData},
dynamics::{
guidance::{GuidanceLaw, Ruggiero, Thruster},
Harmonics, OrbitalDynamics, SolarPressure, SpacecraftDynamics,
Expand Down Expand Up @@ -51,9 +51,8 @@ fn main() -> Result<(), Box<dyn Error>> {

let sc = Spacecraft::builder()
.orbit(orbit)
.dry_mass_kg(1000.0) // 1000 kg of dry mass
.fuel_mass_kg(1000.0) // 1000 kg of fuel, totalling 2.0 tons
.srp(SrpConfig::from_area(3.0 * 6.0)) // Assuming 1 kW/m^2 or 18 kW, giving a margin of 4.35 kW for on-propulsion consumption
.mass(Mass::from_dry_and_prop_masses(1000.0, 1000.0)) // 1000 kg of dry mass and prop, totalling 2.0 tons
.srp(SRPData::from_area(3.0 * 6.0)) // Assuming 1 kW/m^2 or 18 kW, giving a margin of 4.35 kW for on-propulsion consumption
.thruster(Thruster {
// "NEXT-STEP" row in Table 2
isp_s: 4435.0,
Expand Down Expand Up @@ -125,9 +124,9 @@ fn main() -> Result<(), Box<dyn Error>> {
.with(sc, almanac.clone())
.for_duration_with_traj(prop_time)?;

let fuel_usage = sc.fuel_mass_kg - final_state.fuel_mass_kg;
let prop_usage = sc.mass.prop_mass_kg - final_state.mass.prop_mass_kg;
println!("{:x}", final_state.orbit);
println!("fuel usage: {:.3} kg", fuel_usage);
println!("prop usage: {:.3} kg", prop_usage);

// Finally, export the results for analysis, including the penumbra percentage throughout the orbit raise.
traj.to_parquet(
Expand Down
7 changes: 3 additions & 4 deletions examples/03_geo_analysis/stationkeeping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use anise::{
};
use hifitime::{Epoch, TimeUnits, Unit};
use nyx::{
cosmic::{eclipse::EclipseLocator, GuidanceMode, MetaAlmanac, Orbit, SrpConfig},
cosmic::{eclipse::EclipseLocator, GuidanceMode, Mass, MetaAlmanac, Orbit, SRPData},
dynamics::{
guidance::{Ruggiero, Thruster},
Harmonics, OrbitalDynamics, SolarPressure, SpacecraftDynamics,
Expand All @@ -38,9 +38,8 @@ fn main() -> Result<(), Box<dyn Error>> {

let sc = Spacecraft::builder()
.orbit(orbit)
.dry_mass_kg(1000.0) // 1000 kg of dry mass
.fuel_mass_kg(1000.0) // 1000 kg of fuel, totalling 2.0 tons
.srp(SrpConfig::from_area(3.0 * 6.0)) // Assuming 1 kW/m^2 or 18 kW, giving a margin of 4.35 kW for on-propulsion consumption
.mass(Mass::from_dry_and_prop_masses(1000.0, 1000.0)) // 1000 kg of dry mass and prop, totalling 2.0 tons
.srp(SRPData::from_area(3.0 * 6.0)) // Assuming 1 kW/m^2 or 18 kW, giving a margin of 4.35 kW for on-propulsion consumption
.thruster(Thruster {
// "NEXT-STEP" row in Table 2
isp_s: 4435.0,
Expand Down
10 changes: 4 additions & 6 deletions examples/04_lro_od/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use anise::{
};
use hifitime::{Epoch, TimeUnits, Unit};
use nyx::{
cosmic::{Aberration, Frame, MetaAlmanac, SrpConfig},
cosmic::{Aberration, Frame, Mass, MetaAlmanac, SRPData},
dynamics::{
guidance::LocalFrame, Harmonics, OrbitalDynamics, SolarPressure, SpacecraftDynamics,
},
Expand Down Expand Up @@ -77,12 +77,11 @@ fn main() -> Result<(), Box<dyn Error>> {

// To build the trajectory we need to provide a spacecraft template.
let sc_template = Spacecraft::builder()
.dry_mass_kg(1018.0) // Launch masses
.fuel_mass_kg(900.0)
.srp(SrpConfig {
.mass(Mass::from_dry_and_prop_masses(1018.0, 900.0)) // Launch masses
.srp(SRPData {
// SRP configuration is arbitrary, but we will be estimating it anyway.
area_m2: 3.9 * 2.7,
cr: 0.96,
coeff_reflectivity: 0.96,
})
.orbit(Orbit::zero(MOON_J2000)) // Setting a zero orbit here because it's just a template
.build();
Expand Down Expand Up @@ -125,7 +124,6 @@ fn main() -> Result<(), Box<dyn Error>> {
// The harmonics must be computed in the body fixed frame.
// We're using the long term prediction of the Moon principal axes frame.
let moon_pa_frame = MOON_PA_FRAME.with_orient(31008);
// let moon_pa_frame = IAU_MOON_FRAME;
let sph_harmonics = Harmonics::from_stor(
almanac.frame_from_uid(moon_pa_frame)?,
HarmonicsMem::from_shadr(&jggrx_meta.uri, 80, 80, true)?,
Expand Down
Loading
Loading