三自由度车辆模型的扩展卡尔曼滤波(EKF)程序

使用扩展卡尔曼滤波(EKF)来估计三自由度车辆模型的状态。这个模型包括纵向速度、横向速度和横摆角速度。

%% 三自由度车辆模型的扩展卡尔曼滤波程序
clc; clear; close all;

%% 车辆参数设置
m = 1573;       % 车辆质量 (kg)
Iz = 2873;      % 绕Z轴的转动惯量 (kg*m^2)
lf = 1.1;       % 前轴到质心的距离 (m)
lr = 1.58;      % 后轴到质心的距离 (m)
Cf = 80000;     % 前轮侧偏刚度 (N/rad)
Cr = 80000;     % 后轮侧偏刚度 (N/rad)

%% 仿真参数
dt = 0.01;      % 时间步长 (s)
T = 10;         % 总仿真时间 (s)
N = T/dt;       % 总步数

%% 初始状态
% 状态向量: [纵向速度 vx, 横向速度 vy, 横摆角速度 r]
x_true = [20; 0; 0];    % 真实状态 (m/s, m/s, rad/s)
x_est = [19; 0.1; 0.1]; % 估计状态 (初始带有误差)
P = diag([1, 0.1, 0.01]); % 估计误差协方差矩阵

%% 过程噪声和测量噪声
Q = diag([0.1, 0.1, 0.01]); % 过程噪声协方差
R = diag([0.5, 0.5, 0.05]); % 测量噪声协方差

%% 输入控制 (前轮转角和驱动力矩)
% 正弦转向输入
delta = zeros(1, N);
for k = 1:N
    if k < N/2
        delta(k) = 0.1 * sin(2*pi*0.5*k*dt);
    else
        delta(k) = 0.05 * sin(2*pi*0.5*k*dt);
    end
end

% 简单的驱动力矩输入
Fx = 200 * ones(1, N); % 恒定的驱动力 (N)

%% 数据存储
x_true_history = zeros(3, N);
x_est_history = zeros(3, N);
measurements_history = zeros(3, N);
innovation_history = zeros(3, N);

%% 扩展卡尔曼滤波主循环
for k = 1:N
    % 获取当前控制输入
    u = [delta(k); Fx(k)];
    
    % 1. 真实系统动态 (用于生成测量值)
    x_true = vehicle_dynamics(x_true, u, m, Iz, lf, lr, Cf, Cr, dt);
    
    % 2. 生成带有噪声的测量值
    z = measure(x_true) + sqrt(R) * randn(3, 1);
    
    % 3. 预测步骤 (使用非线性模型)
    [x_pred, F] = predict(x_est, u, m, Iz, lf, lr, Cf, Cr, dt);
    P_pred = F * P * F' + Q;
    
    % 4. 更新步骤
    [z_pred, H] = measurement_model(x_pred);
    y = z - z_pred; % 创新向量
    
    S = H * P_pred * H' + R;
    K = P_pred * H' / S;
    
    x_est = x_pred + K * y;
    P = (eye(3) - K * H) * P_pred;
    
    % 存储数据
    x_true_history(:, k) = x_true;
    x_est_history(:, k) = x_est;
    measurements_history(:, k) = z;
    innovation_history(:, k) = y;
end

%% 绘制结果
t = 0:dt:T-dt;

% 状态估计结果
figure('Position', [100, 100, 1200, 800]);
subplot(3,1,1);
plot(t, x_true_history(1,:), 'LineWidth', 2); hold on;
plot(t, x_est_history(1,:), '--', 'LineWidth', 2);
plot(t, measurements_history(1,:), '.', 'MarkerSize', 8);
legend('真实值', '估计值', '测量值');
title('纵向速度 v_x (m/s)');
grid on;

subplot(3,1,2);
plot(t, x_true_history(2,:), 'LineWidth', 2); hold on;
plot(t, x_est_history(2,:), '--', 'LineWidth', 2);
plot(t, measurements_history(2,:), '.', 'MarkerSize', 8);
legend('真实值', '估计值', '测量值');
title('横向速度 v_y (m/s)');
grid on;

subplot(3,1,3);
plot(t, x_true_history(3,:), 'LineWidth', 2); hold on;
plot(t, x_est_history(3,:), '--', 'LineWidth', 2);
plot(t, measurements_history(3,:), '.', 'MarkerSize', 8);
legend('真实值', '估计值', '测量值');
title('横摆角速度 r (rad/s)');
grid on;

% 创新序列 (应表现为零均值白噪声)
figure('Position', [100, 100, 1000, 600]);
subplot(3,1,1);
plot(t, innovation_history(1,:));
title('纵向速度创新序列');
grid on;

subplot(3,1,2);
plot(t, innovation_history(2,:));
title('横向速度创新序列');
grid on;

subplot(3,1,3);
plot(t, innovation_history(3,:));
title('横摆角速度创新序列');
grid on;

% 估计误差
errors = x_est_history - x_true_history;
figure('Position', [100, 100, 1000, 600]);
subplot(3,1,1);
plot(t, errors(1,:));
title('纵向速度估计误差');
grid on;

subplot(3,1,2);
plot(t, errors(2,:));
title('横向速度估计误差');
grid on;

subplot(3,1,3);
plot(t, errors(3,:));
title('横摆角速度估计误差');
grid on;

% 计算并显示均方根误差(RMSE)
rmse_vx = sqrt(mean(errors(1,:).^2));
rmse_vy = sqrt(mean(errors(2,:).^2));
rmse_r = sqrt(mean(errors(3,:).^2));

fprintf('纵向速度估计RMSE: %.4f m/s\n', rmse_vx);
fprintf('横向速度估计RMSE: %.4f m/s\n', rmse_vy);
fprintf('横摆角速度估计RMSE: %.4f rad/s\n', rmse_r);

%% 车辆动力学模型函数
function x_next = vehicle_dynamics(x, u, m, Iz, lf, lr, Cf, Cr, dt)
    % 三自由度车辆模型动力学
    % 状态: x = [vx, vy, r]
    % 输入: u = [delta, Fx]
    
    vx = x(1);
    vy = x(2);
    r = x(3);
    
    delta = u(1);
    Fx = u(2);
    
    % 计算轮胎侧偏角
    alpha_f = atan2(vy + lf*r, vx) - delta;
    alpha_r = atan2(vy - lr*r, vx);
    
    % 计算轮胎侧向力
    Fyf = -Cf * alpha_f;
    Fyr = -Cr * alpha_r;
    
    % 动力学方程
    vx_dot = (Fx - Fyf*sin(delta))/m + vy*r;
    vy_dot = (Fyf*cos(delta) + Fyr)/m - vx*r;
    r_dot = (lf*Fyf*cos(delta) - lr*Fyr)/Iz;
    
    % 欧拉积分
    x_next = x + [vx_dot; vy_dot; r_dot] * dt;
end

%% 预测步骤函数
function [x_pred, F] = predict(x, u, m, Iz, lf, lr, Cf, Cr, dt)
    % 使用非线性模型进行状态预测
    % 并计算状态转移雅可比矩阵F
    
    vx = x(1);
    vy = x(2);
    r = x(3);
    
    delta = u(1);
    Fx = u(2);
    
    % 计算轮胎侧偏角
    alpha_f = atan2(vy + lf*r, vx) - delta;
    alpha_r = atan2(vy - lr*r, vx);
    
    % 计算轮胎侧向力
    Fyf = -Cf * alpha_f;
    Fyr = -Cr * alpha_r;
    
    % 动力学方程
    vx_dot = (Fx - Fyf*sin(delta))/m + vy*r;
    vy_dot = (Fyf*cos(delta) + Fyr)/m - vx*r;
    r_dot = (lf*Fyf*cos(delta) - lr*Fyr)/Iz;
    
    % 状态预测
    x_pred = x + [vx_dot; vy_dot; r_dot] * dt;
    
    % 计算状态转移雅可比矩阵F
    % 这里使用数值方法计算雅可比矩阵
    epsilon = 1e-6;
    F = zeros(3,3);
    
    for i = 1:3
        x_plus = x;
        x_plus(i) = x_plus(i) + epsilon;
        
        x_minus = x;
        x_minus(i) = x_minus(i) - epsilon;
        
        f_plus = vehicle_dynamics(x_plus, u, m, Iz, lf, lr, Cf, Cr, dt);
        f_minus = vehicle_dynamics(x_minus, u, m, Iz, lf, lr, Cf, Cr, dt);
        
        F(:, i) = (f_plus - f_minus) / (2 * epsilon);
    end
end

%% 测量模型函数
function z = measure(x)
    % 测量模型 - 假设我们可以直接测量所有状态
    % 在实际应用中,可能需要使用传感器模型
    z = x;
end

%% 测量模型雅可比矩阵函数
function [z_pred, H] = measurement_model(x)
    % 测量模型及其雅可比矩阵
    % 假设直接测量所有状态,所以H是单位矩阵
    z_pred = x;
    H = eye(3);
end

说明

这个程序实现了一个基于扩展卡尔曼滤波(EKF)的三自由度车辆状态估计器,主要包括以下部分:

1. 车辆模型

三自由度车辆模型包括:

  • 纵向速度 (vx)
  • 横向速度 (vy)
  • 横摆角速度 ®

模型考虑了:

  • 轮胎侧偏特性
  • 前轮转向角输入
  • 驱动力输入

2. 扩展卡尔曼滤波实现

EKF分为两个主要步骤:

预测步骤
  • 使用非线性车辆模型预测状态
  • 计算状态转移雅可比矩阵(使用数值方法)
更新步骤
  • 使用测量值更新状态估计
  • 计算卡尔曼增益
  • 更新估计误差协方差矩阵

3. 仿真设置

  • 使用正弦波作为转向输入
  • 添加过程噪声和测量噪声
  • 比较真实状态、估计状态和测量值

4. 结果分析

程序绘制了以下结果:

  • 状态估计与真实值的比较
  • 创新序列(应表现为零均值白噪声)
  • 估计误差
  • 计算并显示均方根误差(RMSE)

参考代码 应用于三自由度车辆模型的扩展卡尔曼滤波程序 www.3dddown.com/csa/54787.html

使用

  1. 运行程序即可看到仿真结果
  2. 可以调整车辆参数以适应不同的车辆类型
  3. 可以修改噪声参数以模拟不同的传感器性能
  4. 可以修改控制输入以模拟不同的驾驶场景
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值