バックナンバーはこちら。
https://www.simulationroom999.com/blog/model-based-of-minimum-2-backnumber/
はじめに
前回はDummy_FMUModelCS2でオーバーライドしたdo_stepの話。
これで必要な情報は揃ったので、実験用ソースコードを起こす。
基本的な処理は以前のマルチFMUのソースコードをベースとし、
ダミーFMU関連部分を修正するイメージ。
登場人物
博識フクロウのフクさん
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
ダミーFMU実験用ソースコードの元ネタと修正部分
というわけで、ダミーFMU実験用ソースコードを書いてきた。
はや!!
まぁ以前のマルチFMUの時のソースコードをベースにしてるからね。
そっか。
マルチFMUのうちの1個をダミーFMUにするだけだから、
構成はほとんど変わらないのか。
前回のdo_step周りの追加が主な修正部分になってるね。
ダミーFMU実験用ソースコード
というわけでソースコード。
from pyfmi import FMUModelCS2, Master
from pyfmi.tests.test_util import Dummy_FMUModelCS2
import numpy as np
import matplotlib.pyplot as plt
import timeit
model_sub1 = FMUModelCS2( "PID.fmu", "", _connect_dll=True)
model_sub2 = FMUModelCS2( "Motor.fmu", "", _connect_dll=True)
model_dummy = Dummy_FMUModelCS2([], "Dummy.fmu", "", _connect_dll=False)
model_dummy.values[model_dummy.get_variable_valueref("y")] = 0
print_timing = 0
def do_dummy(current_t, step_size, new_step=True):
y = model_dummy.values[model_dummy.get_variable_valueref("y")];
if 0.2 < current_t and current_t < 1.0:
y = y + 100.0/800.0
if 1.2 < current_t and current_t < 2.0:
y = y - 100.0/800.0
model_dummy.values[model_dummy.get_variable_valueref("y")] = y
model_dummy.completed_integrator_step()
while True:
if timeit.default_timer() - start_time >= current_t:
break
global print_timing
if print_timing >= 100:
print("real=%f,sim=%f" % (timeit.default_timer() - start_time, current_t) )
print_timing = 0
print_timing = print_timing + 1
return 0
model_dummy.do_step = do_dummy
models = [model_sub1, model_sub2, model_dummy]
connections = [(model_dummy,"y", model_sub1,"target" ),
(model_sub1,"y",model_sub2,"voltage"),
(model_sub2,"speed",model_sub1,"u")]
master = Master(models, connections)
opts = master.simulate_options()
opts["step_size"] = 0.001
start_time = timeit.default_timer()
res = master.simulate(final_time=2.0, options=opts)
voltage = res[model_sub2]['voltage']
current = res[model_sub2]['current']
speed = res[model_sub2]['speed']
loadTorqueStep_tau = res[model_sub2]['loadTorqueStep.tau']
target = res[model_sub1]['target']
t = res[model_sub1]['time']
plt.plot(t, voltage, label="voltage")
plt.plot(t, current, label="current")
plt.plot(t, speed, label="speed")
plt.plot(t, loadTorqueStep_tau, label="loadTorqueStep.tau")
plt.plot(t, target, label="target")
plt.legend(loc='best')
plt.xlabel('time [sec]')
plt.grid(which='both')
plt.show()
ソースコード解説
まぁdo_stepの話は前回してるし、
それほど説明するところも無いかな。
基本はマルチFMUのところだし、
FMUModelCS2がDummy_FMUModelCS2に変わって、
do_dummy関数を定義して、
do_stepメソッドをdo_dummyで上書きしたってところだね。
説明されてないところだと、
do_dummy関数内のprint部分だけど、
これはまぁ時刻同期がちゃんと出来てるかを表示してくれるってことだろうし、
print_timingって変数でタイミング測ってるのも、
毎回表示すると負荷が上がるから100回に一回だけ表示するようにしてるんだろうね。
正解だ。
0.001秒が1stepなので、0.1秒に一回表示されるようにしてるつもりだ。
それでも0.1秒なのか。
あとは実際に動きを見るしかないねー。
まとめ
まとめだよ。
- ダミーFMU実験用ソースコードは以前のマルチFMUの時の物を流用。
- do_step周りの追加が主な修正部分。
- ソースコード開示。
- FMUModelCS2の一部をDummy_FMUModelCS2。
- do_stepをdo_dummyで上書き。
- 時刻同期ができてるかを確認できるよう一部printを入れている。
バックナンバーはこちら。
コメント