@@ -96,12 +96,9 @@ struct SimArgs {
9696/// Closed-loop simulation arguments combining SimArgs with closed-loop specific options
9797#[ derive( Args , Clone , Debug ) ]
9898struct ClosedLoopSimArgs {
99- /// Input file path
100- #[ arg( short, long, value_parser) ]
101- input : PathBuf ,
102- /// Output file path
103- #[ arg( short, long, value_parser) ]
104- output : PathBuf ,
99+ /// Common simulation input/output arguments
100+ #[ command( flatten) ]
101+ sim : SimArgs ,
105102 /// RNG seed (applies to any stochastic options)
106103 #[ arg( long, default_value_t = 42 ) ]
107104 seed : u64 ,
@@ -119,12 +116,9 @@ struct ClosedLoopSimArgs {
119116/// Particle filter simulation arguments
120117#[ derive( Args , Clone , Debug ) ]
121118struct ParticleFilterSimArgs {
122- /// Input file path
123- #[ arg( short, long, value_parser) ]
124- input : PathBuf ,
125- /// Output file path
126- #[ arg( short, long, value_parser) ]
127- output : PathBuf ,
119+ /// Common simulation input/output arguments
120+ #[ command( flatten) ]
121+ sim : SimArgs ,
128122 /// RNG seed (applies to any stochastic options)
129123 #[ arg( long, default_value_t = 42 ) ]
130124 seed : u64 ,
@@ -212,12 +206,7 @@ fn validate_input_file(input: &Path) -> Result<(), Box<dyn Error>> {
212206/// Validate output path and create parent directories if needed
213207fn validate_output_path ( output : & Path ) -> Result < ( ) , Box < dyn Error > > {
214208 if let Some ( parent) = output. parent ( )
215- && !parent. exists ( )
216- && parent. is_dir ( )
217- {
218- return Err ( format ! ( "Output directory '{}' does not exist." , parent. display( ) ) . into ( ) ) ;
219- }
220- if let Some ( parent) = output. parent ( )
209+ && !parent. as_os_str ( ) . is_empty ( )
221210 && !parent. exists ( )
222211 {
223212 std:: fs:: create_dir_all ( parent) ?;
@@ -259,15 +248,15 @@ fn main() -> Result<(), Box<dyn Error>> {
259248 // This would run dead reckoning simulation
260249 }
261250 Command :: ParticleFilter ( ref args) => {
262- validate_input_file ( & args. input ) ?;
263- validate_output_path ( & args. output ) ?;
251+ validate_input_file ( & args. sim . input ) ?;
252+ validate_output_path ( & args. sim . output ) ?;
264253
265254 // Load sensor data records from CSV
266- let records = TestDataRecord :: from_csv ( & args. input ) ?;
255+ let records = TestDataRecord :: from_csv ( & args. sim . input ) ?;
267256 info ! (
268257 "Read {} records from {}" ,
269258 records. len( ) ,
270- & args. input. display( )
259+ & args. sim . input. display( )
271260 ) ;
272261
273262 let cfg = if let Some ( ref cfg_path) = args. config {
@@ -303,23 +292,25 @@ fn main() -> Result<(), Box<dyn Error>> {
303292 let results = particle_filter_loop ( & mut pf, events, args. averaging_strategy . clone ( ) ) ;
304293
305294 match results {
306- Ok ( ref nav_results) => match NavigationResult :: to_csv ( nav_results, & args. output ) {
307- Ok ( _) => info ! ( "Results written to {}" , args. output. display( ) ) ,
308- Err ( e) => error ! ( "Error writing results: {}" , e) ,
309- } ,
295+ Ok ( ref nav_results) => {
296+ match NavigationResult :: to_csv ( nav_results, & args. sim . output ) {
297+ Ok ( _) => info ! ( "Results written to {}" , args. sim. output. display( ) ) ,
298+ Err ( e) => error ! ( "Error writing results: {}" , e) ,
299+ }
300+ }
310301 Err ( e) => error ! ( "Error running particle filter simulation: {}" , e) ,
311302 } ;
312303 }
313304 Command :: ClosedLoop ( ref args) => {
314- validate_input_file ( & args. input ) ?;
315- validate_output_path ( & args. output ) ?;
305+ validate_input_file ( & args. sim . input ) ?;
306+ validate_output_path ( & args. sim . output ) ?;
316307
317308 // Load sensor data records from CSV, tolerant to mixed/variable-length rows and encoding issues.
318- let records = TestDataRecord :: from_csv ( & args. input ) ?;
309+ let records = TestDataRecord :: from_csv ( & args. sim . input ) ?;
319310 info ! (
320311 "Read {} records from {}" ,
321312 records. len( ) ,
322- & args. input. display( )
313+ & args. sim . input. display( )
323314 ) ;
324315 let cfg = if let Some ( ref cfg_path) = args. config {
325316 match GnssDegradationConfig :: from_file ( cfg_path) {
@@ -340,10 +331,12 @@ fn main() -> Result<(), Box<dyn Error>> {
340331 let mut ukf = initialize_ukf ( records[ 0 ] . clone ( ) , None , None , None , None , None , None ) ;
341332 let results = closed_loop ( & mut ukf, events) ;
342333 match results {
343- Ok ( ref nav_results) => match NavigationResult :: to_csv ( nav_results, & args. output ) {
344- Ok ( _) => info ! ( "Results written to {}" , args. output. display( ) ) ,
345- Err ( e) => error ! ( "Error writing results: {}" , e) ,
346- } ,
334+ Ok ( ref nav_results) => {
335+ match NavigationResult :: to_csv ( nav_results, & args. sim . output ) {
336+ Ok ( _) => info ! ( "Results written to {}" , args. sim. output. display( ) ) ,
337+ Err ( e) => error ! ( "Error writing results: {}" , e) ,
338+ }
339+ }
347340 Err ( e) => error ! ( "Error running closed-loop simulation: {}" , e) ,
348341 } ;
349342 }
0 commit comments