Func Matrix diff_eqs(t, x, u)
Real t;
Matrix x, u;
{
Matrix M, C, tau;
Matrix dx, q, dq;
Real th1, th2, dth1, dth2;
Matrix makeYcMatrix();
M = Z(2,2); C = Z(2,2);
tau = Z(2,1);
q = Z(2,1); dq = Z(2,1);
qr = Z(2,1); dqr = Z(2,1);
th1 = x(1,1); th2 = x(2,1);
dth1 = x(3,1); dth2 = x(4,1);
tau = u;
q = [[th1][th2]];
dq = [[dth1][dth2]];
M(1,1) = a1 + a2 + 2 * a3 * cos(th2);
M(1,2) = a2 + a3 * cos(th2);
M(2,1) = a2 + a3 * cos(th2);
M(2,2) = a2;
C(1,1) = -a3 * sin(th2) * dth2 + a4;
C(1,2) = -a3 * sin(th2) * (dth1 + dth2);
C(2,1) = a3 * sin(th2) * dth1;
C(2,2) = a5;
ddq = D \ (tau - C * dq);
ddth1 = ddq(1,1);
ddth2 = ddq(2,1);
dx = Z(9,1);
dx(1,1) = dth1;
dx(2,1) = dth2;
dx(3,1) = ddth1;
dx(4,1) = ddth2; // プラント
dqr = dqD - lambda * (q - qD);
ddqr= ddqD - lambda * (dq - dqD);
Yc = makeYcMatrix(dqr, ddqr, q, dq);
s = dq - dqr;
da_hat = - gamma * Yc' * s;
dx(5:9,1) = da_hat;
return dx;
}
Func Matrix link_eqs(t, x)
Real t;
Matrix x;
{
Matrix a_hat;
Matrix u, q, dq, qr, dqr;
Real th1, th2, dth1, dth2;
q = Z(2,1); dq = Z(2,1);
qr = Z(2,1); dqr = Z(2,1);
th1 = x(1,1); th2 = x(2,1);
dth1 = x(3,1); dth2 = x(4,1);
q = [[th1][th2]];
dq = [[dth1][dth2]];
a_hat = x(5:9,1);
u = Z(2,1);
dqr = dqD - lambda * (q - qD);
ddqr= ddqD - lambda * (dq - dqD);
Yc = makeYcMatrix(dqr, ddqr, q, dq);
s = dq - dqr;
u = Yc * a_hat - Kd * s;
return u;
}
ここで賢明な人は,どうしてパラメータの更新則がdiff_eqs()の中
に書いてあるのだろう?これでは実際のインプリメントの時に実現できな
いのではないか?という疑問を持たれるでしょう。この疑問は正しいとい
えます。実際に計算機で制御プログラムを作る時にはコントローラは離散
系ですから,このような積分は出来ないと言っても良いでしょう。
ある意味では,制御則は全てlink_eqs()に書くべきだとも言えます。 実際のインプリメントの時には,サンプリング時間が短いということで, 大抵,パラメータ更新則の積分などをオイラー積分ですませることが多い ようです(もちろんルンゲクッタ法関数rngkut4()を入れるようにすれ ばなお良いのですが)。ただし前述したように,その場合結局は diff_eqs()に書いた事と本質的な違いはなくなってしまいます。
したがって,シミュレーションの場合は積分を必要とするものは
diff_eqs()の中に書く方が簡単になると思われます。このような理由で,
この例プログラムはパラメータ更新則をdiff_eqs()の中に書いてい
ます。