ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

两轮差速机器人轨迹跟踪:Simulink建模与PID调参实战

2026/9/29 17:52:01 拓冰建站 浏览量
两轮差速机器人轨迹跟踪:Simulink建模与PID调参实战 1. 为什么两轮差速机器人的轨迹跟踪值得从零搭一遍两轮差速底盘是移动机器人里最经典的构型没有之一。左右两个驱动轮独立控制靠速度差实现转向结构简单、成本低、可靠性高从扫地机到AGV小车再到教学平台到处都是它的身影。但结构简单不代表控制简单——轨迹跟踪这件事恰恰是差速底盘最容易翻车的地方。我见过太多人卡在同一个坎上运动学模型推得头头是道PID参数也照着教程调了仿真一跑直线还行一拐弯就画龙圆圈轨迹直接跑成螺旋线。问题出在哪往往不是PID本身而是从建模到调参这条链路上有几个关键环节被想当然了。这篇内容就是把这整条链路拆开讲清楚。从两轮差速的运动学建模开始到Simulink里怎么搭、PID怎么整定、轨迹怎么生成、误差怎么定义最后到仿真跑通之后怎么往实际控制器上落。适合两类人一类是正在做机器人课程设计或毕设的学生另一类是想把Simulink仿真真正用起来的工程师。不需要你有多深的控制理论背景但基本的微积分和MATLAB操作得会。我自己的经验是这套东西如果只看书很容易觉得就这但真上手搭一遍你会发现每个环节都有坑而且坑和坑之间是连锁的。所以下面我会按实际搭建的顺序来讲重点放在为什么这么做和哪里容易出错上。2. 两轮差速运动学建模别急着写方程先把坐标系定死2.1 全局坐标系与机器人坐标系的约定运动学建模第一步不是推导是约定。很多人推导过程没错结果和别人的对不上就是因为坐标系约定不一样。我建议采用下面这套约定后面所有内容都基于它全局坐标系(X-O-Y)固定在地面上单位是米。机器人坐标系(x_r - o_r - y_r)原点在底盘两轮轴线的中点(x_r) 指向机器人正前方(y_r) 指向左侧。姿态角(\theta)机器人前进方向与全局 (X) 轴的夹角逆时针为正。在这个约定下机器人的位姿用 ([x, y, \theta]^T) 表示。注意(\theta) 是全局坐标系下的绝对角度不是相对某个参考线的角度这一点在写误差方程时非常关键。提示如果你用的是ROS里的odom默认也是这套约定但有些教材会把 (y_r) 指向右侧那样角速度符号会反过来。建议一开始就在Simulink模型里用注释把约定写清楚后面调参时能省很多事。2.2 从轮速到车体速度的映射关系两轮差速的核心关系就两个公式。设左轮线速度为 (v_L)右轮线速度为 (v_R)轮半径为 (r)两轮间距为 (L)则车体线速度 (v) 和角速度 (\omega) 为[ v \frac{v_R v_L}{2} ][ \omega \frac{v_R - v_L}{L} ]反过来给定期望的 (v) 和 (\omega)左右轮速度是[ v_L v - \frac{\omega L}{2} ][ v_R v \frac{\omega L}{2} ]这四个公式是整个控制系统的地基。所有轨迹跟踪算法最终都要落到这两个轮速上。我见过有人直接在 (v) 和 (\omega) 层面做PID然后忘了反解轮速结果仿真里机器人根本不动——因为Simulink里的被控对象是轮子不是车体。2.3 位姿微分方程与离散化处理车体速度到全局位姿的映射是[ \dot{x} v \cos\theta ][ \dot{y} v \sin\theta ][ \dot{\theta} \omega ]这三个方程是非线性的因为 (\cos\theta) 和 (\sin\theta) 的存在。在Simulink里实现时有两种做法连续积分直接用Integrator模块仿真步长设小一点比如1ms精度够用。离散迭代用单位延迟加累加的方式步长固定适合后面要生成代码的场景。我一般先用连续积分快速验证算法确认没问题后再改成离散形式方便后续往嵌入式平台移植。离散化时用前向欧拉就行[ x_{k1} x_k v_k \cos\theta_k \cdot T_s ][ y_{k1} y_k v_k \sin\theta_k \cdot T_s ][ \theta_{k1} \theta_k \omega_k \cdot T_s ]其中 (T_s) 是采样周期。这里有个坑如果 (T_s) 取太大比如10ms以上圆弧轨迹会明显失真因为欧拉法对角度积分误差累积很快。实测下来1ms到5ms是比较稳妥的范围。3. Simulink模型搭建模块怎么摆信号怎么连3.1 整体架构与信号流向设计在动手拖模块之前先在纸上画一遍信号流。我的习惯是分成四个子系统轨迹生成器输出期望位姿 ([x_d, y_d, \theta_d]) 和期望速度 ([v_d, \omega_d])。误差计算根据当前位姿和期望位姿算出跟踪误差。控制器PID在这里输出 (v) 和 (\omega) 的修正量。机器人模型运动学方程加轮速反解输出下一时刻位姿。信号流向是轨迹生成器 → 误差计算 → 控制器 → 机器人模型 → 反馈回误差计算。这是一个典型的闭环结构但误差定义方式决定了闭环的性能后面会专门讲。在Simulink里我建议用Subsystem把每个部分封装起来接口用Inport和Outport明确。这样模型层次清晰调参时想改哪块直接进去改不会在一堆连线里迷路。3.2 轨迹生成模块的三种实现方式轨迹生成看起来简单其实选择很多。常见的有三种第一种解析式轨迹。比如直线、圆弧、正弦曲线直接用MATLAB Function写公式。优点是精确、可重复适合做算法验证。比如一个半径 (R) 的圆function [xd, yd, thd, vd, wd] circle_traj(t, R, w) thd w * t; xd R * sin(thd); yd R * (1 - cos(thd)); vd R * w; wd w; end注意这里的 (\theta_d) 是轨迹切线方向不是极角很多人在这里搞混导致初始误差巨大。第二种查表插值。用From Workspace模块读一组预先算好的路径点配合插值。适合复杂路径比如S形、8字形。第三种状态机切换。用Stateflow做多段轨迹切换比如先直线再圆弧再直线。这种在工程里最常见但调试时要注意切换瞬间的速度连续性否则会有冲击。我一般先用第一种验证控制器再用第三种做完整场景。3.3 误差计算全局误差还是局部误差这是整个模型里最容易出错的地方。误差有两种定义全局误差(e_x x_d - x)(e_y y_d - y)直接在全局坐标系下相减。局部误差把误差投影到机器人坐标系下[ e_x^{local} (x_d - x)\cos\theta (y_d - y)\sin\theta ][ e_y^{local} -(x_d - x)\sin\theta (y_d - y)\cos\theta ]全局误差直观但有个致命问题当机器人朝向和轨迹方向偏差很大时全局误差的符号和大小不能正确反映该往哪转。局部误差则天然解决了这个问题(e_x^{local}) 表示纵向偏差(e_y^{local}) 表示横向偏差控制器设计起来更符合直觉。我的建议是用局部误差做控制用全局误差做监控和可视化。在Simulink里两个都算但PID的输入用局部的。注意局部误差的变换矩阵里用的是当前 (\theta)不是期望 (\theta_d)。用错了会导致误差在机器人转向时剧烈跳变。3.4 轮速反解与饱和限幅的必要性控制器输出 (v) 和 (\omega) 之后要反解成 (v_L) 和 (v_R)。这一步别忘了加饱和限幅。实际电机有最大转速仿真里如果不限幅PID可能会输出一个物理上不可能的速度导致仿真结果虚好一上真机就废。限幅分两层轮速限幅(v_L, v_R) 限制在 ([-v_{max}, v_{max}])。角速度限幅(\omega) 限制在 ([-\omega_{max}, \omega_{max}])。限幅之后如果 (v_L) 和 (v_R) 都被截断实际的车体速度会偏离控制器期望值这时候误差会累积PID会继续加大输出形成积分饱和。解决办法是加抗饱和逻辑当输出饱和时停止积分累加。Simulink的PID模块自带这个功能但需要手动使能。4. PID控制器设计位置环、速度环还是双环4.1 单环PID能不能用先看控制目标很多人一上来就问PID三个参数怎么调但更重要的问题是你控制的是什么量对于轨迹跟踪有两种主流方案方案A位置误差直接进PID输出速度指令。也就是 (e_x^{local}) 和 (e_y^{local}) 分别经过PID输出 (v) 和 (\omega)。结构简单但耦合严重直线还行曲线容易振荡。方案B双环控制。外环是位置环输出期望速度内环是速度环跟踪期望速度。内环响应快外环响应慢解耦效果好。我实测下来方案B在曲线轨迹上的跟踪精度明显优于方案A尤其是高速情况下。但方案B调参更复杂需要先调内环再调外环。4.2 外环位置PID的参数整定顺序外环的任务是消除位置误差。我的整定顺序是先调 (K_p)从小到大加直到机器人能快速响应但不振荡。对于局部误差(e_x^{local}) 的 (K_p) 影响纵向速度(e_y^{local}) 的 (K_p) 影响转向。再加 (K_d)抑制超调。轨迹跟踪里 (K_d) 很重要因为机器人有惯性纯P会冲过头。最后加 (K_i)消除稳态误差。但积分项在轨迹跟踪里要慎用因为轨迹是时变的积分容易累积出问题。我一般把 (K_i) 设得很小或者干脆不用。一个经验值如果采样周期是1ms(K_p) 在1到5之间(K_d) 在0.1到0.5之间先从这个范围试。4.3 内环速度PID与抗积分饱和内环跟踪的是轮速。因为电机模型通常是一阶惯性环节内环PID比较好调。关键是内环带宽要明显高于外环一般高5到10倍。内环的积分饱和问题更突出因为电机启动瞬间误差大积分会迅速累积。Simulink里可以用PID Advanced模块勾选Limit output和Anti-windup模式选clamping。提示如果你后面要生成C代码上嵌入式建议内环用PI就够了D项对编码器噪声很敏感容易放大抖动。4.4 前馈补偿让PID不用那么累纯反馈控制有个天然缺陷它总是等误差出现了才动作。对于已知的轨迹可以加前馈[ v_{cmd} v_d PID(e) ][ \omega_{cmd} \omega_d PID(e) ]前馈项 (v_d) 和 (\omega_d) 直接来自轨迹生成器。这样PID只需要补偿模型误差和扰动负担小很多跟踪精度能提升一个档次。我在圆弧轨迹上试过加前馈后横向误差能降到原来的三分之一。5. 调参实战从画龙到贴线的完整过程5.1 初始参数下的典型失败现象假设你按上面的结构搭好了模型参数随便设了一组跑一个半径1米的圆。大概率会看到这几种现象机器人原地打转角速度符号反了检查 (\omega) 到轮速的反解公式。轨迹越跑越大(K_p) 太小或者前馈没加。轨迹振荡(K_p) 太大或 (K_d) 太小。起步时冲出去积分饱和或者初始误差太大。我第一次搭的时候机器人画了个花瓣后来发现是局部误差变换矩阵里 (\theta) 用成了 (\theta_d)。这个坑很隐蔽因为直线时两者相等只有曲线才暴露。5.2 用Scope和To Workspace定位问题Simulink的Scope只能看波形定位问题还得靠数据。我的做法是把 (x, y, \theta, v, \omega, e_x, e_y) 全部用To Workspace存成数组。仿真结束后在MATLAB里画图轨迹对比图、误差曲线、控制量曲线。重点看误差曲线的相位和幅值如果误差和轨迹同频但滞后是相位问题如果误差持续增大是增益不够。figure; plot(xd, yd, r--, x, y, b); axis equal; legend(期望, 实际); figure; plot(t, ex, t, ey); legend(纵向误差, 横向误差);5.3 分阶段调参先直线后圆弧再变曲率不要一上来就跑复杂轨迹。我的调参流程是直线轨迹调 (K_p) 和 (K_d)让机器人能快速跟上直线超调小。定曲率圆弧加前馈调角速度环观察横向误差。变曲率S形考验控制器的适应性这时候可能需要稍微降低 (K_p)增加 (K_d)。每个阶段记录一组参数最后取一个折中。没有一组参数能通吃所有轨迹这是现实。5.4 常见振荡与稳态误差的对应关系现象可能原因调整方向高频振荡(K_p) 过大或 (K_d) 过小降 (K_p)加 (K_d)低频摆动积分过强或外环带宽过高降 (K_i)降外环 (K_p)稳态误差不消(K_i) 为0或前馈缺失加小 (K_i)检查前馈起步超调积分饱和开抗饱和限制初始输出曲线内侧偏移前馈角速度不足增大 (\omega_d) 前馈系数这张表是我踩坑总结出来的基本覆盖了八成问题。6. 仿真跑通之后往实际控制器上落要注意什么6.1 从连续到离散采样周期怎么选仿真里用连续积分没问题但实际控制器是离散的。采样周期 (T_s) 的选择要满足两个条件香农定理(T_s) 要小于系统最快动态的十分之一。计算能力嵌入式平台的主频和任务调度决定了最小 (T_s)。对于两轮差速机器人如果电机响应时间在10ms量级(T_s) 取1ms到5ms比较合适。我一般先用1ms仿真确认算法没问题后再试5ms和10ms看性能下降多少最后根据实际平台定。6.2 编码器噪声对微分项的影响实际编码器有量化噪声速度估计会有抖动。PID的D项对噪声极其敏感直接微分会让控制量剧烈抖动。解决办法低通滤波在速度反馈上加一阶低通截止频率取控制带宽的2到5倍。不完全微分D项串一个一阶惯性环节Simulink的PID模块支持。用位置差分代替速度微分如果编码器分辨率够高直接对位置差分算速度比微分速度信号更稳。我在实际项目里用的是第二种效果最稳。6.3 代码生成与部署的简化路径Simulink支持直接生成C代码但不是所有模块都支持代码生成。要生成代码得注意用支持代码生成的模块比如Discrete PID、Unit Delay、Gain、Sum。避免用Interpreted MATLAB Function改用MATLAB Function块。定点化如果目标平台是MCU考虑用定点数但PID参数要重新整定。生成代码后先做软件在环测试把生成的代码在PC上跑一遍和Simulink结果对比。确认一致后再下载到硬件。这一步能省掉大量现场调试时间。6.4 仿真与实机的差距来源最后说点实在的。仿真跑得再好实机也会有差距主要来自模型误差轮半径、轮距的实际值和标称值有偏差。摩擦和打滑仿真里通常忽略实际低速时摩擦非线性很明显。延迟传感器采样、通信、执行器响应都有延迟仿真里如果没建模实机会振荡。地面不平差速底盘对地面很敏感稍微有点坡就会偏。我的建议是仿真里故意加一些扰动和参数偏差比如把轮距改±5%加一点噪声看控制器还稳不稳。如果仿真里都扛不住实机肯定不行。这样调出来的参数上真机后基本不用大改最多微调一下前馈系数。这套流程我从课程设计做到工程项目反复用了很多次每次都能在两天内从零跑通一个可用的轨迹跟踪控制器。核心就一句话建模要严谨误差定义要清楚调参要分阶段仿真要留余量。剩下的就是耐心跑数据、看曲线、改参数。