repair some bugs and path planning 0.2.0 version
This commit is contained in:
@@ -103,57 +103,26 @@ class PathPlanner:
|
||||
for j in range(self.ny):
|
||||
y = self._grid_to_world_y(j)
|
||||
if abs(y) > goal_half_width:
|
||||
self.cost_map[i, j] = -3
|
||||
self.static_cost_map[i, j] = -3
|
||||
# 右侧边界:x > field_half_len 的区域,保留球门开口
|
||||
for i in range(self._world_to_grid_x(field_half_len + 0.001), self.nx):
|
||||
for j in range(self.ny):
|
||||
y = self._grid_to_world_y(j)
|
||||
if abs(y) > goal_half_width:
|
||||
self.cost_map[i, j] = -3
|
||||
self.static_cost_map[i, j] = -3
|
||||
# 上下边界
|
||||
for i in range(self.nx):
|
||||
for j in [0, self.ny-1]:
|
||||
self.cost_map[i, j] = -3
|
||||
self.static_cost_map[i, j] = -3
|
||||
# 可选:如果需要在边界内留出线宽,可额外处理
|
||||
|
||||
# 4. 门柱(作为硬墙)
|
||||
goal_post_positions = [
|
||||
(field_half_len+1, goal_half_width+1), # 右侧上柱
|
||||
(field_half_len+1, goal_half_width),
|
||||
(field_half_len+1, goal_half_width-1),
|
||||
(field_half_len, goal_half_width-1),
|
||||
(field_half_len, goal_half_width),
|
||||
(field_half_len, goal_half_width+1),
|
||||
(field_half_len-1, goal_half_width+1),
|
||||
(field_half_len-1, goal_half_width),
|
||||
(field_half_len-1, goal_half_width-1),
|
||||
(field_half_len+1, -goal_half_width+1), # 右侧下柱
|
||||
(field_half_len+1, -goal_half_width),
|
||||
(field_half_len+1, -goal_half_width-1),
|
||||
(field_half_len, -goal_half_width-1),
|
||||
(field_half_len, -goal_half_width),
|
||||
(field_half_len, -goal_half_width+1),
|
||||
(field_half_len-1, -goal_half_width+1),
|
||||
(field_half_len-1, -goal_half_width),
|
||||
(field_half_len-1, -goal_half_width-1),
|
||||
(-field_half_len+1, goal_half_width+1), # 左侧上柱
|
||||
(-field_half_len+1, goal_half_width),
|
||||
(-field_half_len+1, goal_half_width-1),
|
||||
(-field_half_len, goal_half_width-1),
|
||||
(-field_half_len, goal_half_width),
|
||||
(-field_half_len, goal_half_width+1),
|
||||
(-field_half_len-1, goal_half_width+1),
|
||||
(-field_half_len-1, goal_half_width),
|
||||
(-field_half_len-1, goal_half_width-1),
|
||||
(-field_half_len+1, -goal_half_width+1), # 左侧下柱
|
||||
(-field_half_len+1, -goal_half_width),
|
||||
(-field_half_len+1, -goal_half_width-1),
|
||||
(-field_half_len, -goal_half_width-1),
|
||||
(-field_half_len, -goal_half_width),
|
||||
(-field_half_len, -goal_half_width+1),
|
||||
(-field_half_len-1, -goal_half_width+1),
|
||||
(-field_half_len-1, -goal_half_width),
|
||||
(-field_half_len-1, -goal_half_width-1),
|
||||
|
||||
(field_half_len, goal_half_width), # 右侧上柱
|
||||
(field_half_len, -goal_half_width), # 右侧下柱
|
||||
(-field_half_len, goal_half_width), # 左侧上柱
|
||||
(-field_half_len, -goal_half_width), # 左侧下柱
|
||||
]
|
||||
for px, py in goal_post_positions:
|
||||
ix, iy = self._world_to_grid(px, py)
|
||||
@@ -164,7 +133,7 @@ class PathPlanner:
|
||||
if not (0 <= nx < self.nx and 0 <= ny < self.ny):
|
||||
continue
|
||||
dist = np.hypot(dx * self.res, dy * self.res)
|
||||
if dist <= self.post_radius:
|
||||
if dist <= post_radius:
|
||||
self.static_cost_map[nx, ny] = -3
|
||||
|
||||
# ---------- 获取动态障碍物(对手球员) ----------
|
||||
@@ -179,6 +148,16 @@ class PathPlanner:
|
||||
continue # 跳过未看到的球员
|
||||
return opponents
|
||||
|
||||
def _get_teammate_positions(self) -> List[np.ndarray]:
|
||||
"""从 FieldLandmarks 获取所有队友球员的全局位置"""
|
||||
teammates = []
|
||||
for player in self.world.our_team_players:
|
||||
if player.last_seen_time is not None and (self.world.server_time - player.last_seen_time) < 1.0:
|
||||
teammates.append(player.position[:2]) # 只使用 x, y
|
||||
else:
|
||||
# 长时间未看到的球员不添加到避障列表中
|
||||
continue # 跳过未看到的球员
|
||||
return teammates
|
||||
# ---------- 动态障碍物添加到代价地图 ----------
|
||||
def _apply_opponents_to_map(self, cost_map: np.ndarray, opponents: List[np.ndarray]):
|
||||
"""
|
||||
@@ -208,6 +187,22 @@ class PathPlanner:
|
||||
if cost_map[nx, ny] >= 0:
|
||||
cost_map[nx, ny] += 10.0 * (1.0 - (dist - effective_radius) / buffer_width)
|
||||
|
||||
def _apply_teammate_to_map(self, cost_map, teammates):
|
||||
soft_radius = self.robot_radius + 0.2 # 允许稍微接近
|
||||
for tm in teammates:
|
||||
ix, iy = self._world_to_grid(tm[0], tm[1])
|
||||
rad_cells = int(soft_radius / self.res) + 1
|
||||
for dx in range(-rad_cells, rad_cells+1):
|
||||
for dy in range(-rad_cells, rad_cells+1):
|
||||
nx, ny = ix+dx, iy+dy
|
||||
if not (0 <= nx < self.nx and 0 <= ny < self.ny):
|
||||
continue
|
||||
dist = np.hypot(dx*self.res, dy*self.res)
|
||||
if dist <= soft_radius:
|
||||
# 不设为硬墙,只加较小代价
|
||||
if cost_map[nx, ny] >= 0:
|
||||
cost_map[nx, ny] += 5.0 # 代价比对手小
|
||||
|
||||
# ---------- 启发函数 ----------
|
||||
def _heuristic(self, ix1: int, iy1: int, ix2: int, iy2: int) -> float:
|
||||
"""对角线距离(允许8方向移动)"""
|
||||
@@ -268,9 +263,11 @@ class PathPlanner:
|
||||
:param timeout_ms: 超时时间(毫秒)
|
||||
:return: 路径点列表(世界坐标),若失败返回空列表
|
||||
"""
|
||||
# 1. 获取对手并构建动态代价地图
|
||||
opponents = self._get_opponent_positions()
|
||||
# 1. 获取队友并构建动态代价地图
|
||||
teammates = self._get_teammate_positions()
|
||||
cost_map = self.static_cost_map.copy()
|
||||
self._apply_teammate_to_map(cost_map, teammates)
|
||||
opponents = self._get_opponent_positions()
|
||||
self._apply_opponents_to_map(cost_map, opponents)
|
||||
|
||||
# 2. 转换坐标
|
||||
|
||||
Reference in New Issue
Block a user