Project

General

Profile

Genom3tutorialdemo-genom3 » History » Version 4

Aurélie Clodic, 2014-04-10 15:41

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