def calibrate_after_treatment_power_model( times, after_treatment_warm_up_phases, engine_powers_out, is_hybrid=False): """ Calibrates the engine after treatment speed model. :param times: Time vector [s]. :type times: numpy.array :param after_treatment_warm_up_phases: Phases when engine speed is affected by the after treatment warm up [-]. :type after_treatment_warm_up_phases: numpy.array :param engine_powers_out: Engine power vector [kW]. :type engine_powers_out: numpy.array :param is_hybrid: Is the vehicle hybrid? :type is_hybrid: bool :return: After treatment speed model. :rtype: function """ if after_treatment_warm_up_phases.any(): from sklearn.isotonic import IsotonicRegression x, y = [], [] for i, j in co2_utl.index_phases(after_treatment_warm_up_phases): t = times[i:j + 1] - (times[i] if is_hybrid else 0.0) x.extend(t) y.extend(co2_utl.median_filter(t, engine_powers_out[i:j + 1], 4)) # noinspection PyUnresolvedReferences return IsotonicRegression().fit(x, np.maximum(0, y)).predict
def calculate_velocities(times, obd_velocities): """ Filters the obd velocities [km/h]. :param times: Time vector [s]. :type times: numpy.array :param obd_velocities: OBD velocity vector [km/h]. :type obd_velocities: numpy.array :return: Velocity vector [km/h]. :rtype: numpy.array """ from co2mpas.utils import median_filter dt_window = dfl.functions.calculate_velocities.dt_window return median_filter(times, obd_velocities, dt_window, np.mean)
def gear_filter(times, gears): """ Filter the gears to remove oscillations. :param times: Time vector [s]. :type times: numpy.array :param gears: Gear vector [-]. :type gears: numpy.array :return: Filtered gears [-]. :rtype: numpy.array """ gears = median_filter(times, gears.astype(float), change_gear_window_width) gears = clear_fluctuations(times, gears, change_gear_window_width) return np.asarray(gears, dtype=int)
def identify_gears(times, velocities, accelerations, engine_speeds_out, velocity_speed_ratios, stop_velocity, plateau_acceleration, change_gear_window_width, idle_engine_speed): """ Identifies gear time series [-]. :param times: Time vector [s]. :type times: numpy.array :param velocities: Velocity vector [km/h]. :type velocities: numpy.array :param accelerations: Acceleration vector [m/s2]. :type accelerations: numpy.array :param engine_speeds_out: Engine speed [RPM]. :type engine_speeds_out: numpy.array :param velocity_speed_ratios: Constant velocity speed ratios of the gear box [km/(h*RPM)]. :type velocity_speed_ratios: dict :param stop_velocity: Maximum velocity to consider the vehicle stopped [km/h]. :type stop_velocity: float :param plateau_acceleration: Maximum acceleration to be at constant velocity [m/s2]. :type plateau_acceleration: float :param change_gear_window_width: Time window used to apply gear change filters [s]. :type change_gear_window_width: float :param idle_engine_speed: Engine speed idle median and std [RPM]. :type idle_engine_speed: (float, float) :return: Gear vector identified [-]. :rtype: numpy.array """ vsr = [v for v in velocity_speed_ratios.items() if v[0] != 0] ratios = velocities / engine_speeds_out idle_speed = (idle_engine_speed[0] - idle_engine_speed[1], idle_engine_speed[0] + idle_engine_speed[1]) ratios[engine_speeds_out < idle_speed[0]] = 0 id_gear = partial(_identify_gear, idle_speed, vsr, stop_velocity, plateau_acceleration) gear = list(map(id_gear, *(ratios, velocities, accelerations))) gear = co2_utl.median_filter(times, gear, change_gear_window_width) gear = _correct_gear_shifts(times, ratios, gear, velocity_speed_ratios) gear = co2_utl.clear_fluctuations(times, gear, change_gear_window_width) return gear
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
def identify_on_idle( times, velocities, engine_speeds_out_hot, gear_box_speeds_in, gears, stop_velocity, min_engine_on_speed, on_engine, idle_engine_speed): """ Identifies when the engine is on idle [-]. :param times: Time vector [s]. :type times: numpy.array :param velocities: Velocity vector [km/h]. :type velocities: numpy.array :param engine_speeds_out_hot: Engine speed at hot condition [RPM]. :type engine_speeds_out_hot: numpy.array :param gear_box_speeds_in: Gear box speed [RPM]. :type gear_box_speeds_in: numpy.array :param gears: Gear vector [-]. :type gears: numpy.array :param stop_velocity: Maximum velocity to consider the vehicle stopped [km/h]. :type stop_velocity: float :param min_engine_on_speed: Minimum engine speed to consider the engine to be on [RPM]. :type min_engine_on_speed: float :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) :return: If the engine is on idle [-]. :rtype: numpy.array """ # noinspection PyProtectedMember from .gear_box.mechanical import _shift b = engine_speeds_out_hot > min_engine_on_speed b &= (gears == 0) | (velocities <= stop_velocity) on_idle = np.zeros_like(times, int) i = np.where(on_engine)[0] ds = np.abs(gear_box_speeds_in[i] - engine_speeds_out_hot[i]) on_idle[i[ds > idle_engine_speed[1]]] = 1 on_idle = co2_utl.median_filter(times, on_idle, 4) on_idle[b] = 1 for i, j in sh.pairwise(_shift(on_idle)): if not on_idle[i] and times[j - 1] - times[i] <= 2: on_idle[i:j] = 1 return co2_utl.clear_fluctuations(times, on_idle, 4).astype(bool)
def identify_gears( times, velocities, accelerations, gear_box_speeds_in, velocity_speed_ratios, stop_velocity, plateau_acceleration, change_gear_window_width, idle_engine_speed=(0, 0)): """ Identifies gear time series [-]. :param times: Time vector [s]. :type times: numpy.array :param velocities: Velocity vector [km/h]. :type velocities: numpy.array :param accelerations: Acceleration vector [m/s2]. :type accelerations: numpy.array :param gear_box_speeds_in: Gear box speed [RPM]. :type gear_box_speeds_in: numpy.array :param velocity_speed_ratios: Constant velocity speed ratios of the gear box [km/(h*RPM)]. :type velocity_speed_ratios: dict[int | float] :param stop_velocity: Maximum velocity to consider the vehicle stopped [km/h]. :type stop_velocity: float :param plateau_acceleration: Maximum acceleration to be at constant velocity [m/s2]. :type plateau_acceleration: float :param change_gear_window_width: Time window used to apply gear change filters [s]. :type change_gear_window_width: float :param idle_engine_speed: Engine speed idle median and std [RPM]. :type idle_engine_speed: (float, float) :return: Gear vector identified [-]. :rtype: numpy.array """ with np.errstate(divide='ignore', invalid='ignore'): r = velocities / gear_box_speeds_in idle = (idle_engine_speed[0] - idle_engine_speed[1], idle_engine_speed[0] + idle_engine_speed[1]) r[gear_box_speeds_in <= idle[0]] = 0 vsr = velocity_speed_ratios g, vsr = np.array([(k, v) for k, v in sorted(vsr.items()) if k != 0]).T dr = np.abs(vsr[:, None] - r) i, j = np.argmin(dr, 0), np.arange(times.shape[0]) b = velocities <= vsr[i] * idle[0] if idle[1]: b |= np.abs(velocities / idle[1] - r) < dr[i, j] b = (velocities <= stop_velocity) | (b & (accelerations < 0)) gear = np.where(b, 0, g[i]) b = (velocities > stop_velocity) & (accelerations > 0) b |= accelerations > plateau_acceleration gear[(gear == 0) & b] = 1 gear = co2_utl.median_filter(times, gear, change_gear_window_width) gear = _correct_gear_shifts(times, r, gear, velocity_speed_ratios) gear = co2_utl.clear_fluctuations(times, gear, change_gear_window_width) return gear.astype(int)
def identify_gears_v1( times, velocities, accelerations, motive_powers, on_engine, engine_speeds_out, velocity_speed_ratios, stop_velocity, plateau_acceleration, change_gear_window_width, idle_engine_speed, correct_gear): """ Identifies gear time series [-]. :param times: Time vector [s]. :type times: numpy.array :param velocities: Velocity vector [km/h]. :type velocities: numpy.array :param accelerations: Acceleration vector [m/s2]. :type accelerations: numpy.array :param motive_powers: Motive power [kW]. :type motive_powers: numpy.array :param on_engine: If the engine is on [-]. :type on_engine: numpy.array :param engine_speeds_out: Engine speed [RPM]. :type engine_speeds_out: numpy.array :param velocity_speed_ratios: Constant velocity speed ratios of the gear box [km/(h*RPM)]. :type velocity_speed_ratios: dict[int | float] :param stop_velocity: Maximum velocity to consider the vehicle stopped [km/h]. :type stop_velocity: float :param plateau_acceleration: Maximum acceleration to be at constant velocity [m/s2]. :type plateau_acceleration: float :param change_gear_window_width: Time window used to apply gear change filters [s]. :type change_gear_window_width: float :param idle_engine_speed: Engine speed idle median and std [RPM]. :type idle_engine_speed: (float, float) :param correct_gear: A function to correct the gear predicted. :type correct_gear: callable :return: Gear vector identified [-]. :rtype: numpy.array """ n = [k for k in velocity_speed_ratios if k != 0] if len(n) == 1: gears = np.ones_like(times, int) * n[0] gears[velocities <= stop_velocity] = 0 return gears with np.errstate(divide='ignore', invalid='ignore'): r = velocities / engine_speeds_out idle = (idle_engine_speed[0] - idle_engine_speed[1], idle_engine_speed[0] + idle_engine_speed[1]) r[engine_speeds_out <= idle[0]] = 0 _vsr = sh.combine_dicts(velocity_speed_ratios, base={0: 0}) g, vsr = np.array([(k, v) for k, v in sorted(_vsr.items())]).T dr = np.abs(vsr[:, None] - r) i, j = np.argmin(dr, 0), np.arange(times.shape[0]) b = velocities <= vsr[i] * idle[0] if idle[1]: b |= np.abs(velocities / idle[1] - r) < dr[i, j] b = (velocities <= stop_velocity) | (b & (accelerations < 0)) gears = np.where(b, 0, g[i]).astype(int) gears = co2_utl.median_filter(times, gears, change_gear_window_width) gears = _correct_gear_shifts(times, r, gears, velocity_speed_ratios) gears = co2_utl.clear_fluctuations(times, gears, change_gear_window_width) anomalies = velocities > stop_velocity anomalies &= (accelerations > 0) | ~on_engine anomalies |= accelerations > plateau_acceleration anomalies &= gears == 0 from ..control.conventional import calculate_engine_speeds_out_hot ds = calculate_engine_speeds_out_hot(calculate_gear_box_speeds_in( gears, velocities, velocity_speed_ratios, stop_velocity ), on_engine, idle_engine_speed) - engine_speeds_out i = np.where(on_engine & ~anomalies)[0] med = np.nanmedian(ds[i]) std = 3 * max(50, co2_utl.mad(ds[i], med=med)) anomalies[i] |= np.abs(ds[i] - med) >= std b = (gears == 0) & (velocities <= stop_velocity) anomalies[b] = False anomalies = co2_utl.clear_fluctuations( times, anomalies.astype(int), change_gear_window_width ) for i, j in sh.pairwise(_shift(gears)): anomalies[i:j] = anomalies[i:j].mean() > .3 gsm = _calibrate_gsm( velocity_speed_ratios, on_engine, anomalies, gears, velocities, stop_velocity, idle_engine_speed ).init_gear( gears, times, velocities, accelerations, motive_powers, correct_gear=correct_gear ) for i, v in enumerate(anomalies): if v: gears[i] = gsm(i) gears = co2_utl.median_filter(times, gears, change_gear_window_width) gears = co2_utl.clear_fluctuations(times, gears, change_gear_window_width) return gears.astype(int)