这个例子展示了如何使用多个实验来估计模型参数值的混合;有些是用所有实验来估计的有些是用单个实验来估计的。该示例还展示了如何配置与实验相关的参数值的估计实验。
你估计一个可充电电池的参数,基于在放电和充电的实验中收集的数据。
这个例子估计了一个简单的充电电池模型的参数,sdoBattery
.模型输入为电池电流,模型输出为电池端电压,由电池充电状态计算得到。
open_system (“sdoBattery”);
这个模型是基于这个方程的
在方程:
为电池端电压,单位为伏特。
为电池恒压,单位为伏特。
为电池极化电阻,单位为欧姆。
为以安培小时为单位的最大电池容量。
为电池充电状态,1为充满,0为放电。电池的充电状态是由电池电流的积分计算出来的,电池的正电流指示放电,负电流指示充电。电池初始充电状态为 在安时。
为充电时的压降,用电池恒压的分数表示。当电池放电时,这个值为零。
V
,K
,Qmax
,Q0处
,损失
是在模型工作区中定义的变量。
加载实验数据。对1.2V (6500mAh)电池进行了放电实验和充电实验。
负载sdoBattery_ExperimentData
的变量Charge_Data
和DCharge_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)”)
创建一个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)”)传说(模拟电压的,测量电压的,“位置”,“西南”)
次要情节(212)图(...电压(2).Values.Time / 3600、电压(2).Values.Data,...Exp (2) .OutputData.Values。时间/ 3600、Exp (2) .OutputData.Values.Data“-”。)标题(“充电实验:在评估前模拟和测量反应”)包含(的时间(小时)) ylabel (“电压(V)”)传说(模拟电压的,测量电压的,“位置”,“东南”)
估计电池电压值V
,电池极化电阻K
,充电损耗率损失
.的V
和K
利用所有的实验数据进行参数估计损失
参数仅使用充电数据进行估计。
选择电池电压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)”)传说(模拟电压的,测量电压的,“位置”,“东南”)
更新模型V
,K
,损失
参数值。
sdo.setValueInModel (“sdoBattery”, vOpt);
学习如何估计电池参数使用参数估计量,请参阅每次实验估计模型参数(GUI).
关闭模式
bdclose (“sdoBattery”)