Revision 3877047d
client/cpp/examples/random_gaze/main.cpp | ||
---|---|---|
58 | 58 |
gaze.vergence = 0.0; |
59 | 59 |
|
60 | 60 |
//absolute mode |
61 |
gaze.gaze_type = RobotGaze::ABSOLUTE; |
|
62 |
gaze.timestamp = RobotGaze::now();
|
|
61 |
gaze.gaze_type = RobotGaze::ABSOLUTE;
|
|
62 |
gaze.gaze_timestamp = RobotTimestamp::now();
|
|
63 | 63 |
|
64 | 64 |
//robot_controller->set_current_emotion(RobotEmotion(RobotEmotion::ANGRY)); |
65 | 65 |
|
client/cpp/include/RobotGaze.h | ||
---|---|---|
28 | 28 |
|
29 | 29 |
#pragma once |
30 | 30 |
#include <time.h> |
31 |
#include "RobotTimestamp.h" |
|
31 | 32 |
|
32 | 33 |
class RobotGaze{ |
33 | 34 |
public: |
34 |
RobotGaze(){ |
|
35 |
RobotGaze() : gaze_timestamp() {
|
|
35 | 36 |
pan = 0.0; |
36 | 37 |
tilt = 0.0; |
37 | 38 |
roll = 0.0; |
... | ... | |
41 | 42 |
gaze_type = ABSOLUTE; |
42 | 43 |
} |
43 | 44 |
|
44 |
static double now(){ |
|
45 |
/*static double now(){
|
|
45 | 46 |
//fetch time |
46 | 47 |
struct timespec tp; |
47 | 48 |
clock_gettime(CLOCK_REALTIME, &tp); |
48 | 49 |
return tp.tv_sec+tp.tv_nsec/1000000000.0; |
49 |
}; |
|
50 |
};*/
|
|
50 | 51 |
|
51 | 52 |
enum { |
52 | 53 |
RELATIVE = 0, |
53 | 54 |
ABSOLUTE = 1 |
54 | 55 |
}; |
55 | 56 |
|
56 |
double timestamp; |
|
57 |
|
|
57 |
RobotTimestamp gaze_timestamp; |
|
58 | 58 |
int gaze_type; |
59 | 59 |
|
60 | 60 |
float pan, tilt, roll, vergence; |
client/cpp/src/MiddlewareROS.cpp | ||
---|---|---|
154 | 154 |
goal.pan_offset = target.pan_offset; |
155 | 155 |
|
156 | 156 |
//timestamp: |
157 |
goal.timestamp = ros::Time(target.timestamp); |
|
157 |
goal.gaze_timestamp.sec = target.gaze_timestamp.sec; |
|
158 |
goal.gaze_timestamp.nsec = target.gaze_timestamp.nsec; |
|
158 | 159 |
|
159 | 160 |
if (target.gaze_type == RobotGaze::ABSOLUTE){ |
160 | 161 |
goal.gaze_type = hlrc_server::gazetargetGoal::GAZETARGET_ABSOLUTE; |
client/cpp/src/MiddlewareRSB.cpp | ||
---|---|---|
40 | 40 |
#include <boost/algorithm/string.hpp> |
41 | 41 |
#include <boost/range/algorithm_ext/erase.hpp> |
42 | 42 |
|
43 |
WARNING: RSB interface might be deprtecated and needs some backporting |
|
44 |
from the ROS code. [todo] |
|
45 |
|
|
43 | 46 |
using namespace std; |
44 | 47 |
using namespace rsb; |
45 | 48 |
using namespace rsb::patterns; |
client/python/CMakeLists.txt | ||
---|---|---|
6 | 6 |
|
7 | 7 |
find_program(PYTHON "python") |
8 | 8 |
|
9 |
#HACK for qtcreator ide integration. do not remove! |
|
10 |
file(GLOB_RECURSE HEADER_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.py) |
|
11 |
add_custom_target(python_sources SOURCES ${HEADER_LIST}) |
|
12 |
|
|
9 | 13 |
if (PYTHON) |
10 | 14 |
set(SETUP_PY "${CMAKE_CURRENT_SOURCE_DIR}/setup.py") |
11 | 15 |
set(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build") |
client/python/hlrc_client/Middleware.py | ||
---|---|---|
33 | 33 |
from RobotAnimation import * |
34 | 34 |
|
35 | 35 |
class Middleware: |
36 |
#######################################################################
|
|
37 |
def __init__(self, scope, loglevel=logging.WARNING):
|
|
38 |
"""initialise
|
|
39 |
:param scope: base scope we want to listen on
|
|
40 |
"""
|
|
41 |
self.base_scope = scope
|
|
42 |
|
|
43 |
self.logger = logging.getLogger(__name__)
|
|
44 |
|
|
45 |
# create nice and actually usable formatter and add it to the handler
|
|
46 |
self.config_logger(loglevel)
|
|
47 |
|
|
48 |
#initialise defaults
|
|
49 |
self.default_emotion = RobotEmotion()
|
|
50 |
self.current_emotion = RobotEmotion()
|
|
51 |
self.gaze_target = RobotGaze()
|
|
52 |
self.mouth_target = RobotMouth()
|
|
53 |
self.robot_animation = RobotAnimation()
|
|
54 |
|
|
36 |
#######################################################################
|
|
37 |
def __init__(self, scope, loglevel=logging.WARNING):
|
|
38 |
"""initialise |
|
39 |
:param scope: base scope we want to listen on
|
|
40 |
""" |
|
41 |
self.base_scope = scope |
|
42 |
|
|
43 |
self.logger = logging.getLogger(__name__) |
|
44 |
|
|
45 |
# create nice and actually usable formatter and add it to the handler |
|
46 |
self.config_logger(loglevel) |
|
47 |
|
|
48 |
#initialise defaults |
|
49 |
self.default_emotion = RobotEmotion() |
|
50 |
self.current_emotion = RobotEmotion() |
|
51 |
self.gaze_target = RobotGaze() |
|
52 |
self.mouth_target = RobotMouth() |
|
53 |
self.robot_animation = RobotAnimation() |
|
54 |
|
|
55 | 55 |
def __del__(self): |
56 |
"""destructor
|
|
57 |
"""
|
|
58 |
self.logger.debug("destructor of Middleware called")
|
|
59 |
|
|
60 |
def config_logger(self, level): |
|
56 |
"""destructor
|
|
57 |
"""
|
|
58 |
self.logger.debug("destructor of Middleware called")
|
|
59 |
|
|
60 |
def config_logger(self, level):
|
|
61 | 61 |
formatter = logging.Formatter('%(asctime)s %(name)-30s %(levelname)-8s > %(message)s') |
62 | 62 |
ch = logging.StreamHandler() |
63 | 63 |
#ch.setLevel(level) |
64 | 64 |
ch.setFormatter(formatter) |
65 | 65 |
self.logger.setLevel(level) |
66 | 66 |
self.logger.addHandler(ch) |
67 |
|
|
68 |
####################################################################### |
|
69 |
#abstract/virtual functions |
|
70 |
def die_virtual(self, funcname): |
|
71 |
raise NotImplementedError(funcname + "() is virtual, must be overwritten") |
|
72 |
|
|
73 |
def init_middleware(self): |
|
74 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
75 |
|
|
76 |
def publish_default_emotion(self, emotion, blocking): |
|
77 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
78 |
|
|
79 |
def publish_current_emotion(self, emotion, blocking): |
|
80 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
81 |
|
|
82 |
def publish_gaze_target(self, gaze, blocking): |
|
83 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
84 |
|
|
85 |
def publish_mouth_target(self, mouth, blocking): |
|
86 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
87 |
|
|
88 |
def publish_head_animation(self, animation, blocking): |
|
89 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
90 |
|
|
91 |
def publish_speech(self, text, blocking): |
|
92 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
93 |
|
|
94 |
####################################################################### |
|
95 |
#finally some implemented functions |
|
96 |
def set_default_emotion(self, emotion, blocking): |
|
97 |
"""set the default emotion |
|
98 |
:param emotion: RobotEmotion to set |
|
99 |
:param blocking: True if this call should block until execution finished on robot |
|
100 |
""" |
|
101 |
self.default_emotion = emotion |
|
102 |
self.publish_default_emotion(emotion, blocking) |
|
103 |
|
|
104 |
def set_current_emotion(self, emotion, blocking): |
|
105 |
"""set a temporary emotion (duration: see emotion.time_ms) |
|
106 |
:param emotion: RobotEmotion to set temporarily |
|
107 |
:param blocking: True if this call should block until execution finished on robot |
|
108 |
""" |
|
109 |
self.current_emotion = emotion |
|
110 |
self.publish_current_emotion(emotion, blocking) |
|
111 |
|
|
112 |
def set_head_animation(self, animation, blocking): |
|
113 |
"""trigger a head animation |
|
114 |
:param animation: RobotAnimation to set |
|
115 |
:param blocking: True if this call should block until execution finished on robot |
|
116 |
""" |
|
117 |
self.animation = animation |
|
118 |
self.publish_head_animation(animation, blocking) |
|
119 |
|
|
120 |
def set_mouth_target(self, mouth, blocking): |
|
121 |
"""set a mouth target |
|
122 |
:param mouth: RobotMouth to set |
|
123 |
:param blocking: True if this call should block until execution finished on robot |
|
124 |
""" |
|
125 |
self.mouth_target = mouth |
|
126 |
self.publish_mouth_target(mouth, blocking) |
|
127 |
|
|
128 |
def set_speak(self, text, blocking): |
|
129 |
"""trigger a tts speech output |
|
130 |
:param text: text to synthesize and speak |
|
131 |
:param blocking: True if this call should block until execution finished on robot |
|
132 |
""" |
|
133 |
self.publish_speech(text, blocking) |
|
134 |
|
|
135 |
def set_gaze_target(self, gaze, blocking): |
|
136 |
"""set a new gaze |
|
137 |
:param gaze: RobotGaze to set |
|
138 |
:param blocking: True if this call should block until execution finished on robot |
|
139 |
""" |
|
140 |
self.gaze_target = gaze |
|
141 |
self.publish_gaze_target(gaze, blocking) |
|
142 |
|
|
143 |
####################################################################### |
|
144 |
#some get methods |
|
145 |
#def get_current_emotion(self): |
|
146 |
# return self.current_emotion |
|
147 |
# |
|
148 |
#def get_default_emotion(self): |
|
149 |
# return self.default_emotion |
|
150 |
# |
|
67 |
|
|
68 |
####################################################################### |
|
69 |
#abstract/virtual functions |
|
70 |
def die_virtual(self, funcname): |
|
71 |
raise NotImplementedError(funcname + "() is virtual, must be overwritten") |
|
72 |
|
|
73 |
def init_middleware(self): |
|
74 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
75 |
|
|
76 |
def publish_default_emotion(self, emotion, blocking): |
|
77 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
78 |
|
|
79 |
def publish_current_emotion(self, emotion, blocking): |
|
80 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
81 |
|
|
82 |
def publish_gaze_target(self, gaze, blocking): |
|
83 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
84 |
|
|
85 |
def publish_mouth_target(self, mouth, blocking): |
|
86 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
87 |
|
|
88 |
def publish_head_animation(self, animation, blocking): |
|
89 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
90 |
|
|
91 |
def publish_speech(self, text, blocking): |
|
92 |
self.die_virtual(sys._getframe().f_code.co_name) |
|
93 |
|
|
94 |
####################################################################### |
|
95 |
#finally some implemented functions |
|
96 |
def set_default_emotion(self, emotion, blocking): |
|
97 |
"""set the default emotion |
|
98 |
:param emotion: RobotEmotion to set |
|
99 |
:param blocking: True if this call should block until execution finished on robot |
|
100 |
""" |
|
101 |
self.default_emotion = emotion |
|
102 |
self.publish_default_emotion(emotion, blocking) |
|
103 |
|
|
104 |
def set_current_emotion(self, emotion, blocking): |
|
105 |
"""set a temporary emotion (duration: see emotion.time_ms) |
|
106 |
:param emotion: RobotEmotion to set temporarily |
|
107 |
:param blocking: True if this call should block until execution finished on robot |
|
108 |
""" |
|
109 |
self.current_emotion = emotion |
|
110 |
self.publish_current_emotion(emotion, blocking) |
|
111 |
|
|
112 |
def set_head_animation(self, animation, blocking): |
|
113 |
"""trigger a head animation |
|
114 |
:param animation: RobotAnimation to set |
|
115 |
:param blocking: True if this call should block until execution finished on robot |
|
116 |
""" |
|
117 |
self.animation = animation |
|
118 |
self.publish_head_animation(animation, blocking) |
|
119 |
|
|
120 |
def set_mouth_target(self, mouth, blocking): |
|
121 |
"""set a mouth target |
|
122 |
:param mouth: RobotMouth to set |
|
123 |
:param blocking: True if this call should block until execution finished on robot |
|
124 |
""" |
|
125 |
self.mouth_target = mouth |
|
126 |
self.publish_mouth_target(mouth, blocking) |
|
127 |
|
|
128 |
def set_speak(self, text, blocking): |
|
129 |
"""trigger a tts speech output |
|
130 |
:param text: text to synthesize and speak |
|
131 |
:param blocking: True if this call should block until execution finished on robot |
|
132 |
""" |
|
133 |
self.publish_speech(text, blocking) |
|
134 |
|
|
135 |
def set_gaze_target(self, gaze, blocking): |
|
136 |
"""set a new gaze |
|
137 |
:param gaze: RobotGaze to set |
|
138 |
:param blocking: True if this call should block until execution finished on robot |
|
139 |
""" |
|
140 |
self.gaze_target = gaze |
|
141 |
self.publish_gaze_target(gaze, blocking) |
|
142 |
|
|
143 |
####################################################################### |
|
144 |
#some get methods |
|
145 |
#def get_current_emotion(self): |
|
146 |
# return self.current_emotion |
|
147 |
# |
|
148 |
#def get_default_emotion(self): |
|
149 |
# return self.default_emotion |
|
150 |
# |
client/python/hlrc_client/MiddlewareROS.py | ||
---|---|---|
34 | 34 |
from hlrc_server.msg import * |
35 | 35 |
|
36 | 36 |
class MiddlewareROS(Middleware): |
37 |
#default timeout to wait in case of blocking calls
|
|
38 |
ROS_ACTION_CALL_TIMEOUT = 30.0
|
|
39 |
|
|
40 |
#######################################################################
|
|
41 |
def __init__(self, scope, loglevel=logging.WARNING):
|
|
42 |
"""initialise
|
|
43 |
:param scope: base scope we want to listen on
|
|
44 |
"""
|
|
45 |
#init base settings
|
|
46 |
Middleware.__init__(self,scope,loglevel)
|
|
47 |
#call mw init
|
|
48 |
self.init_middleware()
|
|
49 |
|
|
37 |
#default timeout to wait in case of blocking calls
|
|
38 |
ROS_ACTION_CALL_TIMEOUT = 30.0
|
|
39 |
|
|
40 |
#######################################################################
|
|
41 |
def __init__(self, scope, loglevel=logging.WARNING):
|
|
42 |
"""initialise |
|
43 |
:param scope: base scope we want to listen on
|
|
44 |
""" |
|
45 |
#init base settings |
|
46 |
Middleware.__init__(self,scope,loglevel) |
|
47 |
#call mw init |
|
48 |
self.init_middleware() |
|
49 |
|
|
50 | 50 |
def __del__(self): |
51 |
"""destructor
|
|
52 |
"""
|
|
53 |
self.logger.debug("destructor of MiddlewareROS called")
|
|
54 |
|
|
55 |
####################################################################### |
|
56 |
def init_middleware(self):
|
|
51 |
"""destructor
|
|
52 |
"""
|
|
53 |
self.logger.debug("destructor of MiddlewareROS called")
|
|
54 |
|
|
55 |
#######################################################################
|
|
56 |
def init_middleware(self):
|
|
57 | 57 |
"""initialise middleware |
58 | 58 |
""" |
59 | 59 |
self.logger.info("initialising ROS middleware connection on scope %s" % (self.base_scope)) |
... | ... | |
89 | 89 |
self.logger.info("MiddlewareROS initialised") |
90 | 90 |
|
91 | 91 |
|
92 |
####################################################################### |
|
93 |
def publish_emotion(self, em_type, emotion, blocking): |
|
94 |
"""publish an emotion via mw |
|
95 |
:param em_type: type of emotion (RobotEmotion::TYPE_DEFAULT or RobotEmotion::TYPE_CURRENT) |
|
96 |
:param emotion: emotion to set |
|
97 |
:param blocking: True if this call should block until execution finished on robot |
|
98 |
""" |
|
99 |
self.logger.debug("calling the emotion rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
100 |
|
|
101 |
#create a goal to send to the action server. |
|
102 |
goal = emotionstateGoal() |
|
103 |
goal.value = self.convert_emotiontype_to_rosval(emotion.value) |
|
104 |
goal.duration = int(emotion.time_ms) |
|
105 |
|
|
106 |
#which client do we use? |
|
107 |
if (em_type == RobotEmotion.TYPE_DEFAULT): |
|
92 |
#######################################################################
|
|
93 |
def publish_emotion(self, em_type, emotion, blocking):
|
|
94 |
"""publish an emotion via mw
|
|
95 |
:param em_type: type of emotion (RobotEmotion::TYPE_DEFAULT or RobotEmotion::TYPE_CURRENT)
|
|
96 |
:param emotion: emotion to set
|
|
97 |
:param blocking: True if this call should block until execution finished on robot
|
|
98 |
"""
|
|
99 |
self.logger.debug("calling the emotion rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING"))
|
|
100 |
|
|
101 |
#create a goal to send to the action server.
|
|
102 |
goal = emotionstateGoal()
|
|
103 |
goal.value = self.convert_emotiontype_to_rosval(emotion.value)
|
|
104 |
goal.duration = int(emotion.time_ms)
|
|
105 |
|
|
106 |
#which client do we use?
|
|
107 |
if (em_type == RobotEmotion.TYPE_DEFAULT):
|
|
108 | 108 |
client = self.default_emotion_client |
109 |
else: |
|
110 |
client = self.current_emotion_client |
|
111 |
|
|
112 |
#send the goal to the server |
|
113 |
client.send_goal(goal) |
|
114 |
|
|
115 |
#wait for the server to finish |
|
116 |
if (blocking): |
|
117 |
timed_out = client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
118 |
if (timed_out): |
|
119 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
120 |
|
|
121 |
def publish_default_emotion(self, emotion, blocking): |
|
122 |
self.publish_emotion(RobotEmotion.TYPE_DEFAULT, emotion, blocking) |
|
123 |
|
|
124 |
def publish_current_emotion(self, emotion, blocking): |
|
125 |
self.publish_emotion(RobotEmotion.TYPE_CURRENT, emotion, blocking) |
|
126 |
|
|
127 |
def publish_head_animation(self, animation, blocking): |
|
128 |
"""publish an head animation via mw |
|
129 |
:param animation: animation to set |
|
130 |
:param blocking: True if this call should block until execution finished on robot |
|
131 |
""" |
|
132 |
self.logger.debug("calling the animation rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
133 |
|
|
134 |
#create a goal to send to the action server. |
|
135 |
goal = animationGoal() |
|
136 |
goal.target = self.convert_animationtype_to_rosval(animation.value) |
|
137 |
goal.repetitions = animation.repetitions |
|
138 |
goal.duration_each = int(animation.time_ms) |
|
139 |
goal.scale = animation.scale |
|
140 |
|
|
141 |
#send the goal to the server |
|
142 |
self.animation_client.send_goal(goal) |
|
143 |
|
|
144 |
#wait for the server to finish |
|
145 |
if (blocking): |
|
146 |
timed_out = self.animation_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
147 |
if (timed_out): |
|
148 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
149 |
|
|
150 |
self.logger.debug("animation rpc done") |
|
151 |
|
|
152 |
def publish_gaze_target(self, gaze, blocking): |
|
153 |
"""publish a gaze target via mw |
|
154 |
:param gaze: gaze to set |
|
155 |
:param blocking: True if this call should block until execution finished on robot |
|
156 |
""" |
|
157 |
self.logger.debug("calling the gaze rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
158 |
|
|
159 |
#create a goal to send to the action server. |
|
160 |
goal = gazetargetGoal() |
|
161 |
goal.pan = gaze.pan |
|
162 |
goal.tilt = gaze.tilt |
|
163 |
goal.roll = gaze.roll |
|
164 |
goal.vergence = gaze.vergence |
|
165 |
goal.pan_offset = gaze.pan_offset |
|
166 |
goal.tilt_offset = gaze.tilt_offset |
|
167 |
|
|
168 |
#type |
|
169 |
if (gaze.gaze_type == RobotGaze.GAZETARGET_ABSOLUTE): |
|
170 |
goal.gaze_type = gazetargetGoal.GAZETARGET_ABSOLUTE |
|
171 |
else: |
|
172 |
goal.gaze_type = gazetargetGoal.GAZETARGET_RELATIVE |
|
173 |
|
|
174 |
goal.timestamp = rospy.Time.from_sec(gaze.timestamp) |
|
175 |
|
|
176 |
#send the goal to the server |
|
177 |
self.gazetarget_client.send_goal(goal) |
|
178 |
|
|
179 |
#wait for the server to finish |
|
180 |
if (blocking): |
|
181 |
timed_out = self.gazetarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
182 |
if (timed_out): |
|
183 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
184 |
|
|
185 |
|
|
186 |
self.logger.debug("gaze rpc done") |
|
187 |
|
|
188 |
def publish_mouth_target(self, mouth, blocking): |
|
189 |
"""publish a mouth target via mw |
|
190 |
:param mouth: mouth value to set |
|
191 |
:param blocking: True if this call should block until execution finished on robot |
|
192 |
""" |
|
193 |
self.logger.debug("calling the mouth rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
194 |
|
|
195 |
#create a goal to send to the action server. |
|
196 |
goal = mouthtargetGoal() |
|
197 |
goal.opening_left = mouth.opening_left |
|
198 |
goal.opening_center = mouth.opening_center |
|
199 |
goal.opening_right = mouth.opening_right |
|
200 |
goal.position_left = mouth.position_left |
|
201 |
goal.position_center = mouth.position_center |
|
202 |
goal.position_right = mouth.position_right |
|
203 |
|
|
204 |
#send the goal to the server |
|
205 |
self.mouthtarget_client.send_goal(goal) |
|
206 |
|
|
207 |
#wait for the server to finish |
|
208 |
if (blocking): |
|
209 |
timed_out = self.mouthtarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
210 |
if (timed_out): |
|
211 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
212 |
|
|
213 |
self.logger.debug("mouth rpc done") |
|
214 |
|
|
215 |
def publish_speech(self, text_, blocking): |
|
216 |
"""publish a tts request via mw |
|
217 |
:param text_: text to synthesize and speak |
|
218 |
:param blocking: True if this call should block until execution finished on robot |
|
219 |
""" |
|
220 |
self.logger.debug("calling the speech rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
221 |
|
|
222 |
#create a goal to send to the action server. |
|
223 |
goal = speechGoal(text=text_) |
|
224 |
|
|
225 |
#send the goal to the server |
|
226 |
self.speech_client.send_goal(goal) |
|
227 |
|
|
228 |
#wait for the server to finish |
|
229 |
if (blocking): |
|
230 |
timed_out = self.speech_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
231 |
if (timed_out): |
|
232 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
233 |
|
|
234 |
self.logger.debug("speech rpc done") |
|
235 |
|
|
236 |
####################################################################### |
|
237 |
# some helpers |
|
238 |
def convert_animationtype_to_rosval(self, value): |
|
239 |
"""convert RobotAnimation.value to ROS animation value |
|
240 |
:param value: RobotAnimation.* id to convert to rsb id |
|
241 |
""" |
|
242 |
#NOTE: this convertion is important as the actual integer values of |
|
243 |
# thy python api and the protobuf might be different |
|
244 |
if (value == RobotAnimation.IDLE): |
|
245 |
return animationGoal.IDLE |
|
246 |
elif (value == RobotAnimation.HEAD_NOD): |
|
247 |
return animationGoal.HEAD_NOD |
|
248 |
elif (value == RobotAnimation.HEAD_SHAKE): |
|
249 |
return animationGoal.HEAD_SHAKE |
|
250 |
elif (value == RobotAnimation.EYEBLINK_L): |
|
251 |
return animationGoal.EYEBLINK_L |
|
252 |
elif (value == RobotAnimation.EYEBLINK_R): |
|
253 |
return animationGoal.EYEBLINK_R |
|
254 |
elif (value == RobotAnimation.EYEBLINK_BOTH): |
|
255 |
return animationGoal.EYEBLINK_BOTH |
|
256 |
elif (value == RobotAnimation.EYEBROWS_RAISE): |
|
257 |
return animationGoal.EYEBROWS_RAISE |
|
258 |
elif (value == RobotAnimation.EYEBROWS_LOWER): |
|
259 |
return animationGoal.EYEBROWS_LOWER |
|
260 |
else: |
|
261 |
self.logger.error("invalid animation type %d\n" % (value)) |
|
262 |
return animationGoal.NEUTRAL |
|
263 |
|
|
264 |
def convert_emotiontype_to_rosval(self, value): |
|
265 |
"""convert RobotEmotion.value to ROS animation value |
|
266 |
:param value: RobotEmotion.* id to convert to ros id |
|
267 |
""" |
|
268 |
#NOTE: this convertion is important as the actual integer values of |
|
269 |
# thy python api and the protobuf might be different |
|
270 |
|
|
271 |
if (value == RobotEmotion.NEUTRAL): |
|
272 |
return emotionstateGoal.NEUTRAL |
|
273 |
elif (value == RobotEmotion.HAPPY): |
|
274 |
return emotionstateGoal.HAPPY |
|
275 |
elif (value == RobotEmotion.SAD): |
|
276 |
return emotionstateGoal.SAD |
|
277 |
elif (value == RobotEmotion.ANGRY): |
|
278 |
return emotionstateGoal.ANGRY |
|
279 |
elif (value == RobotEmotion.SURPRISED): |
|
280 |
return emotionstateGoal.SURPRISED |
|
281 |
elif (value == RobotEmotion.FEAR): |
|
282 |
return emotionstateGoal.FEAR |
|
283 |
else: |
|
284 |
self.logger.error("invalid emotion type %d\n" % (value)) |
|
285 |
return emotionstateGoal.NEUTRAL |
|
109 |
else: |
|
110 |
client = self.current_emotion_client |
|
111 |
|
|
112 |
#send the goal to the server |
|
113 |
client.send_goal(goal) |
|
114 |
|
|
115 |
#wait for the server to finish |
|
116 |
if (blocking): |
|
117 |
timed_out = client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
118 |
if (timed_out): |
|
119 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
120 |
|
|
121 |
def publish_default_emotion(self, emotion, blocking): |
|
122 |
self.publish_emotion(RobotEmotion.TYPE_DEFAULT, emotion, blocking) |
|
123 |
|
|
124 |
def publish_current_emotion(self, emotion, blocking): |
|
125 |
self.publish_emotion(RobotEmotion.TYPE_CURRENT, emotion, blocking) |
|
126 |
|
|
127 |
def publish_head_animation(self, animation, blocking): |
|
128 |
"""publish an head animation via mw |
|
129 |
:param animation: animation to set |
|
130 |
:param blocking: True if this call should block until execution finished on robot |
|
131 |
""" |
|
132 |
self.logger.debug("calling the animation rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
133 |
|
|
134 |
#create a goal to send to the action server. |
|
135 |
goal = animationGoal() |
|
136 |
goal.target = self.convert_animationtype_to_rosval(animation.value) |
|
137 |
goal.repetitions = animation.repetitions |
|
138 |
goal.duration_each = int(animation.time_ms) |
|
139 |
goal.scale = animation.scale |
|
140 |
|
|
141 |
#send the goal to the server |
|
142 |
self.animation_client.send_goal(goal) |
|
143 |
|
|
144 |
#wait for the server to finish |
|
145 |
if (blocking): |
|
146 |
timed_out = self.animation_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
147 |
if (timed_out): |
|
148 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
149 |
|
|
150 |
self.logger.debug("animation rpc done") |
|
151 |
|
|
152 |
def publish_gaze_target(self, gaze, blocking): |
|
153 |
"""publish a gaze target via mw |
|
154 |
:param gaze: gaze to set |
|
155 |
:param blocking: True if this call should block until execution finished on robot |
|
156 |
""" |
|
157 |
self.logger.debug("calling the gaze rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
158 |
|
|
159 |
#create a goal to send to the action server. |
|
160 |
goal = gazetargetGoal() |
|
161 |
goal.pan = gaze.pan |
|
162 |
goal.tilt = gaze.tilt |
|
163 |
goal.roll = gaze.roll |
|
164 |
goal.vergence = gaze.vergence |
|
165 |
goal.pan_offset = gaze.pan_offset |
|
166 |
goal.tilt_offset = gaze.tilt_offset |
|
167 |
|
|
168 |
#type |
|
169 |
if (gaze.gaze_type == RobotGaze.GAZETARGET_ABSOLUTE): |
|
170 |
goal.gaze_type = gazetargetGoal.GAZETARGET_ABSOLUTE |
|
171 |
else: |
|
172 |
goal.gaze_type = gazetargetGoal.GAZETARGET_RELATIVE |
|
173 |
|
|
174 |
goal.timestamp = rospy.Time.from_sec(gaze.timestamp) |
|
175 |
|
|
176 |
#send the goal to the server |
|
177 |
self.gazetarget_client.send_goal(goal) |
|
178 |
|
|
179 |
#wait for the server to finish |
|
180 |
if (blocking): |
|
181 |
timed_out = self.gazetarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
182 |
if (timed_out): |
|
183 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
184 |
|
|
185 |
|
|
186 |
self.logger.debug("gaze rpc done") |
|
187 |
|
|
188 |
def publish_mouth_target(self, mouth, blocking): |
|
189 |
"""publish a mouth target via mw |
|
190 |
:param mouth: mouth value to set |
|
191 |
:param blocking: True if this call should block until execution finished on robot |
|
192 |
""" |
|
193 |
self.logger.debug("calling the mouth rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
194 |
|
|
195 |
#create a goal to send to the action server. |
|
196 |
goal = mouthtargetGoal() |
|
197 |
goal.opening_left = mouth.opening_left |
|
198 |
goal.opening_center = mouth.opening_center |
|
199 |
goal.opening_right = mouth.opening_right |
|
200 |
goal.position_left = mouth.position_left |
|
201 |
goal.position_center = mouth.position_center |
|
202 |
goal.position_right = mouth.position_right |
|
203 |
|
|
204 |
#send the goal to the server |
|
205 |
self.mouthtarget_client.send_goal(goal) |
|
206 |
|
|
207 |
#wait for the server to finish |
|
208 |
if (blocking): |
|
209 |
timed_out = self.mouthtarget_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
210 |
if (timed_out): |
|
211 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
212 |
|
|
213 |
self.logger.debug("mouth rpc done") |
|
214 |
|
|
215 |
def publish_speech(self, text_, blocking): |
|
216 |
"""publish a tts request via mw |
|
217 |
:param text_: text to synthesize and speak |
|
218 |
:param blocking: True if this call should block until execution finished on robot |
|
219 |
""" |
|
220 |
self.logger.debug("calling the speech rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
221 |
|
|
222 |
#create a goal to send to the action server. |
|
223 |
goal = speechGoal(text=text_) |
|
224 |
|
|
225 |
#send the goal to the server |
|
226 |
self.speech_client.send_goal(goal) |
|
227 |
|
|
228 |
#wait for the server to finish |
|
229 |
if (blocking): |
|
230 |
timed_out = self.speech_client.wait_for_result(rospy.Duration.from_sec(MiddlewareROS.ROS_ACTION_CALL_TIMEOUT)) |
|
231 |
if (timed_out): |
|
232 |
self.logger.error("%s timed out waiting for result" % (sys._getframe().f_code.co_name)) |
|
233 |
|
|
234 |
self.logger.debug("speech rpc done") |
|
235 |
|
|
236 |
####################################################################### |
|
237 |
# some helpers |
|
238 |
def convert_animationtype_to_rosval(self, value): |
|
239 |
"""convert RobotAnimation.value to ROS animation value |
|
240 |
:param value: RobotAnimation.* id to convert to rsb id |
|
241 |
""" |
|
242 |
#NOTE: this convertion is important as the actual integer values of |
|
243 |
# thy python api and the protobuf might be different |
|
244 |
if (value == RobotAnimation.IDLE): |
|
245 |
return animationGoal.IDLE |
|
246 |
elif (value == RobotAnimation.HEAD_NOD): |
|
247 |
return animationGoal.HEAD_NOD |
|
248 |
elif (value == RobotAnimation.HEAD_SHAKE): |
|
249 |
return animationGoal.HEAD_SHAKE |
|
250 |
elif (value == RobotAnimation.EYEBLINK_L): |
|
251 |
return animationGoal.EYEBLINK_L |
|
252 |
elif (value == RobotAnimation.EYEBLINK_R): |
|
253 |
return animationGoal.EYEBLINK_R |
|
254 |
elif (value == RobotAnimation.EYEBLINK_BOTH): |
|
255 |
return animationGoal.EYEBLINK_BOTH |
|
256 |
elif (value == RobotAnimation.EYEBROWS_RAISE): |
|
257 |
return animationGoal.EYEBROWS_RAISE |
|
258 |
elif (value == RobotAnimation.EYEBROWS_LOWER): |
|
259 |
return animationGoal.EYEBROWS_LOWER |
|
260 |
else: |
|
261 |
self.logger.error("invalid animation type %d\n" % (value)) |
|
262 |
return animationGoal.NEUTRAL |
|
263 |
|
|
264 |
def convert_emotiontype_to_rosval(self, value): |
|
265 |
"""convert RobotEmotion.value to ROS animation value |
|
266 |
:param value: RobotEmotion.* id to convert to ros id |
|
267 |
""" |
|
268 |
#NOTE: this convertion is important as the actual integer values of |
|
269 |
# thy python api and the protobuf might be different |
|
270 |
|
|
271 |
if (value == RobotEmotion.NEUTRAL): |
|
272 |
return emotionstateGoal.NEUTRAL |
|
273 |
elif (value == RobotEmotion.HAPPY): |
|
274 |
return emotionstateGoal.HAPPY |
|
275 |
elif (value == RobotEmotion.SAD): |
|
276 |
return emotionstateGoal.SAD |
|
277 |
elif (value == RobotEmotion.ANGRY): |
|
278 |
return emotionstateGoal.ANGRY |
|
279 |
elif (value == RobotEmotion.SURPRISED): |
|
280 |
return emotionstateGoal.SURPRISED |
|
281 |
elif (value == RobotEmotion.FEAR): |
|
282 |
return emotionstateGoal.FEAR |
|
283 |
else: |
|
284 |
self.logger.error("invalid emotion type %d\n" % (value)) |
|
285 |
return emotionstateGoal.NEUTRAL |
client/python/hlrc_client/MiddlewareRSB.py | ||
---|---|---|
38 | 38 |
from rst.robot.MouthTarget_pb2 import MouthTarget |
39 | 39 |
|
40 | 40 |
class MiddlewareRSB(Middleware): |
41 |
#######################################################################
|
|
42 |
def __init__(self, scope, loglevel=logging.WARNING):
|
|
43 |
"""initialise
|
|
44 |
:param scope: base scope we want to listen on
|
|
45 |
"""
|
|
46 |
#init base settings
|
|
47 |
Middleware.__init__(self,scope,loglevel)
|
|
48 |
#call mw init
|
|
49 |
self.init_middleware()
|
|
41 |
#######################################################################
|
|
42 |
def __init__(self, scope, loglevel=logging.WARNING):
|
|
43 |
"""initialise |
|
44 |
:param scope: base scope we want to listen on
|
|
45 |
""" |
|
46 |
#init base settings |
|
47 |
Middleware.__init__(self,scope,loglevel) |
|
48 |
#call mw init |
|
49 |
self.init_middleware() |
|
50 | 50 |
|
51 | 51 |
def __del__(self): |
52 |
"""destructor
|
|
53 |
"""
|
|
54 |
self.logger.debug("destructor of MiddlewareROS called")
|
|
55 |
|
|
56 |
####################################################################### |
|
57 |
def init_middleware(self):
|
|
52 |
"""destructor
|
|
53 |
"""
|
|
54 |
self.logger.debug("destructor of MiddlewareROS called")
|
|
55 |
|
|
56 |
#######################################################################
|
|
57 |
def init_middleware(self):
|
|
58 | 58 |
"""initialise middleware |
59 | 59 |
""" |
60 | 60 |
#mute rsb logging: |
61 |
logging.getLogger("rsb").setLevel(logging.ERROR) |
|
62 |
|
|
63 |
#initialise RSB stuff |
|
64 |
self.logger.info("initialising RSB middleware connection on scope %s, registering rst converters..." % (self.base_scope)) |
|
65 |
|
|
66 |
self.emotionstate_converter = rsb.converter.ProtocolBufferConverter(messageClass = EmotionState) |
|
67 |
rsb.converter.registerGlobalConverter(self.emotionstate_converter) |
|
68 |
|
|
69 |
self.animation_converter = rsb.converter.ProtocolBufferConverter(messageClass = Animation) |
|
70 |
rsb.converter.registerGlobalConverter(self.animation_converter) |
|
71 |
|
|
72 |
self.gaze_converter = rsb.converter.ProtocolBufferConverter(messageClass = GazeTarget) |
|
73 |
rsb.converter.registerGlobalConverter(self.gaze_converter) |
|
74 |
|
|
75 |
self.mouth_converter = rsb.converter.ProtocolBufferConverter(messageClass = MouthTarget) |
|
76 |
rsb.converter.registerGlobalConverter(self.mouth_converter) |
|
77 |
|
|
78 |
try: |
|
61 |
logging.getLogger("rsb").setLevel(logging.ERROR)
|
|
62 |
|
|
63 |
#initialise RSB stuff
|
|
64 |
self.logger.info("initialising RSB middleware connection on scope %s, registering rst converters..." % (self.base_scope))
|
|
65 |
|
|
66 |
self.emotionstate_converter = rsb.converter.ProtocolBufferConverter(messageClass = EmotionState)
|
|
67 |
rsb.converter.registerGlobalConverter(self.emotionstate_converter)
|
|
68 |
|
|
69 |
self.animation_converter = rsb.converter.ProtocolBufferConverter(messageClass = Animation)
|
|
70 |
rsb.converter.registerGlobalConverter(self.animation_converter)
|
|
71 |
|
|
72 |
self.gaze_converter = rsb.converter.ProtocolBufferConverter(messageClass = GazeTarget)
|
|
73 |
rsb.converter.registerGlobalConverter(self.gaze_converter)
|
|
74 |
|
|
75 |
self.mouth_converter = rsb.converter.ProtocolBufferConverter(messageClass = MouthTarget)
|
|
76 |
rsb.converter.registerGlobalConverter(self.mouth_converter)
|
|
77 |
|
|
78 |
try:
|
|
79 | 79 |
self.server = rsb.createRemoteServer(self.base_scope + '/set') |
80 |
except ValueError: |
|
81 |
self.logger.error("ERROR: invalid scope given. server deactivated") |
|
82 |
self.server.deactivate() |
|
83 |
sys.exit(errno.EINVAL) |
|
84 |
|
|
85 |
####################################################################### |
|
86 |
def publish_emotion(self, em_type, emotion, blocking): |
|
87 |
"""publish an emotion via mw |
|
88 |
:param em_type: type of emotion (RobotEmotion::TYPE_DEFAULT or RobotEmotion::TYPE_CURRENT) |
|
89 |
:param emotion: emotion to set |
|
90 |
:param blocking: True if this call should block until execution finished on robot |
|
91 |
""" |
|
92 |
|
|
93 |
#create emotion & fill it with values: |
|
94 |
rsb_em = EmotionState() |
|
95 |
|
|
96 |
#set value |
|
97 |
rsb_em.value = self.convert_emotiontype_to_rsbval(emotion.value) |
|
98 |
|
|
99 |
#set duration |
|
100 |
rsb_em.duration = int(emotion.time_ms) |
|
101 |
|
|
102 |
with rsb.createRemoteServer(self.base_scope + '/set') as server: |
|
103 |
self.logger.debug("calling the emotion rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
104 |
|
|
105 |
if (blocking): |
|
106 |
#blocking rpc call: |
|
107 |
if (em_type == RobotEmotion.TYPE_DEFAULT): |
|
108 |
result = server.defaultEmotion(rsb_em) |
|
109 |
else: |
|
110 |
result = server.currentEmotion(rsb_em) |
|
111 |
|
|
112 |
self.logger.debug("server reply: '%s'" % result) |
|
113 |
else: |
|
114 |
if (em_type == RobotEmotion.TYPE_DEFAULT): |
|
115 |
future = server.defaultEmotion.async(rsb_em) |
|
116 |
else: |
|
117 |
future = server.currentEmotion.async(rsb_em) |
|
118 |
|
|
119 |
#we could block here for a incoming result with a timeout in s |
|
120 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
121 |
self.logger.debug("emotion rpc done") |
|
122 |
|
|
123 |
def publish_head_animation(self, animation, blocking): |
|
124 |
"""publish an head animation via mw |
|
125 |
:param animation: animation to set |
|
126 |
:param blocking: True if this call should block until execution finished on robot |
|
127 |
""" |
|
128 |
|
|
129 |
self.logger.debug("calling the animation rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
130 |
|
|
131 |
#create animation & fill it with values: |
|
132 |
rsb_ani = Animation() |
|
133 |
|
|
134 |
#select ani |
|
135 |
rsb_ani.target = self.convert_animationtype_to_rsbval(animation.value) |
|
136 |
rsb_ani.repetitions = animation.repetitions |
|
137 |
rsb_ani.duration_each = animation.time_ms |
|
138 |
rsb_ani.scale = animation.scale |
|
139 |
|
|
140 |
if (blocking): |
|
141 |
#blocking: |
|
142 |
result = self.server.animation(rsb_ani) |
|
143 |
self.logger.debug("server reply: '%s'" % result) |
|
144 |
else: |
|
145 |
future = self.server.animation.async(rsb_ani) |
|
146 |
#we can block here for a incoming result with a timeout in s |
|
147 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
148 |
|
|
149 |
self.logger.debug("animation rpc done") |
|
150 |
|
|
151 |
def publish_default_emotion(self, emotion, blocking): |
|
152 |
self.publish_emotion(RobotEmotion.TYPE_DEFAULT, emotion, blocking) |
|
153 |
|
|
154 |
def publish_current_emotion(self, emotion, blocking): |
|
155 |
self.publish_emotion(RobotEmotion.TYPE_CURRENT, emotion, blocking) |
|
156 |
|
|
157 |
def publish_gaze_target(self, gaze, blocking): |
|
158 |
"""publish a gaze target via mw |
|
159 |
:param gaze: gaze to set |
|
160 |
:param blocking: True if this call should block until execution finished on robot |
|
161 |
""" |
|
162 |
self.logger.debug("calling the gaze rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
163 |
|
|
164 |
#create gaze target & fill it with values: |
|
165 |
rsb_gaze = GazeTarget() |
|
166 |
|
|
167 |
#fill proto |
|
168 |
rsb_gaze.pan = gaze.pan |
|
169 |
rsb_gaze.tilt = gaze.tilt |
|
170 |
rsb_gaze.roll = gaze.roll |
|
171 |
rsb_gaze.vergence = gaze.vergence |
|
172 |
rsb_gaze.pan_offset = gaze.pan_offset |
|
173 |
rsb_gaze.tilt_offset = gaze.tilt_offset |
|
174 |
|
|
175 |
if (blocking): |
|
176 |
#blocking: |
|
177 |
result = self.server.gaze(rsb_gaze) |
|
178 |
self.logger.debug("server reply: '%s'" % result) |
|
179 |
else: |
|
180 |
future = self.server.gaze.async(rsb_gaze) |
|
181 |
#we can block here for a incoming result with a timeout in s |
|
182 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
183 |
|
|
184 |
self.logger.debug("gaze rpc done") |
|
185 |
|
|
186 |
def publish_mouth_target(self, mouth, blocking): |
|
187 |
"""publish a mouth target via mw |
|
188 |
:param mouth: mouth value to set |
|
189 |
:param blocking: True if this call should block until execution finished on robot |
|
190 |
""" |
|
191 |
self.logger.debug("calling the mouth rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
192 |
|
|
193 |
#create mouth state & fill it with values: |
|
194 |
rsb_mouth = MouthTarget() |
|
195 |
|
|
196 |
#fill proto |
|
197 |
rsb_mouth.opening_left = mouth.opening_left |
|
198 |
rsb_mouth.opening_center = mouth.opening_center |
|
199 |
rsb_mouth.opening_right = mouth.opening_right |
|
200 |
rsb_mouth.position_left = mouth.position_left |
|
201 |
rsb_mouth.position_center = mouth.position_center |
|
202 |
rsb_mouth.position_right = mouth.position_right |
|
203 |
|
|
204 |
if (blocking): |
|
205 |
#blocking: |
|
206 |
result = self.server.mouth(rsb_mouth) |
|
207 |
self.logger.debug("server reply: '%s'" % result) |
|
208 |
else: |
|
209 |
future = self.server.mouth.async(rsb_mouth) |
|
210 |
#we can block here for a incoming result with a timeout in s |
|
211 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
212 |
|
|
213 |
self.logger.debug("mouth rpc done") |
|
214 |
|
|
215 |
def publish_speech(self, text, blocking): |
|
216 |
"""publish a tts request via mw |
|
217 |
:param text: text to synthesize and speak |
|
218 |
:param blocking: True if this call should block until execution finished on robot |
|
219 |
""" |
|
220 |
self.logger.debug("calling the speech rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
221 |
|
|
222 |
if (blocking): |
|
223 |
#blocking: |
|
224 |
result = self.server.speech(text) |
|
225 |
self.logger.debug("server reply: '%s'" % result) |
|
226 |
else: |
|
227 |
future = self.server.speech.async(text) |
|
228 |
#we can block here for a incoming result with a timeout in s |
|
229 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
230 |
|
|
231 |
self.logger.debug("speech rpc done") |
|
232 |
|
|
233 |
####################################################################### |
|
234 |
# some helpers |
|
235 |
def convert_animationtype_to_rsbval(self, value): |
|
236 |
"""convert RobotAnimation.value to RSB animation value |
|
237 |
:param value: RobotAnimation.* id to convert to rsb id |
|
238 |
""" |
|
239 |
#NOTE: this convertion is important as the actual integer values of |
|
240 |
# thy python api and the protobuf might be different |
|
241 |
|
|
242 |
if (value == RobotAnimation.IDLE): |
|
243 |
return Animation().IDLE |
|
244 |
elif (value == RobotAnimation.HEAD_NOD): |
|
245 |
return Animation().HEAD_NOD |
|
246 |
elif (value == RobotAnimation.HEAD_SHAKE): |
|
247 |
return Animation().HEAD_SHAKE |
|
248 |
elif (value == RobotAnimation.EYEBLINK_L): |
|
249 |
return Animation().EYEBLINK_L |
|
250 |
elif (value == RobotAnimation.EYEBLINK_R): |
|
251 |
return Animation().EYEBLINK_R |
|
252 |
elif (value == RobotAnimation.EYEBLINK_BOTH): |
|
253 |
return Animation().EYEBLINK_BOTH |
|
254 |
elif (value == RobotAnimation.EYEBROWS_RAISE): |
|
255 |
return Animation().EYEBROWS_RAISE |
|
256 |
elif (value == RobotAnimation.EYEBROWS_LOWER): |
|
257 |
return Animation().EYEBROWS_LOWER |
|
258 |
else: |
|
259 |
self.logger.error("invalid animation type %d\n" % (value)) |
|
260 |
return Animation().NEUTRAL |
|
261 |
|
|
262 |
def convert_emotiontype_to_rsbval(self, value): |
|
263 |
"""convert RobotEmotion.value to RSB animation value |
|
264 |
:param value: RobotEmotion.* id to convert to rsb id |
|
265 |
""" |
|
266 |
#NOTE: this convertion is important as the actual integer values of |
|
267 |
# thy python api and the protobuf might be different |
|
268 |
|
|
269 |
if (value == RobotEmotion.NEUTRAL): |
|
270 |
return EmotionState().NEUTRAL |
|
271 |
elif (value == RobotEmotion.HAPPY): |
|
272 |
return EmotionState().HAPPY |
|
273 |
elif (value == RobotEmotion.SAD): |
|
274 |
return EmotionState().SAD |
|
275 |
elif (value == RobotEmotion.ANGRY): |
|
276 |
return EmotionState().ANGRY |
|
277 |
elif (value == RobotEmotion.SURPRISED): |
|
278 |
return EmotionState().SURPRISED |
|
279 |
elif (value == RobotEmotion.FEAR): |
|
280 |
return EmotionState().FEAR |
|
281 |
else: |
|
282 |
self.logger.error("invalid emotion type %d\n" % (value)) |
|
283 |
return EmotionState().NEUTRAL |
|
80 |
except ValueError: |
|
81 |
self.logger.error("ERROR: invalid scope given. server deactivated") |
|
82 |
self.server.deactivate() |
|
83 |
sys.exit(errno.EINVAL) |
|
84 |
|
|
85 |
####################################################################### |
|
86 |
def publish_emotion(self, em_type, emotion, blocking): |
|
87 |
"""publish an emotion via mw |
|
88 |
:param em_type: type of emotion (RobotEmotion::TYPE_DEFAULT or RobotEmotion::TYPE_CURRENT) |
|
89 |
:param emotion: emotion to set |
|
90 |
:param blocking: True if this call should block until execution finished on robot |
|
91 |
""" |
|
92 |
|
|
93 |
#create emotion & fill it with values: |
|
94 |
rsb_em = EmotionState() |
|
95 |
|
|
96 |
#set value |
|
97 |
rsb_em.value = self.convert_emotiontype_to_rsbval(emotion.value) |
|
98 |
|
|
99 |
#set duration |
|
100 |
rsb_em.duration = int(emotion.time_ms) |
|
101 |
|
|
102 |
with rsb.createRemoteServer(self.base_scope + '/set') as server: |
|
103 |
self.logger.debug("calling the emotion rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
104 |
|
|
105 |
if (blocking): |
|
106 |
#blocking rpc call: |
|
107 |
if (em_type == RobotEmotion.TYPE_DEFAULT): |
|
108 |
result = server.defaultEmotion(rsb_em) |
|
109 |
else: |
|
110 |
result = server.currentEmotion(rsb_em) |
|
111 |
|
|
112 |
self.logger.debug("server reply: '%s'" % result) |
|
113 |
else: |
|
114 |
if (em_type == RobotEmotion.TYPE_DEFAULT): |
|
115 |
future = server.defaultEmotion.async(rsb_em) |
|
116 |
else: |
|
117 |
future = server.currentEmotion.async(rsb_em) |
|
118 |
|
|
119 |
#we could block here for a incoming result with a timeout in s |
|
120 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
121 |
self.logger.debug("emotion rpc done") |
|
122 |
|
|
123 |
def publish_head_animation(self, animation, blocking): |
|
124 |
"""publish an head animation via mw |
|
125 |
:param animation: animation to set |
|
126 |
:param blocking: True if this call should block until execution finished on robot |
|
127 |
""" |
|
128 |
|
|
129 |
self.logger.debug("calling the animation rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
130 |
|
|
131 |
#create animation & fill it with values: |
|
132 |
rsb_ani = Animation() |
|
133 |
|
|
134 |
#select ani |
|
135 |
rsb_ani.target = self.convert_animationtype_to_rsbval(animation.value) |
|
136 |
rsb_ani.repetitions = animation.repetitions |
|
137 |
rsb_ani.duration_each = animation.time_ms |
|
138 |
rsb_ani.scale = animation.scale |
|
139 |
|
|
140 |
if (blocking): |
|
141 |
#blocking: |
|
142 |
result = self.server.animation(rsb_ani) |
|
143 |
self.logger.debug("server reply: '%s'" % result) |
|
144 |
else: |
|
145 |
future = self.server.animation.async(rsb_ani) |
|
146 |
#we can block here for a incoming result with a timeout in s |
|
147 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
148 |
|
|
149 |
self.logger.debug("animation rpc done") |
|
150 |
|
|
151 |
def publish_default_emotion(self, emotion, blocking): |
|
152 |
self.publish_emotion(RobotEmotion.TYPE_DEFAULT, emotion, blocking) |
|
153 |
|
|
154 |
def publish_current_emotion(self, emotion, blocking): |
|
155 |
self.publish_emotion(RobotEmotion.TYPE_CURRENT, emotion, blocking) |
|
156 |
|
|
157 |
def publish_gaze_target(self, gaze, blocking): |
|
158 |
"""publish a gaze target via mw |
|
159 |
:param gaze: gaze to set |
|
160 |
:param blocking: True if this call should block until execution finished on robot |
|
161 |
""" |
|
162 |
self.logger.debug("calling the gaze rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
163 |
|
|
164 |
#create gaze target & fill it with values: |
|
165 |
rsb_gaze = GazeTarget() |
|
166 |
|
|
167 |
#fill proto |
|
168 |
rsb_gaze.pan = gaze.pan |
|
169 |
rsb_gaze.tilt = gaze.tilt |
|
170 |
rsb_gaze.roll = gaze.roll |
|
171 |
rsb_gaze.vergence = gaze.vergence |
|
172 |
rsb_gaze.pan_offset = gaze.pan_offset |
|
173 |
rsb_gaze.tilt_offset = gaze.tilt_offset |
|
174 |
|
|
175 |
if (blocking): |
|
176 |
#blocking: |
|
177 |
result = self.server.gaze(rsb_gaze) |
|
178 |
self.logger.debug("server reply: '%s'" % result) |
|
179 |
else: |
|
180 |
future = self.server.gaze.async(rsb_gaze) |
|
181 |
#we can block here for a incoming result with a timeout in s |
|
182 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
183 |
|
|
184 |
self.logger.debug("gaze rpc done") |
|
185 |
|
|
186 |
def publish_mouth_target(self, mouth, blocking): |
|
187 |
"""publish a mouth target via mw |
|
188 |
:param mouth: mouth value to set |
|
189 |
:param blocking: True if this call should block until execution finished on robot |
|
190 |
""" |
|
191 |
self.logger.debug("calling the mouth rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
192 |
|
|
193 |
#create mouth state & fill it with values: |
|
194 |
rsb_mouth = MouthTarget() |
|
195 |
|
|
196 |
#fill proto |
|
197 |
rsb_mouth.opening_left = mouth.opening_left |
|
198 |
rsb_mouth.opening_center = mouth.opening_center |
|
199 |
rsb_mouth.opening_right = mouth.opening_right |
|
200 |
rsb_mouth.position_left = mouth.position_left |
|
201 |
rsb_mouth.position_center = mouth.position_center |
|
202 |
rsb_mouth.position_right = mouth.position_right |
|
203 |
|
|
204 |
if (blocking): |
|
205 |
#blocking: |
|
206 |
result = self.server.mouth(rsb_mouth) |
|
207 |
self.logger.debug("server reply: '%s'" % result) |
|
208 |
else: |
|
209 |
future = self.server.mouth.async(rsb_mouth) |
|
210 |
#we can block here for a incoming result with a timeout in s |
|
211 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
212 |
|
|
213 |
self.logger.debug("mouth rpc done") |
|
214 |
|
|
215 |
def publish_speech(self, text, blocking): |
|
216 |
"""publish a tts request via mw |
|
217 |
:param text: text to synthesize and speak |
|
218 |
:param blocking: True if this call should block until execution finished on robot |
|
219 |
""" |
|
220 |
self.logger.debug("calling the speech rpc (%s)..." % ("BLOCKING" if blocking else "NON-BLOCKING")) |
|
221 |
|
|
222 |
if (blocking): |
|
223 |
#blocking: |
|
224 |
result = self.server.speech(text) |
|
225 |
self.logger.debug("server reply: '%s'" % result) |
|
226 |
else: |
|
227 |
future = self.server.speech.async(text) |
|
228 |
#we can block here for a incoming result with a timeout in s |
|
229 |
#print '> server reply: "%s"' % future.get(timeout = 10); |
|
230 |
|
|
231 |
self.logger.debug("speech rpc done") |
|
232 |
|
|
233 |
####################################################################### |
|
234 |
# some helpers |
|
235 |
def convert_animationtype_to_rsbval(self, value): |
|
236 |
"""convert RobotAnimation.value to RSB animation value |
|
237 |
:param value: RobotAnimation.* id to convert to rsb id |
|
238 |
""" |
|
239 |
#NOTE: this convertion is important as the actual integer values of |
|
240 |
# thy python api and the protobuf might be different |
|
241 |
|
|
242 |
if (value == RobotAnimation.IDLE): |
|
243 |
return Animation().IDLE |
|
244 |
elif (value == RobotAnimation.HEAD_NOD): |
|
245 |
return Animation().HEAD_NOD |
|
246 |
elif (value == RobotAnimation.HEAD_SHAKE): |
|
247 |
return Animation().HEAD_SHAKE |
|
248 |
elif (value == RobotAnimation.EYEBLINK_L): |
|
249 |
return Animation().EYEBLINK_L |
|
250 |
elif (value == RobotAnimation.EYEBLINK_R): |
|
251 |
return Animation().EYEBLINK_R |
|
252 |
elif (value == RobotAnimation.EYEBLINK_BOTH): |
|
253 |
return Animation().EYEBLINK_BOTH |
|
254 |
elif (value == RobotAnimation.EYEBROWS_RAISE): |
|
255 |
return Animation().EYEBROWS_RAISE |
|
256 |
elif (value == RobotAnimation.EYEBROWS_LOWER): |
|
257 |
return Animation().EYEBROWS_LOWER |
|
258 |
else: |
|
259 |
self.logger.error("invalid animation type %d\n" % (value)) |
|
260 |
return Animation().NEUTRAL |
|
261 |
|
|
262 |
def convert_emotiontype_to_rsbval(self, value): |
|
263 |
"""convert RobotEmotion.value to RSB animation value |
|
264 |
:param value: RobotEmotion.* id to convert to rsb id |
|
265 |
""" |
|
266 |
#NOTE: this convertion is important as the actual integer values of |
|
267 |
# thy python api and the protobuf might be different |
|
268 |
|
|
269 |
if (value == RobotEmotion.NEUTRAL): |
|
270 |
return EmotionState().NEUTRAL |
|
271 |
elif (value == RobotEmotion.HAPPY): |
|
272 |
return EmotionState().HAPPY |
|
273 |
elif (value == RobotEmotion.SAD): |
|
274 |
return EmotionState().SAD |
|
275 |
elif (value == RobotEmotion.ANGRY): |
|
276 |
return EmotionState().ANGRY |
|
277 |
elif (value == RobotEmotion.SURPRISED): |
|
278 |
return EmotionState().SURPRISED |
|
279 |
elif (value == RobotEmotion.FEAR): |
|
280 |
return EmotionState().FEAR |
|
281 |
else: |
|
282 |
self.logger.error("invalid emotion type %d\n" % (value)) |
|
283 |
return EmotionState().NEUTRAL |
client/python/hlrc_client/RobotAnimation.py | ||
---|---|---|
26 | 26 |
""" |
27 | 27 |
|
28 | 28 |
class RobotAnimation: |
29 |
IDLE = 0
|
|
30 |
HEAD_NOD = 1
|
|
31 |
HEAD_SHAKE = 2
|
|
32 |
EYEBLINK_L = 3
|
|
33 |
EYEBLINK_R = 4
|
|
34 |
EYEBLINK_BOTH = 5
|
|
35 |
EYEBROWS_RAISE = 6
|
|
36 |
EYEBROWS_LOWER = 7
|
|
29 |
IDLE = 0
|
|
30 |
HEAD_NOD = 1
|
|
31 |
HEAD_SHAKE = 2
|
|
32 |
EYEBLINK_L = 3
|
|
33 |
EYEBLINK_R = 4
|
|
34 |
EYEBLINK_BOTH = 5
|
|
35 |
EYEBROWS_RAISE = 6
|
|
36 |
EYEBROWS_LOWER = 7
|
|
37 | 37 |
|
38 |
def __init__(self, v = IDLE):
|
|
39 |
self.value = v
|
|
40 |
self.time_ms = 1000
|
|
41 |
self.repetitions = 1
|
|
42 |
self.scale = 1.0
|
|
38 |
def __init__(self, v = IDLE):
|
|
39 |
self.value = v |
|
40 |
self.time_ms = 1000 |
|
41 |
self.repetitions = 1 |
|
42 |
self.scale = 1.0 |
|
43 | 43 |
|
44 | 44 |
def value_as_str(self): |
45 |
if (self.value == RobotAnimation.IDLE):
|
|
46 |
return "idle"
|
|
47 |
elif (self.value == RobotAnimation.HEAD_NOD):
|
|
48 |
return "head nod"
|
|
49 |
elif (self.value == RobotAnimation.HEAD_SHAKE):
|
|
50 |
return "head shake"
|
|
51 |
elif (self.value == RobotAnimation.EYEBLINK_L):
|
|
52 |
return "eyeblink l"
|
|
53 |
elif (self.value == RobotAnimation.EYEBLINK_R):
|
|
54 |
return "eyeblink r"
|
|
55 |
elif (self.value == RobotAnimation.EYEBROWS_RAISE):
|
|
56 |
return "eyebrows raise"
|
|
57 |
elif (self.value == RobotAnimation.EYEBROWS_LOWER):
|
|
58 |
return "eyebrows lower"
|
|
59 |
else:
|
|
60 |
return "INVALID ANIMATION TYPE"
|
|
61 |
|
|
62 |
def __str__(self): |
|
45 |
if (self.value == RobotAnimation.IDLE):
|
|
46 |
return "idle" |
|
47 |
elif (self.value == RobotAnimation.HEAD_NOD):
|
|
48 |
return "head nod" |
|
49 |
elif (self.value == RobotAnimation.HEAD_SHAKE):
|
|
50 |
return "head shake" |
|
51 |
elif (self.value == RobotAnimation.EYEBLINK_L):
|
|
52 |
return "eyeblink l" |
|
53 |
elif (self.value == RobotAnimation.EYEBLINK_R):
|
|
54 |
return "eyeblink r" |
|
55 |
elif (self.value == RobotAnimation.EYEBROWS_RAISE):
|
|
56 |
return "eyebrows raise" |
|
57 |
elif (self.value == RobotAnimation.EYEBROWS_LOWER):
|
|
58 |
return "eyebrows lower" |
|
59 |
else:
|
|
60 |
return "INVALID ANIMATION TYPE" |
|
61 |
|
|
62 |
def __str__(self):
|
|
63 | 63 |
return "RobotAnimation = { value='%s', time_ms=%d repetitions=%d scale=%6.2f }" % \ |
64 |
(self.value_as_str(), self.time_ms, self.repetitions, self.scale)
|
|
64 |
(self.value_as_str(), self.time_ms, self.repetitions, self.scale)
|
|
65 | 65 |
|
66 | 66 |
|
client/python/hlrc_client/RobotController.py | ||
---|---|---|
30 | 30 |
import errno |
31 | 31 |
|
32 | 32 |
class RobotController: |
33 |
def __init__(self, mw_name, scope, loglevel=logging.WARNING): |
|
34 |
"""initialise |
|
35 |
:param mw_name: which mw to use, currentyl ROS and RSB are supported |
|
36 |
:param scope: base scope we want to listen on |
|
37 |
:param loglevel: optional log level |
|
38 |
""" |
|
39 |
self.logger = logging.getLogger(__name__) |
|
40 |
|
|
41 |
# create nice and actually usable formatter and add it to the handler |
|
42 |
self.config_logger(loglevel) |
|
43 |
|
|
44 |
#store |
|
45 |
self.scope = scope |
|
46 |
self.mw = mw_name |
|
47 |
self.loglevel = loglevel |
|
48 |
|
|
49 |
self.middleware = None |
|
50 |
|
|
51 |
|
|
52 |
if (self.mw.upper() == "RSB"): |
|
53 |
self.logger.info("creating new middleware connection via RSB") |
|
54 |
try: |
|
55 |
from MiddlewareRSB import MiddlewareRSB |
|
56 |
except ImportError, e: |
|
57 |
self.logger.error("failed to import RSB or the necessary data types: {}".format(e)) |
|
58 |
sys.exit(errno.EINVAL) |
|
33 |
def __init__(self, mw_name, scope, loglevel=logging.WARNING): |
|
34 |
"""initialise |
|
35 |
:param mw_name: which mw to use, currentyl ROS and RSB are supported |
|
36 |
:param scope: base scope we want to listen on |
|
37 |
:param loglevel: optional log level |
|
38 |
""" |
|
39 |
self.logger = logging.getLogger(__name__) |
|
40 |
|
|
41 |
# create nice and actually usable formatter and add it to the handler |
|
42 |
self.config_logger(loglevel) |
|
43 |
|
|
44 |
#store |
|
45 |
self.scope = scope |
|
46 |
self.mw = mw_name |
|
47 |
self.loglevel = loglevel |
|
48 |
|
|
49 |
self.middleware = None |
|
59 | 50 |
|
60 |
#import worked, safe to intantiate RSB mw now |
|
61 |
self.middleware = MiddlewareRSB(self.scope, self.loglevel) |
|
62 | 51 |
|
63 |
elif (self.mw.upper() == "ROS"): |
|
52 |
if (self.mw.upper() == "RSB"): |
|
53 |
self.logger.info("creating new middleware connection via RSB") |
|
54 |
try: |
|
55 |
from MiddlewareRSB import MiddlewareRSB |
|
56 |
except ImportError, e: |
|
57 |
self.logger.error("failed to import RSB or the necessary data types: {}".format(e)) |
|
58 |
sys.exit(errno.EINVAL) |
|
59 |
|
|
60 |
#import worked, safe to intantiate RSB mw now |
|
61 |
self.middleware = MiddlewareRSB(self.scope, self.loglevel) |
|
62 |
|
|
63 |
elif (self.mw.upper() == "ROS"): |
|
64 | 64 |
self.logger.info("creating new middleware connection via ROS") |
65 | 65 |
try: |
66 |
from MiddlewareROS import MiddlewareROS |
|
67 |
except ImportError, e: |
|
68 |
self.logger.error("failed to import ROS or the necessary data types: {}".format(e)) |
|
69 |
sys.exit(errno.EINVAL) |
|
70 |
|
|
71 |
#import worked, safe to intantiate RSB mw now |
|
72 |
self.middleware = MiddlewareROS(self.scope, self.loglevel) |
|
73 |
else: |
|
74 |
self.logger.error("invalid middleware requested (%s). supported: {ROS, RSB}\n\n" % (self.mw)) |
|
75 |
sys.exit(errno.EINVAL) |
|
76 |
|
|
77 |
def __del__(self): |
|
78 |
"""destructor |
|
79 |
""" |
|
80 |
self.logger.debug("destructor of RobotController called") |
|
81 |
|
|
82 |
def config_logger(self, level): |
|
83 |
"""initialise a nice logger formatting |
|
84 |
:param level: log level |
|
85 |
""" |
|
86 |
formatter = logging.Formatter('%(asctime)s %(name)-30s %(levelname)-8s > %(message)s') |
|
87 |
ch = logging.StreamHandler() |
|
88 |
#ch.setLevel(level) |
|
89 |
ch.setFormatter(formatter) |
|
90 |
self.logger.setLevel(level) |
|
91 |
self.logger.addHandler(ch) |
|
92 |
|
|
93 |
def set_current_emotion(self, robot_emotion, blocking = False): |
|
94 |
"""set the current emotion |
|
95 |
:param robot_emotion: a RobotEmotion object |
|
96 |
:param blocking: should this call block during execution? |
|
97 |
""" |
|
98 |
self.logger.debug("set_current_emotion(%s) %s" % (robot_emotion, ("BLOCKING" if blocking else "NON_BLOCKING"))) |
|
99 |
self.middleware.set_current_emotion(robot_emotion, blocking) |
|
100 |
|
|
101 |
def set_default_emotion(self, robot_emotion, blocking = False): |
|
102 |
"""set the default emotion |
|
103 |
:param robot_emotion: a RobotEmotion object |
|
104 |
:param blocking: should this call block during execution? |
|
105 |
""" |
|
106 |
self.logger.debug("set_default_emotion(%s) %s" % (robot_emotion, ("BLOCKING" if blocking else "NON_BLOCKING"))) |
|
107 |
self.middleware.set_default_emotion(robot_emotion, blocking) |
|
108 |
|
|
109 |
def set_gaze_target(self, robot_gaze, blocking = False): |
|
110 |
"""set a gaze target |
|
111 |
:param robot_gaze: a RobotGaze object |
|
112 |
:param blocking: should this call block during execution? |
|
113 |
""" |
|
114 |
|
|
115 |
self.logger.debug("set_gaze_target(%s) %s" % (robot_gaze, ("BLOCKING" if blocking else "NON_BLOCKING"))) |
|
116 |
self.middleware.set_gaze_target(robot_gaze, blocking) |
|
117 |
|
|
118 |
def set_mouth_target(self, robot_mouth, blocking = False): |
|
119 |
"""set a mouth target |
|
120 |
:param robot_mouth: a RobotMouth object |
|
121 |
:param blocking: should this call block during execution? |
|
122 |
""" |
|
123 |
self.logger.debug("set_mouth_target(%s) %s" % (robot_mouth, ("BLOCKING" if blocking else "NON_BLOCKING"))) |
|
124 |
self.middleware.set_mouth_target(robot_mouth, blocking) |
|
125 |
|
|
126 |
def set_head_animation(self, robot_animation, blocking = False): |
|
127 |
"""set a head animation |
|
128 |
:param robot_animation: a RobotAnimation object |
|
129 |
:param blocking: should this call block during execution? |
|
130 |
""" |
|
131 |
self.logger.debug("set_head_animation(%s) %s" % (robot_animation, ("BLOCKING" if blocking else "NON_BLOCKING"))) |
|
132 |
self.middleware.set_head_animation(robot_animation, blocking) |
|
133 |
|
|
134 |
def set_speak(self, text, blocking = False): |
|
135 |
"""request the robot to say something using tts |
|
136 |
:param text: text to synthesize |
|
137 |
:param blocking: should this call block during execution? |
|
138 |
""" |
|
139 |
self.logger.debug("set_speak(%s) %s" % (text, ("BLOCKING" if blocking else "NON_BLOCKING"))) |
|
140 |
self.middleware.set_speak(text, blocking) |
|
141 |
|
|
142 |
#def get_gaze_target(self): |
|
143 |
# result = self.middleware.get_gaze_target() |
|
144 |
# self.logger.debug("get_gaze_target() returned %s" % (result)) |
|
145 |
# return self.middleware.get_gaze_target() |
|
66 |
from MiddlewareROS import MiddlewareROS |
|
67 |
except ImportError, e: |
|
68 |
self.logger.error("failed to import ROS or the necessary data types: {}".format(e)) |
|
69 |
sys.exit(errno.EINVAL) |
|
70 |
|
|
71 |
#import worked, safe to intantiate RSB mw now |
|
72 |
self.middleware = MiddlewareROS(self.scope, self.loglevel) |
Also available in: Unified diff