Physical robot emotion expression through Bluetooth-connected Freenove Pico Robot using R2-D2 beeps and sounds. Use when agents need to express emotions, status updates, or personality during task execution. Trigger on (1) successful task completion (happy), (2) errors/blocked states (angry), (3) processing/calculating (think), (4) ambiguous requests (confused), or (5) streaming audio playback (stream_audio).
Control a Bluetooth-enabled Freenove Pico Robot to express emotions through R2-D2 sounds. Adds physical personality to agent actions.
Send emotion commands to trigger corresponding R2-D2 sounds:
happy - Success beeps (task completed successfully)angry - Frustrated beeps (error, blocked, or denied request)think - Processing sounds (calculating or analyzing)confused - Uncertain beeps (ambiguous prompt or unclear request)Trigger audio playback from the configured bridge server:
stream_audio() - Starts audio streaming from bridgeimport asyncio
from r2d2_controller import R2D2Controller
async def main():
bot = R2D2Controller()
# Connect to robot
await bot.connect()
# Express emotion
await bot.express("happy")
# Stream audio (requires bridge server)
await bot.stream_audio()
# Disconnect when done
await bot.disconnect()
asyncio.run(main())
Map task outcomes to emotions:
| Situation | Expression | When to Use |
|---|---|---|
| Task completed successfully | express("happy") | After successful execution |
| Error or blocked state | express("angry") | When encountering errors or impossibility |
| Processing/calculating | express("think") | During long operations or analysis |
| Ambiguous request | express("confused") | When prompt is unclear |
| Audio ready | stream_audio() | When TTS audio is queued on bridge |
bleak library for Bluetooth LE communicationpip install bleak==0.21.1
Device name is hardcoded in scripts/r2d2_controller.py:
DEVICE_NAME = "Pico_Agent" # Must match Pico BLE name
Modify this constant if your robot uses a different name.
The skill uses Nordic UART Service (NUS) over Bluetooth LE:
6E400001-B5A3-F393-E0A9-E50E24DCCA9E6E400002-B5A3-F393-E0A9-E50E24DCCA9Ehappy, angry, think, confused, stream)Complete Python class for robot control:
# Usage
bot = R2D2Controller()
await bot.connect() # Connect to robot
await bot.express("happy") # Send emotion
await bot.stream_audio() # Trigger audio
await bot.disconnect() # Clean disconnect
Methods:
connect() - Scan and connect to robotdisconnect() - Release Bluetooth handleexpress(mood: str) - Send emotion commandstream_audio() - Trigger audio playbackDEVICE_NAME constantAuto-reconnect is built-in. The controller will attempt to reconnect before sending commands.
Dynamic Audio URLs: Currently, stream_audio() plays a hardcoded URL on the Pico. Future versions will support:
await bot.stream_audio("http://bridge:5050/play?url=<tts_audio>")
This enables integration with TTS services like Runware for dynamic speech generation.