Spaces:
Build error
Build error
| import logging | |
| from typing import Any, Dict, Tuple, Literal | |
| from reachy_mini.utils import create_head_pose | |
| from reachy_mini_conversation_app.tools.core_tools import Tool, ToolDependencies | |
| from reachy_mini_conversation_app.dance_emotion_moves import GotoQueueMove | |
| logger = logging.getLogger(__name__) | |
| Direction = Literal["left", "right", "up", "down", "front"] | |
| class MoveHead(Tool): | |
| """Move head in a given direction.""" | |
| name = "move_head" | |
| description = "Move your head in a given direction: left, right, up, down or front." | |
| parameters_schema = { | |
| "type": "object", | |
| "properties": { | |
| "direction": { | |
| "type": "string", | |
| "enum": ["left", "right", "up", "down", "front"], | |
| }, | |
| }, | |
| "required": ["direction"], | |
| } | |
| # mapping: direction -> args for create_head_pose | |
| DELTAS: Dict[str, Tuple[int, int, int, int, int, int]] = { | |
| "left": (0, 0, 0, 0, 0, 40), | |
| "right": (0, 0, 0, 0, 0, -40), | |
| "up": (0, 0, 0, 0, -30, 0), | |
| "down": (0, 0, 0, 0, 30, 0), | |
| "front": (0, 0, 0, 0, 0, 0), | |
| } | |
| async def __call__(self, deps: ToolDependencies, **kwargs: Any) -> Dict[str, Any]: | |
| """Move head in a given direction.""" | |
| direction_raw = kwargs.get("direction") | |
| if not isinstance(direction_raw, str): | |
| return {"error": "direction must be a string"} | |
| direction: Direction = direction_raw # type: ignore[assignment] | |
| logger.info("Tool call: move_head direction=%s", direction) | |
| deltas = self.DELTAS.get(direction, self.DELTAS["front"]) | |
| target = create_head_pose(*deltas, degrees=True) | |
| # Use new movement manager | |
| try: | |
| movement_manager = deps.movement_manager | |
| # Get current state for interpolation | |
| current_head_pose = deps.reachy_mini.get_current_head_pose() | |
| _, current_antennas = deps.reachy_mini.get_current_joint_positions() | |
| # Create goto move | |
| goto_move = GotoQueueMove( | |
| target_head_pose=target, | |
| start_head_pose=current_head_pose, | |
| target_antennas=(0, 0), # Reset antennas to default | |
| start_antennas=( | |
| current_antennas[0], | |
| current_antennas[1], | |
| ), # Skip body_yaw | |
| target_body_yaw=0, # Reset body yaw | |
| start_body_yaw=current_antennas[0], # body_yaw is first in joint positions | |
| duration=deps.motion_duration_s, | |
| ) | |
| movement_manager.queue_move(goto_move) | |
| movement_manager.set_moving_state(deps.motion_duration_s) | |
| return {"status": f"looking {direction}"} | |
| except Exception as e: | |
| logger.error("move_head failed") | |
| return {"error": f"move_head failed: {type(e).__name__}: {e}"} | |