Вернуться на страницу brain2net:
https://brain2net.ru/post/model-prostogo-osczillyatora/#more-67
import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt
Простейшая функция, описывающая один шаг решения уравнения осциллятора методом Эйлера
def step(x, dt, gamma = 0., omega0 = 1., f = 0.):
x[1] = - omega0**2 * x[0] * dt+ (1 - 2 * gamma * dt) * x[1] + f
x[0] = x[0] + x[1] * dt
return x
Решение уравнения простого осциллятора со слабым затуханием
x = np.array([[1.],[0.]])
dt = 0.005
position = [x[0,0]]
velosity = [x[1,0]]
time = [0]
gamma = 0.05
omega0 = 1.
for i in range(10000):
result = step(x, dt, gamma = gamma, omega0 = omega0)
position += [result[0,0]]
velosity += [result[1,0]]
time += [dt * i]
plt.figure(figsize=(18,8))
plt.plot(time, position)
plt.grid()
На осциллятор каждые dtau действует случайное возмудение с мат. ожиданием 0 и f_std
x = np.array([[1.],[0.]])
dt = 0.005
dtau = 0.004
f_std = 10.
position = [x[0,0]]
velosity = [x[1,0]]
time = [0]
tau = 0.
gamma = 0.05
omega0 = 1.
for i in range(10000):
if tau < dtau:
f = 0.
tau += dt
else:
tau = 0.
f = random.gauss(0,f_std)
result = step(x, dt, gamma = gamma, omega0 = omega0, f=f)
position += [result[0,0]]
velosity += [result[1,0]]
time += [dt * i]
plt.figure(figsize=(18,8))
plt.plot(time, position)
plt.grid()
Размер матриц
x [k,1]
F [k,k]
Q [k,k]
P [k,k]
y [m,1]
H [m,k]
R [m,m]
gamma = 0.05
omega0 = 1.
# Вводится слоучайное отличие к константы модели
omega_st = 0.2
gamma_st = 0.01
omega0_ = random.gauss(omega0,omega_st)
omega0_ = random.gauss(gamma,gamma_st)
F = np.array([[1., dt],[- omega0_**2* dt,(1 - 2 * gamma * dt) ]])
Q = np.array([[1., 0.],[0., 1.]])
H = np.array([[1., 0.]])
R = np.array([[1.0]])
gamma = 0.05
omega0 = 1.
x = np.array([[1.],[0.]])
x_ = np.array([[1.],[0.]])
P = np.array([[999.,0.],[999.,0.]])
dt = 0.005
dtau = 0.004
f_std = 10.
position = [x[0,0]]
velosity = [x[1,0]]
position_ = [x_[0,0]]
velosity_ = [x_[1,0]]
predict_position = [x_[0,0]]
predict_velosity = [x_[1,0]]
time = [0]
tau = 0.
for i in range(10000):
if tau < dtau:
f = 0.
tau += dt
else:
tau = 0.
f = random.gauss(0,f_std)
x = step(x, dt, gamma = gamma, omega0 = omega0, f=f)
position += [x[0,0]]
velosity += [x[1,0]]
# Этап экстраполяции
x_ = np.dot(F,x_)
predict_position += [x_[0,0]]
predict_velosity += [x_[1,0]]
P = np.dot(np.dot(F,P),F.transpose()) + Q
# Этап коррекции
# Размер матрицы [m,1]
z = [[x[0,0]]]
# Размер матрицы [m,k][k,1]
y = z - np.dot(H,x_)
# Размер матрицы [m,k][k,k][k,m]
S = np.dot(np.dot(H,P),H.transpose()) + R
K = np.dot(np.dot(P,H.transpose()),np.linalg.inv(S))
x_ = x_ + np.dot(K,y)
aaa = (np.eye(len(P)) - np.dot(K,H))
P = np.dot(aaa,P)
position_ += [x_[0,0]]
velosity_ += [x_[1,0]]
time += [dt * i]
На графике ниже показана зависимость реального отклонения осциллятора - зеленые кружки, которые слились в полосу.
Отклонение осциллятора, оцененное фильтром Калмана - желтая линия в середине зеленой полосы.
Отклонение осциллятора, оцененное фильтром Калмана на этапе экстраполяции - малиновый пунктир, расположенный практически на желтой линии.
plt.figure(figsize=(18,8))
plt.plot(time, position,'go')
plt.plot(time, position_, 'y')
plt.plot(time, predict_position,'m--')
plt.grid()
На графике ниже показана разность между реальным отклонением осциллятора и оценкой фильтром Калмана - зеленый пунктир.
Красные точки - разность между реальным отклонением осциллятора и оценкой фильтром Калмана на этапе экстраполяции
plt.figure(figsize=(18,8))
plt.plot(time, np.array(position) - np.array(predict_position),'r.')
plt.plot(time, np.array(position) - np.array(position_),'g--')
plt.grid()
На графике ниже показана зависимость реальной скорости осциллятора - зеленые кружки, которые слились в полосу.
Скорость осциллятора, оцененное фильтром Калмана - желтые кружки, которые слились в полосу.
Скорость осциллятора, оцененное фильтром Калмана на этапе экстраполяции - малиновый пунктир, расположенный практически на желтой полосе.
NB Замер скорости осциллятора не подавался в фильтр Калмана
plt.figure(figsize=(18,8))
plt.plot(time, velosity,'go')
plt.plot(time, velosity_,'yo')
plt.plot(time, predict_velosity,'m--')
plt.grid()
На графике ниже показана разность между реальной скоростью осциллятора и оценкой фильтром Калмана - зеленый пунктир.
Красные точки - разность между реальной скоростью осциллятора и оценкой фильтром Калмана на этапе экстраполяции
plt.figure(figsize=(18,8))
plt.plot(time, np.array(velosity) - np.array(predict_velosity),'r.')
plt.plot(time, np.array(velosity) - np.array(velosity_),'g--')
plt.grid()
Вернуться на страницу brain2net:
https://brain2net.ru/post/model-prostogo-osczillyatora/#more-67