Guard function defined in ConfigureHook

Hi,

I am trying to use as a guard for an rFSM transition a function that I
define in the ConfigureHook of the component that loads the statemachine.

When I put the function directly in the rfsm file it works fine:

trans {src="NotAllReady", tgt="AllReady",
guard= function()
for i=1,n_agents,1 do
if get_agent_state(i) ~= "root.Ready" then return false end
end
return true
end
},

But when I do:

trans {src="NotAllReady", tgt="AllReady",
guard=all_agents_ready()
},

With in the ConfigureHook:

all_agents_ready=function()
for i=1,n_agents,1 do
if get_agent_state(i) ~= "root.Ready" then return false end
end
return true
end

I get the following error:
0.394 [ ERROR ][ScriptingService] LuaComponent 'Coordinator': error
calling function configureHook: fsm_coordinator.lua:39: attempt to call
global 'all_agents_ready' (a nil value)

This same function does work fine as entry, doo or exit function. So why
not as guard? Is this a bug or is there a reason for that?

Thanks!

Bert

Guard function defined in ConfigureHook

On Mon, Jan 21, 2013 at 03:09:56PM +0100, Bert Willaert wrote:
>
> Hi,
>
> I am trying to use as a guard for an rFSM transition a function that I define
> in the ConfigureHook of the component that loads the statemachine.
>
> When I put the function directly in the rfsm file it works fine:
>
> trans {src="NotAllReady", tgt="AllReady",
> guard= function()
> for i=1,n_agents,1 do
> if get_agent_state(i) ~= "root.Ready" then return false end
> end
> return true
> end
> },
>
> But when I do:
>
> trans {src="NotAllReady", tgt="AllReady",
> guard=all_agents_ready()
> },

You are assigning the return value of calling all_agents_ready() to
the guard. Unless all_agents_ready happens to generate a guard
function, this should probably be

guard=all_agents_ready,

> With in the ConfigureHook:
>
> all_agents_ready=function()
> for i=1,n_agents,1 do
> if get_agent_state(i) ~= "root.Ready" then return false end
> end
> return true
> end
>
> I get the following error:
> 0.394 [ ERROR ][ScriptingService] LuaComponent 'Coordinator': error calling
> function configureHook: fsm_coordinator.lua:39: attempt to call global
> 'all_agents_ready' (a nil value)

I suppose you get this error because you are calling the guard above,
but your configureHook has not executed, so the function is not
defined yet. So even if you follow my above suggestion, you still need
to ensure that all_agents_ready is defined before you define or load
the fsm. You can achieve that by means of a forward declaration of
all_agents_ready somewhere at the top of your Lua component:

all_agents_ready=false

or

all_agents_ready=function() error("redefined in configureHook") end

to get an error in case the function is called.

> This same function does work fine as entry, doo or exit function. So why not as
> guard? Is this a bug or is there a reason for that?

Markus

Guard function defined in ConfigureHook

On Mon, Jan 21, 2013 at 3:48 PM, Markus Klotzbuecher <
markus [dot] klotzbuecher [..] ...> wrote:

> On Mon, Jan 21, 2013 at 03:09:56PM +0100, Bert Willaert wrote:
> >
> > Hi,
> >
> > I am trying to use as a guard for an rFSM transition a function that I
> define
> > in the ConfigureHook of the component that loads the statemachine.
> >
> > When I put the function directly in the rfsm file it works fine:
> >
> > trans {src="NotAllReady", tgt="AllReady",
> > guard= function()
> > for i=1,n_agents,1 do
> > if get_agent_state(i) ~= "root.Ready" then return false
> end
> > end
> > return true
> > end
> > },
> >
> > But when I do:
> >
> > trans {src="NotAllReady", tgt="AllReady",
> > guard=all_agents_ready()
> > },
>
> You are assigning the return value of calling all_agents_ready() to
> the guard. Unless all_agents_ready happens to generate a guard
> function, this should probably be
>
> guard=all_agents_ready,
>

Ok, I see. After changing this, there is no more error given.

>
>
> > With in the ConfigureHook:
> >
> > all_agents_ready=function()
> > for i=1,n_agents,1 do
> > if get_agent_state(i) ~= "root.Ready" then return false end
> > end
> > return true
> > end
> >
> > I get the following error:
> > 0.394 [ ERROR ][ScriptingService] LuaComponent 'Coordinator': error
> calling
> > function configureHook: fsm_coordinator.lua:39: attempt to call global
> > 'all_agents_ready' (a nil value)
>
> I suppose you get this error because you are calling the guard above,
> but your configureHook has not executed, so the function is not
> defined yet. So even if you follow my above suggestion, you still need
> to ensure that all_agents_ready is defined before you define or load
> the fsm. You can achieve that by means of a forward declaration of
> all_agents_ready somewhere at the top of your Lua component:
>
> all_agents_ready=false
>
> or
>
> all_agents_ready=function() error("redefined in configureHook") end
>
> to get an error in case the function is called.
>

Hmm,

Forward declaration seems to help only when I put the full function
definition before:

fsm = rfsm.init(rfsm.load("Coordinator/fsm_coordinator.lua"))

In the other case, i.e. without forward declaration or with
all_agents_ready=false, the transition happens 'each time' while it
shouldn't ???

>
> > This same function does work fine as entry, doo or exit function. So why
> not as
> > guard? Is this a bug or is there a reason for that?
>

So far, I haven't done forward declaration of functions used in the entry,
exit or doo function and I never got trouble with it.
Is it needed here, and not in the other cases, because you assign to the
value guard actually the function itself,
while in a enty function for example you are only interested in the return
value?

>
> Markus
>
>
>

Guard function defined in ConfigureHook

On Mon, Jan 21, 2013 at 04:41:14PM +0100, Bert Willaert wrote:
> On Mon, Jan 21, 2013 at 3:48 PM, Markus Klotzbuecher
> markus [dot] klotzbuecher [..] ...> wrote:
>
> On Mon, Jan 21, 2013 at 03:09:56PM +0100, Bert Willaert wrote:
...

> > With in the ConfigureHook:
> >
> > all_agents_ready=function()
> > for i=1,n_agents,1 do
> > if get_agent_state(i) ~= "root.Ready" then return false end
> > end
> > return true
> > end
> >
> > I get the following error:
> > 0.394 [ ERROR ][ScriptingService] LuaComponent 'Coordinator': error
> calling
> > function configureHook: fsm_coordinator.lua:39: attempt to call global
> > 'all_agents_ready' (a nil value)
>
> I suppose you get this error because you are calling the guard above,
> but your configureHook has not executed, so the function is not
> defined yet. So even if you follow my above suggestion, you still need
> to ensure that all_agents_ready is defined before you define or load
> the fsm. You can achieve that by means of a forward declaration of
> all_agents_ready somewhere at the top of your Lua component:
>
> all_agents_ready=false
>
> or
>
> all_agents_ready=function() error("redefined in configureHook") end
>
> to get an error in case the function is called.
>
>
> Hmm,
>
> Forward declaration seems to help only when I put the full function definition
> before:
>
> fsm = rfsm.init(rfsm.load("Coordinator/fsm_coordinator.lua"))
>
> In the other case, i.e. without forward declaration or with all_agents_ready=
> false, the transition happens 'each time' while it shouldn't ???

Because in that case the variable all_agents_ready is undefined so the
guard is assigned nil which is indistinguishable from not having a
guard. Thus I usally recommend writing

guard=function() return all_agents_ready() end

Which will catch the error that all_agents_ready is undefined. An
other option is to load the strict module [1], which will catch access
to undeclared global variables (but this may lead to complaints about
other non-error cases).

>
> > This same function does work fine as entry, doo or exit function. So why
> not as
> > guard? Is this a bug or is there a reason for that?
>
>
> So far, I haven't done forward declaration of functions used in the entry, exit
> or doo function and I never got trouble with it.
> Is it needed here, and not in the other cases, because you assign to the value
> guard actually the function itself,
> while in a enty function for example you are only interested in the return
> value?

No, you always have to ensure that a function is defined before you
assign it.

Markus

[1] http://metalua.luaforge.net/src/lib/strict.lua.html