nyx_space/od/msr/
types.rs1use anise::astro::AzElRange;
20use arrow::datatypes::{DataType, Field};
21use serde_derive::{Deserialize, Serialize};
22use std::collections::HashMap;
23
24use crate::od::ODError;
25
26#[derive(Copy, Clone, Debug, Hash, Serialize, Deserialize, PartialEq, Eq)]
27pub enum MeasurementType {
28 #[serde(rename = "range_km")]
29 Range,
30 #[serde(rename = "doppler_km_s")]
31 Doppler,
32 #[serde(rename = "azimuth_deg")]
33 Azimuth,
34 #[serde(rename = "elevation_deg")]
35 Elevation,
36 #[serde(rename = "receive_freq")]
37 ReceiveFrequency,
38 #[serde(rename = "transmit_freq")]
39 TransmitFrequency,
40}
41
42impl MeasurementType {
43 pub fn unit(self) -> &'static str {
45 match self {
46 Self::Range => "km",
47 Self::Doppler => "km/s",
48 Self::Azimuth | Self::Elevation => "deg",
49 Self::ReceiveFrequency | Self::TransmitFrequency => "Hz",
50 }
51 }
52
53 pub(crate) fn may_be_two_way(self) -> bool {
55 match self {
56 MeasurementType::Range | MeasurementType::Doppler => true,
57 MeasurementType::Azimuth
58 | MeasurementType::Elevation
59 | MeasurementType::ReceiveFrequency
60 | MeasurementType::TransmitFrequency => false,
61 }
62 }
63
64 pub fn to_field(&self) -> Field {
67 let mut meta = HashMap::new();
68 meta.insert("unit".to_string(), self.unit().to_string());
69
70 Field::new(
71 format!("{self:?} ({})", self.unit()),
72 DataType::Float64,
73 true,
74 )
75 .with_metadata(meta)
76 }
77
78 pub fn compute_one_way(self, aer: AzElRange, noise: f64) -> Result<f64, ODError> {
80 match self {
81 Self::Range => Ok(aer.range_km + noise),
82 Self::Doppler => Ok(aer.range_rate_km_s + noise),
83 Self::Azimuth => Ok(aer.azimuth_deg + noise),
84 Self::Elevation => Ok(aer.elevation_deg + noise),
85 Self::ReceiveFrequency | Self::TransmitFrequency => Err(ODError::MeasurementSimError {
86 details: format!("{self:?} is only supported in CCSDS TDM parsing"),
87 }),
88 }
89 }
90
91 pub fn compute_two_way(
94 self,
95 aer_t0: AzElRange,
96 aer_t1: AzElRange,
97 noise: f64,
98 ) -> Result<f64, ODError> {
99 match self {
100 Self::Range => {
101 let range_km = (aer_t1.range_km + aer_t0.range_km) * 0.5;
102 Ok(range_km + noise / 2.0_f64.sqrt())
103 }
104 Self::Doppler => {
105 let doppler_km_s = (aer_t1.range_rate_km_s + aer_t0.range_rate_km_s) * 0.5;
106 Ok(doppler_km_s + noise / 2.0_f64.sqrt())
107 }
108 Self::Azimuth => {
109 let az_deg = (aer_t1.azimuth_deg + aer_t0.azimuth_deg) * 0.5;
110 Ok(az_deg + noise / 2.0_f64.sqrt())
111 }
112 Self::Elevation => {
113 let el_deg = (aer_t1.elevation_deg + aer_t0.elevation_deg) * 0.5;
114 Ok(el_deg + noise / 2.0_f64.sqrt())
115 }
116 Self::ReceiveFrequency | Self::TransmitFrequency => Err(ODError::MeasurementSimError {
117 details: format!("{self:?} is only supported in CCSDS TDM parsing"),
118 }),
119 }
120 }
121}