package org.envirocar.core.trackprocessing; import com.google.common.base.Preconditions; import org.envirocar.core.entity.Measurement; import org.envirocar.core.exception.FuelConsumptionException; import org.envirocar.core.exception.UnsupportedFuelTypeException; import org.envirocar.core.logging.Logger; import static org.envirocar.core.entity.Measurement.PropertyKey.*; /** * * This implements the diesel fuel calculations based on the following parameters:<br/> * * <ul> * <li>Lambda Voltage equivalence ratio</li> * <li>MAF</li> * <li>a set of pre-calculated co-efficients</li> * </ul> * * Lambda voltage equivalence ratio might not be available in some situations (in deed it is capped * for some cars), thus a a regression function (using lambda voltage) is used to derive the * actual lambda voltage equivalence ratio above the capped values: * * <pre>lambda ER = x1 / ( x2 - x3 * lambda_voltage )</pre> * * with actual values: * * <pre>lambda ER = 0.23478 / ( 0.218911 - 0.18415 * lambda_voltage )</pre> * */ public class DieselConsumptionAlgorithm implements ConsumptionAlgorithm { private static final Logger LOG = Logger.getLogger(DieselConsumptionAlgorithm.class); /** * regression function co-efficients */ private static final double CO_EFFICIENT_X1 = 0.23478; private static final double CO_EFFICIENT_X2 = 0.218911; private static final double CO_EFFICIENT_X3 = 0.18415; /** * the minimum required air for diesel engines */ private static final double MINIMUM_REQUIRED_AIR = 14.5; /** * density of diesel fuel */ private static final double FUEL_DENSITY = 0.832; @Override public double calculateConsumption(Measurement measurement) throws FuelConsumptionException, UnsupportedFuelTypeException { Preconditions.checkNotNull(measurement); if (!measurement.hasProperty(LAMBDA_VOLTAGE_ER) && !measurement.hasProperty(LAMBDA_VOLTAGE)) { throw new FuelConsumptionException("No lambda voltage values available"); } /** * we assume a consumption of zero if the lambda voltage exceeds 1.1 */ Double lambdaV = measurement.getProperty(LAMBDA_VOLTAGE); if (lambdaV > 1.1) { //TODO check with TU-BS - seems to happen very often LOG.info("Lambda Voltage > 1.1; this might be no consumption at all?"); return 0.0; } double lambdaER = calculateLambdaVoltageER(measurement.getProperty(LAMBDA_VOLTAGE_ER), lambdaV); //mass air flow in kilogram double mafKG = resolveMassAirFlow(measurement) / 1000; /** * calculate mass fuel flow in kg/h */ double massFuelFlow = ((mafKG / lambdaER) / MINIMUM_REQUIRED_AIR) * 3600; /** * calculate volumetric fuel flow in l/h */ return massFuelFlow * FUEL_DENSITY; } private double resolveMassAirFlow(Measurement measurement) throws FuelConsumptionException { if (measurement.hasProperty(MAF)) { return measurement.getProperty(MAF); } else if (measurement.hasProperty(CALCULATED_MAF)) { return measurement.getProperty(CALCULATED_MAF); } throw new FuelConsumptionException("No MAF value available"); } private double calculateLambdaVoltageER(double lambdaER, double lambdaV) throws FuelConsumptionException { /** * we will use the provided lambda ER if it is less than 1.97 (= the observed capped max) */ if (lambdaER <= 1.97) { return lambdaER; } /** * we calculate the lambda ER using the regression function */ double denominator = CO_EFFICIENT_X2 - CO_EFFICIENT_X3 * lambdaV; //check if we might get into divided by zero if (denominator == 0.0) { throw new FuelConsumptionException("Invalid lambda parameters would result in division by zero"); } return CO_EFFICIENT_X1 / denominator; } @Override public double calculateCO2FromConsumption(double consumption) throws FuelConsumptionException { return consumption * 2.65; //kg/h } }