这段代码实现了一个名为 rungeKutta
的函数,用于使用经典的 Runge-Kutta 方法(RK4) 对状态空间模型(obj
)进行数值求解。Runge-Kutta 方法是一种常用的数值积分方法,用于求解常微分方程(ODEs)。以下是代码的详细解释:
函数签名
function rungeKutta(obj, stepSize)
-
输入参数:
-
obj
: 状态空间模型对象,包含状态、辅助状态、控制、参数和输入的定义。 -
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. 检查控制是否为规则定义的
if strcmp(obj.u.(ctrlNames{1}).def, ctrlNames{1}) ruleBased = false; else ruleBased = true; end
-
检查第一个控制的定义是否是其名称本身。如果是,则控制是预定义的(非规则定义);否则,控制是基于规则的。
3. 创建空白轨迹
[x, a, u] = createBlankTrajectories(obj, length(timePhase));
-
调用
createBlankTrajectories
函数,为状态、辅助状态和控制创建空白轨迹(初始化为NaN
)。
4. 加载初始值
[x0, u0, a0, p, d0] = getInitialValues(obj); x = insertValue(x, x0, 1); a = insertValue(a, a0, 1); u = insertValue(u, u0, 1);
-
调用
getInitialValues
函数,获取状态、控制、辅助状态、参数和输入的初始值。 -
将初始值插入到轨迹的第一个时间点。
5. 使用 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, ruleBased); u1 = getControlsAtTime(obj, t, x0, a0, u0, d0, p, ruleBased); % 使用 RK4 方法计算下一步的状态和辅助状态 [x1, a1] = getNextStep(obj, stepSize, x0, a0, u0, uHalf, u1, d0, dHalf, d1, p); % 存储新值 x = insertValue(x, x1, n); a = insertValue(a, a1, n); u = insertValue(u, u1, n); % 准备下一轮计算 x0 = x1; u0 = u1; a0 = a1; d0 = d1; end
-
遍历时间点,使用 RK4 方法逐步计算状态和辅助状态的值:
-
计算中间时间点(
tHalf
)和当前时间点(t
)的输入和控制值。 -
调用
getNextStep
函数,使用 RK4 方法计算下一步的状态和辅助状态。 -
将计算结果存储到轨迹中。
-
更新初始值,准备下一轮计算。
-
6. 复制计算结果到模型对象
if ~ruleBased u = []; % 如果控制是预定义的,则不需要保存 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, u, a, p, d] = getInitialValues(obj)
-
获取状态、控制、辅助状态、参数和输入的初始值。
5. getControls
function u1 = getControls(obj, x, a, u0, d, p)
-
根据规则计算控制值。
6. getNextStep
function [x1, a1] = getNextStep(obj, stepSize, x0, a0, u0, uHalf, u1, d0, dHalf, d1, p)
-
使用 RK4 方法计算下一步的状态和辅助状态。
7. getK
function k = getK(obj, stepSize, x0, a0, u0, d0, p)
-
计算 RK4 方法中的斜率
k
。
总结
rungeKutta
函数的主要作用是使用经典的 RK4 方法对状态空间模型进行数值求解。它通过逐步计算状态和辅助状态的值,并将结果保存到模型对象中。该函数的核心逻辑包括:
-
初始化时间范围和状态变量。
-
使用 RK4 方法逐步计算状态和辅助状态的值。
-
将计算结果保存到模型对象中。
该函数在状态空间模型的仿真和分析中非常有用,特别是在需要高精度数值求解时。