-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #21 from novalabsxyz/jsk/subsume-itm-rs
Subsume ITM repo as a workspace member
- Loading branch information
Showing
16 changed files
with
656 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,8 @@ jobs: | |
|
||
- name: Setup | Checkout | ||
uses: actions/checkout@v3 | ||
with: | ||
submodules: true | ||
|
||
- name: Setup | Rust toolchain | ||
uses: dtolnay/[email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "extern/itm"] | ||
path = extern/itm | ||
url = https://github.com/dirkcgrunwald/itm.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[package] | ||
categories = ["science"] | ||
description = "A wrapper around NTIA's Irregular Terrain Model" | ||
edition = "2021" | ||
homepage = "https://github.com/jaykickliter/geoprof" | ||
keywords = ["rf", "radio", "modeling", "ntia"] | ||
license-file = "LICENSE.md" | ||
name = "itm" | ||
readme = "README.md" | ||
repository = "https://github.com/jaykickliter/geoprof" | ||
version = "0.1.0" | ||
|
||
[features] | ||
default = [] | ||
address_sanitizer = [] | ||
serde = ["serde/derive"] | ||
|
||
[dependencies] | ||
cxx = "1" | ||
serde = { workspace = true, optional = true } | ||
thiserror = { workspace = true } | ||
|
||
[build-dependencies] | ||
cxx-build = "1" | ||
|
||
[dev-dependencies] | ||
anyhow = "1" | ||
clap = { workspace = true } | ||
geo = { workspace = true } | ||
terrain = { path = "../terrain" } | ||
|
||
[[example]] | ||
name = "p2p" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
SOFTWARE DISCLAIMER / RELEASE | ||
|
||
This software was developed by employees of the National Telecommunications and Information Administration (NTIA), an agency of the Federal Government and is provided to you as a public service. Pursuant to Title 15 United States Code Section 105, works of NTIA employees are not subject to copyright protection within the United States. | ||
|
||
The software is provided by NTIA “AS IS.” NTIA MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NTIA does not warrant or make any representations regarding the use of the software or the results thereof, including but not limited to the correctness, accuracy, reliability or usefulness of the software. | ||
|
||
To the extent that NTIA holds rights in countries other than the United States, you are hereby granted the non-exclusive irrevocable and unconditional right to print, publish, prepare derivative works and distribute the NTIA software, in any medium, or authorize others to do so on your behalf, on a royalty-free basis throughout the World. | ||
|
||
You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. | ||
|
||
You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. | ||
|
||
Please provide appropriate acknowledgments of NTIA’s creation of the software in any copies or derivative works of this software. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Irregular Terrain Model (ITM) | ||
|
||
`itm` is a wrapper around NTIA's [library] for modeling radio frequency | ||
propogation. | ||
|
||
[library]: https://github.com/NTIA/itm | ||
|
||
## License | ||
|
||
See NTIA's [license](LICENSE.md) file. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
fn main() { | ||
let cxx_sources = [ | ||
"../extern/itm/src/ComputeDeltaH.cpp", | ||
"../extern/itm/src/DiffractionLoss.cpp", | ||
"../extern/itm/src/FindHorizons.cpp", | ||
"../extern/itm/src/FreeSpaceLoss.cpp", | ||
"../extern/itm/src/FresnelIntegral.cpp", | ||
"../extern/itm/src/H0Function.cpp", | ||
"../extern/itm/src/InitializeArea.cpp", | ||
"../extern/itm/src/InitializePointToPoint.cpp", | ||
"../extern/itm/src/InverseComplementaryCumulativeDistributionFunction.cpp", | ||
"../extern/itm/src/KnifeEdgeDiffraction.cpp", | ||
"../extern/itm/src/LineOfSightLoss.cpp", | ||
"../extern/itm/src/LinearLeastSquaresFit.cpp", | ||
"../extern/itm/src/LongleyRice.cpp", | ||
"../extern/itm/src/QuickPfl.cpp", | ||
"../extern/itm/src/SigmaHFunction.cpp", | ||
"../extern/itm/src/SmoothEarthDiffraction.cpp", | ||
"../extern/itm/src/TerrainRoughness.cpp", | ||
"../extern/itm/src/TroposcatterLoss.cpp", | ||
"../extern/itm/src/ValidateInputs.cpp", | ||
"../extern/itm/src/Variability.cpp", | ||
"../extern/itm/src/itm_area.cpp", | ||
"../extern/itm/src/itm_p2p.cpp", | ||
"wrapper/itm-wrapper.cpp", | ||
]; | ||
|
||
let mut bridge = cxx_build::bridge("src/lib.rs"); | ||
bridge.flag("-std=c++11"); | ||
bridge.include("../extern/itm/include"); | ||
#[cfg(feature = "address_sanitizer")] | ||
{ | ||
bridge.flag("-fno-omit-frame-pointer"); | ||
bridge.flag("-fsanitize=address"); | ||
bridge.flag("-ggdb"); | ||
} | ||
for path in &cxx_sources { | ||
bridge.file(path); | ||
} | ||
bridge.compile("itm_wrapper"); | ||
|
||
println!("cargo:rerun-if-changed=wrapper/itm-wrapper.cpp"); | ||
println!("cargo:rerun-if-changed=wrapper/itm-wrapper.h"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
mod options; | ||
|
||
use anyhow::Error as AnyErr; | ||
use clap::Parser; | ||
use itm::{Climate, ModeVariability, Polarization}; | ||
use options::{Cli, LatLonAlt}; | ||
use terrain::{Profile, TileMode, Tiles}; | ||
|
||
// Example for 900 MHz across black rock desert. | ||
// ``` | ||
// cargo run --example p2p -- --tile-dir=/path/to/nasadem/3-arcsecond/hgt/tiles/ --start=40.885629,-119.065844,10 --frequency=900e6 --end=40.904691,-119.043429,10 | ||
// ``` | ||
fn main() -> Result<(), AnyErr> { | ||
let Cli { | ||
tile_dir, | ||
max_step, | ||
start: LatLonAlt(start_coord, start_alt), | ||
end: LatLonAlt(end_coord, end_alt), | ||
frequency, | ||
} = Cli::parse(); | ||
|
||
let tiles = Tiles::new(tile_dir, TileMode::MemMap)?; | ||
let t0 = std::time::Instant::now(); | ||
let profile = Profile::<f32>::builder() | ||
.start(start_coord) | ||
.start_alt(start_alt) | ||
.max_step(max_step) | ||
.end(end_coord) | ||
.end_alt(end_alt) | ||
.build(&tiles)?; | ||
let profile_runtime = t0.elapsed(); | ||
|
||
let climate = Climate::Desert; | ||
let n0 = 301.; | ||
let f_hz = frequency; | ||
let pol = Polarization::Vertical; | ||
let epsilon = 15.; | ||
let sigma = 0.005; | ||
let mdvar = ModeVariability::Accidental; | ||
let time = 50.0; | ||
let location = 50.0; | ||
let situation = 50.0; | ||
let step_size_m = profile.distances_m[1]; | ||
let terrain = profile.terrain_elev_m; | ||
let t0 = std::time::Instant::now(); | ||
let attenuation_db = itm::p2p( | ||
start_alt.into(), | ||
end_alt.into(), | ||
step_size_m.into(), | ||
&terrain, | ||
climate, | ||
n0, | ||
f_hz.into(), | ||
pol, | ||
epsilon, | ||
sigma, | ||
mdvar, | ||
time, | ||
location, | ||
situation, | ||
)?; | ||
let itm_p2p_runtime = t0.elapsed(); | ||
|
||
let total_distance_m = profile.distances_m.last().unwrap(); | ||
let fspl = fspl(*total_distance_m, frequency); | ||
|
||
println!("profile runtime: {profile_runtime:?}"); | ||
println!("itm runtime: {itm_p2p_runtime:?}"); | ||
println!("distance: {total_distance_m} m"); | ||
println!("fspl: {fspl} dB"); | ||
println!("attenuation: {attenuation_db} dB"); | ||
|
||
Ok(()) | ||
} | ||
|
||
fn fspl(meters: f32, freq: f32) -> f32 { | ||
20.0 * meters.log10() + 20.0 * freq.log10() - 147.55 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use anyhow::{anyhow, Error as AnyError}; | ||
use clap::Parser; | ||
use geo::geometry::Coord; | ||
use std::{path::PathBuf, str::FromStr}; | ||
|
||
/// Generate point-to-point terrain profiles. | ||
#[derive(Parser, Debug, Clone)] | ||
#[allow(clippy::struct_excessive_bools)] | ||
pub struct Cli { | ||
/// Directory elevation tiles. | ||
#[arg(short, long)] | ||
pub tile_dir: PathBuf, | ||
|
||
/// Maximum path incremental step size, in meters. | ||
#[arg(short, long, default_value_t = 90.0)] | ||
pub max_step: f32, | ||
|
||
/// Start "lat,lon,alt", where 'alt' is meters above ground. | ||
#[arg(long)] | ||
pub start: LatLonAlt, | ||
|
||
/// Destination "lat,lon,alt", where 'alt' is meters above ground. | ||
#[arg(long)] | ||
pub end: LatLonAlt, | ||
|
||
/// Signal frequency (Hz). | ||
#[arg(long, short)] | ||
pub frequency: f32, | ||
} | ||
|
||
#[derive(Clone, Debug, Copy)] | ||
pub struct LatLonAlt(pub Coord<f32>, pub f32); | ||
|
||
impl FromStr for LatLonAlt { | ||
type Err = AnyError; | ||
fn from_str(s: &str) -> Result<Self, AnyError> { | ||
let (lat_str, lon_str, alt_str) = { | ||
let idx = s | ||
.find(',') | ||
.ok_or_else(|| anyhow!("not a valid lat,lon,alt"))?; | ||
let (lat_str, lon_alt_str) = s.split_at(idx); | ||
let idx = lon_alt_str[1..] | ||
.find(',') | ||
.ok_or_else(|| anyhow!("not a valid lat,lon,alt"))?; | ||
let (lon_str, alt_str) = lon_alt_str[1..].split_at(idx); | ||
(lat_str, lon_str, &alt_str[1..]) | ||
}; | ||
let lat = f32::from_str(lat_str)?; | ||
let lon = f32::from_str(lon_str)?; | ||
let alt = f32::from_str(alt_str)?; | ||
Ok(Self(Coord { y: lat, x: lon }, alt)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
use std::ffi::c_int; | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum ItmErrCode { | ||
#[error("TX terminal height is out of range")] | ||
TxTerminalHeight, | ||
#[error("RX terminal height is out of range")] | ||
RxTerminalHeight, | ||
#[error("Invalid value for radio climate")] | ||
InvalidRadioClimate, | ||
#[error("Time percentage is out of range")] | ||
InvalidTime, | ||
#[error("Location percentage is out of range")] | ||
InvalidLocation, | ||
#[error("Situation percentage is out of range")] | ||
InvalidSituation, | ||
#[error("Confidence percentage is out of range")] | ||
InvalidConfidence, | ||
#[error("Reliability percentage is out of range")] | ||
InvalidReliability, | ||
#[error("Refractivity is out of range")] | ||
Refractivity, | ||
#[error("Frequency is out of range")] | ||
Frequency, | ||
#[error("Invalid value for polarization")] | ||
Polarization, | ||
#[error("Epsilon is out of range")] | ||
Epsilon, | ||
#[error("Sigma is out of range")] | ||
Sigma, | ||
#[error("The imaginary portion of the complex impedance is larger than the real portion")] | ||
GroundImpedance, | ||
#[error("Invalid value for mode of variability")] | ||
Mdvar, | ||
#[error("Internally computed effective earth radius is invalid")] | ||
EffectiveEarth, | ||
#[error("Path distance is out of range")] | ||
PathDistance, | ||
#[error("Delta H (terrain irregularity parameter) is out of range")] | ||
DeltaH, | ||
#[error("Invalid value for TX siting criteria")] | ||
TxSitingCriteria, | ||
#[error("Invalid value for RX siting criteria")] | ||
RxSitingCriteria, | ||
#[error("Internally computed surface refractivity value is too small")] | ||
SurfaceRefractivitySmall, | ||
#[error("Internally computed surface refractivity value is too large")] | ||
SurfaceRefractivityLarge, | ||
} | ||
|
||
impl ItmErrCode { | ||
pub fn from_retcode<T>(err_code: c_int, val: T) -> Result<T, ItmErrCode> { | ||
let err = match err_code { | ||
0 | 1 => return Ok(val), | ||
1000 => ItmErrCode::TxTerminalHeight, | ||
1001 => ItmErrCode::RxTerminalHeight, | ||
1002 => ItmErrCode::InvalidRadioClimate, | ||
1003 => ItmErrCode::InvalidTime, | ||
1004 => ItmErrCode::InvalidLocation, | ||
1005 => ItmErrCode::InvalidSituation, | ||
1006 => ItmErrCode::InvalidConfidence, | ||
1007 => ItmErrCode::InvalidReliability, | ||
1008 => ItmErrCode::Refractivity, | ||
1009 => ItmErrCode::Frequency, | ||
1010 => ItmErrCode::Polarization, | ||
1011 => ItmErrCode::Epsilon, | ||
1012 => ItmErrCode::Sigma, | ||
1013 => ItmErrCode::GroundImpedance, | ||
1014 => ItmErrCode::Mdvar, | ||
1016 => ItmErrCode::EffectiveEarth, | ||
1017 => ItmErrCode::PathDistance, | ||
1018 => ItmErrCode::DeltaH, | ||
1019 => ItmErrCode::TxSitingCriteria, | ||
1020 => ItmErrCode::RxSitingCriteria, | ||
1021 => ItmErrCode::SurfaceRefractivitySmall, | ||
1022 => ItmErrCode::SurfaceRefractivityLarge, | ||
_ => unreachable!(), | ||
}; | ||
Err(err) | ||
} | ||
} |
Oops, something went wrong.