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 deddbba..0bde563 100644 --- a/src/control_backend/agents/user_interrupt/user_interrupt_agent.py +++ b/src/control_backend/agents/user_interrupt/user_interrupt_agent.py @@ -26,7 +26,7 @@ class UserInterruptAgent(BaseAgent): - Send a prioritized message to the `RobotSpeechAgent` - Send a prioritized gesture to the `RobotGestureAgent` - - Send a belief override to the `BDIProgramManager`in order to activate a + - Send a belief override to the `BDI Core` in order to activate a trigger/conditional norm or complete a goal. Prioritized actions clear the current RI queue before inserting the new item, @@ -75,7 +75,9 @@ class UserInterruptAgent(BaseAgent): These are the different types and contexts: - type: "speech", context: string that the robot has to say. - type: "gesture", context: single gesture name that the robot has to perform. - - type: "override", context: belief_id that overrides the goal/trigger/conditional norm. + - type: "override", context: id that belongs to the goal/trigger/conditional norm. + - type: "override_unachieve", context: id that belongs to the conditional norm to unachieve. + - type: "next_phase", context: None, indicates to the BDI Core to - type: "pause", context: boolean indicating whether to pause - type: "reset_phase", context: None, indicates to the BDI Core to - type: "reset_experiment", context: None, indicates to the BDI Core to @@ -93,68 +95,82 @@ class UserInterruptAgent(BaseAgent): self.logger.debug("Received event type %s", event_type) - if event_type == "speech": - await self._send_to_speech_agent(event_context) - self.logger.info( - "Forwarded button press (speech) with context '%s' to RobotSpeechAgent.", - event_context, - ) - elif event_type == "gesture": - await self._send_to_gesture_agent(event_context) - self.logger.info( - "Forwarded button press (gesture) with context '%s' to RobotGestureAgent.", - event_context, - ) - elif event_type == "override": - ui_id = str(event_context) - if asl_trigger := self._trigger_map.get(ui_id): - await self._send_to_bdi("force_trigger", asl_trigger) + match event_type: + case "speech": + await self._send_to_speech_agent(event_context) self.logger.info( - "Forwarded button press (override) with context '%s' to BDI Core.", + "Forwarded button press (speech) with context '%s' to RobotSpeechAgent.", event_context, ) - elif asl_cond_norm := self._cond_norm_map.get(ui_id): - await self._send_to_bdi("force_norm", asl_cond_norm) + case "gesture": + await self._send_to_gesture_agent(event_context) self.logger.info( - "Forwarded button press (override) with context '%s' to BDIProgramManager.", + "Forwarded button press (gesture) with context '%s' to RobotGestureAgent.", event_context, ) - elif asl_goal := self._goal_map.get(ui_id): - await self._send_to_bdi_belief(asl_goal) - self.logger.info( - "Forwarded button press (override) with context '%s' to BDI Core.", + case "override": + ui_id = str(event_context) + if asl_trigger := self._trigger_map.get(ui_id): + await self._send_to_bdi("force_trigger", asl_trigger) + self.logger.info( + "Forwarded button press (override) with context '%s' to BDI Core.", + event_context, + ) + elif asl_cond_norm := self._cond_norm_map.get(ui_id): + await self._send_to_bdi_belief(asl_cond_norm) + self.logger.info( + "Forwarded button press (override) with context '%s' to BDI Core.", + event_context, + ) + elif asl_goal := self._goal_map.get(ui_id): + await self._send_to_bdi_belief(asl_goal) + self.logger.info( + "Forwarded button press (override) with context '%s' to BDI Core.", + event_context, + ) + # Send achieve_goal to program manager to update semantic belief extractor + goal_achieve_msg = InternalMessage( + to=settings.agent_settings.bdi_program_manager_name, + thread="achieve_goal", + body=ui_id, + ) + + await self.send(goal_achieve_msg) + else: + self.logger.warning("Could not determine which element to override.") + case "override_unachieve": + ui_id = str(event_context) + if asl_cond_norm := self._cond_norm_map.get(ui_id): + await self._send_to_bdi_belief(asl_cond_norm, True) + self.logger.info( + "Forwarded button press (override_unachieve)" + "with context '%s' to BDI Core.", + event_context, + ) + else: + self.logger.warning( + "Could not determine which conditional norm to unachieve." + ) + + case "pause": + self.logger.debug( + "Received pause/resume button press with context '%s'.", event_context + ) + await self._send_pause_command(event_context) + if event_context: + self.logger.info("Sent pause command.") + else: + self.logger.info("Sent resume command.") + + case "next_phase" | "reset_phase" | "reset_experiment": + await self._send_experiment_control_to_bdi_core(event_type) + case _: + self.logger.warning( + "Received button press with unknown type '%s' (context: '%s').", + event_type, event_context, ) - goal_achieve_msg = InternalMessage( - to=settings.agent_settings.bdi_program_manager_name, - thread="achieve_goal", - body=ui_id, - ) - - await self.send(goal_achieve_msg) - else: - self.logger.warning("Could not determine which element to override.") - - elif event_type == "pause": - self.logger.debug( - "Received pause/resume button press with context '%s'.", event_context - ) - await self._send_pause_command(event_context) - if event_context: - self.logger.info("Sent pause command.") - else: - self.logger.info("Sent resume command.") - - elif event_type in ["next_phase", "reset_phase", "reset_experiment"]: - await self._send_experiment_control_to_bdi_core(event_type) - else: - self.logger.warning( - "Received button press with unknown type '%s' (context: '%s').", - event_type, - event_context, - ) - async def handle_message(self, msg: InternalMessage): """ Handle commands received from other internal Python agents. @@ -195,9 +211,10 @@ class UserInterruptAgent(BaseAgent): await self._send_experiment_update(payload) self.logger.info(f"UI Update: Goal {goal_name} started (ID: {ui_id})") case "active_norms_update": - norm_list = [s.strip("() '\",") for s in msg.body.split(",") if s.strip("() '\",")] - - await self._broadcast_cond_norms(norm_list) + active_norms_asl = [ + s.strip("() '\",") for s in msg.body.split(",") if s.strip("() '\",") + ] + await self._broadcast_cond_norms(active_norms_asl) case _: self.logger.debug(f"Received internal message on unhandled thread: {msg.thread}") @@ -308,12 +325,15 @@ class UserInterruptAgent(BaseAgent): await self.send(msg) self.logger.info(f"Directly forced {thread} in BDI: {body}") - async def _send_to_bdi_belief(self, asl_goal: str): + async def _send_to_bdi_belief(self, asl_goal: str, unachieve: bool = False): """Send belief to BDI Core""" belief_name = f"achieved_{asl_goal}" belief = Belief(name=belief_name, arguments=None) self.logger.debug(f"Sending belief to BDI Core: {belief_name}") - belief_message = BeliefMessage(create=[belief]) + # Conditional norms are unachieved by removing the belief + belief_message = ( + BeliefMessage(delete=[belief]) if unachieve else BeliefMessage(create=[belief]) + ) msg = InternalMessage( to=settings.agent_settings.bdi_core_name, thread="beliefs",