バックナンバーはこちら。
https://www.simulationroom999.com/blog/model-based-of-minimum-2-backnumber/
はじめに
前回、実験構成を決め、
ダミーFMUを混ぜたFMUロードのところまで。
既存のFMUをロードした方がインターフェース仕様の整合が付けやすい。
(インターフェースだけのアルゴリズムは空っぽでOK)
今回は、Dummy_FMUModelCS2でオーバーライドしたdo_stepの話を中心にしていく。
登場人物
博識フクロウのフクさん
イラスト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
do_stepの実装方針
今回はdo_stepをやるんだよねー。
そうだね。
まずは実装方針を書き出そう。
ちなみにRampの代わりに出力する部分なので、
出力信号は以下とする。
- 出力初期値は0.0
- 0.2秒から1.0秒にかけて出力値1.0になるようにRamp Up
- 1.2秒まで出力を1.0に固定
- 1.2秒から2.0秒にかけて出力値0.0になるようRamp Down
登って、止まって、下るって感じか。
そして時間制御の部分は以下。
- シミュレーション開始時刻を記憶。
- \([現時刻 – シミュレーション開始時刻]\)をシミュレーション時間と比較
- シミュレーション時間が上記以上になるまで処理をホールド
これで、シミュレーション時間と実時間が一致するようになるのか。
do_stepの出力信号のソースコード
そして、出力に関するコードはこんな感じにする予定。
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()
PyFMIでも実際の信号にアクセスする場合は一旦valueReferenceの取得が必要なんだね。
そうそう。
valueReferenceが取れれば
valuesがvalueReferenceをキーとして連想配列になってるんで、それを利用して信号の読み書きができる。
do_stepの時間制御のソースコード
そして、時間制御の部分はこんな感じになる。
シミュレーション開始前に以下を実施
start_time = timeit.default_timer()
do_stepから戻る手前で以下の処理を実施
while True:
if timeit.default_timer() - start_time >= current_t:
break
start_timeがオフセットになるイメージか。
そうだね。
本来だとtimeit.default_timer()のオーバーフローとかも気にする必要はあるのだろうが、
timeit.default_timer()がプロセス開始時に0.0であるのと
シミュレーション時間が数秒ということで気にしないこととした。
do_stepの上書き
そういえば、do_stepを上書きするんだっけ?
そのためにDummy_FMUModelCS2でオーバーライドされてるんだよね?
うん。
これはシンプルで以下に感じにすればOK。
model_dummy.do_step = do_dummy
ホントに上書きするんだ・・・。
これでdo_stepの処理がdo_dummyに切り替わって、step毎処理をこちらで制御できる状態となる。
まとめ
まとめだよ。
- do_stepの実装方針を決めた。
- Ramp UpとRamp Down。
- 出力信号のソースコード。
- シミュレーション時間を見ながら出力信号を決定する方式。
- 時刻同期のソースコード。
- 単にタイマーを使ってシミュレーション時間が実時間に追いつくのを待つ。
- do_stepメソッドの上書きはそのまま作成関数で上書きすればOK。
バックナンバーはこちら。
コメント