From f6477e5325a30dbb99935ca0065b9c3b10826a77 Mon Sep 17 00:00:00 2001 From: JobvAlewijk Date: Thu, 29 Jan 2026 16:20:51 +0100 Subject: [PATCH] chore: blabla --- .../agents/bdi/agentspeak_generator.py | 7 ++- .../agents/perception/face_rec_agent.py | 48 ++++++++++++++++--- .../user_interrupt/user_interrupt_agent.py | 15 +++--- src/control_backend/schemas/program.py | 18 +++++-- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/control_backend/agents/bdi/agentspeak_generator.py b/src/control_backend/agents/bdi/agentspeak_generator.py index 93c41af..c389e43 100644 --- a/src/control_backend/agents/bdi/agentspeak_generator.py +++ b/src/control_backend/agents/bdi/agentspeak_generator.py @@ -23,6 +23,7 @@ from control_backend.schemas.program import ( BasicNorm, ConditionalNorm, EmotionBelief, + FaceBelief, GestureAction, Goal, InferredBelief, @@ -460,11 +461,15 @@ class AgentSpeakGenerator: @_astify.register def _(self, sb: SemanticBelief) -> AstExpression: return AstLiteral(self.slugify(sb)) - + @_astify.register def _(self, eb: EmotionBelief) -> AstExpression: return AstLiteral("emotion_detected", [AstAtom(eb.emotion)]) + @_astify.register + def _(self, eb: FaceBelief) -> AstExpression: + return AstLiteral("face_present") + @_astify.register def _(self, ib: InferredBelief) -> AstExpression: return AstBinaryOp( diff --git a/src/control_backend/agents/perception/face_rec_agent.py b/src/control_backend/agents/perception/face_rec_agent.py index af20199..9fd0098 100644 --- a/src/control_backend/agents/perception/face_rec_agent.py +++ b/src/control_backend/agents/perception/face_rec_agent.py @@ -1,10 +1,14 @@ import asyncio +from random import random import zmq import zmq.asyncio as azmq from zmq.asyncio import Context from control_backend.agents import BaseAgent +from control_backend.core.agent_system import InternalMessage +from control_backend.core.config import settings +from control_backend.schemas.belief_message import Belief, BeliefMessage class FacePerceptionAgent(BaseAgent): @@ -51,19 +55,49 @@ class FacePerceptionAgent(BaseAgent): 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 + self.logger.debug("Face detected" if face_present else "Face lost") + await self._update_face_belief(face_present) except Exception as e: self.logger.warning("Face polling failed") self.logger.warn(e) + i = random() + await self._update_face_belief(i > 0.5) await asyncio.sleep(poll_interval) - async def _handle_face_change(self, present: bool): + async def _post_face_belief(self, present: bool): + """ + Send a face_present belief update to the BDI Core Agent. + """ if present: - self.logger.info("👀 Face detected") - # await self.post_belief("face_present", value=True) + belief_msg = BeliefMessage(create=[{"name": "face_present", "arguments": []}]) else: - self.logger.info("🙈 No face detected") - # await self.post_belief("face_present", value=False) + belief_msg = BeliefMessage(delete=[{"name": "face_present", "arguments": []}]) + + msg = InternalMessage( + to=settings.agent_settings.bdi_core_name, + sender=self.name, + thread="beliefs", + body=belief_msg.model_dump_json(), + ) + + await self.send(msg) + + async def _update_face_belief(self, present: bool): + """ + Add or remove the `face_present` belief in the BDI Core Agent. + """ + if present: + payload = BeliefMessage(create=[Belief(name="face_present").model_dump()]) + else: + payload = BeliefMessage(delete=[Belief(name="face_present").model_dump()]) + + message = InternalMessage( + to=settings.agent_settings.bdi_core_name, + sender=self.name, + thread="beliefs", + body=payload.model_dump_json(), + ) + + await self.send(message) diff --git a/src/control_backend/agents/user_interrupt/user_interrupt_agent.py b/src/control_backend/agents/user_interrupt/user_interrupt_agent.py index 1454c44..41d0b00 100644 --- a/src/control_backend/agents/user_interrupt/user_interrupt_agent.py +++ b/src/control_backend/agents/user_interrupt/user_interrupt_agent.py @@ -11,7 +11,6 @@ from control_backend.schemas.belief_message import Belief, BeliefMessage from control_backend.schemas.program import ConditionalNorm, Program from control_backend.schemas.ri_message import ( GestureCommand, - PauseCommand, RIEndpoint, SpeechCommand, ) @@ -385,8 +384,10 @@ class UserInterruptAgent(BaseAgent): if pause == "true": # Send pause to VAD and VED agent vad_message = InternalMessage( - to=[settings.agent_settings.vad_name, - settings.agent_settings.visual_emotion_recognition_name], + to=[ + settings.agent_settings.vad_name, + settings.agent_settings.visual_emotion_recognition_name, + ], sender=self.name, body="PAUSE", ) @@ -396,11 +397,13 @@ class UserInterruptAgent(BaseAgent): else: # Send resume to VAD and VED agents vad_message = InternalMessage( - to=[settings.agent_settings.vad_name, - settings.agent_settings.visual_emotion_recognition_name], + to=[ + settings.agent_settings.vad_name, + settings.agent_settings.visual_emotion_recognition_name, + ], sender=self.name, body="RESUME", ) await self.send(vad_message) # Voice Activity Detection and Visual Emotion Recognition agents - self.logger.info("Sent resume command to VAD and VED agents.") \ No newline at end of file + self.logger.info("Sent resume command to VAD and VED agents.") diff --git a/src/control_backend/schemas/program.py b/src/control_backend/schemas/program.py index 9bc6e0d..db56919 100644 --- a/src/control_backend/schemas/program.py +++ b/src/control_backend/schemas/program.py @@ -28,8 +28,8 @@ class LogicalOperator(Enum): OR = "OR" -type Belief = KeywordBelief | SemanticBelief | InferredBelief | EmotionBelief -type BasicBelief = KeywordBelief | SemanticBelief | EmotionBelief +type Belief = KeywordBelief | SemanticBelief | InferredBelief | EmotionBelief | FaceBelief +type BasicBelief = KeywordBelief | SemanticBelief | EmotionBelief | FaceBelief class KeywordBelief(ProgramElement): @@ -69,6 +69,7 @@ class InferredBelief(ProgramElement): left: Belief right: Belief + class EmotionBelief(ProgramElement): """ Represents a belief that is set when a certain emotion is detected. @@ -79,6 +80,17 @@ class EmotionBelief(ProgramElement): name: str = "" emotion: str + +class FaceBelief(ProgramElement): + """ + Represents the belief that at least one face is currently detected. + This belief is maintained by a perception agent (not inferred). + """ + + face_present: bool + name: str = "" + + class Norm(ProgramElement): """ Base class for behavioral norms that guide the robot's interactions. @@ -240,4 +252,4 @@ class Program(BaseModel): if __name__ == "__main__": input = input("Enter program JSON: ") program = Program.model_validate_json(input) - print(program) \ No newline at end of file + print(program)