サンプル:自動システム#
自動システム#
このサンプルは、自動システムの実装例です。Listで自動運転のプログラムを記述、コマンドの実行エンジンの実装例になっています。
編成のイベントハンドラーは、ユーザー定義ハンドラに統一。 ユーザー定義ハンドラは、イベント発生時にListに記述されたコマンドを解釈、実行します。
レイアウトスクリプトに、自動システムのコード、ユーザー定義ハンドラを記述。 レイアウトスクリプトは、ビュワー起動時に最初にPythonにロードされるため、ここに全体で利用するコードを記述します。
このサンプルのコードは、改変自由、発表自由、サポート対象外です。 また、最小構成の実装例のため、クラス、エラー対応、機能拡張、センサー対応など、このコードをベースに拡張してください。
サンプルは、先行編成と後続編成の2つの編成があります。後続編成は、3秒後の出発。先行編成に連結します。
先行編成は、Xキーで分割できます。3秒以内に分割した場合、後続編成は、生成された新しい編成に連結します。
また、Wキーでポイントを分岐側に切り替えます。
これらが、Listに記述した簡易コードで実行されます。
サンプルダウンロード#
ダウンロード後、zipファイルを展開してください。スターターキットの部品のみで構成しています。 システムバージョン 6.0.0.159以降で使用可能です。
コード解説#
コマンド定義#
レイアウトスクリプトで、コマンドを定数定義します。
#コマンド
ADRV_TERM = 0
ADRV_KEYEVENT = 1
ADRV_SPLIT = 2
ADRV_AUTOSPEED = 3
ADRV_TIME = 4
ADRV_TIMER = 5
ADRV_AFTER = 6
ADRV_LOG = 7
ADRV_SETPOINT = 8
ADRV_COUPLE = 9
ADRV_LIST = 10
コマンドは、実装例になっています。イベントの対応、他の部品の制御など実装例を参考に拡張してください。
command | guide |
---|---|
ADRV_TERM | コマンド実行を終了 |
ADRV_KEYEVENT | キー入力イベントを設定 |
ADRV_SPLIT | 編成を分割します。生成された編成に新しいコマンドリストを割り当てます。 |
ADRV_AUTOSPEED | 速度制御 |
ADRV_TIME | 時間イベントの設定 |
ADRV_TIMER | タイマーイベントの設定 |
ADRV_AFTER | 時間経過イベントの設定 |
ADRV_LOG | ログ |
ADRV_SETPOINT | ポイント操作。編成以外の部品操作の実装例 |
ADRV_COUPLE | 連結イベントの設定 |
ADRV_LIST | 別のコマンドリストを実行 |
エンジン#
自動システムのエンジン部分です。
自動システムは、[ステータス、命令、パラメータ]のリストを順次実行します。 現在ステータスに一致する命令を実行、ステータスを+1して、次に一致するステータスの命令を実行します。
ADRV_TERMが実行されると、一連の実行処理を終了します。
ADRV_AUTOSPEEDは、編成オブジェクトに対しての操作実装例です。
trainobj.AutoSpeedCTRL(cmd[2],cmd[3])
trainobjに対して、AutoSpeedCTRL関数をコール、引数は、cmdの#2、#3のデータを設定しています。 エラー処理は省略しています。cmdに設定されている値は、正しいものとします。
ADRV_KEYEVENTは、イベントの設定例です。 ここで設定したイベントは、ユーザー定義ハンドラのkeydownイベントでキャッチされます。
ADRV_SETPOINTは、外部部品操作の実装例です。 IDで部品オブジェクトを取得、オブジェクトに対して、操作します。
ADRV_COUPLEは、特殊イベントの実装例です。 オブジェクトのdictに、パラメータを記述。イベント発生時は、そのパラメータで処理を行います。 連結イベントについては、実装例はすべての連結に対して、無条件で処理を行っています。 イベントに条件づけを行うなど工夫の余地があります。
この他、条件分岐などアイデア次第です。
#exec_statusから実行する
def adrv_exec(trainobj,exec_status):
dc = trainobj.GetDict()
if ('adrv_cmdlist' in dc) == False:
return
#解析実行
cmdlist = dc['adrv_cmdlist']
for cmd in cmdlist:
if cmd[0] == exec_status:
dc['adrv_status'] = exec_status
vrmapi.LOG("OBJID "+str(trainobj.GetID())+" -- CMD->" + str(cmd[1]) + "ST:" + str(exec_status))
if cmd[1] == ADRV_TERM:
return
elif cmd[1] == ADRV_KEYEVENT:
exec_status+=1
#キー入力イベント設定
#ADRV_KEYEVENT, keycode文字, キーを押したときのステータス
trainobj.SetEventKeyDown(cmd[2],cmd[3])
elif cmd[1] == ADRV_SPLIT:
exec_status+=1
#編成分割
#ADRV_SPLIT,分割号車番号、分割で生成された編成の自動運転リスト,初期ステータス
tid = trainobj.SplitTrain(cmd[2])
nobj = vrmapi.LAYOUT().GetTrain(tid)
adrv_init(nobj,cmd[3],cmd[4])
elif cmd[1] == ADRV_AUTOSPEED:
exec_status+=1
#出発
#ADRV_AUTOSPEED,dist,v
trainobj.AutoSpeedCTRL(cmd[2],cmd[3])
elif cmd[1] == ADRV_TIME:
exec_status+=1
#時間イベント設定
#ADRV_TIME,発生時刻,発生後のスタータス
trainobj.SetEventTime(cmd[2],cmd[3])
elif cmd[1] == ADRV_TIMER:
exec_status+=1
#タイマーイベント設定
#ADRV_TIMER,時間,発生後のスタータス
trainobj.SetEventTimer(cmd[2],cmd[3])
elif cmd[1] == ADRV_AFTER:
exec_status+=1
#時間経過イベント設定
#ADRV_AFTER,時間,発生後のスタータス
trainobj.SetEventAfter(cmd[2],cmd[3])
elif cmd[1] == ADRV_LOG:
exec_status+=1
#ログを記録
#ADRV_LOG,logtext
vrmapi.LOG(cmd[2])
elif cmd[1] == ADRV_SETPOINT:
exec_status+=1
#ポイントを操作
#ADRV_SETPOINT,PointID,param
pointobj = vrmapi.LAYOUT().GetPoint(cmd[2])
pointobj.SetBranch(cmd[3])
elif cmd[1] == ADRV_COUPLE:
exec_status+=1
#連結イベント
#ADRV_COUPLE,event_status
dc['adrv_couple'] = cmd[2]
elif cmd[1] == ADRV_LIST:
exec_status+=1
#新しいコマンドリストを実行
#ADRV_LIST,new_list,exec_status
adrv_init(trainobj,cmd[2],cmd[3])
エンジン初期化#
SetUserEventFunction()でユーザー定義ハンドラを設定。
オブジェクトのdictに自動システムの変数を設定して、初期化コマンドを実行します。
init_statusが、Listにない数値の場合は、初期化コマンドは実行されません。
#編成に自動運転を設定する
def adrv_init(trainobj,cmdlist,init_status):
#ユーザーハンドラに切り替える
trainobj.SetUserEventFunction("vrmevent_usertrain")
dc = trainobj.GetDict()
dc['adrv_cmdlist'] = cmdlist
dc['adrv_status'] = init_status
dc['adrv_couple'] = 0
adrv_exec(trainobj,init_status)
ユーザー定義ハンドラ#
ユーザー定義ハンドラの実装例です。
この実装例では、連結、分割イベントでログに記録しています。
#user定義ハンドラ
def vrmevent_usertrain(obj,ev,param):
if ev == 'init':
vrmapi.LOG('USER INIT - '+str(obj.GetID()))
elif ev == 'broadcast':
dummy = 1
elif ev == 'timer':
adrv_exec(obj,param['eventUID'])
elif ev == 'time':
adrv_exec(obj,param['eventUID'])
elif ev == 'after':
adrv_exec(obj,param['eventUID'])
elif ev == 'frame':
dummy = 1
elif ev == 'couple':
vrmapi.LOG('CODE HANDLER userhander')
vrmapi.LOG('*連結event - '+str(obj.GetID()))
vrmapi.LOG('消滅編成ID = '+str(param['delid']))
#連結イベント実行
dc = obj.GetDict()
if 'adrv_couple' in dc:
adrv_exec(obj,dc['adrv_couple'])
elif ev == 'split':
vrmapi.LOG('CODE HANDLER userhander')
vrmapi.LOG('*分割event - '+str(obj.GetID()))
vrmapi.LOG('新規編成ID = '+str(param['newid']))
vrmapi.LOG('成功フラグ = '+str(param['live']))
#通常は、新規編成には分割元のスクリプトがコピーされる
#ここで新規編成もユーザーハンドラに変更する
if param['live'] == 1:
newobj = vrmapi.LAYOUT().GetTrain(param['newid'])
newobj.SetUserEventFunction("vrmevent_usertrain")
elif ev == 'start':
dummy = 1
elif ev == 'stop':
dummy = 1
elif ev == 'autospeed':
dummy = 1
elif ev == 'delete':
dummy = 1
elif ev == 'create':
dummy = 1
elif ev == 'homekey':
dummy = 1
elif ev == 'endkey':
dummy = 1
elif ev == 'insertkey':
dummy = 1
elif ev == 'spacekey':
dummy = 1
elif ev == 'active':
dummy = 1
elif ev == 'view':
dummy = 1
elif ev == 'keydown':
adrv_exec(obj,param['eventUID'])
先行編成#
ID=7の編成の実装例です。
autolist7に編成のコマンドを記述しています。
また、autolistNTに分割で生成される編成のコマンドを記述しています。
標準のイベントハンドラでは、initでadrv_init()を実行。 以降、すべての制御は、自動システム側に移ります。
autolist7は、初期化で100から実行。キーイベントの設定などを行っています。
Xキー入力で、1000から実行。編成を分割、新しい編成にautolistNTを割り当てます。
autolistNT = [
[100,ADRV_LOG,"*** 新規編成START ***"],
[101,ADRV_COUPLE,400],
[102,ADRV_TERM],
#couple
[400,ADRV_LOG,"+++ 連結イベント実行 NT編成"],
[401,ADRV_TERM]
]
autolist7 = [
[100,ADRV_KEYEVENT,'X',1000],
[101,ADRV_KEYEVENT,'W',3000],
[102,ADRV_COUPLE,200],
[103,ADRV_TERM],
#couple
[200,ADRV_LOG,"+++ 連結イベント実行 7編成"],
[201,ADRV_TERM],
# x key
[1000,ADRV_SPLIT,1,autolistNT,100],
[1001,ADRV_LOG,"*** 編成分割 ***"],
[1002,ADRV_TERM],
# y key
[3000,ADRV_SETPOINT, 10, 1],
[3001,ADRV_LOG,"*** ポイント変更"],
[3002,ADRV_TERM]
]
def vrmevent_7(obj,ev,param):
if ev == 'init':
vrmapi.LOG('INIT - '+str(obj.GetID()))
adrv_init(obj,autolist7,100)
後続編成#
ID=9の編成の実装例です。
autolist9に編成のコマンドを記述しています。
3秒後にAfterイベントを発生、イベント発生時は、ステータス500から実行します。
ステータス500では、100mmで電圧0.2を目標に自動運転を開始します。
標準のイベントハンドラでは、initでadrv_init()を実行。 以降、すべての制御は、自動システム側に移ります。
autolist9 = [
#init
[100,ADRV_AFTER,3,500],
[101,ADRV_TERM],
#after
[500,ADRV_AUTOSPEED,100,0.2],
[501,ADRV_TERM]
]
def vrmevent_9(obj,ev,param):
if ev == 'init':
vrmapi.LOG('INIT - '+str(obj.GetID()))
adrv_init(obj,autolist9,100)
実行例#
先行編成に後続編成が連結した場合。
ビュワー起動後、3秒で後続編成9が出発、先行編成7に連結します。連結で、停車中の先行編成7に連結イベントが発生します。
実行例のログです。
[2020/5/21 8:48:5][10.549891ns : ID 0] : string : CODE HANDLER userhander
[2020/5/21 8:48:5][10.549891ns : ID 0] : string : *連結event - 7
[2020/5/21 8:48:5][10.549891ns : ID 0] : string : 消滅編成ID = 9
[2020/5/21 8:48:5][10.549891ns : ID 0] : string : OBJID 7 -- CMD->7ST:200
[2020/5/21 8:48:5][10.549891ns : ID 0] : string : +++ 連結イベント実行 7編成
[2020/5/21 8:48:5][10.549891ns : ID 0] : string : OBJID 7 -- CMD->0ST:201
先行編成を分割、新規編成に後続編成が連結した場合。
ビュワー起動後、Xキーで先行編成を分割。生成された編成に後続が連結します。生成された編成で連結イベントが発生します。
実行例のログです。
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : CODE HANDLER userhander
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : *分割event - 7
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : 新規編成ID = 1073741824
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : 成功フラグ = 1
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : OBJID 1073741824 -- CMD->7ST:100
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : *** 新規編成START ***
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : OBJID 1073741824 -- CMD->9ST:101
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : OBJID 1073741824 -- CMD->0ST:102
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : OBJID 7 -- CMD->7ST:1001
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : *** 編成分割 ***
[2020/5/21 8:49:5][1.363807ns : ID 0] : string : OBJID 7 -- CMD->0ST:1002
3秒で後続が出発、10秒で連結しています。
[2020/5/21 8:49:7][3.015129ns : ID 0] : string : OBJID 9 -- CMD->3ST:500
[2020/5/21 8:49:7][3.015129ns : ID 0] : string : OBJID 9 -- CMD->0ST:501
[2020/5/21 8:49:15][10.554655ns : ID 0] : string : CODE HANDLER userhander
[2020/5/21 8:49:15][10.554655ns : ID 0] : string : *連結event - 1073741824
[2020/5/21 8:49:15][10.554655ns : ID 0] : string : 消滅編成ID = 9
[2020/5/21 8:49:15][10.554655ns : ID 0] : string : OBJID 1073741824 -- CMD->7ST:400
[2020/5/21 8:49:15][10.554655ns : ID 0] : string : +++ 連結イベント実行 NT編成
[2020/5/21 8:49:15][10.554655ns : ID 0] : string : OBJID 1073741824 -- CMD->0ST:401