A ROS2-based cognitive robotic assistant running on the Pepper humanoid robot that manages personal To-Do Lists through natural spoken language. The system integrates face-based user identification, LLM-powered dialog management (Mistral via Azure AI), automatic speech recognition (Whisper), and a real-time web dashboard on Pepper's tablet.
📄 Developed as a university project at Università degli Studi di Salerno — DIEM (Cognitive Robotics course), Group 02.
P.E.P.Pe turns the Pepper robot into a personal task-management assistant. The user interacts entirely through natural spoken Italian, and the system:
| Constraint | Value |
|---|---|
| Max interaction distance | 3 metres |
| Acoustic environment | No significant background noise |
| Concurrent users | One at a time (one-to-one interaction) |

| Node | Full Name | Role |
|---|---|---|
| PINo | People Identification Node | Face detection (MTCNN) + embedding extraction (InceptionResNetV1/VGGFace2) |
| RINo | ReSpeaker Interface Node | Microphone array management, VAD, speech prefetch, sends audio to ASR |
| LINo | LLM Interaction Node | Central orchestrator: user identification, NLU via LLM, tool calling, DB management |
| GINo | Graphic Interface Node | Async web server (aiohttp, port 8000), MJPEG stream + WebSocket push to tablet |
| TTS Node | text2speech_node | Wraps Pepper's ALTextToSpeech; manages ego-speech suppression |
| ASR Node | asr_whisper | Whisper large-v3-turbo via Hugging Face Transformers |
| Topic | Publisher | Subscriber | Message Type | Description |
|---|---|---|---|---|
/scene_embedding | PINo | LINo | Float32MultiArray | Face embedding of the closest detected user |
/scene_view | PINo | GINo | Image | Camera frame with bounding box overlay |
/speech_text | RINo (via ASR) | LINo | String | Transcribed user speech |
/ui_data | LINo | GINo | String (JSON) | Current user name + task list for tablet display |
| Service | Server | Caller | Description |
|---|---|---|---|
asr | asr_whisper | RINo | Transcribe an audio buffer → text |
tts | text2speech_node | LINo | Speak a text string on Pepper |
mic_active | RINo | LINo | Enable/disable microphone (ego-speech suppression) |
load_url | tablet_node (proprietary) | GINo | Force Pepper's tablet browser to open a URL |
P.E.P.Pe-Personal_Enhanced_Planner_with_PEpper/
│
└── project_ws/ # ROS2 workspace
└── src/
│
├── PEPPe/ # Main application package
│ ├── PEPPe/
│ │ ├── LINo.py # LLM Interaction Node (orchestrator)
│ │ ├── GINo.py # Graphic Interface Node (tablet web server)
│ │ ├── PINo.py # People Identification Node (face ID)
│ │ ├── fake_od.py # Stub: fake object detection (simulation)
│ │ ├── fake_stt.py # Stub: fake speech-to-text (simulation)
│ │ ├── fake_tts.py # Stub: fake text-to-speech (simulation)
│ │ ├── requirements.txt # Python dependencies for this package
│ │ └── users_list/ # User database (JSON persistence)
│ ├── launch/ # ROS2 launch files
│ ├── setup.py
│ ├── setup.cfg
│ └── package.xml
│
├── pepper_nodes/ # Pepper hardware interface package
│ ├── pepper_nodes/ # ReSpeaker (RINo), ASR, TTS nodes
│ ├── conf/ # ROS2 parameter YAML files
│ ├── launch/ # Launch files for hardware nodes
│ ├── setup.py
│ └── package.xml
│
├── pepper_interfaces/ # Custom ROS2 message/service definitions
│
└── audio_common/ # Audio utilities / common audio ROS2 package
fake_*.py)| Library | Purpose |
|---|---|
azure-ai-inference | Mistral LLM API (Tool Calling) |
facenet-pytorch | MTCNN face detection + InceptionResNetV1 embeddings |
transformers | Whisper ASR (large-v3-turbo via Hugging Face) |
aiohttp | Async web server for GINo tablet dashboard |
torch | Deep learning backend (PINo + ASR) |
opencv-python | Frame capture and preprocessing |
See project_ws/src/PEPPe/PEPPe/requirements.txt for the full pinned list.
# 1. Clone the repository
git clone https://github.com/antocarbone/P.E.P.Pe-Personal_Enhanced_Planner_with_PEpper.git
cd P.E.P.Pe-Personal_Enhanced_Planner_with_PEpper
# 2. Source your ROS2 installation
source /opt/ros/humble/setup.bash
# 3. Install Python dependencies
pip install -r project_ws/src/PEPPe/PEPPe/requirements.txt
# 4. Build the ROS2 workspace
cd project_ws
colcon build --symlink-install
# 5. Source the workspace overlay
source install/setup.bash
Before launching, set the following environment variables or edit the relevant YAML parameter files in project_ws/src/pepper_nodes/conf/:
# Azure AI credentials for the LLM
export AZURE_INFERENCE_ENDPOINT="https://<your-endpoint>.inference.ai.azure.com"
export AZURE_INFERENCE_KEY="<your-api-key>"
# Pepper robot IP (if running on real hardware)
export PEPPER_IP="<robot-ip>"
| Parameter | Default | Description |
|---|---|---|
speech_continuation | 1.5 s | Silence duration after which speech recording ends |
speech_prefetch | 2.0 s | Pre-speech audio buffer to avoid clipping sentence starts |
detection_timeout | 3.0 s | Time to keep last valid face embedding if detection fails |
pending_time | 2.0 s | Seconds of continuous new-face detection before switching user context |
embedding_threshold | 0.9 | Euclidean distance threshold for face re-identification |
# Terminal 1 — Hardware nodes (ReSpeaker, ASR, TTS, camera)
ros2 launch pepper_nodes pepper_hardware.launch.py pepper_ip:=<ROBOT_IP>
# Terminal 2 — Main application nodes (LINo, GINo, PINo)
ros2 launch PEPPe peppers_application.launch.py
Once running, Pepper's tablet will automatically open http://<ROBOT_IP>:8000 showing the live dashboard.
The fake_*.py stubs allow full end-to-end testing without a physical Pepper robot:
# Use fake STT (type text instead of speaking)
ros2 run PEPPe fake_stt
# Use fake TTS (prints to console instead of speaking)
ros2 run PEPPe fake_tts
# Use fake object detection (publishes a dummy embedding)
ros2 run PEPPe fake_od
# Then launch the core logic nodes normally
ros2 launch PEPPe peppers_application.launch.py
The cognitive core is LINo, which uses Mistral-medium via Azure AI Inference with the Tool Calling paradigm.
| Tool | Description |
|---|---|
add(elem, date, time) | Add a task to the current user's list |
remove(elem) | Remove a task from the current user's list |
read_list() | Read all tasks in the current user's list |
register_user(nome) | Associate a name with the new face embedding |
Every user message is enriched with metadata before being sent to the LLM:
timestamp: YYYY-MM-DD HH:MM:SS | nome: <USERNAME> | <USER_MESSAGE>
This allows the model to resolve relative time expressions (e.g., "domani alle sedici e mezza" → date: 2026-01-30, time: 16:30) without maintaining internal state.
To prevent the robot from transcribing its own voice in an infinite loop:
mic_active(False) → RINo disables VAD and flushes audio buffersmic_active(True) → listening resumesUser data is stored in users_list/users_db.json. Each record contains:
{
"id": 1,
"nome": "Franco",
"embedding": [0.23, -0.11, ...],
"todo_list": {
"fare la spesa": "2026-01-28T21:00:00",
"andare dal commercialista": "2026-01-30T16:30:00"
}
}
/scene_embeddingembedding_threshold → user recognised, context restoredregister_userPENDING_TIME seconds before a context switch triggers, preventing flicker from brief misdetectionsThe system was validated with 9 black-box test cases — all passed:
| # | Test Case | Outcome |
|---|---|---|
| TC1 | New user registration via face + name | ✅ PASSED |
| TC2 | Re-identification and context reload | ✅ PASSED |
| TC3 | NLU: extract task + relative date/time from free speech | ✅ PASSED |
| TC4 | Task removal with anaphora resolution ("toglila") | ✅ PASSED |
| TC5 | Task modification (remove + re-add with updated time) | ✅ PASSED |
| TC6 | Robustness: duplicate task insertion + non-existent removal | ✅ PASSED |
| TC7 | Robustness: occupied time slot detection | ✅ PASSED |
| TC8 | Robustness: past date rejection | ✅ PASSED |
| TC9 | Relative time reasoning ("settimana prossima") | ✅ PASSED |
Python
98.3%
CMake
1.7%
A ROS2-based cognitive robotic assistant running on the Pepper humanoid robot that manages personal To-Do Lists through natural spoken language. The system integrates face-based user identification, LLM-powered dialog management (Mistral via Azure AI), automatic speech recognition (Whisper), and a real-time web dashboard on Pepper's tablet.
📄 Developed as a university project at Università degli Studi di Salerno — DIEM (Cognitive Robotics course), Group 02.
P.E.P.Pe turns the Pepper robot into a personal task-management assistant. The user interacts entirely through natural spoken Italian, and the system:
| Constraint | Value |
|---|---|
| Max interaction distance | 3 metres |
| Acoustic environment | No significant background noise |
| Concurrent users | One at a time (one-to-one interaction) |

| Node | Full Name | Role |
|---|---|---|
| PINo | People Identification Node | Face detection (MTCNN) + embedding extraction (InceptionResNetV1/VGGFace2) |
| RINo | ReSpeaker Interface Node | Microphone array management, VAD, speech prefetch, sends audio to ASR |
| LINo | LLM Interaction Node | Central orchestrator: user identification, NLU via LLM, tool calling, DB management |
| GINo | Graphic Interface Node | Async web server (aiohttp, port 8000), MJPEG stream + WebSocket push to tablet |
| TTS Node | text2speech_node | Wraps Pepper's ALTextToSpeech; manages ego-speech suppression |
| ASR Node | asr_whisper | Whisper large-v3-turbo via Hugging Face Transformers |
| Topic | Publisher | Subscriber | Message Type | Description |
|---|---|---|---|---|
/scene_embedding | PINo | LINo | Float32MultiArray | Face embedding of the closest detected user |
/scene_view | PINo | GINo | Image | Camera frame with bounding box overlay |
/speech_text | RINo (via ASR) | LINo | String | Transcribed user speech |
/ui_data | LINo | GINo | String (JSON) | Current user name + task list for tablet display |
| Service | Server | Caller | Description |
|---|---|---|---|
asr | asr_whisper | RINo | Transcribe an audio buffer → text |
tts | text2speech_node | LINo | Speak a text string on Pepper |
mic_active | RINo | LINo | Enable/disable microphone (ego-speech suppression) |
load_url | tablet_node (proprietary) | GINo | Force Pepper's tablet browser to open a URL |
P.E.P.Pe-Personal_Enhanced_Planner_with_PEpper/
│
└── project_ws/ # ROS2 workspace
└── src/
│
├── PEPPe/ # Main application package
│ ├── PEPPe/
│ │ ├── LINo.py # LLM Interaction Node (orchestrator)
│ │ ├── GINo.py # Graphic Interface Node (tablet web server)
│ │ ├── PINo.py # People Identification Node (face ID)
│ │ ├── fake_od.py # Stub: fake object detection (simulation)
│ │ ├── fake_stt.py # Stub: fake speech-to-text (simulation)
│ │ ├── fake_tts.py # Stub: fake text-to-speech (simulation)
│ │ ├── requirements.txt # Python dependencies for this package
│ │ └── users_list/ # User database (JSON persistence)
│ ├── launch/ # ROS2 launch files
│ ├── setup.py
│ ├── setup.cfg
│ └── package.xml
│
├── pepper_nodes/ # Pepper hardware interface package
│ ├── pepper_nodes/ # ReSpeaker (RINo), ASR, TTS nodes
│ ├── conf/ # ROS2 parameter YAML files
│ ├── launch/ # Launch files for hardware nodes
│ ├── setup.py
│ └── package.xml
│
├── pepper_interfaces/ # Custom ROS2 message/service definitions
│
└── audio_common/ # Audio utilities / common audio ROS2 package
fake_*.py)| Library | Purpose |
|---|---|
azure-ai-inference | Mistral LLM API (Tool Calling) |
facenet-pytorch | MTCNN face detection + InceptionResNetV1 embeddings |
transformers | Whisper ASR (large-v3-turbo via Hugging Face) |
aiohttp | Async web server for GINo tablet dashboard |
torch | Deep learning backend (PINo + ASR) |
opencv-python | Frame capture and preprocessing |
See project_ws/src/PEPPe/PEPPe/requirements.txt for the full pinned list.
# 1. Clone the repository
git clone https://github.com/antocarbone/P.E.P.Pe-Personal_Enhanced_Planner_with_PEpper.git
cd P.E.P.Pe-Personal_Enhanced_Planner_with_PEpper
# 2. Source your ROS2 installation
source /opt/ros/humble/setup.bash
# 3. Install Python dependencies
pip install -r project_ws/src/PEPPe/PEPPe/requirements.txt
# 4. Build the ROS2 workspace
cd project_ws
colcon build --symlink-install
# 5. Source the workspace overlay
source install/setup.bash
Before launching, set the following environment variables or edit the relevant YAML parameter files in project_ws/src/pepper_nodes/conf/:
# Azure AI credentials for the LLM
export AZURE_INFERENCE_ENDPOINT="https://<your-endpoint>.inference.ai.azure.com"
export AZURE_INFERENCE_KEY="<your-api-key>"
# Pepper robot IP (if running on real hardware)
export PEPPER_IP="<robot-ip>"
| Parameter | Default | Description |
|---|---|---|
speech_continuation | 1.5 s | Silence duration after which speech recording ends |
speech_prefetch | 2.0 s | Pre-speech audio buffer to avoid clipping sentence starts |
detection_timeout | 3.0 s | Time to keep last valid face embedding if detection fails |
pending_time | 2.0 s | Seconds of continuous new-face detection before switching user context |
embedding_threshold | 0.9 | Euclidean distance threshold for face re-identification |
# Terminal 1 — Hardware nodes (ReSpeaker, ASR, TTS, camera)
ros2 launch pepper_nodes pepper_hardware.launch.py pepper_ip:=<ROBOT_IP>
# Terminal 2 — Main application nodes (LINo, GINo, PINo)
ros2 launch PEPPe peppers_application.launch.py
Once running, Pepper's tablet will automatically open http://<ROBOT_IP>:8000 showing the live dashboard.
The fake_*.py stubs allow full end-to-end testing without a physical Pepper robot:
# Use fake STT (type text instead of speaking)
ros2 run PEPPe fake_stt
# Use fake TTS (prints to console instead of speaking)
ros2 run PEPPe fake_tts
# Use fake object detection (publishes a dummy embedding)
ros2 run PEPPe fake_od
# Then launch the core logic nodes normally
ros2 launch PEPPe peppers_application.launch.py
The cognitive core is LINo, which uses Mistral-medium via Azure AI Inference with the Tool Calling paradigm.
| Tool | Description |
|---|---|
add(elem, date, time) | Add a task to the current user's list |
remove(elem) | Remove a task from the current user's list |
read_list() | Read all tasks in the current user's list |
register_user(nome) | Associate a name with the new face embedding |
Every user message is enriched with metadata before being sent to the LLM:
timestamp: YYYY-MM-DD HH:MM:SS | nome: <USERNAME> | <USER_MESSAGE>
This allows the model to resolve relative time expressions (e.g., "domani alle sedici e mezza" → date: 2026-01-30, time: 16:30) without maintaining internal state.
To prevent the robot from transcribing its own voice in an infinite loop:
mic_active(False) → RINo disables VAD and flushes audio buffersmic_active(True) → listening resumesUser data is stored in users_list/users_db.json. Each record contains:
{
"id": 1,
"nome": "Franco",
"embedding": [0.23, -0.11, ...],
"todo_list": {
"fare la spesa": "2026-01-28T21:00:00",
"andare dal commercialista": "2026-01-30T16:30:00"
}
}
/scene_embeddingembedding_threshold → user recognised, context restoredregister_userPENDING_TIME seconds before a context switch triggers, preventing flicker from brief misdetectionsThe system was validated with 9 black-box test cases — all passed:
| # | Test Case | Outcome |
|---|---|---|
| TC1 | New user registration via face + name | ✅ PASSED |
| TC2 | Re-identification and context reload | ✅ PASSED |
| TC3 | NLU: extract task + relative date/time from free speech | ✅ PASSED |
| TC4 | Task removal with anaphora resolution ("toglila") | ✅ PASSED |
| TC5 | Task modification (remove + re-add with updated time) | ✅ PASSED |
| TC6 | Robustness: duplicate task insertion + non-existent removal | ✅ PASSED |
| TC7 | Robustness: occupied time slot detection | ✅ PASSED |
| TC8 | Robustness: past date rejection | ✅ PASSED |
| TC9 | Relative time reasoning ("settimana prossima") | ✅ PASSED |
Python
98.3%
CMake
1.7%