277 lines
11 KiB
Plaintext
277 lines
11 KiB
Plaintext
# =============================================================================
|
|
# AGIBOT A3 - Voice Control | configuration
|
|
# =============================================================================
|
|
# Copy this file to `.env` and edit that copy. Nothing in the source code needs
|
|
# to change to switch between the simulator and the real robot.
|
|
#
|
|
# Restart the server after editing, or press "Reload config" in the dashboard.
|
|
# =============================================================================
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 1. WEB SERVER (this PC)
|
|
# -----------------------------------------------------------------------------
|
|
# 127.0.0.1 = only this PC can open the dashboard (recommended).
|
|
# 0.0.0.0 = other devices on your LAN can open it too (tablet, phone).
|
|
HOST=127.0.0.1
|
|
PORT=8000
|
|
LOG_LEVEL=info
|
|
|
|
# Only needed if you serve the frontend from a different origin. Usually empty.
|
|
CORS_ORIGINS=
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 2. ROBOT MODE <<< THIS IS THE SWITCH >>>
|
|
# -----------------------------------------------------------------------------
|
|
# mock = simulated robot, no hardware required (default; use this today)
|
|
# real = talk to a physical AGIBOT A3 over the network
|
|
ROBOT_MODE=mock
|
|
|
|
ROBOT_NAME=AGIBOT A3
|
|
ROBOT_MODEL=AgiBot A3
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 3. ROBOT ADDRESS <<< PUT THE ROBOT IP HERE WHEN YOU HAVE IT >>>
|
|
# -----------------------------------------------------------------------------
|
|
# Leave ROBOT_IP empty while ROBOT_MODE=mock.
|
|
# When the robot is powered on and on the same LAN:
|
|
# ROBOT_MODE=real
|
|
# ROBOT_IP=192.168.1.50 <- the robot's actual IP on YOUR network
|
|
# ROBOT_PORT=59301 <- AgiBot's documented A3 TTS RPC port (HDU)
|
|
#
|
|
# NOTE: AgiBot's own examples use 10.42.10.10 - that is the robot's INTERNAL
|
|
# address for its head unit (HDU) and is not reachable from your PC. Use the
|
|
# HDU's address on your WiFi/LAN. Find it with: python scripts/discover_robot.py
|
|
ROBOT_IP=
|
|
ROBOT_PORT=59301
|
|
ROBOT_USE_TLS=false
|
|
|
|
# Timing (seconds). Keep connect timeout short so the UI never feels stuck.
|
|
ROBOT_CONNECT_TIMEOUT=3.0
|
|
ROBOT_REQUEST_TIMEOUT=8.0
|
|
ROBOT_HEALTH_INTERVAL=5.0
|
|
ROBOT_RECONNECT_MIN_DELAY=1.0
|
|
ROBOT_RECONNECT_MAX_DELAY=15.0
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 4. HOW TO TALK TO THE A3
|
|
# -----------------------------------------------------------------------------
|
|
# Only used when ROBOT_MODE=real.
|
|
#
|
|
# aimdk - AgiBot's documented A3 speech RPC <<< USE THIS, it is the default >>>
|
|
# http - a generic HTTP/REST endpoint you specify yourself
|
|
# ws - a WebSocket endpoint you specify yourself
|
|
# ros2 - a ROS 2 topic or service (requires ROS 2 on this PC)
|
|
# ssh - run a command on the robot over SSH (last-resort fallback)
|
|
#
|
|
# The `aimdk` transport implements the interface AgiBot documents for the A3:
|
|
# POST http://<robot>:59301/rpc/aimdk.protocol.TTSService/PlayTTS
|
|
# Content-Type: application/json
|
|
# {"text": "...", "priority_level": "INTERACTION_L6", "domain": "...",
|
|
# "trace_id": "...", "is_interrupted": true}
|
|
# Docs: https://open.agibot.com/docs/en/aimdk/a3/v3_2/dev_guide/07-02-audio_play
|
|
#
|
|
# The defaults below come from that documentation, but they are still settings
|
|
# rather than hard-coded values: AgiBot does not guarantee ports or names across
|
|
# firmware, and there is no endpoint-discovery API. If your unit differs, change
|
|
# it here - never in the source. See docs/AGIBOT_A3_INTEGRATION.md.
|
|
A3_TRANSPORT=aimdk
|
|
|
|
|
|
# --- 4a. AimDK transport (recommended) ---------------------------------------
|
|
# Uses ROBOT_IP and ROBOT_PORT above.
|
|
A3_AIMDK_SERVICE=aimdk.protocol.TTSService
|
|
A3_AIMDK_PLAY_METHOD=PlayTTS
|
|
A3_AIMDK_STOP_METHOD=StopTTSTraceId
|
|
A3_AIMDK_STATUS_METHOD=GetAudioStatus
|
|
|
|
# Playback priority. Only INTERACTION_L6 appears in AgiBot's A3 examples.
|
|
A3_AIMDK_PRIORITY=INTERACTION_L6
|
|
|
|
# Free-form caller tag sent with each request, so robot-side logs show who spoke.
|
|
A3_AIMDK_DOMAIN=voice_control
|
|
|
|
# true = a new utterance interrupts whatever is currently playing.
|
|
A3_AIMDK_INTERRUPT=true
|
|
|
|
# Hard request limit documented by AgiBot: 1024 BYTES of UTF-8 (not characters).
|
|
# Longer text is split automatically on sentence boundaries and sent in order.
|
|
A3_AIMDK_MAX_BYTES=1024
|
|
|
|
|
|
# --- 4b. Generic HTTP / REST transport ---------------------------------------
|
|
# Only needed if your unit does NOT use the AimDK interface above.
|
|
# Path is relative to http://ROBOT_IP:ROBOT_PORT
|
|
# Example shape only - replace with the documented endpoint:
|
|
# A3_HTTP_SPEAK_PATH=/api/v1/tts/speak
|
|
A3_HTTP_SPEAK_PATH=
|
|
A3_HTTP_SPEAK_METHOD=POST
|
|
|
|
# JSON body template. {text} is replaced with the operator's text.
|
|
# Placeholders: {text} {id} {voice} {language} {volume} {speed}
|
|
# A key whose value resolves to nothing is dropped from the request.
|
|
A3_HTTP_SPEAK_PAYLOAD={"text": "{text}"}
|
|
|
|
# Optional: endpoint that interrupts speech.
|
|
A3_HTTP_STOP_PATH=
|
|
A3_HTTP_STOP_METHOD=POST
|
|
A3_HTTP_STOP_PAYLOAD={}
|
|
|
|
# Optional: cheap endpoint polled for the connection indicator.
|
|
# If left empty the app falls back to a TCP connect test on ROBOT_PORT.
|
|
A3_HTTP_STATUS_PATH=
|
|
A3_HTTP_STATUS_METHOD=GET
|
|
|
|
# Optional: extra headers and auth.
|
|
A3_HTTP_HEADERS={}
|
|
A3_HTTP_AUTH_TOKEN=
|
|
|
|
# Optional: dotted path to a success flag in the JSON response, e.g. "code" or
|
|
# "result.success". Leave empty to trust the HTTP status code alone.
|
|
A3_HTTP_SUCCESS_FIELD=
|
|
|
|
|
|
# --- 4c. WebSocket transport --------------------------------------------------
|
|
A3_WS_PATH=
|
|
A3_WS_SPEAK_PAYLOAD={"text": "{text}"}
|
|
A3_WS_STOP_PAYLOAD={}
|
|
A3_WS_PING_INTERVAL=20
|
|
|
|
# Optional: how the robot announces "finished speaking". With these set, the
|
|
# dashboard shows real completion instead of an estimate.
|
|
# A3_WS_DONE_FIELD=event
|
|
# A3_WS_DONE_VALUE=speech_end
|
|
A3_WS_DONE_FIELD=
|
|
A3_WS_DONE_VALUE=
|
|
|
|
|
|
# --- 4d. ROS 2 transport ------------------------------------------------------
|
|
# Requires ROS 2 installed on this PC and the same ROS_DOMAIN_ID as the robot.
|
|
A3_ROS_DOMAIN_ID=0
|
|
A3_ROS_SPEAK_TOPIC=
|
|
A3_ROS_SPEAK_MSG_TYPE=std_msgs/msg/String
|
|
A3_ROS_SPEAK_MSG_FIELD=data
|
|
A3_ROS_STOP_TOPIC=
|
|
A3_ROS_USE_SERVICE=false
|
|
A3_ROS_SERVICE_NAME=
|
|
A3_ROS_SERVICE_TYPE=
|
|
|
|
|
|
# --- 4e. SSH transport (last resort) --------------------------------------------
|
|
# Runs a command on the robot's own Linux computer. {text} is shell-quoted.
|
|
# A3_SSH_SPEAK_COMMAND=<the command that makes your robot speak> {text}
|
|
A3_SSH_USER=root
|
|
A3_SSH_PORT=22
|
|
A3_SSH_KEY_PATH=
|
|
A3_SSH_PASSWORD=
|
|
A3_SSH_SPEAK_COMMAND=
|
|
A3_SSH_STOP_COMMAND=
|
|
A3_SSH_PROBE_COMMAND=true
|
|
|
|
|
|
# --- 4f. Optional TTS parameters (sent only when set) -------------------------
|
|
A3_VOICE=
|
|
A3_LANGUAGE=
|
|
A3_VOLUME=
|
|
A3_SPEED=
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 5. SPEECH BEHAVIOUR
|
|
# -----------------------------------------------------------------------------
|
|
SPEECH_MAX_LENGTH=1000
|
|
SPEECH_MIN_LENGTH=1
|
|
# true = pressing Speak while talking interrupts and says the new text
|
|
# false = pressing Speak while talking is rejected with "already speaking"
|
|
SPEECH_ALLOW_INTERRUPT=true
|
|
SPEECH_HISTORY_LIMIT=100
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 6. MOCK ROBOT (ROBOT_MODE=mock only)
|
|
# -----------------------------------------------------------------------------
|
|
MOCK_CONNECT_DELAY_MS=350
|
|
MOCK_NETWORK_LATENCY_MS=45
|
|
MOCK_PROCESSING_MS=180
|
|
MOCK_WORDS_PER_MINUTE=150
|
|
|
|
# Set to 0.2 to make 1 in 5 utterances fail, for testing error handling.
|
|
MOCK_FAILURE_RATE=0.0
|
|
# Set to true to make the simulated link drop occasionally, for testing reconnect.
|
|
MOCK_FLAKY_CONNECTION=false
|
|
# --- PC speaker playback (simulator only) ------------------------------------
|
|
# true = the simulator actually SPEAKS the text through this laptop's speakers,
|
|
# so you can rehearse a demo before the robot is on the network.
|
|
# When this is on, the real audio drives the UI: "Completed" appears exactly when
|
|
# the sound stops, and Stop cuts the voice mid-word.
|
|
#
|
|
# Windows uses the built-in SAPI voices - nothing to install.
|
|
# macOS uses `say`. Linux needs: sudo apt install espeak-ng
|
|
MOCK_LOCAL_AUDIO=true
|
|
|
|
# Which PC voice to use (matched against the voice name, case-insensitive).
|
|
# python scripts/voices.py list what is installed
|
|
# python scripts/voices.py --demo hear each one
|
|
#
|
|
# NOTE: this is the SIMULATOR's voice, not the robot's - the real A3 synthesises
|
|
# speech on-board. The robot's configured voice is "Yunxiao": a MALE TEENAGER,
|
|
# multi-language. Windows ships no teenage voice, so the closest approximation is
|
|
# its lighter adult male voice (Mark) pitched up a little. It is a stand-in, not
|
|
# a match. Run `python scripts/voices.py --demo` to hear the alternatives.
|
|
MOCK_VOICE=Mark
|
|
|
|
# Speaking rate, -10 (slowest) to 10 (fastest). Try -1 or -2 for a noisy room.
|
|
MOCK_SPEECH_RATE=0
|
|
|
|
# Volume, 0-100.
|
|
MOCK_SPEECH_VOLUME=100
|
|
|
|
# Pitch, -10 (deepest) to 10 (highest). Left at 0: raising it makes the voice
|
|
# sound affected rather than natural, which is the opposite of what a service
|
|
# robot should sound like.
|
|
MOCK_SPEECH_PITCH=0
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 7. GEMINI CLOUD VOICE (simulator only - nothing here touches the real robot)
|
|
# -----------------------------------------------------------------------------
|
|
# The built-in Windows voice is instant but robotic. Gemini gives the simulator a
|
|
# natural neural voice, at the cost of a network round trip.
|
|
#
|
|
# system = built-in OS voice - instant, robotic
|
|
# gemini = Gemini neural voice - natural, ~4s to synthesise new text
|
|
MOCK_VOICE_ENGINE=system
|
|
|
|
# Get a key at https://aistudio.google.com/apikey
|
|
GEMINI_API_KEY=
|
|
|
|
GEMINI_TTS_MODEL=gemini-3.1-flash-tts-preview
|
|
|
|
# Prebuilt voice. Iapetus ("Clear") is the default: professional and straight,
|
|
# which is how a tour-guide robot actually speaks. Charon ("Informative") is the
|
|
# same register but deeper and more adult - swap it in if you prefer that.
|
|
# Puck / Fenrir read younger but bouncier. Hear them all:
|
|
# python scripts/voices.py
|
|
GEMINI_VOICE=Iapetus
|
|
|
|
# Optional acting direction. LEAVE THIS EMPTY. Anything here makes the model
|
|
# *perform* the line instead of simply saying it, which sounds theatrical and
|
|
# fake for a service robot. Only set it for a deliberate stage character.
|
|
GEMINI_TTS_STYLE=
|
|
|
|
# 0 = never split. Every line is spoken as ONE clip, in one continuous take.
|
|
# Set a character count (e.g. 280) only if you want very long paragraphs to
|
|
# start speaking before the whole thing is synthesised - the pieces are then
|
|
# synthesised separately, and the join between them can be audible.
|
|
GEMINI_CHUNK_CHARS=0
|
|
|
|
# LATENCY: new text takes ~4s (short) to ~8s (paragraph) to synthesise. Audio is
|
|
# cached on disk in .voice-cache/, so a repeated line is INSTANT and stays
|
|
# instant across restarts. Before a live demo, warm your lines:
|
|
# python scripts/warm_voice.py --file demo_lines.txt
|
|
# If Gemini is unreachable the simulator falls back to the built-in voice, so a
|
|
# network problem never leaves you with silence.
|