主要内容

创建IDNLGREY模型文件

这个例子展示了如何为非线性灰盒模型编写ODE文件作为MATLAB和C MEX文件。

灰盒建模在概念上不同于黑盒建模,因为它涉及更全面的建模步骤。对于IDNLGREY(非线性灰盒模型对象;(IDGREY的非线性版本),这一步包括创建一个ODE文件,也称为“模型文件”。ODE文件指定状态的右边,以及通常通过物理第一原理建模得到的输出方程。在本例中,我们将集中讨论将其实现为MATLAB文件或C MEX文件的一般方面。

IDNLGREY模型文件

IDNLGREY支金宝app持对非线性模型结构中的参数和初始状态的估计,并将其写在以下显式状态空间形式(所谓的输出误差,OE形式,命名为噪声e(t)仅以加性方式影响模型结构的输出):

xn(t) = F(t, x(t), u(t), p1,…, pNpo);x(0) = X0;

y(t) = H(t, x(t), u(t), p1,…, pNpo) + e(t)

对于离散时间结构,xn(t) = x(t +Ts),其中Ts为采样时间,对于连续时间结构,xn(t) = d/dt x(t)。此外,F(.)和H(.)是任意线性或非线性函数,分别具有Nx(状态数)和Ny(输出数)分量。任意一个模型参数p1,…, pNpo和初始状态向量X(0)都可以估计出来。值得强调的是

  1. 时间序列建模,即没有外源输入信号u(t)的建模,和

  2. 静态建模,即没有任何状态的建模x(t)

是IDNLGREY支持的两种特殊情况。金宝app(有关这两个建模类别的示例,请参阅idnlgreydemo3和idnlgreydemo5教程)。

要执行的第一个IDNLGREY建模步骤总是实现一个MATLAB或C MEX模型文件,指定如何更新状态和计算输出。更重要的是,用户必须编写一个模型文件MODFILENAME。m或MODFILENAME.c,使用以下输入和输出参数定义(注意,MATLAB和C MEX类型的模型文件都需要这种形式)

[dx, y] = MODFILENAME(t, x, u, p1, p2,…, pNpo, FileArgument)

MODFILENAME可以是任意用户选择的MATLAB或C mex文件的文件名,例如,参见twotanks_m。M, pendulum_c.c等。这个文件应该定义为返回两个输出:

  • dx:状态空间方程的右边(一个有Nx个实项的列向量;[]用于静态模型)

  • y:输出方程的右边s(一个有Ny个实项的列向量)

并且它应该接受3+Npo(+1)输入参数,如下所示:

  • T:当前时间

  • X: t时刻的状态向量(静态模型[])

  • U:时间序列模型t时刻的输入向量([])

  • P1, p2,…, pNpo:单个参数(可以是实标量、列向量或二维矩阵);Npo在这里是参数对象的数量,对于具有标量参数的模型,它与参数Np的数量一致

  • FileArgument:模型文件的可选输入

在接下来的讨论中,我们将重点讨论使用MATLAB语言或C-MEX文件编写模型。但是,IDNLGREY也支持p文件(使用MAT金宝appLAB命令“pcode”获得的受保护的MATLAB文件)和函数句柄。事实上,不仅可以使用C MEX模型文件,也可以使用Fortran MEX文件。有关后者的更多信息,请参阅MATLAB文档中的外部接口。

应该实现什么样的模型文件?这个问题的答案实际上取决于模型的使用。

使用MATLAB语言实现(产生*。M文件)有一些明显的优点。首先,可以避免耗时的低级编程,更多地集中在建模方面。其次,MATLAB及其工具箱中可用的任何函数都可以直接在模型文件中使用。第三,这样的文件将更小,无需任何修改,所有内置的MATLAB错误检查将自动执行。此外,这是在没有任何代码编译的情况下获得的。

C MEX建模要复杂得多,需要有关C编程语言的基本知识。使用C MEX模型文件的主要优点是提高了执行速度。我们的一般建议是,当模型将被多次使用时,当使用大型数据集时,和/或当模型结构包含大量计算时,采用C MEX建模。从使用MATLAB文件开始,然后转向C MEX对应文件通常是值得的。

IDNLGREY模型文件用MATLAB语言编写

说了这些,让我们接下来进入MATLAB文件建模,并使用非线性二阶模型结构,描述一个双罐系统,作为一个例子。有关建模细节,请参阅idnlgreydemo2。twotanks_m的内容。M的值如下。

类型twotanks_m.m
function [dx, y] = twotanks_m(t, x, u, A1, k, A1, g, A2, A2, varargin) % twotanks_m双罐系统。版权所有2005-2006 The MathWorks, Inc. %输出方程。Y = x(2);%水位,下水箱。%状态方程。dx = [1/A1*(k*u(1)-a1*√(2*g*x(1)));…%上槽水位。1 / A2 * a1 *√(2 * g * x (1)) A2 * 12 + (2 * g * x(2)))……%水位,下水箱。 ];

在函数头中,我们在这里找到所需的t、x和u输入参数,后面跟着六个标量模型参数,A1、k、A1、g、A2和A2。在MATLAB文件案例中,最后一个输入参数应该始终是varargin,以支持可选模型文件输入参数FileArgument的传递。金宝app在IDNLGREY模型对象中,FileArgument存储为可能包含任何类型数据的单元格数组。FileArgument的第一个元素是通过varargin{1}{1}访问的。

变量和参数以标准的MATLAB方式引用。第一个状态是x(1),第二个状态是x(2),输入是u(1)(如果是标量,则只输入u),标量参数可以通过它们的名称(A1, k, A1, g, A2和A2)简单地访问。向量参数和矩阵参数的单个元素分别被访问为P(i)(向量参数P的元素i)和P(i, j)(矩阵参数P的第i行和第j列的元素)。

IDNLGREY C MEX模型文件

编写C MEX模型文件比编写MATLAB模型文件更复杂。为简化该步骤,建议将已有的IDNLGREY C MEX模型模板复制到“MODFILENAME.c”目录下。此模板包含基本源代码以及关于如何为特定应用程序定制代码的详细说明。通过在MATLAB命令提示符中输入以下命令可以找到模板文件的位置。

fullfile(matlabroot, 'toolbox', 'ident', 'nlident', 'IDNLGREY_MODEL_TEMPLATE.c')

对于两个坦克的例子,这个模板被复制到twotanks_c.c。经过一些初始修改和配置(如下所述)后,输入状态和输出方程,从而产生以下C MEX源代码。

类型twotanks_c.c
/*版权所有2005-2015 The MathWorks, Inc. */ /*作者:Peter Lindskog*/ /*包含库。*/ #include " mexico .h" #include  /*在这里指定输出数。*/ #定义NY 1 /*状态方程。*/ void compute_dx(double *dx, double t, double *x, double *u, double *p, const mxArray *auxvar){/*检索模型参数。*/ double *A1, *k, *A1, *g, *A2, *A2;A1 = p[0];/*上槽区。*/ k = p[1];/*泵常数。 */ a1 = p[2]; /* Upper tank outlet area. */ g = p[3]; /* Gravity constant. */ A2 = p[4]; /* Lower tank area. */ a2 = p[5]; /* Lower tank outlet area. */ /* x[0]: Water level, upper tank. */ /* x[1]: Water level, lower tank. */ dx[0] = 1/A1[0]*(k[0]*u[0]-a1[0]*sqrt(2*g[0]*x[0])); dx[1] = 1/A2[0]*(a1[0]*sqrt(2*g[0]*x[0])-a2[0]*sqrt(2*g[0]*x[1])); } /* Output equation. */ void compute_y(double *y, double t, double *x, double *u, double **p, const mxArray *auxvar) { /* y[0]: Water level, lower tank. */ y[0] = x[1]; } /*----------------------------------------------------------------------- * DO NOT MODIFY THE CODE BELOW UNLESS YOU NEED TO PASS ADDITIONAL INFORMATION TO COMPUTE_DX AND COMPUTE_Y To add extra arguments to compute_dx and compute_y (e.g., size information), modify the definitions above and calls below. *-----------------------------------------------------------------------*/ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { /* Declaration of input and output arguments. */ double *x, *u, **p, *dx, *y, *t; int i, np; size_t nu, nx; const mxArray *auxvar = NULL; /* Cell array of additional data. */ if (nrhs < 3) { mexErrMsgIdAndTxt("IDNLGREY:ODE_FILE:InvalidSyntax", "At least 3 inputs expected (t, u, x)."); } /* Determine if auxiliary variables were passed as last input. */ if ((nrhs > 3) && (mxIsCell(prhs[nrhs-1]))) { /* Auxiliary variables were passed as input. */ auxvar = prhs[nrhs-1]; np = nrhs - 4; /* Number of parameters (could be 0). */ } else { /* Auxiliary variables were not passed. */ np = nrhs - 3; /* Number of parameters. */ } /* Determine number of inputs and states. */ nx = mxGetNumberOfElements(prhs[1]); /* Number of states. */ nu = mxGetNumberOfElements(prhs[2]); /* Number of inputs. */ /* Obtain double data pointers from mxArrays. */ t = mxGetPr(prhs[0]); /* Current time value (scalar). */ x = mxGetPr(prhs[1]); /* States at time t. */ u = mxGetPr(prhs[2]); /* Inputs at time t. */ p = mxCalloc(np, sizeof(double*)); for (i = 0; i < np; i++) { p[i] = mxGetPr(prhs[3+i]); /* Parameter arrays. */ } /* Create matrix for the return arguments. */ plhs[0] = mxCreateDoubleMatrix(nx, 1, mxREAL); plhs[1] = mxCreateDoubleMatrix(NY, 1, mxREAL); dx = mxGetPr(plhs[0]); /* State derivative values. */ y = mxGetPr(plhs[1]); /* Output values. */ /* Call the state and output update functions. Note: You may also pass other inputs that you might need, such as number of states (nx) and number of parameters (np). You may also omit unused inputs (such as auxvar). For example, you may want to use orders nx and nu, but not time (t) or auxiliary data (auxvar). You may write these functions as: compute_dx(dx, nx, nu, x, u, p); compute_y(y, nx, nu, x, u, p); */ /* Call function for state derivative update. */ compute_dx(dx, t[0], x, u, p, auxvar); /* Call function for output update. */ compute_y(y, t[0], x, u, p, auxvar); /* Clean up. */ mxFree(p); }

让我们浏览一下这个文件的内容。首先观察一下,我们可以将编写C MEX模型文件的工作分为四个独立的子步骤,最后一个是可选的:

  1. 包含c库和输出数量的定义。

  2. 写出计算状态方程右边的函数compute_dx。

  3. 写出计算输出方程右边的函数compute_y。

  4. 可选地更新主接口函数,其中包括基本错误检查功能、创建和处理输入输出参数的代码,以及对compute_dx和compute_y的调用。

在我们更详细地讨论这些子步骤之前,让我们简要地评论一下C编程语言的几个一般特性。

  1. 高精度变量(IDNLGREY对象的所有输入、状态、输出和参数)应该定义为数据类型“double”。

  2. 放在变量名或参数名前面的一元*操作符就是所谓的解引用操作符。c声明"double *A1;"指定A1是一个指向双精度变量的指针。指针结构是C语言中的一个概念,它并不总是那么容易理解。幸运的是,如果compute_y和compute_dx的输出/输入变量的声明没有改变,并且所有解包的模型参数都在内部用*声明,那么就不需要从IDNLGREY建模的角度了解更多关于指针的知识。

  3. compute_y和compute_dx都是首先声明和实现的,然后在主接口函数中调用它们。在声明中,关键字“void”显式声明不返回任何值。

有关C编程语言的更多细节,请参阅这本书

b·w·克尼根和d·里奇。C编程语言,第二

版,普伦蒂斯霍尔,1988年。

在第一个子步骤中,我们首先包含c库“mexico .h”(必需)和“math.h”(更高级的数学必需)。输出的数量也使用标准的C-define声明每个建模文件:

/*包含库。* /

# include“mex.h”

# include“math.h”

/*在这里指定输出的数量。* /

#定义纽约1

如果需要,还可以包含比上述更多的c库。

每当任何状态或输出方程包含更高级的数学时,如三角函数和平方根函数,都必须包括"math.h"库。下面是"math.h"中包含的函数列表,以及MATLAB中的对应函数:

c函数MATLAB函数

========================================

Sin cos tan Sin cos tan

Asin, acos, atan Asin, acos, atan

Sinh cosh tanh Sinh cosh tanh

Exp log log10 Exp log log10

(x, y) x^y

√√

晶圆厂的腹肌

请注意,MATLAB函数比相应的c函数更通用,例如,前者处理复数,而后者不处理复数。

接下来,在文件中,我们发现用于更新状态的函数compute_dx和输出compute_y。这两个函数都包含参数列表,在位置1处有要计算的输出(dx或y),之后是分别计算状态和输出方程右侧所需的所有变量和参数。

所有参数都包含在参数数组p中。compute_dx和compute_y中的第一步是解包并命名后续方程中使用的参数。在twotanks_c.c中,compute_dx声明了六个参数变量,它们的值是据此确定的:

/*检索模型参数。* /

双*A1, *k, *A1, *g, *A2, *A2;

A1 = p[0];/*上槽区。* /

K = p[1];/*泵常数。* /

A1 = p[2];/*上槽出口区域。* /

G = p[3];/*重力常数。* /

A2 = p[4];/*下槽面积。* /

A2 = p[5];/*下槽出口区域。* /

另一方面,Compute_y不需要任何参数来计算输出,因此不需要检索模型参数。

与C语言一样,数组的第一个元素存储在位置0。因此,C中的dx[0]对应于MATLAB中的dx(1)(如果它是标量,则仅为dx),输入u[0]对应于u(或u(1)),参数A1[0]对应于A1,以此类推。

在上面的例子中,我们只使用标量参数,在这种情况下,参数的总数Np等于参数对象的数量Npo。如果模型中包含任何向量或矩阵参数,则Npo < Np。

标量参数被引用为P[0] (P(1)或MATLAB文件中的P),第i:第一个向量元素被引用为P[i-1] (MATLAB文件中的P(i))。传递给C MEX模型文件的矩阵是不同的,因为列以明显的顺序堆叠在一起。因此,如果P是一个2 × 2矩阵,那么P(1,1)被称为P[0], P(2,1)被称为P[1], P(1,2)被称为P[2], P(2,2)被称为P[3]。参见“非线性灰盒识别教程:一个工业三自由度机器人:使用向量/矩阵参数的MIMO系统的C MEX-File建模”,idnlgreydemo8,其中使用了标量、向量和矩阵参数。

状态和输出更新函数还可以包括其他计算,而不仅仅是检索参数和计算右边表达式。为了加快执行速度,可以声明并使用中间变量,这些变量的值将在接下来的表达式中多次使用。上面提到的机器人教程idnlgreydemo8就是一个很好的例子。

compute_dx和compute_y也能够处理一个可选的FileArgument。FileArgument数据在auxvar变量中传递给这些函数,这样就可以获得FileArgument的第一个组件(单元格数组)

mxArray* auxvar1 = mxGetCell(auxvar, 0);

这里,mxArray是一个MATLAB定义的数据类型,可以在C mex文件和MATLAB之间交换数据。反过来,auxvar1可能包含任何数据。auxvar1的解析、检查和使用必须在这些函数中单独处理,由模型文件设计器来实现该功能。让我们在这里只参考关于外部接口的MATLAB文档,以获得关于操作mxArrays的函数的更多信息。idnlgreydemo6“非线性灰盒识别教程:信号传输系统:使用可选输入参数的C MEX-文件建模”提供了如何使用可选C MEX模型文件参数的示例。

主界面功能几乎总是具有相同的内容,对于大多数应用程序不需要任何修改。原则上,唯一需要考虑更改的部分是调用compute_dx和compute_y的地方。对于静态系统,可以省略对compute_dx的调用。在其他情况下,可能希望只传递状态和输出方程中引用的变量和参数。例如,在双罐系统的输出方程中,只使用了一种状态,可以很好地将输入参数列表缩短为

Void compute_y(double *y, double *x)

并在主接口函数中调用compute_y为

compute_y (y、x);

还可以扩展compute_dx和compute_y的输入参数列表,以包括在接口函数中推断出的其他变量。下面的整数变量被计算出来,因此可能被传递:nu(输入的数量),nx(状态的数量)和np(这里是参数对象的数量)。例如,在教程idnlgreydemo6中研究的模型中,nx被传递给compute_y。

必须先编译完整的C MEX模型文件,然后才能将其用于IDNLGREY建模。编译可以很容易地从MATLAB命令行完成

墨西哥人MODFILENAME.c

注意,必须在第一次使用mexo命令之前配置它。这也是通过MATLAB命令行实现的

墨西哥人设置

IDNLGREY模型对象

有了一个执行就绪的模型文件,就可以直接创建IDNLGREY模型对象,为其进行模拟、参数估计等。我们通过创建两个不同的IDNLGREY模型对象来举例说明这两个坦克系统,一个使用MATLAB编写的模型文件,另一个使用上面详细介绍的C MEX文件(注意这里C MEX模型文件已经编译)。

Order = [1 1 2];%模型订单[ny nu nx]。参数= [0.5;0.003;0.019;9.81;0.25;0.016);初始参数向量。InitialStates = [0;0.1);%初始状态的初始值。Nlgr_m = idnlgrey(“twotanks_m”,顺序,参数,InitialStates, 0)
nlgr_m =由'twotanks_m'定义的连续时间非线性灰盒模型(MATLAB文件):dx/dt = F(t, u(t), x(t), p1,…, p6) y(t) = H(t, u(t), x(t), p1,…, p6) + e(t),有1个输入,2个状态,1个输出,6个自由参数(从6个中)。状态:通过直接构造或转换创建。不估计。
Nlgr_cmex = idnlgrey(“twotanks_c”,顺序,参数,InitialStates, 0)
nlgr_cmex =由'twotanks_c' (MEX-file)定义的连续时间非线性灰盒模型:dx/dt = F(t, u(t), x(t), p1,…, p6) y(t) = H(t, u(t), x(t), p1,…, p6) + e(t),有1个输入,2个状态,1个输出,6个自由参数(从6个中)。状态:通过直接构造或转换创建。不估计。

结论

在本教程中,我们讨论了如何编写IDNLGREY MATLAB和C MEX模型文件。最后,我们通过列出当前可用的IDNLGREY模型文件以及使用它们的教程/案例研究来结束演示。为了简化进一步的比较,我们列出MATLAB(命名约定FILENAME_m.m)和C MEX模型文件(命名约定FILENAME_c.c),并在教程列中指出教程或案例研究中使用的建模方法类型。

教程/案例分析MATLAB文件C mexi文件

======================================================================

idnlgreydemo1 (MATLAB) dcmotor_m。m dcmotor_c.c

idnlgreydemo2 (C MEX) twotanks_m。m twotanks_c.c

idnlgreydemo3 (MATLAB) preys_m。m preys_c.c

(C MEX) preprey1_m。m predprey1_c.c

(C MEX) preprey2_m。m predprey2_c.c

idnlgreydemo4 (MATLAB) narendrali_m。m narendrali_c.c

idnlgreydemo5 (MATLAB) friction_m。m friction_c.c

idnlgreydemo6 (C MEX)信号传输。m signaltransmission_c.c

idnlgreydemo7 (C MEX) twobodies_m。m twobodies_c.c

idnlgreydemo8 (C MEX) robot_m. txt。m robot_c.c

idnlgreydemo9 (MATLAB) cstr_m。m cstr_c.c

idnlgreydemo10 (MATLAB)摆。m pendulum_c.c

idnlgreydemo11 (C MEX) vehicle_m. txt。m vehicle_c.c

idnlgreydemo12 (C MEX) aero_m。m aero_c.c

idnlgreydemo13 (C MEX) robotarm_m。m robotarm_c.c

这些模型文件的内容可以通过type FILENAME_m命令显示在MATLAB命令窗口中。m”或“type FILENAME_c.c”。所有模型文件都可以在下面的MATLAB命令返回的目录中找到。

Fullfile (matlabroot, 'toolbox', 'ident', 'iddemos', 'examples')

另请参阅

||

相关的话题