- ROS2 node subscribing to orchestrator state, battery, balance, person tracker, voice commands, health - State-to-emotion mapping: navigation → excited, social → happy/curious, low battery → concerned, etc. - Smooth emotion transitions (0.3–1.2s) with confidence tracking - Idle behaviors: blink (~3s), look-around (~8s), breathing (sine wave) - Social memory: familiarity-based warmth modifier (0.3–1.0) for known people - Personality-aware responses: extroversion, playfulness, responsiveness, anxiety (0.0–1.0 configurable) - Publishes /saltybot/emotion_state (JSON): emotion, intensity, confidence, expression name, context, idle_flags - Configurable via emotion_engine.yaml: personality traits, battery thresholds, update rate - Launch file: emotion_engine.launch.py Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
SaltyBot Emotion Engine (Issue #429)
Context-aware facial expression and emotion selection system for SaltyBot.
Features
1. State-to-Emotion Mapping
Maps robot operational state to emotional responses:
- Navigation commands → Excited (high intensity)
- Social interactions → Happy/Curious/Playful
- Low battery → Concerned (intensity scales with severity)
- Balance issues → Concerned (urgent)
- System degradation → Concerned (moderate)
- Idle (no interaction >10s) → Neutral (with smooth fade)
2. Smooth Emotion Transitions
- Configurable transition durations (0.3–1.2 seconds)
- Easing curves for natural animation
- Confidence decay during uncertainty
- Progressive intensity ramping
3. Personality-Aware Responses
Configurable personality traits (0.0–1.0):
- Extroversion: Affects how eager to interact (playful vs. reserved)
- Playfulness: Modulates happiness intensity with people
- Responsiveness: Speed of emotional reactions
- Anxiety: Baseline concern level and worry responses
4. Social Memory & Familiarity
- Tracks interaction history per person
- Warmth modifier (0.3–1.0) based on relationship tier:
- Stranger: 0.5 (neutral warmth)
- Regular contact: 0.6–0.8 (warmer)
- Known favorite: 0.9–1.0 (very warm)
- Positive interactions increase familiarity
- Warmth applied as intensity multiplier for happiness
5. Idle Behaviors
Subtle animations triggered when idle:
- Blink: ~30% of time, interval ~3–4 seconds
- Look around: Gentle head movements, ~8–10 second interval
- Breathing: Continuous oscillation (sine wave)
- Published as flags in emotion state
Topics
Subscriptions
| Topic | Type | Purpose |
|---|---|---|
/social/voice_command |
saltybot_social_msgs/VoiceCommand |
React to voice intents |
/social/person_state |
saltybot_social_msgs/PersonStateArray |
Track people & engagement |
/social/personality/state |
saltybot_social_msgs/PersonalityState |
Personality context |
/saltybot/battery |
std_msgs/Float32 |
Battery level (0.0–1.0) |
/saltybot/balance_stable |
std_msgs/Bool |
Balance/traction status |
/saltybot/system_health |
std_msgs/String |
System health state |
Publications
| Topic | Type | Content |
|---|---|---|
/saltybot/emotion_state |
std_msgs/String (JSON) |
Current emotion + metadata |
Emotion State JSON Schema
{
"emotion": "happy|curious|excited|concerned|confused|tired|playful|neutral",
"intensity": 0.0–1.0,
"confidence": 0.0–1.0,
"expression": "happy_intense|happy|happy_subtle|...",
"context": "navigation_command|engaged_with_N_people|low_battery|...",
"triggered_by": "voice_command|person_tracking|battery_monitor|balance_monitor|idle_timer",
"social_target_id": "person_id or null",
"social_warmth": 0.0–1.0,
"idle_flags": {
"blink": true|false,
"look_around": true|false,
"breathing": true|false
},
"timestamp": unix_time,
"battery_level": 0.0–1.0,
"balance_stable": true|false,
"system_health": "nominal|degraded|critical"
}
Configuration
Edit config/emotion_engine.yaml:
personality:
extroversion: 0.6 # 0=introvert, 1=extrovert
playfulness: 0.5 # How playful with people
responsiveness: 0.8 # Reaction speed
anxiety: 0.3 # Baseline worry level
battery_warning_threshold: 0.25 # 25% triggers mild concern
battery_critical_threshold: 0.10 # 10% triggers high concern
update_rate_hz: 10.0 # Publishing frequency
Running
From launch file
ros2 launch saltybot_emotion_engine emotion_engine.launch.py
Direct node launch
ros2 run saltybot_emotion_engine emotion_engine
Integration with Face Expression System
The emotion engine publishes /saltybot/emotion_state which should be consumed by:
- Face expression controller (applies expressions based on emotion + intensity)
- Idle animation controller (applies blink, look-around, breathing)
- Voice response controller (modulates speech tone/style by emotion)
Emotion Logic Flow
Input: Voice command, person tracking, battery, etc.
↓
Classify event → determine target emotion
↓
Apply personality modifiers (intensity * personality traits)
↓
Initiate smooth transition (current emotion → target emotion)
↓
Apply social warmth modifier if person-directed
↓
Update idle flags
↓
Publish emotion state (JSON)
Example Usage
Subscribe and monitor emotion state:
ros2 topic echo /saltybot/emotion_state
Example output (when person talks):
{
"emotion": "excited",
"intensity": 0.85,
"confidence": 0.9,
"expression": "surprised_intense",
"context": "navigation_command",
"triggered_by": "voice_command",
"social_target_id": "person_42",
"social_warmth": 0.75,
"idle_flags": {"blink": false, "look_around": true, "breathing": true},
"timestamp": 1699564800.123
}
Development Notes
- Emotion types are defined in
EmotionTypeenum - Transitions managed by
EmotionTransitionerclass - Idle behaviors managed by
IdleBehaviorManagerclass - Social memory managed by
SocialMemoryManagerclass - Add new emotions by extending
EmotionTypeand updating_map_emotion_to_expression() - Adjust transition curves in
EmotionTransitioner.transition_curvesdict
Future Enhancements
- Machine learning model for context → emotion prediction
- Voice sentiment analysis to modulate emotion
- Facial expression feedback from /social/faces/expressions
- Multi-person emotional dynamics (ensemble emotion)
- Persistent social memory (database backend)
- Integration with LLM for contextual emotion explanation