MPC模型预测控制

article/2025/11/9 13:26:01

这篇主要讲一下模型预测控制,如果对PID控制了解的同学,那效果更好。如果不了解PID控制,还是熟悉下比较好。

模型预测控制,顾名思义,基于模型,预测未来,进行控制。这个控制是基于模型的,也就是model-based。

有人会问,我这个系统的模型怎么来呢?我想到两点解决方法:

1. 文献上去找别人已经建好的,公认的模型;

2. 首先进行系统辨识,再进行建模。(难度太大,不建议)

下面给上经典的MPC控制流程图:

模型预测控制是一种基于模型的闭环优化控制策略。

预测控制算法的三要素:内部(预测)模型、参考轨迹、控制算法。现在一般则更清楚地表述为内部(预测)模型、滚动优化、反馈控制。 
大量的预测控制权威性文献都无一例外地指出, 预测控制最大的吸引力在于它具有显式处理约束的能力, 这种能力来自其基于模型对系统未来动态行为的预测, 通过把约束加到未来的输入、输出或状态变量上, 可以把约束显式表示在一个在线求解的二次规划或非线性规划问题中. 
模型预测控制具有控制效果好、鲁棒性强等优点,可有效地克服过程的不确定性、非线性和并联性,并能方便的处理过程被控变量和操纵变量中的各种约束。[1]

在线性模型预测控制(Linear Model Predictive Control, LMPC)的基础上,发展了非线性模型预测控制(Non-linear Model Predictive Control, NMPC),显示模型预测控制(Explicit Model Predictive Control, EMPC)和 鲁棒模型预测控制(Robust Model Predictive Control)

首先,我们定义一个模型来描述我们的车辆。[2]

这是自行车模型,运动学上面经常使用。

(x, y)是车辆的质心,ψ是当前车身的角度,v是当前车辆的速度,lf是当前车辆质心到原点的距离, β是速度和车身的角度。在我们的例子中,我们假设β为零,也就是没有侧滑。

在我们的模型中,我们可以通过控制前轮的转角δf 以及车辆的加速度a来控制车辆轨迹。简单起见,我们只考虑前轮驱动的车辆,并且将δf记作δ。

  模型预测控制的细节

每个控制周期,我们都从传感器读取数据并得到车辆状态量:

  • 车辆的位置(x,y)

  • 速度v

  • 车身角度 ψ

  • 转向角(舵角) δ

  • 加速度a

轨迹模型:

我们的道路检测系统应该能够为我们规划好路线,比如,以接下来6个航点的坐标的形式。在我们的例子中,我们使用6个航点去逼近一个3阶多项式函数。我们用这个模型去计算y坐标和相对于x轴的车身角度ψ。

使用模型预测控制和PID实现自动驾驶的车道保持

轨迹模型一般有规划模块给出,在这里就不做深入的研究。

动态模型:

接下来,我们要创建动态模型利用t时刻的状态去预测在t+1拍时刻的车辆状态。利用动力学模型,我们可以轻易地从最新时刻地采样推导出下一时刻的位置,车身角度和速度。

使用模型预测控制和PID实现自动驾驶的车道保持

我们可以在添加另外2个状态去衡量轨迹跟踪误差和车身角度误差ψ:

使用模型预测控制和PID实现自动驾驶的车道保持

损失函数:

在模型预测控制中,我们需要定义损失函数来优化路径。如果模型不能保持目标速度,那么我们就要惩罚模型。如果可能的话,我们并不想要突然的加减速或者突然的转向。但是既然这些实际上是不可避免的,我们可以尽可能地抑制加减速和转向地变化率。这减轻了晕车同时更加省油(也省人民币)。模型的损失函数应当包含

  • 跟踪误差

  • 转向误差

  • 速度损失函数项(尽量保持在100英里每小时)

  • 转向损失函数项(尽量避免转向)

  • 加速度损失函数项(尽量保持0加速度)

  • 转向变化率(越小越好)

  • 加速度变化率(越小越好)

因为这些目标也许会相互冲突,我们需要给这些损失项定义权重以体现优先级。损失函数如下:

使用模型预测控制和PID实现自动驾驶的车道保持

总而言之:

我们需要用模型预测控制来寻找最优路径,那么就需要动力学模型来预测下一拍的状态,以下是动力学模型和系统约束:

使用模型预测控制和PID实现自动驾驶的车道保持

这是下面GitHub链接里,别人给的权重。

    const int cte_cost_weight = 2000;const int epsi_cost_weight = 2000;const int v_cost_weight = 1;const int delta_cost_weight = 10;const int a_cost_weight = 10;const int delta_change_cost_weight = 100;const int a_change_cost_weight = 10;

 

优化模型预测控制

我们通过解决一个约束条件下优化损失函数的问题来解决了控制问题。这些约束条件包括油门和转向的控制。

  1. 从道路中检测下6个航点,并且计算3次插值的来建立行驶轨迹

  2. 从传感器读取当前速度v,  方向ψ,  转向角 δ 以及加速度  a

  3. 使用传感器读取的数据和动力学模型计算出第一个车辆状态

  4. 根据1秒内的车辆状态响应优化控制动作,控制的周期为100ms,所以1s内有10个周期

  5. 模型预测控制的两个变量(也是控制量):加速度(油门对应正加速度,刹车对应负加速度)和转向角

  6. 给出加速度和转向角的约束范围

  7. 我们将动态模型计算9次,得到未来9个时间拍的系统状态

  8. 给出每个采样计算周期的损失函数

  9. 用1个优化器解算出在约束定义下周期1到周期9的最小总损失(注意,在我们的定义中,时间周期并不从0开始,而是从1开始到10)

  10. 我们仅仅选择周期1给出的控制量

  11. 但是,我们延时100ms后再将控制量给模拟器。这样能够模拟现实世界,毕竟处理计算(读取传感器)和执行都需要时间。

  12. 从步骤1开始重复,寻找下一个最优控制量。

 

可调性:

在我们的例子中,我们计算了1秒中内的最优解,这个参数是可以调节的。长时间窗口的优化会给控制器的动作漂亮的曲线,但是也会积累过多的误差。实际上,如果这个优化时间窗口太大,汽车反而会脱离期望轨迹。

上面的文章内容都来自于链接[2]中,但是很多人对MPC还是有点不明白。模型也建立好了,约束我也会给,那怎么求解呢?求的解怎么利用呢?

现在我们看第一个问题:

1. 如何求解

上面的文章其实来自于Udacity的自动驾驶的一个课程。

大家可以去GitHub上下载下来,自己跑一下上面的代码。链接是这个https://github.com/mvirgo/MPC-Project,里面是一位博主写好的代码。大家配置好环境后可以直接跑起来的,然后有个可视化软件,可以看到3D引擎看到动画。

比如像这样的:https://github.com/mvirgo/MPC-Project/blob/master/MPC_vid.mov。

这个代码尽量在Ubuntu上去跑,因为装的东西比较多,给的教程关于LInux的。教程还是看Udacity给的模板比较好,但是代码不要下这个网址的,当时我环境配置好了之后还是有报错,我还以为是我环境配置的有问题。https://github.com/udacity/CarND-MPC-Project

这个代码是C++写的。

主函数中的调用

 /** Calculate steering angle and throttle using MPC.* Both are in between [-1, 1].* Simulator has 100ms latency, so will predict state at that point in time.* This will help the car react to where it is actually at by the point of actuation.*/// Fits a 3rd-order polynomial to the above x and y coordinatesauto coeffs = polyfit(ptsx_car, ptsy_car, 3);// Calculates the cross track error// Because points were transformed to vehicle coordinates, x & y equal 0 below.// 'y' would otherwise be subtracted from the polyeval valuedouble cte = polyeval(coeffs, 0);// Calculate the orientation error// Derivative of the polyfit goes in atan() below// Because x = 0 in the vehicle coordinates, the higher orders are zero// Leaves only coeffs[1]double epsi = -atan(coeffs[1]);// Center of gravity needed related to psi and epsiconst double Lf = 2.67;// Latency for predicting time at actuationconst double dt = 0.1;// Predict state after latency// x, y and psi are all zero after transformation abovedouble pred_px = 0.0 + v * dt; // Since psi is zero, cos(0) = 1, can leave outconst double pred_py = 0.0; // Since sin(0) = 0, y stays as 0 (y + v * 0 * dt)double pred_psi = 0.0 + v * -delta / Lf * dt;double pred_v = v + a * dt;double pred_cte = cte + v * sin(epsi) * dt;double pred_epsi = epsi + v * -delta / Lf * dt;// Feed in the predicted state valuesEigen::VectorXd state(6);state << pred_px, pred_py, pred_psi, pred_v, pred_cte, pred_epsi;// Solve for new actuations (and to show predicted x and y in the future)auto vars = mpc.Solve(state, coeffs);// Calculate steering and throttle// Steering must be divided by deg2rad(25) to normalize within [-1, 1].// Multiplying by Lf takes into account vehicle's turning abilitydouble steer_value = vars[0] / (deg2rad(25) * Lf);double throttle_value = vars[1];

MPC函数的实现

// MPC class definition implementation.
//
MPC::MPC() {}
MPC::~MPC() {}vector<double> MPC::Solve(Eigen::VectorXd state, Eigen::VectorXd coeffs) {bool ok = true;typedef CPPAD_TESTVECTOR(double) Dvector;// State vector holds all current values neede for vars belowdouble x = state[0];double y = state[1];double psi = state[2];double v = state[3];double cte = state[4];double epsi = state[5];// Setting the number of model variables (includes both states and inputs).// N * state vector size + (N - 1) * 2 actuators (For steering & acceleration)size_t n_vars = N * 6 + (N - 1) * 2;// Setting the number of constraintssize_t n_constraints = N * 6;// Initial value of the independent variables.// SHOULD BE 0 besides initial state.Dvector vars(n_vars);for (int i = 0; i < n_vars; i++) {vars[i] = 0.0;}Dvector vars_lowerbound(n_vars);Dvector vars_upperbound(n_vars);// Sets lower and upper limits for variables.// Set all non-actuators upper and lowerlimits// to the max negative and positive values.for (int i = 0; i < delta_start; i++) {vars_lowerbound[i] = -1.0e19;vars_upperbound[i] = 1.0e19;}// The upper and lower limits of delta are set to -25 and 25// degrees (values in radians).for (int i = delta_start; i < a_start; i++) {vars_lowerbound[i] = -0.436332;vars_upperbound[i] = 0.436332;}// Acceleration/decceleration upper and lower limits.for (int i = a_start; i < n_vars; i++) {vars_lowerbound[i] = -1.0;vars_upperbound[i] = 1.0;}// Lower and upper limits for the constraints// Should be 0 besides initial state.Dvector constraints_lowerbound(n_constraints);Dvector constraints_upperbound(n_constraints);for (int i = 0; i < n_constraints; i++) {constraints_lowerbound[i] = 0;constraints_upperbound[i] = 0;}// Start lower and upper limits at current valuesconstraints_lowerbound[x_start] = x;constraints_lowerbound[y_start] = y;constraints_lowerbound[psi_start] = psi;constraints_lowerbound[v_start] = v;constraints_lowerbound[cte_start] = cte;constraints_lowerbound[epsi_start] = epsi;constraints_upperbound[x_start] = x;constraints_upperbound[y_start] = y;constraints_upperbound[psi_start] = psi;constraints_upperbound[v_start] = v;constraints_upperbound[cte_start] = cte;constraints_upperbound[epsi_start] = epsi;// object that computes objective and constraintsFG_eval fg_eval(coeffs);//// NOTE: You don't have to worry about these options//// options for IPOPT solverstd::string options;// Uncomment this if you'd like more print informationoptions += "Integer print_level  0\n";// NOTE: Setting sparse to true allows the solver to take advantage// of sparse routines, this makes the computation MUCH FASTER. If you// can uncomment 1 of these and see if it makes a difference or not but// if you uncomment both the computation time should go up in orders of// magnitude.options += "Sparse  true        forward\n";options += "Sparse  true        reverse\n";// NOTE: Currently the solver has a maximum time limit of 0.5 seconds.// Change this as you see fit.options += "Numeric max_cpu_time          0.5\n";// place to return solutionCppAD::ipopt::solve_result<Dvector> solution;// solve the problemCppAD::ipopt::solve<Dvector, FG_eval>(options, vars, vars_lowerbound, vars_upperbound, constraints_lowerbound,constraints_upperbound, fg_eval, solution);// Check some of the solution valuesok &= solution.status == CppAD::ipopt::solve_result<Dvector>::success;// Costauto cost = solution.obj_value;std::cout << "Cost " << cost << std::endl;// Return the first actuator values, along with predicted x and y values to plot in the simulator.vector<double> solved;solved.push_back(solution.x[delta_start]);solved.push_back(solution.x[a_start]);for (int i = 0; i < N; ++i) {solved.push_back(solution.x[x_start + i]);solved.push_back(solution.x[y_start + i]);}return solved;}

 具体源码大家还是去直接下载代码看看看。跑下看看效果。然后可以改下预测步长N和采样周期t。这里给的N=10,t=0.1s。

大家有什么问题,我们可以一起交流下,相互促进,共同进步。我C++一般,是硬伤,Linux也是用了没多久,就为了跑这个工程。

如何求解的问题已经解决。

2. 如何利用

如何利用比求解简单多了啊,看代码:

// Send values to the simulatorjson msgJson;msgJson["steering_angle"] = steer_value;msgJson["throttle"] = throttle_value;// Display the MPC predicted trajectoryvector<double> mpc_x_vals = {state[0]};vector<double> mpc_y_vals = {state[1]};// add (x,y) points to list here, points are in reference to the vehicle's coordinate system// the points in the simulator are connected by a Green linefor (int i = 2; i < vars.size(); i+=2) {mpc_x_vals.push_back(vars[i]);mpc_y_vals.push_back(vars[i+1]);}msgJson["mpc_x"] = mpc_x_vals;msgJson["mpc_y"] = mpc_y_vals;// Display the waypoints/reference linevector<double> next_x_vals;vector<double> next_y_vals;// add (x,y) points to list here, points are in reference to the vehicle's coordinate system// the points in the simulator are connected by a Yellow linedouble poly_inc = 2.5;int num_points = 25;for (int i = 1; i < num_points; i++) {next_x_vals.push_back(poly_inc * i);next_y_vals.push_back(polyeval(coeffs, poly_inc * i));}msgJson["next_x"] = next_x_vals;msgJson["next_y"] = next_y_vals;auto msg = "42[\"steer\"," + msgJson.dump() + "]";std::cout << msg << std::endl;// Latency// The purpose is to mimic real driving conditions where// the car doesn't actuate the commands instantly.this_thread::sleep_for(chrono::milliseconds(100));ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);}} else {// Manual drivingstd::string msg = "42[\"manual\",{}]";ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);}

 主要看前两句,就是把计算好的发送到模拟器,实际的话应该是发信号给方向盘和脚踏板。还有预测的轨迹点也输出到模拟器。

现在大家再看看链接[2]中的这段话,是不是有点感觉:

自动驾驶的3大核心科技是定位(在哪里),感知(周围是啥)以及控制(咋开车呢)。通过车道检测,我们可以对车的行进路线进行路径规划。本篇文章主要通过一个自行车的动力学模型讨论车辆的加速、刹车和转向的模型预测控制。目的不仅在于尽可能地控制车辆轨迹,同时也还要尽可能使速度平滑以避免晕车和频繁的刹车。

模型预测控制主要在约束条件下使损失函数最小。例如,我们想要以100ms的周期调整转向和速度,在转向角度不能超过25°的约束下,最小化以规划的路径和实际路径之间的误差。我们通过传感器获取车辆的状态,比如速度,而我们的动作基于传感器读数以一个短的周期执行(例如1s)。例如,我们顺时针转向20°,然后每100ms周期减小1°。加入这些动作可以1秒钟之后的损失函数最小,我们将会采用第一个动作:顺时针转动20°,但是却并不执行后续的动作,而是在100ms后,重复优化过程。100ms后,有了新的读数,我们就重新计算下一个最优动作。模型预测控制通过预测接下来一段较长时间(1s)的损失函数,来计算选择出下一个较短周期(100ms)的最优动作。相比于短视的贪心算法,模型预测控制具有鲁棒性,因此能够控制得更好。

给出一张图,大家可能看的更明白了。

这是维基百科上的图[3]。 

这一篇就到这里吧,写的也不够深入,下一篇我会讲MATLAB中的实现。感谢下以下三个链接的作者。

 [1] https://www.cnblogs.com/kui-sd具体u/p/9026796.html

 [2] https://www.leiphone.com/news/201812/3iia3PiNHnHiUFMb.html(中文翻译)

     https://medium.com/@jonathan_hui/lane-keeping-in-autonomous-driving-with-model-predictive-control-50f06e989bc9(英文原版,视频需翻墙)

 [3] https://zh.wikipedia.org/wiki/%E6%A8%A1%E5%9E%8B%E9%A0%90%E6%B8%AC%E6%8E%A7%E5%88%B6


http://chatgpt.dhexx.cn/article/CdM40rrU.shtml

相关文章

模型预测控制(MPC)简介

1.引言 在当今过程控制中&#xff0c;PID当然是用的最多的控制方法&#xff0c;但MPC也超过了10%的占有率。MPC是一个总称&#xff0c;有着各种各样的算法。其动态矩阵控制&#xff08;DMC&#xff09;是代表作。DMC采用的是系统的阶跃响应曲线&#xff0c;其突出的特点是解决…

模型预测控制算法(MPC算法)底层逻辑

目录 MPC算法的基本原理 详细解析 预测模型中需要注意的点 滚动优化需要注意的点 构造目标函数约束部分 约束部分 举例说明 复盘总结 MPC算法的基本原理 MPC 的基本原理可以分为三个步骤&#xff1a;预测模型、滚动优化、反馈校正 &#xff08;1&#xff09;预测模型…

模型预测控制(MPC)算法原理

模型预测算法是在欧美等国家兴起的应用于工业领域的一种优化控制算法。目前经过多年的发展&#xff0c;在工业领域、智能控制领域等都有应用。随着算法的理论的完善&#xff0c;其已经成为工业领域内经常使用的一种经典算法。虽然在各个领域算法的应用存在差异。但他们都遵循预…

到底什么是模型预测控制MPC(一)

1. 为什么使用MPC控制 在浏览文章的时候&#xff0c;很多文章都是基于MPC来做的。那么究竟什么是模型预测呢&#xff1f; 模型预测也可以说是一种我们熟悉的反馈控制算法&#xff0c;其目的就是预测出未来的输出。以一个生活中的例子引入&#xff1a; 在我们驾驶汽车的时候&am…

MPC控制笔记(一)

转自 我的博客 笔记参考1&#xff1a;Understanding Model Predictive Control(Youtube 带自动生成字幕) 笔记参考2&#xff1a;Understanding Model Predictive Control(B站 生肉) 一、什么是MPC模型预测控制 MPC(Model Predict Control)是一种反馈控制(feedback control)算…

PID与MPC控制方法

记录udacity–无人驾驶工程师课程中控制部分。 MPC代码和实践链接https://github.com/udacity/CarND-MPC-Quizzes 本文按照对udacity课程的理解和翻译而来 1、PID P&#xff1a;Proportional 比例项&#xff0c; 用比例项乘以误差&#xff1b;快速缩小误差&#xff1b; I&…

了解模型预测控制2--什么是模型预测控制(MPC)

本节&#xff0c;我们将讨论模型预测控制器的工作原理。 在控制问题中&#xff0c;控制器的目标是计算被控对象的输入&#xff0c;使得被控对象输出遵循期望的参考信号。模型预测控制器计算此输入的策略是预测未来。 这听起来像算命&#xff0c;但让我们看看它究竟是什么。MPC使…

模型预测控制(MPC,Model Predictive Control)

发展历史 20世纪70年代后期&#xff0c;一类新型的计算机控制算法出现在美法等国的工业过程领域&#xff0c;如动态矩阵控制(DMC,Dynamic Matrix Control)、模型算法控制(MAC,Model Algorithm Control)。1987年&#xff0c;首次有学者阐述了该系列算法的动因、机理及其在控制工…

MPC学习笔记(1)——原理

最近在学习M. W. Mehrez的MPC时发现了很多不了解的细节&#xff0c;分享一下对该算法的梳理与理解。 在自动驾驶或机器人领域中&#xff0c;模型预测控制(Model Predictive Control, MPC)解决的是轨迹规划的问题。其前提条件是环境地图、载体位姿已知&#xff0c;根据MPC算法&…

MPC 控制原理

MPC 控制原理 1 生活中的启示2 实际控制的例子参考文献 Yin 机械工程师 本文引自 一个模型预测控制&#xff08;MPC&#xff09;的简单实现. 1 生活中的启示 情景如下&#xff1a;你们团队每天早晨开一次例会&#xff0c;主要会议内容是你汇报工作进度&#xff0c;领导根据工作…

EA建模工具,介绍常用的UML图

[导读] 作为程序猿都最好掌握的一门语言&#xff0c;那就是UML&#xff08;Unified Modeling Language&#xff09;&#xff0c;统一建模语言(UML)是软件工程领域中一种通用的开发建模语言&#xff0c;旨在提供一种可视化系统设计的标准方法。是开发人员、系统设计人员交流的有…

uml c语言函数流程图,UML流程图模板分享

原标题&#xff1a;UML流程图模板分享 UML是统一建模语言&#xff0c;又称标准建模语言是用来对软件密集系统进行可视化建模的一种语言。UML的定义包括UML语义和UML表示法两个元素。在流程图中也会经常使用到&#xff0c;但是网上关于该主题的模板不是很多&#xff0c;下面是分…

软技能之UML图

软技能之UML图 工欲善其事必先利其器&#xff0c;程序员建模过程中需要用到的建模工具UML。 UML&#xff1a;Unified Modeling Language 统一建模语言。目标是以对象图的方式来描述任何类型的系统。 UML可分为两类&#xff1a;结构型&#xff08;描述某种结构&#xff09;、行…

生成C++工程的UML类图和类继承关系图

简介 在进行软件开发时&#xff0c;了解代码结构和关系、类之间的继承关系以及类内部的成员函数和变量定义是非常重要的。为此&#xff0c;我们可以使用Doxygen和Graphviz工具来生成UML类图和类集成关系图。 Doxygen是一个用于从注释的C源代码中生成文档的工具&#xff0c;支…

Ubuntu系统画大型UML图

一、 环境配置 1. 配置java环境&#xff08;请自行查找教程&#xff09; 2. 安装graphviz sudo apt install graphviz 3. 下载plantuml.jar 下载页面 下载好以后&#xff0c;我将其放在了~/bin/目录下面 4. 配置alias export PLANTUML_JAR_PATH~/bin/ export PLANTUML_LIM…

UML图有哪些类型?

UML&#xff08;Unified Modeling Language &#xff09;是用来对软件密集系统进行可视化建模的一种语言&#xff0c;是在开发阶段、说明、可视化、构建和书写一个面向对象软件密集系统的制品的开放方法。 UML图分为两种类型&#xff1a;结构图和行为图。结构图是可视化组件如…

UML建模工具——用例图

【面向对象分析UML建模工具全部文章】 UML建模工具(1)——用例图UML建模工具(2)——活动图UML建模工具(3)——类图UML建模工具(4)——顺序图UML建模工具(5)——通信图UML建模工具(6)——状态图 UML建模工具——用例图 系统 System参与者 Actors用例 Use Cases关系 Relations…

移动端UML图应用之UML图简述

系列文章目录 移动端UML图应用之UML图简述 移动端UML图应用之UML行为图——用例图、活动图和状态机图 移动端UML图应用之UML交互图——顺序图和通信图 移动端UML图应用之UML结构图——包图、部署图和组件图 移动端UML图应用之UML结构图——类图 文章目录 系列文章目录前言一、…

IDEA 思维导图 ,类UML 图工具插件 plantUML integration

文章目录 IDEA 思维导图 ,类UML 图工具插件 plantUML integration1、安装2、UML3、使用 plantUML integrationIDEA 思维导图 ,类UML 图工具插件 plantUML integration 1、安装 找到插件并安装 2、UML UML 图包括序列图、用例图、类图、活动图、协作图、组件图、对象图、状态…

Mac下一款好用的UML图绘制工具(StarUML)

Mac下一款好用的UML图绘制工具&#xff08;StarUML&#xff09; 推荐一款好用的Mac下绘制UML图的工具&#xff0c;叫做StarUML&#xff0c;它是一款很好用的UML图的工具&#xff0c;但是是收费的&#xff0c;不过可以设置相应代码&#xff0c;免费使用&#xff0c;附上官方下载…