apsis-rs/crates/network/apsis-isl/src/link.rs

80 lines
2.9 KiB
Rust

//! The link geometry type and the state of a link.
use apsis_math::Vec3;
/// The geometry of a link between two satellites.
///
/// The range is the straight line distance, which a link budget uses for the
/// free space path loss. The two pointing vectors are the directions each
/// terminal must aim, expressed in the frame the positions were given in.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LinkGeometry {
/// The distance between the two satellites, in kilometers.
pub range_km: f64,
/// The unit vector from the first satellite toward the second.
pub direction_first_to_second: Vec3,
/// The unit vector from the second satellite toward the first.
pub direction_second_to_first: Vec3,
/// The closest the line between the two passes to the centre of the
/// body, in kilometers.
///
/// This is the quantity that decides whether the link is blocked. It is
/// reported because a link that clears the limb by a small margin is
/// fragile: atmospheric refraction and the oblateness of the body both
/// eat into the margin.
pub centre_distance_km: f64,
}
impl LinkGeometry {
/// Returns the grazing margin of the link, in kilometers.
///
/// This is how far the line between the two satellites clears the
/// surface, measured at the closest point. A negative value means the
/// link is blocked.
pub fn surface_clearance(&self, body_radius: f64) -> f64 {
self.centre_distance_km - body_radius
}
/// Returns `true` when the link clears the body.
pub fn is_clear(&self, body_radius: f64) -> bool {
self.centre_distance_km >= body_radius
}
}
/// The state of a link at one instant.
///
/// A link is either carrying traffic or not. The reasons a link can be
/// unavailable are kept separate, because routing across a constellation has
/// to distinguish a link that is geometrically blocked from one that is
/// merely not established yet.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LinkState {
/// The link is geometrically clear and may be used.
Available,
/// The Earth blocks the line between the two satellites.
Blocked,
/// The Sun is within the field of view of one of the terminals, so an
/// optical link cannot be used.
SunInField,
/// The link is clear but is not established, for example because it has
/// not yet been acquired or its capacity is exhausted.
NotEstablished,
}
impl LinkState {
/// Returns `true` when the link may carry traffic.
pub const fn is_usable(self) -> bool {
matches!(self, Self::Available)
}
/// Returns a short name for the state.
pub const fn name(self) -> &'static str {
match self {
Self::Available => "available",
Self::Blocked => "blocked",
Self::SunInField => "sun in field",
Self::NotEstablished => "not established",
}
}
}