Skip to content

Commit

Permalink
Aircraft performance handler:
Browse files Browse the repository at this point in the history
Fixed issues in where states were not detected properly.
Corrected fuel calculation which is now only done if fuel flow is detected to avoid case where user changes fuel in the simulator.
Fixed issue where aircraft descending was not detected.
Added method to give aircraft state as text.
albar965/littlenavmap#340
  • Loading branch information
albar965 committed Jul 10, 2019
1 parent 5c3f6dd commit ce7cb86
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 19 deletions.
92 changes: 74 additions & 18 deletions src/fs/perf/aircraftperfhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ void AircraftPerfHandler::start()
{
currentFlightSegment = NONE;
startFuel = totalFuelConsumed = weightVolRatio = 0.f;

lastSampleTimeMs = lastCruiseSampleTimeMs = lastClimbSampleTimeMs = lastDescentSampleTimeMs = 0L;

aircraftClimb = aircraftDescent = aircraftFuelFlow = aircraftGround = aircraftFlying = false;
aircraftCruise = 0;

perf->setNull();

active = true;
Expand All @@ -71,6 +75,13 @@ void AircraftPerfHandler::simDataChanged(const sc::SimConnectData& simulatorData
if(!active || !aircraft.isValid() || aircraft.isSimPaused() || aircraft.isSimReplay())
return;

aircraftClimb = isClimbing(aircraft);
aircraftDescent = isDescending(aircraft);
aircraftCruise = isAtCruise(aircraft);
aircraftFuelFlow = aircraft.hasFuelFlow();
aircraftGround = aircraft.isOnGround();
aircraftFlying = aircraft.isFlying();

// Fill metadata if still empty
if(perf->getAircraftType().isEmpty())
perf->setAircraftType(aircraft.getAirplaneModel());
Expand All @@ -89,16 +100,20 @@ void AircraftPerfHandler::simDataChanged(const sc::SimConnectData& simulatorData
perf->setJetFuel(jetfuel);
qDebug() << Q_FUNC_INFO << "weightVolRatio" << weightVolRatio << "jetfuel" << perf->isJetFuel();
}
// else insufficient fuel amount
}

// Remember fuel in tanks if not done already ========================================================
if(startFuel < 0.1f)
// Delay fuel calculation until there is fuel flow to avoid catching user changes
// in fuel amount before flight
if(startFuel < 0.1f && aircraftFuelFlow)
{
startFuel = aircraft.getFuelTotalWeightLbs();
qDebug() << Q_FUNC_INFO << "startFuel" << startFuel;
}

totalFuelConsumed = startFuel - aircraft.getFuelTotalWeightLbs();
if(aircraftFuelFlow)
totalFuelConsumed = startFuel - aircraft.getFuelTotalWeightLbs();

// Determine current flight sement ================================================================
FlightSegment flightSegment = currentFlightSegment;
Expand All @@ -111,53 +126,53 @@ void AircraftPerfHandler::simDataChanged(const sc::SimConnectData& simulatorData

case NONE:
// Nothing sampled yet - start from scratch ==============
if(aircraft.isOnGround())
flightSegment = aircraft.hasFuelFlow() ? DEPARTURE_TAXI : DEPARTURE_PARKING;
else if(isAtCruise(aircraft) == 0)
if(aircraftGround)
flightSegment = aircraftFuelFlow ? DEPARTURE_TAXI : DEPARTURE_PARKING;
else if(aircraftCruise == 0)
flightSegment = CRUISE;
else if(isClimbing(aircraft) && isAtCruise(aircraft) == -1)
else if(isClimbing(aircraft) && aircraftCruise == -1)
flightSegment = CLIMB;
else if(isDescending(aircraft) && isAtCruise(aircraft) == -1)
else if(isDescending(aircraft) && aircraftCruise == -1)
flightSegment = DESCENT;
break;

case DEPARTURE_PARKING:
if(aircraft.hasFuelFlow())
if(aircraftFuelFlow)
flightSegment = DEPARTURE_TAXI;
if(aircraft.isFlying())
if(aircraftFlying)
// Skip directly to climb if in the air
flightSegment = CLIMB;
break;

case DEPARTURE_TAXI:
if(aircraft.isFlying())
if(aircraftFlying)
flightSegment = CLIMB;
break;

case CLIMB:
if(isAtCruise(aircraft) >= 0)
if(aircraftCruise >= 0)
// At cruise - 200 ft or above
flightSegment = CRUISE;
break;

case CRUISE:
if(isAtCruise(aircraft) < 0)
if(aircraftCruise < 0)
// Below cruise - start descent
flightSegment = DESCENT;
break;

case DESCENT:
if(!aircraft.isFlying())
if(!aircraftFlying)
// Landed
flightSegment = DESTINATION_TAXI;

if(isAtCruise(aircraft) >= 0)
if(aircraftCruise >= 0)
// Momentary deviation go back to cruise
flightSegment = CRUISE;
break;

case DESTINATION_TAXI:
if(!aircraft.hasFuelFlow())
if(!aircraftFuelFlow)
// Engine shutdown
flightSegment = DESTINATION_PARKING;
break;
Expand All @@ -182,7 +197,7 @@ void AircraftPerfHandler::simDataChanged(const sc::SimConnectData& simulatorData
}

// Sum up taxi fuel ========================================================
if(currentFlightSegment == DEPARTURE_TAXI)
if(currentFlightSegment == DEPARTURE_TAXI && aircraftFuelFlow)
perf->setTaxiFuel(startFuel - aircraft.getFuelTotalWeightLbs());

// Sample every 500 ms ========================================
Expand Down Expand Up @@ -210,6 +225,47 @@ void AircraftPerfHandler::setAircraftPerformance(const AircraftPerf& value)
*perf = value;
}

QStringList AircraftPerfHandler::getAircraftStatusTexts()
{
QStringList retval;
if(aircraftGround)
{
retval.append(tr("on ground"));
if(aircraftFuelFlow)
retval.append(tr("fuel flow"));
}

if(aircraftFlying)
{
// retval.append(tr("flight"));
if(aircraftClimb)
retval.append(tr("climbing"));
else if(aircraftDescent)
retval.append(tr("descending"));
else
{
if(aircraftCruise == 0)
retval.append(tr("at cruise altitude"));
else if(aircraftCruise < 0)
retval.append(tr("below cruise altitude"));
else if(aircraftCruise > 0)
retval.append(tr("above cruise altitude"));
}
}

if(!retval.isEmpty())
{
QString& first = retval.first();
if(!first.isEmpty())
{
QChar firstChar = first.at(0);
first.remove(0, 1);
first.prepend(firstChar.toUpper());
}
}
return retval;
}

float AircraftPerfHandler::sampleValue(qint64 lastSampleDuration, qint64 curSampleDuration, float lastValue,
float curValue)
{
Expand Down Expand Up @@ -279,12 +335,12 @@ void AircraftPerfHandler::samplePhase(FlightSegment flightSegment, const SimConn

bool AircraftPerfHandler::isClimbing(const SimConnectUserAircraft& aircraft) const
{
return aircraft.getVerticalSpeedFeetPerMin() > 200.f;
return aircraft.getVerticalSpeedFeetPerMin() > 150.f;
}

bool AircraftPerfHandler::isDescending(const SimConnectUserAircraft& aircraft) const
{
return aircraft.getVerticalSpeedFeetPerMin() < 200.f;
return aircraft.getVerticalSpeedFeetPerMin() < -150.f;
}

int AircraftPerfHandler::isAtCruise(const SimConnectUserAircraft& aircraft) const
Expand Down
9 changes: 9 additions & 0 deletions src/fs/perf/aircraftperfhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ class AircraftPerfHandler
/* Sets a copy */
void setAircraftPerformance(const atools::fs::perf::AircraftPerf& value);

/* Get a list describing aircraft status, like cruise, fuel flow, etc */
QStringList getAircraftStatusTexts();

signals:
void flightSegmentChanged(const atools::fs::perf::FlightSegment& flightSegment);

Expand Down Expand Up @@ -143,6 +146,12 @@ class AircraftPerfHandler
/* Collecting data if true. Set to false after landing. */
bool active = false;

bool aircraftClimb = false, aircraftDescent = false, aircraftFuelFlow = false, aircraftGround = false,
aircraftFlying = false;

/* -1 if below, 0 if at and 1 if above flight plan cruise altitude. Use below as default. */
int aircraftCruise = -1;

/* Last time of sample to allow calculation of averages */
qint64 lastSampleTimeMs = 0L;
qint64 lastCruiseSampleTimeMs = 0L, lastClimbSampleTimeMs = 0L, lastDescentSampleTimeMs = 0L;
Expand Down
2 changes: 1 addition & 1 deletion src/fs/sc/simconnectuseraircraft.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class SimConnectUserAircraft :

bool hasFuelFlow() const
{
return fuelFlowGPH > 1.f || fuelFlowPPH > 0.1f;
return fuelFlowGPH > 0.5f || fuelFlowPPH > 1.0f;
}

/* Calculate the weight/volume ratio and determine if it is jet fuel
Expand Down

0 comments on commit ce7cb86

Please sign in to comment.