From 14b12e61d57016c71de0270c170ad295d6a1e23c Mon Sep 17 00:00:00 2001 From: NuoDaJia02 Date: Mon, 5 Jan 2026 09:53:18 +0800 Subject: [PATCH] update @huiyu --- package.xml | 21 +++++++++++ resource/robot_speaker | 0 robot_speaker/__init__.py | 0 robot_speaker/robot_speaker_node.py | 55 +++++++++++++++++++++++++++++ setup.cfg | 4 +++ setup.py | 26 ++++++++++++++ 6 files changed, 106 insertions(+) create mode 100644 package.xml create mode 100644 resource/robot_speaker create mode 100644 robot_speaker/__init__.py create mode 100644 robot_speaker/robot_speaker_node.py create mode 100644 setup.cfg create mode 100644 setup.py diff --git a/package.xml b/package.xml new file mode 100644 index 0000000..84aa0e6 --- /dev/null +++ b/package.xml @@ -0,0 +1,21 @@ + + + + robot_speaker + 0.0.0 + TODO: Package description + mzebra + Apache-2.0 + + rclpy + example_interfaces + + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/resource/robot_speaker b/resource/robot_speaker new file mode 100644 index 0000000..e69de29 diff --git a/robot_speaker/__init__.py b/robot_speaker/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/robot_speaker/robot_speaker_node.py b/robot_speaker/robot_speaker_node.py new file mode 100644 index 0000000..9be64cc --- /dev/null +++ b/robot_speaker/robot_speaker_node.py @@ -0,0 +1,55 @@ +import rclpy +from rclpy.node import Node +from example_interfaces.msg import String +import threading +from queue import Queue +import time +import espeakng +import pyttsx3 + + +class RobotSpeakerNode(Node): + def __init__(self, node_name): + super().__init__(node_name) + self.novels_queue_ = Queue() + self.novel_subscriber_ = self.create_subscription( + String, 'robot_msg', self.novel_callback, 10) + self.speech_thread_ = threading.Thread(target=self.speak_thread) + self.speech_thread_.start() + + def novel_callback(self, msg): + self.novels_queue_.put(msg.data) + + def speak_thread(self): + # 初始化引擎 + engine = pyttsx3.init() + # 调整参数 + engine.setProperty('rate', 150) # 语速(150更自然) + engine.setProperty('volume', 1.0) # 音量(0.0-1.0) + + # 选择中文音色(修正:使用 languages 属性,且是列表) + voices = engine.getProperty('voices') + for voice in voices: + # 检查语音支持的语言列表中是否包含中文('zh' 或 'zh-CN' 等) + if any('zh' in lang for lang in voice.languages): + engine.setProperty('voice', voice.id) + self.get_logger().info(f'已选择中文语音:{voice.id}') + break + else: + self.get_logger().warning('未找到中文语音库,将使用默认语音') + + while rclpy.ok(): + if self.novels_queue_.qsize() > 0: + text = self.novels_queue_.get() + engine.say(text) + engine.runAndWait() # 等待语音播放完成 + else: + time.sleep(0.5) + + + +def main(args=None): + rclpy.init(args=args) + node = RobotSpeakerNode("robot_speaker_node") + rclpy.spin(node) + rclpy.shutdown() diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..a631b4c --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/robot_speaker +[install] +install_scripts=$base/lib/robot_speaker diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..3f2d00e --- /dev/null +++ b/setup.py @@ -0,0 +1,26 @@ +from setuptools import find_packages, setup + +package_name = 'robot_speaker' + +setup( + name=package_name, + version='0.0.0', + packages=[package_name], + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='mzebra', + maintainer_email='mzebra@foxmail.com', + description='TODO: Package description', + license='Apache-2.0', + tests_require=['pytest'], + entry_points={ + 'console_scripts': [ + 'robot_speaker_node=robot_speaker.robot_speaker_node:main' + ], + }, +)