-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhowToUseExpressions
226 lines (138 loc) · 5.58 KB
/
howToUseExpressions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
This node, the way you can find it now, needs a lot of refactoring! It was just an approach of how to accomplish Q.bo expressions, but due to scheduling problems, it was never finished properly.
=== How it work? ===
qbo_expression is a node which load a file /config/feelings.xml, and traduce the XML code into an array which will be interpreted by ThreadCmd.py
later on.
After loading and decoding feelings.xml, it subscribes to the topic /Qbo/runExpression, waiting for a std_msgs/String message with the name of the expression to fake. That name has to be one of the feelings written at feelings.xml.
For example, feelings.xml might look like this:
<feeling yes_move>
<movement>
<eyes 200>
<wait -1>
</movement>
<movement 3>
<mouth smile>
<head_relative 0 -70 0.0 0.7>
<wait 0.2>
<head_relative 0 70 0.0 0.7>
<wait 0.2>
</movement>
<movement>
<mouth smile>
<wait 5>
<expression neutral>
</movement>
</feeling>
and that would be translated to
{'yes_move': "['m', 'e', '200', 'w', '-1', 'm', 'm', 'o', 'smile', 'v', '0', '-70', '0.0', '0.7', 'w', '0.2', 'v', '0', '70', '0.0', '0.7', 'w', '0.2', 'o', 'smile', 'v', '0', '-70', '0.0', '0.7', 'w', '0.2', 'v', '0', '70', '0.0', '0.7', 'w', '0.2', 'o', 'smile', 'v', '0', '-70', '0.0', '0.7', 'w', '0.2', 'v', '0', '70', '0.0', '0.7', 'w', '0.2', 'm', 'm', 'o', 'smile', 'w', '5', 'x', ['m', 'e', '270', 'o', 'none', 'h', '0', '50', '1.0', '1.0', 'w', '-1', 'm'], 'm']",}
And this is what is given to the MainThread in ThreadsCmd.py
== ThreadsCmd.py
Each component of an expression launch its own thread, that means one for eyes, one for head movement, one for mouths, and so on. The MainThread reads each position of the array above, and execute what is needed. If the position is, for example, 'e' that means it has to launch/reactivate the thread for both eyes, which will move them to the position 200, or if it is an 'o' it will launch/reactivate the thread in charge of mouths.
There are one thread for head movement, one for relative head movement, one for left eye, right eye, both eyes, mouths and speaking.
=== How to create an expression in feelings.xml ===
1.- An expression has to be written between <feeling [name]> and </feeling>
[name] is the name of the expression. For example: happy, sad, etc
2.- Inside these labels, you have to define one, or more, movements with labels: <movement [loop]> and </movement>
[loop] makes this movement to repeat its content as many times as [loop] says.
For example:
...
<movement 4>
<say hello>
</movement>
...
Will say four times "hello"
If you do not want to make any loop, do not write a number.
For example:
...
<movement>
<say hello>
</movement>
...
Will say "hello" only once.
3.- Inside a movement you can use:
___ <head [pan_position] [tilt_position] [pan_speed] [tilt_speed]> ___
It moves the head to [pan_position] and [tilt_position] with the speed defined at [pan_speed] and [tilt_speed]
Positions are between [-200, 200]
Speeds are between [0, 1.0], where 0 is no move and 1.0 maximum speed.
Examples:
Let's make a "no" move, moving the head from left to right and vice versa.
<feeling no>
<movement 2>
<head -50 0 0.7 0.0>
<wait -1>
<head 50 0 0.7 0.0>
<wait -1>
</movement>
</feeling>
Now a "yes" move, moving the head up and down.
<feeling yes>
<movement 3>
<mouth smile>
<head_relative 0 -70 0.0 0.7>
<wait 0.2>
<head_relative 0 70 0.0 0.7>
<wait 0.2>
</movement>
</feeling>
___ <head_relative [pan_position] [tilt_position] [pan_speed] [tilt_speed]> ___
Same as above, but now the positions are relative to the actual position of the head.
___ <eyes [position]> ___
Moves both eyes to [position]
[position] is between [0,280] grades
___ <leftEye [position]> ___
Like before but now only the left eye.
___ <rightEye [position]> ___
Like before but now only the right eye.
___ <wait [seconds]> ___
It pauses the action the time specified by [seconds]. If it is "-1" it will wait indefinitely until all the previous threads finish their movements
.
Example:
<wait 2.5> It will wait 2.5 seconds
___ <mouth [mouth_name]> ___
It displays the mouth corresponding to [mouth_name
]
[mouth_name] can adopt all this values:
-smile
-none
-sad
-puckerRight
-puckerLeft
-staight
-smallMouth
-surprise
-regular
-laugh
-laugh2
-laugh3
-laugh4
-laugh5
-laugh6
-tongue
___ <say [sentence]> ___
It makes the Q.bo to speak the sentence written at [sentence].
Examples
<say hello how are you>
<say hi my name is qbo>
<say goodbye>
So far we have defined all the parameters with numbers, but you can also get random numbers with rand(minValue&maxValue).
For example:
<feeling random_move>
<movement 4>
<eyes rand(90&150)>
<wait -1>
</movement>
</feeling>
This will make the eyes to move randomly to positions between 90 and 150 degrees.
You can also nest expressions. In order to call an expression inside other just use the label <expression [expression_name]>
For example:
<feeling example>
<movement>
<say I can be happy>
<wait -1>
<expression happy>
<movement>
<movement>
<say and also sad>
<wait -1>
<expression sad_move>
<movement>
</feeling>