ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
23 октября
1549591 Топик полностью
Cкpипaчпророк (Сегодня, 11:17, просмотров: 68) ответил Cкpипaч на Очень интересно. Т.е. "одномерный Калман" это БИХ-фильтр с правильным k? А где-же распиаренная фишка прeдсказания скорости движения?
Ответ от AI. 
import numpy as np
import matplotlib.pyplot as plt

class KalmanFilterPressureWithAccel:
    def __init__(self, initial_pressure=0.0, initial_velocity=0.0, initial_acceleration=0.0, dt=1.0, 
                 process_noise_std=0.1, measurement_noise_std=1.0):
        """
        Фильтр Калмана для показаний датчика давления с учетом ускорения.
        
        Эта модель описывает давление как состояние с позицией (давление), скоростью (скорость изменения давления)
        и ускорением (скорость изменения скорости). Учитывает внешние воздействия, позволяя шуму процесса
        влиять на ускорение (модель с белым шумом рывка).
        
        Параметры:
        - initial_pressure: Начальная оценка давления.
        - initial_velocity: Начальная оценка скорости изменения давления.
        - initial_acceleration: Начальная оценка ускорения (вторая производная).
        - dt: Шаг времени между измерениями.
        - process_noise_std: Стандартное отклонение шума процесса (влияет на рывок, изменение ускорения).
        - measurement_noise_std: Стандартное отклонение шума измерений.
        """
        # Вектор состояния: [давление, скорость, ускорение]^T
        self.x = np.array([[initial_pressure], [initial_velocity], [initial_acceleration]])
        
        # Начальная ковариационная матрица (неопределенность)
        self.P = np.eye(3) * 10.0  # Начальная неопределенность
        
        # Матрица перехода состояний (модель постоянного ускорения)
        self.F = np.array([[1, dt, 0.5 * dt**2],
                           [0, 1, dt],
                           [0, 0, 1]])
        
        # Матрица измерений (измеряется только давление)
        self.H = np.array([[1, 0, 0]])
        
        # Ковариационная матрица шума процесса (модель белого шума рывка)
        q = process_noise_std ** 2
        self.Q = q * np.array([[dt**5 / 20, dt**4 / 8, dt**3 / 6],
                               [dt**4 / 8,  dt**3 / 3, dt**2 / 2],
                               [dt**3 / 6,  dt**2 / 2, dt]])
        
        # Ковариационная матрица шума измерений
        self.R = np.array([[measurement_noise_std ** 2]])
    
    def predict(self):
        """Предсказать следующее состояние на основе модели."""
        self.x = self.F @ self.x
        self.P = self.F @ self.P @ self.F.T + self.Q
    
    def update(self, measurement):
        """Обновить состояние на основе нового измерения."""
        z = np.array([[measurement]])
        y = z - self.H @ self.x  # Инновация
        S = self.H @ self.P @ self.H.T + self.R  # Ковариация инновации
        K = self.P @ self.H.T @ np.linalg.inv(S)  # Коэффициент усиления Калмана
        self.x = self.x + K @ y
        I = np.eye(3)
        self.P = (I - K @ self.H) @ self.P
    
    def get_pressure(self):
        """Получить текущее оцененное давление."""
        return self.x[0, 0]

# Пример использования с визуализацией
if __name__ == "__main__":
    # Симуляция измерений давления с шумом и изменениями
    np.random.seed(42)  # Для воспроизводимости
    time_steps = np.arange(0, 10, 1)
    true_pressures = [100, 102, 105, 107, 110, 108, 105, 103, 100, 98]  # Изменения из-за внешних факторов
    measurements = [p + np.random.normal(0, 1) for p in true_pressures]  # Шумные измерения
    
    # Инициализация фильтра Калмана
    kf = KalmanFilterPressureWithAccel(initial_pressure=100.0, dt=1.0, process_noise_std=0.5, measurement_noise_std=1.0)
    
    # Запуск фильтра
    filtered = []
    for z in measurements:
        kf.predict()
        kf.update(z)
        filtered.append(kf.get_pressure())
    
    # Вывод результатов
    print("Измерения:", measurements)
    print("Отфильтрованные давления:", filtered)
    
    # Визуализация
    plt.figure(figsize=(10, 6))
    plt.plot(time_steps, true_pressures, 'b-', label='Истинное давление', linewidth=2)
    plt.plot(time_steps, measurements, 'ro', label='Измеренное давление', markersize=5)
    plt.plot(time_steps, filtered, 'g--', label='Отфильтрованное давление', linewidth=2)
    plt.xlabel('Время (с)')
    plt.ylabel('Давление')
    plt.title('Фильтр Калмана для показаний датчика давления')
    plt.legend()
    plt.grid(True)
    plt.show()

... но не любой ценой.