This commit is contained in:
2026-03-10 09:35:27 -04:00
commit e31f827726
46 changed files with 2615 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
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()

View File

@@ -0,0 +1,94 @@
symmetry: true
kp: 75
kd: 1
keyframes:
- delta: 1
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: -114.592
Shoulder_Roll: -71.619
Elbow_Pitch: -85.944
Elbow_Yaw: -171.887
Waist: 0.000
Hip_Pitch: -45.836
Hip_Roll: 179.908
Hip_Yaw: 179.908
Knee_Pitch: -179.908
Ankle_Pitch: 89.954
Ankle_Roll: 89.954
kp: 250
kd: 1
p_gains:
Hip_Pitch: 20
Hip_Roll: 20
Hip_Yaw: 20
Knee_Pitch: 20
d_gains:
Hip_Pitch: 1
Hip_Roll: 1
Hip_Yaw: 1
Knee_Pitch: 1
- delta: 0.8125
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: -114.592
Shoulder_Roll: -89.954
Elbow_Pitch: -85.944
Elbow_Yaw: 0.000
Waist: 0.000
Hip_Pitch: -45.836
Hip_Roll: 179.908
Hip_Yaw: 179.908
Knee_Pitch: -179.908
Ankle_Pitch: 63.026
Ankle_Roll: 45.836
p_gains:
Hip_Pitch: 25
Hip_Roll: 25
Hip_Yaw: 25
Knee_Pitch: 25
- delta: 0.6
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: 89.954
Shoulder_Roll: -89.954
Elbow_Pitch: 0.000
Elbow_Yaw: 0.000
Waist: 0.000
Hip_Pitch: 20.054
Hip_Roll: 11.459
Hip_Yaw: 0.000
Knee_Pitch: -42.971
Ankle_Pitch: 57.296
Ankle_Roll: 0.000
kp: 40
kd: 4
p_gains:
Ankle_Pitch: 100
Ankle_Roll: 100
- delta: 0.25
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: 0.000
Shoulder_Roll: -77.363
Elbow_Pitch: -85.944
Elbow_Yaw: 0.000
Waist: 0.000
Hip_Pitch: 20.054
Hip_Roll: 7.162
Hip_Yaw: 0.000
Knee_Pitch: -42.971
Ankle_Pitch: 0.000
Ankle_Roll: 0.000
kp: 200
kd: 3.5

View File

@@ -0,0 +1,91 @@
symmetry: true
kp: 75
kd: 1
keyframes:
- delta: 0.1
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: -89.954
Shoulder_Roll: -71.619
Elbow_Pitch: 0.000
Elbow_Yaw: -114.592
Waist: 0.000
Hip_Pitch: 0.000
Hip_Roll: 14.324
Hip_Yaw: 0.000
Knee_Pitch: 0.000
Ankle_Pitch: 0.000
Ankle_Roll: 0.000
- delta: 0.5
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: 57.296
Shoulder_Roll: -71.619
Elbow_Pitch: -85.944
Elbow_Yaw: -171.887
Waist: 0.000
Hip_Pitch: 0.000
Hip_Roll: 14.324
Hip_Yaw: 0.000
Knee_Pitch: -28.648
Ankle_Pitch: 0.000
Ankle_Roll: 0.000
- delta: 0.8125
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: 89.954
Shoulder_Roll: -89.954
Elbow_Pitch: -85.944
Elbow_Yaw: 0.000
Waist: 0.000
Hip_Pitch: 200.536
Hip_Roll: 143.239
Hip_Yaw: 114.592
Knee_Pitch: -171.887
Ankle_Pitch: 89.954
Ankle_Roll: 24.919
- delta: 0.45
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: 89.954
Shoulder_Roll: -89.954
Elbow_Pitch: -85.944
Elbow_Yaw: 0.000
Waist: 0.000
Hip_Pitch: 20.054
Hip_Roll: 11.459
Hip_Yaw: 0.000
Knee_Pitch: -42.972
Ankle_Pitch: 0.000
Ankle_Roll: 0.000
kp: 50
kd: 2
p_gains:
Ankle_Pitch: 50
Ankle_Roll: 50
- delta: 0.13
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: 0.000
Shoulder_Roll: -77.363
Elbow_Pitch: -85.944
Elbow_Yaw: 0.000
Waist: 0.000
Hip_Pitch: 20.054
Hip_Roll: 7.162
Hip_Yaw: 0.000
Knee_Pitch: -42.972
Ankle_Pitch: 0.000
Ankle_Roll: 0.000
kp: 200
kd: 1.95

View File

@@ -0,0 +1,89 @@
from behaviors.behavior import Behavior
import yaml
class KeyframeSkill(Behavior):
def __init__(self, agent, file: str):
super().__init__(agent)
self.keyframe_step: int = 0
self.keyframe_start_time: float = None
with open(f"{file}", "r") as f:
self.skill_description = yaml.safe_load(f)
self.has_symmetry: bool = self.skill_description["symmetry"]
self.keyframes: list = self.skill_description["keyframes"]
self.kp: float = self.skill_description["kp"]
self.kd: float = self.skill_description["kd"]
def execute(self, reset, *args, **kwargs):
if reset:
self.keyframe_step = 0
self.keyframe_start_time = self.agent.world.server_time
current_keyframe = self.keyframes[self.keyframe_step]
raw_motor_positions = current_keyframe["motor_positions"]
current_keyframe_kp = current_keyframe.get("kp", self.kp)
current_keyframe_kd = current_keyframe.get("kd", self.kd)
p_gains = current_keyframe.get("p_gains", None)
d_gains = current_keyframe.get("d_gains", None)
for readable_motor_name, position in raw_motor_positions.items():
p_gain = (
p_gains.get(readable_motor_name, current_keyframe_kp)
if p_gains
else current_keyframe_kp
)
d_gain = (
d_gains.get(readable_motor_name, current_keyframe_kd)
if d_gains
else current_keyframe_kd
)
if self.has_symmetry:
motor_names, is_inverse_direction = self.agent.robot.MOTOR_SYMMETRY[
readable_motor_name
]
for motor_name in motor_names:
server_motor_name = self.agent.robot.MOTOR_FROM_READABLE_TO_SERVER[
motor_name
]
self.agent.robot.set_motor_target_position(
motor_name=server_motor_name,
target_position=position if is_inverse_direction else -position,
kp=p_gain,
kd=d_gain,
)
if is_inverse_direction:
is_inverse_direction = False # Only inverts one joint
else:
server_motor_name = self.agent.robot.MOTOR_FROM_READABLE_TO_SERVER[
readable_motor_name
]
self.agent.robot.set_motor_target_position(
motor_name=server_motor_name,
target_position=position,
kp=self.kp,
kd=self.kd,
)
keyframe_time: float = current_keyframe["delta"]
elapsed_keyframe_time = self.agent.world.server_time - self.keyframe_start_time
if elapsed_keyframe_time >= keyframe_time:
self.keyframe_start_time = self.agent.world.server_time
self.keyframe_step += 1
if self.keyframe_step >= len(self.keyframes):
return True
return False
def is_ready(self, *args):
return True

View File

@@ -0,0 +1,7 @@
import os
from behaviors.custom.keyframe.keyframe import KeyframeSkill
class Neutral(KeyframeSkill):
def __init__(self, agent):
super().__init__(agent, os.path.join(os.path.dirname(__file__), "neutral.yaml"))

View File

@@ -0,0 +1,19 @@
symmetry: true
kp: 150
kd: 1
keyframes:
- delta: 0.0
motor_positions:
Head_yaw: 0.000
Head_pitch: 0.000
Shoulder_Pitch: 0.000
Shoulder_Roll: -89.954
Elbow_Pitch: 0.000
Elbow_Yaw: 0.000
Waist: 0.000
Hip_Pitch: 0.000
Hip_Roll: 0.000
Hip_Yaw: 0.000
Knee_Pitch: 0.000
Ankle_Pitch: 0.000
Ankle_Roll: 0.000