[英]Avoid loading the same script twice with rFSM library in LUA
問題描述
以下代碼是復制我遇到的問題的最小示例。 使用了 rFSM 庫,可以在這里找到: https ://github.com/kmarkus/rFSM
有三個 lua 腳本。 “main”,稱為runscript.lua
,它初始化並運行需要運行的狀態機 (SM),稱為mainTask.lua
,而后者又使用輔助狀態機subTask.lua
。
代碼流程如下。 我們在狀態機mainTask.lua
內部啟動並立即進入Sim
復合狀態,然后狀態evaluate
。 在那里,我們調用subTask.lua
中的函數evaluateData
並將局部變量var
設置為false
。 在這個函數調用之后,我們再次進入mainTask.lua
,進行一次轉換並再次進入subTask.lua
。 在那里我們打印var
的值。
同樣,示意性地: mainTask.lua
-> subTask.lua
-> mainTask.lua
-> subTask.lua
。
我們期望var
的值為false
。 然而,正如你所見,在mainTask.lua
中,我們通過rfsm.load("subTask.lua"),
加載了subTask.lua
兩次。 這導致有兩個輔助 SM 實例,但我想要一個。
rfsm.load
函數是
function load(file)
local fsm = dofile(file)
if not is_state(fsm) then
error("rfsm.load: no valid rfsm in file '" .. tostring(file) .. "' found.")
end
return fsm
end
代碼
runscript.lua
-- Set lua path to location of rFSM library
package.path = "/home/anfr/rFSM-master/?.lua;./?.lua";
require 'rfsm';
print('[runscript.lua] Before rfsm.load("mainTask.lua")')
fsm_ = rfsm.load("mainTask.lua")
print('[runscript.lua] Before rfsm.init(fsm_)')
fsm = rfsm.init(fsm_);
print('[runscript.lua] Before rfsm.run(fsm)')
rfsm.run(fsm);
mainTask.lua
local var = true;
return rfsm.state{
Sim = rfsm.composite_state
{
evaluate = rfsm.state {
entry=function()
var = false;
if (evaluateData(var)) then
rfsm.send_events(fsm, "internal_EvaluateDone")
end
end,
},
sub = rfsm.load("subTask.lua"),
rfsm.trans {
src='initial',
tgt='evaluate',
effect=function()
print('[mainTask.lua] initial -> evaluate')
end,
},
rfsm.trans {
src='evaluate',
tgt='sub',
events={'internal_EvaluateDone'},
effect=function()
print('[mainTask.lua] evaluate -> sub with event "internal_EvaluateDone"')
end,
},
}, -- end of Sim
Seq = rfsm.composite_state
{
entry=function()
print('Entry Seq')
end,
exit=function()
print('Exit Seq')
end,
Running = rfsm.composite_state
{
entry=function()
print('Entry Running')
end,
exit=function()
print('Exit Running')
end,
--sub_2 = sub,
sub_2 = rfsm.load("subTask.lua"),
rfsm.trans {
src='initial',
tgt='sub_2',
effect=function()
print('[Seq composite state] initial -> sub_2')
end,
},
},
rfsm.trans {
src='initial',
tgt='Running',
effect=function()
print('[Seq composite state] initial -> Running')
end,
},
}, -- end of Seq
rfsm.trans {
src='initial',
tgt='Sim',
effect=function()
print('[mainTask.lua] initial -> Sim')
end,
},
};
subTask.lua
print("--- start of subTask.lua ---")
local var = true;
function evaluateData(value)
print("[subTask.lua] var before setting in evaluateData is " .. tostring(var));
var = value;
print("[subTask.lua] var after setting in evaluateData is " .. tostring(var))
return true
end
return rfsm.state {
execute = rfsm.state {
entry=function()
print('[subTask.lua] var inside execute is ' .. tostring(var))
end,
},
rfsm.trans {
src='initial',
tgt='execute',
effect=function()
print('[subTask.lua] initial -> execute')
end,
},
},
print("--- end of subTask.lua ---")
日志
下面的日志顯示,我們第二次進入輔助SM時,我們使用了var
的值為true
的第二個實例(我們不希望這樣)。
[runscript.lua] Before rfsm.load("mainTask.lua")
--- start of subTask.lua ---
--- end of subTask.lua ---
--- start of subTask.lua ---
--- end of subTask.lua ---
[runscript.lua] Before rfsm.init(fsm_)
[runscript.lua] Before rfsm.run(fsm)
[mainTask.lua] initial -> Sim
[mainTask.lua] initial -> evaluate
[subTask.lua] var before setting in evaluateData is true
[subTask.lua] var after setting in evaluateData is false
[mainTask.lua] evaluate -> sub with event "internal_EvaluateDone"
[subTask.lua] initial -> execute
[subTask.lua] var inside execute is true
嘗試解決方案
嘗試 1
這種嘗試實際上適用於我的本地示例(不是真實系統)並使用注釋行sub_2 = sub
。 所以想法是加載一次狀態機,這里簡單參考一下。 我想知道不同版本的LUA是否對此有影響。 在本地,我在系統 Lua 5.1 上有 Lua 5.2。
編輯
如果我只是在Seq
復合狀態中添加另一個虛擬狀態,此嘗試將停止工作。 也不依賴 Lua 版本。
嘗試 2
實現第二個版本的load
和使用require
而不是dofile
。 然后在mainTask.lua
的那兩個地方使用這個函數。
function load2(file)
local fileWithoutExtension = file:gsub("%.lua", "")
print(fileWithoutExtension)
local fsm = require(fileWithoutExtension)
if not is_state(fsm) then
error("rfsm.load: no valid rfsm in file '" .. tostring(file) .. "' found.")
end
return fsm
end
如果我運行它,我會得到:
[runscript.lua] Before rfsm.load("mainTask.lua")
subTask
--- start of subTask.lua ---
--- end of subTask.lua ---
subTask
[runscript.lua] Before rfsm.init(fsm_)
lua: /home/anfr/rFSM-master/rfsm.lua:483: bad argument #1 to 'find' (string expected, got table)
stack traceback:
[C]: in function 'find'
/home/anfr/rFSM-master/rfsm.lua:483: in function '__resolve_path'
/home/anfr/rFSM-master/rfsm.lua:511: in function '__resolve_src'
/home/anfr/rFSM-master/rfsm.lua:551: in function 'func'
/home/anfr/rFSM-master/rfsm.lua:272: in function 'f'
/home/anfr/rFSM-master/utils.lua:246: in function 'map'
/home/anfr/rFSM-master/rfsm.lua:268: in function '__mapfsm'
/home/anfr/rFSM-master/rfsm.lua:275: in function 'f'
/home/anfr/rFSM-master/utils.lua:246: in function 'map'
/home/anfr/rFSM-master/rfsm.lua:268: in function '__mapfsm'
/home/anfr/rFSM-master/rfsm.lua:275: in function 'f'
/home/anfr/rFSM-master/utils.lua:246: in function 'map'
/home/anfr/rFSM-master/rfsm.lua:268: in function '__mapfsm'
/home/anfr/rFSM-master/rfsm.lua:283: in function 'mapfsm'
/home/anfr/rFSM-master/rfsm.lua:554: in function 'resolve_trans'
/home/anfr/rFSM-master/rfsm.lua:704: in function 'init'
runscript.lua:9: in main chunk
[C]: in ?
我不明白為什么我得到一個表格而不是一個字符串。 不幸的是,需要在 rFSM 庫代碼中導航以提供幫助,但我會很感激任何提示。
Ps:在subTask.lua
中將變量var
設為全局將給出正確的行為。 但是,我試圖避免兩次加載相同腳本的不必要開銷。
我想知道不同版本的LUA是否對此有影響
所有 Lua 版本都具有相同的對象引用分配語義。
如您所見,在 mainTask.lua 中,我們通過 rfsm.load("subTask.lua") 加載了 subTask.lua 兩次
當您使用require
時,將返回相同的狀態對象。
我不明白為什么我得到一個表格而不是一個字符串
函數resolve_trans(fsm)
將轉換的.src
字段從字符串轉換為對象(表)。
當您第二次解析相同的轉換對象時,會引發錯誤,因為tr.src
字段應為字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.