【PyFMI】最小構成のMBD事例 第2章 その121【リアルタイム描画⑮】

【PyFMI】最小構成のMBD事例 第2章 その121【リアルタイム描画⑮】 事例
【PyFMI】最小構成のMBD事例 第2章 その121【リアルタイム描画⑮】

バックナンバーはこちら。
https://www.simulationroom999.com/blog/model-based-of-minimum-2-backnumber/

はじめに

tkinterによるFMUシミュレーションのリアルタイム波形描画。
ついに前回からFMU関連処理に突入したが、
いろいろと考えるポイントがありそうということで一旦情報整理をした。

結論としては、
FIFO、Queueのようなデータ構造を利用して、
古いデータを捨てていかないとメモリがいくらあってもたりなり。
dequeを使用するとそこらへんは解決できそう。

今回は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関連処理についてコードを追加していこう。
内容的にはすでにやったものばかりなので走り気味に行くよ。

フクさん
フクさん

まずimportするのは以下。

from pyfmi import load_fmu, FMUModelCS2, Master
from pyfmi.tests.test_util import Dummy_FMUModelCS2
太郎くん
太郎くん

以前やったコードからすると追加するコードは以下になるかな。

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

def do_dummy( current_t, step_size, new_step=True):
    model_dummy.values[model_dummy.get_variable_valueref("y")] = _y
    model_dummy.completed_integrator_step()
    return 0

_y = 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)
フクさん
フクさん

うん。
おそらくOKだろう。

太郎くん
太郎くん

コード自体はどこに追加すれば良いのかな?

フクさん
フクさん

ぶっちゃけroot.mainloop()より前だったらどこでも良いな。

太郎くん
太郎くん

まぁ具体的は配置箇所は改めて見せるとしてとりあえず適当に配置しておこう。

deque関連の初期化

フクさん
フクさん

次が今回新顔のdeque。

太郎くん
太郎くん

即行で出て来たな。deque。

フクさん
フクさん

dequeはcollectionsというライブラリの一部なので先にimportしておく必要がある。

import collections
フクさん
フクさん

そして、一定時間以上のデータは捨てるようサイズの最大値を決めておく必要がある。

太郎くん
太郎くん

データ個数の最大値だったら決められる気がするけど、
一定時間ってのは中々決め辛いような・・・。

フクさん
フクさん

シミュレーションのstep時間を決めてしまえば、そこからデータ個数が確定する。
例えば、0.001秒をstep時間として、
8.5秒分のデータを格納するのであれば、
8.5÷0.001=8500
で、8500個のデータを指定すれば良い。

太郎くん
太郎くん

なるほど。
時間の刻みが分かっていれば格納個数も決められるのか。

フクさん
フクさん

というわけで、コードは以下になる。

step_size = 0.001
queue_max = int(8.5/step_size)    # 8.5秒分のqueueを用意

# define queues
deque_voltage = collections.deque(maxlen=queue_max)
deque_current = collections.deque(maxlen=queue_max)
deque_speed = collections.deque(maxlen=queue_max)
deque_loadTorqueStep_tau = collections.deque(maxlen=queue_max)
deque_target = collections.deque(maxlen=queue_max)
deque_time = collections.deque(maxlen=queue_max)
deque_cpuload = collections.deque(maxlen=queue_max)
太郎くん
太郎くん

取り出す信号分のdequeを先に作っておくんだね。

フクさん
フクさん

そうそう。

フクさん
フクさん

次はFMUのシミュレーションをするためのタイマハンドラの実装ではあるが、
タイマハンドラ内の処理に対して、もう少し前準備が残っている。

まとめ

フクさん
フクさん

まとめだよ。

  • FMU関連処理前準備を一気に説明。
    • いままでやってきたものなので細かい説明は省略。
  • deque関連の初期化。
    • dequeはcollectionsライブラリの一部。
    • maxlenで最大要素数を指定できる。
      • 指定なしの場合は無限に入れられる。
        • 実際には物理的な限界はあるだろうが・・・。

バックナンバーはこちら。

コメント

タイトルとURLをコピーしました