void FlightSetupPanel::Prepare(ContainerWindow &parent, const PixelRect &rc) { RowFormWidget::Prepare(parent, rc); const ComputerSettings &settings = CommonInterface::GetComputerSettings(); const Plane &plane = CommonInterface::GetComputerSettings().plane; const double db = 5; AddFloat(_("Ballast"), _("Ballast of the glider. Increase this value if the pilot/cockpit load is greater than the reference pilot weight of the glide polar (typically 75kg). Press ENTER on this field to toggle count-down of the ballast volume according to the dump rate specified in the configuration settings."), _T("%.0f l"), _T("%.0f"), 0, db*ceil(plane.max_ballast/db), db, false, 0, this); WndProperty *wing_loading = AddFloat(_("Wing loading"), nullptr, _T("%.1f %s"), _T("%.0f"), 0, 300, 5, false, UnitGroup::WING_LOADING, 0); wing_loading->SetReadOnly(true); AddFloat(_("Bugs"), /* xgettext:no-c-format */ _("How clean the glider is. Set to 0% for clean, larger numbers as the wings " "pick up bugs or gets wet. 50% indicates the glider's sink rate is doubled."), _T("%.0f %%"), _T("%.0f"), 0, 50, 1, false, (1 - polar_settings.bugs) * 100, this); WndProperty *wp; wp = AddFloat(_("QNH"), _("Area pressure for barometric altimeter calibration. This is set automatically if Vega connected."), GetUserPressureFormat(true), GetUserPressureFormat(), Units::ToUserPressure(Units::ToSysUnit(850, Unit::HECTOPASCAL)), Units::ToUserPressure(Units::ToSysUnit(1300, Unit::HECTOPASCAL)), GetUserPressureStep(), false, Units::ToUserPressure(settings.pressure), this); { DataFieldFloat &df = *(DataFieldFloat *)wp->GetDataField(); df.SetUnits(Units::GetPressureName()); wp->RefreshDisplay(); } AddReadOnly(_("Altitude"), NULL, _T("%.0f %s"), UnitGroup::ALTITUDE, 0); wp = AddFloat(_("Max. temp."), _("Set to forecast ground temperature. Used by convection estimator (temperature trace page of Analysis dialog)"), _T("%.0f %s"), _T("%.0f"), Units::ToUserTemperature(CelsiusToKelvin(-50)), Units::ToUserTemperature(CelsiusToKelvin(60)), 1, false, Units::ToUserTemperature(settings.forecast_temperature)); { DataFieldFloat &df = *(DataFieldFloat *)wp->GetDataField(); df.SetUnits(Units::GetTemperatureName()); wp->RefreshDisplay(); } }
/** * Parse the $PLXVS sentence (LXNav V7). * * $PLXVS,OAT,mode,voltage *CS<CR><LF> * * Example: $PLXVS,23.1,0,12.3,*CS<CR><LF> * * @see http://www.xcsoar.org/trac/raw-attachment/ticket/1666/V7%20dataport%20specification%201.97.pdf */ static bool PLXVS(NMEAInputLine &line, NMEAInfo &info) { fixed temperature; if (line.ReadChecked(temperature)) { info.temperature = CelsiusToKelvin(temperature); info.temperature_available = true; } int mode; info.switch_state.flight_mode = SwitchState::FlightMode::UNKNOWN; if (line.ReadChecked(mode)) { if (mode == 0) info.switch_state.flight_mode = SwitchState::FlightMode::CIRCLING; else if (mode == 1) info.switch_state.flight_mode = SwitchState::FlightMode::CRUISE; } fixed voltage; if (line.ReadChecked(voltage)) { info.voltage = voltage; info.voltage_available.Update(info.clock); } return true; }
/** * Parse a "$VMVABD" sentence. * * Example: "$VMVABD,0000.0,M,0547.0,M,-0.0,,,MS,0.0,KH,22.4,C*65" */ static bool FlytecParseVMVABD(NMEAInputLine &line, NMEAInfo &info) { fixed value; // 0,1 = GPS altitude, unit if (line.ReadCheckedCompare(info.gps_altitude, "M")) info.gps_altitude_available.Update(info.clock); // 2,3 = baro altitude, unit if (line.ReadCheckedCompare(value, "M")) info.ProvideBaroAltitudeTrue(value); // 4-7 = integrated vario, unit line.Skip(4); // 8,9 = indicated or true airspeed, unit if (line.ReadCheckedCompare(value, "KH")) // XXX is that TAS or IAS? Documentation isn't clear. info.ProvideBothAirspeeds(Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR)); // 10,11 = temperature, unit info.temperature_available = line.ReadCheckedCompare(value, "C"); if (info.temperature_available) info.temperature = CelsiusToKelvin(value); return true; }
void ComputerSettings::SetDefaults() { wind.SetDefaults(); polar.SetDefaults(); team_code.SetDefaults(); voice.SetDefaults(); poi.SetDefaults(); features.SetDefaults(); circling.SetDefaults(); wave.SetDefaults(); average_eff_time = ae30seconds; set_system_time_from_gps = false; utc_offset = RoughTimeDelta::FromSeconds(GetSystemUTCOffset()); forecast_temperature = CelsiusToKelvin(25); pressure = AtmosphericPressure::Standard(); pressure_available.Clear(); airspace.SetDefaults(); task.SetDefaults(); contest.SetDefaults(); logger.SetDefaults(); #ifdef HAVE_TRACKING tracking.SetDefaults(); #endif weather.SetDefaults(); }
bool OpenVarioDevice::POV(NMEAInputLine &line, NMEAInfo &info) { /* * Type definitions: * * E: TE vario in m/s * P: static pressure in hPa * Q: dynamic pressure in Pa * R: total pressure in hPa * S: true airspeed in km/h * T: temperature in deg C */ while (!line.IsEmpty()) { char type = line.ReadOneChar(); if (type == '\0') break; fixed value; if (!line.ReadChecked(value)) break; switch (type) { case 'E': { info.ProvideTotalEnergyVario(value); break; } case 'P': { AtmosphericPressure pressure = AtmosphericPressure::HectoPascal(value); info.ProvideStaticPressure(pressure); break; } case 'Q': { AtmosphericPressure pressure = AtmosphericPressure::Pascal(value); info.ProvideDynamicPressure(pressure); break; } case 'R': { AtmosphericPressure pressure = AtmosphericPressure::HectoPascal(value); info.ProvidePitotPressure(pressure); break; } case 'S': { value = Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR); info.ProvideTrueAirspeed(value); break; } case 'T': { info.temperature = CelsiusToKelvin(value); info.temperature_available = true; break; } } } return true; }
JNIEXPORT void JNICALL Java_org_xcsoar_NativeBMP085Listener_onBMP085Values(JNIEnv *env, jobject obj, jdouble temperature, jint pressure) { jlong ptr = env->GetLongField(obj, NativeBMP085Listener::ptr_field); if (ptr == 0) return; BMP085Listener &listener = *(BMP085Listener *)(void *)ptr; listener.onBMP085Values(CelsiusToKelvin(fixed(temperature)), AtmosphericPressure::Pascal(fixed(pressure))); }
/** * $PWES0,DD,VVVV,MMMM,NNNN,BBBB,SSSS,AAAAA,QQQQQ,IIII,TTTT,UUU,CCCC*CS<CR><LF> */ static bool PWES0(NMEAInputLine &line, NMEAInfo &info) { int i; line.Skip(); /* device */ if (line.ReadChecked(i) && i >= -999 && i <= 999) info.ProvideTotalEnergyVario(fixed(i) / 10); line.Skip(); /* average vario */ if (line.ReadChecked(i) && i >= -999 && i <= 999) info.ProvideNettoVario(fixed(i) / 10); line.Skip(); /* average netto vario */ line.Skip(); /* speed to fly */ unsigned altitude; if (line.ReadChecked(altitude) && altitude <= 99999) info.ProvidePressureAltitude(fixed(altitude)); if (line.ReadChecked(altitude) && altitude <= 99999) info.ProvideBaroAltitudeTrue(fixed(altitude)); unsigned ias, tas; bool have_ias = line.ReadChecked(ias) && ias <= 9999; bool have_tas = line.ReadChecked(tas) && tas <= 9999; if (have_ias && have_tas) info.ProvideBothAirspeeds(Units::ToSysUnit(fixed(ias) / 10, Unit::KILOMETER_PER_HOUR), Units::ToSysUnit(fixed(tas) / 10, Unit::KILOMETER_PER_HOUR)); else if (!have_ias && have_tas) info.ProvideTrueAirspeed(Units::ToSysUnit(fixed(tas) / 10, Unit::KILOMETER_PER_HOUR)); unsigned voltage; if (line.ReadChecked(voltage) && voltage <= 999) { info.voltage = fixed(voltage) / 10; info.voltage_available.Update(info.clock); } if (line.ReadChecked(i) && i >= -999 && i <= 999) { info.temperature = CelsiusToKelvin(fixed(i) / 10); info.temperature_available = true; } return true; }
/** * $PWES0,DD,VVVV,MMMM,NNNN,BBBB,SSSS,AAAAA,QQQQQ,IIII,TTTT,UUU,CCCC*CS<CR><LF> */ static bool PWES0(NMEAInputLine &line, NMEAInfo &info) { int i, k; line.skip(); /* device */ if (line.read_checked(i)) info.ProvideTotalEnergyVario(fixed(i) / 10); line.skip(); /* average vario */ if (line.read_checked(i)) info.ProvideNettoVario(fixed(i) / 10); line.skip(); /* average netto vario */ line.skip(); /* speed to fly */ if (line.read_checked(i)) info.ProvidePressureAltitude(fixed(i)); if (line.read_checked(i)) info.ProvideBaroAltitudeTrue(fixed(i)); bool have_ias = line.read_checked(i); bool have_tas = line.read_checked(k); if (have_ias && have_tas) info.ProvideBothAirspeeds(Units::ToSysUnit(fixed(i) / 10, Unit::KILOMETER_PER_HOUR), Units::ToSysUnit(fixed(k) / 10, Unit::KILOMETER_PER_HOUR)); else if (!have_ias && have_tas) info.ProvideTrueAirspeed(Units::ToSysUnit(fixed(k) / 10, Unit::KILOMETER_PER_HOUR)); if (line.read_checked(i)) { info.voltage = fixed(i) / 10; info.voltage_available.Update(info.clock); } if (line.read_checked(i)) { info.temperature = CelsiusToKelvin(fixed(i) / 10); info.temperature_available = true; } return true; }
/** * Parse a "$D" sentence. * * Example: "$D,+0,100554,+25,18,+31,,0,-356,+25,+11,115,96*6A" */ static bool LeonardoParseD(NMEAInputLine &line, NMEAInfo &info) { double value; // 0 = vario [dm/s] if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value / 10); if (line.Rest().empty()) /* short "$D" sentence ends after vario */ return true; // 1 = air pressure [Pa] if (line.ReadChecked(value)) info.ProvideStaticPressure(AtmosphericPressure::Pascal(value)); // 2 = netto vario [dm/s] if (line.ReadChecked(value)) info.ProvideNettoVario(value / 10); // 3 = airspeed [km/h] /* XXX is that TAS or IAS? */ if (line.ReadChecked(value)) info.ProvideTrueAirspeed(Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR)); // 4 = temperature [deg C] double oat; info.temperature_available = line.ReadChecked(oat); if (info.temperature_available) info.temperature = CelsiusToKelvin(oat); // 5 = compass [degrees] /* XXX unsupported by XCSoar */ // 6 = optimal speed [km/h] /* XXX unsupported by XCSoar */ // 7 = equivalent MacCready [cm/s] /* XXX unsupported by XCSoar */ // 8 = wind speed [km/h] /* not used here, the "$C" record repeats it together with the direction */ return true; }
/** * Parse a "$C" sentence. * * Example: "$C,+2025,-7,+18,+25,+29,122,314,314,0,-356,+25,45,T*3D" */ static bool LeonardoParseC(NMEAInputLine &line, NMEAInfo &info) { double value; // 0 = altitude [m] if (line.ReadChecked(value)) info.ProvideBaroAltitudeTrue(value); // 1 = vario [cm/s] if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value / 100); // 2 = airspeed [km/h] /* XXX is that TAS or IAS? */ if (line.ReadChecked(value)) info.ProvideTrueAirspeed(Units::ToSysUnit(value, Unit::KILOMETER_PER_HOUR)); if (line.Rest().empty()) /* short "$C" sentence ends after airspeed */ return true; // 3 = netto vario [dm/s] if (line.ReadChecked(value)) info.ProvideNettoVario(value / 10); // 4 = temperature [deg C] double oat; info.temperature_available = line.ReadChecked(oat); if (info.temperature_available) info.temperature = CelsiusToKelvin(oat); line.Skip(5); // 10 = wind speed [km/h] // 11 = wind direction [degrees] SpeedVector wind; if (ReadSpeedVector(line, wind)) info.ProvideExternalWind(wind); return true; }
void VoltageDevice::onVoltageValues(int temp_adc, int voltage_index, int volt_adc) { ScopeLock protect(device_blackboard->mutex); NMEAInfo &basic = device_blackboard->SetRealState(index); basic.UpdateClock(); basic.alive.Update(basic.clock); // When no calibration data present, use defaults if (factor == fixed(0)) { // Set default for temp sensor only when sensor present. if (temp_adc >= 0 && offset == fixed(0)) offset = fixed(-130); factor = fixed(0.016666); basic.ProvideSensorCalibration(factor, offset); } if (temp_adc >= 0) { fixed v = CelsiusToKelvin(offset + fixed(temp_adc)); if (temperature_filter.Update(v)) v = temperature_filter.Average(); basic.temperature = v; basic.temperature_available = true; } else { basic.temperature_available = false; } if ((unsigned)voltage_index < NUMBER_OF_VOLTAGES) { fixed v; switch (voltage_index) { case 0: v = factor * volt_adc; break; case 1: v = fixed(0.0071744) * volt_adc; break; case 2: v = (volt_adc - (250*1024)/331) * fixed(0.001786); break; // ACS712 current sensor } if (voltage_filter[voltage_index].Update(v)) v = voltage_filter[voltage_index].Average(); basic.voltage = v; basic.voltage_available.Update(basic.clock); } device_blackboard->ScheduleMerge(); }
static bool VARIO(NMEAInputLine &line, NMEAInfo &info) { // $VARIO,fPressure,fVario,Bat1Volts,Bat2Volts,BatBank,TempSensor1,TempSensor2*CS // fVario = the variometer in decimeters per second // Bat1Volts = the voltage of the battery in bank 1 // Bat2Volts = the voltage of the battery in bank 2 // BatBank = the battery bank in use. // TempSensor1 = temperature in ºC of external wireless sensor 1 // TempSensor2 = temperature in ºC of external wireless sensor 2 fixed value; if (line.ReadChecked(value)) info.ProvideStaticPressure(AtmosphericPressure::HectoPascal(value)); if (line.ReadChecked(value)) info.ProvideTotalEnergyVario(value / 10); unsigned battery_bank; fixed voltage[2]; if (line.ReadChecked(voltage[0]) && line.ReadChecked(voltage[1]) && line.ReadChecked(battery_bank) && battery_bank != 0 && battery_bank <= 2) { info.voltage = voltage[battery_bank - 1]; info.voltage_available.Update(info.clock); } if (line.ReadChecked(value)) { info.temperature = CelsiusToKelvin(value); info.temperature_available = true; } return true; }
/** * Parse a "$FLYSEN" sentence. * * @see http://www.flytec.ch/public/Special%20NMEA%20sentence.pdf */ bool FlytecDevice::ParseFLYSEN(NMEAInputLine &line, NMEAInfo &info) { // Detect firmware/sentence version // // V or A in field 9 -> 3.31- // V or A in field 10 -> 3.32+ NMEAInputLine line_copy(line); line_copy.Skip(8); bool has_date_field = false; char validity = line_copy.ReadFirstChar(); if (validity != 'A' && validity != 'V') { validity = line_copy.ReadFirstChar(); if (validity != 'A' && validity != 'V') return false; has_date_field = true; } // Date(ddmmyy), 6 Digits (only in firmware version 3.32+) if (has_date_field) NMEAParser::ReadDate(line, info.date_time_utc); // Time(hhmmss), 6 Digits fixed time; if (NMEAParser::ReadTime(line, info.date_time_utc, time) && !NMEAParser::TimeHasAdvanced(time, last_time, info)) return true; if (validity == 'V') { // In case of V (void=not valid) GPS data should not be used. // GPS altitude, position and speed should be ignored. line.Skip(7); } else { // Latitude(ddmm.mmm), 8 Digits incl. decimal // N (or S), 1 Digit // Longitude(dddmm.mmm), 9 Digits inc. decimal // E (or W), 1 Digit GeoPoint location; if (NMEAParser::ReadGeoPoint(line, location)) { info.location = location; info.location_available.Update(info.clock); } // Track (xxx Deg), 3 Digits fixed track; if (line.ReadChecked(track)) { info.track = Angle::Degrees(track); info.track_available.Update(info.clock); } // Speed over Ground (xxxxx dm/s), 5 Digits fixed ground_speed; if (line.ReadChecked(ground_speed)) { info.ground_speed = ground_speed / 10; info.ground_speed_available.Update(info.clock); } // GPS altitude (xxxxx meter), 5 Digits fixed gps_altitude; if (line.ReadChecked(gps_altitude)) { info.gps_altitude = gps_altitude; info.gps_altitude_available.Update(info.clock); } } // Validity of 3 D fix A or V, 1 Digit line.Skip(); // Satellites in Use (0 to 12), 2 Digits unsigned satellites_used; if (line.ReadChecked(satellites_used)) { info.gps.satellites_used = satellites_used; info.gps.satellites_used_available.Update(info.clock); } // Raw pressure (xxxxxx Pa), 6 Digits fixed pressure; if (line.ReadChecked(pressure)) info.ProvideStaticPressure(AtmosphericPressure::Pascal(pressure)); // Baro Altitude (xxxxx meter), 5 Digits (-xxxx to xxxxx) (Based on 1013.25hPa) fixed baro_altitude; if (line.ReadChecked(baro_altitude)) info.ProvidePressureAltitude(baro_altitude); // Variometer (xxxx cm/s), 4 or 5 Digits (-9999 to 9999) fixed vario; if (line.ReadChecked(vario)) info.ProvideTotalEnergyVario(vario / 100); // True airspeed (xxxxx dm/s), 5 Digits fixed tas; if (line.ReadChecked(tas)) info.ProvideTrueAirspeed(tas / 10); // Airspeed source P or V, 1 Digit P= pitot, V = Vane wheel line.Skip(); // Temp. PCB (xxx °C), 3 Digits fixed pcb_temperature; bool pcb_temperature_available = line.ReadChecked(pcb_temperature); // Temp. Balloon Envelope (xxx °C), 3 Digits fixed balloon_temperature; bool balloon_temperature_available = line.ReadChecked(balloon_temperature); if (balloon_temperature_available) { info.temperature = CelsiusToKelvin(balloon_temperature); info.temperature_available = true; } else if (pcb_temperature_available) { info.temperature = CelsiusToKelvin(pcb_temperature); info.temperature_available = true; } // Battery Capacity Bank 1 (0 to 100%) 3 Digits fixed battery_level_1; bool battery_level_1_available = line.ReadChecked(battery_level_1); // Battery Capacity Bank 2 (0 to 100%) 3 Digits fixed battery_level_2; bool battery_level_2_available = line.ReadChecked(battery_level_2); if (battery_level_1_available) { if (battery_level_2_available) info.battery_level = (battery_level_1 + battery_level_2) / 2; else info.battery_level = battery_level_1; info.battery_level_available.Update(info.clock); } else if (battery_level_2_available) { info.battery_level = battery_level_2; info.battery_level_available.Update(info.clock); } // Dist. to WP (xxxxxx m), 6 Digits (Max 200000m) // Bearing (xxx Deg), 3 Digits // Speed to fly1 (MC0 xxxxx cm/s), 5 Digits // Speed to fly2 (McC. xxxxx cm/s) 5 Digits // Keypress Code (Experimental empty to 99) 2 Digits return true; }
static bool ParseData(NMEAInputLine &line, NMEAInfo &info) { // $PCPROBE,T,Q0,Q1,Q2,Q3,ax,ay,az,temp,rh,batt,delta_press,abs_press,C, // see http://www.compassitaly.com/CMS/index.php/en/download/c-probe/231-c-probeusermanual/download unsigned _q[4]; bool q_available = line.ReadHexChecked(_q[0]); if (!line.ReadHexChecked(_q[1])) q_available = false; if (!line.ReadHexChecked(_q[2])) q_available = false; if (!line.ReadHexChecked(_q[3])) q_available = false; if (q_available) { fixed q[4]; for (unsigned i = 0; i < 4; ++i) // Cast to int16_t to interpret the 16th bit as the sign bit q[i] = fixed((int16_t)_q[i]) / 1000; fixed sin_pitch = -2 * (q[0] * q[2] - q[3] * q[1]); if (sin_pitch <= fixed(1) && sin_pitch >= fixed(-1)) { info.attitude.pitch_angle_available = true; info.attitude.pitch_angle = Angle::asin(sin_pitch); Angle heading = Angle::HalfCircle() + Angle::FromXY(sqr(q[3]) - sqr(q[0]) - sqr(q[1]) + sqr(q[2]), Double(q[1] * q[2] + q[3] * q[0])); info.attitude.heading_available.Update(info.clock); info.attitude.heading = heading; Angle roll = Angle::FromXY(sqr(q[3]) + sqr(q[0]) - sqr(q[1]) - sqr(q[2]), Double(q[0] * q[1] + q[3] * q[2])); info.attitude.bank_angle_available = true; info.attitude.bank_angle = roll; } } unsigned _a[3]; bool a_available = line.ReadHexChecked(_a[0]); if (!line.ReadHexChecked(_a[1])) a_available = false; if (!line.ReadHexChecked(_a[2])) a_available = false; if (a_available) { fixed a[3]; for (unsigned i = 0; i < 3; ++i) // Cast to int16_t to interpret the 16th bit as the sign bit a[i] = fixed((int16_t)_a[i]) / 1000; info.acceleration.ProvideGLoad(sqrt(sqr(a[0]) + sqr(a[1]) + sqr(a[2])), true); } unsigned temperature; if (line.ReadHexChecked(temperature)) { info.temperature_available = true; info.temperature = CelsiusToKelvin(fixed((int16_t)temperature) / 10); } unsigned humidity; if (line.ReadHexChecked(humidity)) { info.humidity_available = true; info.humidity = fixed((int16_t)humidity) / 10; } unsigned battery_level; if (line.ReadHexChecked(battery_level)) { info.battery_level_available.Update(info.clock); info.battery_level = fixed((int16_t)battery_level); } unsigned _delta_pressure; if (line.ReadHexChecked(_delta_pressure)) { fixed delta_pressure = fixed((int16_t)_delta_pressure) / 10; info.ProvideDynamicPressure(AtmosphericPressure::Pascal(delta_pressure)); } return true; }