nyx_space/od/ground_station/
asn1.rs1use super::GroundStation;
20use crate::io::ConfigRepr;
21use crate::od::msr::MeasurementType;
22use crate::od::noise::StochasticNoise;
23use der::{Decode, Encode, Reader};
24use indexmap::{IndexMap, IndexSet};
25
26impl ConfigRepr for GroundStation {}
27
28#[derive(der::Sequence)]
29struct MsrNoisePair {
30 msr_type: MeasurementType,
31 noise: StochasticNoise,
32}
33
34impl<'a> Decode<'a> for GroundStation {
35 fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
36 let name: String = decoder.decode()?;
37 let location = decoder.decode()?;
38 let msr_types_vec: Vec<MeasurementType> = decoder.decode()?;
40 let measurement_types = IndexSet::from_iter(msr_types_vec);
41
42 let light_time_correction = decoder.decode()?;
43 let relativistic_corrections = decoder.decode()?;
44
45 let flags: u8 = decoder.decode()?;
47
48 let doppler_config = if flags & (1 << 0) != 0 {
49 Some(decoder.decode()?)
50 } else {
51 None
52 };
53
54 let timestamp_noise_s = if flags & (1 << 1) != 0 {
55 Some(decoder.decode()?)
56 } else {
57 None
58 };
59
60 let stochastic_noises = if flags & (1 << 2) != 0 {
61 let stochastics_vec: Vec<MsrNoisePair> = decoder.decode()?;
65 let mut map = IndexMap::new();
66 for pair in stochastics_vec {
67 map.insert(pair.msr_type, pair.noise);
68 }
69 Some(map)
70 } else {
71 None
72 };
73
74 let obstruction_body = if flags & (1 << 3) != 0 {
75 Some(decoder.decode()?)
76 } else {
77 None
78 };
79
80 Ok(GroundStation {
81 name,
82 location,
83 measurement_types,
84 doppler_config,
85 light_time_correction,
86 timestamp_noise_s,
87 stochastic_noises,
88 obstructing_body: obstruction_body,
89 relativistic_corrections,
90 })
91 }
92}
93
94impl Encode for GroundStation {
95 fn encoded_len(&self) -> der::Result<der::Length> {
96 let msr_types_vec: Vec<MeasurementType> = self.measurement_types.iter().copied().collect();
97
98 let stochastics_vec = self.stochastic_noises.as_ref().map(|map| {
99 map.iter()
100 .map(|(k, v)| MsrNoisePair {
101 msr_type: *k,
102 noise: *v,
103 })
104 .collect::<Vec<MsrNoisePair>>()
105 });
106
107 self.name.encoded_len()?
108 + self.location.encoded_len()?
109 + msr_types_vec.encoded_len()?
110 + self.light_time_correction.encoded_len()?
111 + self.relativistic_corrections.encoded_len()?
112 + self.available_data().encoded_len()?
113 + self.doppler_config.encoded_len()?
114 + self.timestamp_noise_s.encoded_len()?
115 + stochastics_vec.encoded_len()?
116 + self.obstructing_body.encoded_len()?
117 }
118
119 fn encode(&self, encoder: &mut impl der::Writer) -> der::Result<()> {
120 self.name.encode(encoder)?;
121 self.location.encode(encoder)?;
122
123 let msr_types_vec: Vec<MeasurementType> = self.measurement_types.iter().copied().collect();
124 msr_types_vec.encode(encoder)?;
125
126 self.light_time_correction.encode(encoder)?;
127 self.relativistic_corrections.encode(encoder)?;
128 self.available_data().encode(encoder)?;
129
130 self.doppler_config.encode(encoder)?;
131 self.timestamp_noise_s.encode(encoder)?;
132
133 let stochastics_vec = self.stochastic_noises.as_ref().map(|map| {
134 map.iter()
135 .map(|(k, v)| MsrNoisePair {
136 msr_type: *k,
137 noise: *v,
138 })
139 .collect::<Vec<MsrNoisePair>>()
140 });
141 stochastics_vec.encode(encoder)?;
142
143 self.obstructing_body.encode(encoder)?;
144
145 Ok(())
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use crate::od::ground_station::DopplerConfig;
153 use crate::od::msr::IntegrationRef;
154 use crate::od::noise::{GaussMarkov, WhiteNoise};
155 use anise::astro::{Location, TerrainMask};
156 use anise::constants::frames::IAU_EARTH_FRAME;
157 use hifitime::{TimeUnits, Unit};
158
159 #[test]
160 fn test_ground_station_asn1_roundtrip() {
161 let mut measurement_types = IndexSet::new();
162 measurement_types.insert(MeasurementType::Range);
163 measurement_types.insert(MeasurementType::Doppler);
164
165 let mut stochastics = IndexMap::new();
166 stochastics.insert(
167 MeasurementType::Range,
168 StochasticNoise {
169 bias: Some(GaussMarkov::new(1.days(), 5e-3).unwrap()),
170 white_noise: Some(WhiteNoise::constant_white_noise(1e-3)),
171 },
172 );
173 stochastics.insert(
174 MeasurementType::Doppler,
175 StochasticNoise {
176 bias: Some(GaussMarkov::new(1.days(), 5e-5).unwrap()),
177 white_noise: None,
178 },
179 );
180
181 let mut gs = GroundStation {
182 name: "Test Station".to_string(),
183 location: Location {
184 latitude_deg: 40.427_222,
185 longitude_deg: 4.250_556,
186 height_km: 0.834_939,
187 frame: IAU_EARTH_FRAME.into(),
188 terrain_mask: TerrainMask::from_flat_terrain(5.0),
189 terrain_mask_ignored: false,
190 },
191 measurement_types: measurement_types.clone(),
192 doppler_config: None,
193 light_time_correction: true,
194 timestamp_noise_s: None,
195 stochastic_noises: None,
196 obstructing_body: None,
197 relativistic_corrections: false,
198 };
199
200 let mut buf = vec![];
202 gs.encode_to_vec(&mut buf).unwrap();
203 let decoded = GroundStation::from_der(&buf).unwrap();
204 assert_eq!(decoded, gs);
205
206 gs.doppler_config = Some(DopplerConfig::default());
208 buf.clear();
209 gs.encode_to_vec(&mut buf).unwrap();
210 let decoded = GroundStation::from_der(&buf).unwrap();
211 assert_eq!(decoded, gs);
212
213 gs.doppler_config = Some(DopplerConfig {
215 integration_time: 10 * Unit::Second,
216 integration_ref: IntegrationRef::Start,
217 });
218 buf.clear();
219 gs.encode_to_vec(&mut buf).unwrap();
220 let decoded = GroundStation::from_der(&buf).unwrap();
221 assert_eq!(decoded, gs);
222
223 gs.timestamp_noise_s = Some(StochasticNoise {
225 bias: Some(GaussMarkov::new(10 * Unit::Second, 1e-9).unwrap()),
226 white_noise: None,
227 });
228 buf.clear();
229 gs.encode_to_vec(&mut buf).unwrap();
230 let decoded = GroundStation::from_der(&buf).unwrap();
231 assert_eq!(decoded, gs);
232
233 gs.stochastic_noises = Some(stochastics);
235 buf.clear();
236 gs.encode_to_vec(&mut buf).unwrap();
237 let decoded = GroundStation::from_der(&buf).unwrap();
238 assert_eq!(decoded, gs);
239
240 gs.doppler_config = None;
242 gs.timestamp_noise_s = None;
243 buf.clear();
244 gs.encode_to_vec(&mut buf).unwrap();
245 let decoded = GroundStation::from_der(&buf).unwrap();
246 assert_eq!(decoded, gs);
247
248 gs.obstructing_body = Some(IAU_EARTH_FRAME.into());
250 buf.clear();
251 gs.encode_to_vec(&mut buf).unwrap();
252 let decoded = GroundStation::from_der(&buf).unwrap();
253 assert_eq!(decoded, gs);
254
255 gs.relativistic_corrections = true;
257 buf.clear();
258 gs.encode_to_vec(&mut buf).unwrap();
259 let decoded = GroundStation::from_der(&buf).unwrap();
260 assert_eq!(decoded, gs);
261 }
262}