守门员基础版 + 进阶意图层 + 关键帧技能
守门员基础版: - 1号门将从外场逻辑中分流,具备 HOME/INTERCEPT/CLEAR/PENALTY_READY/RECOVER 状态机 - 门线封角、横移巡逻、禁区内拦截、边路清球、点球站位 - 只依赖 Walk/Neutral/GetUp,不引入真实 catch 或 RL 扑救 守门员进阶意图层: - GoalieSet 保留为生产姿态 - BLOCK_LEFT/BLOCK_RIGHT 降为意图层,不作为正式比赛动作 - CATCH_* 骨架与计时保留,不发真实协议 - GoalieBlock RL 占位接口预留 新增关键帧技能: - GoalieSet(生产)、LowBlockLeft/LowBlockRight(实验) - 注册到 BehaviorManager,has_skill() 接口新增 MonitorClient 改动: - place_player 支持 yaw 参数
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
from behaviors.custom.keyframe.get_up.get_up import GetUp
|
from behaviors.custom.keyframe.get_up.get_up import GetUp
|
||||||
from behaviors.custom.keyframe.keyframe import KeyframeSkill
|
from behaviors.custom.keyframe.keyframe import KeyframeSkill
|
||||||
|
from behaviors.custom.keyframe.poses.goalie_set.goalie_set import GoalieSet
|
||||||
|
from behaviors.custom.keyframe.poses.low_block_left.low_block_left import LowBlockLeft
|
||||||
|
from behaviors.custom.keyframe.poses.low_block_right.low_block_right import LowBlockRight
|
||||||
from behaviors.custom.keyframe.poses.neutral.neutral import Neutral
|
from behaviors.custom.keyframe.poses.neutral.neutral import Neutral
|
||||||
from behaviors.behavior import Behavior
|
from behaviors.behavior import Behavior
|
||||||
from behaviors.custom.reinforcement.walk.walk import Walk
|
from behaviors.custom.reinforcement.walk.walk import Walk
|
||||||
@@ -22,7 +25,7 @@ class BehaviorManager:
|
|||||||
Each skill is indexed by its class name.
|
Each skill is indexed by its class name.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
classes: list[type[Behavior]] = [Walk, Neutral, GetUp]
|
classes: list[type[Behavior]] = [Walk, Neutral, GoalieSet, LowBlockLeft, LowBlockRight, GetUp]
|
||||||
|
|
||||||
# instantiate each Skill and store in the skills dictionary
|
# instantiate each Skill and store in the skills dictionary
|
||||||
self.skills = {cls.__name__: cls(agent=self.agent) for cls in classes}
|
self.skills = {cls.__name__: cls(agent=self.agent) for cls in classes}
|
||||||
@@ -33,6 +36,9 @@ class BehaviorManager:
|
|||||||
raise KeyError(f"No skill found with the name '{name}'")
|
raise KeyError(f"No skill found with the name '{name}'")
|
||||||
return self.skills[name]
|
return self.skills[name]
|
||||||
|
|
||||||
|
def has_skill(self, name: str) -> bool:
|
||||||
|
return name in self.skills
|
||||||
|
|
||||||
def execute(self, skill_name: str, *args, **kwargs) -> bool:
|
def execute(self, skill_name: str, *args, **kwargs) -> bool:
|
||||||
"""
|
"""
|
||||||
Executes one step of the specified skill.
|
Executes one step of the specified skill.
|
||||||
|
|||||||
8
behaviors/custom/keyframe/poses/goalie_set/goalie_set.py
Normal file
8
behaviors/custom/keyframe/poses/goalie_set/goalie_set.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from behaviors.custom.keyframe.keyframe import KeyframeSkill
|
||||||
|
|
||||||
|
|
||||||
|
class GoalieSet(KeyframeSkill):
|
||||||
|
def __init__(self, agent):
|
||||||
|
super().__init__(agent, os.path.join(os.path.dirname(__file__), "goalie_set.yaml"))
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from behaviors.custom.keyframe.keyframe import KeyframeSkill
|
||||||
|
|
||||||
|
|
||||||
|
class LowBlockLeft(KeyframeSkill):
|
||||||
|
def __init__(self, agent):
|
||||||
|
super().__init__(agent, os.path.join(os.path.dirname(__file__), "low_block_left.yaml"))
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from behaviors.custom.keyframe.keyframe import KeyframeSkill
|
||||||
|
|
||||||
|
|
||||||
|
class LowBlockRight(KeyframeSkill):
|
||||||
|
def __init__(self, agent):
|
||||||
|
super().__init__(agent, os.path.join(os.path.dirname(__file__), "low_block_right.yaml"))
|
||||||
32
behaviors/custom/reinforcement/goalie_block/goalie_block.py
Normal file
32
behaviors/custom/reinforcement/goalie_block/goalie_block.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
from behaviors.behavior import Behavior
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class GoalieBlock(Behavior):
|
||||||
|
"""
|
||||||
|
Placeholder interface for a future RL-based goalkeeper blocking skill.
|
||||||
|
|
||||||
|
The production code does not register or call this skill yet.
|
||||||
|
It exists to lock down the expected execution shape for later training work.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, agent):
|
||||||
|
super().__init__(agent)
|
||||||
|
self.last_side: str | None = None
|
||||||
|
|
||||||
|
def execute(self, reset: bool, side: str, *args, **kwargs) -> bool:
|
||||||
|
if reset:
|
||||||
|
self.last_side = side
|
||||||
|
|
||||||
|
logger.warning(
|
||||||
|
"GoalieBlock.execute(side=%s) was called before an RL model was integrated.",
|
||||||
|
side,
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_ready(self, *args) -> bool:
|
||||||
|
return False
|
||||||
@@ -57,7 +57,14 @@ class MonitorClient:
|
|||||||
unum: int,
|
unum: int,
|
||||||
team_name: str,
|
team_name: str,
|
||||||
pos: tuple[float, float, float],
|
pos: tuple[float, float, float],
|
||||||
|
yaw_deg: float | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.send(
|
if yaw_deg is None:
|
||||||
f"(agent (unum {unum}) (team {team_name}) (pos {pos[0]} {pos[1]} {pos[2]}))"
|
command = f"(agent (unum {unum}) (team {team_name}) (pos {pos[0]} {pos[1]} {pos[2]}))"
|
||||||
)
|
else:
|
||||||
|
command = (
|
||||||
|
f"(agent (unum {unum}) (team {team_name}) "
|
||||||
|
f"(move {pos[0]} {pos[1]} {pos[2]} {yaw_deg}))"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.send(command)
|
||||||
|
|||||||
Reference in New Issue
Block a user