8
8
9
9
import rclpy
10
10
import requests
11
+ from ament_index_python import get_package_prefix
11
12
from rcl_interfaces .msg import Parameter , SetParametersResult
12
13
from rclpy .node import Node
13
14
from rclpy .publisher import Publisher
@@ -24,6 +25,13 @@ def speak(text: str, publisher: Publisher, priority: int = 20, speaking_active:
24
25
publisher .publish (msg )
25
26
26
27
28
+ def say (text : str ) -> None :
29
+ """Start the shell `say.sh` script to output given text with mimic3. Beware: this is blocking."""
30
+ script_path = os .path .join (get_package_prefix ("bitbots_tts" ), "lib/bitbots_tts/say.sh" )
31
+ process = subprocess .Popen ((script_path , text ))
32
+ process .wait ()
33
+
34
+
27
35
class Speaker (Node ):
28
36
"""
29
37
Uses tts to say messages from the speak topic.
@@ -50,17 +58,6 @@ def __init__(self) -> None:
50
58
# Callback for parameter changes
51
59
self .add_on_set_parameters_callback (self .on_set_parameters )
52
60
53
- # Mapping from robot name to voice name
54
- self .robot_voice_mapping = {
55
- "amy" : "en_US/vctk_low" ,
56
- "donna" : "en_US/vctk_low" ,
57
- "jack" : "en_UK/apope_low" ,
58
- "melody" : "en_US/vctk_low" ,
59
- "rory" : "en_UK/apope_low" ,
60
- }
61
-
62
- self .robot_speed_mapping = {"amy" : 2.2 , "donna" : 2.2 , "jack" : 1.0 , "melody" : 2.2 , "rory" : 1.0 }
63
-
64
61
# Subscribe to the speak topic
65
62
self .create_subscription (Audio , "speak" , self .speak_cb , 10 )
66
63
@@ -92,30 +89,15 @@ def on_set_parameters(self, parameters: List[Parameter]) -> SetParametersResult:
92
89
return SetParametersResult (successful = True )
93
90
94
91
def run_speaker (self ) -> None :
95
- """Continously checks the queue and speaks the next message."""
92
+ """Continuously checks the queue and speaks the next message."""
96
93
# Check if there is a message in the queue
97
94
if len (self .prio_queue ) > 0 :
98
95
# Get the next message and speak it
99
96
text , _ = self .prio_queue .pop (0 )
100
- self .say (text )
101
-
102
- def say (self , text : str ) -> None :
103
- """Speak this specific text."""
104
- # Get the voice name from the environment variable ROBOT_NAME or use the default voice if it's not set
105
- voice = self .robot_voice_mapping .get (os .getenv ("ROBOT_NAME" ), "en_US/vctk_low" )
106
- # Get the speed for the given robot or use the default speed if no robot name is set
107
- speed = self .robot_speed_mapping .get (os .getenv ("ROBOT_NAME" ), 2.2 )
108
- try :
109
- # Generate the speech with mimic
110
- mimic_subprocess = subprocess .Popen (
111
- ("mimic3" , "--remote" , "--voice" , voice , "--length-scale" , str (speed ), text ), stdout = subprocess .PIPE
112
- )
113
- # Play the audio from the previous process with aplay
114
- aplay_subprocess = subprocess .Popen (("aplay" , "-" ), stdin = mimic_subprocess .stdout , stdout = subprocess .PIPE )
115
- # Wait for the process to finish
116
- aplay_subprocess .wait ()
117
- except OSError :
118
- self .get_logger ().error (str (traceback .format_exc ()))
97
+ try :
98
+ say (text )
99
+ except OSError :
100
+ self .get_logger ().error (str (traceback .format_exc ()))
119
101
120
102
def speak_cb (self , msg : Audio ) -> None :
121
103
"""Handles incoming msg on speak topic."""
0 commit comments