Need help for real time behavior with script/command/event/statemachine

Hello,

I have a state machine that receives events to initiate the movement of an
axis. I want to be able to call this event from a script, and wait for the
completion of the movement. To this end, I wrapped the event inside a
command. The moveAxis event/command have a variable number of parameters,
depending on which control strategy is selected (speed, position...) . Here
is what it looks like :

THE EVENT

Event<void(std::string controlStrategy, vector moveAxisEvent;

THE COMMAND

Command<bool(std::string controlStrategy, vector moveAxisCmd;

which calls the function :

bool moveAxisCommandWrapper(std::string controlStrategy, vector<double>
params)
{
moveAxisEvent(controlStrategy, params);
}

and ends when this function becomes true :

bool moveFinished()
{
return
engine()->states()->getStateMachine("myStateMachine")->inState("READY");
}

THE SCRIPT

program TestMove {

var array speedParams = array(1.0);
var string speedStrategy("Speed");

var array positionParams = array(1.0, 2.0, 3.0);
var string positionStrategy("Position");

moveToCommand(speedStrategy, speedParams);
moveToCommand(positionStrategy, positionParams);

}

THE STATE MACHINE

StateMachine MyStateMachine
{
var array controlParams;

initial state INIT {
transition select READY;
}

state READY {

transition moveAxisEvent(controlMode, controlParams)
if ((controlMode == "Position") && (controlParams.size() == 3))
then select POSITION;

transition moveAxisEvent(controlMode, controlParams)
if ((controlMode == "Speed") && (controlParams.size() == 1))
then select SPEED;
}

state POSITION {

entry {
do PositionController.start();
do PositionController.moveToMethod(controlParams[0],
controlParams[1], controlParams[2]);
}

exit {
do PositionController.stop();
}

transition if (!PositionController.isMoving) then select READY;

}

state SPEED {

entry {
do SpeedController.start();
do SpeedController.moveToMethod(controlParams[0]);
}

exit {
do SpeedController.stop();
}

transition if (!SpeedController.isMoving) then select READY;

}

[other states have been omitted]

}

So, the big question is : Is that real time? I think that it's real time
from the script (real-time array initialisation) to the command/event
(passing through the heap), but I'm not sure with the state machine. The
array "controlParams" is not initialized in the script. His size may vary
depending on which control strategy is called (size = 1 or 3).

Thank for your help!

Philippe

Re: Need help for real time behavior wih [...]

Well, I saw that my code didn't appeared correctly because I didn't use the good code syntax. I'm re-submitting the code in the good way :

THE EVENT

Event<void(std::string controlStrategy, vector<double> params)> moveAxisEvent;

THE COMMAND

Command<bool(std::string controlStrategy, vector<double> params)> moveAxisCmd;

which calls the function :

bool moveAxisCommandWrapper(std::string controlStrategy, vector<double> params)
{
    moveAxisEvent(controlStrategy, params);
}

and ends when this function becomes true :

bool moveFinished()
{
    return engine()->states()->getStateMachine("myStateMachine")->inState("READY");
}

THE SCRIPT

program TestMove {
 
var array speedParams = array(1.0);
var string speedStrategy("Speed");
 
var array positionParams = array(1.0, 2.0, 3.0);
var string positionStrategy("Position");
 
moveToCommand(speedStrategy, speedParams);
moveToCommand(positionStrategy, positionParams);
 
}

THE STATE MACHINE

StateMachine MyStateMachine
{
    var array controlParams;
 
    initial state INIT {
        transition select READY;
    }
 
    state READY {
 
        transition moveAxisEvent(controlMode, controlParams)
            if ((controlMode == "Position") && (controlParams.size() == 3)) then select POSITION;
 
        transition moveAxisEvent(controlMode, controlParams)
            if ((controlMode == "Speed") && (controlParams.size() == 1)) then select SPEED;
    }
 
    state POSITION {
 
        entry {
            do PositionController.start();
            do PositionController.moveToMethod(controlParams[0], controlParams[1], controlParams[2]);
        }
 
        exit {
            do PositionController.stop();
        }
 
        transition if (!PositionController.isMoving) then select READY;
 
    }
 
    state SPEED {
 
        entry {
            do SpeedController.start();
            do SpeedController.moveToMethod(controlParams[0]);
        }
 
        exit {
            do SpeedController.stop();
        }
 
        transition if (!SpeedController.isMoving) then select READY;
 
    }
 
[other states have been omitted]
 
}

Need help for real time behavior wih [...]

On Monday 23 March 2009 14:05:26 philippe [dot] hamelin [..] ... wrote:
> Well, I saw that my code didn't appeared correctly because I didn't use the
> good code syntax. I'm re-submitting the code in the good way :

(I'm still looking for a way to get the < and > symbols be displayed correctly on the forum.)

>
> THE EVENT
>
>

> Event<void(std::string controlStrategy, vector<double> params)>
> moveAxisEvent; 

This has already issues. What you need to write is:

Event<void(const string& controlStrategy, const vector&<double> params)> moveAxisEvent; 

You must pass string and vector by const reference and not by value. Passing them by
value will lead to copies, and memory allocation. The scripting can
cope with const references, so just change your C++ part.

>
> THE COMMAND
>
>

> Command<bool(std::string controlStrategy, vector<double> params)>
> moveAxisCmd; 

Ditto.

>
> which calls the function :
>
>

> bool moveAxisCommandWrapper(std::string controlStrategy, vector<double>
> params) {
>     moveAxisEvent(controlStrategy, params);
> }
> 

Ditto.

>
> and ends when this function becomes true :
>
>

> bool moveFinished()
> {
>     return
> engine()->states()->getStateMachine("myStateMachine")->inState("READY"); }
> 

OK.

>
> THE SCRIPT
>
>

> program TestMove {
>
> var array speedParams = array(1.0);
> var string speedStrategy("Speed");
 
Both real-time .
 
>
> var array positionParams = array(1.0, 2.0, 3.0);
> var string positionStrategy("Position");
 
Both real-time.
 
>
> moveToCommand(speedStrategy, speedParams);
> moveToCommand(positionStrategy, positionParams);
 
Real-time if signature above is correct.
 
>
> }
> 

>
> THE STATE MACHINE
>
>
> StateMachine MyStateMachine
> {
>     var array controlParams;
 
This is indeed a variable size vector which may allocate. There is however an easy
fix: use a capacity 'hint' declaration:
 
var array controlParams(3); // max capacity == 3.
 
If you then write 
controlParams =  array(1.0); // use  1 out of 3 elements.
controlParams =  array(1.0,2.0,4.0); // use  3 out of 3 elements.
 
>
>     initial state INIT {
>         transition select READY;
>     }
>
>     state READY {
>
>         transition moveAxisEvent(controlMode, controlParams)
>             if ((controlMode == "Position") && (controlParams.size() == 3))
> then select POSITION;
>
>         transition moveAxisEvent(controlMode, controlParams)
>             if ((controlMode == "Speed") && (controlParams.size() == 1))
> then select SPEED; }
 
This check is real-time. Comparing stuff (and size()/capacity()) is real-time.
 
>
>     state POSITION {
>
>         entry {
>             do PositionController.start();
>             do PositionController.moveToMethod(controlParams[0],
> controlParams[1], controlParams[2]); }
>
>         exit {
>             do PositionController.stop();
>         }
>
>         transition if (!PositionController.isMoving) then select READY;
>
>     }
>
>     state SPEED {
>
>         entry {
>             do SpeedController.start();
>             do SpeedController.moveToMethod(controlParams[0]);
>         }
>
>         exit {
>             do SpeedController.stop();
>         }
>
>         transition if (!SpeedController.isMoving) then select READY;
>
>     }
>
> [other states have been omitted]
>
> }
> 

I don't see any issues other than the one discussed. The main points to remember are:
1. Use const reference for passing string/vector in real-time code (even if not using scripting)
2. Use the capacity hint in array or string declarations in scripting such that the scripting
language knows how much space it must allocate to hold all your data elements.

Hope this helps,
Peter

Need help for real time behavior wih [...]

I tried to pass constant reference to my event and it gives me a bunch of
error in DataSourceAdaptor and EventProcessor. I did a simple example (see
TestEvent.cpp and TestEvent.h in attachment) with a const std::string &. It
seems that there's no problem with the "const" keyword, but rather with the
reference "&". The build log (TestEventBuild.log) is also in attachment.
Does passing reference to events has already been tested with RTT 1.8.x ?

Thank you,

Philippe Hamelin

2009/3/23 Peter Soetens <peter [dot] soetens [..] ...>

> On Monday 23 March 2009 14:05:26 philippe [dot] hamelin [..] ... wrote:
> > Well, I saw that my code didn't appeared correctly because I didn't use
> the
> > good code syntax. I'm re-submitting the code in the good way :
>
> (I'm still looking for a way to get the < and > symbols be displayed
> correctly on the forum.)
>
> >
> > THE EVENT
> >
> >

> > Event<void(std::string controlStrategy, vector<double> params)>
> > moveAxisEvent; 

>
> This has already issues. What you need to write is:
>
> Event<void(const string& controlStrategy, const vector&<double> params)>
> moveAxisEvent;
> 

>
> You must pass string and vector by const reference and not by value.
> Passing them by
> value will lead to copies, and memory allocation. The scripting can
> cope with const references, so just change your C++ part.
>
> >
> > THE COMMAND
> >
> >
> > Command<bool(std::string controlStrategy, vector<double> params)>
> > moveAxisCmd; 

>
> Ditto.
>
> >
> > which calls the function :
> >
> >
> > bool moveAxisCommandWrapper(std::string controlStrategy, vector<double>
> > params) {
> >     moveAxisEvent(controlStrategy, params);
> > }
> > 

>
> Ditto.
>
> >
> > and ends when this function becomes true :
> >
> >
> > bool moveFinished()
> > {
> >     return
> > engine()->states()->getStateMachine("myStateMachine")->inState("READY");
> }
> > 

>
> OK.
>
> >
> > THE SCRIPT
> >
> >
> > program TestMove {
> >
> > var array speedParams = array(1.0);
> > var string speedStrategy("Speed");
>
> Both real-time .
>
> >
> > var array positionParams = array(1.0, 2.0, 3.0);
> > var string positionStrategy("Position");
>
> Both real-time.
>
> >
> > moveToCommand(speedStrategy, speedParams);
> > moveToCommand(positionStrategy, positionParams);
>
> Real-time if signature above is correct.
>
> >
> > }
> > 

> >
> > THE STATE MACHINE
> >
> >
> > StateMachine MyStateMachine
> > {
> >     var array controlParams;
>
> This is indeed a variable size vector which may allocate. There is however
> an easy
> fix: use a capacity 'hint' declaration:
>
> var array controlParams(3); // max capacity == 3.
>
> If you then write
> controlParams =  array(1.0); // use  1 out of 3 elements.
> controlParams =  array(1.0,2.0,4.0); // use  3 out of 3 elements.
>
> >
> >     initial state INIT {
> >         transition select READY;
> >     }
> >
> >     state READY {
> >
> >         transition moveAxisEvent(controlMode, controlParams)
> >             if ((controlMode == "Position") && (controlParams.size() ==
> 3))
> > then select POSITION;
> >
> >         transition moveAxisEvent(controlMode, controlParams)
> >             if ((controlMode == "Speed") && (controlParams.size() == 1))
> > then select SPEED; }
>
> This check is real-time. Comparing stuff (and size()/capacity()) is
> real-time.
>
> >
> >     state POSITION {
> >
> >         entry {
> >             do PositionController.start();
> >             do PositionController.moveToMethod(controlParams[0],
> > controlParams[1], controlParams[2]); }
> >
> >         exit {
> >             do PositionController.stop();
> >         }
> >
> >         transition if (!PositionController.isMoving) then select READY;
> >
> >     }
> >
> >     state SPEED {
> >
> >         entry {
> >             do SpeedController.start();
> >             do SpeedController.moveToMethod(controlParams[0]);
> >         }
> >
> >         exit {
> >             do SpeedController.stop();
> >         }
> >
> >         transition if (!SpeedController.isMoving) then select READY;
> >
> >     }
> >
> > [other states have been omitted]
> >
> > }
> > 

>
> I don't see any issues other than the one discussed. The main points to
> remember are:
> 1. Use const reference for passing string/vector in real-time code (even if
> not using scripting)
> 2. Use the capacity hint in array or string declarations in scripting such
> that the scripting
> language knows how much space it must allocate to hold all your data
> elements.
>
> Hope this helps,
> Peter
> --
> Peter Soetens -- FMTC -- <http://www.fmtc.be>
>

Need help for real time behavior wih [...]

On Tuesday 24 March 2009 13:57:47 Philippe Hamelin wrote:
> I tried to pass constant reference to my event and it gives me a bunch of
> error in DataSourceAdaptor and EventProcessor. I did a simple example (see
> TestEvent.cpp and TestEvent.h in attachment) with a const std::string &. It
> seems that there's no problem with the "const" keyword, but rather with the
> reference "&". The build log (TestEventBuild.log) is also in attachment.
> Does passing reference to events has already been tested with RTT 1.8.x ?

Looking at the build errors, this isn't going to be fixed easily. Also, they
are in a part which is going to disappear in RTT 2.0, but I can't tell yet if
that will fix the overall issue as well. The other fix is to use a real-time
malloc allocator in your string/vector types (and add them as such to the type
system) Also not a small change, and planned food for RTT 2.0.

So I can't help you in the short term. You'll have to accept (or measure) the
small copy allocations and/or work around it.

Peter