基于模型预测控制(MPC)的最优竞赛(Matlab代码实现)

 💥💥💞💞欢迎来到本博客❤️❤️💥💥

🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。

⛳️座右铭:行百里者,半于九十。

📋📋📋本文目录如下:🎁🎁🎁

目录

💥1 概述

📚2 运行结果

🎉3 参考文献

🌈4 Matlab代码实现


💥1 概述

  • 基于模型预测控制(MPC)的最优竞赛是一种优化问题,旨在通过控制系统的动态模型来最小化某个性能指标。在竞赛中,这个性能指标通常是比赛时间或者比赛得分。MPC是一种基于模型的控制方法,它使用系统的动态模型来预测未来的状态,并根据预测结果来生成最优的控制策略。

    在最优竞赛中,MPC可以用来生成最优的控制策略,以最小化比赛时间或得分。MPC的基本思想是在每个时间步骤上,使用系统的动态模型来预测未来的状态,并根据预测结果来生成最优的控制策略。这个控制策略可以是连续的,也可以是离散的,具体取决于竞赛的要求。

    MPC的优点是可以考虑到系统的动态特性和约束条件,从而生成最优的控制策略。此外,MPC还可以处理非线性系统和多变量系统,因此在竞赛中具有广泛的应用前景。

    总之,基于模型预测控制(MPC)的最优竞赛是一种优化问题,旨在通过控制系统的动态模型来最小化某个性能指标。MPC可以用来生成最优的控制策略,以最小化比赛时间或得分。MPC的优点是可以考虑到系统的动态特性和约束条件,因此在竞赛中具有广泛的应用前景。

本代码利用模型预测控制,使汽车选择转向命令,使其在模拟赛道上以最佳方式比赛。

​操作流程:

首先,转到并运行,添加到 MATLAB 路径:/utilsprecompute_grid.m/utils

然后回到主文件夹,现在您可以选择运行三个解决方案中的任何一个:

  • 执行 MPC 的最简单解决方案,生成有效但次优轨迹:solution_1_simple_grid_search.m
  • 执行更复杂的解决方案,以更优化的方式解决 MPC,但速度非常慢:solution_2_recursive_search.m
  • 使用 fmincon 执行以进行持续优化,从而获得最佳结果:solution_3_fmincon.m

所需工具箱:

  • Matlab(2022b年开发,不确定向后兼容性),
  • Matlab 优化工具箱版本 9.4.,
  • 统计和机器学习工具箱版本 12.5。

📚2 运行结果

主函数部分代码:

% setup
clear; clc;
close all; drawnow;
​
% loading Kosinka Grid and making the variables global
load("precompute_grid.mat")
global x_min_here
; x_min_here = x_min; 
global
 y_min_here; y_min_here = y_min; 
global
 spacing_here; spacing_here = spacing; 
global
 x_size_here; x_size_here = x_size; 
global
 y_size_here; y_size_here = y_size;global distances_here; distances_here = distances; global progresses_here; progresses_here = progresses;
% real cone positions from the map
% innerConePosition = [6.49447171658257,41.7389113024907;8.49189149682204,41.8037451937836;10.4848751821667,4692264908853,-8.52739205631154;-32.9016624434539,-6.87420998418598;-34.1160057737752,-1.60803776182190;-34.3261608207142,0.237322459171913;-34.4624174228984,2.11880932640591;-34.5407037273032,4.03273612643633;-34.5779532171168,5.97700580252438;-34.5920061096721,7.95066706685753;-34.6203010935088,11.9628384547546;-34.6463516562825,13.9656473217268;-34.6751545298116,15.9616504117489;-34.7230350194217,19.9334733431980;-34.7332354577762,21.9093507078716;-34.7284338451120,23.8784778261844;-34.6466389854161,27.7320065787716547;4.31684977705784,47.6749328204622;8.29483356036796,47.8005083348189];% load outer cone x and y coordinates
% assume constant width of the track, calculate from the first cones
in_x = innerConePosition(:,1); in_y = innerConePosition(:,2);
out_x = outerConePosition(:,1); out_y = outerConePosition(:,2);
w = sqrt((in_x(1)-out_x(1))^2+(in_y(1)-out_y(1))^2);
% generating track
[test_path_x, test_path_y] = generate_track(innerConePosition, outerConePosition);
​
% constants hashmap, which is also made global
keySet = ["tau", "width", "steps", "horizons", "global_steps", "min_speed", "max_speed", "max_acceleration", "max_brake", "steer_change", "lateral_acceleration", "max_steer", "intervals"];
valueSet = [0.01   w        50         3         1500          1                100            12              12            pi/6               50                  pi/3           3];
global constant; constant = containers.Map(keySet, valueSet);
​
% best choices at given moment: turning angle, progress along the line, acceleration
best_omega = 0; best = 0; best_a = 0;
​
% storing the path we actually took by taking the first step
taken_x = zeros(constant("global_steps"), 1); taken_x(1) = (in_x(1)+out_x(1))/2;
taken_y = zeros(constant("global_steps"), 1); taken_y(1) = (in_y(1)+out_y(1))/2;
taken_omega = zeros(constant("global_steps"), 1); taken_omega(1) = 0; % best omega to take
taken_theta = zeros(constant("global_steps"), 1); taken_theta(1) = 0; % best theta
taken_velocity = zeros(constant("global_steps"), 1); taken_velocity(1) = 1; % setting start velocity
taken_acceleration = zeros(constant("global_steps"), 1); taken_acceleration(1) = 0.1;
taken_best = zeros(constant("global_steps"), 1); taken_best(1) = 0; % best progress along the line
​
% bool to plot or not
plot_meanwhile = 1;
% plot the track to watch the car on
if plot_meanwhile == 1
    figure; plot(test_path_x, test_path_y, 're', 'MarkerSize',5);
    hold on; plot(innerConePosition(:,1),innerConePosition(:,2),'ye','MarkerSize',5)
    hold on; plot(outerConePosition(:,1),outerConePosition(:,2),'bl','MarkerSize',5)
    hold on
end
​
% main loop
for a = 2:constant("global_steps")
    % update the current state
    current_velocity = taken_velocity(a-1); current_theta = taken_theta(a-1);
    current_x = taken_x(a-1); current_y = taken_y(a-1);
    current_omega = taken_omega(a-1); current_acceleration = taken_acceleration(a-1); current_best = taken_best(a-1);
​
    % watch the plot as it is generated
    if plot_meanwhile == 1
        scatter(current_x, current_y, 30, current_velocity+1, 'filled'); % path the model took: color = speed, size = change in angle
        hold on;
        pause(0.001)
    end
    % find the best move
    [best_a, best_omega, best_progress] = best_step_recursive(current_velocity, current_x, current_y, current_theta, constant("horizons"), current_acceleration, current_omega, current_best, constant("intervals"));
    % check if any move is possible
    if best_progress == -1
        upper "CRASHED"; break;
    end
    % let the model move
    [path_x, path_y, path_theta, velocities] = unicycle_model_acceleration_fixed(current_velocity, best_a, best_omega, current_x, current_y, current_theta, 2, constant("tau"), constant("max_speed"), constant("min_speed"));
    % save variables to keep track of the model
    taken_x(a)
 = path_x(
2
); taken_y(a) = path_y(
2
);    taken_omega(a) = best_omega; taken_acceleration(a) = best_a; taken_best(a) = best_progress;
    taken_theta(a) = path_theta(2); taken_velocity(a) = velocities(2);
end
​
% plotting all the curves at the end
figure; plot(test_path_x, test_path_y, 're', 'MarkerSize',5); % reference path to follow
hold on; plot(innerConePosition(:,1),innerConePosition(:,2),'ye','MarkerSize',5) % boundaries
hold on; plot(outerConePosition(:,1),outerConePosition(:,2),'bl','MarkerSize',5)
hold on; scatter(taken_x, taken_y, 30, taken_velocity+1, 'filled'); % path the model took: color = speed, size = change in angle
​
function [best_acceleration, best_omega, best_progress] = best_step_recursive(current_velocity, current_x, current_y, current_theta, horizons, last_acceleration, last_omega, last_progress, intervals)
    if horizons == 0 % recursion base case, return the last given variables
        best_acceleration = last_acceleration; best_omega = last_omega; best_progress = last_progress; return;
    end
    scored_scores = zeros(intervals, intervals); % keeping track of best scores
    global constant
    accelerations = linspace(-constant("max_brake"), constant("max_acceleration"), constant("intervals")); % generating accelerations
    for acceleration_index = 1:constant("intervals") % pick acceleration between limits and by braking and speeding up
        acceleration = accelerations(acceleration_index);
        max_velocity = max(current_velocity + acceleration*constant("tau")*constant("steps"), current_velocity); % maximum velocity on the next horizon
        omegas = linspace(max([-round(constant("lateral_acceleration")/max_velocity), -constant("max_steer"), last_omega - constant("steer_change")]), min([round(constant("lateral_acceleration")/max_velocity), last_omega + constant("steer_change"), constant("max_steer")]), constant("intervals")); % figure out viable angles
        for omega_index = 1:constant("intervals") % try angles
            omega = omegas(omega_index);
            % predict model movement 
            [path_x, path_y, path_theta, path_velocities] = unicycle_model_acceleration_fixed(current_velocity, acceleration, omega, current_x, current_y, current_theta, constant("steps"), constant("tau"), constant("max_speed"), constant("min_speed"));
            % check if path is valid by making x and y into indices on the grid
            global x_min_here; global y_min_here; global spacing_here; global x_size_here; global y_size_here;
            indices_x = floor((path_x-x_min_here)/x_size_here*spacing_here); indices_y = floor((path_y-y_min_here)/y_size_here*spacing_here);
            % take the maximum distance on the grid if all distances on the path are in the grid
            if max(indices_x) > spacing_here || min(indices_x) < 1 || max(indices_y) > spacing_here || min(indices_y) < 1
                continue
            end
            % find the maximum distance on the path
            global distances_here
; max_distance = max(distances_here(sub2ind([spacing_here, spacing_here],indices_x,indices_y)));            % if path within the lines, find the progress
            if max_distance < constant("width")/2
                global progresses_here; final_progress = progresses_here(indices_x(end), indices_y(end)); % find the maximum progress
                final_x = path_x(end); final_y = path_y(end);
                final_velocity = path_velocities(end); final_theta = path_theta(end);
                % make recursive call
                [~, ~, best_progress_now] = best_step_recursive(final_velocity, final_x, final_y, final_theta, horizons - 1, acceleration, omega, final_progress, intervals);
                scored_scores(acceleration_index, omega_index) = best_progress_now; % keep track of recursive progress
            end
        end
    end
    % if we did not get any valid action
    if scored_scores == zeros(intervals, intervals)
        best_acceleration = last_acceleration;
        best_omega = last_omega;
        best_progress = -1;
        return;
    end
    % pass back the maximal values from the recursive calls
    [max_progress, max_indices] = max(scored_scores(:));
    [max_x, max_y] = ind2sub(size(scored_scores), max_indices);
    best_acceleration = accelerations(max_x);
    best_omega = omegas(max_y);
    best_progress = max_progress;
end

🎉3 参考文献

[1]廖兴华. 基于MPC的FSAC赛车横向控制策略研究[D].西华大学,2020.​

部分理论引用网络文献,若有侵权联系博主删除。

🌈4 Matlab代码实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值