Skip to content

Commit 45026ae

Browse files
committed
Added barometric altitude calculations
1 parent 983b3ac commit 45026ae

1 file changed

Lines changed: 61 additions & 29 deletions

File tree

core/src/earth.rs

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,9 @@
3232
//! are primarily used to convert between the ECEF and local-level frames. The rotations
3333
//! from the local level frame to the body frame can be taken care of by the `nalgebra`
3434
//! crate, which provides the necessary rotation matrices using the Rotation3 type.
35-
36-
// ----------
37-
// Working notes:
38-
// The canonical strapdown navigation state vector is WGS84 geodetic position (latitude, longitude, altitude) and local tangent plane (NED) velocities (north, east,
39-
// down). The state vector is updated by integrating the IMU measurements (body frame) to estimate the position and velocity of the sensor. Velocities are updated
40-
// in NED, whereas the positions are updated in WGS84.
41-
// ----------
42-
// Rotations can be handled using nalgebra's Rotation3 type, which can be converted to a DCM using the into() method. The Rotation3 type can be created from
43-
// Euler angles for the body to local-level frame rotation. The inverse of the Rotation3 type can be used to convert from the local-level frame to the body frame.
44-
// ----------
4535
use crate::{wrap_latitude, wrap_to_180};
4636
use ::nalgebra::{Matrix3, Vector3};
4737
use ::nav_types::{ECEF, WGS84};
48-
49-
// Earth constants (WGS84)
5038
/// Earth's rotation rate rad/s ($\omega_{ie}$)
5139
pub const RATE: f64 = 7.2921159e-5;
5240
/// Earth's rotation rate rad/s ($\omega_{ie}$) in a vector form
@@ -65,6 +53,8 @@ pub const ECCENTRICITY_SQUARED: f64 = ECCENTRICITY * ECCENTRICITY;
6553
pub const GE: f64 = 9.7803253359; // m/s^2, equatorial radius
6654
/// Earth's gravitational acceleration at the poles ($g_p$) in $m/s^2$
6755
pub const GP: f64 = 9.8321849378; // $m/s^2$, polar radius
56+
/// Earth's average gravitational acceleration ($g$) in $m/s^2$
57+
pub const G0: f64 = 9.80665; // m/s^2, average gravitational acceleration
6858
/// Earth's flattening factor ($f$)
6959
pub const F: f64 = 1.0 / 298.257223563; // Flattening factor
7060
/// Somigliana's constant ($K$)
@@ -82,7 +72,49 @@ pub const MAGNETIC_FIELD_STRENGTH: f64 = 3.12e-5; // T, reference mean magnetic
8272
pub const METERS_TO_DEGREES: f64 = 1.0 / (60.0 * 1852.0);
8373
/// Rough conversion factor from degrees to meters for latitude/longitude via nautical miles (1 degree ~ 60 nautical miles; 1 nautical mile ~ 1852 meters)
8474
pub const DEGREES_TO_METERS: f64 = 60.0 * 1852.0;
85-
75+
/// Sea-level atmospheric pressure in pascals
76+
pub const SEA_LEVEL_PRESSURE: f64 = 101325.0; // Pa, standard sea-level pressure
77+
/// Temperature lapse rate in Kelvin per meter
78+
pub const TEMPERATURE_LAPSE_RATE: f64 = 0.00976; // K/m, standard temperature lapse rate in the troposphere
79+
/// Constant-pressure specific heat
80+
pub const CONSTANT_PRESSURE_SPECIFIC_HEAT: f64 = 1004.68506; // J/(kg·K), specific heat at constant pressure for dry air
81+
/// Sea level standard temperature in Kelvin
82+
pub const SEA_LEVEL_STANDARD_TEMPERATURE: f64 = 288.15; // K, standard sea-level temperature
83+
/// Molar mass of dry air in kg/mol
84+
pub const MOLAR_MASS_DRY_AIR: f64 = 0.02896968; // kg/mol, molar mass of dry air
85+
/// Universal gas constant in J/(mol·K)
86+
pub const UNIVERSAL_GAS_CONSTANT: f64 = 8.314462618; // J/(mol·K), universal gas constant
87+
/// Calculate the barometric altitude from pressure and temperature
88+
///
89+
/// This function calculates the barometric altitude using the barometric formula, which relates
90+
/// the pressure at a given altitude to the pressure at sea level. The formula is based on the
91+
/// assumption of an isothermal atmosphere and the ideal gas law.
92+
///
93+
/// # Arguments
94+
/// - `pressure` - The atmospheric pressure at the given altitude in pascals
95+
///
96+
/// # Returns
97+
/// The barometric altitude in meters
98+
pub fn barometric_altitude(pressure: f64) -> f64 {
99+
let exponent: f64 = -((UNIVERSAL_GAS_CONSTANT * TEMPERATURE_LAPSE_RATE) / (G0 * MOLAR_MASS_DRY_AIR));
100+
(SEA_LEVEL_STANDARD_TEMPERATURE / TEMPERATURE_LAPSE_RATE) * (pressure / SEA_LEVEL_PRESSURE) * exponent.exp()
101+
}
102+
/// Calculates the relative barometric altitude from pressure and temperature
103+
///
104+
/// This function calculates the relative barometric altitude using the barometric formula,
105+
/// which relates the pressure at a given altitude to the pressure at a reference altitude.
106+
/// This is similar to how aircraft pressure altimeters work, where the preassure at a known
107+
/// altitude is used to calibrate the altimeter.
108+
///
109+
/// # Arguments
110+
/// - `pressure` - The measured atmospheric pressure
111+
/// - `initial_pressure` - The atmospheric pressure at the reference altitude in pascals
112+
///
113+
/// # Returns
114+
/// The relative barometric altitude in meters, i.e. the altitude relative to the reference.
115+
pub fn relative_barometric_altitude(pressure: f64, initial_pressure: f64) -> f64 {
116+
((UNIVERSAL_GAS_CONSTANT * SEA_LEVEL_PRESSURE) / (G0 * MOLAR_MASS_DRY_AIR)) * (initial_pressure / pressure).ln()
117+
}
86118
/// Convert a three-element vector to a skew-symmetric matrix
87119
///
88120
/// Groves' notation uses a lot of skew-symmetric matrices to represent cross products
@@ -141,7 +173,7 @@ pub fn skew_symmetric_to_vector(skew: &Matrix3<f64>) -> Vector3<f64> {
141173
/// system with the origin at the Earth's center. The ECI frame is fixed with respect to the
142174
/// stars, whereas the ECEF frame rotates with the Earth.
143175
///
144-
/// # Parameters
176+
/// # Arguments
145177
/// - `time` - The time in seconds that define the rotation period
146178
///
147179
/// # Returns
@@ -171,7 +203,7 @@ pub fn eci_to_ecef(time: f64) -> Matrix3<f64> {
171203
/// system with the origin at the Earth's center. The ECI frame is fixed with respect to the
172204
/// stars, whereas the ECEF frame rotates with the Earth.
173205
///
174-
/// # Parameters
206+
/// # Arguments
175207
/// - `time` - The time in seconds that define the rotation period
176208
///
177209
/// # Returns
@@ -194,7 +226,7 @@ pub fn ecef_to_eci(time: f64) -> Matrix3<f64> {
194226
/// position. The local-level frame is defined by the tangent to the ellipsoidal surface at the sensor's
195227
/// position. The local level frame is defined by the WGS84 latitude and longitude.
196228
///
197-
/// # Parameters
229+
/// # Arguments
198230
/// - `latitude` - The WGS84 latitude in degrees
199231
/// - `longitude` - The WGS84 longitude in degrees
200232
///
@@ -231,7 +263,7 @@ pub fn ecef_to_lla(latitude: &f64, longitude: &f64) -> Matrix3<f64> {
231263
/// position. The local-level frame is defined by the tangent to the ellipsoidal surface at the sensor's
232264
/// position. The local level frame is defined by the WGS84 latitude and longitude.
233265
///
234-
/// # Parameters
266+
/// # Arguments
235267
/// - `latitude` - The WGS84 latitude in degrees
236268
/// - `longitude` - The WGS84 longitude in degrees
237269
///
@@ -254,7 +286,7 @@ pub fn lla_to_ecef(latitude: &f64, longitude: &f64) -> Matrix3<f64> {
254286
/// The [principal radii of curvature](https://en.wikipedia.org/wiki/Earth_radius) are used to
255287
/// calculate and convert Cartesian body frame quantities to the local-level frame WGS84 coordinates.
256288
///
257-
/// # Parameters
289+
/// # Arguments
258290
/// - `latitude` - The WGS84 latitude in degrees
259291
/// - `altitude` - The WGS84 altitude in meters
260292
///
@@ -288,7 +320,7 @@ pub fn principal_radii(latitude: &f64, altitude: &f64) -> (f64, f64, f64) {
288320
/// the Earth's gravity as a function of the latitude and altitude. The gravity model is used to
289321
/// calculate the gravitational force scalar in the local-level frame. Free-air correction is applied.
290322
///
291-
/// # Parameters
323+
/// # Arguments
292324
/// - `latitude` - The WGS84 latitude in degrees
293325
/// - `altitude` - The WGS84 altitude in meters
294326
///
@@ -322,7 +354,7 @@ pub fn gravity(latitude: &f64, altitude: &f64) -> f64 {
322354
/// Down (NED) or East, North, Up (ENU). This function uses the ENU convention, thus gravity acts
323355
/// along the negative Z-axis (downward) in the local-level frame.
324356
///
325-
/// # Parameters
357+
/// # Arguments
326358
/// - `latitude` - The WGS84 latitude in degrees
327359
/// - `longitude` - The WGS84 longitude in degrees
328360
/// - `altitude` - The WGS84 altitude in meters
@@ -359,7 +391,7 @@ pub fn gravitation(latitude: &f64, longitude: &f64, altitude: &f64) -> Vector3<f
359391
/// at the given latitude and altitude via the Somigliana method. Additionally, this function
360392
/// compensates for the motion of the platform (if any) using the Eötvös correction.
361393
///
362-
/// # Parameters
394+
/// # Arguments
363395
/// - `latitude` - The WGS84 latitude in degrees
364396
/// - `altitude` - The WGS84 altitude in meters
365397
/// - `north_velocity` - The northward velocity component in m/s
@@ -406,7 +438,7 @@ pub fn eotvos(latitude: &f64, altitude: &f64, north_velocity: &f64, east_velocit
406438
/// The Earth's rotation rate modeled as a vector in the local-level frame. This vector
407439
/// is used to calculate the Coriolis and centrifugal effects in the local-level frame.
408440
///
409-
/// # Parameters
441+
/// # Arguments
410442
/// - `latitude` - The WGS84 latitude in degrees
411443
///
412444
/// # Returns
@@ -430,7 +462,7 @@ pub fn earth_rate_lla(latitude: &f64) -> Vector3<f64> {
430462
/// with respect to the ECEF frame since the origin point of the local-level frame is
431463
/// always tangential to the WGS84 ellipsoid and thus constantly moving in the ECEF frame.
432464
///
433-
/// # Parameters
465+
/// # Arguments
434466
/// - `latitude` - The WGS84 latitude in degrees
435467
/// - `altitude` - The WGS84 altitude in meters
436468
/// - `velocities` - The velocity vector in the local-level frame (northward, eastward, downward)
@@ -463,7 +495,7 @@ pub fn transport_rate(latitude: &f64, altitude: &f64, velocities: &Vector3<f64>)
463495
/// dipole model. The dipole model approximates the Earth's magnetic field as a magnetic
464496
/// dipole with the axis through the geographic poles.
465497
///
466-
/// # Parameters
498+
/// # Arguments
467499
/// - `latitude` - The WGS84 latitude in degrees
468500
/// - `longitude` - The WGS84 longitude in degrees
469501
/// - `altitude` - The WGS84 altitude in meters
@@ -496,7 +528,7 @@ pub fn calculate_magnetic_field(latitude: &f64, longitude: &f64, altitude: &f64)
496528

497529
/// Calculate the radial component of Earth's magnetic field using the dipole model
498530
///
499-
/// # Parameters
531+
/// # Arguments
500532
/// - `colatitude` - The magnetic *colatitude* in radians (angle from magnetic north pole)
501533
/// - `radius` - The distance from Earth's center in meters
502534
///
@@ -518,7 +550,7 @@ pub fn calculate_radial_magnetic_field(colatitude: f64, radius: f64) -> f64 {
518550

519551
/// Calculate the latitudinal component of Earth's magnetic field using the dipole model
520552
///
521-
/// # Parameters
553+
/// # Arguments
522554
/// - `colatitude` - The magnetic *colatitude* in radians (angle from magnetic north pole)
523555
/// - `radius` - The distance from Earth's center in meters
524556
///
@@ -541,7 +573,7 @@ pub fn calculate_latitudinal_magnetic_field(colatitude: f64, radius: f64) -> f64
541573
/// using the dipole model of Earth's magnetic field. The transformation is based on
542574
/// the location of the geomagnetic north pole.
543575
///
544-
/// # Parameters
576+
/// # Arguments
545577
/// - `latitude` - The WGS84 latitude in degrees
546578
/// - `longitude` - The WGS84 longitude in degrees
547579
///
@@ -587,7 +619,7 @@ pub fn wgs84_to_magnetic(latitude: &f64, longitude: &f64) -> (f64, f64) {
587619
/// magnetic field vector, positive downward. At the magnetic equator, the inclination
588620
/// is zero. At the magnetic poles, the inclination is ±90°.
589621
///
590-
/// # Parameters
622+
/// # Arguments
591623
/// - `latitude` - The WGS84 latitude in degrees
592624
/// - `longitude` - The WGS84 longitude in degrees
593625
/// - `altitude` - The WGS84 altitude in meters
@@ -621,7 +653,7 @@ pub fn magnetic_inclination(latitude: &f64, longitude: &f64, altitude: &f64) ->
621653
/// positive eastward. This is essential for navigation as it represents the correction
622654
/// needed to convert between magnetic compass readings and true bearings.
623655
///
624-
/// # Parameters
656+
/// # Arguments
625657
/// - `latitude` - The WGS84 latitude in degrees
626658
/// - `longitude` - The WGS84 longitude in degrees
627659
/// - `altitude` - The WGS84 altitude in meters

0 commit comments

Comments
 (0)