主要内容

每次实验估计模型参数(代码)

这个例子展示了如何使用多个实验来估计模型参数值的混合;有些是用所有实验来估计的有些是用单个实验来估计的。该示例还展示了如何配置与实验相关的参数值的估计实验。

你估计一个可充电电池的参数,基于在放电和充电的实验中收集的数据。

打开模型,获取实验数据

这个例子估计了一个简单的充电电池模型的参数,sdoBattery.模型输入为电池电流,模型输出为电池端电压,由电池充电状态计算得到。

open_system (“sdoBattery”);

这个模型是基于这个方程的

E 1 - 损失 V - K 马克斯 1 - 年代 年代

在方程:

E 为电池端电压,单位为伏特。

V 为电池恒压,单位为伏特。

K 为电池极化电阻,单位为欧姆。

马克斯 为以安培小时为单位的最大电池容量。

年代 为电池充电状态,1为充满,0为放电。电池的充电状态是由电池电流的积分计算出来的,电池的正电流指示放电,负电流指示充电。电池初始充电状态为 0 在安时。

损失 为充电时的压降,用电池恒压的分数表示。当电池放电时,这个值为零。

VKQmaxQ0处,损失是在模型工作区中定义的变量。

加载实验数据。对1.2V (6500mAh)电池进行了放电实验和充电实验。

负载sdoBattery_ExperimentData

的变量Charge_DataDCharge_Data加载到工作区中。第一列Charge_Data包含时间数据。第二列和第三列Charge_Data描述电池充电实验中的电流和电压。DCharge_Data结构类似,并包含电池放电实验的数据。

绘制实验数据

次要情节(221),情节(DCharge_Data (: 1) / 3600, DCharge_Data(:, 2)标题(“实验:放电”)包含(的时间(小时)) ylabel (“电流(A)”) subplot(223) plot(DCharge_Data(:,1)/3600,DCharge_Data(:,3)) xlabel(的时间(小时)) ylabel (“电压(V)”) subplot(222), plot(Charge_Data(:,1)/3600,Charge_Data(:,2)) title(实验:电荷的)包含(的时间(小时)) ylabel (“电流(A)”) subplot(224) plot(Charge_Data(:,1)/3600,Charge_Data(:,3)) xlabel(的时间(小时)) ylabel (“电压(V)”

图中包含4个轴对象。带有标题的轴对象1实验:放电包含一个类型为line的对象。axis对象2包含一个类型为line的对象。轴对象3,标题为实验:电荷包含一个类型为线的对象。axis对象4包含一个类型为line的对象。

定义估计实验

创建一个2元素的实验对象数组,以指定两个实验的测量数据。

创建电池放电实验的实验对象。测量到的电流数据在实验对象中指定为时间序列。

DCharge_Exp = sdo。实验(“sdoBattery”);

将输入数据(当前)指定为timeseries对象。

DCharge_Exp。InputData = timeseries (DCharge_Data (:, 2), DCharge_Data (: 1));

创建一个对象来指定测量的电压输出数据。

VoltageSig = 金宝appSimulink.SimulationData.Signal;VoltageSig。Name =“电压”;VoltageSig。BlockPath =“sdoBattery / SOC - >电压”;VoltageSig。PortType =“输出港”;VoltageSig。PortIndex = 1;VoltageSig。Values = timeseries(DCharge_Data(:,3),DCharge_Data(:,1));

将电压信号加到放电实验中作为预期输出数据。

DCharge_Exp。OutputData = VoltageSig;

指定实验中电池的初始充电状态。对电池充电状态进行了建模问(啊)块,它的初始值由变量指定Q0处.的参数Q0处变量,并将参数添加到实验中。Q0处是依赖于实验的,在放电和充电实验中假设不同的值。

Q0 = sdo.getParameterFromModel (“sdoBattery”“Q0处”);Q0处。Value = 6.5; Q0.Free = false;

Q0处。免费的被设置为因为初始电量是已知的,不需要估算。

添加Q0处参数的实验。

DCharge_Exp。参数= Q0处;

创建实验对象,用于存储充电实验数据。将测量到的电流输入和测量到的电压输出数据添加到对象中。

Charge_Exp = sdo。实验(“sdoBattery”);Charge_Exp。InputData = timeseries (Charge_Data (:, 2), Charge_Data (: 1));VoltageSig。Values = timeseries(Charge_Data(:,3),Charge_Data(:,1)); Charge_Exp.OutputData = VoltageSig;

实验中加入电池初始充电和充电损耗率参数。在本实验中,初始电荷(Q0处)是已知的(0ah),但充电损耗率(损失)是未知的。

Q0处。Value = 0; Loss = sdo.getParameterFromModel(“sdoBattery”“损失”);的损失。免费的=true; Loss.Minimum = 0; Loss.Maximum = 0.5; Charge_Exp.Parameters = [Q0;Loss];

的损失。免费的的值设置为true,以便损失估计。

将两个实验收集到一个向量中。

经验= [DCharge_Exp;Charge_Exp];

比较测量输出和初始模拟输出

使用第一个(放电)实验创建一个模拟场景并获得模拟输出。

模拟器= createSimulator (Exp (1));模拟器= sim(模拟器);

在记录的仿真数据中查找电压信号。

SimLog =找到(模拟器。LoggedData get_param (“sdoBattery”“SignalLoggingName”));电压(1)=找到(SimLog“电压”);

获得第二(充电)实验的模拟电压信号。

模拟器= createSimulator (Exp(2),模拟器);模拟器= sim(模拟器);SimLog =找到(模拟器。LoggedData get_param (“sdoBattery”“SignalLoggingName”));电压(2)=找到(SimLog,“电压”);

绘制测量和模拟数据。模型响应与实验输出数据不匹配。

次要情节(211)图(...电压(1).Values.Time / 3600、电压(1).Values.Data,...实验(1).OutputData.Values。时间/ 3600、Exp (1) .OutputData.Values.Data“-”。)标题(“放电实验:在评估前模拟和测量响应”) ylabel (“电压(V)”)传说(模拟电压的测量电压的“位置”“西南”

图中包含3个轴对象。axis对象1包含一个类型为line的对象。axis对象2包含一个类型为line的对象。轴对象3标题放电实验:估算前的模拟和测量响应包含2个类型为线的对象。这些对象代表模拟电压,测量电压。

次要情节(212)图(...电压(2).Values.Time / 3600、电压(2).Values.Data,...Exp (2) .OutputData.Values。时间/ 3600、Exp (2) .OutputData.Values.Data“-”。)标题(“充电实验:在评估前模拟和测量反应”)包含(的时间(小时)) ylabel (“电压(V)”)传说(模拟电压的测量电压的“位置”“东南”

指定估算参数

估计电池电压值V,电池极化电阻K,充电损耗率损失.的VK利用所有的实验数据进行参数估计损失参数仅使用充电数据进行估计。

选择电池电压V和电池的极化电阻K模型的参数。为这些参数指定最小和最大界限。

p = sdo.getParameterFromModel (“sdoBattery”, {“V”“K”});(1页)。最小值= 0;(1页)。最大= 2;(2页)。最小值= 1 e-6;(2页)。最大= 1 e 1;

得到experiment-specific损失参数来自实验。

s = getValuesToEstimate (Exp);

将所有要估计的参数分组。

v = (p, s)
v(1, - 1) =名字:“v”值:1.2000最低:0最大:2自由:1规模:2信息:[1 x1 struct] v(2, 1) =名字:“K”值:1.0000 e 03最低:1.0000 e-06最大:0.1000自由:1比例:0.0020信息:[1 x1 struct] v(3,1) =名字:“损失”值:0.0100最低:0最高:0.5000自由:1比例:0.0156信息:[1 x1 struct] 3 x1参数。连续

确定评估目标

创建一个估计目标函数,以评估使用估计参数值生成的模拟输出与测量数据的匹配程度。

使用带有一个输入参数的匿名函数来调用sdoBattery_Objective函数。我们将匿名函数传递给sdo.optimize,它在每次优化迭代时对函数进行计算。

estFcn = @(v) sdoBattery_Objective(v,模拟器,Exp);

sdoBattery_Objective功能:

  • 有一个输入参数,指定估计的电池参数值。

  • 具有一个输入参数,指定包含测量数据的实验对象。

  • 返回模拟输出和实验输出之间的误差向量。

sdoBattery_Objective函数需要两个输入,但是sdo.optimize要求具有一个输入参数的函数。为了解决这个问题,estFcn是一个带有一个输入参数的匿名函数,v,但它调用sdoBattery_Objective使用两个输入参数,v经验值

有关匿名函数的更多信息,请参见匿名函数

sdo.optimize命令最小化匿名函数的返回参数estFcn,即返回的残差sdoBattery_Objective.有关如何编写目标/约束函数的更多细节sdo.optimize命令,键入帮助sdoExampleCostFunction在MATLAB®命令提示符。

为了更详细地检查估计目标函数,类型编辑sdoBattery_Objective在MATLAB命令提示符处。

类型sdoBattery_Objective
sdoBattery_Objective函数用于将模型%输出与实验数据进行比较。|v|输入参数是估计模型参数值%和初始状态的向量。模拟器|输入参数是一个模拟对象,使用估计的参数值模拟模型。|Exp|输入参数包含估计实验数据。|val |返回参数包含关于%模型模拟结果与实验数据匹配程度的信息,并由|sdo %使用。优化|函数,估计模型参数。% %参见sdo。定义一个信号跟踪需求,以计算模型输出与实验数据的匹配程度。配置跟踪需求,以便%它返回跟踪误差残差(而不是%和平方误差),并且不对错误进行归一化。% r = sdo.requirements.SignalTracking;r.Type =“= =”; r.Method = 'Residuals'; r.Normalize = 'off'; %% % Update the experiments with the estimated parameter values. % Exp = setEstimatedValues(Exp,v); %% % Simulate the model and compare model outputs with measured experiment % data. % Error = []; for ct=1:numel(Exp) Simulator = createSimulator(Exp(ct),Simulator); Simulator = sim(Simulator); SimLog = find(Simulator.LoggedData,get_param('sdoBattery','SignalLoggingName')); Voltage = find(SimLog,'Voltage'); VoltageError = evalRequirement(r,Voltage.Values,Exp(ct).OutputData(1).Values); Error = [Error; VoltageError(:)]; end %% % Return the residual errors to the optimization solver. % vals.F = Error(:); end

估计的参数

使用sdo.optimize功能来估计电池参数值。

指定优化选项。估计函数sdoBattery_Objective返回模拟数据和实验数据之间的误差残差,并且不包含任何约束条件,使这个问题成为“lsqnonlin”求解器的理想问题。

选择= sdo.OptimizeOptions;opt.Method =“lsqnonlin”

估计的参数。

vOpt = sdo.optimize (estFcn, v,选择)
优化开始于01- 9 -2021 16:57:23一阶Iter f -count f(x)步长优化0 7 3272.22 11 14 619.356 0.1634 3.15e+05 2 21 411.131 0.2175 28.7 3 28 405.529 0.3838 2.16e+03 4 35 403.727 0.2767 15.2 5 42 403.379 0.1645 1.14e+03局部最小可能。Lsqnonlin停止的原因是相对于初始值的平方和的最终变化小于函数的容差值。vOpt(1, - 1) =名字:“V”值:1.3083最低:0最大:2自由:1规模:2信息:[1 x1 struct] vOpt(2, 1) =名字:“K”值:0.0010最低:1.0000 e-06最大:0.1000自由:1比例:0.0020信息:[1 x1 struct] vOpt(3,1) =名字:“损失”值:5.1801 e-05最低:0最高:0.5000自由:1比例:0.0156信息:[1 x1 struct] 3 x1参数。连续

比较测量输出和最终模拟输出

用估计的参数值更新实验。

经验= setEstimatedValues (Exp、vOpt);

获得第一次(放电)实验的模拟输出。

模拟器= createSimulator (Exp(1)模拟器);模拟器= sim(模拟器);SimLog =找到(模拟器。LoggedData get_param (“sdoBattery”“SignalLoggingName”));电压(1)=找到(SimLog“电压”);

得到第二次(充电)实验的模拟输出。

模拟器= createSimulator (Exp(2),模拟器);模拟器= sim(模拟器);SimLog =找到(模拟器。LoggedData get_param (“sdoBattery”“SignalLoggingName”));电压(2)=找到(SimLog,“电压”);

绘制测量和模拟数据。仿真结果与实验数据吻合较好,除了在电池充满电的区域。这是意料之中的,因为简单的电池模型没有模型的指数电压下降时,电池完全充电。

次要情节(211)图(...电压(1).Values.Time / 3600、电压(1).Values.Data,...实验(1).OutputData.Values。时间/ 3600、Exp (1) .OutputData.Values.Data“-”。)标题(放电实验:估计后的模拟和测量响应) ylabel (“电压(V)”)传说(模拟电压的测量电压的“位置”“西南”情节)次要情节(212)(...电压(2).Values.Time / 3600、电压(2).Values.Data,...Exp (2) .OutputData.Values。时间/ 3600、Exp (2) .OutputData.Values.Data“-”。)标题(充电实验:模拟和测量估计后的反应)包含(的时间(小时)) ylabel (“电压(V)”)传说(模拟电压的测量电压的“位置”“东南”

图中包含2个轴对象。轴对象1,标题放电实验:估计后的模拟和测量响应包含2个类型线对象。这些对象代表模拟电压,测量电压。标题为“充电实验:估计后的模拟和测量响应”的轴对象2包含2个类型为线的对象。这些对象代表模拟电压,测量电压。

更新模型参数值

更新模型VK,损失参数值。

sdo.setValueInModel (“sdoBattery”, vOpt);

相关的例子

学习如何估计电池参数使用参数估计量,请参阅每次实验估计模型参数(GUI)

关闭模式

bdclose (“sdoBattery”