【PyFMI】最小構成のMBD事例 第2章 その105【ダミーFMU⑦】

【PyFMI】最小構成のMBD事例 第2章 その105【ダミーFMU⑦】 事例
【PyFMI】最小構成のMBD事例 第2章 その105【ダミーFMU⑦】

バックナンバーはこちら。
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を入れている。

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

コメント

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