Genom3tutorialdemo-genom3 » History » Revision 5
« Previous |
Revision 5/22
(diff)
| Next »
Aurélie Clodic, 2014-04-10 16:00
Genom3tutorialdemo-genom3¶
- Table of contents
- Genom3tutorialdemo-genom3
- read and set the current speed at any moment
- move the mobile to a given position
- move the mobile of a given distance (from its current position)
- monitor when the mobile passes a given position
- stop the motion
Moreover, the demo module export a port with the current state of the mobile (position and speed).
To implement this, we first create a directory named demo-genom3.
mkdir demo-genom3 cd demo-genom3
Write .gen file¶
In that directory, we will write the description file demo.gen. The file demo.gen is made up of several parts, each of them being identified with a keywordcomponent
ids
port
exception
task
attribute
function
activity
This .gen reflects the fact that a component need to define an interface made of a set of services and data ports. A component must provide a service invocation facility as well as unidirectional (input and output) data ports. It must be able to send and receive events. It has to define an internal data structure, named the ids
, that is used by codels to store global and permanent objects.
Each codel has access to the ids
objects and use them to communicate with other codels within the component.
Finally, a component has to define one or more execution tasks
that represent the execution context (e.g. thread) in which services are run. Those tasks may be periodic or aperiodic.
The easiest way is to see how all of this is defined is to start from an existing file, so you can download ".gen" file. We will now explain step by step each part of this file.
component
¶
The component declaration describes the instance of the GenoM3 component. It is defined by a unique name (an identifier) that also defines an IDL scope for any embedded types. See the component declaration documentation for details.
component demo { version "1.1"; email "openrobots@laas.fr"; lang "c"; require "genom3 >= 2.99.20";
- version : The component version number, as a string
- lang : The programming language of the codels interface
- email : A string containing the e-mail address of the author of the component.
- requires : A list of dependencies of the component. It indicates an external dependency on a software package that is required. It assumes that the package is using the pkg-config utility. Each string should contain a package name in pkg-config format.
NB: component declaration is not over, the final } is left for the end .gen
file.
ids
¶
ids
stands for internal data structure, it is used by codels to store global and permanent objects.
Each codel has access to the ids
objects and use them to communicate with other codels within the component.
For our example, we considerto store the state, the speed reference and the position of the mobile:
ids { demo::state state; /* Current state */ demo::speed speedRef; /* Speed reference */ double posRef; };
demo::state
and demo::speed
are types derived from ...
port
¶
A component define input and output data ports, used to implement data flow connections in parallel to services.
Ports implement the data flow between components as a publish/subscribe model. Ports have a name and a type and can be either out (for publishing data) or in (for subscribing to a sibling out port). Data ports Data ports are defined via the in or out keyword, followed by an IDL type and the name of the port e.g.:
port in data<type> name; port out data<type> name;
In our example, we choose to export the state of the mobile to let this information accessible for example to another port from another component:
/* ---- Port declaration ---- */ port out demo::state Mobile;
exception
¶
It is possible to
/* ---- exception declaration ---- */ exception TOO_FAR_AWAY {double overshoot;}; exception INVALID_SPEED;
execution task
¶
Tasks define an execution context suitable for running activities. A task may define a state machine and associated codels. The state machine starts in the start state when the task is created during component initialization.
Tasks can define the following properties:
period
The granularity of the codel scheduler. Periodic task will sequence the codels they manage at that frequency.delay
The delay from the beginning of each period after which codels are run. This can be used to delay two tasks running at the same period in the same component.priority
Can be used to prioritize different tasks whithin the same component.scheduling real-time
This indicates that the task requires real-time scheduling. This may not be supported by all templates.stack
Defines the required stack size for this task. The stack size should be big enough to run all codels that the task manages.
In our example, we choose to get the task_period from ...
/* ---- Execution task declaration ---- */ task motion { period demo::task_period ms; priority 100; stack 4000; codel <start> InitDemoSDI(out ::ids, port out Mobile) yield ether; };
services declations¶
A service is an interface for running codels. It can be invoked via a request on the component service port.
Services have optional input and output data and a list of failure reports. Input data is stored in the IDS (and output read from there), so that codels can access it.
A service might be incompatible with other services of the same component or can be started multiple time, provided it is compatible with itself. It always interrupts other incompatible services when starting.
A service invocation triggers an activity that manages codel execution. An activity is described by a Petri net in which places correspond to codels execution and transitions are events generated either externally or implicitely by the return value of codels.
service name(inout s) { doc "Service description"; task taskname; validate svalidate(); throws ERROR_1, ERROR_2, ...; interrupts name; codel <start> sstart() yield step1; codel <step1> sstep1() yield step1, step2; codel <step2> sstep2() yield ether; codel <stop> sstop() yield ether; };
where:
name
corresponds to the name of the services
corresponds to the parameter of the service. Parameter could be in/inout/out depending of its type. It is possible to have several parameters.task
corresponds to the task that handle the servicevalidate
corresponds to a function that would be called once at the beginning of the service execution and that aims to check service parameter(s) consistencythrows
corresponds to the list of failure report(s)interrupts
corresponds to the service(s) that would be automatically interrupted when the this service is called
When an activity starts, the start event is generated and the corresponding codel executed. Similarly, the activity is interrupted whenever the stop event is generated.
Asynchronous events trigger the execution of the corresponding codel (if any). A special sleep transition is defined so that an activity can be put in a sleeping state, waiting for external events or a stop to trigger a new transition. The activity stops when all active places in the Petri net have returned the special ether event. If the execution task of a service is periodic, transitions are executed at each period. They are otherwise executed as soon as all the codels corresponding to active places have returned. The codel execution order is undefined.
It should be noted that no direct remote procedure call (RPC) for service invocation between components is allowed. RPC should be performed by external applications that take care of setting up the architecture of com-
ponents. While this differs from traditional approaches, this guarantees that components can be controlled and will not interfere with the system. This also grants an increased reusability since no component explicitely depends on a particular set of services implemented by other components.
3 types of services are available through GenoM3: attribute, function and activity. Each follow the same service pattern.
attribute
¶
attribute
service type should be used to
attribute SetSpeed(in speedRef = demo::SLOW :"Mobile speed") { doc "To change speed"; validate controlSpeed (local in speedRef); throw INVALID_SPEED; }; attribute GetSpeed(out speedRef = :"Mobile speed") { doc "To get current speed value"; };
function
function Stop()
{
doc "Stops motion and interrupts all motion requests";
interrupts MoveDistance, GotoPosition;
};
activity
activity MoveDistance(in double distRef = 0 :"Distance in m")
{
doc "Move of the given distance";
validate controlDistance(in distRef, in state.position);
codel <start> mdStartEngine(in distRef, in state.position,
out posRef) yield exec, ether;
codel <exec> mdGotoPosition(in speedRef, in posRef, inout state,
port out Mobile) yield exec, end;
codel <end, stop> mdStopEngine() yield ether;
interrupts MoveDistance, GotoPosition;
task motion;
throw TOO_FAR_AWAY;
};
Updated by Aurélie Clodic over 10 years ago · 22 revisions