-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmain.rs
More file actions
110 lines (109 loc) · 3.75 KB
/
Copy pathmain.rs
File metadata and controls
110 lines (109 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use clap::Parser;
use csv::ReaderBuilder;
use std::error::Error;
use std::path::PathBuf;
use strapdown::sim::{
NavigationResult, TestDataRecord, closed_loop, dead_reckoning, degrade_measurements,
};
/// Command line arguments
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
/// Mode of operation, either open-loop or closed-loop
#[clap(
short,
long,
value_parser,
default_value = "open-loop",
help = "Mode of operation: 'open-loop' or 'closed-loop'"
)]
mode: String,
/// Input CSV file path
#[clap(
short,
long,
value_parser,
help = "Path to the input CSV file containing IMU and (optionally) GPS data"
)]
input: PathBuf,
/// Output CSV file path
#[clap(
short,
long,
value_parser,
help = "Path to the output CSV file for navigation results"
)]
output: PathBuf,
/// Optional: GPS measurement interval in seconds (for simulating intermittent GPS outages)
#[clap(
long,
value_parser,
help = "Interval (in seconds) between GPS measurements, used to simulate GPS outages. Default is 0.0 which updates at every iteration."
)]
gps_interval: Option<f64>,
/// Optional: GPS degradation factor
#[clap(
long,
value_parser,
default_value = "1.0",
help = "Factor by which GPS accuracy is degraded. 1.0 is no degradation. >= 1.0 is a degradation factor. This factor is applied as a scalar multiplier to the recorded GPS accuracy."
)]
gps_degradation: Option<f64>,
/// Optional: GPS spoofing offset
#[clap(
long,
value_parser,
default_value = "0.0",
help = "Offset to apply to GPS coordinates (in meters)"
)]
gps_spoofing_offset: Option<f64>,
}
fn main() -> Result<(), Box<dyn Error>> {
let args = Args::parse();
// Validate the mode
if args.mode != "open-loop" && args.mode != "closed-loop" {
return Err("Invalid mode specified. Use 'open-loop' or 'closed-loop'.".into());
}
// Validate the GPS measurement interval is positive
match args.gps_interval {
Some(interval) if interval < 0.0 => {
return Err("GPS measurement interval must be a non-negative value.".into());
}
_ => {}
}
// Read the input CSV file
let mut rdr = ReaderBuilder::new().from_path(&args.input)?;
let mut records: Vec<TestDataRecord> = rdr.deserialize().collect::<Result<_, _>>()?;
println!(
"Read {} records from {}",
records.len(),
&args.input.display()
);
records = match args.gps_degradation {
Some(value) => degrade_measurements(records, value),
None => records,
};
let results: Vec<NavigationResult>;
if args.mode == "closed-loop" {
println!(
"Running in closed-loop mode with GPS interval: {:?}",
args.gps_interval
);
results = closed_loop(&records, args.gps_interval);
//match write_results_to_csv(&results, &args.output) {
match NavigationResult::to_csv(&results, &args.output) {
Ok(_) => println!("Results written to {}", args.output.display()),
Err(e) => eprintln!("Error writing results: {}", e),
};
} else if args.mode == "open-loop" {
results = dead_reckoning(&records);
// match write_results_to_csv(&results, &args.output) {
match NavigationResult::to_csv(&results, &args.output) {
Ok(_) => println!("Results written to {}", args.output.display()),
Err(e) => eprintln!("Error writing results: {}", e),
};
} else {
return Err("Invalid mode specified. Use 'open-loop' or 'closed-loop'.".into());
}
Ok(())
}