見出し画像

Rosso Laboratory

Pythonで単線閉塞両方向運転を構築する(後編)

では3つの項目を詳しく見ていきましょう。

①共通ステータスのコマンドには偽物がある(^_^;)
SetStatusDataIntやGetStatusDataInt等のステータス関連のコマンドには2種類あったのですが、レイアウトオブジェクトのコマンドの方を見て「共通ステータスのコマンド見っけ」と思い、その後部品共通のコマンドにもSetStatusDataIntやGetStatusDataIntがあったので「センサーでも同様に使えるな」と思ったのです。これが間違いで、部品共通のコマンドの方は共通ステータスではなく部品ステータスというよく分からんものを読み書きするものでした(^_^;) なので、レイアウト同様にセンサーでもobj.SetStatusDataInt("ステータス名",整数)と書いていたのですが、センサーではvrmapi.LAYOUT().SetStatusDataInt("共通ステータス名",整数)のように書く必要があったのです。紛らわしいですね(^_^;) これが「止まるべきところで列車が止まらず」の原因でした。

②自動センサーの向きは自動ではない(^_^;)
自動センサーは昔のセンサーと違って向きがあり、普通に使うならば有効な方向と無効な方向は自動で認識されるのですが、これがスクリプトでは自動ではなかったのです(^_^;) 向きはあるのですが順方向で使うならば方向を得るGetForwardを使い、
    elif ev == 'catch':
        f = obj.GetForward()
        if f == 1:
というスクリプトを書いておく必要がありました。これが「止まってはいけないところで列車が止まる」原因でした。

③同じ関数内でも違うイベント間ではローカル変数は使えない(^_^;)
これでいけるかと思いきや今度は再出発してくれないという問題が発生しました。原因はローカル変数のスコープでした。まず'catch'イベのGetTrainで編成「train」をゲットし停車させます。その20秒後'after'イベ内でSetEventTimerを5秒おきに実行。'timer'イベ内で共通ステータスを見て条件が整ったら「train」を出発します。ところが'catch'イベでゲットした「train」は'timer'イベで使おうとした時にはもう居ないのです。同じdef(関数定義)内だからローカル変数でスコープは有効だと思っていたのですが、角卓氏著「「鉄道模型シミュレーターNX」で学ぶPythonプログラミング入門」P.38によると「イベントが発生するたびに「vrmevent関数」が呼ばれますが、関数内で定義した「ローカル変数」は、その都度初期化されてしまいます。」とのことで、正にここに原因がありました。よって「train」はグローバル変数にしておく必要があったのです。(角氏によるとグローバル変数よりもDict型メンバー変数を使う方が良いとのことですが、まだDict型がよく分からないもので(^_^;))

ということで、これで大体予定通り動き出したのですが、ずっと動かし続けていると再出発が早すぎて対向列車に邪魔されて止まるような状態もまだ発生しており、もう少し考える必要がありそうです。しかし、Pythonスクリプトでやる方が簡単とまでは言いませんがスマートに出来るような気はしますね。参考までにセンサーに書き込んだスクリプトの1つを掲載しておきます。

#海→信号所センサー(第3センサー)
#OBJID=xx
import vrmapi
def vrmevent_xx(obj,ev,param):
    if ev == 'init':
        global train3
        global evid3
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        if param['eventUID'] == 10002:
            singou = vrmapi.LAYOUT().GetStatusDataInt("信号所山行")
            yama = vrmapi.LAYOUT().GetStatusDataInt("山側")
            if singou == 1:
                if yama == 0:
                    train3.AutoSpeedCTRL(200.0,1.0)
                    vrmapi.LAYOUT().SetStatusDataInt("信号所山行",0)
                    obj.ResetEvent(evid3)
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        if param['eventUID'] == 10003:
            evid3 = obj.SetEventTimer(5,10002)
    elif ev == 'frame':
        dummy = 1
    elif ev == 'catch':
        f = obj.GetForward()
        if f == 1:
            train3 = obj.GetTrain()
            vrmapi.LAYOUT().SetStatusDataInt("海側",0)
            yama = vrmapi.LAYOUT().GetStatusDataInt("山側")
            if yama == 1:
                train3.AutoSpeedCTRL(450.0,0.0)
                vrmapi.LAYOUT().SetStatusDataInt("信号所山行",1)
                obj.SetEventAfter(10,10003)

PVアクセスランキング にほんブログ村


ランキングに参加中。クリックして応援お願いします!

名前:
コメント:

※文字化け等の原因になりますので顔文字の投稿はお控えください。

コメント利用規約に同意の上コメント投稿を行ってください。

 

※ブログ作成者から承認されるまでコメントは反映されません。

  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最新の画像もっと見る

最近の「Pythonスクリプト」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事