Beispiel #1
0
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
Beispiel #2
0
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)
Beispiel #3
0
    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)
Beispiel #4
0
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
Beispiel #5
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
Beispiel #6
0
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)
Beispiel #7
0
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)
Beispiel #8
0
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)