Skip to content

Commit

Permalink
Develop (#263)
Browse files Browse the repository at this point in the history
* Improve Readme
* Improve fops/ definitions
* CSV export
* Working on RTK opmode and interfacing
* Definitions for rtk
* Orbit Upgrade
* RTK upgrade

---------

Signed-off-by: Guillaume W. Bres <[email protected]>
  • Loading branch information
gwbres committed Aug 18, 2024
1 parent 99994db commit 64e92df
Show file tree
Hide file tree
Showing 43 changed files with 1,473 additions and 896 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ test_resources/

Cargo.lock

*.csv
*.png
*.jpg
*.html
Expand Down
7 changes: 4 additions & 3 deletions rinex-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ serde = { version = "1.0", default-features = false, features = ["derive"] }

kml = { version = "0.8", optional = true }
gpx = { version = "0.10", optional = true }
csv = { version = "1.3.0", optional = true }

plotly = "0.9"
# plotly = { path = "../../plotly-rs/plotly" }
Expand All @@ -44,9 +45,9 @@ hifitime = { version = "4.0.0-alpha", features = ["serde", "std"] }

gnss-rs = { version = "2.2.1", features = ["serde"] }

# gnss-rtk = { version = "0.6.0", features = ["serde"] }
# gnss-rtk = { path = "../../rtk-rs/gnss-rtk", features = ["serde"] }
gnss-rtk = { git = "https://github.com/rtk-rs/gnss-rtk", branch = "main", features = ["serde"] }
gnss-rtk = { version = "0.7.0", features = ["serde"] }
# gnss-rtk = { path = "../../rtk-rs/gnss-rtk", features = ["serde"] }
# gnss-rtk = { git = "https://github.com/rtk-rs/gnss-rtk", branch = "main", features = ["serde"] }

cggtts = { version = "4.1.5", features = ["serde", "scheduler"], optional = true }
# cggtts = { path = "../../cggtts/cggtts", features = ["serde", "scheduler"], optional = true }
Expand Down
2 changes: 1 addition & 1 deletion rinex-cli/src/cli/fops/filegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn subcommand() -> Command {
.long_flag("filegen")
.arg_required_else_help(false)
.about(
"Parse, preprocess and generate data while preserving input format. See --filegen --help."
"Parse, preprocess and generate new RINEX and/or SP3 data. Input forms are preserved. See --filegen --help."
)
.long_about("
Use this mode to generate all file formats we support after preprocessing them.
Expand Down
54 changes: 54 additions & 0 deletions rinex-cli/src/cli/fops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,58 @@ use rinex::prod::{DataSource, FFU, PPU};
* Arguments that are shared by all file operations.
* Mainly [ProductionAttributes] (re)definition opts
*/
#[cfg(not(feature = "csv"))]
lazy_static! {
pub static ref SHARED_GENERAL_ARGS : Vec<Arg> = vec![
Arg::new("batch")
.short('b')
.long("batch")
.required(false)
.value_parser(value_parser!(u8))
.help("Set # (number ID) in case this file is part of a file serie"),
Arg::new("short")
.short('s')
.long("short")
.action(ArgAction::SetTrue)
.help("Prefer (deprecated) short filenames as historically used.
Otherwise, this ecosystem prefers modern (longer) filenames that contain more information."),
Arg::new("gzip")
.long("gzip")
.action(ArgAction::SetTrue)
.help("Force .gzip compressed file generation, even if input data is not."),
Arg::new("unzip")
.long("unzip")
.action(ArgAction::SetTrue)
.help("Force plain/readable file generation. By default, if input data is gzip compressed, we will preserve
the input compression. Use this to bypass."),
Arg::new("csv")
.long("csv")
.action(ArgAction::SetTrue)
.help("[NOT AVAILABLE] requires `csv` compilation option"),
Arg::new("agency")
.short('a')
.long("agency")
.required(false)
.help("Define a custom agency name, possibly overwriting
what the original filename did define (according to conventions)."),
Arg::new("country")
.short('c')
.long("country")
.required(false)
.help("Define a custom (3 letter) country code.
This code should represent where the Agency is located."),
Arg::new("source")
.long("src")
.required(false)
.value_name("[RCVR,STREAM]")
.value_parser(value_parser!(DataSource))
.help("Define the data source.
In RINEX standards, we use \"RCVR\" when data was sampled from a hardware receiver.
Use \"STREAM\" for other stream data source, like RTCM for example.")
];
}

#[cfg(feature = "csv")]
lazy_static! {
pub static ref SHARED_GENERAL_ARGS : Vec<Arg> = vec![
Arg::new("batch")
Expand Down Expand Up @@ -64,7 +116,9 @@ This code should represent where the Agency is located."),
In RINEX standards, we use \"RCVR\" when data was sampled from a hardware receiver.
Use \"STREAM\" for other stream data source, like RTCM for example.")
];
}

lazy_static! {
pub static ref SHARED_DATA_ARGS : Vec<Arg> = vec![
Arg::new("PPU")
.long("ppu")
Expand Down
80 changes: 51 additions & 29 deletions rinex-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,21 @@ impl Default for Cli {
}
}

pub struct RemoteReferenceSite {
pub data: QcContext,
pub rx_ecef: Option<(f64, f64, f64)>,
}

/// Context defined by User.
pub struct Context {
/// Quiet option
pub quiet: bool,
/// Data context defined by user.
/// In differential opmode, this is the ROVER.
pub data: QcContext,
/// Secondary dataset defined by user
/// serves as BASE in differential opmodes.
pub station_data: Option<QcContext>,
/// Remote reference site (secondary dataset) defined by User.
/// Serves as reference point in differential techniques.
pub reference_site: Option<RemoteReferenceSite>,
/// Context name is derived from the primary file loaded in Self,
/// and mostly used in output products generation.
pub name: String,
Expand Down Expand Up @@ -83,13 +88,23 @@ impl Context {
panic!("failed to create {}: {:?}", path.display(), e);
})
}
// Returns True if this context is compatible with RTK positioning
pub fn rtk_compatible(&self) -> bool {
if let Some(remote) = &self.reference_site {
self.data.observation().is_some()
&& self.rx_ecef.is_some()
&& remote.data.observation().is_some()
&& remote.rx_ecef.is_some()
} else {
false
}
}
}

impl Cli {
/// Build new command line interface
pub fn new() -> Self {
Self {
matches: {
let cmd =
Command::new("rinex-cli")
.author("Guillaume W. Bres, <[email protected]>")
.version(env!("CARGO_PKG_VERSION"))
Expand Down Expand Up @@ -167,6 +182,14 @@ but you can extend that with --depth. Refer to -f for more information."))
By default the $RINEX_WORKSPACE variable is prefered if it is defined.
You can also use this flag to customize it.
If none are defined, we will then try to create a local directory named \"WORKSPACE\" like it is possible in this very repo."))
.next_help_heading("Output customization")
.arg(
Arg::new("output-name")
.short('o')
.action(ArgAction::Set)
.help("Customize output file or report name.
In analysis opmode, report is named index.html by default, this will redefine that.
In file operations (filegen, etc..) we can manually define output filenames with this option."))
.next_help_heading("Report customization")
.arg(
Arg::new("report-sum")
Expand All @@ -183,12 +206,6 @@ If none are defined, we will then try to create a local directory named \"WORKSP
By default, report synthesis happens once per input set (file combnation and cli options).
Use this option to force report regeneration.
This has no effect on file operations that do not synthesize a report."))
.arg(
Arg::new("report-name")
.short('o')
.action(ArgAction::Set)
.help("Custom report name, otherwise, report is named index.html")
)
.arg(
Arg::new("report-brdc-sky")
.long("brdc-sky")
Expand Down Expand Up @@ -268,15 +285,17 @@ Otherwise it gets automatically picked up."))
.value_name("\"lat,lon,alt\" coordinates in ddeg [°]")
.help("Define the (RX) antenna position manualy, in decimal degrees."))
.next_help_heading("Exclusive Opmodes: you can only run one at a time.")
.subcommand(filegen::subcommand())
.subcommand(merge::subcommand())
.subcommand(positioning::ppp_subcommand())
.subcommand(positioning::rtk_subcommand())
.subcommand(split::subcommand())
.subcommand(diff::subcommand())
.subcommand(time_binning::subcommand())
.get_matches()
},
.subcommand(filegen::subcommand());

let cmd = cmd
.subcommand(merge::subcommand())
.subcommand(positioning::ppp_subcommand())
.subcommand(positioning::rtk_subcommand())
.subcommand(split::subcommand())
.subcommand(diff::subcommand())
.subcommand(time_binning::subcommand());
Self {
matches: cmd.get_matches(),
}
}
/// Recursive browser depth
Expand Down Expand Up @@ -404,11 +423,14 @@ Otherwise it gets automatically picked up."))
}
/// True if File Operations to generate data is being deployed
pub fn has_fops_output_product(&self) -> bool {
match self.matches.subcommand() {
Some(("filegen", _)) | Some(("merge", _)) | Some(("split", _)) | Some(("tbin", _))
| Some(("diff", _)) => true,
_ => false,
}
matches!(
self.matches.subcommand(),
Some(("filegen", _))
| Some(("merge", _))
| Some(("split", _))
| Some(("tbin", _))
| Some(("diff", _))
)
}
/// True if forced report synthesis is requested
pub fn force_report_synthesis(&self) -> bool {
Expand All @@ -428,7 +450,7 @@ Otherwise it gets automatically picked up."))
.chain(self.rover_files().into_iter().sorted())
.chain(self.preprocessing().into_iter().sorted())
.join(",");
if let Some(custom) = self.custom_report_name() {
if let Some(custom) = self.custom_output_name() {
string.push_str(custom);
}
if let Some(geo) = self.manual_geodetic() {
Expand Down Expand Up @@ -456,8 +478,8 @@ Otherwise it gets automatically picked up."))
force_brdc_skyplot: self.matches.get_flag("report-brdc-sky"),
}
}
/// Report to be generated for this session
pub fn custom_report_name(&self) -> Option<&String> {
self.matches.get_one::<String>("report-name")
/// Customized / manually defined output to be generated
pub fn custom_output_name(&self) -> Option<&String> {
self.matches.get_one::<String>("output-name")
}
}
Loading

0 comments on commit 64e92df

Please sign in to comment.