Statistics
| Branch: | Tag: | Revision:

hlrc / server / src / Arbiter.cpp @ e21d7f2c

History | View | Annotate | Download (9.221 KB)

1 0c286af0 Simon Schulz
/*
2
* This file is part of hlrc_server
3
*
4
* Copyright(c) sschulz <AT> techfak.uni-bielefeld.de
5
* http://opensource.cit-ec.de/projects/hlrc_server
6
*
7
* This file may be licensed under the terms of the
8
* GNU General Public License Version 3 (the ``GPL''),
9
* or (at your option) any later version.
10
*
11
* Software distributed under the License is distributed
12
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13
* express or implied. See the GPL for the specific language
14
* governing rights and limitations.
15
*
16
* You should have received a copy of the GPL along with this
17
* program. If not, go to http://www.gnu.org/licenses/gpl.html
18
* or write to the Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
*
21
* The development of this software was supported by the
22
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
23
* The Excellence Cluster EXC 277 is a grant of the Deutsche
24
* Forschungsgemeinschaft (DFG) in the context of the German
25
* Excellence Initiative.
26
*
27
*/
28
29
#include "Arbiter.h"
30
#include "AudioPlayerLibAO.h"
31
#include "AudioPlayerRSB.h"
32
#include <boost/algorithm/string/predicate.hpp>
33
34
using namespace boost;
35
using namespace std;
36
37
38
Arbiter::Arbiter(std::string audio_output){
39
    //initialize audio player:
40
    if (iequals(audio_output.substr(0,3), "rsb")){
41
        #ifdef RSB_SUPPORT
42
            audio_player = new AudioPlayerRSB(audio_output);
43
        #else
44
            printf("> ERROR: hlc is compiled without RSB support, RSB audio transport not available, defaulting to libao (default output!)\n");
45
            audio_player = new AudioPlayerLibAO("");
46
        #endif
47
    }else{
48
        audio_player = new AudioPlayerLibAO(audio_output);
49
    }
50
51
    //set default emotion:
52
    emotion_config_current.init_sad();
53
    emotion_config_current.set_duration(2000);
54
    emotion_config_default.init_neutral();
55 2e526a15 Simon Schulz
56
    utterance = boost::shared_ptr<Utterance>(new Utterance());
57 0c286af0 Simon Schulz
}
58
59
Arbiter::~Arbiter(){
60
}
61
62
void Arbiter::set_default_emotion(EmotionState e){
63
    //lock access
64
    mutex::scoped_lock scoped_lock(emotion_config_default_mutex);
65
66
    //update our config, ignore duration as this is the default emotion
67
    emotion_config_default.select_config(e.value);
68
69
    printf("> stored default emotion\n");
70
}
71
72
void Arbiter::set_current_emotion(EmotionState e){
73
    //lock access
74
    mutex::scoped_lock scoped_lock(emotion_config_current_mutex);
75
76
    //this will set a emotion override for a given time, after the timeout
77
    //we will return to the default emotion state:
78
    emotion_config_current.select_config(e.value);
79
    emotion_config_current.set_duration(e.duration);
80
81
    printf("> stored current emotion (val=%d, duration = %dms)\n",e.value, e.duration);
82
}
83
84
void Arbiter::set_mouth_config(MouthConfig m){
85
    //lock access
86
    mutex::scoped_lock scoped_lock(mouth_config_override_mutex);
87
88
    mouth_config = m;
89
}
90
91
void Arbiter::set_gaze_target(humotion::GazeState target){
92
    //lock access
93
    mutex::scoped_lock scoped_lock(requested_gaze_state_mutex);
94
95
    requested_gaze_state = target;
96
}
97
98
void Arbiter::set_mouth_target(humotion::MouthState target){
99
    //lock access
100
    mutex::scoped_lock scoped_lock(requested_mouth_state_mutex);
101
102
    requested_mouth_state = target;
103
}
104
105
//! note: this is blocking!
106
void Arbiter::play_animation(boost::shared_ptr<Animation> incoming_animation){
107
    //incoming animation, check if this would conflict with any pending animations:
108
    //lock access & iterate over vector:
109
    mutex::scoped_lock lock_av(active_animation_vector_mutex);
110
    active_animation_vector_t::iterator it;
111
    for(it = active_animation_vector.begin(); it<active_animation_vector.end(); it++){
112
        boost::shared_ptr<Animation> current_ani = *it;
113
        //check if the running animation collides with the incoming animation:
114
        if (current_ani->collides_with(incoming_animation.get())){
115
            //this would fail, we can not play this animation right now!
116
            throw runtime_error("incoming animation collides with unfinished active animation");
117
            return;
118
        }
119
    }
120
121
    //ok, fine. no other animations are active that would collide with the new request
122
    //thus it is safe to enqueue this item:
123
    active_animation_vector.push_back(incoming_animation);
124
125
    //unlock mutex
126
    lock_av.unlock();
127
128
    //start playback!
129
    incoming_animation->start();
130
131
    //block until ani was played back
132
    while(incoming_animation->is_active()){
133
        //printf("A"); fflush(stdout);
134
        usleep(1*1000); //1ms, save cpu cycles
135
    }
136
137
    //ok, it finished. we can safely remove it now:
138
    lock_av.lock();
139
    for(it = active_animation_vector.begin(); it<active_animation_vector.end();){
140
        boost::shared_ptr<Animation> current_ani = *it;
141
        if (*it == incoming_animation){
142
            //printf(">match -> remove incoming ani again\n");
143
            it = active_animation_vector.erase(it);
144
          }else{
145
            ++it;
146
          }
147
    }
148
}
149
150 2e526a15 Simon Schulz
void Arbiter::speak(boost::shared_ptr<Utterance> u){ //, ao_sample_format audio_format, char *audio_data, unsigned int audio_len){
151 0c286af0 Simon Schulz
    //lock audio playback as such:
152
    mutex::scoped_lock scoped_lock_audio(audio_player_mutex);
153
154
    //lock utterance & store data:
155
    mutex::scoped_lock scoped_lock(utterance_mutex);
156
    utterance = u;
157
    scoped_lock.unlock();
158
159
    //start audio playback, this function returns once we started playback
160 2e526a15 Simon Schulz
    audio_player->play(utterance->get_audio_data());
161
    utterance->start_playback();
162 0c286af0 Simon Schulz
163
    //wait until audio playback was finished:
164
    while(audio_player->is_playing()){
165
        //save some cpu cycles:
166
        usleep(1*1000); //1ms
167
    }
168
    //in case the audio output fails, we end up here before the utterance is finished.
169
    //so check now if the utterance finished as well:
170 2e526a15 Simon Schulz
    while (utterance->is_playing()){
171 0c286af0 Simon Schulz
        //save some cpu cycles:
172
        usleep(1*1000); //1ms
173
    }
174
175
}
176
177
bool Arbiter::speak_active(){
178
    return audio_player->is_playing();
179
}
180
181
void Arbiter::arbitrate(){
182
    //handle arbitration, DO NOT RE-ORDER these calls!
183
184
    //try to process all incoming requests
185
    override_by_emotion();
186
187
    //overwrite with mouth targets from outside:
188
    override_by_mouth();
189
190
    //lip animation
191
    override_by_utterance();
192
193
    //animations
194
    override_by_animation();
195
196
    //gaze target is set by requested_gaze_target
197
    override_by_gaze();
198
}
199
200
void Arbiter::override_by_utterance(){
201
    //fetch MouthState by utterance:
202 2e526a15 Simon Schulz
    if (!utterance->is_playing()){
203 0c286af0 Simon Schulz
        //not playing -> return
204
        return;
205
    }
206
207
    //fetch symbol
208 2e526a15 Simon Schulz
    string symbol = utterance->currently_active_phoneme();
209 0c286af0 Simon Schulz
    if ((symbol.empty()) || (symbol == "")){
210
        return;
211
    }
212
213
    //fetch config
214
    mouth_config.init_by_symbol(symbol);
215
216
    //overwrite mouth with offsets from utterance player
217
    mouth_config.apply_on_mouth_state(&mouth_state);
218
}
219
220
void Arbiter::override_by_mouth(){
221
    //external mouth requests can overwrite the mouth targets!
222
    if ((requested_mouth_state.position_center + requested_mouth_state.position_left + requested_mouth_state.position_right) > 0.0){
223
        //values given -> override emotion data
224
        mouth_state = requested_mouth_state;
225
    }
226
    //requested_mouth_state.dump();
227
    //mouth_state.dump();
228
}
229
230
void Arbiter::override_by_gaze(){
231
    //copy from requested target:
232
    gaze_state.pan   = requested_gaze_state.pan;
233
    gaze_state.tilt  = requested_gaze_state.tilt;
234
    gaze_state.roll  = requested_gaze_state.roll;
235
236
    gaze_state.timestamp = requested_gaze_state.timestamp;
237
    gaze_state.vergence  = requested_gaze_state.vergence;
238
239
    //add offset values from user:
240
    gaze_state.pan_offset  += requested_gaze_state.pan_offset;
241
    gaze_state.tilt_offset += requested_gaze_state.tilt_offset;
242
243
}
244
245
void Arbiter::override_by_emotion(){
246
    //lock access
247
    mutex::scoped_lock scoped_lock1(emotion_config_default_mutex);
248
    mutex::scoped_lock scoped_lock2(emotion_config_current_mutex);
249
250
    EmotionConfig *emotion_target = &emotion_config_default;
251
252
    //which emotion is active?
253
    if (emotion_config_current.is_active()){
254
        //current emotion is not timed out, override default
255
        emotion_target = &emotion_config_current;
256
    }
257
258
    //emotions will set the mouth state here (will be overwritten by speak)
259
    mouth_state = emotion_target->mouth_override;
260
261
    //emotions will add an offset to the gaze state:
262
    //pan,tilt,roll will be overwritten by override_by_gaze() we only keep the offset values from this!
263
    //FIXME: change to eyelid opening  upper/lower once humotion supports it
264
    //eyebrow angles come from this
265
    gaze_state = emotion_target->gaze_override;
266
    //gaze_state.dump();
267
268
    //IMPORTANT: clear request from emotion target:
269
    emotion_target->gaze_override.eyeblink_request_left = 0;
270
    emotion_target->gaze_override.eyeblink_request_right = 0;
271
272
}
273
274
275
void Arbiter::override_by_animation(){
276
    //lock access & iterate over vector:
277
    mutex::scoped_lock lock_av(active_animation_vector_mutex);
278
    active_animation_vector_t::iterator it;
279
    for(it = active_animation_vector.begin(); it<active_animation_vector.end(); it++){
280
        boost::shared_ptr<Animation> current_ani = *it;
281
282
        //gaze_state.dump();
283
        current_ani->apply_on_gazestate(&gaze_state);
284
        //gaze_state.dump();
285
    }
286
}
287
288
humotion::GazeState Arbiter::get_gaze_state(){
289
    return gaze_state;
290
}
291
292
humotion::MouthState Arbiter::get_mouth_state(){
293
    return mouth_state;
294
}