☰
Stribeck摩擦模型Matlab实现:从低速爬行现象到参数辨识与仿真
2026/10/17 16:21:44 网站建设 项目流程

简介:这份资源面向从事机械传动、伺服控制与摩擦补偿研究的工程师及高年级学生,提供Stribeck摩擦力模型的Matlab实现代码与调用示例,用于解决低速工况下负斜率摩擦现象的建模与仿真问题。压缩包共3个文件,均为m脚本,整体约1KB,体量轻便,其中包含模型核心函数与演示脚本,便于直接运行观察摩擦力随速度变化的曲线特征。模型采用指数形式描述克服静摩擦后摩擦力先降后升的过程,涉及静摩擦、库仑摩擦与Stribeck速度等关键参数,可帮助读者理解参数对负斜率区间的影响。已有1137人学习下载,适合作为摩擦建模入门与控制器前馈补偿验证的参考素材,读者可在此基础上修改参数、接入自建系统模型,快速完成仿真对比与算法调试。

1. 从一条“抖动”曲线说起:这个 Stribeck 摩擦模型到底能干什么

如果你调过伺服电机或者做过机械臂的低速轨迹跟踪,大概率见过一种很玄学的现象:速度指令给得很小,电机却像卡住一样一顿一顿地爬,位置曲线在目标点附近来回蹭,怎么调 PID 都压不下去。很多人第一反应是增益没整定好,其实根子往往在摩擦上——尤其是低速段那个从静摩擦跌到动摩擦的“负斜率”区间,也就是常说的 Stribeck 效应。这份资源就是围绕这个现象来的:一套用 Matlab 写的 Stribeck 摩擦力模型实现代码,外加能直接跑起来的使用示例。它适合两类人,一类是做控制算法、想给仿真里加个像样摩擦环节的,另一类是带机械负载、想搞清楚低速爬行到底怎么建模的。代码本身不复杂,但把静摩擦、库仑摩擦、粘滞摩擦和 Stribeck 速度衰减这几块拼在一起,能复现出真实机构里那种“起步要使劲、动起来反而省力”的曲线,这一点比单纯写个F = mu * N有用得多。

2. 模型拆解:Stribeck 曲线是怎么用四个参数拼出来的

2.1 从摩擦力-速度曲线看懂四个分量

先把物理图像摆清楚。Stribeck 模型描述的是摩擦力随相对速度变化的稳态关系,横轴是速度,纵轴是摩擦力。在速度为零附近,摩擦力最大,这叫静摩擦;速度刚起来一点点,摩擦力会先往下掉一段,这个下降段就是 Stribeck 区;速度继续增大,摩擦力趋于一个稳定值,这是库仑摩擦;再往上,摩擦力随速度线性上升,这是粘滞摩擦。把这四段合起来,常见的指数形式是这样:

function F = stribeck_friction(v, Fc, Fs, vs, sigma) % v : 相对速度 (标量或向量) % Fc : 库仑摩擦力 % Fs : 静摩擦力 (Fs >= Fc) % vs : Stribeck 特征速度,越小下降越陡 % sigma : 粘滞摩擦系数 F = Fc * sign(v) ... + (Fs - Fc) * exp(-abs(v)/vs) .* sign(v) ... + sigma * v; end

这里sign(v)负责方向,(Fs - Fc) * exp(-abs(v)/vs)就是那条从静摩擦往库仑摩擦衰减的指数项,sigma * v是粘滞项。参数含义很直白:Fs和Fc的差值决定 Stribeck 区的“落差”有多大,vs决定这个落差在多大速度范围内完成,sigma决定高速段翘得多快。我一般会先把Fc、Fs按实测的启动力和滑动摩擦力估出来,vs取额定速度的百分之一到十分之一之间试,sigma最后调。

2.2 零速附近的处理:别让 sign 函数把你坑了

上面那段代码在v = 0处有个隐患,sign(0)返回 0,摩擦力直接变成 0,这跟“静摩擦要克服才能动”的物理事实是矛盾的。真实情况是速度为零时摩擦力是个区间,能取到[-Fs, Fs]之间的任何值来平衡外力。所以工程实现里通常要分状态处理,常见做法是引入一个速度阈值v_eps,低于它就用静摩擦逻辑:

function F = stribeck_friction_v2(v, Fc, Fs, vs, sigma, v_eps) if abs(v) < v_eps % 低速区:用静摩擦上限,方向由外力决定 F = Fs * sign(v); % 实际使用时 sign(v) 常替换为外力方向 else F = Fc * sign(v) ... + (Fs - Fc) * exp(-abs(v)/vs) * sign(v) ... + sigma * v; end end

v_eps这个阈值不是随便取的,它要小于你关心的最低速度,又要大于数值积分可能产生的速度抖动,一般取1e-3到1e-4量级。注意这里sign(v)在零速附近其实是个简化,严谨的做法是判断外力是否超过Fs,没超过就保持静止、摩擦力等于外力,超过了才切换到滑动。示例代码里如果只做曲线绘制,用简化版就够了;要做动力学仿真,这个状态切换必须补上,否则积分器会在零速附近反复穿越,出现数值抖动。

2.3 参数怎么定:从实测数据反推的流程

模型能不能用,八成看参数。Fc、Fs最好来自实测:缓慢加力直到机构开始动,记下最大力就是Fs,动起来之后维持匀速所需的力就是Fc。vs和sigma靠拟合,把实测的摩擦力-速度点丢进最小二乘,让模型曲线去贴。Matlab 里可以用lsqcurvefit或者fminsearch,目标函数就是模型输出和实测值的残差平方和。如果手头没有实测数据,按经验估也行:Fs取Fc的 1.2 到 1.5 倍,vs取系统最低可控速度的一半左右,sigma取Fc除以额定速度再乘个 0.1 到 0.3。这些数不是标准答案,但能让曲线形状先对起来,后面再细调。

3. 跑起来:示例脚本、仿真步长和曲线验证

3.1 目录结构与文件职责

拿到一份 Matlab 代码,先别急着运行,把文件职责理清楚能省很多事。这类项目通常长这样:一个stribeck_friction.m放核心模型函数,一个demo_stribeck.m或main.m做参数设置和绘图,可能还有个simulink文件夹放.slx模型,外加一个data目录存实测数据。核心函数只负责“给速度算摩擦力”,不掺任何绘图和仿真逻辑,这样它才能被 Simulink 的 MATLAB Function 模块或者别的脚本复用。示例脚本负责把参数填进去、扫一遍速度、画曲线。如果你拿到的版本把绘图和模型混在一个文件里,建议先拆开,不然后面接动力学仿真会很难受。

3.2 用示例脚本扫出第一条 Stribeck 曲线

跑通的第一步是画静态曲线,不涉及积分,最不容易翻车。示例脚本大概是这样:

% demo_stribeck.m clear; clc; % 参数设置 Fc = 5; % 库仑摩擦 (N) Fs = 7; % 静摩擦 (N) vs = 0.05; % Stribeck 特征速度 (m/s) sigma = 2; % 粘滞摩擦系数 (N·s/m) % 速度扫描,注意要包含负速度才能看全曲线 v = linspace(-0.5, 0.5, 2001); % 逐点计算摩擦力 F = arrayfun(@(x) stribeck_friction(x, Fc, Fs, vs, sigma), v); % 绘图 figure; plot(v, F, 'LineWidth', 1.5); xlabel('相对速度 v (m/s)'); ylabel('摩擦力 F (N)'); title('Stribeck 摩擦模型曲线'); grid on;

linspace的点数取 2001 是为了让零速点正好落在中间,曲线在原点附近不会因为采样太稀而看起来断开。arrayfun是逐元素调用,速度慢但直观,速度向量大了可以改成向量化写法。跑完应该看到一条过原点、在零速附近最陡、往两边先降后升的曲线。如果曲线在原点是个尖点而不是平滑过渡,说明vs太小或者速度分辨率不够。

3.3 接进动力学仿真:步长和求解器的选择

静态曲线对了,下一步是把它塞进运动方程看动态响应。最简单的做法是写个单质量系统:

% 单质量系统 + Stribeck 摩擦 m = 1; % 质量 (kg) F_drive = 6; % 驱动力 (N),略大于 Fc 小于 Fs v0 = 0; % 初始速度 odefun = @(t, v) (F_drive - stribeck_friction(v, Fc, Fs, vs, sigma)) / m; [t, v] = ode45(odefun, [0 5], v0); figure; plot(t, v); xlabel('时间 t (s)'); ylabel('速度 v (m/s)'); title('驱动力略大于库仑摩擦时的速度响应'); grid on;

这里F_drive取 6,介于Fc=5和Fs=7之间,理论上机构应该先静止、等外力积累到超过静摩擦才动起来。但用ode45跑你会发现它可能直接就从零开始加速了,因为简化模型在v=0处摩擦力算出来是 0,没有“锁住”的效果。这就是 2.2 节说的零速处理问题。要做对,得用带状态判断的版本,或者换成ode15s并把v_eps调大一点。步长方面,vs越小,Stribeck 区越窄,需要的步长越小,一般让求解器自适应就行,但最大步长最好限制在vs对应时间尺度的十分之一以内,否则会跨过整个下降段,结果失真。

3.4 怎么判断模型跑对了

三个检查点。第一,静态曲线在v=0处的值应该接近Fs而不是 0,如果画出来是 0,说明零速处理没做。第二,曲线在正负速度上应该关于原点对称,不对称就是sign用错了。第三,动态仿真里如果驱动力小于Fs,速度应该保持为零;大于Fs之后才加速,加速过程中速度曲线应该平滑,不该有高频抖动。抖动通常来自状态切换太硬或者步长太大,把v_eps调大、步长调小能缓解。这三点过了,模型基本就能用了。

4. 避坑与排查:低速仿真里最容易翻车的几件事

4.1 现象:速度在零附近高频抖动,积分越跑越慢

原因基本是零速附近的摩擦力不连续。sign(v)在v=0处跳变,求解器为了满足误差要求会把步长压到极小,甚至卡死。解决办法是给摩擦力在零速附近加个平滑过渡,比如用tanh(v/v_eps)代替sign(v),或者用 2.2 节的状态机把静止和滑动分开处理。平滑过渡会损失一点静摩擦的“硬”特性,但换来的是能跑完的仿真,工程上通常划算。

4.2 现象:曲线形状对,但幅值整体偏大或偏小

先查单位。sigma的单位是 N·s/m,vs是 m/s,如果速度用的是 rad/s 或者 mm/s,参数全得跟着换。再查Fs和Fc有没有搞反,Fs必须大于等于Fc,反了的话指数项系数为负,曲线会往上翘,形状完全不对。还有一种情况是速度向量里没有零速点,linspace的奇数点数没取对,导致原点附近被跳过,看起来幅值不对。

4.3 现象:Simulink 里接 MATLAB Function 模块报维度错误

MATLAB Function 模块默认输入输出是标量或者固定维度,如果你在函数里用了arrayfun或者返回向量,模块会报维度不匹配。解决办法是把核心函数写成纯标量形式,向量化留给外面的脚本;或者在模块里显式声明输入输出的尺寸和类型。另外注意sign和exp在代码生成时对复数输入的处理,速度输入如果是复数(比如某些求解器中间步),abs和sign的组合可能出意外,加个real()保险。

4.4 现象:换了组参数曲线就发散

大概率是vs取太小而步长没跟着调。vs小意味着 Stribeck 区很窄,摩擦力在很小速度范围内从Fs掉到Fc,等效刚度很大,显式求解器容易不稳定。把vs放大一倍试试,如果稳定了就说明是刚性问题,换ode15s或者减小最大步长。还有一种可能是sigma取太大,粘滞项在高速段主导,速度反馈变成正反馈,这种情况检查一下sigma的符号,应该是正的。

5. 二次开发:把模型接进你的控制回路和参数辨识流程

模型跑通只是起点,真正要用起来,得把它接到你自己的场景里。我一般分三步走。第一步是参数辨识,把实测的摩擦力-速度数据整理成两列,用lsqcurvefit拟合Fc、Fs、vs、sigma四个参数,拟合前先固定Fs和Fc的粗略值,只放开vs和sigma,收敛更稳。第二步是把辨识好的模型塞进你的动力学仿真,替换掉原来那个常数摩擦或者干脆没有摩擦的环节,看看低速跟踪误差是不是变小了。第三步才是做摩擦补偿,常见做法是在控制量里加一个前馈项,大小等于模型算出来的摩擦力,方向跟速度相反。

改造时有几个点值得注意。如果你要做的是自适应或者在线辨识,核心函数得能接受时变参数,别把参数写死在函数体里,改成传参或者用persistent变量。如果要接 Simulink 做硬件在环,把模型函数编译成 C 代码时注意exp和sign的代码生成兼容性,tanh通常比sign更友好。还有一点,Stribeck 模型描述的是稳态摩擦,如果你的机构速度变化很快,得考虑加个一阶滞后环节模拟摩擦力的动态响应,否则仿真和实测会对不上。

参数辨识这块我踩过的坑最多。有一次拟合出来的vs特别小,曲线看着很贴,但一放进仿真就抖得没法看,后来发现是实测数据在低速段采样太稀,拟合被高速段的数据带偏了。从那以后我每次做参数辨识,都强制把低速段的数据单独拎出来加权,权重给到高速段的五到十倍,让拟合重点照顾 Stribeck 区。这个习惯帮我省了不少返工。希望这些能帮到你,拿到代码先跑静态曲线,再逐步往动态和补偿上走,别一上来就接闭环。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询