Skip to content

Commit 163e8fe

Browse files
committed
Revert enemy team support
1 parent 6a4d4ae commit 163e8fe

2 files changed

Lines changed: 56 additions & 137 deletions

File tree

src/software/gameplay_tests/field_test_runner.py

Lines changed: 53 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,33 @@ def __init__(
7272

7373
@override
7474
def set_world_state(self, world_state: WorldState):
75-
"""Send move tactics to robots to the positions in the given world state.
75+
"""Send move tactics to drive the friendly robots to the positions in
76+
the given world state.
7677
7778
:param world_state: The WorldState proto with the desired robot states
7879
"""
79-
self.set_tactics(
80-
blue_tactics=self._create_move_tactics(world_state.blue_robots),
81-
yellow_tactics=self._create_move_tactics(world_state.yellow_robots),
80+
friendly_move_tactics = self._create_move_tactics(
81+
world_state.yellow_robots
82+
if self.is_yellow_friendly
83+
else world_state.blue_robots
8284
)
8385

86+
if self.is_yellow_friendly:
87+
self.set_tactics(blue_tactics=None, yellow_tactics=friendly_move_tactics)
88+
else:
89+
self.set_tactics(blue_tactics=friendly_move_tactics, yellow_tactics=None)
90+
8491
self._wait_for_robots_at_world_state(world_state)
8592

8693
@override
8794
def set_tactics(self, blue_tactics={}, yellow_tactics={}):
88-
"""Override AI tactics, remapping each team's simulated robot ids to the
89-
robot ids that are actually available on the field.
95+
"""Override AI tactics, remapping the friendly team's simulated robot ids
96+
to the robot ids that are actually available on the field.
9097
"""
9198
if self.is_yellow_friendly:
92-
blue_sim_to_field_id = self.enemy_sim_to_field_id
93-
yellow_sim_to_field_id = self.friendly_sim_to_field_id
99+
yellow_tactics = self._map_tactics_to_field_ids(yellow_tactics)
94100
else:
95-
blue_sim_to_field_id = self.friendly_sim_to_field_id
96-
yellow_sim_to_field_id = self.enemy_sim_to_field_id
97-
98-
blue_tactics = self._map_tactics_to_field_ids(
99-
blue_tactics, blue_sim_to_field_id, "blue"
100-
)
101-
yellow_tactics = self._map_tactics_to_field_ids(
102-
yellow_tactics, yellow_sim_to_field_id, "yellow"
103-
)
101+
blue_tactics = self._map_tactics_to_field_ids(blue_tactics)
104102

105103
super().set_tactics(blue_tactics=blue_tactics, yellow_tactics=yellow_tactics)
106104

@@ -214,21 +212,16 @@ def _survey_field_robots(self):
214212
# survey field for available robot ids
215213
survey_start_time = time.time()
216214
self.friendly_robot_ids_field = []
217-
self.enemy_robot_ids_field = []
218215
while time.time() - survey_start_time < WORLD_BUFFER_TIMEOUT:
219216
try:
220217
world = self.world_buffer.get(block=True, timeout=0.1)
221218
self.initial_world = world
222219
self.friendly_robot_ids_field = [
223220
robot.id for robot in world.friendly_team.team_robots
224221
]
225-
self.enemy_robot_ids_field = [
226-
robot.id for robot in world.enemy_team.team_robots
227-
]
228222

229223
if len(self.friendly_robot_ids_field) > 0:
230224
logger.info(f"friendly team ids {self.friendly_robot_ids_field}")
231-
logger.info(f"enemy team ids {self.enemy_robot_ids_field}")
232225
break
233226
except queue.Empty:
234227
continue
@@ -239,41 +232,20 @@ def _survey_field_robots(self):
239232
# Simulated tests create robots with contiguous ids (0, 1, 2, ...), but
240233
# the robots physically on the field may have arbitrary ids and there may
241234
# be fewer of them. Map each simulated id to an available field id, in
242-
# ascending order and per team, so tactics and validations written against
243-
# simulated ids refer to the robots that are actually present. e.g. field
244-
# robots [4, 5] map simulated id 0 -> 4 and 1 -> 5; field robots [0, 1, 5]
245-
# map 0 -> 0, 1 -> 1 and 2 -> 5.
246-
self.friendly_sim_to_field_id = self._build_sim_to_field_mapping(
247-
self.friendly_robot_ids_field
248-
)
249-
self.enemy_sim_to_field_id = self._build_sim_to_field_mapping(
250-
self.enemy_robot_ids_field
251-
)
252-
# Inverse mappings, used to relabel the world's field ids back to the
253-
# simulated ids that validations are written against.
254-
self.friendly_field_to_sim_id = {
255-
field_id: sim_id
256-
for sim_id, field_id in self.friendly_sim_to_field_id.items()
235+
# ascending order, so tactics written against simulated ids are sent to
236+
# the robots that are actually present. e.g. field robots [4, 5] map
237+
# simulated id 0 -> 4 and 1 -> 5; field robots [0, 1, 5] map 0 -> 0,
238+
# 1 -> 1 and 2 -> 5.
239+
self.sim_to_field_robot_id = {
240+
sim_id: field_id
241+
for sim_id, field_id in enumerate(sorted(self.friendly_robot_ids_field))
257242
}
258-
self.enemy_field_to_sim_id = {
259-
field_id: sim_id for sim_id, field_id in self.enemy_sim_to_field_id.items()
243+
# Inverse mapping, used to relabel the world's field ids back to the
244+
# simulated ids that validations are written against.
245+
self.field_to_sim_robot_id = {
246+
field_id: sim_id for sim_id, field_id in self.sim_to_field_robot_id.items()
260247
}
261-
logger.info(
262-
f"friendly simulated id to field id mapping {self.friendly_sim_to_field_id}"
263-
)
264-
logger.info(
265-
f"enemy simulated id to field id mapping {self.enemy_sim_to_field_id}"
266-
)
267-
268-
@staticmethod
269-
def _build_sim_to_field_mapping(field_ids):
270-
"""Map contiguous simulated robot ids (0, 1, 2, ...) onto the available
271-
field ids for a team, in ascending order.
272-
273-
:param field_ids: the robot ids present on the field for a team
274-
:return: dict of simulated_robot_id -> field_robot_id
275-
"""
276-
return {sim_id: field_id for sim_id, field_id in enumerate(sorted(field_ids))}
248+
logger.info(f"simulated id to field id mapping {self.sim_to_field_robot_id}")
277249

278250
def _create_move_tactics(self, robot_states):
279251
"""Create a MoveTactic for each robot to drive it to its world state.
@@ -294,109 +266,74 @@ def _create_move_tactics(self, robot_states):
294266
for robot_id, robot_state in robot_states.items()
295267
}
296268

297-
def _map_tactics_to_field_ids(self, tactics, sim_to_field_id, team_name):
269+
def _map_tactics_to_field_ids(self, tactics):
298270
"""Remap a tactics dict keyed by simulated robot ids to the robot ids
299271
available on the field. Tactics for simulated ids with no available
300272
field robot are dropped with a warning.
301273
302274
:param tactics: None or dict of simulated_robot_id -> tactic
303-
:param sim_to_field_id: the team's simulated-id -> field-id mapping
304-
:param team_name: the team colour, used in warnings
305275
:return: None if tactics is None, else dict of field_robot_id -> tactic
306276
"""
307277
if tactics is None:
308278
return None
309279

310280
mapped_tactics = {}
311281
for sim_id, tactic in tactics.items():
312-
if sim_id not in sim_to_field_id:
282+
if sim_id not in self.sim_to_field_robot_id:
313283
logger.warning(
314-
f"no {team_name} field robot available for simulated robot id "
315-
f"{sim_id}; skipping its tactic"
284+
f"no field robot available for simulated robot id {sim_id}; "
285+
"skipping its tactic"
316286
)
317287
continue
318-
mapped_tactics[sim_to_field_id[sim_id]] = tactic
288+
mapped_tactics[self.sim_to_field_robot_id[sim_id]] = tactic
319289

320290
return mapped_tactics
321291

322-
@staticmethod
323-
def _remap_robot_state_ids(robot_states, sim_to_field_id):
324-
"""Remap a world-state robot map keyed by simulated ids to field ids,
325-
dropping any simulated id with no available field robot.
326-
327-
:param robot_states: map of simulated_robot_id -> RobotState
328-
:param sim_to_field_id: the team's simulated-id -> field-id mapping
329-
:return: dict of field_robot_id -> RobotState
330-
"""
331-
return {
332-
sim_to_field_id[sim_id]: robot_state
333-
for sim_id, robot_state in robot_states.items()
334-
if sim_id in sim_to_field_id
335-
}
336-
337292
def _relabel_world_to_sim_ids(self, world: World) -> World:
338-
"""Return a copy of the world with both teams' robot ids translated from
293+
"""Return a copy of the world with friendly robot ids translated from
339294
field ids back to the simulated ids the test uses.
340295
341296
Validations match robots by the contiguous simulated ids (0, 1, 2, ...),
342297
but the world reports the robots' actual field ids. Relabeling the world
343298
here lets every id-based validation find the correct robot without each
344-
validation needing to know about the mapping. Robots with no mapping
345-
(e.g. extras not part of the test) keep their field id.
299+
validation needing to know about the mapping. Friendly robots with no
300+
mapping (e.g. extras not part of the test) keep their field id.
346301
347302
:param world: The World proto reported by the field full system
348-
:return: a copy of the world with robot ids in simulated-id space
303+
:return: a copy of the world with friendly robot ids in simulated-id space
349304
"""
350305
relabeled_world = World()
351306
relabeled_world.CopyFrom(world)
352-
self._relabel_team_to_sim_ids(
353-
relabeled_world.friendly_team, self.friendly_field_to_sim_id
354-
)
355-
self._relabel_team_to_sim_ids(
356-
relabeled_world.enemy_team, self.enemy_field_to_sim_id
357-
)
307+
for robot in relabeled_world.friendly_team.team_robots:
308+
if robot.id in self.field_to_sim_robot_id:
309+
robot.id = self.field_to_sim_robot_id[robot.id]
358310
return relabeled_world
359311

360-
@staticmethod
361-
def _relabel_team_to_sim_ids(team, field_to_sim_id):
362-
"""Relabel a team's robot ids in place from field ids to simulated ids.
363-
364-
:param team: a Team proto whose robots' ids to relabel
365-
:param field_to_sim_id: the team's field-id -> simulated-id mapping
366-
"""
367-
for robot in team.team_robots:
368-
if robot.id in field_to_sim_id:
369-
robot.id = field_to_sim_id[robot.id]
370-
371312
def _wait_for_robots_at_world_state(self, world_state: WorldState):
372313
"""Block until every robot in the world state is within
373314
ROBOT_SETUP_TOLERANCE_M of its target position.
374315
375316
Robot positions are read from the friendly full system's World in the
376-
same fashion as _survey_field_robots. The friendly team maps to the
377-
friendly-coloured robots in the world state, and the enemy team to the
378-
other colour. Each team's targets are remapped from simulated ids to the
379-
field ids they were assigned to in set_tactics.
317+
same fashion as _survey_field_robots. The friendly targets are remapped
318+
from simulated ids to the field ids they were assigned to in set_tactics.
380319
381320
:param world_state: The WorldState proto with the desired robot states
382321
:raises Exception: if the robots do not reach their targets within
383322
ROBOT_SETUP_TIMEOUT_S
384323
"""
385-
if self.is_yellow_friendly:
386-
friendly_targets = world_state.yellow_robots
387-
enemy_targets = world_state.blue_robots
388-
else:
389-
friendly_targets = world_state.blue_robots
390-
enemy_targets = world_state.yellow_robots
324+
friendly_targets = (
325+
world_state.yellow_robots
326+
if self.is_yellow_friendly
327+
else world_state.blue_robots
328+
)
391329

392-
# Remap each team's targets onto the field ids they were commanded to,
330+
# Remap the friendly targets onto the field ids they were commanded to,
393331
# dropping any simulated id that has no available field robot
394-
friendly_targets = self._remap_robot_state_ids(
395-
friendly_targets, self.friendly_sim_to_field_id
396-
)
397-
enemy_targets = self._remap_robot_state_ids(
398-
enemy_targets, self.enemy_sim_to_field_id
399-
)
332+
friendly_targets = {
333+
self.sim_to_field_robot_id[sim_id]: robot_state
334+
for sim_id, robot_state in friendly_targets.items()
335+
if sim_id in self.sim_to_field_robot_id
336+
}
400337

401338
logger.info("waiting for robots to reach their target positions")
402339
wait_start_time = time.time()
@@ -410,14 +347,8 @@ def _wait_for_robots_at_world_state(self, world_state: WorldState):
410347
robot.id: robot.current_state.global_position
411348
for robot in world.friendly_team.team_robots
412349
}
413-
enemy_positions = {
414-
robot.id: robot.current_state.global_position
415-
for robot in world.enemy_team.team_robots
416-
}
417350

418-
if self._all_robots_at_targets(
419-
friendly_targets, friendly_positions
420-
) and self._all_robots_at_targets(enemy_targets, enemy_positions):
351+
if self._all_robots_at_targets(friendly_targets, friendly_positions):
421352
logger.info("all robots reached their target positions")
422353
return
423354

src/software/gameplay_tests/fixture.py

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -207,17 +207,13 @@ def field_session(args, runtime_subpath):
207207
blue_full_system_proto_unix_io = ProtoUnixIO()
208208

209209
debug_full_sys = args.debug_blue_full_system
210-
friendly_runtime_dir = f"{args.blue_full_system_runtime_dir}/{runtime_subpath}"
211-
enemy_runtime_dir = f"{args.yellow_full_system_runtime_dir}/{runtime_subpath}"
210+
runtime_dir = f"{args.blue_full_system_runtime_dir}/{runtime_subpath}"
212211
friendly_proto_unix_io = blue_full_system_proto_unix_io
213-
enemy_proto_unix_io = yellow_full_system_proto_unix_io
214212

215213
if args.run_yellow:
216214
debug_full_sys = args.debug_yellow_full_system
217-
friendly_runtime_dir = f"{args.yellow_full_system_runtime_dir}/{runtime_subpath}"
218-
enemy_runtime_dir = f"{args.blue_full_system_runtime_dir}/{runtime_subpath}"
215+
runtime_dir = f"{args.yellow_full_system_runtime_dir}/{runtime_subpath}"
219216
friendly_proto_unix_io = yellow_full_system_proto_unix_io
220-
enemy_proto_unix_io = blue_full_system_proto_unix_io
221217

222218
estop_mode, estop_path = get_estop_config(
223219
args.keyboard_estop, args.disable_communication
@@ -226,18 +222,11 @@ def field_session(args, runtime_subpath):
226222
with (
227223
FullSystem(
228224
"software/unix_full_system",
229-
full_system_runtime_dir=friendly_runtime_dir,
225+
full_system_runtime_dir=runtime_dir,
230226
debug_full_system=debug_full_sys,
231227
friendly_colour_yellow=args.run_yellow,
232228
should_restart_on_crash=False,
233229
) as friendly_fs,
234-
FullSystem(
235-
"software/unix_full_system",
236-
full_system_runtime_dir=enemy_runtime_dir,
237-
debug_full_system=debug_full_sys,
238-
friendly_colour_yellow=not args.run_yellow,
239-
should_restart_on_crash=False,
240-
) as enemy_fs,
241230
Gamecontroller(
242231
# we would be using conventional port if and only if we are playing in robocup.
243232
suppress_logs=(not args.verbose),
@@ -260,7 +249,6 @@ def field_session(args, runtime_subpath):
260249
) as rc_friendly,
261250
):
262251
friendly_fs.setup_proto_unix_io(friendly_proto_unix_io)
263-
enemy_fs.setup_proto_unix_io(enemy_proto_unix_io)
264252

265253
gamecontroller.setup_proto_unix_io(
266254
blue_full_system_proto_unix_io=blue_full_system_proto_unix_io,

0 commit comments

Comments
 (0)