feat: connected with RI properly
ref: N25B-397
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
from .face_rec_agent import FacePerceptionAgent as FacePerceptionAgent
|
||||||
from .transcription_agent.transcription_agent import (
|
from .transcription_agent.transcription_agent import (
|
||||||
TranscriptionAgent as TranscriptionAgent,
|
TranscriptionAgent as TranscriptionAgent,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,74 +1,55 @@
|
|||||||
import zmq
|
import asyncio
|
||||||
import zmq.asyncio as azmq
|
|
||||||
|
|
||||||
from control_backend.agents import BaseAgent
|
from control_backend.agents import BaseAgent
|
||||||
|
|
||||||
|
|
||||||
class FacePerceptionAgent(BaseAgent):
|
class FacePerceptionAgent(BaseAgent):
|
||||||
"""
|
"""
|
||||||
Receives and processes face detection / recognition events
|
Receives face presence updates from the RICommunicationAgent
|
||||||
coming from Pepper (via a NAOqi -> ZMQ bridge).
|
via the internal PUB/SUB bus.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
super().__init__(name)
|
super().__init__(name)
|
||||||
self._address = "tcp://127.0.0.1:5559"
|
self._last_face_state: bool | None = None
|
||||||
self._socket: azmq.Socket | None = None
|
|
||||||
|
|
||||||
async def setup(self):
|
async def setup(self):
|
||||||
self.logger.info("Starting FacePerceptionAgent")
|
self.logger.info("Starting FacePerceptionAgent")
|
||||||
|
self.add_behavior(self._poll_loop())
|
||||||
|
|
||||||
ctx = azmq.Context.instance()
|
async def _poll_loop(self):
|
||||||
self._socket = ctx.socket(zmq.SUB)
|
poll_interval = 1.0
|
||||||
self._socket.setsockopt_string(zmq.SUBSCRIBE, "")
|
|
||||||
|
|
||||||
self._socket.connect(self._address)
|
|
||||||
|
|
||||||
self.add_behavior(self._listen_loop())
|
|
||||||
|
|
||||||
async def _listen_loop(self):
|
|
||||||
while self._running:
|
while self._running:
|
||||||
try:
|
try:
|
||||||
msg = await self._socket.recv_json()
|
# Ask RICommunicationAgent (via main socket)
|
||||||
await self._process_face_data(msg)
|
await self._req_socket.send_json({"endpoint": "face", "data": {}})
|
||||||
except Exception:
|
|
||||||
self.logger.exception("Error receiving face data")
|
|
||||||
|
|
||||||
async def _process_face_data(self, data: dict):
|
response = await asyncio.wait_for(
|
||||||
"""
|
self._req_socket.recv_json(), timeout=poll_interval
|
||||||
Processes NAOqi FaceDetected-derived data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
faces = data.get("faces", [])
|
|
||||||
new_recognitions = data.get("new_recognitions", [])
|
|
||||||
|
|
||||||
if not faces:
|
|
||||||
self.logger.debug("No faces detected")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.logger.debug("Detected %d face(s)", len(faces))
|
|
||||||
|
|
||||||
for face in faces:
|
|
||||||
face_id = face.get("face_id")
|
|
||||||
alpha = face.get("alpha")
|
|
||||||
beta = face.get("beta")
|
|
||||||
# size_x = face.get("size_x")
|
|
||||||
# size_y = face.get("size_y")
|
|
||||||
|
|
||||||
recognized = face.get("recognized", False)
|
|
||||||
label = face.get("label")
|
|
||||||
score = face.get("score", 0.0)
|
|
||||||
|
|
||||||
if recognized:
|
|
||||||
self.logger.info("Recognized %s (score=%.2f, id=%s)", label, score, face_id)
|
|
||||||
else:
|
|
||||||
self.logger.debug(
|
|
||||||
"Unrecognized face id=%s at (α=%.2f, β=%.2f)", face_id, alpha, beta
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Temporal-filtered recognition (important!)
|
face_present = bool(response.get("data", False))
|
||||||
for name in new_recognitions:
|
|
||||||
self.logger.info("New person recognized: %s", name)
|
|
||||||
|
|
||||||
# 🔮 Example belief posting hook
|
if self._last_face_state is None:
|
||||||
# await self.post_belief("person_present", name=name)
|
self._last_face_state = face_present
|
||||||
|
continue
|
||||||
|
|
||||||
|
if face_present != self._last_face_state:
|
||||||
|
self._last_face_state = face_present
|
||||||
|
self.logger.info("👀 Face detected" if face_present else "🙈 Face lost")
|
||||||
|
# TODO: post belief to BDI here
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning("Face polling failed")
|
||||||
|
self.logger.warn(e)
|
||||||
|
|
||||||
|
await asyncio.sleep(poll_interval)
|
||||||
|
|
||||||
|
async def _handle_face_change(self, present: bool):
|
||||||
|
if present:
|
||||||
|
self.logger.info("👀 Face detected")
|
||||||
|
# await self.post_belief("face_present", value=True)
|
||||||
|
else:
|
||||||
|
self.logger.info("🙈 No face detected")
|
||||||
|
# await self.post_belief("face_present", value=False)
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class AgentSettings(BaseModel):
|
|||||||
robot_speech_name: str = "robot_speech_agent"
|
robot_speech_name: str = "robot_speech_agent"
|
||||||
robot_gesture_name: str = "robot_gesture_agent"
|
robot_gesture_name: str = "robot_gesture_agent"
|
||||||
user_interrupt_name: str = "user_interrupt_agent"
|
user_interrupt_name: str = "user_interrupt_agent"
|
||||||
|
face_agent_name: str = "face_detection_agent"
|
||||||
|
|
||||||
|
|
||||||
class BehaviourSettings(BaseModel):
|
class BehaviourSettings(BaseModel):
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ from control_backend.agents.communication import RICommunicationAgent
|
|||||||
# Emotional Agents
|
# Emotional Agents
|
||||||
# LLM Agents
|
# LLM Agents
|
||||||
from control_backend.agents.llm import LLMAgent
|
from control_backend.agents.llm import LLMAgent
|
||||||
|
from control_backend.agents.perception.face_rec_agent import FacePerceptionAgent
|
||||||
|
|
||||||
# User Interrupt Agent
|
# User Interrupt Agent
|
||||||
from control_backend.agents.user_interrupt.user_interrupt_agent import UserInterruptAgent
|
from control_backend.agents.user_interrupt.user_interrupt_agent import UserInterruptAgent
|
||||||
@@ -147,6 +148,12 @@ async def lifespan(app: FastAPI):
|
|||||||
"name": settings.agent_settings.user_interrupt_name,
|
"name": settings.agent_settings.user_interrupt_name,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
"FaceDetectionAgent": (
|
||||||
|
FacePerceptionAgent,
|
||||||
|
{
|
||||||
|
"name": settings.agent_settings.face_agent_name,
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
agents = []
|
agents = []
|
||||||
|
|||||||
Reference in New Issue
Block a user