Skip to content
Closed
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
2 changes: 1 addition & 1 deletion examples/01_orbit_prop/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Set up the spacecraft dynamics.

// Specify that the orbital dynamics must account for the graviational pull of the Moon and the Sun.
// The gravity of the Earth will also be accounted for since the spaceraft in an Earth orbit.
// The gravity of the Earth will also be accounted for since the spacecraft in an Earth orbit.
let mut orbital_dyn = OrbitalDynamics::point_masses(vec![MOON, SUN]);

// We want to include the spherical harmonics, so let's download the gravitational data from the Nyx Cloud.
Expand Down
2 changes: 1 addition & 1 deletion examples/03_geo_analysis/drift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Set up the spacecraft dynamics.

// Specify that the orbital dynamics must account for the graviational pull of the Moon and the Sun.
// The gravity of the Earth will also be accounted for since the spaceraft in an Earth orbit.
// The gravity of the Earth will also be accounted for since the spacecraft in an Earth orbit.
let mut orbital_dyn = OrbitalDynamics::point_masses(vec![MOON, SUN]);

// We want to include the spherical harmonics, so let's download the gravitational data from the Nyx Cloud.
Expand Down
2 changes: 1 addition & 1 deletion examples/03_geo_analysis/raise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Set up the spacecraft dynamics.

// Specify that the orbital dynamics must account for the graviational pull of the Moon and the Sun.
// The gravity of the Earth will also be accounted for since the spaceraft in an Earth orbit.
// The gravity of the Earth will also be accounted for since the spacecraft in an Earth orbit.
let mut orbital_dyn = OrbitalDynamics::point_masses(vec![MOON, SUN]);

// We want to include the spherical harmonics, so let's download the gravitational data from the Nyx Cloud.
Expand Down
2 changes: 1 addition & 1 deletion examples/04_lro_od/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Set up the spacecraft dynamics.

// Specify that the orbital dynamics must account for the graviational pull of the Earth and the Sun.
// The gravity of the Moon will also be accounted for since the spaceraft in a lunar orbit.
// The gravity of the Moon will also be accounted for since the spacecraft in a lunar orbit.
let mut orbital_dyn = OrbitalDynamics::point_masses(vec![EARTH, SUN, JUPITER_BARYCENTER]);

// We want to include the spherical harmonics, so let's download the gravitational data from the Nyx Cloud.
Expand Down
42 changes: 21 additions & 21 deletions src/dynamics/drag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,18 @@ pub enum AtmDensity {
StdAtm { max_alt_m: f64 },
}

/// `ConstantDrag` implements a constant drag model as defined in Vallado, 4th ed., page 551, with an important caveat.
/// Implements a constant drag model as defined in Vallado, 4th ed., page 551.
///
/// **WARNING:** This basic model assumes that the velocity of the spacecraft is identical to the velocity of the upper atmosphere,
/// This is a **bad** assumption and **should not** be used for high fidelity simulations.
/// This will be resolved after https://gitlab.com/chrisrabotin/nyx/issues/93 is implemented.
/// **WARNING:** This model assumes the spacecraft velocity is identical to the upper atmosphere velocity,
/// which is a significant simplification. Not for high-fidelity simulations.
/// This will be resolved after https://github.com/nyx-space/nyx/issues/93 is implemented.
#[derive(Clone)]
pub struct ConstantDrag {
/// atmospheric density in kg/m^3
/// Atmospheric density in kg/m^3.
pub rho: f64,
/// Geoid causing the drag
/// Geoid causing the drag.
pub drag_frame: Frame,
/// Set to true to estimate the coefficient of drag
/// Set to true to estimate the coefficient of drag.
pub estimate: bool,
}

Expand Down Expand Up @@ -78,7 +78,7 @@ impl ForceModel for ConstantDrag {
})?;

let velocity = osc.velocity_km_s;
// Note the 1e3 factor to convert drag units from ((kg * km^2 * s^-2) / m^1) to (kg * km * s^-2)
// A factor of 1e3 is needed to convert the acceleration to km/s^2.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undo this change, the previous comment made the units explicit and it's very helpful here.

Ok(-0.5
* 1e3
* self.rho
Expand All @@ -99,14 +99,14 @@ impl ForceModel for ConstantDrag {
}
}

/// `Drag` implements all three drag models.
/// Implements three drag models.
#[derive(Clone)]
pub struct Drag {
/// Density computation method
/// The density computation method.
pub density: AtmDensity,
/// Frame to compute the drag in
/// The frame to compute the drag in.
pub drag_frame: Frame,
/// Set to true to estimate the coefficient of drag
/// Set to true to estimate the coefficient of drag.
pub estimate: bool,
}

Expand Down Expand Up @@ -175,7 +175,7 @@ impl ForceModel for Drag {
match self.density {
AtmDensity::Constant(rho) => {
let velocity = osc_drag_frame.velocity_km_s;
// Note the 1e3 factor to convert drag units from ((kg * km^2 * s^-2) / m^1) to (kg * km * s^-2)
// A factor of 1e3 is needed to convert the acceleration to km/s^2.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undo this change.

Ok(-0.5
* 1e3
* rho
Expand All @@ -202,8 +202,8 @@ impl ForceModel for Drag {
/ ref_alt_m)
.exp();

// TODO: Drag modeling will be improved in https://github.com/nyx-space/nyx/issues/317
// The frame will be double checked in this PR as well.
// TODO: Drag modeling will be improved in https://github.com/nyx-space/nyx/issues/317.
// The frame will be double-checked in this PR as well.
let velocity_integr_frame = almanac
.transform_to(osc_drag_frame, integration_frame, None)
.context(DynamicsAlmanacSnafu {
Expand All @@ -212,7 +212,7 @@ impl ForceModel for Drag {
.velocity_km_s;

let velocity = velocity_integr_frame - osc_drag_frame.velocity_km_s;
// Note the 1e3 factor to convert drag units from ((kg * km^2 * s^-2) / m^1) to (kg * km * s^-2)
// A factor of 1e3 is needed to convert the acceleration to km/s^2.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undo this change

Ok(-0.5
* 1e3
* rho
Expand All @@ -230,11 +230,11 @@ impl ForceModel for Drag {
.context(AstroPhysicsSnafu)
.context(DynamicsAstroSnafu)?;
let rho = if altitude_km > max_alt_m / 1_000.0 {
// Use a constant density
// Use a constant density.
10.0_f64.powf((-7e-5) * altitude_km - 14.464)
} else {
// Code from AVS/Schaub's Basilisk
// Calculating the density based on a scaled 6th order polynomial fit to the log of density
// Code from AVS/Schaub's Basilisk.
// Calculating the density based on a scaled 6th order polynomial fit to the log of density.
let scale = (altitude_km - 526.8000) / 292.8563;
let logdensity =
0.34047 * scale.powi(6) - 0.5889 * scale.powi(5) - 0.5269 * scale.powi(4)
Expand All @@ -243,7 +243,7 @@ impl ForceModel for Drag {
- 2.3024 * scale
- 12.575;

/* Calculating density by raising 10 to the log of density */
// Calculating density by raising 10 to the log of density.
10.0_f64.powf(logdensity)
};

Expand All @@ -255,7 +255,7 @@ impl ForceModel for Drag {
.velocity_km_s;

let velocity = velocity_integr_frame - osc_drag_frame.velocity_km_s;
// Note the 1e3 factor to convert drag units from ((kg * km^2 * s^-2) / m^1) to (kg * km * s^-2)
// A factor of 1e3 is needed to convert the acceleration to km/s^2.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undo this change

Ok(-0.5
* 1e3
* rho
Expand Down
83 changes: 42 additions & 41 deletions src/dynamics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,43 +31,42 @@ use std::sync::Arc;

pub use crate::errors::NyxError;

/// The orbital module handles all Cartesian based orbital dynamics.
/// Cartesian-based orbital dynamics.
///
/// It is up to the engineer to ensure that the coordinate frames of the different dynamics borrowed
/// from this module match, or perform the appropriate coordinate transformations.
/// Ensure coordinate frames match or perform transformations when combining dynamics.
pub mod orbital;
use self::guidance::GuidanceError;
pub use self::orbital::*;

/// The spacecraft module allows for simulation of spacecraft dynamics in general, including propulsion/maneuvers.
/// Spacecraft dynamics, including propulsion and maneuvers.
pub mod spacecraft;
pub use self::spacecraft::*;

/// Defines a few examples of guidance laws.
/// Guidance laws.
pub mod guidance;

/// Defines some velocity change controllers.
/// Velocity change controllers.
pub mod deltavctrl;

/// Defines solar radiation pressure models
/// Solar radiation pressure models.
pub mod solarpressure;
pub use self::solarpressure::*;

/// The drag module handles drag in a very basic fashion. Do not use for high fidelity dynamics.
/// Atmospheric drag models.
pub mod drag;
pub use self::drag::*;

/// Define the spherical harmonic models.
/// This module allows loading gravity models from [PDS](http://pds-geosciences.wustl.edu/), [EGM2008](http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/) and GMAT's own COF files.
/// Spherical harmonic gravity models.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undo this change

///
/// Supports loading models from PDS, EGM2008, and GMAT's COF files.
pub mod sph_harmonics;
pub use self::sph_harmonics::*;

/// The `Dynamics` trait handles and stores any equation of motion *and* the state is integrated.
/// A trait for models with equations of motion that can be integrated.
///
/// Its design is such that several of the provided dynamics can be combined fairly easily. However,
/// when combining the dynamics (e.g. integrating both the attitude of a spaceraft and its orbital
/// parameters), it is up to the implementor to handle time and state organization correctly.
/// For time management, I highly recommend using `hifitime` which is thoroughly validated.
/// This trait is designed for composition, allowing different dynamics to be combined.
/// When combining dynamics, ensure that time and state are handled consistently.
/// `hifitime` is recommended for time management.
#[allow(clippy::type_complexity)]
pub trait Dynamics: Clone + Sync + Send
where
Expand All @@ -79,11 +78,11 @@ where
type HyperdualSize: DimName;
type StateType: State;

/// Defines the equations of motion for these dynamics, or a combination of provided dynamics.
/// The time delta_t is in **seconds** PAST the context epoch. The state vector is the state which
/// changes for every intermediate step of the integration. The state context is the state of
/// what is being propagated, it should allow rebuilding a new state context from the
/// provided state vector.
/// Defines the equations of motion.
///
/// - `delta_t`: Time in seconds past the context epoch.
/// - `state_vec`: The state vector, which changes at each integration step.
/// - `state_ctx`: The state context, used to rebuild the state from the state vector.
fn eom(
&self,
delta_t: f64,
Expand All @@ -94,9 +93,9 @@ where
where
DefaultAllocator: Allocator<<Self::StateType as State>::VecLength>;

/// Defines the equations of motion for Dual numbers for these dynamics.
/// _All_ dynamics need to allow for automatic differentiation. However, if differentiation is not supported,
/// then the dynamics should prevent initialization with a context which has an STM defined.
/// Defines the equations of motion for dual numbers, enabling automatic differentiation.
///
/// If differentiation is not supported, this function should prevent initialization with a context that has an STM defined.
fn dual_eom(
&self,
_delta_t: f64,
Expand All @@ -118,9 +117,9 @@ where
Err(DynamicsError::StateTransitionMatrixUnset)
}

/// Optionally performs some final changes after each successful integration of the equations of motion.
/// For example, this can be used to update the Guidance mode.
/// NOTE: This function is also called just prior to very first integration step in order to update the initial state if needed.
/// Performs final changes after each successful integration step.
///
/// Also called before the first integration step to update the initial state if needed.
fn finally(
&self,
next_state: Self::StateType,
Expand All @@ -130,61 +129,63 @@ where
}
}

/// The `ForceModel` trait handles immutable dynamics which return a force. Those will be divided by the mass of the spacecraft to compute the acceleration (F = ma).
/// A trait for immutable dynamics that return a force (e.g., solar radiation pressure, drag).
///
/// Examples include Solar Radiation Pressure, drag, etc., i.e. forces which do not need to save the current state, only act on it.
/// The force is divided by the spacecraft's mass to compute acceleration (F=ma).
pub trait ForceModel: Send + Sync + fmt::Display {
/// If a parameter of this force model is stored in the spacecraft state, then this function should return the index where this parameter is being affected
/// Returns the estimation index if a parameter of this force model is stored in the spacecraft state.
fn estimation_index(&self) -> Option<usize>;

/// Defines the equations of motion for this force model from the provided osculating state.
/// Defines the equations of motion for this force model.
fn eom(&self, ctx: &Spacecraft, almanac: Arc<Almanac>) -> Result<Vector3<f64>, DynamicsError>;

/// Force models must implement their partials, although those will only be called if the propagation requires the
/// computation of the STM. The `osc_ctx` is the osculating context, i.e. it changes for each sub-step of the integrator.
/// The last row corresponds to the partials of the parameter of this force model wrt the position, i.e. this only applies to conservative forces.
/// Defines the partial derivatives of the equations of motion.
///
/// The last row corresponds to the partials of the parameter of this force model with respect to position, which only applies to conservative forces.
fn dual_eom(
&self,
osc_ctx: &Spacecraft,
almanac: Arc<Almanac>,
) -> Result<(Vector3<f64>, Matrix4x3<f64>), DynamicsError>;
}

/// The `AccelModel` trait handles immutable dynamics which return an acceleration. Those can be added directly to Orbital Dynamics for example.
///
/// Examples include spherical harmonics, i.e. accelerations which do not need to save the current state, only act on it.
/// A trait for immutable dynamics that return an acceleration (e.g., spherical harmonics).
pub trait AccelModel: Send + Sync + fmt::Display {
/// Defines the equations of motion for this force model from the provided osculating state in the integration frame.
/// Defines the equations of motion for this acceleration model.
fn eom(&self, osc: &Orbit, almanac: Arc<Almanac>) -> Result<Vector3<f64>, DynamicsError>;

/// Acceleration models must implement their partials, although those will only be called if the propagation requires the
/// computation of the STM.
/// Defines the partial derivatives of the equations of motion.
fn dual_eom(
&self,
osc_ctx: &Orbit,
almanac: Arc<Almanac>,
) -> Result<(Vector3<f64>, Matrix3<f64>), DynamicsError>;
}

/// Stores dynamical model errors
/// Dynamical model errors.
#[derive(Debug, PartialEq, Snafu)]
#[snafu(visibility(pub(crate)))]
pub enum DynamicsError {
/// Fuel exhausted at the provided spacecraft state
/// Fuel exhausted.
#[snafu(display("fuel exhausted at {sc}"))]
FuelExhausted { sc: Box<Spacecraft> },
/// State Transition Matrix (STM) was expected but not set.
#[snafu(display("expected STM to be set"))]
StateTransitionMatrixUnset,
/// Astrodynamics error.
#[snafu(display("dynamical model encountered an astro error: {source}"))]
DynamicsAstro { source: AstroError },
/// Guidance error.
#[snafu(display("dynamical model encountered an issue with the guidance: {source}"))]
DynamicsGuidance { source: GuidanceError },
/// Almanac error.
#[snafu(display("dynamical model issue due to Almanac: {action} {source}"))]
DynamicsAlmanacError {
action: &'static str,
#[snafu(source(from(AlmanacError, Box::new)))]
source: Box<AlmanacError>,
},
/// Planetary data error.
#[snafu(display("dynamical model issue due to planetary data: {action} {source}"))]
DynamicsPlanetaryError {
action: &'static str,
Expand Down
22 changes: 11 additions & 11 deletions src/dynamics/orbital.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,31 @@ use std::sync::Arc;

pub use super::sph_harmonics::Harmonics;

/// `OrbitalDynamics` provides the equations of motion for any celestial dynamic, without state transition matrix computation.
/// Equations of motion for celestial dynamics.
#[derive(Clone)]
pub struct OrbitalDynamics {
pub accel_models: Vec<Arc<dyn AccelModel + Sync>>,
}

impl OrbitalDynamics {
/// Initializes the point masses gravities with the provided list of bodies
/// Initializes the dynamics with point mass gravity from a list of celestial bodies.
pub fn point_masses(celestial_objects: Vec<i32>) -> Self {
// Create the point masses
Self::new(vec![PointMasses::new(celestial_objects)])
}

/// Initializes a OrbitalDynamics which does not simulate the gravity pull of other celestial objects but the primary one.
/// Initializes two-body dynamics, which only simulate the gravity of the primary body.
pub fn two_body() -> Self {
Self::new(vec![])
}

/// Initialize orbital dynamics with a list of acceleration models
/// Initializes orbital dynamics with a list of acceleration models.
pub fn new(accel_models: Vec<Arc<dyn AccelModel + Sync>>) -> Self {
Self { accel_models }
}

/// Initialize new orbital mechanics with the provided model.
/// **Note:** Orbital dynamics _always_ include two body dynamics, these cannot be turned off.
/// Initializes orbital dynamics with a single acceleration model.
///
/// **Note:** Two-body dynamics are always included and cannot be disabled.
pub fn from_model(accel_model: Arc<dyn AccelModel + Sync>) -> Self {
Self::new(vec![accel_model])
}
Expand Down Expand Up @@ -166,23 +166,23 @@ impl OrbitalDynamics {
}
}

/// PointMasses model
/// A point mass gravity model.
pub struct PointMasses {
pub celestial_objects: Vec<i32>,
/// Light-time correction computation if extra point masses are needed
/// Light-time correction.
pub correction: Option<Aberration>,
}

impl PointMasses {
/// Initializes the point masses gravities with the provided list of bodies
/// Initializes the point mass gravity model with a list of celestial bodies.
pub fn new(celestial_objects: Vec<i32>) -> Arc<Self> {
Arc::new(Self {
celestial_objects,
correction: None,
})
}

/// Initializes the point masses gravities with the provided list of bodies, and accounting for some light time correction
/// Initializes the point mass gravity model with a list of celestial bodies and a light-time correction.
pub fn with_correction(celestial_objects: Vec<i32>, correction: Aberration) -> Self {
Self {
celestial_objects,
Expand Down
Loading
Loading