Refactor: Consolidate geonav-sim into strapdown-sim with feature flag#212
Conversation
Closes #207 Extract duplicated utility functions from sim/src/main.rs and geonav/src/main.rs into a new shared module. This reduces code duplication by ~300 lines. Functions extracted: - init_logger() - Logger initialization - validate_input_path() - Path validation - get_csv_files() - CSV file discovery - validate_output_path() - Output directory creation - read_user_input() - User prompt utilities - prompt_config_name(), prompt_config_path() - prompt_input_path(), prompt_output_path() - prompt_f64_with_default() - Generic prompt helper - process_files() - Parallel/sequential file processing Also adds tempfile as a dev-dependency for unit tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Closes #208 Add optional `geonav` feature to strapdown-sim that enables geophysical navigation capabilities when compiled with `--features geonav`. Changes: - Add `geonav` feature flag in sim/Cargo.toml with optional strapdown-geonav dep - Add feature-gated `GeophysicalArgs` struct for CLI arguments - Integrate geo options into `ClosedLoopSimArgs` via `#[command(flatten)]` - Add `--geo` flag to enable geophysical navigation mode - Add geo-specific options: gravity/magnetic resolution, bias, noise, map files - Implement `run_geo_closed_loop_cli()` function for geophysical simulation - Add resolution conversion functions and map auto-detection helpers Usage: # Standard GNSS-aided INS strapdown-sim cl --filter ukf --input data.csv --output out/ # With geophysical navigation strapdown-sim cl --filter ukf --input data.csv --output out/ \ --geo --gravity-resolution one-minute Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Closes #210 Remove the standalone geonav-sim binary as it has been consolidated into strapdown-sim with the --geo flag. Changes: - Remove [[bin]] section from geonav/Cargo.toml - Delete geonav/src/main.rs (~840 lines) - Add usage comment in Cargo.toml pointing to new command Migration: Old: geonav-sim cl --input data.csv --output out.csv --gravity-resolution one-minute New: strapdown-sim cl --input data.csv --output out.csv --geo --gravity-resolution one-minute Build with: cargo build --package strapdown-sim --features geonav The strapdown-geonav crate is now library-only. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Closes #211 Update documentation to reflect the consolidation of geonav-sim into strapdown-sim. Changes: - Update README.md to remove references to standalone geonav-sim binary - Add geophysical navigation usage instructions to main README - Rewrite geonav/README.md to reflect library-only status - Update usage examples for new strapdown-sim --features geonav syntax Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR consolidates the geonav-sim binary into strapdown-sim with an optional geonav feature flag, successfully reducing code duplication by extracting shared utilities into a common module while maintaining the strapdown-geonav library as a standalone crate.
Key Changes:
- Extracted ~400 lines of shared CLI utilities into
sim/src/common.rswith comprehensive test coverage - Added
geonavfeature flag tosim/Cargo.tomlwith optional dependency onstrapdown-geonav - Integrated geophysical navigation functionality into
strapdown-simwith proper feature-gating - Removed the standalone
geonav-simbinary (~840 lines) fromgeonav/src/main.rs - Updated documentation in README files to reflect the new usage pattern
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| sim/src/common.rs | New shared utility module with logger initialization, path validation, file discovery, user input prompts, and parallel processing utilities. Includes comprehensive unit tests. |
| sim/src/main.rs | Integrated geophysical navigation with feature-gated imports, structs, and functions. Added resolution conversion functions and run_geo_closed_loop_cli for geophysical simulations. |
| sim/Cargo.toml | Added geonav feature with optional strapdown-geonav dependency and tempfile dev-dependency for tests. |
| geonav/src/main.rs | Removed entire 836-line binary implementation, now consolidated into strapdown-sim. |
| geonav/Cargo.toml | Removed [[bin]] section and added helpful comments directing users to use strapdown-sim --features geonav. |
| geonav/README.md | Rewritten to reflect library-only status with clear instructions for using the consolidated simulation tool and API examples. |
| README.md | Updated with instructions for enabling geophysical navigation capabilities via feature flag. |
| Cargo.lock | Updated dependencies to reflect the new structure. |
| GeoResolution::FourMinutes => MagneticResolution::FourMinutes, | ||
| GeoResolution::ThreeMinutes => MagneticResolution::ThreeMinutes, | ||
| GeoResolution::TwoMinutes => MagneticResolution::TwoMinutes, | ||
| _ => MagneticResolution::TwoMinutes, |
There was a problem hiding this comment.
The wildcard pattern in this match statement silently maps unsupported GeoResolution variants (OneMinute, ThirtySeconds, FifteenSeconds, ThreeSeconds, OneSecond) to TwoMinutes. This could lead to unexpected behavior where users specify a higher resolution than magnetic maps support, but get silently downgraded without warning. Consider explicitly matching all variants and returning an error for unsupported resolutions, or at least logging a warning.
| pub fn process_files<F>( | ||
| csv_files: &[PathBuf], | ||
| parallel: bool, | ||
| processor: F, | ||
| ) -> Result<(), Box<dyn Error>> | ||
| where | ||
| F: Fn(&Path) -> Result<(), Box<dyn Error>> + Send + Sync, | ||
| { | ||
| let is_multiple = csv_files.len() > 1; | ||
|
|
||
| if parallel && is_multiple { | ||
| // Parallel processing | ||
| let errors = Mutex::new(Vec::new()); | ||
|
|
||
| csv_files.par_iter().for_each(|input_file| { | ||
| if let Err(e) = processor(input_file) { | ||
| error!("Error processing {}: {}", input_file.display(), e); | ||
| errors | ||
| .lock() | ||
| .expect("Failed to acquire lock on error collection") | ||
| .push((input_file.clone(), e.to_string())); | ||
| } | ||
| }); | ||
|
|
||
| let errors = errors | ||
| .into_inner() | ||
| .expect("Failed to extract errors from mutex"); | ||
| if !errors.is_empty() { | ||
| error!("{} file(s) failed to process", errors.len()); | ||
| for (file, err) in &errors { | ||
| error!(" {}: {}", file.display(), err); | ||
| } | ||
| return Err(format!("{} file(s) failed to process", errors.len()).into()); | ||
| } | ||
| } else { | ||
| // Sequential processing | ||
| let mut failures = 0usize; | ||
| for input_file in csv_files { | ||
| if let Err(e) = processor(input_file) { | ||
| if !is_multiple { | ||
| return Err(e); | ||
| } | ||
| failures += 1; | ||
| error!("Error processing {}: {}", input_file.display(), e); | ||
| } | ||
| } | ||
| if failures > 0 { | ||
| error!("{} file(s) failed to process", failures); | ||
| } | ||
| } | ||
|
|
||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
The process_files function is defined but never used in the codebase. According to the PR description, this is intentional for future use. However, this will generate compiler warnings. Consider either using the function now or marking it with the allow attribute to suppress warnings until it's needed.
| GeoResolution::ThreeMinutes => GravityResolution::ThreeMinutes, | ||
| GeoResolution::TwoMinutes => GravityResolution::TwoMinutes, | ||
| GeoResolution::OneMinute => GravityResolution::OneMinute, | ||
| _ => GravityResolution::OneMinute, |
There was a problem hiding this comment.
The wildcard pattern in this match statement silently maps unsupported GeoResolution variants (ThirtySeconds, FifteenSeconds, ThreeSeconds, OneSecond) to OneMinute. This could lead to unexpected behavior where users specify a higher resolution than gravity maps support, but get silently downgraded without warning. Consider explicitly matching all variants and returning an error for unsupported resolutions, or at least logging a warning.
|
@copilot open a new pull request to apply changes based on the comments in this thread |
|
@jbrodovsky I've opened a new pull request, #213, to work on those changes. Once the pull request is ready, I'll request review from you. |
Summary
This PR consolidates the
geonav-simbinary intostrapdown-simwith an optionalgeonavfeature flag, eliminating ~40-50% code duplication while keepingstrapdown-geonavas a separate library crate.Closes: #206, #207, #208, #209, #210, #211
Changes
Step 1: Extract shared utilities (#207)
sim/src/common.rswith shared CLI utilities (~400 lines)init_logger,validate_input_path,get_csv_files,validate_output_path, user prompt utilitiesStep 2: Add geonav feature flag (#208)
geonavfeature tosim/Cargo.tomlwith optionalstrapdown-geonavdependencyGeophysicalArgsstruct for CLI arguments--geoflag and geophysical options intoClosedLoopSimArgsrun_geo_closed_loop_cli()for geophysical simulationStep 3: Parallel processing
process_files()utility for future use (currently unused warning)Step 4: Remove geonav-sim binary (#210)
geonav/src/main.rs(~840 lines)[[bin]]section fromgeonav/Cargo.tomlstrapdown-geonavis now library-onlyStep 5: Documentation (#211)
README.mdwith geonav usage instructionsgeonav/README.mdto reflect library-only statusUsage
Breaking Changes
geonav-simbinary no longer existsstrapdown-sim --features geonavwith--geoflagTest plan
cargo build --package strapdown-simcargo build --package strapdown-sim --features geonavcargo test --workspace🤖 Generated with Claude Code