Skip to content

Commit 9948b80

Browse files
Copilotjbrodovsky
andcommitted
Add generate-config CLI command for GNSS degradation config files
Co-authored-by: jbrodovsky <57160841+jbrodovsky@users.noreply.github.com>
1 parent ce4d95e commit 9948b80

2 files changed

Lines changed: 195 additions & 77 deletions

File tree

core/src/messages.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,11 @@ pub enum GnssScheduler {
150150
/// GnssFaultModel::Hijack { offset_n_m: 50.0, offset_e_m: 0.0, start_s: 120.0, duration_s: 60.0 },
151151
/// ]);
152152
/// ```
153-
#[derive(Clone, Debug, Serialize, Deserialize)]
153+
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
154154
#[serde(tag = "kind", rename_all = "snake_case")]
155155
pub enum GnssFaultModel {
156156
/// No corruption; GNSS fixes are passed through unchanged.
157+
#[default]
157158
None,
158159

159160
/// (2) Degraded accuracy: AR(1)-correlated noise on position and velocity,
@@ -206,6 +207,7 @@ pub enum GnssFaultModel {
206207
/// combining e.g. `SlowBias` with a `Hijack` to simulate multi-stage spoofing.
207208
Combo(Vec<GnssFaultModel>),
208209
}
210+
209211
/// Configuration container for GNSS degradation in simulation.
210212
///
211213
/// This ties together a [`GnssScheduler`] (which controls *when* GNSS fixes
@@ -242,23 +244,41 @@ pub enum GnssFaultModel {
242244
/// seed: 42,
243245
/// };
244246
/// ```
247+
/// Default seed value for reproducible simulations
248+
fn default_seed() -> u64 {
249+
42
250+
}
251+
245252
#[derive(Clone, Debug, Serialize, Deserialize)]
246253
pub struct GnssDegradationConfig {
247254
/// Scheduler that determines when GNSS measurements are emitted
248255
/// (e.g., pass-through, fixed interval, or duty-cycled).
256+
#[serde(default)]
249257
pub scheduler: GnssScheduler,
250258

251259
/// Fault model that corrupts the contents of each emitted GNSS measurement
252260
/// (e.g., degraded wander, slow bias drift, hijack).
261+
#[serde(default)]
253262
pub fault: GnssFaultModel,
254263

255264
/// Random number generator seed for deterministic tests and reproducibility.
256265
///
257266
/// Use the same seed to repeat scenarios exactly; change it to get a new
258267
/// realization of stochastic processes such as AR(1) degradation.
268+
#[serde(default = "default_seed")]
259269
pub seed: u64,
260270
}
261271

272+
impl Default for GnssDegradationConfig {
273+
fn default() -> Self {
274+
GnssDegradationConfig {
275+
scheduler: GnssScheduler::default(),
276+
fault: GnssFaultModel::default(),
277+
seed: default_seed(),
278+
}
279+
}
280+
}
281+
262282
impl GnssDegradationConfig {
263283
/// Write the configuration to a JSON file (pretty-printed).
264284
pub fn to_json<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
@@ -1372,4 +1392,38 @@ mod serialization_tests {
13721392
let loaded = GnssDegradationConfig::from_file(&path).unwrap();
13731393
assert_eq!(cfg.seed, loaded.seed);
13741394
}
1395+
1396+
#[test]
1397+
fn default_config_roundtrip() {
1398+
// Test that default config can be serialized and read back
1399+
let cfg = GnssDegradationConfig::default();
1400+
1401+
// Verify default values
1402+
assert_eq!(cfg.seed, 42);
1403+
assert!(matches!(cfg.scheduler, GnssScheduler::PassThrough));
1404+
assert!(matches!(cfg.fault, GnssFaultModel::None));
1405+
1406+
// Test JSON roundtrip
1407+
let f = NamedTempFile::new().unwrap();
1408+
let path = f.path().with_extension("json");
1409+
cfg.to_file(&path).unwrap();
1410+
let loaded = GnssDegradationConfig::from_file(&path).unwrap();
1411+
assert_eq!(cfg.seed, loaded.seed);
1412+
assert!(matches!(loaded.scheduler, GnssScheduler::PassThrough));
1413+
assert!(matches!(loaded.fault, GnssFaultModel::None));
1414+
1415+
// Test YAML roundtrip
1416+
let f2 = NamedTempFile::new().unwrap();
1417+
let path2 = f2.path().with_extension("yaml");
1418+
cfg.to_file(&path2).unwrap();
1419+
let loaded2 = GnssDegradationConfig::from_file(&path2).unwrap();
1420+
assert_eq!(cfg.seed, loaded2.seed);
1421+
1422+
// Test TOML roundtrip
1423+
let f3 = NamedTempFile::new().unwrap();
1424+
let path3 = f3.path().with_extension("toml");
1425+
cfg.to_file(&path3).unwrap();
1426+
let loaded3 = GnssDegradationConfig::from_file(&path3).unwrap();
1427+
assert_eq!(cfg.seed, loaded3.seed);
1428+
}
13751429
}

0 commit comments

Comments
 (0)