Esempio n. 1
0
def _filter_temperature_samples(spl, on_engine, thermostat):
    adt = np.abs(spl[:, -1])
    b = ~((adt <= 0.001) & on_engine[1:])
    b[:co2_utl.argmax(on_engine)] = False
    i = co2_utl.argmax(thermostat < spl[:, 0])
    b[i:] = True
    b[:i] &= adt[:i] < dfl.functions._filter_temperature_samples.max_abs_dt_cold
    return spl[b]
Esempio n. 2
0
def _filter_temperature_samples(X, Y, on_engine, thermostat):
    adt = np.abs(Y)
    b = ~((adt <= 0.001) & on_engine[1:])
    b[:co2_utl.argmax(on_engine)] = False
    i = co2_utl.argmax(thermostat < X[:, 0])
    b[i:] = True
    # noinspection PyProtectedMember
    b[:
      i] &= adt[:i] < dfl.functions._filter_temperature_samples.max_abs_dt_cold
    return X[b], Y[b]
Esempio n. 3
0
def check_initial_temperature(initial_temperature, engine_coolant_temperatures,
                              engine_speeds_out, idle_engine_speed_median):
    """
    Checks if initial temperature is valid according NEDC and WLTP regulations.

    :param initial_temperature:
        Engine initial temperature [°C]
    :type initial_temperature: float

    :param engine_coolant_temperatures:
        Engine coolant temperature vector [°C].
    :type engine_coolant_temperatures: numpy.array

    :param engine_speeds_out:
        Engine speed vector [RPM].
    :type engine_speeds_out: numpy.array

    :param idle_engine_speed_median:
        Engine speed idle median [RPM].
    :type idle_engine_speed_median: float

    :return:
        True if data pass the checks.
    :rtype: bool
    """

    idle = idle_engine_speed_median - con_vals.DELTA_RPM2VALIDATE_TEMP
    b = engine_speeds_out > idle
    i = co2_utl.argmax(b) + 1
    t = np.mean(engine_coolant_temperatures[:i])
    dT = abs(initial_temperature - t)
    return dT <= con_vals.MAX_VALIDATE_DTEMP and t <= con_vals.MAX_INITIAL_TEMP
Esempio n. 4
0
    def fit(self,
            currents,
            on_engine,
            times,
            soc,
            statuses,
            *args,
            init_time=0.0):
        b = (statuses[1:] > 0) & on_engine[1:]
        i = co2_utl.argmax(times >= times[0] + init_time)
        from ....engine._thermal import _build_samples
        X, Y = _build_samples(currents, soc, statuses, *args)
        if b[i:].any():
            self.model, self.mask = self._fit_model(X[i:][b[i:]], Y[i:][b[i:]])
        elif b[:i].any():
            self.model, self.mask = self._fit_model(X[b], Y[b])
        else:
            self.model = lambda *args, **kwargs: [0.0]
            self.mask = np.array((0, ))
        self.mask += 1

        if b[:i].any():
            init_spl = (times[1:i + 1] - times[0])[:, None], X[:i]
            init_spl = np.concatenate(init_spl, axis=1)[b[:i]]
            a = self._fit_model(init_spl, Y[:i][b[:i]], (0, ), (2, ))
            self.init_model, self.init_mask = a
        else:
            self.init_model, self.init_mask = self.model, self.mask

        return self
Esempio n. 5
0
def identify_cold_start_speeds_phases(engine_coolant_temperatures,
                                      engine_thermostat_temperature, on_idle):
    """
    Identifies phases when engine speed is affected by the cold start [-].

    :param engine_coolant_temperatures:
        Engine coolant temperature vector [°C].
    :type engine_coolant_temperatures: numpy.array

    :param engine_thermostat_temperature:
        Engine thermostat temperature [°C].
    :type engine_thermostat_temperature: float

    :param on_idle:
        If the engine is on idle [-].
    :type on_idle: numpy.array

    :return:
        Phases when engine speed is affected by the cold start [-].
    :rtype: numpy.array
    """
    temp = engine_coolant_temperatures
    i = co2_utl.argmax(temp > engine_thermostat_temperature)
    p = on_idle.copy()
    p[i:] = False
    return p
Esempio n. 6
0
    def fit(self,
            currents,
            on_engine,
            times,
            soc,
            statuses,
            *args,
            init_time=0.0):
        b = (statuses[1:] > 0) & on_engine[1:]
        i = co2_utl.argmax(times > times[0] + init_time)
        spl = _build_samples(currents, soc, statuses, *args)
        if b[i:].any():
            self.model, self.mask = self._fit_model(spl[i:][b[i:]])
        elif b[:i].any():
            self.model, self.mask = self._fit_model(spl[b])
        else:
            self.model, self.mask = lambda *args, **kwargs: [0.0], np.array(
                (0, ))
        self.mask += 1

        if b[:i].any():
            init_spl = (np.array([times[1:i + 1] - times[0]]).T, spl[:i])
            init_spl = np.concatenate(init_spl, axis=1)[b[:i]]
            self.init_model, self.init_mask = self._fit_model(
                init_spl, (0, ), (2, ))
        else:
            self.init_model, self.init_mask = self.model, self.mask

        return self
Esempio n. 7
0
def identify_cold_start_speeds_phases(engine_coolant_temperatures,
                                      engine_thermostat_temperature, on_idle):

    temp = engine_coolant_temperatures
    i = co2_utl.argmax(temp > engine_thermostat_temperature)
    p = on_idle.copy()
    p[i:] = False
    return p
Esempio n. 8
0
    def fit(self, is_hybrid, times, charging_statuses, state_of_charges,
            motive_powers):

        i = co2_utl.argmax(charging_statuses != 3)

        status, soc = charging_statuses[i:], state_of_charges[i:]

        self._fit_bers(status, motive_powers[i:])
        self._fit_charge(status, soc, times[i:], is_hybrid)

        return self
Esempio n. 9
0
    def fit(self, times, alternator_statuses, state_of_charges,
            gear_box_powers_in):

        i = co2_utl.argmax(alternator_statuses != 3)

        status, soc = alternator_statuses[i:], state_of_charges[i:]

        self._fit_bers(status, gear_box_powers_in[i:])
        self._fit_charge(status, soc)
        self._fit_boundaries(status, soc, times[i:])

        return self
Esempio n. 10
0
    def fit(self, idle_engine_speed, on_engine, temperature_derivatives,
            temperatures, *args):
        """
        Calibrates an engine temperature regression model to predict engine
        temperatures.

        This model returns the delta temperature function of temperature
        (previous), acceleration, and power at the wheel.

        :param idle_engine_speed:
            Engine speed idle median and std [RPM].
        :type idle_engine_speed: (float, float)

        :param on_engine:
            If the engine is on [-].
        :type on_engine: numpy.array

        :param temperature_derivatives:
            Derivative temperature vector [°C].
        :type temperature_derivatives: numpy.array

        :param temperatures:
            Temperature vector [°C].
        :type temperatures: numpy.array

        :return:
            The calibrated engine temperature regression model.
        :rtype: ThermalModel
        """
        spl = _build_samples(temperature_derivatives, temperatures, *args)
        self.thermostat = self._identify_thermostat(spl, idle_engine_speed)

        spl = _filter_temperature_samples(spl, on_engine, self.thermostat)
        opt = {
            ## FIXME: Normally RANSAC sets this from its own `random_state`,
            #  but strangely, without this `seed`, it fails with:
            #       Failed DISPATCHING 'engine_model/thermal/calibrate_engine_temperature_regression_model' due to: # noqa
            #       XGBoostError(b"Invalid Parameter format for seed expect int but value='<mtrand.RandomState",)   # noqa
            'seed': 0,
            'max_depth': 2,
            'n_estimators': int(min(300.0, 0.25 * (len(spl) - 1)))
        }

        model = _SafeRANSACRegressor(
            base_estimator=self.base_model(**opt),
            random_state=0,
            min_samples=0.85,
            max_trials=10
        )

        model = sk_pip.Pipeline([
            ('feature_selection', _SelectFromModel(model, '0.8*median',
                                                   in_mask=(0, 2))),
            ('classification', model)
        ])
        model.fit(spl[:, :-1], spl[:, -1])

        self.model = model.steps[-1][-1]
        self.mask = np.where(model.steps[0][-1]._get_support_mask())[0]

        self.min_temp = spl[:, 0].min()
        spl = spl[:co2_utl.argmax(self.thermostat <= spl[:, 0])]

        if not spl.any():
            self.min_temp = -float('inf')
            return self
        spl = spl[:co2_utl.argmax(np.percentile(spl[:, 0], 60) <= spl[:, 0])]
        opt = {
            'random_state': 0,
            'max_depth': 2,
            'n_estimators': int(min(300.0, 0.25 * (len(spl) - 1)))
        }
        model = self.base_model(**opt)
        model = sk_pip.Pipeline([
            ('feature_selection', _SelectFromModel(model, '0.8*median',
                                                   in_mask=(1,))),
            ('classification', model)
        ])
        model.fit(spl[:, 1:-1], spl[:, -1])
        self.cold = model.steps[-1][-1]
        self.mask_cold = np.where(model.steps[0][-1]._get_support_mask())[0] + 1

        return self
Esempio n. 11
0
def _filter_samples(spl, on_engine, thermostat):
    b = ~((np.abs(spl[:, -1]) <= 0.001) & on_engine[1:])
    b[:co2_utl.argmax(on_engine)] = False
    b[co2_utl.argmax(thermostat < spl[:, 0]):] = True
    return spl[b]
Esempio n. 12
0
    def fit(self, idle_engine_speed, on_engine, temperature_derivatives,
            temperatures, *args):
        """
        Calibrates an engine temperature regression model to predict engine
        temperatures.

        This model returns the delta temperature function of temperature
        (previous), acceleration, and power at the wheel.

        :param idle_engine_speed:
            Engine speed idle median and std [RPM].
        :type idle_engine_speed: (float, float)

        :param on_engine:
            If the engine is on [-].
        :type on_engine: numpy.array

        :param temperature_derivatives:
            Derivative temperature vector [°C].
        :type temperature_derivatives: numpy.array

        :param temperatures:
            Temperature vector [°C].
        :type temperatures: numpy.array

        :return:
            The calibrated engine temperature regression model.
        :rtype: ThermalModel
        """

        spl = _build_samples(temperature_derivatives, temperatures, *args)
        self.thermostat = self._identify_thermostat(spl, idle_engine_speed)

        spl = _filter_samples(spl, on_engine, self.thermostat)
        opt = {
            'random_state': 0,
            'max_depth': 2,
            'n_estimators': int(min(300, 0.25 * (len(spl) - 1))),
            'loss': 'huber',
            'alpha': 0.99
        }
        model = co2_utl._SafeRANSACRegressor(
            base_estimator=self.base_model(**opt),
            random_state=0,
            min_samples=0.85,
            max_trials=10)

        model = sk_pip.Pipeline([('feature_selection',
                                  _SelectFromModel(model,
                                                   '0.8*median',
                                                   in_mask=(0, 2))),
                                 ('classification', model)])
        model.fit(spl[:, :-1], spl[:, -1])

        self.model = model.steps[-1][-1]
        self.mask = np.where(model.steps[0][-1]._get_support_mask())[0]

        self.min_temp = spl[:, 0].min()
        spl = spl[:co2_utl.argmax(self.thermostat <= spl[:, 0])]

        if not spl.any():
            self.min_temp = -float('inf')
            return self
        spl = spl[:co2_utl.argmax(np.percentile(spl[:, 0], 60) <= spl[:, 0])]
        opt = {
            'random_state': 0,
            'max_depth': 2,
            'n_estimators': int(min(300, 0.25 * (len(spl) - 1))),
            'loss': 'huber',
            'alpha': 0.99
        }
        model = self.base_model(**opt)
        model = sk_pip.Pipeline([('feature_selection',
                                  _SelectFromModel(model,
                                                   '0.8*median',
                                                   in_mask=(1, ))),
                                 ('classification', model)])
        model.fit(spl[:, 1:-1], spl[:, -1])
        self.cold = model.steps[-1][-1]
        self.mask_cold = np.where(
            model.steps[0][-1]._get_support_mask())[0] + 1

        return self
Esempio n. 13
0
def identify_after_treatment_warm_up_phases(
        times, engine_speeds_out, engine_speeds_out_hot, on_idle, on_engine,
        idle_engine_speed, velocities, engine_starts, stop_velocity,
        is_hybrid=False):
    """
    Identifies when engine speed is affected by the after treatment warm up [-].

    :param times:
        Time vector [s].
    :type times: numpy.array

    :param engine_speeds_out:
        Engine speed [RPM].
    :type engine_speeds_out: numpy.array

    :param engine_speeds_out_hot:
        Engine speed at hot condition [RPM].
    :type engine_speeds_out_hot: numpy.array

    :param on_idle:
        If the engine is on idle [-].
    :type on_idle: numpy.array

    :param on_engine:
        If the engine is on [-].
    :type on_engine: numpy.array

    :param idle_engine_speed:
        Engine speed idle median and std [RPM].
    :type idle_engine_speed: (float, float)

    :param velocities:
        Velocity vector [km/h].
    :type velocities: numpy.array

    :param engine_starts:
        When the engine starts [-].
    :type engine_starts: numpy.array

    :param stop_velocity:
        Maximum velocity to consider the vehicle stopped [km/h].
    :type stop_velocity: float

    :param is_hybrid:
        Is the vehicle hybrid?
    :type is_hybrid: bool

    :return:
        Phases when engine speed is affected by the after treatment warm up [-].
    :rtype: numpy.array
    """
    from .control import identify_engine_starts
    i, phases = np.where(on_idle)[0], np.zeros_like(times, int)
    start = engine_starts.copy()
    if is_hybrid:
        with np.errstate(divide='ignore', invalid='ignore'):
            r = engine_speeds_out[i] / engine_speeds_out_hot[i]
            b = ~co2_utl.get_inliers(r, 2, np.nanmedian, co2_utl.mad)[0]
        phases[i[b]] = 1
    else:
        ds = np.abs(engine_speeds_out[i] - engine_speeds_out_hot[i])
        phases[i[ds > idle_engine_speed[1]]] = 1
        start |= identify_engine_starts(velocities > stop_velocity)
    for i, j in np.searchsorted(times, times[start, None] + [-2, 5 + dfl.EPS]):
        phases[i:j], start[i:j] = 0, True
    phases = co2_utl.median_filter(times, phases, 4)
    phases = co2_utl.clear_fluctuations(times, phases, 4).astype(bool)
    indices = co2_utl.index_phases(phases)
    if is_hybrid:
        indices = indices[(np.diff(times[indices], axis=1) > 10).ravel()][:1]
    else:
        b, f = identify_engine_starts(~on_engine), False
        for i, j in np.searchsorted(times, times[b, None] + [-5, 2 + dfl.EPS]):
            b[i:j] = f
            f = True
        b = (on_idle & ~start) | b | (times > np.min(times[on_engine]) + 200)
        indices = indices[:co2_utl.argmax(b[indices[:, 1]])]
    phases[:], n = False, len(times)
    for i, j in indices:
        while i and on_idle.take(i - 1, mode='clip'):
            i -= 1
        phases[i:j + 1] = True
    return phases
Esempio n. 14
0
def _set_alt_init_status(times, initialization_time, statuses):
    if initialization_time > 0:
        statuses[:co2_utl.argmax(times > (times[0] + initialization_time))] = 3
    return statuses
Esempio n. 15
0
def identify_alternator_initialization_time(alternator_currents,
                                            gear_box_powers_in, on_engine,
                                            accelerations, state_of_charges,
                                            alternator_statuses, times,
                                            alternator_current_threshold):
    """
    Identifies the alternator initialization time delta [s].

    :param alternator_currents:
        Alternator current vector [A].
    :type alternator_currents: numpy.array

    :param gear_box_powers_in:
        Gear box power vector [kW].
    :type gear_box_powers_in: numpy.array

    :param on_engine:
        If the engine is on [-].
    :type on_engine: numpy.array

    :param accelerations:
        Vehicle acceleration [m/s2].
    :type accelerations: numpy.array

    :param state_of_charges:
        State of charge of the battery [%].

        .. note::

            `state_of_charges` = 99 is equivalent to 99%.
    :type state_of_charges: numpy.array

    :param alternator_statuses:
        The alternator status (0: off, 1: on, due to state of charge, 2: on due
        to BERS) [-].
    :type alternator_statuses: numpy.array

    :param times:
        Time vector [s].
    :type times: numpy.array

    :param alternator_current_threshold:
        Alternator current threshold [A].
    :type alternator_current_threshold: float

    :return:
        Alternator initialization time delta [s].
    :rtype: float
    """

    if alternator_statuses[0] == 1:
        s = alternator_currents < alternator_current_threshold
        n, i = len(on_engine), co2_utl.argmax((s[:-1] != s[1:]) & s[:-1])
        i = min(n - 1, i)
        opt = {
            'random_state': 0,
            'max_depth': 2,
            'loss': 'huber',
            'alpha': 0.99
        }

        spl = _build_samples(alternator_currents, state_of_charges,
                             alternator_statuses, gear_box_powers_in,
                             accelerations)

        j = min(i, int(n / 2))
        opt['n_estimators'] = int(min(100, 0.25 * (n - j))) or 1
        model = GradientBoostingRegressor(**opt)
        model.fit(spl[j:][:, :-1], spl[j:][:, -1])
        err = np.abs(spl[:, -1] - model.predict(spl[:, :-1]))
        sets = np.array(co2_utl.get_inliers(err)[0], dtype=int)[:i]
        if sum(sets) / i < 0.5 or i > j:
            reg = DecisionTreeClassifier(max_depth=1, random_state=0)
            reg.fit(np.array((times[1:i + 1], )).T, sets)
            l, r = reg.tree_.children_left[0], reg.tree_.children_right[0]
            l, r = np.argmax(reg.tree_.value[l]), np.argmax(reg.tree_.value[r])
            if l == 0 and r == 1:
                return reg.tree_.threshold[0] - times[0]
            elif r == 0 and not i > j:
                return times[i] - times[0]

    elif alternator_statuses[0] == 3:
        i = co2_utl.argmax(alternator_statuses != 3)
        return times[i] - times[0]
    return 0.0
Esempio n. 16
0
def identify_service_battery_initialization_time(
        alternator_electric_powers, motive_powers, accelerations,
        service_battery_state_of_charges, service_battery_charging_statuses,
        times, service_battery_electric_powers_supply_threshold):
    """
    Identifies the alternator initialization time delta [s].

    :param alternator_electric_powers:
        Alternator electric power [kW].
    :type alternator_electric_powers: numpy.array

    :param motive_powers:
        Motive power [kW].
    :type motive_powers: numpy.array

    :param accelerations:
        Vehicle acceleration [m/s2].
    :type accelerations: numpy.array

    :param service_battery_state_of_charges:
        State of charge of the service battery [%].
    :type service_battery_state_of_charges: numpy.array

    :param service_battery_charging_statuses:
        Service battery charging statuses (0: Discharge, 1: Charging, 2: BERS,
        3: Initialization) [-].
    :type service_battery_charging_statuses: numpy.array

    :param times:
        Time vector [s].
    :type times: numpy.array

    :param service_battery_electric_powers_supply_threshold:
        Service battery not charging power threshold [kW].
    :type service_battery_electric_powers_supply_threshold: float

    :return:
        Service battery initialization time delta [s].
    :rtype: float
    """
    bats, p = service_battery_charging_statuses, motive_powers
    i = co2_utl.argmax(bats != 0)
    if bats[0] == 1 or (i and ((bats[:i] == 0) & (p[:i] == 0)).all()):
        s = service_battery_electric_powers_supply_threshold
        s = alternator_electric_powers < s
        n, i = len(times), int(co2_utl.argmax((s[:-1] != s[1:]) & s[:-1]))
        i = min(n - 1, i)

        # noinspection PyProtectedMember
        from ....engine._thermal import _build_samples, _XGBRegressor

        x, y = _build_samples(alternator_electric_powers,
                              service_battery_state_of_charges, bats, p,
                              accelerations)

        j = min(i, int(n / 2))
        # noinspection PyArgumentEqualDefault
        model = _XGBRegressor(random_state=0,
                              max_depth=2,
                              n_estimators=int(min(100.0, 0.25 * (n - j)))
                              or 1,
                              objective='reg:squarederror').fit(x[j:], y[j:])
        err = np.abs(y - model.predict(x))
        sets = np.array(co2_utl.get_inliers(err)[0], dtype=int)[:i]
        if (i and sum(sets) / i < 0.5) or i > j:
            from sklearn.tree import DecisionTreeClassifier
            reg = DecisionTreeClassifier(max_depth=1, random_state=0)
            reg.fit(times[1:i + 1, None], sets)
            s, r = reg.tree_.children_left[0], reg.tree_.children_right[0]
            s, r = np.argmax(reg.tree_.value[s]), np.argmax(reg.tree_.value[r])
            if s == 0 and r == 1:
                return reg.tree_.threshold[0] - times[0]
            elif r == 0 and not i > j:
                return times[i] - times[0]

    elif bats[0] == 3:
        i = co2_utl.argmax(bats != 3)
        return times[i] - times[0]
    return 0.0