基于实验数据的轮胎模型
参考CarSim的轮胎公式,本篇介绍一种基于实验数据的轮胎模型。输入为垂直力,侧偏角,外倾角,滑移率,输出为牵引力,侧向力和回正力矩。模型对轮胎进行了简化,不考虑路面摩擦,车速及轮胎Mx,My转矩。程序代码用Simulink S-Function完成,计算结果与CarSim自带的轮胎模型进行了对比。
1. 坐标系
轮胎坐标系的坐标原点位于轮胎与地面的接触点,方向设置如下图。
2. 模型公式
Gamma角对轮胎侧向力和回正力矩的影响,通过修正侧偏角Alpha来实现的。公式如下:
其中τ会Alpha角度的斜率,为Camber Trust系数,为Linear Conering Stiffness。
实验数据是针对纯滑移率或纯侧偏情况下采集的。而实际上轮胎力为侧向力和牵引力的合力,彼此是有影响的。因此该模型采用Pacejka的Combine Slip Theory来对两个分力进行椭圆化。
求解公式如下,具体解释可参考CarSim的轮胎帮助文档。
对上面公式进行正交化,max为相应的力最大时取得的delta值。
从而可以求出新的滑移率和侧偏角:
将它们带入实验数据,可得对应的牵引力和侧向力。
对这两个力进行椭圆化:
当时, 时。
从而求出最终的牵引力和侧向力:
其中:
上面这些变量之间的关系,参见下图:
回转力矩的公式由下式求出:
3. 轮胎S-Function实现
S-Function的用法,参见博文: MATLAB中的S-Function的用法(C语言) 。
线性插值方法,参见博文: 双线性插值(Bilinear Interpolation) 。
#define S_FUNCTION_NAME CarSimTire #define S_FUNCTION_LEVEL 2 #include "simstruc.h" #include <math.h> #define TIRE_FX_KAPPA(S) ssGetSFcnParam(S,0) #define TIRE_FX_LOAD(S) ssGetSFcnParam(S,1) #define TIRE_FX(S) ssGetSFcnParam(S,2) #define TIRE_FY_ALPHA(S) ssGetSFcnParam(S,3) #define TIRE_FY_LOAD(S) ssGetSFcnParam(S,4) #define TIRE_FY(S) ssGetSFcnParam(S,5) #define TIRE_MZ_ALPHA(S) ssGetSFcnParam(S,6) #define TIRE_MZ_LOAD(S) ssGetSFcnParam(S,7) #define TIRE_MZ(S) ssGetSFcnParam(S,8) #define TIRE_CAM_LOAD(S) ssGetSFcnParam(S,9) #define TIRE_CAM_COEF(S) ssGetSFcnParam(S,10) #define ROWS 300 #define COLS 10 #define PI 3.1416 #define ABS(val) val>=0?val:-val #define SIGN(val) (val==0)?0:(val>0?1:-1) #define ZERO 0.00001 static real_T TireFxKappaPeak[COLS]; static real_T TireFyAlphaPeak[COLS]; static int_T TireFxSize[2]; static int_T TireFySize[2]; static int_T TireMzSize[2]; static int_T TireCamSize;static void mdlInitializeSizes(SimStruct *S) {ssSetNumSFcnParams(S, 11); /* Number of expected parameters */if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) return;ssSetNumContStates(S, 0);ssSetNumDiscStates(S, 0);if (!ssSetNumInputPorts(S, 4)) return;ssSetInputPortWidth(S, 0, 1);ssSetInputPortRequiredContiguous(S, 0, true);ssSetInputPortDirectFeedThrough(S, 0, 1);ssSetInputPortWidth(S, 1, 1);ssSetInputPortRequiredContiguous(S, 1, true);ssSetInputPortDirectFeedThrough(S, 1, 1);ssSetInputPortWidth(S, 2, 1);ssSetInputPortRequiredContiguous(S, 2, true);ssSetInputPortDirectFeedThrough(S, 2, 1);ssSetInputPortWidth(S, 3, 1);ssSetInputPortRequiredContiguous(S, 3, true);ssSetInputPortDirectFeedThrough(S, 3, 1);if (!ssSetNumOutputPorts(S, 3)) return;ssSetOutputPortWidth(S, 0, 1);ssSetOutputPortWidth(S, 1, 1);ssSetOutputPortWidth(S, 2, 1);ssSetNumSampleTimes(S, 1);ssSetNumRWork(S, 0);ssSetNumIWork(S, 0);ssSetNumPWork(S, 0);ssSetNumModes(S, 0);ssSetNumNonsampledZCs(S, 0);/* Specify the sim state compliance to be same as a built-in block */ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);ssSetOptions(S, 0); }/* Function: mdlInitializeSampleTimes =========================================* Abstract:* This function is used to specify the sample time(s) for your* S-function. You must register the same number of sample times as* specified in ssSetNumSampleTimes.*/ static void mdlInitializeSampleTimes(SimStruct *S) {ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);ssSetOffsetTime(S, 0, 0.0); }#define MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */ #if defined(MDL_INITIALIZE_CONDITIONS)/* Function: mdlInitializeConditions ========================================* Abstract:* In this function, you should initialize the continuous and discrete* states for your S-function block. The initial states are placed* in the state vector, ssGetContStates(S) or ssGetRealDiscStates(S).* You can also perform any other initialization activities that your* S-function may require. Note, this routine will be called at the* start of simulation and if it is present in an enabled subsystem* configured to reset states, it will be call when the enabled subsystem* restarts execution to reset the states.*/static void mdlInitializeConditions(SimStruct *S){} #endif /* MDL_INITIALIZE_CONDITIONS */#define MDL_START /* Change to #undef to remove function */ #if defined(MDL_START) /* Function: mdlStart =======================================================* Abstract:* This function is called once at start of model execution. If you* have states that should be initialized once, this is the place* to do it.*/ static void mdlStart(SimStruct *S) {real_T *pFxKappa = mxGetPr(TIRE_FX_KAPPA(S));real_T *pFxLoad = mxGetPr(TIRE_FX_LOAD(S));real_T *pFx = mxGetPr(TIRE_FX(S));real_T *pFyAlpha = mxGetPr(TIRE_FY_ALPHA(S));real_T *pFyLoad = mxGetPr(TIRE_FY_LOAD(S));real_T *pFy = mxGetPr(TIRE_FY(S));int_T *dFx = mxGetDimensions(TIRE_FX(S));int_T *dFy = mxGetDimensions(TIRE_FY(S));int_T *dMz = mxGetDimensions(TIRE_MZ(S));TireFxSize[0] = dFx[0];TireFxSize[1] = dFx[1];TireFySize[0] = dFy[0];TireFySize[1] = dFy[1];TireMzSize[0] = dMz[0];TireMzSize[1] = dMz[1];PeakValues(TireFxKappaPeak, pFxKappa, pFxLoad, pFx, TireFxSize);PeakValues(TireFyAlphaPeak, pFyAlpha, pFyLoad, pFy, TireFySize); } #endif /* MDL_START *//* Function: mdlOutputs =======================================================* Abstract:* In this function, you compute the outputs of your S-function* block.*/ static void mdlOutputs(SimStruct *S, int_T tid) {//Paramtersreal_T *pFxKappa = mxGetPr(TIRE_FX_KAPPA(S));real_T *pFxLoad = mxGetPr(TIRE_FX_LOAD(S));real_T *pFx = mxGetPr(TIRE_FX(S));real_T *pFyAlpha = mxGetPr(TIRE_FY_ALPHA(S));real_T *pFyLoad = mxGetPr(TIRE_FY_LOAD(S));real_T *pFy = mxGetPr(TIRE_FY(S));real_T *pMzAlpha = mxGetPr(TIRE_MZ_ALPHA(S));real_T *pMzLoad = mxGetPr(TIRE_MZ_LOAD(S));real_T *pMz = mxGetPr(TIRE_MZ(S));real_T *pCamLoad = mxGetPr(TIRE_CAM_LOAD(S));real_T *pCamCoef = mxGetPr(TIRE_CAM_COEF(S));//Inputsreal_T *uTireFz = (const real_T*) ssGetInputPortSignal(S,0); //Vertical Loadreal_T *uAlpha = (const real_T*) ssGetInputPortSignal(S,1); //Side Slip Anglereal_T *uGamma = (const real_T*) ssGetInputPortSignal(S,2); //Inclination Angle(Camber angle)real_T *uKappa = (const real_T*) ssGetInputPortSignal(S,3); //Longitudinal slip ratio//Outputsreal_T *yTireFx = ssGetOutputPortSignal(S,0);real_T *yTireFy = ssGetOutputPortSignal(S,1);real_T *yTireMz = ssGetOutputPortSignal(S,2);//Variables real_T deltaX, deltaY;real_T deltaXMax, deltaYMax;real_T deltaXStar, deltaYStar, deltaStar;real_T alphaMax, kappaMax;real_T alpha2, kappa2;real_T tireFx0, tireFy0, tireMz0;real_T tireFxNorm0, tireFyNorm0;real_T theta,lambda;real_T tireFx, tireFy, tireFz, tireMz;real_T alpha, kappa, gamma;real_T alphaK, gammaK;real_T tmp, tmp2, sgn;real_T epsilon;tireFz = uTireFz[0];alpha = uAlpha[0];kappa = uKappa[0];gamma = uGamma[0];//Camber Effect (Simple)LinearSpline(&gammaK, pCamLoad, pCamCoef, TireCamSize, tireFz);BiLinearSpline(&tmp, pFyAlpha, pFyLoad, pFy, TireFySize, pFyAlpha[2], tireFz);alphaK = tmp / pFyAlpha[2];tmp = ABS(gammaK/alphaK);alpha = alpha + gamma * tmp;//Combined Slip Theorytmp = 1.0 + kappa;tmp = (tmp < ZERO) ? ZERO : tmp;deltaX = -kappa / tmp;deltaY = (real_T)tan(alpha * PI / 180.0) / tmp;LinearSpline(&kappaMax, pFxLoad, TireFxKappaPeak, TireFxSize[1], tireFz); //Slip ratio for the Max FxLinearSpline(&alphaMax, pFyLoad, TireFyAlphaPeak, TireFySize[1], tireFz); //Slip angle for the Max FydeltaXMax = -kappaMax / (1 + kappaMax);deltaYMax = (real_T)tan(alphaMax * PI / 180.0) / (1 + kappaMax);deltaXStar = deltaX / deltaXMax;deltaYStar = deltaY / deltaYMax;deltaStar = (real_T)sqrt(deltaXStar * deltaXStar + deltaYStar * deltaYStar);sgn = SIGN(deltaX);kappa2 = -deltaStar * deltaXMax / (1 - deltaStar * deltaXMax * sgn);BiLinearSpline(&tireFx0, pFxKappa, pFxLoad, pFx, TireFxSize, kappa2, tireFz);alpha2 = (real_T)atan(deltaStar * deltaYMax) * 180 / PI;BiLinearSpline(&tireFy0, pFyAlpha, pFyLoad, pFy, TireFySize, alpha2, tireFz);epsilon = (deltaStar > 1) ? 1 : deltaStar;tmp = (deltaStar < ZERO) ? ZERO : deltaStar;tireFxNorm0 = tireFx0 - epsilon * (tireFx0 - tireFy0) * (deltaYStar / tmp) * (deltaYStar / tmp);tireFyNorm0 = tireFy0 - epsilon * (tireFy0 - tireFx0) * (deltaXStar / tmp) * (deltaXStar / tmp);tmp = ABS(deltaX);tmp = (tmp < ZERO) ? ZERO : tmp;theta = (real_T)atan(deltaY / tmp);lambda = theta;sgn = SIGN(deltaXStar);tireFx = tireFxNorm0 * cos(lambda) * sgn;tireFy = -tireFyNorm0 * sin(lambda);BiLinearSpline(&tireMz0, pMzAlpha, pMzLoad, pMz, TireMzSize, alpha2, tireFz);tmp = ABS(tireFy);sgn = SIGN(alpha);tmp2 = (tireFyNorm0 < ZERO) ? ZERO : tireFyNorm0;tireMz = tireMz0 * tmp / tmp2 * sgn;yTireFx[0] = tireFx;yTireFy[0] = tireFy;yTireMz[0] = tireMz; }static void LinearSpline(real_T* outY, const real_T* dataX, const real_T* dataY, const int_T length, const real_T inX) {int_T i;int_T cx1, cx2;real_T x1, x2, y1, y2;real_T tmp;//x positionif(inX <= dataX[0]){cx1 = 0;cx2 = 1;}else if(inX >= dataX[length-1]){cx1 = length - 2;cx2 = length - 1;}else{for(i=0; i<length-1; i++){if (inX >= dataX[i] && inX < dataX[i + 1]){cx1 = i;cx2 = i + 1;break;}}}//rangex1 = dataX[cx1];x2 = dataX[cx2];y1 = dataY[cx1];y2 = dataY[cx2];//Linear Spline Equationtmp = x2 - x1;*outY = y1 * (x2 - inX) / tmp + y2 * (inX - x1) / tmp; }static void BiLinearSpline(real_T* outZ, const real_T* dataX, const real_T* dataY, const real_T* dataZ, const int_T* size, const real_T inX, const real_T inY) {int_T i;int_T cx1, cx2, cy1, cy2;real_T x1, x2, y1, y2, z11, z12, z21, z22;real_T tmp;//x positionif(inX <= dataX[0]){cx1 = 0;cx2 = 1;}else if(inX >= dataX[size[0]-1]){cx1 = size[0] - 2;cx2 = size[0] - 1;}else{for(i=0; i<size[0]-1; i++){if (inX >= dataX[i] && inX < dataX[i + 1]){cx1 = i;cx2 = i + 1;break;}}}//y positionif(inY <= dataY[0]){cy1 = 0;cy2 = 1;}else if(inY >= dataY[size[1]-1]){cy1 = size[1] - 2;cy2 = size[1] - 1;}else{for(i=0; i<size[1]-1; i++){if (inY >= dataY[i] && inY < dataY[i + 1]){cy1 = i;cy2 = i + 1;break;}}}//rangex1 = dataX[cx1];x2 = dataX[cx2];y1 = dataY[cy1];y2 = dataY[cy2];z11 = dataZ[cy1 * size[0] + cx1];z12 = dataZ[cy2 * size[0] + cx1];z21 = dataZ[cy1 * size[0] + cx2];z22 = dataZ[cy2 * size[0] + cx2];//BiLinear Spline Equationtmp = (x2 - x1) * (y2 - y1);*outZ = z11 * (x2 - inX) * (y2 - inY) / tmp + z21 * (inX - x1) * (y2 - inY) / tmp+ z12 * (x2 - inX) * (inY - y1) / tmp + z22 * (inX - x1) * (inY - y1) / tmp;}static void PeakValues(real_T* outX, const real_T* dataX, const real_T* dataY, const real_T* dataZ, const int_T* size) {int_T i, j;real_T x, z;int_T step;real_T stepSize;real_T tmpX, tmpY, tmpZ;step = 500;stepSize = (dataX[size[0] - 1] - dataX[0]) / (real_T)step;for(j=0; j<size[1]; j++){tmpY = dataY[j];x = dataX[0];z = dataZ[j*size[0]];for(i=0; i<step; i++){tmpX = (i + 1) * stepSize + dataX[0];BiLinearSpline(&tmpZ, dataX, dataY, dataZ, size, tmpX, tmpY);if(tmpZ > z){x = tmpX;z = tmpZ;}}outX[j] = x;}}#define MDL_UPDATE /* Change to #undef to remove function */ #if defined(MDL_UPDATE)/* Function: mdlUpdate ======================================================* Abstract:* This function is called once for every major integration time step.* Discrete states are typically updated here, but this function is useful* for performing any tasks that should only take place once per* integration step.*/static void mdlUpdate(SimStruct *S, int_T tid){} #endif /* MDL_UPDATE */#define MDL_DERIVATIVES /* Change to #undef to remove function */ #if defined(MDL_DERIVATIVES)/* Function: mdlDerivatives =================================================* Abstract:* In this function, you compute the S-function block's derivatives.* The derivatives are placed in the derivative vector, ssGetdX(S).*/static void mdlDerivatives(SimStruct *S){} #endif /* MDL_DERIVATIVES *//* Function: mdlTerminate =====================================================* Abstract:* In this function, you should perform any actions that are necessary* at the termination of a simulation. For example, if memory was* allocated in mdlStart, this is the place to free it.*/ static void mdlTerminate(SimStruct *S) { }/*======================================================** See sfuntmpl_doc.c for the optional S-function methods **======================================================*//*=============================** Required S-function trailer **=============================*/#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else #include "cg_sfun.h" /* Code generation registration function */ #endif
4. 轮胎稳态实验
实验采用CarSim的205/55 R16轮胎数据,输入变量为滑移率,值从-1到1。Simulink模型见下图:
该S-Function模型与CarSim自带轮胎的结果如下:
从以上结果可以看出,该轮胎模型与CarSim的内部轮胎模型结果基本一致。
5. 整车双车道切换实验
实验是使用CarSim与Simulink联合仿真(方法参见博文: CarSim与Simulink联合仿真 )。
由于该模型没有考虑滚动摩擦和轮胎力的滞后,所以在测试CarSim的Internal Tire时,需要将轮胎的滚动摩擦系数Rr_c和Rr_v设成非常小的值,并将Tire Model Option设为Internal Table Model with Simple Camber。
测试Simulink模型时,CarSim做如下设置:
Simulink模型如下:
实验结果:
下图为侧向位移,S-Function结果与CarSim的完全一致,说明本轮胎模型可以较好的完成整车测试任务。
纵向力
侧向力
回转力矩
由对比可知,结果基本和CarSim自带的轮胎模型一致。
参考文献:
1. CarSim Tire Model 帮助文档
2. A New Tire Model with an Application in Vehicle Dynamics Studies, Bakker E,Pacejka H B,Lidner L.A.
转载于:https://www.cnblogs.com/xpvincent/archive/2013/04/01/2994480.html
基于实验数据的轮胎模型相关推荐
- 【电信学】【2009.06】基于实验数据的参考MIMO天线构型性能研究
本文为芬兰赫尔辛基理工大学(作者:Mònica Salicrú Cortés)的硕士论文,共87页. 近年来,多输入多输出(MIMO)系统的性能已经从理论上得到了很好的验证.通过在无线链路的两端引入一 ...
- H.B.Pacejke轮胎模型(魔术公式)
轮胎的非线性特性对汽车的转向特性及行驶稳定性有非常重要的影响.进行汽车控制研究往往要建立精确的轮胎模型.目前应用比较广泛的轮胎模型有: Fiala轮胎模型 UA轮胎模型 郭孔辉轮胎模型(幂指数公式) ...
- 虚幻3载具(Vehicle)轮胎模型
虚幻3有丰富的车辆系统,而载具具有物理系统的支持,虚幻3中的车辆体现在物理系统支持的方面主要是从车辆的轮胎入手.而车辆的轮胎使用的物理模型是魔术公式.只要使用魔术公式的轮胎模型主要有Pacejka ' ...
- 机器学习实验笔记-基于信用卡数据建立行为评分模型的机器学习方法
基于信用卡数据建立行为评分模型的机器学习方法 很久之前的一个答疑, 应该不会再影响评分了, 记录以供复习. 数据集与代码放在CSDN下载区域, 也可以留言索要. https://download.cs ...
- 切削力matlab数据处理,基于MATLAB的切削力测量实验数据的处理及分析
基于MATLAB 的切削力测量实验数据的处理及分析 卞化梅 , 牛小铁 , 陈金英 , 郭 勇 (北京工业职业技术学院 , 北京 100042) 摘 要 : 以曲面铣削加工实验数据的处理为例 ,介绍了 ...
- 基于分子对接与体外实验数据的一致性研究预测出槲皮素衍生物可以为α-Glucosidase 新的抑制剂
摘要:本文通过运用Discovery Studio中的CDOCKER方法,验证了α-Glucosidase 抑制剂与体外实验数据的一致性,并预测出槲皮素衍生物(compound 7)可以作为潜在α-G ...
- pandas基于时序数据计算模型预测推理需要的统计数据(累计时间、长度变化、变化率、方差、均值、最大、最小等):范围内的统计量、变化率、获得数据集最后的几条数据的统计量、变化率、获得范围内的统计量
pandas基于时序数据计算模型预测推理需要的统计数据(累计时间.长度变化.变化率.方差.均值.最大.最小等):范围内的统计量.变化率.获得数据集最后的几条数据的统计量.变化率.获得范围内的统计量 目 ...
- R语言基于自定义函数构建xgboost模型并使用LIME解释器进行模型预测结果解释:基于训练数据以及模型构建LIME解释器解释一个iris数据样本的预测结果、LIME解释器进行模型预测结果解释并可视化
R语言基于自定义函数构建xgboost模型并使用LIME解释器进行模型预测结果解释:基于训练数据以及模型构建LIME解释器解释一个iris数据样本的预测结果.LIME解释器进行模型预测结果解释并可视化 ...
- R语言基于自定义函数构建xgboost模型并使用LIME解释器进行模型预测结果解释:基于训练数据以及模型构建LIME解释器解释多个iris数据样本的预测结果、使用LIME解释器进行模型预测结果解释
R语言基于自定义函数构建xgboost模型并使用LIME解释器进行模型预测结果解释:基于训练数据以及模型构建LIME解释器解释多个iris数据样本的预测结果.使用LIME解释器进行模型预测结果解释并可 ...
最新文章
- Kafka源码剖析 —— 网络I/O篇 —— 浅析KafkaSelector
- Connect模块解析 转载
- wxpython富文本_Python实例讲解 -- wxpython 基本的控件 (文本)
- pytorch 忽略层权重
- Key Components and Internals of Spring Boot Framework--转
- php sdk微信,GitHub - swayer/wechat-php-sdk: 微信公众平台 PHP SDK
- DFS--POJ 1190 生日蛋糕
- Web 的MSN,可以不用装客户端
- python高级含金量技巧_2020年最新Python开发的高级技巧,面试必学
- 【SimpleITK】胸部CT数据3D space归一化,以及3D plot
- Html 5 Input type=range 滑动条
- android adb sdk下载地址,Android SDK 下载和安装
- 视频监控安防平台-国标35114(GB35114)A级检测
- C语言学习-翁凯(第十章笔记)
- Word2010经常莫名其妙无法撤销
- 感染 <SCRIPT Language=VBScript> DropFileName = “svchost.exe” Ramnit 蠕虫病毒 HTML清除工具
- 大疆精灵4航测输出正摄影和三维模型教程
- js删除json中指定的元素
- [UE4]Epic Games Launcher,Intall failed. code:0以及下载慢的问题
- 利用文件的md5值查重并删除重复的文件
热门文章
- java用输入流创建数据文件_java开发知识IO知识之输入输出流以及文件
- python2没有pip命令_解决Windows下python和pip命令无法使用的问题
- android 判断服务是否活动,Android:我如何获得当前的前台活动(从服务)?
- python计算长方体体积编程_计算体积 编程创建一个Box类(长方体) 联合开发网 - pudn.com...
- linux ls 时间显示时间格式,ls -l显示的日期格式如何设定?
- linux nand 坏块_韦东山-NAND 上面都是坏块怎么办啊? - 百问网嵌入式问答社区
- 怎样手动给无线网设置一个DNS服务器地址,无线网的dns怎样设置.docx
- HTML的不同版本区别,HTML4.0、XHTML、HTML5每个版本之间有什么区别
- zstd安装_在ARM架构服务器上编译Greenplum6并制作rpm安装包
- springboot完成进度条_Springboot从0开始第一周