質量ばねと二重振り子を備えた (やや奇妙な) システムの運動方程式をシミュレートしています。このシステムには、質量行列と関数 f(x) があり、ode45 を呼び出して解決します。
M*x' = f(x,t);
5 つの状態変数 q= [ QDot, phi, phiDot, r, rDot]'; があります。(QDot は現在の QDot に依存するものがないため削除されました。) ここで、いくつかの力を計算するために、ode45 が各積分ステップで計算する rDotDot の計算値も保存したいと思いますが、ode45 はこれを返しません。私は少し調べましたが、私が見つけた唯一の2つの解決策は、a)これを3次問題に変え、状態ベクトルにphiDotDotとrDotDotを追加することです。これは可能な限り回避したいと思います。これはすでに非線形であり、これにより事態がさらに悪化し、計算時間が大幅に増加するからです。
b)ここで説明されているように、状態を拡張して関数を直接計算します。ただし、例では、質量行列にゼロの行を追加すると彼は言います。そうしないと導関数を積分し、ある点で評価するだけでなく、質量行列を特異にするので、これは理にかなっています。私にはうまくいかないようです...
これは基本的なことのように思えます (状態ベクトルの微分値を取得するため)。私が考えていない明らかなことはありますか? (または、それほど明白ではないものでも構いません....)
ああ、そしてグローバル変数はそれほど素晴らしいものではありません。なぜなら、ode45 は f() 関数をステップの調整中に何度も呼び出すため、グローバル変数のサイズと返される状態ベクトル q がまったく一致しないからです。
誰かがそれを必要とする場合に備えて、コードは次のとおりです。
%(Initialization of parameters are above this line)
options = odeset('Mass',@massMatrix);
[T,q] = ode45(@f, tspan,q0,options);
function dqdt = f(t,q,p)
% q = [qDot phi phiDot r rDot]';
dqdt = zeros(size(q));
dqdt(1) = -R/L*q(1) - kb/L*q(3) +vs/L;
dqdt(2) = q(3);
dqdt(3) = kt*q(1) + mp*sin(q(2))*lp*g;
dqdt(4) = q(5);
dqdt(5) = mp*lp*cos(q(2))*q(3)^2 - ks*q(4) - (mb+mp)*g;
end
function M = massMatrix(~,q)
M = [
1 0 0 0 0;
0 1 0 0 0;
0 0 mp*lp^2 0 -mp*lp*sin(q(2));
0 0 0 1 0;
0 0 mp*lp*sin(q(2)) 0 (mb+mp)
];
end