docs: bilingual comments for the error types, links and mesh
The error modules across the remaining crates share a shape, so one table covers them all. Also the inter-satellite link geometry and the mesh connectivity analysis, including the Menger and Kosaraju notes.
This commit is contained in:
parent
e41e2c77bb
commit
99807cb5e6
|
|
@ -3,20 +3,34 @@
|
|||
use core::fmt;
|
||||
|
||||
/// The category of an access error.
|
||||
///
|
||||
/// 接入错误的类别。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum AccessErrorKind {
|
||||
/// The station or its mask is not usable.
|
||||
///
|
||||
/// 地面站或其遮蔽角不可用。
|
||||
InvalidStation,
|
||||
/// The sampling step is not positive and finite.
|
||||
///
|
||||
/// 采样步长非正或非有限。
|
||||
InvalidSampleStep,
|
||||
/// The crossing tolerance is not positive and finite.
|
||||
///
|
||||
/// 交叉容差非正或非有限。
|
||||
InvalidTolerance,
|
||||
/// The search interval is empty or not ordered.
|
||||
///
|
||||
/// 搜索区间为空或次序不对。
|
||||
InvalidInterval,
|
||||
/// The sample sequence is not in increasing time order.
|
||||
///
|
||||
/// 样本序列未按时间递增排列。
|
||||
UnorderedSamples,
|
||||
/// A supplied satellite position is not usable.
|
||||
///
|
||||
/// 所提供的卫星位置不可用。
|
||||
InvalidPosition,
|
||||
}
|
||||
|
||||
|
|
@ -35,6 +49,8 @@ impl fmt::Display for AccessErrorKind {
|
|||
}
|
||||
|
||||
/// A failure while finding access windows.
|
||||
///
|
||||
/// 查找可见性窗口时发生的失败。
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct AccessError {
|
||||
kind: AccessErrorKind,
|
||||
|
|
|
|||
|
|
@ -3,16 +3,26 @@
|
|||
use core::fmt;
|
||||
|
||||
/// The category of a handover error.
|
||||
///
|
||||
/// 切换错误的类别。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum HandoverErrorKind {
|
||||
/// The candidate list is empty.
|
||||
///
|
||||
/// 候选列表为空。
|
||||
NoCandidates,
|
||||
/// The same satellite appears more than once in the candidate list.
|
||||
///
|
||||
/// 同一卫星在候选列表中出现多次。
|
||||
DuplicateSatellite,
|
||||
/// A quality value is outside its range or not finite.
|
||||
///
|
||||
/// 某质量值超出取值范围或非有限。
|
||||
InvalidQuality,
|
||||
/// A policy parameter is not usable.
|
||||
///
|
||||
/// 某策略参数不可用。
|
||||
InvalidPolicy,
|
||||
}
|
||||
|
||||
|
|
@ -29,6 +39,8 @@ impl fmt::Display for HandoverErrorKind {
|
|||
}
|
||||
|
||||
/// A failure while making a handover decision.
|
||||
///
|
||||
/// 作出切换决策时发生的失败。
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct HandoverError {
|
||||
kind: HandoverErrorKind,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,14 @@ use apsis_math::{Vec3, parallel::map_index};
|
|||
///
|
||||
/// A pair whose test is undefined, because a position is not finite or the
|
||||
/// body radius is not positive, yields `false`.
|
||||
///
|
||||
/// 按顺序返回各位置有序对的可见性。
|
||||
///
|
||||
/// 结果按行主序:位于 `row * positions.len() + column` 的元素是
|
||||
/// `positions[row]` 对 `positions[column]` 的可见性。卫星对自身总可见,
|
||||
/// 这提示调用方跳过对角线。
|
||||
///
|
||||
/// 测试未定义的点对(位置非有限或天体半径非正)给出 `false`。
|
||||
pub fn visibility_matrix(positions: &[Vec3], body_radius: f64) -> Vec<bool> {
|
||||
let len = positions.len();
|
||||
let mut matrix = vec![false; len * len];
|
||||
|
|
@ -34,6 +42,7 @@ pub fn visibility_matrix(positions: &[Vec3], body_radius: f64) -> Vec<bool> {
|
|||
}
|
||||
|
||||
/// Returns the visibility of every ordered pair of positions, across several
|
||||
/// 跨多个线程返回各位置有序对的可见性。
|
||||
/// threads.
|
||||
///
|
||||
/// The result matches [`visibility_matrix`] element for element and in the
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ use apsis_math::Vec3;
|
|||
/// blocking body lies between the terminals.
|
||||
///
|
||||
/// Returns `None` when either point is not finite.
|
||||
///
|
||||
/// 返回原点到两点连线的最短距离。
|
||||
///
|
||||
/// 最近点落在两端之间时它是垂距,否则是到较近一端的距离。对星间链路
|
||||
/// 而言前一种情形是要紧的,因为遮挡天体位于两端之间。
|
||||
///
|
||||
/// 任一点非有限时返回 `None`。
|
||||
pub fn closest_approach_to_centre(first: Vec3, second: Vec3) -> Option<f64> {
|
||||
if !first.is_finite() || !second.is_finite() {
|
||||
return None;
|
||||
|
|
@ -39,6 +46,13 @@ pub fn closest_approach_to_centre(first: Vec3, second: Vec3) -> Option<f64> {
|
|||
///
|
||||
/// Returns `None` when either position is not finite or the body radius is
|
||||
/// not positive.
|
||||
///
|
||||
/// 当两颗卫星能越过该天体互相可见时返回 `true`。
|
||||
///
|
||||
/// 判据是两位置之间的线段是否保持在给定半径的球体之外。恰好擦过表面
|
||||
/// 的链路被视为通畅,因为该极限即几何地平线。
|
||||
///
|
||||
/// 任一位置非有限或天体半径非正时返回 `None`。
|
||||
pub fn mutual_visibility(first: Vec3, second: Vec3, body_radius: f64) -> Option<bool> {
|
||||
if !body_radius.is_finite() || body_radius <= 0.0 {
|
||||
return None;
|
||||
|
|
@ -57,6 +71,14 @@ pub fn mutual_visibility(first: Vec3, second: Vec3, body_radius: f64) -> Option<
|
|||
/// or when the body radius is not usable. A cell that reports its own
|
||||
/// position for both ends has no link, so that case is rejected rather than
|
||||
/// returned with a zero range.
|
||||
///
|
||||
/// 返回两颗卫星之间链路的完整几何。
|
||||
///
|
||||
/// 各方向是自每颗卫星指向对方的单位矢量。其中含对中心的最接近距离,使
|
||||
/// 调用方能判断该链路有多少余量。
|
||||
///
|
||||
/// 任一位置非有限、两者重合或天体半径不可用时返回 `None`。两端回报
|
||||
/// 自身位置的单元没有链路,故该情形被拒绝而非以零距离返回。
|
||||
pub fn link_geometry(first: Vec3, second: Vec3, body_radius: f64) -> Option<LinkGeometry> {
|
||||
if !body_radius.is_finite() || body_radius < 0.0 {
|
||||
return None;
|
||||
|
|
@ -80,6 +102,8 @@ pub fn link_geometry(first: Vec3, second: Vec3, body_radius: f64) -> Option<Link
|
|||
/// Returns `true` when the Sun is within the field of view of an optical
|
||||
/// link.
|
||||
///
|
||||
/// 当太阳位于某光链路的视场内时返回 `true`。
|
||||
///
|
||||
/// The test is the angle between the link direction and the direction to the
|
||||
/// Sun. If that angle is within the field of view at either terminal, the
|
||||
/// Sun is in the beam and the link cannot be used.
|
||||
|
|
|
|||
|
|
@ -7,13 +7,24 @@ use apsis_math::Vec3;
|
|||
/// 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.
|
||||
|
|
@ -22,6 +33,11 @@ pub struct LinkGeometry {
|
|||
/// 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,
|
||||
}
|
||||
|
||||
|
|
@ -31,11 +47,17 @@ impl LinkGeometry {
|
|||
/// 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.
|
||||
///
|
||||
/// 当该链路越过天体时返回 `true`。
|
||||
pub fn is_clear(&self, body_radius: f64) -> bool {
|
||||
self.centre_distance_km >= body_radius
|
||||
}
|
||||
|
|
@ -47,27 +69,44 @@ impl LinkGeometry {
|
|||
/// 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.
|
||||
///
|
||||
/// 当该链路可承载业务时返回 `true`。
|
||||
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",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,13 @@ use apsis_topology::Topology;
|
|||
/// hops. The result is in node order.
|
||||
///
|
||||
/// Returns an empty vector when the node is out of range.
|
||||
///
|
||||
/// 沿边的方向返回自某节点可达的节点集合。
|
||||
///
|
||||
/// 起点节点被包含在内,因为节点经零跳路径可达自身。结果按节点次序
|
||||
/// 排列。
|
||||
///
|
||||
/// 节点越界时返回空向量。
|
||||
pub fn reachable_from(topology: &Topology, source: usize) -> Vec<usize> {
|
||||
if source >= topology.node_count() {
|
||||
return Vec::new();
|
||||
|
|
@ -43,6 +50,18 @@ pub fn reachable_from(topology: &Topology, source: usize) -> Vec<usize> {
|
|||
/// Returns `Some(0)` when no path exists, and `None` when either node is out
|
||||
/// of range or the two nodes are the same, for which the question is not
|
||||
/// defined.
|
||||
///
|
||||
/// 返回两节点之间相互独立的路径条数。
|
||||
///
|
||||
/// 两条路径在不含公共边时相互独立。依 Menger 定理,该条数即使这两节点
|
||||
/// 断连所需移除的最少边数,故即该连接可承受的链路失效次数。
|
||||
///
|
||||
/// 该值以两节点之间单位容量的最大流计算,采用 Ford-Fulkerson 方法的
|
||||
/// Edmonds-Karp 变体,每步沿最短增广。对卫星网这样的小图它既快又
|
||||
/// 精确。
|
||||
///
|
||||
/// 不存在路径时返回 `Some(0)`;任一节点越界或两节点相同(此时该问题
|
||||
/// 无定义)时返回 `None`。
|
||||
pub fn edge_connectivity(topology: &Topology, source: usize, destination: usize) -> Option<usize> {
|
||||
if source >= topology.node_count() || destination >= topology.node_count() {
|
||||
return None;
|
||||
|
|
@ -125,6 +144,18 @@ pub fn edge_connectivity(topology: &Topology, source: usize, destination: usize)
|
|||
///
|
||||
/// Source: Kosaraju's algorithm as described in Cormen et al.,
|
||||
/// *Introduction to Algorithms*, 3rd edition, MIT Press, 2009, chapter 22.
|
||||
///
|
||||
/// 返回强连通分量的数量。
|
||||
///
|
||||
/// 一个分量内每个节点都能沿边的方向到达其余每个节点时,它即强连通。
|
||||
/// 该计数是各自内部可路由的独立网络数,对含定向星间链路的卫星网而
|
||||
/// 言,它正是衡量该网由几部分构成的恰当度量。
|
||||
///
|
||||
/// 算法为 Kosaraju:一次深度优先搜索记录各节点的完成次序,再在反向
|
||||
/// 边上按完成次序的逆序做第二次搜索,输出各分量。
|
||||
///
|
||||
/// 出处:Kosaraju 算法,见 Cormen 等,*Introduction to Algorithms*,
|
||||
/// 第 3 版,MIT Press,2009,第 22 章。
|
||||
pub fn strongly_connected_components(topology: &Topology) -> usize {
|
||||
let node_count = topology.node_count();
|
||||
if node_count == 0 {
|
||||
|
|
|
|||
|
|
@ -3,22 +3,38 @@
|
|||
use core::fmt;
|
||||
|
||||
/// The category of a topology error.
|
||||
///
|
||||
/// 拓扑错误的类别。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum TopologyErrorKind {
|
||||
/// A node index is outside the range of the graph.
|
||||
///
|
||||
/// 节点下标超出该图的取值范围。
|
||||
NoSuchNode,
|
||||
/// An edge already exists between the two nodes.
|
||||
///
|
||||
/// 两节点之间已存在该边。
|
||||
DuplicateEdge,
|
||||
/// No edge exists between the two nodes.
|
||||
///
|
||||
/// 两节点之间不存在该边。
|
||||
NoSuchEdge,
|
||||
/// A cost is not finite or not positive.
|
||||
///
|
||||
/// 代价非有限或非正。
|
||||
InvalidCost,
|
||||
/// The series is empty.
|
||||
///
|
||||
/// 该序列为空。
|
||||
EmptySeries,
|
||||
/// The times in a series are not strictly increasing.
|
||||
///
|
||||
/// 序列中的时刻非严格递增。
|
||||
UnorderedTimes,
|
||||
/// A time is not finite.
|
||||
///
|
||||
/// 某时刻非有限。
|
||||
InvalidTime,
|
||||
}
|
||||
|
||||
|
|
@ -38,6 +54,8 @@ impl fmt::Display for TopologyErrorKind {
|
|||
}
|
||||
|
||||
/// A failure while building or querying a topology.
|
||||
///
|
||||
/// 构建或查询拓扑时发生的失败。
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TopologyError {
|
||||
kind: TopologyErrorKind,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
use core::fmt;
|
||||
|
||||
/// The category of a scenario error.
|
||||
///
|
||||
/// 场景错误的类别。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum ScenarioErrorKind {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,22 @@
|
|||
use core::fmt;
|
||||
|
||||
/// The category of a simulation error.
|
||||
///
|
||||
/// 仿真错误的类别。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum SimulationErrorKind {
|
||||
/// The scenario is not usable.
|
||||
///
|
||||
/// 该场景不可用。
|
||||
InvalidScenario,
|
||||
/// The scheduled resources do not form a usable set.
|
||||
///
|
||||
/// 所调度的资源未构成可用的集合。
|
||||
InvalidResources,
|
||||
/// A scheduled placement does not match the task it names.
|
||||
///
|
||||
/// 某处放置与其所指名的任务不匹配。
|
||||
InconsistentPlan,
|
||||
}
|
||||
|
||||
|
|
@ -26,6 +34,8 @@ impl fmt::Display for SimulationErrorKind {
|
|||
}
|
||||
|
||||
/// A failure while preparing or starting a simulation.
|
||||
///
|
||||
/// 准备或启动仿真时发生的失败。
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct SimulationError {
|
||||
kind: SimulationErrorKind,
|
||||
|
|
@ -41,6 +51,8 @@ impl SimulationError {
|
|||
}
|
||||
|
||||
/// Attaches a description of what caused the failure.
|
||||
///
|
||||
/// 附加对导致该失败之事的说明。
|
||||
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
|
||||
self.detail = Some(detail.into());
|
||||
self
|
||||
|
|
|
|||
Loading…
Reference in New Issue