from collections import deque import logging import os from behaviors.behavior import Behavior from behaviors.custom.keyframe.keyframe import KeyframeSkill logger = logging.getLogger() class GetUp(Behavior): STABILITY_THRESHOLD_CYCLES: int = 3 NEUTRAL_EXECUTION_TIME: float = 1.5 def __init__(self, agent): super().__init__(agent) self.get_up_front = KeyframeSkill( agent=agent, file=os.path.join(os.path.dirname(__file__), "get_up_front.yaml"), ) self.get_up_back = KeyframeSkill( agent=agent, file=os.path.join(os.path.dirname(__file__), "get_up_back.yaml"), ) def execute(self, reset, *args, **kwargs): robot = self.agent.robot if reset: self.neutral_start_time = None self.has_get_up = False self.gyro_queue = deque(maxlen=self.STABILITY_THRESHOLD_CYCLES) self.state = 0 self.chosen_get_up = None self.should_reset_get_up = True if not self.has_get_up: if not self.chosen_get_up and self.agent.skills_manager.execute_sub_skill("Neutral", True): self.gyro_queue.append(max(abs(robot.gyroscope))) if len(self.gyro_queue) == self.STABILITY_THRESHOLD_CYCLES and all(g < 2.5 for g in self.gyro_queue): if abs(robot.accelerometer[1]) < 2 and abs(robot.accelerometer[2]) < 3: if robot.accelerometer[0] < -8: self.chosen_get_up = self.get_up_front elif robot.accelerometer[0] > 8: self.chosen_get_up = self.get_up_back if self.chosen_get_up: self.has_get_up = self.chosen_get_up.execute(reset=self.should_reset_get_up) self.should_reset_get_up = False else: if not self.neutral_start_time: self.neutral_start_time = self.agent.world.server_time neutral_elapsed_time = ( self.agent.world.server_time - self.neutral_start_time ) if neutral_elapsed_time < self.NEUTRAL_EXECUTION_TIME: self.agent.skills_manager.execute_sub_skill( "Walk", reset=neutral_elapsed_time <= 1e-6, target_2d=(0, 0), is_target_absolute=False ) else: return True return False def is_ready(self, *args): return self.agent.world.is_fallen()