yahboom
HomeTutorialsProduct
Solution
Blog
Online Store
About Us
EN/中文
Store
ROSMASTER A1 PRO📖
00.Configuration and Operation Guide
  • 0. Unboxing and Review
  • 1.Assembly Videos
  • 2.User Manual
  • 3.Enter Docker (For Raspberry Pi)
  • 4.A1Pro Front Wheel Servo Calibration
  • 5.USB Camera Calibration
  • 6.Depth Camera Calibration
  • 7.FAQ
  • 8.Desktop Configuration Center and Remote Control Guide
01.Chassis Control Course
  • 1.Robot Information Publishing
  • 2.Robot Handle Control
  • 3.Robot Keyboard Control
  • 4.Linear Velocity Calibration
  • 5.Angular Velocity Calibration
  • 6.Robot URDF Model
  • 7.Robot EKF State Estimation
02.Lidar Course
  • 1.Lidar Introduction and Use
  • 2.Lidar Obstacle Avoidance
  • 3.Lidar Following
  • 4.Lidar Patrol
  • 5.GMapping-SLAM Mapping
  • 6.Cartographer-SLAM Mapping
  • 7.Slam-Toolbox Mapping
  • 8.Lifelong Mode Mapping
  • 9.Navigation2 Single Point Navigation
  • 10.Navigation2 Multi Point Navigation
  • 11.Cartographer Relocalization Navigation
  • 12.Slam-Toolbox Localization Navigation
  • 13.Synchronous Mapping And Navigation
  • 14.Aruco Visual Relocalization Navigation
  • 15.Mobile App Mapping And Navigation
  • 16.AprilTag Transport
  • 17.Color Block Transport
03.USB Camera-Depth Camera Course
  • 1.USB Camera Introduction
  • 2.USB Camera Intrinsic Calibration
  • 3.Nuwa-HP60C Camera Introduction (Depth Camera Only)
  • 4.Depth Camera Distance Measurement (Depth Camera Only)
  • 5.Depth Pseudo Color Image (Depth Camera Only)
  • 6.Block Volume Calculation (Depth Camera Only)
  • 7.Edge Detection (Depth Camera Only)
  • 8.RTAB-Map SLAM Mapping (Depth Camera Only)
  • 9.RTAB-Map Navigation (Depth Camera Only)
04.Robotic Arm and 3D Space Gripping Course
  • 0.Robotic Arm Basic Usage
  • 1.Robotic Arm Kinematics
  • 2.Robotic Arm Chassis Coordination Control
  • 3.AprilTag ID Sorting
  • 4.AprilTag Height Anomaly Sorting
  • 5.AprilTag Tracking and Grasping
  • 6.Color Block Sorting
  • 7.Color Block Height Anomaly Sorting
  • 8.Color Block Tracking and Grasping
  • 9.Wood Block Shape Sorting
  • 10.KCF Tracking and Grasping Objects
  • 11.Mediapipe Gesture ID Sorting AprilTag
  • 12.Mediapipe Gesture Height Sorting AprilTag
  • 13.Desktop Tracking and Grasping AprilTag
  • 14.3D Spatial Tracking AprilTag
  • 15.Line Following Obstacle Clearing
  • 16.Transformer Model Tracking Algorithm
05.Road Network Planning and Navigation
  • 1.Introduction To Road Network Planning
  • 2.Road Network Annotation
  • 3.Planning And Navigation Between Waypoints
  • 4.Road Network Navigation In Any Pose
  • 5.Path Re-planning
06.OpenClaw Basic Course
  • 1.Introduction to OpenClaw
  • 2.OpenClaw Core Concepts
  • 3.OpenClaw API-KEY Configuration
  • 4.OpenClaw Switch Models
  • 5.OpenClaw System Prompt Words
  • 6.OpenClaw Common CLI Commands
07.OpenClaw Interaction Method
  • 1.OpenClaw Webchat Interaction
  • 2.OpenClaw Tui Interaction
  • 3.OpenClaw Voice Dialogue Interaction
  • 4.OpenClaw WhatsApp Interaction
08.OpenClaw Development
  • 1.OpenClaw Connecting to Robot MCP Service
  • 2.Robot CLI Command Tool
  • 3.robot-control plugin tool
  • 4.reply-bridge plugin tool
  • 5.OpenClaw Multimodal Vision
  • 6.OpenClaw Chassis Control
  • 7.OpenClaw Robotic Arm Control
  • 8.OpenClaw Skills Development
  • 9.OpenClaw Scheduled Tasks
  • 10.OpenClaw Multi-Agent Intelligent Agent
  • 11.OpenClaw Active Interaction
  • 12.OpenClaw Vector Memory
09.OpenClaw Embodied Intelligent Application
  • 1.OpenClaw Target Tracking
  • 2.OpenClaw Arm Tracking And Grasping
  • 3.OpenClaw Arm Fixed-point Placement
  • 4.OpenClaw Waste Sorting
  • 5.OpenClaw SLAM Mapping And Navigation
  • 6.OpenClaw Navigation Transport
  • 7.OpenClaw AprilTag Grasping
  • 8.OpenClaw Color Line Patrol
  • 9.OpenClaw Visual Distance Measurement
10.OpenClaw Scenario Sandbox
  • 1.Map Description and Prop Placement
  • 2.Build Sand Table Map
  • 3.Visual Relocation Markers
  • 4.Map Mapping Markers
  • 5.OpenClaw Scenario Sandbox Comprehensive Case
11.AI Model Basics
  • 1.AI Large Model Types and Principles
  • 2.RAG Retrieval Enhancement and Model Training Samples
  • 3.Embodied Intelligent Robot System Architecture
  • 4.Embodied Intelligent Functions Core Source Code
12.AI Model Development
  • 1.Register a Model Service Provider Aaccount
  • 2.Configuring API-KEY
  • 3.Introduction to Dify
  • 4.Basic Dify Features
  • 5.AI Large Model Development - chatbot
  • 6.Deploy the RAG Knowledge Base
  • 7.RAG Knowledge Base + chatbot
  • 8.AI Agent Workflow
  • 9.Custom Wake-up Response
13.AI Model - Text Version
  • 1.Semantic Understand and Command Follow
  • 2.Multimodal Visual Understand
  • 3.Multimodal Visual Understand + Robotic Arm Gripping
  • 4.Multimodal Visual Understand+SLAM Navigation
  • 5.Robotic Arm Gripping+Multimodal Visual Understand+SLAM Navigation
  • 6.Intention Estimation
14.AI Model - Voice Version
  • 1.Semantic Understand and Command Follow
  • 2.Multimodal Visual Understand
  • 3. Multimodal Large Model+Robotic Arm Gripping
  • 4.Multimodal Visual Understand+SLAM Navigation
  • 5.Robotic Arm Gripping+Multimodal Visual Understand+SLAM Navigation
  • 6.Intention Estimation
15.Mediapipe Visual Course
  • 1.Hand Detection
  • 2.Posture Detection
  • 3.Overall Detection
  • 4.Facial Landmark Detection
  • 5.Face Detection
  • 6.Face Special Effects
  • 7.3D Object Recognition
  • 8.Brush
  • 9.Finger Control
  • 10.Palm Target Positioning
  • 11.Fingertip Trajectory Recognition
  • 12.Fingertip Gesture Control Cobotic Arm
  • 13.Gesture Grabbing and Releasing Objects
  • 14.Finger Control Robotic Arm
  • 15.Medipipe Gesture Control Robotic arm Cction Group
16.MoveIt2 Simulation Course
  • 1.MovelT2 Configuration
  • 2.MovelT2 Simulation-Reality Linkage
  • 3.Random Movement
  • 4.Forward Kinematics Design
  • 5.Inverse Kinematics Design
  • 6.Cartesian Path
  • 7.Scene Design
  • 8.Trajectory Planning
  • 9.Collision Detection
  • 10.3D Perception Obstacle‑Avoidance
17.Multi-vehicle Course
  • 1.Multi-vehicle Control
  • 2.Multi-vehicle Navigation
  • 3.Multi-vehicle Formation
18.YOLO26 Development
  • 1.CLI Use
  • 2.Object Detection
  • 3.Instance Segmentation
  • 4.Pose Estimation
  • 5.Image Classification
  • 6.Oriented Object Detection
  • 7.YOLOv26 + DeepSORT Tracking
  • 8.Monocular Depth Estimation
19.Control Board STM32 Driver Course
  • 0.Notes (Must Read)
  • 1.About Expansion Board
  • 2.STM32 Development Environment
  • 3.Button Control
  • 4.FreeRTOS Application
  • 5.Serial Communication
  • 6.SBUS Model Aircraft Remote Control
  • 7.CAN Bus Communication
  • 8.RGB Colorful Light Bar
  • 9.Timer Interrupt to Control PWM Servo
  • 10.Control Serial Port Servos
  • 11.Nine-axis Attitude Sensor to Obtain Data
  • 12.Control Motor
  • 13.Timer Captures the Encoder Data
  • 14.1 Kinematic Analysis of Mecanum Wheel
  • 14.2 Kinematic Analysis of Ackerman
  • 14.3 Kinematic Analysis of 4WD
  • 15.PID Control Robot Movement
20.Docker Course
  • 1.Docker Introduction and Installation
  • 2.Docker Basic Commands
  • 3.Docker Submission and Multi-Terminal Access
  • 4. Docker Startup Script
  • 5.Docker-Vscode Environment Construction
21.Image Processing Basics Course
  • 1. Introduction to Open Source CV
  • 2. Image reading and display
  • 3. Image writing
  • 4. Image quality
  • 5. Pixel Operation
  • 6. Image zoom
  • 7. Image cutting
  • 8. Image translation
  • 9. Image Mirroring
  • 10. Affine Transformation
  • 11. Image Rotation
  • 12. Perspective Transformation
  • 13. Grayscale processing
  • 14. Image Binarization
  • 15. Edge Detection
  • 16. Line drawing
  • 17. Rectangle and circle drawing
  • 18. Drawing text and pictures
22.Linux System Course
  • 1.Introduction to Linux system
  • 2.Ubuntu file system
  • 3.Ubuntu common commands
  • 4.Ubuntu common editors
  • 5.Ubuntu software operation commands
  • 6.Virtual machine installation
  • 7.SSH remote control
  • 8.VNC remote control
  • 9.Transfer files remotely
  • 10.Driver library and communication
  • 11.Static IP and hotspot mode
  • 12.Bind device ID
  • 13.Capacity expansion and resource allocation
  • 14.Update system software sources
  • 15.Set root user password
  • 16.sudo free password
  • 17.Connect to WiFi network
  • 18.View system version
  • 19.Customized service management
  • 20.Back up system image
23.ROS2 Basic Course
  • 1.Introduction to ROS2
  • 2.ROS2 install Humble
  • 3.ROS2 development environment
  • 4.ROS2 workspace
  • 5.ROS2 function package
  • 6.ROS2 node
  • 7.ROS2 topic communication
  • 8.ROS2 service communication
  • 9.ROS2 action communication
  • 10.ROS2 custom interface message
  • 11.ROS2 parameter service case
  • 12.ROS2 meta-function package
  • 13.ROS2 distributed communication
  • 14.ROS2 DDS
  • 15.ROS2 time related API
  • 16.ROS2 common command tools
  • 17.ROS2 rviz2 use
  • 18.ROS2 rqt toolbox
  • 19.ROS2 Launch startup file configuration
  • 20.ROS2 recording and playback tool
  • 21.ROS2 URDF model
  • 22.ROS2 Gazebo simulation platform
  • 23.ROS2 TF2 coordinate transformation
24.Main Control Course
Jetson Orin Nano_NX
  • 1.Jetson Orin board introduction
  • 2.Restore the factory image system
  • 3.Backup SSD system
  • 4.SSD expansion
  • 5.Network configuration
  • 6.SSH remote login
  • 7.VNC remote control
  • 8.Remote file transfer
  • 9.Jtop tool
  • 10.Exchange space expansion
Raspberry Pi
  • 1. Introduction to Raspberry PI 5
  • 2. Raspberry PI system installation and backup
  • 3. Powering the Raspberry PI 5
  • 4. Startup of Raspberry PI 5
  • 5. Update and upgrade operating system
  • 6. Introduction to raspi-config tool
  • 7. config.txt file description
  • 8. Network Configuration
  • 9. remote access
  • 10. Transfer files remotely
  • 11. Set display resolution and rotation
  • 12. Set screen to sleep
  • 13. Play audio and video
  • 14. Using USB camera
  • 15. Using MIPI camera
  • 16. Get real-time temperature of Raspberry Pi
RDKX5
  • 1.Introduction to RDK X5 board
  • 2.Write system file
  • 3.Hardware interface description
  • 4.Install case and other accessories
  • 5.Network configuration
  • 6.Remote login
  • 7.Update system
  • 8.srpi-config user guide
  • 9.config. txt configuration file
  • 10.Self-startup setting
  • 11.RDK exclusive command usage
  • 12.Linux command usage
  • 13.GPIO readwrite operation
  • 14.Image classification algorithm
  • 15.Use USB camera
  • 16.Use MIPI camera
  • 17.Binocular camera depth algorithm
  • 18. Controlling RGB Cooling Fans
Download
  • SystemFile
  • Code
  • 3D_Model_File
  • Software_Tools
  • Hardware_Info
  • Introduction_Manual
  • Script_File
  • Dify AI Agent
Download ZIP

Welcome to ROSMASTER A1 PRO repository

4.reply-bridge plugin tool

reply-bridge Plugin Tool

reply-bridge Plugin Tool1. Course ContentCourse OverviewLearning Objectives3. Introduction to reply-bridge Plugin4. Demo Case5. Source Code Analysis5.1 Plugin Entry and Hook Registration5.2 TTS Tag Extraction and Deduplication Mechanism5.3 TTS Server

1. Course Content

Course Overview

  • reply-bridge plugin is a speech synthesis bridging plugin for OpenClaw. It listens to AI response messages from OpenClaw, parses the <tts>...</tts> speech tags, automatically calls the TTS tool on the MCP server for speech synthesis, and plays the audio through a USB audio device.

  • When used with the robot-control plugin, it enables voice dialogue interaction with the robot, allowing the robot to "speak".

Learning Objectives

  1. Understand the functionality of the reply-bridge plugin

  2. Master plugin installation, viewing, and basic management operations

  3. Understand the working principle of the plugin using MCP protocol to invoke TTS speech synthesis

  4. Be able to use <tts> tags to implement voice broadcast functionality in OpenClaw interaction scenarios

 

3. Introduction to reply-bridge Plugin

reply-bridge plugin is a speech synthesis bridging plugin adapted for OpenClaw vehicle-side. Its working principle is as follows:

  • Listening Mechanism: The plugin registers two hooks: before_message_write and message_sending, to listen for <tts>...</tts> tags in AI response messages

  • Text Extraction: When an AI response contains <tts>label text</tts>, the plugin automatically extracts the text content within the tags

  • Speech Synthesis: Through a built-in MCP client, it calls the TTS tool on the MCP server to convert text to speech

  • Audio Playback: The MCP server calls the TTS engine through the openclaw_bridge node, and finally plays the speech through a USB audio device

  • Deduplication Mechanism: The plugin has a session-level deduplication mechanism built in; the same TTS text will not be repeated in the session to avoid voice redundancy

The plugin communication architecture is as follows:

xxxxxxxxxx
                                                         ┌─────────────┐
                                                         │  OpenClaw   │
                                                         └──────┬──────┘
                                                                │
                                                                ▼
                                                        ┌─────────────┐
                                                         │reply-bridge │
                                                         │     Plugin   │
                                                         └──────┬──────┘
                                                                │MCP Protocol
                                                                ▼
                                                         ┌─────────────┐
                                                         │ MCP Server  │
                                                         └──────┬──────┘
                                                                │
                                                                ▼
                                                         ┌─────────────┐
                                                         |openclaw_   │
                                                         |  bridge    │
                                                         └──────┬──────┘
                                                                │
                                                                ▼
                                                         ┌─────────────┐
                                                            TTS Engine
                                                         └──────┬──────┘
                                                                │
                                                                ▼
                                                         ┌─────────────┐
                                                         | USB Audio   |
                                                         |   Device    |
                                                         └──────-──────┘

 

4. Demo Case

  • Refer to the preceding chapter [OpenClaw Interaction Methods] — [OpenClaw Voice Dialogue Interaction] section for dialogue functionality; this section only explains the implementation principle of the voice dialogue function

 

5. Source Code Analysis

5.1 Plugin Entry and Hook Registration

Source code directory:

xxxxxxxxxx
$HOME/.openclaw/extensions/reply-bridge/index.ts

The plugin source code is located in index.ts under the plugin directory. It uses the registerReplyBridge function as the entry point and registers event listener hooks using the OpenClaw Plugin API. The core code is as follows:

xxxxxxxxxx
export default function registerReplyBridge(api: OpenClawPluginApi) {
  // Hook: before_message_write — triggered when each message is written to session history
  api.on("before_message_write", (event, ctx) => {
    const message = event.message as AgentMessage;
    const sessionId = ctx.sessionId;

    // Only process messages with assistant role
    if (message.role !== "assistant") return;

    const text = extractTextFromAgentMessage(message);
    if (!text) return;

    const ttsTexts = extractTtsTags(text);
    if (ttsTexts.length === 0) return;

    api.logger.info(`[reply-bridge] extracted ${ttsTexts.length} TTS segment(s)`);
    sendTtsTextsFireAndForget(ttsTexts, sessionId, (msg) => api.logger.info(msg));
  });

  api.logger.info("reply-bridge: Plugin registered (hooks: before_message_write, message_sending)");
}

Code Description:

  1. Registration Entry: export default function registerReplyBridge(api) is the plugin's default export function. OpenClaw automatically calls it when loading the plugin, passing in the OpenClawPluginApi instance

  2. api.on("before_message_write"): Registers a pre-message-write hook that triggers when the AI generates a response and writes it to session history—this is the main channel for TTS processing

  3. Role Filtering: message.role !== "assistant" ensures only AI assistant response messages are processed, ignoring user messages

  4. Extraction Flow: extractTextFromAgentMessage → extractTtsTags → sendTtsTextsFireAndForget—three steps complete the full chain from message text to TTS playback

  5. Fire-and-Forget Mode: TTS calls use a fire-and-forget pattern that does not block the message write process, ensuring a smooth user experience

Key Function Description:

  • extractTextFromAgentMessage(message): Extracts plain text content from an AgentMessage object, handling possible multimodal content (text, images, etc.) in the message

  • extractTtsTags(text): Parses all content within <tts>...</tts> tags from the text, returning a list of TTS text fragments

  • sendTtsTextsFireAndForget(ttsTexts, sessionId, logger): Asynchronously sends the extracted TTS text to the MCP server for speech synthesis using a fire-and-forget pattern without blocking the main flow

  • ctx.sessionId: Current session ID, used for session-level TTS deduplication to ensure the same text is not repeatedly played in the same session

5.2 TTS Tag Extraction and Deduplication Mechanism

The code for extracting <tts> tag content from AI response text is as follows:

xxxxxxxxxx
/**
 * Extract plain text fragments wrapped in <tts>...</tts> tags
 * Uses indexOf instead of regex to avoid boundary issues with pattern matching
 */
function extractTtsTags(content: string): string[] {
  const matches: string[] = [];
  const openTag = "<tts>";
  const closeTag = "</tts>";
  let start = 0;

  while (true) {
    const openIdx = content.indexOf(openTag, start);
    if (openIdx === -1) break;
    const closeIdx = content.indexOf(closeTag, openIdx + openTag.length);
    if (closeIdx === -1) break;
    const text = content.slice(openIdx + openTag.length, closeIdx).trim();
    if (text) matches.push(text);
    start = closeIdx + closeTag.length;
  }

  return matches;
}

Code Description:

  1. extractTtsTags(): Uses indexOf to scan through text section by section, extracting all content within <tts>...</tts> tags. Choosing indexOf over regex is to avoid boundary issues with special characters and nested pattern matching, improving parsing stability

  2. Deduplication Mechanism: Through sentTtsTexts (Map<string, Set<string>>), records texts already played for each session; the same text will not be repeatedly played in the session, avoiding voice redundancy

Code Detail Description:

  • indexOf(openTag, start): Searches for the <tts> opening tag starting from the start position, returning the tag's starting index, or -1 if not found

  • indexOf(closeTag, openIdx + openTag.length): Searches for the </tts> closing tag after the opening tag, ensuring correct matching of the nearest closing position

  • content.slice(openIdx + openTag.length, closeIdx).trim(): Extracts the text content between opening and closing tags and trims leading/trailing whitespace

  • start = closeIdx + closeTag.length: Updates the search starting position to after the closing tag, supporting multiple <tts> tags within the same text

  • sentTtsTexts: Map<sessionId, Set<text>> structure, using session ID as key and played text set as value, implementing session-level deduplication

 

5.3 TTS Server

xxxxxxxxxx
~/yahboomcar_ros2_ws/dofbot_pro_ws/src/ackermann_mcp/ackermann_mcp/openclaw_bridge.py

 

  • init_tts_engine: Initialize TTS speech synthesis engine

    • When USE_OLINE_TTS is False: Load local PiperTTS engine for offline speech synthesis

    • When tts_supplier is aliyun: Load TongyiTTS (Alibaba Cloud Tongyi), requires API Key, model, and voice tone configuration

    • When tts_supplier is xunfei: Load XunfeiTTS (iFlytek), requires key path and encryption key configuration

  • _process_tts_queue: TTS queue processing worker thread

    • Continuously checks the stop flag and retrieves text to synthesize from the queue (0.5s timeout)

    • Calls _handle_tts to process each text

  • _handle_tts: Handle single TTS request

    • Wait for play_audio Action server to be ready

    • Call tts_engine.synthesize to synthesize text into an audio file

    • Send PlayAudio Action goal, handle goal acceptance/rejection via callback

    • Wait for playback to complete, check stop flag during playback, support canceling ongoing playback

Code Detail Description:

  • self.USE_OLINE_TTS: Offline TTS switch. When False, load local PiperTTS engine; when True, load online engine based on tts_supplier

  • self.tts_supplier: Online TTS provider selection, supports aliyun (Alibaba Cloud Tongyi) and xunfei (iFlytek)

  • self.tts_engine.synthesize(text, self.tts_out_path): Call TTS engine to synthesize text into an audio file, saved to tts_out_path path

  • self.audio_client.wait_for_server(timeout_sec=3.0): Wait for play_audio Action server to come online; skip this playback if timeout exceeds 3 seconds

  • PlayAudio.Goal(): Construct Action goal message for playing audio, file_path specifies the synthesized audio file path

  • _goal_response_cb: Action goal sending callback, checks if the server accepted the goal; if rejected, logs a warning and ends

  • _tts_goal_handle_lock: Thread lock, protects concurrent access to _current_tts_goal_handle, ensuring safety for cancellation operations

  • _result_cb: Action completion callback, clears current goal handle and sets done_event to notify main thread

  • done_event.wait(timeout=0.1): Main loop polls playback completion status at 0.1-second intervals, checks stop flag during polling to support playback cancellation

  • gh.cancel_goal_async(): Asynchronously cancel the currently playing Action goal when the stop flag is detected


    def init_tts_engine(self):
        if not self.USE_OLINE_TTS:
            from multi_brains_pre.utils.tts import  PiperTTS
            self.tts_engine=PiperTTS(self.language)
            if self.tts_engine.init_tts_engine() :
                self.get_logger().info(Fore.GREEN+"Piper TTS_Engine initialized successfully"+Fore.RESET)
            else:
                error_msg="Piper TTS_Engine initialized failed"

                self.get_logger().error(Fore.RED+error_msg+Fore.RESET)
                raise RuntimeError(error_msg)
            return

        if self.tts_supplier=="aliyun":
            from multi_brains_pre.utils.tts import TongyiTTS
            self.tts_engine=TongyiTTS(self.aliyun_api_key,self.tts_model,self.tts_voice_tone)
            result=self.tts_engine.init_tts_engine()
            if result[0]:
                self.get_logger().info(Fore.GREEN+"Tongyi TTS_Engine initialized successfully"+Fore.RESET)
            else:
                self.get_logger().error(Fore.RED+f"Tongyi TTS_Engine initialized failed:{result[1]}"+Fore.RESET)

                raise RuntimeError(f"Tongyi TTS_Engine initialized failed:{result[1]}")


        elif self.tts_supplier=="xunfei":
            from multi_brains_pre.utils.tts import  XunfeiTTS
            self.tts_engine=XunfeiTTS(self.key_path,self.xunfei_encrypted_key,self.config_file)

            if self.tts_engine.init_tts_engine():
                self.get_logger().info(Fore.GREEN+"Xunfei TTS_Engine initialized successfully"+Fore.RESET)
            else:

                error_msg="Xunfei TTS_Engine initialized failed"
                self.get_logger().error(Fore.RED+error_msg+Fore.RESET)
                raise RuntimeError(error_msg)
    def _process_tts_queue(self):
        """TTS queue processing worker thread"""
        while not self._tts_worker_stop_event.is_set():
            try:
                text = self._tts_queue.get(timeout=0.5)
            except queue.Empty:
                continue
            self._handle_tts(text)

    def _handle_tts(self, text: str):
        if not self.audio_client.wait_for_server(timeout_sec=3.0):
            self.get_logger().warn(Fore.YELLOW + "play_audio action server not available, skip voice" + Fore.RESET)
            return
        if not self.tts_engine.synthesize(text, self.tts_out_path):
            self.get_logger().error(Fore.RED + "Speech synthesis failed. Check whether the TTS model is available" + Fore.RESET)
            return

        goal = PlayAudio.Goal()
        goal.file_path = self.tts_out_path

        done_event = threading.Event()

        def _goal_response_cb(future):
            goal_handle = future.result()
            if not goal_handle or not goal_handle.accepted:
                self.get_logger().warn("TTS play goal rejected")
                done_event.set()
                return
            with self._tts_goal_handle_lock:
                if self._tts_worker_stop_event.is_set():
                    goal_handle.cancel_goal_async()
                    done_event.set()
                    return
                self._current_tts_goal_handle = goal_handle
            result_future = goal_handle.get_result_async()
            result_future.add_done_callback(_result_cb)

        def _result_cb(future):
            with self._tts_goal_handle_lock:
                self._current_tts_goal_handle = None
            done_event.set()

        send_future = self.audio_client.send_goal_async(goal)
        send_future.add_done_callback(_goal_response_cb)

        while not done_event.wait(timeout=0.1):
            if self._tts_worker_stop_event.is_set():
                with self._tts_goal_handle_lock:
                    gh = self._current_tts_goal_handle
                if gh is not None:
                    gh.cancel_goal_async()
                break

robot-control plugin tool
OpenClaw Multimodal Vision

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文