spaceman 0.1.0

A WIP library for calculating common orbital maneuvers in Kerbal Space Program.
Documentation
use crate::celestial_bodies::CelestialBody;

/// A bi-elliptic transfer between two different circular orbits.
/// The bi-elliptic transfer has lower delta-v costs than the Hohmann transfer
/// if the ratio of final to initial semi-major axis is 11.94 or greater,
/// depending on the intermediate semi-major axis chosen.
///
/// See [Wikipedia](https://en.wikipedia.org/wiki/Bi-elliptic_transfer) for further information.
#[derive(Copy, Clone, Debug)]
pub struct BiellipticTransfer {
    /// The current altitude of the spacecraft.
    pub start_altitude: f64,
    /// The apoapsis of the elliptical transfer orbit.
    pub intermediate_altitude: f64,
    /// The target altitude of the spacecraft.
    pub end_altitude: f64,
    /// The celestial body the spacecraft is orbiting.
    pub celestial_body: CelestialBody,
}

impl BiellipticTransfer {
    /// Create a new bi-elliptic transfer
    pub fn new(start_altitude: f64, intermediate_altitude: f64, end_altitude: f64, celestial_body: CelestialBody) -> Self {
        Self {
            start_altitude,
            intermediate_altitude,
            end_altitude,
            celestial_body,
        }
    }

    /// Calculate the Δv needed for the first burn.
    /// The first burn raises the spacecraft's apoapsis to the specified intermediate altitude.
    pub fn transfer_delta_v(&self) -> f64 {
        let start_velocity = self.celestial_body.circular_velocity(self.start_altitude);
        let transfer_velocity = self.celestial_body.velocity(self.start_altitude, (self.start_altitude + self.intermediate_altitude) * 0.5 + self.celestial_body.radius);

        (start_velocity - transfer_velocity).abs()
    }

    /// Calculate the Δv needed for the second burn.
    /// The second burn raises the periapsis of the elliptical transfer orbit to match the specified end altitude.
    pub fn periapsis_raise_delta_v(&self) -> f64 {
        let intermediate_velocity = self.celestial_body.velocity(self.intermediate_altitude, (self.start_altitude + self.intermediate_altitude) * 0.5 + self.celestial_body.radius);
        let transfer_velocity = self.celestial_body.velocity(self.intermediate_altitude, (self.end_altitude + self.intermediate_altitude) * 0.5 + self.celestial_body.radius);

        (intermediate_velocity - transfer_velocity).abs()
    }

    /// Calculate the Δv needed for the third burn.
    /// The third burn circularizes the orbit at the specified end altitude.
    pub fn circularization_delta_v(&self) -> f64 {
        let transfer_velocity = self.celestial_body.velocity(self.end_altitude, (self.end_altitude + self.intermediate_altitude) * 0.5 + self.celestial_body.radius);
        let end_velocity = self.celestial_body.circular_velocity(self.end_altitude);

        (transfer_velocity - end_velocity).abs()
    }

    /// Calculate the total amount of Δv needed for the bi-elliptic transfer.
    pub fn total_delta_v(&self) -> f64 {
        self.transfer_delta_v() + self.periapsis_raise_delta_v() + self.circularization_delta_v()
    }

}