这段代码定义了一个名为 rungeKuttaWithAux
的 MATLAB 函数,用于使用经典的 Runge-Kutta 方法(RK4) 对状态空间模型(obj
)进行数值求解,同时计算辅助状态。以下是代码的详细解释:
函数签名
function rungeKuttaWithAux(obj, stepSize, ctrlStep)
-
输入参数:
-
obj
: 状态空间模型对象,包含状态、辅助状态、控制、参数和输入的定义。 -
stepSize
: 状态变量的时间步长,用于数值积分。 -
ctrlStep
: 控制变量的时间步长(可选,默认为stepSize
)。
-
-
功能:
-
使用 RK4 方法对状态空间模型进行数值求解,同时计算辅助状态,并将结果保存到模型对象中。
-
代码逻辑
1. 初始化时间范围和状态变量
tStart = obj.t.val(1); tEnd = obj.t.val(2); timePhase = tStart:stepSize:(tEnd-stepSize); [stateNames, auxNames, ctrlNames, paramNames, inputNames] = getFieldNames(obj);
-
提取仿真时间范围(
tStart
和tEnd
),并生成时间点向量timePhase
。 -
获取状态空间模型中的状态、辅助状态、控制、参数和输入的名称列表。
2. 创建空白轨迹
[x, a, u] = createBlankTrajectories(obj, length(timePhase));
-
调用
createBlankTrajectories
函数,为状态、辅助状态和控制创建空白轨迹(初始化为NaN
)。
3. 加载初始值
[x0, a0, u0, p, d0] = getInitialValues(obj); x = insertValue(x, x0, 1); a = insertValue(a, a0, 1); u = insertValue(u, u0, 1);
-
调用
getInitialValues
函数,获取状态、辅助状态、控制、参数和输入的初始值。 -
将初始值插入到轨迹的第一个时间点。
4. 使用 RK4 方法计算轨迹
for n = 2:length(timePhase) pb.print(100*n/length(timePhase),100); % 更新进度条 t = timePhase(n); tHalf = 1/2*(timePhase(n)+timePhase(n-1)); % 计算中间时间点的输入和控制 dHalf = getInputsAtTime(obj, tHalf); d1 = getInputsAtTime(obj, t); uHalf = getControlsAtTime(obj, tHalf, x0, a0, u0, d0, p); u1 = getControlsAtTime(obj, t, x0, a0, u0, d0, p); % 检查是否需要更新控制 if floor(n/ctrlStepRatio) > floor((n-1)/ctrlStepRatio) nextCtrl = true; else nextCtrl = false; end % 使用 RK4 方法计算下一步的状态、辅助状态和控制 [x1, a1, u1] = getNextStep(obj, stepSize, x0, a0, u0, d0, dHalf, d1, uHalf, u1, p, nextCtrl); % 存储新值 x = insertValue(x, x1, n); a = insertValue(a, a1, n); u = insertValue(u, u1, n); % 准备下一轮计算 x0 = x1; a0 = a1; u0 = u1; d0 = d1; end
-
遍历时间点,使用 RK4 方法逐步计算状态、辅助状态和控制的值:
-
计算中间时间点(
tHalf
)和当前时间点(t
)的输入和控制值。 -
检查是否需要更新控制(基于
ctrlStep
)。 -
调用
getNextStep
函数,使用 RK4 方法计算下一步的状态、辅助状态和控制。 -
将计算结果存储到轨迹中。
-
更新初始值,准备下一轮计算。
-
5. 复制计算结果到模型对象
for k=1:length(ctrlNames) if strcmp(obj.u.(ctrlNames{k}).def, ['u.' ctrlNames{k}]) u.(ctrlNames{k}) = []; % 如果控制是预定义的,则不需要保存 end end copyValues(obj, x, a, u, timePhase);
-
如果控制是预定义的,则不需要保存控制轨迹。
-
调用
copyValues
函数,将计算的状态、辅助状态和控制轨迹复制到模型对象中。
辅助函数
1. copyValues
function copyValues(obj, x, a, u, timePhase)
-
将计算的状态、辅助状态和控制轨迹复制到模型对象中。
2. createBlankTrajectories
function [x, a, u] = createBlankTrajectories(obj, trajSize)
-
创建空白的状态、辅助状态和控制轨迹(初始化为
NaN
)。
3. insertValue
function z = insertValue(z, z0, n)
-
将值
z0
插入到轨迹z
的第n
个时间点。
4. getInitialValues
function [x, a, u, p, d] = getInitialValues(obj)
-
获取状态、辅助状态、控制、参数和输入的初始值。
5. getControls
function u1 = getControls(obj, x, u0, d, p)
-
根据规则计算控制值。
6. getNextStep
function [x1, a1, u1] = getNextStep(obj, stepSize, x0, a0, u0, d0, dHalf, d1, uHalf, u1, p, nextCtrl)
-
使用 RK4 方法计算下一步的状态、辅助状态和控制。
7. getK
function k = getK(obj, stepSize, x, a, u, d, p)
-
计算 RK4 方法中的斜率
k
。
总结
rungeKuttaWithAux
函数的主要作用是使用经典的 RK4 方法对状态空间模型进行数值求解,同时计算辅助状态。它通过逐步计算状态、辅助状态和控制的值,并将结果保存到模型对象中。该函数的核心逻辑包括:
-
初始化时间范围和状态变量。
-
使用 RK4 方法逐步计算状态、辅助状态和控制的值。
-
将计算结果保存到模型对象中。
该函数在状态空间模型的仿真和分析中非常有用,特别是在需要高精度数值求解并同时计算辅助状态时。