diff --git a/flow/energy_models/base_energy.py b/flow/energy_models/base_energy.py index bf1e16e09..a16c84694 100644 --- a/flow/energy_models/base_energy.py +++ b/flow/energy_models/base_energy.py @@ -12,9 +12,7 @@ class BaseEnergyModel(metaclass=ABCMeta): to be an averaged-size vehicle. """ - def __init__(self, kernel): - self.k = kernel - + def __init__(self): # 15 kilowatts = 1 gallon/hour conversion factor self.conversion = 15e3 diff --git a/flow/energy_models/power_demand.py b/flow/energy_models/power_demand.py index ddf09b2fc..d8c6bc9ec 100644 --- a/flow/energy_models/power_demand.py +++ b/flow/energy_models/power_demand.py @@ -16,14 +16,12 @@ class PowerDemandModel(BaseEnergyModel, metaclass=ABCMeta): """ def __init__(self, - kernel, mass=2041, area=3.2, rolling_res_coeff=0.0027, aerodynamic_drag_coeff=0.4, p1_correction=4598.7155, p3_correction=975.12719): - self.k = kernel self.g = 9.807 self.rho_air = 1.225 self.gamma = 1 @@ -31,8 +29,7 @@ def __init__(self, self.cross_area = area self.rolling_res_coeff = rolling_res_coeff self.aerodynamic_drag_coeff = aerodynamic_drag_coeff - self.p1_correction = p1_correction - self.p3_correction = p3_correction + self.power_correction_coeffs = np.array([p1_correction, p3_correction]) def calculate_power_at_the_wheels(self, accel, speed, grade): """Calculate the instantaneous power required. @@ -91,7 +88,8 @@ def get_power_correction_factor(self, accel, speed, grade): ------- float """ - return self.p1_correction * accel + self.p3_correction * accel * speed + state_variables = np.array([accel, accel * speed]) + return max(0, np.dot(self.power_correction_coeffs, state_variables)) def get_instantaneous_power(self, accel, speed, grade): """See parent class. @@ -100,27 +98,68 @@ def get_instantaneous_power(self, accel, speed, grade): """ regen_cap = self.get_regen_cap(accel, speed, grade) power_at_the_wheels = max(regen_cap, self.calculate_power_at_the_wheels(accel, speed, grade)) - correction_factor = max(regen_cap, self.get_power_correction_factor(accel, speed, grade)) + correction_factor = self.get_power_correction_factor(accel, speed, grade) return power_at_the_wheels + correction_factor class PDMCombustionEngine(PowerDemandModel): """Power Demand Model for a combustion engine vehicle.""" + def __init__(self, + idle_coeff=3405.5481762, + linear_friction_coeff=83.123929917, + quadratic_friction_coeff=6.7650718327, + drag_coeff=0.7041355229, + p1_correction=4598.7155, + p3_correction=975.12719): + super(PDMCombustionEngine, self).__init__() + self.fuel_consumption_power_coeffs = np.array([idle_coeff, + linear_friction_coeff, + quadratic_friction_coeff, + drag_coeff]) + def get_regen_cap(self, accel, speed, grade): """See parent class.""" return 0 + def calculate_fuel_consumption_power(self, accel, speed, grade): + """Calculate the instantaneous power from a fitted function to Toyota Tacoma fuel consumption. + + Parameters + ---------- + accel : float + Instantaneous acceleration of the vehicle + speed : float + Instantaneous speed of the vehicle + grade : float + Instantaneous road grade of the vehicle + Returns + ------- + float + """ + state_variables = np.array([1, speed, speed**2, speed**3]) + power_0 = np.dot(self.fuel_consumption_power_coeffs, state_variables) + return max(self.mass * accel * speed + power_0, 0) + + def get_instantaneous_power(self, accel, speed, grade): + """See parent class.""" + fuel_consumption_power = self.calculate_fuel_consumption_power(accel, speed, grade) + power_correction_factor = self.get_power_correction_factor(accel, speed, grade) + return fuel_consumption_power + power_correction_factor + class PDMElectric(PowerDemandModel): """Power Demand Model for an electric vehicle.""" - def __init__(self, kernel): - super(PDMElectric, self).__init__(kernel, - mass=1663, - area=2.4, - rolling_res_coeff=0.007, - aerodynamic_drag_coeff=0.24) + def __init__(self, + mass=1663, + area=2.4, + rolling_res_coeff=0.007, + aerodynamic_drag_coeff=0.24): + super(PDMElectric, self).__init__(mass=mass, + area=area, + rolling_res_coeff=rolling_res_coeff, + aerodynamic_drag_coeff=aerodynamic_drag_coeff) def get_regen_cap(self, accel, speed, grade): """See parent class.""" diff --git a/flow/energy_models/toyota_energy.py b/flow/energy_models/toyota_energy.py index d24b41662..64036aab6 100644 --- a/flow/energy_models/toyota_energy.py +++ b/flow/energy_models/toyota_energy.py @@ -9,9 +9,7 @@ class ToyotaModel(BaseEnergyModel, metaclass=ABCMeta): """Base Toyota Energy model class.""" - def __init__(self, kernel, filename=None): - self.k = kernel - + def __init__(self, filename): # download file from s3 bucket s3 = boto3.client('s3') s3.download_file('toyota.restricted', filename, 'temp.pkl') @@ -30,14 +28,15 @@ def get_instantaneous_power(self, accel, speed, grade): class PriusEnergy(ToyotaModel): """Toyota Prius (EV) energy model class.""" - def __init__(self, kernel, soc=0.9): - super(PriusEnergy, self).__init__(kernel, filename='prius_ev.pkl') + def __init__(self, sim_step, soc=0.9): + super(PriusEnergy, self).__init__(filename='prius_ev.pkl') + self.sim_step = sim_step self.soc = soc def get_instantaneous_power(self, accel, speed, grade): """See parent class.""" socdot = self.toyota_energy(self.soc, accel, speed, grade) - self.soc -= socdot * self.k.env.sim_step + self.soc -= socdot * self.sim_step # FIXME (Joy): convert socdot to power return socdot @@ -45,8 +44,8 @@ def get_instantaneous_power(self, accel, speed, grade): class TacomaEnergy(ToyotaModel): """Toyota Tacoma energy model class.""" - def __init__(self, kernel): - super(TacomaEnergy, self).__init__(kernel, filename='tacoma.pkl') + def __init__(self): + super(TacomaEnergy, self).__init__(filename='tacoma.pkl') def get_instantaneous_power(self, accel, speed, grade): """See parent class."""