Project

General

Profile

Genom3tutorialdemo-genom3 » History » Version 6

Aurélie Clodic, 2014-04-10 16:14

1 1 Aurélie Clodic
h1. Genom3tutorialdemo-genom3
2
3
{{toc}}
4
5
6 6 Aurélie Clodic
This section will illustrate genom3 concepts through a concrete example. 
7
8
The demo compoment will control a virtual mobile that can move in a 1D world. Some of the services the module offers are:
9 1 Aurélie Clodic
* read and set the current speed at any moment
10
* move the mobile to a given position
11
* move the mobile of a given distance (from its current position)
12
* monitor when the mobile passes a given position
13
* stop the motion 
14
15 6 Aurélie Clodic
Moreover, the demo component export a port with the current state of the mobile (position and speed).
16 1 Aurélie Clodic
17
To implement this, we first create a directory named demo-genom3. 
18
19
<pre>
20
mkdir demo-genom3
21
cd demo-genom3
22
</pre>
23
24 6 Aurélie Clodic
h3. The component description file: .gen file
25 1 Aurélie Clodic
26 6 Aurélie Clodic
We will describe the .gen description file. It is made up of several parts, each of them being identified with a keyword
27 1 Aurélie Clodic
* @component@
28
* @ids@
29
* @port@
30
* @exception@
31
* @task@
32
* @attribute@
33
* @function@
34
* @activity@
35
36 5 Aurélie Clodic
This .gen reflects the fact that a component need to define 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 define an internal data structure, named the @ids@, that is used by codels to store global and permanent objects.
37
Each codel has access to the @ids@ objects and use them to communicate with other codels within the component.
38
Finally, a component has to define 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.
39 1 Aurélie Clodic
40 5 Aurélie Clodic
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.
41
42
43 1 Aurélie Clodic
h4. @component@
44
45 5 Aurélie Clodic
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":http://homepages.laas.fr/mallet/share/doc/genom3/genom3.html/Component-declaration.html#Component-declaration for details.
46 1 Aurélie Clodic
47
<pre>
48
component demo {
49
  version	"1.1";
50
  email		"openrobots@laas.fr";
51
  lang		"c";
52
  require	"genom3 >= 2.99.20";
53
</pre>
54
55
56
* version : The component version number, as a string
57
* lang : The programming language of the codels interface
58
* email : A string containing the e-mail address of the author of the component.
59 5 Aurélie Clodic
* 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. 
60 1 Aurélie Clodic
61
NB: component declaration is not over, the final } is left for the end @.gen@ file.
62
63
h4. @ids@
64
65 5 Aurélie Clodic
@ids@ stands for internal data structure, it is used by codels to store global and permanent objects.
66
Each codel has access to the @ids@ objects and use them to communicate with other codels within the component.
67
68
For our example, we considerto store the state, the speed reference and the position of the mobile: 
69 1 Aurélie Clodic
<pre>
70
ids {
71
  demo::state state;          /* Current state */
72
  demo::speed speedRef;       /* Speed reference */
73
  double      posRef;
74
};
75
</pre>
76
77 5 Aurélie Clodic
@demo::state@ and @demo::speed@ are types derived from ...
78
79 1 Aurélie Clodic
h4. @port@
80
81 5 Aurélie Clodic
A component define input and output data ports, used to implement data flow connections in parallel to services.
82
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 defined via the in or out keyword, followed by an IDL type and the name of the port e.g.: 
83 4 Aurélie Clodic
<pre>
84
port in data<type> name;
85
port out data<type> name;
86
</pre>
87
88 5 Aurélie Clodic
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:
89 1 Aurélie Clodic
<pre>
90
/* ---- Port declaration ---- */
91
  port out demo::state Mobile;
92
</pre>
93
94
h4. @exception@
95
96 6 Aurélie Clodic
It is possible to...
97 1 Aurélie Clodic
<pre>
98
/* ---- exception declaration ---- */
99
  exception TOO_FAR_AWAY {double overshoot;};
100
  exception INVALID_SPEED;
101
</pre>
102
103
h4. @execution task@
104
105
Tasks define an execution context suitable for running activities. A task may define a state machine and associated codels. 
106 6 Aurélie Clodic
The state machine starts in the start state when the task is created during component initialization. 
107
Task description follows this scheme:
108
<pre>
109
task name {
110
period: 100ms;
111
priority: 200;
112
stack: 20k;
113
codel start: tstart(in ::ids) yield main;
114
codel main: tmain(in d, out s)
115
yield main, stop;
116
codel stop: tstop() yield ether;
117
};
118
</pre>
119
120 1 Aurélie Clodic
Tasks can define the following properties:
121
* @period@ The granularity of the codel scheduler. Periodic task will sequence the codels they manage at that frequency.
122
* @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.
123
* @priority@ Can be used to prioritize different tasks whithin the same component.
124
* @scheduling real-time@ This indicates that the task requires real-time scheduling. This may not be supported by all templates.
125
* @stack@ Defines the required stack size for this task. The stack size should be big enough to run all codels that the task manages.
126
127
128
In our example, we choose to get the task_period from ...
129
<pre>
130
/* ---- Execution task declaration ---- */
131
132
  task motion {
133
    period	demo::task_period ms;
134
    priority	100;
135
    stack	4000;
136
    codel <start>	InitDemoSDI(out ::ids, port out Mobile) yield ether;
137
  };
138
</pre>
139 2 Aurélie Clodic
140
h4. services declations
141
142 6 Aurélie Clodic
A service is an interface for running codels. It can be invoked via a request on the component service port. A service has 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.
143 2 Aurélie Clodic
144 6 Aurélie Clodic
Service description follows this scheme:
145 2 Aurélie Clodic
<pre>
146
service name(inout s) {
147
doc "Service description";
148
task taskname;
149
validate svalidate();
150
throws ERROR_1, ERROR_2, ...;
151
interrupts name;
152
codel <start> sstart() yield step1;
153
codel <step1> sstep1() yield step1, step2;
154
codel <step2> sstep2() yield ether;
155
codel <stop> sstop() yield ether;
156
};
157
</pre>
158
where:
159
* @name@ corresponds to the name of the service
160
* @s@ corresponds to the parameter of the service. Parameter could be in/inout/out depending of its type. It is possible to have several parameters.
161
* @task@ corresponds to the task that handle the service
162
* @validate@ corresponds to a function that would be called once at the beginning of the service execution and that aims to check service parameter(s) consistency
163
* @throws@ corresponds to the list of failure report(s)
164
* @interrupts@ corresponds to the service(s) that would be automatically interrupted when the this service is called
165
166
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.
167
Asynchronous events trigger the execution of the corresponding codel (if any). A special sleep transition is defined 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 undefined.
168
169
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-
170
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.
171
172 3 Aurélie Clodic
3 types of services are available through GenoM3: attribute, function and activity. Each follow the same service pattern.
173 2 Aurélie Clodic
174 1 Aurélie Clodic
175
h5. @attribute@
176 3 Aurélie Clodic
177
@attribute@ service type should be used to 
178
179 1 Aurélie Clodic
<pre>
180
 attribute SetSpeed(in speedRef = demo::SLOW	:"Mobile speed")
181
  {
182
    doc		"To change speed";
183
    validate	controlSpeed (local in speedRef);
184
    throw	INVALID_SPEED;
185
  };
186
187
  attribute GetSpeed(out speedRef =	:"Mobile speed")
188
  {
189
    doc		"To get current speed value";
190
  };
191
</pre>
192
193
h5. @function@
194
<pre>
195
 function Stop()
196
  {
197
    doc		"Stops motion and interrupts all motion requests";
198
    interrupts	MoveDistance, GotoPosition;
199
  };
200
</pre>
201
202
h5. @activity@
203
<pre>
204
activity MoveDistance(in double distRef = 0	:"Distance in m")
205
  {
206
    doc		"Move of the given distance";
207
    validate	controlDistance(in distRef, in state.position);
208
209
    codel <start>	mdStartEngine(in distRef, in state.position,
210
                              out posRef) yield exec, ether;
211
    codel <exec>	mdGotoPosition(in speedRef, in posRef, inout state,
212
                               port out Mobile) yield exec, end;
213
    codel <end, stop>	mdStopEngine() yield ether;
214
    interrupts	MoveDistance, GotoPosition;
215
    task	motion;
216
    throw	TOO_FAR_AWAY;
217
  };
218
</pre>