做车辆稳定性分析这些年,我越来越觉得“相平面”是绕不开的一条路。无论是ESP算法预研、底盘集成控制还是整车的极限工况评估,最后都会落到一个核心问题上:当前车辆的质心侧偏角和横摆角速度处于什么状态,离失稳边缘还有多远。而二自由度车辆模型的相平面分析,恰好能把这个抽象的问题变成一张直观的图——横轴是质心侧偏角β,纵轴是横摆角速度r,车辆的运动趋势是一簇簇箭头,稳定边界是一条条轨迹线。这篇博文是我完整梳理“二自由度车辆模型+相平面+鞍点+临界轨迹绘制”这套分析流程的记录,配套的MATLAB仿真代码我会逐步展开讲清楚。适合正在做车辆稳定性控制、毕设课题涉及相平面分析,或者想给ESP阈值标定找参考依据的朋友阅读。内容不绕弯子,从模型推导一路讲到代码落地,最后把实操中容易踩的坑也一并交代。
1. 相平面方法在车辆稳定性分析中的定位
1.1 为什么偏偏是质心侧偏角-横摆角速度平面
车辆稳定性本质上是一个非线性动力学问题。轮胎力在大侧偏角下会饱和,整车响应在大横摆角速度下会呈现明显的非线性特征。传统做法里,时域阶跃响应能告诉我们系统在某个工况下是收敛还是发散,但只能反映单个初始状态;特征值分析能给出局部线性化系统的稳定性,却在非线性区域无能为力。相平面方法的价值在于:它把整个状态空间铺开来看,把每个点上的运动趋势画成方向场,再把初始状态和运动轨迹叠上去,全局稳定性一目了然。
质心侧偏角β和横摆角速度r这两个状态量恰好刻画了车辆稳定性的两个维度。β反映车辆实际运动方向与车身指向的偏差,r反映车辆绕垂轴的转动快慢。驾驶员能感知的是横摆角速度,但真正危险的是质心侧偏角在某些工况下快速增大——后轴侧滑、甩尾失稳都伴随着β的异常增长。把这两个量放在同一个平面里,比单看某一个量更能识别“即将失控”的状态组合,这也是车辆稳定性控制领域普遍采用β-r相平面的根本原因。
1.2 二自由度模型能干到什么程度
所谓二自由度,就是只保留侧向运动和横摆运动这两个自由度,不考虑垂向、侧倾、俯仰和纵向速度的变化。这个模型把四轮车辆等效成一辆“自行车”——前轮和后轮各用一个等效轮胎代表,车辆的纵向车速假定恒定。它忽略了很多东西,但在分析车辆稳定性的核心机理时恰恰够用:轮胎的侧偏特性、轴距和质心位置对稳定性的影响都能体现出来。
实际项目中我常把二自由度模型当作第一道筛子。做相平面分析和稳定域划分,用它先跑出一批结果,再在必要时换更高精度的模型(比如Carsim联合仿真的17自由度模型)验证关键边界。二自由度模型的好处是参数少、计算快、机理清晰,任何算出来的现象都能找到对应物理原因。坏处是它没法覆盖大纵向加速度、强侧倾或路面附着变化非常剧烈的场景——这些场景下轮胎的垂直载荷转移和侧偏特性耦合会让模型失真。
2. 二自由度车辆动力学模型推导
2.1 动力学方程与轮胎侧偏角
推导从牛顿第二定律出发。车辆坐标系中,侧向力平衡方程为:
$$ mV(\dot{\beta} + r) = F_{yf} + F_{yr} $$
横摆力矩平衡方程为:
$$ I_z \dot{r} = a F_{yf} - b F_{yr} $$
其中m是整车质量,V是纵向车速,I_z是横摆转动惯量,a是质心到前轴距离,b是质心到后轴距离,F_yf和F_yr分别是前后轴等效侧向力。
前轮侧偏角和后轮侧偏角由运动学关系确定:
$$ \alpha_f = \delta - \beta - \frac{a r}{V} $$
$$ \alpha_r = -\beta + \frac{b r}{V} $$
这里的δ是前轮转角,单位是弧度。侧偏角的符号约定是:当车辆向左转向且质心侧偏角为正时,前轮侧偏角由三项组成——转向角δ使得α_f增大、β使得α_f减小、横摆运动a·r/V进一步减小α_f。这些关系是整个模型的基础,后面所有数值计算都依赖它们。
2.2 为什么要引入轮胎饱和特性
纯线性轮胎模型假设侧向力与侧偏角成正比,F_y = C_α·α,其中C_α是侧偏刚度。这个模型在小侧偏角范围(通常2度以内)精度尚可,但在分析稳定性边界时有一个致命问题:线性系统的相平面要么全部收敛、要么全部发散,根本没有“局部稳定域”和“临界轨迹”的概念,鞍点也只能在转向输入下出现一个,稳定域边界退化成直线。这显然无法反映轮胎饱和导致的失稳机理——真实车辆在大侧偏角下轮胎力饱和,车辆会逐渐失去恢复能力,稳定域边界是一条由鞍点稳定流形决定的复杂曲线。
我用的是tanh饱和模型来近似轮胎侧偏特性:
$$ F_{yf} = C_f \cdot \alpha_{sat,f} \cdot \tanh\left(\frac{\alpha_f}{\alpha_{sat,f}}\right) $$
$$ F_{yr} = C_r \cdot \alpha_{sat,r} \cdot \tanh\left(\frac{\alpha_r}{\alpha_{sat,r}}\right) $$
这个模型在α接近0时退化为线性模型(斜率等于侧偏刚度C),在|α|增大时侧向力平滑趋近于饱和值C·α_sat。相比于分段线性模型,tanh模型连续可微,数值求解Jacobian矩阵时不会出现跳变点,稳定性判断更顺畅,而且物理含义直观——α_sat就是轮胎侧偏力开始饱和的特征侧偏角。
2.3 状态空间表达与MATLAB函数封装
把轮胎模型代入动力学方程,整理成状态方程形式:
$$ \dot{\beta} = \frac{F_{yf} + F_{yr}}{m V} - r $$
$$ \dot{r} = \frac{a F_{yf} - b F_{yr}}{I_z} $$
这个两维的非线性常微分方程组就是相平面分析的核心对象。在MATLAB中把它封装成一个函数,参数用结构体传递,方便后期做参数扫掠:
function dx = veh_dyn(~, x, p) beta = x(1); r = x(2); alpha_f = p.delta - beta - p.a * r / p.V; alpha_r = -beta + p.b * r / p.V; Fyf = p.Cf * p.alpha_sat_f * tanh(alpha_f / p.alpha_sat_f); Fyr = p.Cr * p.alpha_sat_r * tanh(alpha_r / p.alpha_sat_r); dbeta = (Fyf + Fyr) / (p.m * p.V) - r; dr = (p.a * Fyf - p.b * Fyr) / p.Iz; dx = [dbeta; dr]; end参数按典型轿车的数量级来取,这套参数在我后续的仿真里都能直接跑出理想结果:
| 参数 | 数值 | 单位 | 说明 |
|---|---|---|---|
| m | 1520 | kg | 整车质量 |
| I_z | 2800 | kg·m² | 横摆转动惯量 |
| a | 1.2 | m | 质心到前轴距离 |
| b | 1.6 | m | 质心到后轴距离 |
| C_f | 80000 | N/rad | 前轮侧偏刚度 |
| C_r | 110000 | N/rad | 后轮侧偏刚度 |
| α_sat,f | 0.12 | rad | 前轮饱和特征角 |
| α_sat,r | 0.12 | rad | 后轮饱和特征角 |
| V | 20 | m/s | 纵向车速(72km/h) |
| δ | 0.02 | rad | 前轮转角(约1.15°) |
3. 平衡点分析:从求解到鞍点识别
3.1 平衡点的物理含义
平衡点就是让系统状态不再随时间变化的位置,数学上是令β_dot=0且r_dot=0同时成立的点。在相平面上,平衡点是所有轨迹的“归宿”或“源头”——稳定焦点周围螺旋线逐渐收拢到它,鞍点附近轨迹则沿着特定方向靠近又离开。
在车辆稳定性语境下,平衡点对应着车辆的极限均衡状态:稳态转向时横摆角速度和质心侧偏角都稳定的点,是稳定焦点;而鞍点则对应一种微妙的临界状态——它看似平衡,但任何微小扰动都可能让车辆状态沿某一方向加速发散。搞清楚鞍点在哪里,比搞清楚稳定焦点在哪里更重要,因为鞍点的稳定流形恰恰就是稳定域边界。
3.2 fsolve全平面扫描求平衡点
非线性系统的平衡点无法直接解析求解,我用fsolve在β-r平面内做全平面扫描。做法是在感兴趣的区域内铺一层网格,从每个网格点出发求解方程组,把找到的解去重后汇总:
options = optimoptions('fsolve', 'Display', 'off', 'Algorithm', 'trust-region-dogleg'); beta_grid = linspace(-0.35, 0.35, 15); r_grid = linspace(-0.8, 0.8, 15); eq_points = []; for b0 = beta_grid for r0 = r_grid [x_star, ~, flag] = fsolve(@(x) veh_dyn(0, x, param), [b0; r0], options); if flag > 0 if isempty(eq_points) || min(vecnorm(eq_points - x_star.', 2, 2)) > 1e-3 eq_points(end+1, :) = x_star.'; end end end end初值网格的密度直接影响能找到几个平衡点。网格太疏会漏掉鞍点,太密则浪费时间。经验做法是先铺15×15的粗网格扫描找大致位置,再在疑似平衡点附近用密集网格细扫确认。
3.3 特征值判据与平衡点分类
找到平衡点后,判断它是什么类型,需要用Jacobian矩阵的特征值。Jacobian矩阵是动力学方程在当前点的线性化,可以用数值差分法计算:
function A = jacobian_veh(x_star, p) h = 1e-6; A = zeros(2, 2); for j = 1:2 xp = x_star; xp(j) = xp(j) + h; xm = x_star; xm(j) = xm(j) - h; A(:, j) = (veh_dyn(0, xp, p) - veh_dyn(0, xm, p)) / (2 * h); end end特征值实部的符号决定了平衡点类型:
| 平衡点类型 | 特征值条件 | 相平面形态 |
|---|---|---|
| 稳定节点 | 两个负实特征值 | 轨迹直接收拢到平衡点 |
| 稳定焦点 | 共轭复根且实部为负 | 轨迹螺旋收敛到平衡点 |
| 不稳定节点 | 两个正实特征值 | 轨迹直接发散 |
| 不稳定焦点 | 共轭复根且实部为正 | 轨迹螺旋发散 |
| 鞍点 | 一正一负实特征值 | 轨迹沿稳定方向靠近、沿不稳定方向离开 |
在默认参数(V=20m/s,δ=0.02rad)下,模型预测出三个平衡点:中央一个稳定焦点,两侧各一个鞍点。这个结果是相平面分析的典型形态,也是一般稳定车辆在轮胎饱和模型下的特征——中央稳定域被鞍点分割,临界轨迹从鞍点处展开,决定了车辆能“hold住”的状态范围。
3.4 车速与前轮转角如何移动鞍点
鞍点不是固定不动的。车速升高时,轮胎力对侧偏角的敏感性相对降低,鞍点逐渐向中央稳定焦点靠近,稳定域随之收缩,这对应着高速工况下车辆更容易失稳的直觉。前轮转角增大时,平衡点整体偏移,稳定域几何形状不对称——转向方向一侧的稳定裕度减小,反向一侧相对增大。
这两个趋势在工程上有直接意义。ESP控制的触发阈值如果基于固定β和r的限值,在高速或大转角下必然失真。更科学的做法是实时根据车速和转向角查表得到当前工况的临界轨迹位置,再判断车辆状态是否越过边界。这也是相平面分析在实车控制中最重要的落地场景。
4. 相平面与临界轨迹的MATLAB实现
4.1 向量场绘制:方向场的可视化
相平面的第一层是向量场。在β-r平面上铺网格,计算每个格点上的β_dot和r_dot,用quiver画成箭头:
beta_vec = linspace(-0.3, 0.3, 25); r_vec = linspace(-0.6, 0.6, 25); [B, R] = meshgrid(beta_vec, r_vec); dB = zeros(size(B)); dR = zeros(size(B)); for i = 1:numel(B) dx = veh_dyn(0, [B(i); R(i)], param); dB(i) = dx(1); dR(i) = dx(2); end figure('Color', 'w'); quiver(B, R, dB, dR, 1.8, 'Color', [0.6 0.6 0.6]); hold on; xlabel('质心侧偏角 \beta (rad)', 'FontSize', 12); ylabel('横摆角速度 r (rad/s)', 'FontSize', 12); axis tight;向量场的箭头密度要适中。25×25的网格在观感和计算速度之间比较均衡;网格太密箭头叠成一团看不清,太疏看不出流场的连续变化。quiver的缩放因子也需要微调,默认值常常导致箭头过长或过短,我一般试用1.5到2之间的值。
4.2 相轨迹正向积分:从初始状态看走向
向量场是静态的,要理解动态过程需要从不同初始状态出发,沿正向时间积分得到轨迹曲线。这样能直观看到哪些初始点会收敛到中央稳定焦点,哪些会发散到远处:
init_cond = [0.05, 0.1; -0.05, -0.1; 0.15, 0.3; -0.2, -0.4; 0.1, -0.2]; for ic = 1:size(init_cond, 1) [~, Y] = ode45(@(t, x) veh_dyn(t, x, param), [0, 8], init_cond(ic, :)); plot(Y(:, 1), Y(:, 2), 'LineWidth', 1.5, 'Color', [0.85 0.35 0.1]); end积分时间的选取要观察轨迹是否已经“稳定”——要么收敛到平衡点附近,要么越过绘图边界。若8秒不够,可以延长到15秒,代价是计算时间增加。实际绘制时我习惯对稳定轨迹取较短积分时长(能看到收敛趋势即可),对发散轨迹取稍长时间展示逃逸路径,然后手动挑好看的绘制区间。
4.3 临界轨迹的核心技巧:鞍点稳定流形的反向积分
这一节是整个相平面分析里最值得反复琢磨的地方。临界轨迹,也就是稳定域的边界,在数学上正是鞍点的稳定流形——沿着这条曲线,正向时间下轨迹会收敛到鞍点;从曲线两侧出发的轨迹则分别流向不同的归宿。
数值上提取稳定流形有个巧妙的做法:在鞍点附近,沿稳定特征向量方向取一个微小偏移的初始点,然后对原系统做时间反演积分。因为时间反演把“沿稳定方向收敛”变成了“沿稳定方向发散”,轨迹会从鞍点向外延伸,恰好画出稳定流形在相平面中的完整形态。
实现代码如下,事件函数用于控制轨迹不超出绘图边界:
function [traj_plus, traj_minus] = stable_manifold(x_saddle, param) A = jacobian_veh(x_saddle, param); [V, D] = eig(A); evals = diag(D); [~, idx_s] = min(real(evals)); % 稳定特征值 vs = V(:, idx_s); % 稳定特征向量 eps0 = 1e-6; p0_plus = x_saddle + eps0 * vs; p0_minus = x_saddle - eps0 * vs; bounds = [-0.35, 0.35, -0.7, 0.7]; % [beta_min, beta_max, r_min, r_max] opts = odeset('Events', @(t, y) stop_event(t, y, bounds)); [~, Yp] = ode45(@(t, x) -veh_dyn(t, x, param), [0, 20], p0_plus, opts); [~, Ym] = ode45(@(t, x) -veh_dyn(t, x, param), [0, 20], p0_minus, opts); traj_plus = Yp; traj_minus = Ym; end function [value, isterminal, direction] = stop_event(~, y, bounds) value = [bounds(1) - y(1); y(1) - bounds(2); bounds(3) - y(2); y(2) - bounds(4)]; isterminal = ones(4, 1); direction = zeros(4, 1); end反向积分这件事,很多初学者第一次写容易想反:为什么不是沿不稳定方向积分?关键在于时间反演改变了稳定性的方向——沿稳定特征方向取初始点再做反向积分,轨迹恰好追踪的是鞍点稳定流形。若沿不稳定方向反向积分,轨迹会直接跑到远处,画出来的不是边界而是发散路径。
4.4 完整绘图主程序:把三层信息叠在一起
把向量场、相轨迹、临界轨迹和平衡点叠在一张图上,形成完整相平面图:
% 参数与平衡点求解(见第3章代码) % 假设 eq_points 中已知稳定焦点 x_focus 和两个鞍点 x_saddle1、x_saddle2 figure('Color', 'w', 'Position', [100 100 720 560]); hold on; % 第一层:向量场 beta_vec = linspace(-0.3, 0.3, 23); r_vec = linspace(-0.6, 0.6, 23); [B, R] = meshgrid(beta_vec, r_vec); dB = zeros(size(B)); dR = zeros(size(B)); for i = 1:numel(B) dx = veh_dyn(0, [B(i); R(i)], param); dB(i) = dx(1); dR(i) = dx(2); end quiver(B, R, dB, dR, 1.8, 'Color', [0.75 0.75 0.75], 'LineWidth', 0.6); % 第二层:相轨迹 init_set = [0.02, 0.05; -0.02, -0.05; 0.08, 0.2; -0.08, -0.2; 0.15, 0.05; -0.15, -0.05; 0.06, -0.15; -0.06, 0.15]; for ic = 1:size(init_set, 1) [~, Y] = ode45(@(t, x) veh_dyn(t, x, param), [0, 10], init_set(ic, :)); plot(Y(:, 1), Y(:, 2), 'Color', [0.1 0.45 0.8], 'LineWidth', 1.2); end % 第三层:临界轨迹(两个鞍点的稳定流形) for i = 1:2 x_s = eq_points(i, :).'; [tp, tm] = stable_manifold(x_s, param); plot(tp(:, 1), tp(:, 2), 'r-', 'LineWidth', 2.0); plot(tm(:, 1), tm(:, 2), 'r-', 'LineWidth', 2.0); end % 平衡点标记 plot(x_focus(1), x_focus(2), 'ko', 'MarkerSize', 10, 'MarkerFaceColor', 'g'); plot(x_saddle1(1), x_saddle1(2), 'ks', 'MarkerSize', 10, 'MarkerFaceColor', 'r'); plot(x_saddle2(1), x_saddle2(2), 'ks', 'MarkerSize', 10, 'MarkerFaceColor', 'r'); xlabel('质心侧偏角 \beta (rad)', 'FontSize', 13); ylabel('横摆角速度 r (rad/s)', 'FontSize', 13); legend({'向量场', '相轨迹', '临界轨迹', '稳定焦点', '鞍点'}, ... 'Location', 'northwest', 'FontSize', 10); axis([-0.3 0.3 -0.6 0.6]); grid on;这套代码把相平面分析的三层信息完整呈现:灰色箭头是系统的运动趋势,蓝色曲线是不同初始状态的演化路径,红色粗线是稳定域的临界边界。稳定焦点和鞍点用不同形状的标记标出,一眼就能看出整个稳定域的几何形状。
5. 仿真结果与物理规律解读
5.1 前轮转角对稳定域的挤压效应
在V=20m/s的默认车速下,我把前轮转角从0逐步增加到0.05rad,观察稳定域形态的变化。δ=0时,相平面对称,中央稳定焦点位于原点,左右两个鞍点对称分布,临界轨迹围出一个大致关于原点对称的稳定域。转向角增大到0.02rad时,稳定焦点向某个方向偏移,两个鞍点的位置不再对称,稳定域的一侧被明显“挤压”,另一侧相对宽松。
这个现象背后的物理机理是:转向时前后轮侧偏角重新分配,一侧轮胎先于另一侧进入饱和区。从控制角度看,它提醒我们——同一套稳定性判定阈值在不同转向方向上的余量并不相同,若用对称阈值是保守还是激进完全取决于稳态工况点。
5.2 车速对稳定域的收缩作用
车速是另一个关键变量。我对比了V=15m/s、20m/s和30m/s三组仿真,稳定域面积随车速升高明显缩减。V=15m/s时,临界轨迹围出的区域较宽,β极限可以到0.25rad以上;V=30m/s时,稳定域收缩到β±0.15rad左右,横摆角速度范围也同步收窄。鞍点位置与稳定焦点的距离迅速拉近,意味着系统从稳定到失稳的过渡区间变短——车辆在高速下更“脆”了。
这个结果和实车感受完全一致:低速下猛打方向车头会响应并很快建立稳定转向,高速下同样的操作会引发车辆大幅横摆甚至甩尾。相平面把这个物理过程量化了,这也是ESP系统在高速工况下需要更早介入的原因。
5.3 从临界轨迹到稳定性控制阈值
临界轨迹的工程价值在于它提供了定量的失稳边界。实际做控制阈值设计时,可以这样利用:根据当前车速V和驾驶员转向输入δ,实时解算当前工况下的临界轨迹;然后把车辆的实时状态(β, r)与临界轨迹比较,计算某个“稳定裕度指标”。如果状态点与边界的最小距离小于设定阈值,就触发稳定性干预。
这种做法的优势在于它比单一限值的逻辑更精细。传统阈值控制常出现误触发或漏触发,而基于相平面边界的方法天然适应车辆非线性特性和工况变化。我见过不少实车标定团队用类似思路做ESP的参考阈值预研,先在仿真环境里标定稳定域边界,再上实车微调。
6. 常见问题与实操避坑实录
6.1 反向积分的积分方向陷阱
临界轨迹绘制最容易翻车的地方是积分方向。从鞍点附近出发做时间反演积分,目的是追踪稳定流形。但很多初学者会做成“从鞍点出发沿不稳定特征向量方向正向积分”,画出来的轨迹其实是鞍点的不稳定流形——它是失稳逃逸的路径,不是稳定域的边界。判断画得对不对有个简便方法:稳定流形上的轨迹从远离鞍点的地方沿时间正向运动会收敛到鞍点。如果画出的红色曲线,正向积分下是远离鞍点的,那就画反了。
6.2 鞍点求解的初值选取
fsolve求鞍点经常遇到初值敏感问题。网格扫描一开始可能漏掉鞍点,尤其是当两个鞍点靠得比较近或者处于网格间隙中。我的经验是:先用粗网格扫描找到所有解的“聚类中心”,再对每个疑似区域用更密的局部网格重新扫描,同时把fsolve的容差收紧到1e-10。另一个辅助手段是观察向量场——箭头汇聚处往往是平衡点,先目测定位再数值求解可以大幅提高命中率。
6.3 网格密度与计算时间的折中
向量场网格和初始状态网格都会影响计算量。25×25向量场只有625个点,瞬时就能算完。但若是批量仿真不同车速和转向角的相平面组合,这里就会积累出明显的耗时。举例来说,50组工况、每组25×25向量场加上20条相轨迹,总计算量在普通笔记本电脑上要跑好几分钟。我一般先用稀疏网格把所有工况扫一遍,挑选出稳定域形状变化明显的工况,再对精选工况做密网格精细绘图。
6.4 单位与量纲:角度永远用弧度
车辆动力学仿真中单位错误是低级但致命的错误。所有角度——β、r、δ、α_f、α_r——在数值计算中必须使用弧度。若用角度制输入,模型中的侧偏刚度等参数全部对不上号,求解出来的平衡点位置和相平面形态会完全错误。我在封装veh_dyn函数之前专门写过一个断言函数,检查所有角度参数是否在合理弧度范围内,避免在长时间调试后才意识到单位问题。
6.5 tanh模型参数标定的边界
tanh模型中的α_sat参数不是随手取的。它决定了轮胎线性区的范围以及饱和后侧向力的大小,直接影响鞍点位置和稳定域面积。如果用魔术公式拟合过的轮胎数据,α_sat通常在5到10度之间,即0.09到0.18rad。不同轮胎类型(轿车胎、SUV胎、运动胎)差异很大,需要根据实际轮胎参数标定。如果只是定性分析,取0.1到0.12区间都能接受;如果用于实车级仿真,需要精确匹配轮胎模型数据。
6.6 事件函数与积分溢出的隐藏问题
stable_manifold中用了事件函数来限制反向积分范围,避免轨迹飘出绘图区域。但事件函数有一个隐藏问题:如果事件检查条件设置不当,或者轨迹在边界来回振荡,可能导致积分提前终止或卡死。我在实际调试中遇到过轨迹距离边界还有一段距离就误触发事件的情况——原因是反向积分的轨迹数值在边界附近出现锯齿状波动。解决办法是把事件检查的容差放宽,或者在ode45的选项中设置较大的ReTol(如1e-5),必要时在事件函数里加一个最小步长判断。
经历这些之后,我对相平面分析最大的体会是:画图只是手段,理解边界才是目的。鞍点的位置、临界轨迹的形状、稳定域的面积,这些才是车辆失稳机制的数字投影。当你把仿真代码跑通、把不同工况下的相平面图放在一起比较时,很多原本只在感觉层面的东西——比如高速更危险、大转角更敏感——都会变成清晰可量化的规律。这恰好是相平面方法相比其他分析工具最迷人的地方。