import numpy as np
from filterpy.kalman import KalmanFilter
from scipy.signal import savgol_filter
import matplotlib.pyplot as plt
# 加载数据
data = np.loadtxt('D:\新建文件夹\data.txt', delimiter='\t')
# 初始化Kalman滤波器
kf = KalmanFilter(dim_x=2, dim_z=2)
kf.F = np.array([[1., 1.], [0., 1.]])
kf.H = np.array([[1., 0.], [0., 1.]])
kf.Q = np.diag([0.1, 0.1])
kf.R = np.diag([10., 10.])
kf.x = np.array([data[0, 0], 0.])
kf.P = np.diag([10., 10.])
# 对数据进行滤波
filtered_data = []
for i in range(data.shape[0]):
kf.predict()
kf.update(data[i, :2])
filtered_state = np.concatenate([kf.x, kf.P.diagonal()])
filtered_data.append(np.concatenate([filtered_state, data[i, 2:]]))
filtered_data = np.array(filtered_data)
# 保存滤波后的数据到文件
np.savetxt('filtered_data.txt', filtered_data, delimiter='\t')
# 绘制图表
fig, axs = plt.subplots(3, 1, figsize=(10, 10))
for i in range(3):
axs[i].plot(data[:, i], label='Raw Data')
axs[i].plot(np.array(filtered_data)[:, i], label='Filtered Data')
axs[i].legend()
axs[i].set_xlabel('Time')
axs[i].set_ylabel('Acceleration (g)')
axs[i].set_title(f'Acceleration in {["X", "Y", "Z"][i]} ')
plt.show()
我是想做三轴加速度的卡尔曼滤波,用chatgpt写的滤波器,然后我的z轴过滤出来的结果很奇怪,想问问这方面有了解的人是什么问题,还有就是我的滤波器能否还可以再改善
首先,根据提供的代码和数据,我发现卡尔曼滤波器的初始化有些问题,应该将dim_x
设置为3,而不是2。因为我们要过滤的是三轴加速度,所以状态向量应该有三个分量。同时,根据系统模型,状态转移矩阵F
应该改为:
kf.F = np.array([[1., dt, 0.5*dt*dt], [0., 1., dt], [0., 0., 1.]])
其中,dt
是两个采样点之间的时间间隔,可以从数据中计算得到。这个矩阵表示当前时刻的状态向量与上一个时刻的状态向量之间的转移关系。
其次,在更新状态向量之前,应该先将加速度数据进行单位转换,从m/s^2转换为g。这可以通过乘以一个常数来完成。
最后,我发现在绘制图表时,y轴的标签应该是Acceleration (m/s^2),而不是Acceleration (g)。另外,z轴的结果可能会有一些误差,因为z轴的加速度通常会受到重力的影响,需要进行一些特殊处理。
下面是修改后的代码示例:
import numpy as np
from filterpy.kalman import KalmanFilter
from scipy.signal import savgol_filter
import matplotlib.pyplot as plt
# 加载数据
data = np.loadtxt('data.txt', delimiter='\t')
# 初始化Kalman滤波器
kf = KalmanFilter(dim_x=3, dim_z=3)
kf.F = np.array([[1., dt, 0.5*dt*dt], [0., 1., dt], [0., 0., 1.]])
kf.H = np.array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
kf.Q = np.diag([0.1, 0.1, 0.1])
kf.R = np.diag([10., 10., 10.])
kf.x = np.array([data[0, 0], 0., 0.])
kf.P = np.diag([10., 10., 10.])
# 对数据进行滤波
filtered_data = []
for i in range(data.shape[0]):
kf.predict()
kf.update(data[i, :3] * 9.81) # 将加速度转换为m/s^2
filtered_state = np.concatenate([kf.x, kf.P.diagonal()])
filtered_data.append(np.concatenate([filtered_state, data[i, 3:]]))
filtered_data = np.array(filtered_data)
# 保存滤波后的数据到文件
np.savetxt('filtered_data.txt', filtered_data, delimiter='\t')
# 绘制图表
fig, axs = plt.subplots(3, 1, figsize=(10, 10))
for i in range(3):
axs[i].plot(data[:, i], label='Raw Data')
axs[i].plot(np.array(filtered_data)[:, i], label='Filtered Data')
axs[i].legend()
axs[i].set_xlabel('Time')
axs[i].set_ylabel('Acceleration (m/s^2)')
axs[i].set_title(f'Acceleration in {["X", "Y", "Z"][i]}')
plt.show()
提供参考实例:https://blog.csdn.net/qq_50597556/article/details/128478744
【评论区有完整代码,供参考】
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先,你的代码中使用了 KalmanFilter 类来实现卡尔曼滤波。但是,该类默认使用的是一维(一维状态向量、一维观测向量)的卡尔曼滤波。如果要求解三轴加速度,应该将状态向量和观测向量都改成三维的。具体来说,应该将 dim_x 和 dim_z 变量分别设置为 3。修改后的初始化代码如下:
kf = KalmanFilter(dim_x=3, dim_z=3)
kf.F = np.array([[1., 1., 0.5], [0., 1., 1.], [0., 0., 1.]])
kf.H = np.array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
kf.Q = np.diag([0.1, 0.1, 0.1])
kf.R = np.diag([10., 10., 10.])
kf.x = np.array([data[0, 0], data[0, 1], data[0, 2]])
kf.P = np.diag([10., 10., 10.])
另外,卡尔曼滤波的参数取值对滤波效果也有很大影响。可以根据具体信号的特点来对参数进行调整。一种常用的方法是通过试错法(trial and error)进行调整。
最后,建议在卡尔曼滤波的基础上再加上其他滤波算法(如中值滤波、均值滤波等),以求得更好的效果。修改后的代码如下:
import numpy as np
from filterpy.kalman import KalmanFilter
from scipy.signal import savgol_filter, medfilt
import matplotlib.pyplot as plt
# 加载数据
data = np.loadtxt('D:\新建文件夹\data.txt', delimiter='\t')
# 初始化Kalman滤波器
kf = KalmanFilter(dim_x=3, dim_z=3)
kf.F = np.array([[1., 1., 0.5], [0., 1., 1.], [0., 0., 1.]])
kf.H = np.array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
kf.Q = np.diag([0.1, 0.1, 0.1])
kf.R = np.diag([10., 10., 10.])
kf.x = np.array([data[0, 0], data[0, 1], data[0, 2]])
kf.P = np.diag([10., 10., 10.])
# 对数据进行滤波
filtered_data = []
for i in range(data.shape[0]):
kf.predict()
kf.update(data[i, :3])
filtered_state = np.concatenate([kf.x, kf.P.diagonal()])
filtered_data.append(np.concatenate([filtered_state, data[i, 3:]]))
filtered_data = np.array(filtered_data)
# 中值滤波
filtered_data[:, :3] = medfilt(filtered_data[:, :3], kernel_size=5)
# 绘制图表
fig, axs = plt.subplots(3, 1, figsize=(10, 10))
for i in range(3):
axs[i].plot(data[:, i], label='Raw Data')
axs[i].plot(np.array(filtered_data)[:, i], label='Filtered Data')
axs[i].legend()
axs[i].set_xlabel('Time')
axs[i].set_ylabel('Acceleration (g)')
axs[i].set_title(f'Acceleration in {["X", "Y", "Z"][i]} ')
plt.show()
如果我的回答解决了您的问题,请采纳!
不知道你这个问题是否已经解决, 如果还没有解决的话:引用chatGPT作答,根据您提供的代码,我发现您使用了一个简单的Kalman滤波器来滤波三轴加速度数据。您提到其中的Z轴结果很奇怪,可能存在两个问题:
1.数据预处理
在滤波器之前,您需要先对原始数据进行预处理,以确保数据符合Kalman滤波器的要求。对于加速度数据,需要进行坐标系的旋转和零偏校准。您需要确保Z轴的测量方向与滤波器中的Z轴一致,同时要校准零偏(即在静止状态下,加速度为0)。
2.滤波器参数
滤波器的参数对滤波效果有很大的影响,需要根据具体的应用场景进行调整。您可以尝试调整卡尔曼滤波器的参数,例如调整协方差矩阵Q和R的值,以获得更好的滤波效果。另外,如果发现Z轴的滤波效果很差,可以考虑将Z轴的参数与其他轴分开处理,以获得更好的滤波效果。
最后,建议您检查一下输入数据的正确性和滤波器的实现是否正确。希望这些建议能够帮助您解决问题!