def sendMsg(self, snd, cmd, s, arg2="", vol=1.0, prior = 1, **kwargs): """ Internal method that publishes the sound request, either directly as a SoundRequest to the soundplay_node or through the actionlib interface (which blocks until the sound has finished playing). The blocking behavior is nominally the class-wide setting unless it has been explicitly specified in the play call. """ # Use the passed-in argument if it exists, otherwise fall back to the # class-wide setting. blocking = kwargs.get('blocking', self._blocking) msg = SoundRequest() msg.sound = snd # Threshold volume between 0 and 1. msg.volume = max(0, min(1, vol)) msg.command = cmd msg.arg = s msg.arg2 = arg2 msg.priority = prior rospy.logdebug('Sending sound request with volume = {}' ' and blocking = {}'.format(msg.volume, blocking)) # Defensive check for the existence of the correct communicator. if not blocking and not self.pub: rospy.logerr('Publisher for SoundRequest must exist') return if blocking and not self.actionclient: rospy.logerr('Action client for SoundRequest does not exist.') return if not blocking: # Publish message directly and return immediately self.pub.publish(msg) if self.pub.get_num_connections() < 1: rospy.logwarn("Sound command issued, but no node is subscribed" " to the topic. Perhaps you forgot to run" " soundplay_node.py?") else: # Block until result comes back. assert self.actionclient, 'Actionclient must exist' rospy.logdebug('Sending action client sound request [blocking]') self.actionclient.wait_for_server() goal = SoundRequestGoal() goal.sound_request = msg self.actionclient.send_goal(goal) self.actionclient.wait_for_result() rospy.logdebug('sound request response received') return
def sendMsg(self, snd, cmd, s, arg2="", vol=1.0, **kwargs): """ Internal method that publishes the sound request, either directly as a SoundRequest to the soundplay_node or through the actionlib interface (which blocks until the sound has finished playing). The blocking behavior is nominally the class-wide setting unless it has been explicitly specified in the play call. """ # Use the passed-in argument if it exists, otherwise fall back to the # class-wide setting. blocking = kwargs.get('blocking', self._blocking) msg = SoundRequest() msg.sound = snd # Threshold volume between 0 and 1. msg.volume = max(0, min(1, vol)) msg.command = cmd msg.arg = s msg.arg2 = arg2 rospy.logdebug('Sending sound request with volume = {}' ' and blocking = {}'.format(msg.volume, blocking)) # Defensive check for the existence of the correct communicator. if not blocking and not self.pub: rospy.logerr('Publisher for SoundRequest must exist') return if blocking and not self.actionclient: rospy.logerr('Action client for SoundRequest does not exist.') return if not blocking: # Publish message directly and return immediately self.pub.publish(msg) if self.pub.get_num_connections() < 1: rospy.logwarn("Sound command issued, but no node is subscribed" " to the topic. Perhaps you forgot to run" " soundplay_node.py?") else: # Block until result comes back. assert self.actionclient, 'Actionclient must exist' rospy.logdebug('Sending action client sound request [blocking]') self.actionclient.wait_for_server() goal = SoundRequestGoal() goal.sound_request = msg self.actionclient.send_goal(goal) self.actionclient.wait_for_result() rospy.logdebug('sound request response received') return
def play_sound(sound, lang='', topic_name='robotsound', volume=1.0, wait=False): """ Plays sound using sound_play server Args: sound: if sound is pathname, plays sound file located at given path if it is number, server plays builtin sound otherwise server plays sound as speech sentence topic-name: namespace of sound_play server wait: wait until sound is played """ msg = SoundRequest(command=SoundRequest.PLAY_ONCE) if isinstance(sound, int): msg.sound = sound elif isinstance(sound, str) and Path(sound).exists(): msg.sound = SoundRequest.PLAY_FILE msg.arg = sound elif isinstance(sound, str): msg.sound = SoundRequest.SAY msg.arg = sound else: raise ValueError if hasattr(msg, 'volume'): msg.volume = volume if topic_name in _sound_play_clients: client = _sound_play_clients[topic_name] else: client = actionlib.SimpleActionClient(topic_name, SoundRequestAction) client.wait_for_server() goal = SoundRequestGoal() if client.get_state() == actionlib_msgs.msg.GoalStatus.ACTIVE: client.cancel_goal() client.wait_for_result(timeout=rospy.Duration(10)) goal.sound_request = msg _sound_play_clients[topic_name] = client client.send_goal(goal) if wait is True: client.wait_for_result(timeout=rospy.Duration(10)) return client
def do_speak(self, goal): """The action handler. Note that although it responds to client after the audio play is finished, a client can choose not to wait by not calling ``SimpleActionClient.waite_for_result()``. """ self.goal_text = strip_tags(goal.text) self.state_pub.publish(state=TTSState.SYNTHESIZING, text=self.goal_text) res = do_synthesize(goal) rospy.loginfo('synthesizer returns: %s', res) try: res = json.loads(res.result) except ValueError as err: syn = 'Expecting JSON from synthesizer but got {}'.format( res.result) rospy.logerr('%s. Exception: %s', syn, err) self.state_pub.publish(state=TTSState.ERROR, text=syn) self.finish_with_result(syn) return if 'Audio File' in res: audio_file = res['Audio File'] rospy.loginfo('Will play %s', audio_file) mut_d = mutagen.File(audio_file) self.length = mut_d.info.length self.utterance_pub.publish(self.goal_text) msg = SoundRequest() # self.sendMsg(SoundRequest.PLAY_FILE, SoundRequest.PLAY_ONCE, sound, # vol=volume, **kwargs) msg.sound = SoundRequest.PLAY_FILE msg.volume = rospy.get_param("/flo_hum_vol") msg.command = SoundRequest.PLAY_ONCE msg.arg = audio_file msg.arg2 = "" goal = SoundRequestGoal() goal.sound_request = msg self.done = False self.sound_client.send_goal(goal, active_cb=self.sound_received, feedback_cb=self.sound_fb, done_cb=self.sound_done) # self.result = audio_file t_rate = rospy.Rate(10) success = True while not self.done: if self.server.is_preempt_requested(): self.sound_client.cancel_goal() self.server.set_preempted() success = False break t_rate.sleep() self.state_pub.publish(state=TTSState.WAITING) if success: self.finish_with_result('completed sound play in') else: rospy.logerr('No audio file in synthesize voice result') self.state_pub.publish(state=TTSState.ERROR, text='no audio file') self.finish_with_result('no audio file')