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

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

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

はじめに

必要なタイマハンドラは2つ。

  • FMU_handler:FMUシミュレーション用(短周期呼び出し)
  • plot_handler:matplotlibリアルタイム更新用(長周期呼び出し)

これらの実装について考えていく。
(今回はFMU_handler)

登場人物

博識フクロウのフクさん

指差しフクロウ

イラスト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_handler

フクさん
フクさん

じゃ、まずはFMU_handlerことFMUシミュレーション用の処理だ。
コードにすると以下になる。

def FMU_handler():
    global start_tick
    global currenttime
    current_tick = time.perf_counter()
    delta_tick = current_tick - start_tick;
    start_tick = current_tick
    delta_simulate = delta_tick
    
    res = master.simulate(start_time=currenttime, final_time=currenttime+delta_simulate-step_size/100, options=opts)
    opts["initialize"] = 0
    
    currenttime = currenttime + delta_simulate

    deque_voltage.extend(res[model_sub2]['voltage'])
    deque_current.extend(res[model_sub2]['current'])
    deque_speed.extend(res[model_sub2]['speed'])
    deque_loadTorqueStep_tau.extend(res[model_sub2]['loadTorqueStep.tau'])
    deque_target.extend(res[model_sub1]['target'])
    deque_time.extend(res[model_sub2]['time'])
    deque_cpuload.extend(np.ones(len(res[model_sub2]['time']))*delta_simulate*1000)

    root.after(1, FMU_handler)

FMU_handler詳細

太郎くん
太郎くん

先頭の方にglobalで定義された変数があるね?
これは何?

フクさん
フクさん

グローバル変数が存在していることを明示した書き方だな。
Pythonはスコープがネストしている場合、
特に明示しなくても参照できるのだが、
start_tick = current_tick
のような行があると、
ここで変数が新たに作られる場合とそうでない場合が区別つかないんだよね。
よって、この場合、グローバル変数が先に存在することを明示してあげる必要がある。

太郎くん
太郎くん

よくわからんが、
ローカル変数なのか、外側のスコープに別の変数がいるのかが分からなくなる場合があるからちゃんと指示して上げないといけない局面があるってことかな?
そして今回のstart_tickとcurrenttimeがそれに該当すると。

フクさん
フクさん

正解だ。

太郎くん
太郎くん

あとは実時間の進んだ時間をstart_tickとcurrenttimeを使って求めて、
その時間分をシミュレーション時間として進めてる感じか。

太郎くん
太郎くん

ちょっと気になるところはmaster.simulateメソッドの
final_time=currenttime+delta_simulate-step_size/100
ってところかな?
currenttime+delta_simulate
は、終了時間を示しているのは察せるけど、
-step_size/100
は何を示してるんだろう?

フクさん
フクさん

ここはちょっと苦肉の策みたいな部分はあるねー。

フクさん
フクさん

FMUのシミュレーションとして
final_time=currenttime+delta_simulate
とすると、
今回の最後のstepと次の最初のstepが重複しちゃうんだよね。
それを回避しようと
final_time=currenttime+delta_simulate-step_size
にすると、
今回の最後のstepと次の最初のstepの間に1step分の隙間が生まれて
キレイにシミュレーションしてくれない。
よって、微妙に次の先頭stepに係らない程度の時間を指定して、
演算としては辻褄が合うようにしている。

太郎くん
太郎くん

何を言ってるのか全く分からん。

フクさん
フクさん

まぁ図にしてみるとこんな感じだな。

シミュレーション時間の重複、欠落状態、1step重複、1step欠落、欠落微小とし影響無し
太郎くん
太郎くん

ほう。
こんなことが起きているのか。
まぁ欠落微小で影響ないならOKだよね。

フクさん
フクさん

事前実験では問題なく動いていたことは確認しているので、
おそらく問題はないだろう。

まとめ

フクさん
フクさん

まとめだよ。

  • FMU_handlerことFMUシミュレーション用処理のコードを提示。
    • 外部の変数を使用するためにglobal定義している変数あり。
  • 実時間の経過を元にFMUシミュレーション時間を決定している。
    • 実時間にシミュレーション時間を追いつかせる方式。
    • ただし、開始と終了のstepが重複したり欠落したりするので微小時間の調整が必要。

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

コメント

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