def broadcastButtonProgram(text, voice, ttsEngine): # Have we broadcast a button program before? if RoboComm.ROS_BUTTON_PROGRAM_BROADCASTER is None: # No, let's create a ros publisher: if SpeakeasyUtils.rosMasterRunning(): # Declare us to be a ROS node. # Allow multiple GUIs to run simultaneously. Therefore # the anonymous=True: RoboComm.ROS_BUTTON_PROGRAM_BROADCASTER = rospy.Publisher('SpeakEasyButtonProgram', SpeakEasyButtonProgram); nodeInfo = rospy.init_node('speakeasy_remote_gui', anonymous=True); else: raise NotImplementedError("ROS master must be running to broadcast button programs.") msg = SpeakEasyButtonProgram() msg.text = text msg.voiceName = voice msg.engineName = ttsEngine RoboComm.ROS_BUTTON_PROGRAM_BROADCASTER.publish(msg)
def __init__(self): ''' Initialize sound to play at the robot. Initializes self.sound_file_names to a list of sound file names for use with play-sound calls to the Robot via ROS. @raise NotImplementedError: if ROS initialization failed. @raise IOError: if SpeakEasy node is online, but service call to it failed. ''' if not ROS_IMPORT_OK: raise NotImplementedError("ROS is not installed on this machine."); self.rosSpeakEasyNodeAvailable = False; self.latestCapabilitiesReply = None; self.nodeStatusLock = threading.Lock(); self.textToSpeechLock = threading.Lock(); self.musicLock = threading.Lock(); self.soundLock = threading.Lock(); # Place to remember threads that repeat voice/sound/music. # These lists are used when stopping those threads: self.speechThreads = []; self.soundThreads = []; self.musicThreads = []; # init_node hangs indefinitely if roscore is not running. # Therefore: check for that. if not SpeakeasyUtils.rosMasterRunning(): raise NotImplementedError("The roscore process is not running."); # We now know that ROS is installed, and that roscore is running. # Publishers of requests for sound effects, music, and text-to-speech: self.rosSoundRequestor = rospy.Publisher('speakeasy_sound_req', SpeakEasySound); self.rosMusicRequestor = rospy.Publisher('speakeasy_music_req', SpeakEasyMusic); self.rosTTSRequestor = rospy.Publisher('speakeasy_text_to_speech_req', SpeakEasyTextToSpeech); # Declare us to be a ROS node. # Allow multiple GUIs to run simultaneously. Therefore # the anonymous=True: nodeInfo = rospy.init_node('speakeasy_remote_gui', anonymous=True); # Don't know why, but without a bit of delay after this init, the first # published message will not be transmitted, no matter what the message type: rospy.sleep(1.0); # Wait for Ros SpeakEasy service for a limited time; there might be none: waitTime = 4; # seconds secsWaited = 0; while not self.robotAvailable() and (secsWaited < waitTime): rospy.loginfo("No SpeakEasy node available. Keep checking for %d more second(s)..." % (waitTime - secsWaited)); rospy.sleep(1); secsWaited += 1; if secsWaited >= waitTime: rospy.logerr("Speech/sound/music capabilities service is offline."); self.rosSpeakEasyNodeAvailable = False; raise NotImplementedError("Speech capabilities service is offline."); rospy.loginfo("Speech capabilities service online.");