Skip to content

Commit

Permalink
improve QNH temperature correction
Browse files Browse the repository at this point in the history
  • Loading branch information
rkusa committed May 2, 2021
1 parent efddbf9 commit 5058687
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 40 deletions.
6 changes: 3 additions & 3 deletions crates/datis-core/src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl MissionRpc {
)
.await?;
// ... to retrieve the QNH
let pressure_qnh = data.pressure;
let pressure_sealevel = data.pressure;

// then get weather at actual altitude
let data: Data = self
Expand Down Expand Up @@ -82,8 +82,8 @@ impl MissionRpc {
wind_speed: data.wind_speed,
wind_dir,
temperature: data.temp,
pressure_qnh,
pressure_qfe: data.pressure,
pressure_sealevel,
pressure_groundlevel: data.pressure,
fog_thickness: data.fog_thickness,
fog_visibility: data.fog_visibility,
dust_density: data.dust_density,
Expand Down
34 changes: 17 additions & 17 deletions crates/datis-core/src/station.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ fn hectopascal_report(weather: &WeatherInfo, alt: Length, spoken: bool) -> Strin
)
}

fn qfe_report(weather: &WeatherInfo, alt: Length, spoken: bool) -> String {
fn qfe_report(weather: &WeatherInfo, spoken: bool) -> String {
format!(
"QFE {} {}or {}. {}",
// times 100, because we don't want to speak the DECIMAL place
pronounce_number(
(weather.get_qfe(alt).get::<inch_of_mercury>() * 100.0).round(),
(weather.get_qfe().get::<inch_of_mercury>() * 100.0).round(),
spoken
),
if spoken {
Expand All @@ -212,7 +212,7 @@ fn qfe_report(weather: &WeatherInfo, alt: Length, spoken: bool) -> String {
} else {
""
},
pronounce_number(weather.get_qfe(alt).get::<hectopascal>().round(), spoken),
pronounce_number(weather.get_qfe().get::<hectopascal>().round(), spoken),
break_(spoken),
)
}
Expand Down Expand Up @@ -396,8 +396,8 @@ impl Station {
wind_speed: Velocity::new::<knot>(5.0),
wind_dir: Angle::new::<degree>(330.0),
temperature: Temperature::new::<degree_celsius>(22.0),
pressure_qnh: Pressure::new::<pascal>(101_500.0),
pressure_qfe: Pressure::new::<pascal>(101_500.0),
pressure_sealevel: Pressure::new::<pascal>(101_500.0),
pressure_groundlevel: Pressure::new::<pascal>(101_500.0),
position: Position::default(),
..Default::default()
};
Expand Down Expand Up @@ -516,7 +516,7 @@ impl Airfield {

report += &format!("REMARKS. {}", break_(spoken));
report += &hectopascal_report(weather, alt, spoken);
report += &qfe_report(weather, alt, spoken);
report += &qfe_report(weather, spoken);

report += &format!("End information {}.", information_letter);

Expand Down Expand Up @@ -653,7 +653,7 @@ impl WeatherTransmitter {

report += &format!("REMARKS. {}", break_(spoken),);
report += &hectopascal_report(weather, alt, spoken);
report += &qfe_report(weather, alt, spoken);
report += &qfe_report(weather, spoken);

report += &format!("End information {}.", information_letter);

Expand Down Expand Up @@ -752,8 +752,8 @@ mod test {
};

let report = station.generate_report(26).await.unwrap().unwrap();
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is Kutaisi information Alpha. | Runway in use is ZERO 4. | Traffic frequency 2 4 NINER DECIMAL 5. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 7. | REMARKS. | 1 ZERO 1 5 hectopascal. | QFE 2 NINER NINER 7 <break time=\"500ms\" /> or 1 ZERO 1 5. | End information Alpha.\n</speak>");
assert_eq!(report.textual, "This is Kutaisi information Alpha. Runway in use is 04. Traffic frequency 249.5. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2997. REMARKS. 1015 hectopascal. QFE 2997 or 1015. End information Alpha.");
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is Kutaisi information Alpha. | Runway in use is ZERO 4. | Traffic frequency 2 4 NINER DECIMAL 5. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 5. | REMARKS. | 1 ZERO 1 4 hectopascal. | QFE 2 NINER NINER 5 <break time=\"500ms\" /> or 1 ZERO 1 4. | End information Alpha.\n</speak>");
assert_eq!(report.textual, "This is Kutaisi information Alpha. Runway in use is 04. Traffic frequency 249.5. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2995. REMARKS. 1014 hectopascal. QFE 2995 or 1014. End information Alpha.");
}

#[tokio::test]
Expand All @@ -775,8 +775,8 @@ mod test {
};

let report = station.generate_report(26).await.unwrap().unwrap();
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is Kutaisi information Papa. | Runway in use is ZERO 4. | Traffic frequency 2 4 NINER DECIMAL 5. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 7. | REMARKS. | 1 ZERO 1 5 hectopascal. | QFE 2 NINER NINER 7 <break time=\"500ms\" /> or 1 ZERO 1 5. | End information Papa.\n</speak>");
assert_eq!(report.textual, "This is Kutaisi information Papa. Runway in use is 04. Traffic frequency 249.5. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2997. REMARKS. 1015 hectopascal. QFE 2997 or 1015. End information Papa.");
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is Kutaisi information Papa. | Runway in use is ZERO 4. | Traffic frequency 2 4 NINER DECIMAL 5. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 5. | REMARKS. | 1 ZERO 1 4 hectopascal. | QFE 2 NINER NINER 5 <break time=\"500ms\" /> or 1 ZERO 1 4. | End information Papa.\n</speak>");
assert_eq!(report.textual, "This is Kutaisi information Papa. Runway in use is 04. Traffic frequency 249.5. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2995. REMARKS. 1014 hectopascal. QFE 2995 or 1014. End information Papa.");
}

#[tokio::test]
Expand All @@ -798,8 +798,8 @@ mod test {
};

let report = station.generate_report(26).await.unwrap().unwrap();
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is Kutaisi information Quebec. | Runway in use is ZERO 4. | Traffic frequency 2 4 NINER DECIMAL 5. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 7. | REMARKS. | 1 ZERO 1 5 hectopascal. | QFE 2 NINER NINER 7 <break time=\"500ms\" /> or 1 ZERO 1 5. | End information Quebec.\n</speak>");
assert_eq!(report.textual, "This is Kutaisi information Quebec. Runway in use is 04. Traffic frequency 249.5. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2997. REMARKS. 1015 hectopascal. QFE 2997 or 1015. End information Quebec.");
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is Kutaisi information Quebec. | Runway in use is ZERO 4. | Traffic frequency 2 4 NINER DECIMAL 5. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 5. | REMARKS. | 1 ZERO 1 4 hectopascal. | QFE 2 NINER NINER 5 <break time=\"500ms\" /> or 1 ZERO 1 4. | End information Quebec.\n</speak>");
assert_eq!(report.textual, "This is Kutaisi information Quebec. Runway in use is 04. Traffic frequency 249.5. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2995. REMARKS. 1014 hectopascal. QFE 2995 or 1014. End information Quebec.");
}

#[test]
Expand Down Expand Up @@ -828,8 +828,8 @@ mod test {
};

let report = station.generate_report(26).await.unwrap().unwrap();
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\n99, | Stennis\'s <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">wind</phoneme> 3 3 ZERO at 5 knots, | altimeter 2 NINER NINER 7, | CASE 1, | BRC 1 8 ZERO, | expected final heading 1 7 1, | report initial.\n</speak>");
assert_eq!(report.textual, "99, Stennis\'s wind 330 at 5 knots, altimeter 2997, CASE 1, BRC 180, expected final heading 171, report initial.");
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\n99, | Stennis\'s <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">wind</phoneme> 3 3 ZERO at 5 knots, | altimeter 3 ZERO ZERO 3, | CASE 1, | BRC 1 8 ZERO, | expected final heading 1 7 1, | report initial.\n</speak>");
assert_eq!(report.textual, "99, Stennis\'s wind 330 at 5 knots, altimeter 3003, CASE 1, BRC 180, expected final heading 171, report initial.");
}

#[tokio::test]
Expand Down Expand Up @@ -873,7 +873,7 @@ mod test {
};

let report = station.generate_report(26).await.unwrap().unwrap();
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is weather station Mountain Range information Papa. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 7. | REMARKS. | 1 ZERO 1 5 hectopascal. | QFE 2 NINER NINER 7 <break time=\"500ms\" /> or 1 ZERO 1 5. | End information Papa.\n</speak>");
assert_eq!(report.textual, "This is weather station Mountain Range information Papa. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2997. REMARKS. 1015 hectopascal. QFE 2997 or 1015. End information Papa.");
assert_eq!(report.spoken, "<speak version=\"1.0\" xml:lang=\"en\">\nThis is weather station Mountain Range information Papa. | <phoneme alphabet=\"ipa\" ph=\"w&#618;nd\">Wind</phoneme> 3 3 ZERO at 5 knots. | Temperature 2 2 celcius. | ALTIMETER 2 NINER NINER 5. | REMARKS. | 1 ZERO 1 4 hectopascal. | QFE 2 NINER NINER 5 <break time=\"500ms\" /> or 1 ZERO 1 4. | End information Papa.\n</speak>");
assert_eq!(report.textual, "This is weather station Mountain Range information Papa. Wind 330 at 5 knots. Temperature 22 celcius. ALTIMETER 2995. REMARKS. 1014 hectopascal. QFE 2995 or 1014. End information Papa.");
}
}
38 changes: 18 additions & 20 deletions crates/datis-core/src/weather.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::station::Position;
use serde::Deserialize;
use uom::num::Zero;
use uom::num_traits::Pow;
use uom::si::f64::{Angle, Pressure, ThermodynamicTemperature as Temperature, Velocity};
use uom::si::i32::Length;
use uom::si::length::{foot, meter};
use uom::si::pressure::pascal;
use uom::si::thermodynamic_temperature::degree_celsius;
use uom::si::pressure::{inch_of_mercury, millibar, pascal};

#[derive(Debug, PartialEq, Clone, Default)]
pub struct WeatherInfo {
Expand All @@ -14,8 +14,8 @@ pub struct WeatherInfo {
/// The direction the wind is coming from
pub wind_dir: Angle,
pub temperature: Temperature,
pub pressure_qnh: Pressure,
pub pressure_qfe: Pressure,
pub pressure_sealevel: Pressure,
pub pressure_groundlevel: Pressure,
/// This basically determines how heigh the fog is, from 0 to `fog_thickness`.
pub fog_thickness: Length,
pub fog_visibility: Length,
Expand Down Expand Up @@ -67,25 +67,23 @@ pub struct OldClouds {
impl WeatherInfo {
/// Get QNH correct for the current temperature (as far as possible in DCS)
pub fn get_qnh(&self, alt: Length) -> Pressure {
self.pressure_qnh + self.pressure_correction(alt)
}
// see https://en.wikipedia.org/wiki/Pressure_altitude
let pressure_altitude: f64 = 14_5366.45
* (1.0
- (self.get_qfe().get::<millibar>() / self.pressure_sealevel.get::<millibar>())
.pow(0.190284));
let alt_diff = f64::from(alt.get::<foot>()) - pressure_altitude;

/// Get QFE correct for the current temperature (as far as possible in DCS)
pub fn get_qfe(&self, alt: Length) -> Pressure {
self.pressure_qfe + self.pressure_correction(alt)
// this corrects the pressure for the current temperature
let correction = Pressure::new::<pascal>(alt_diff / 27.0 * 100.0);

self.pressure_sealevel + correction
}

fn pressure_correction(&self, alt: Length) -> Pressure {
let alt = alt.get::<foot>();
let angels = f64::from(alt) / 1000.0;
// ISA at see level is 16 and not 15 in DCS, see
// https://forums.eagle.ru/topic/256057-altitude-qnh-error-bug/
let isa_at_alt = 16.0 - 1.98 * angels;
let isa_diff = self.temperature.get::<degree_celsius>() - isa_at_alt;
let palt_diff = 4.0 * isa_diff * angels;

// translate alt diff into a QNH diff
Pressure::new::<pascal>((palt_diff / 27.0) * 100.0)
/// Get QFE correct for the current temperature (as far as possible in DCS)
pub fn get_qfe(&self) -> Pressure {
// offset ground level pressure by empirically derived offset (DCS specific)
self.pressure_groundlevel - Pressure::new::<inch_of_mercury>(0.02)
}

pub fn get_visibility(&self, alt: Length) -> Option<Length> {
Expand Down

0 comments on commit 5058687

Please sign in to comment.