バックナンバーはこちら。
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。
バックナンバーはこちら。
コメント