Implementation:Google deepmind Dm control Soccer Observables
| Metadata | |
|---|---|
| Knowledge Sources | dm_control |
| Domains | Multi-Agent Reinforcement Learning, Observation Design |
| Last Updated | 2026-02-15 00:00 GMT |
Overview
Concrete tool for adding egocentric, per-player observations to a multi-agent soccer environment, including proprioception, ball state, teammate/opponent state, arena landmarks, game statistics, and interception events.
Description
The soccer observables module defines an abstract ObservablesAdder protocol and three concrete implementations:
CoreObservablesAdder-- Adds the full core observation set for each player:- Proprioception: enables
proprioceptionandkinematic_sensorsobservables, plus theprev_actionobservable. - Ball (egocentric): adds
ball_ego_position,ball_ego_linear_velocity, andball_ego_angular_velocityusing MuJoCoframepos,framelinvel, andframeangvelsensors with the player's root body as the reference frame. - Other players (egocentric): for each teammate and opponent, adds
{prefix}_ego_position,{prefix}_ego_linear_velocity,{prefix}_ego_orientation(concatenated x/y/z axis sensors),{prefix}_ego_end_effectors_pos, and{prefix}_end_effectors_pos(in the other player's own frame). - Arena landmarks: adds egocentric vectors to eight clockwise pitch landmarks (team goal corners, mid-goal, field corners, opponent goal corners). For away-team players, the landmark order is rotated by half to maintain a consistent team-relative naming convention.
- Game statistics: adds
stats_vel_to_ball,stats_closest_vel_to_ball,stats_veloc_forward,stats_vel_ball_to_goal,stats_home_avg_teammate_dist,stats_teammate_spread_out,stats_home_score, andstats_away_score.
- Proprioception: enables
InterceptionObservablesAdder-- Adds binary event observables for ball reception and opponent interception at distance thresholds of 5m, 10m, and 15m:stats_i_received_ball,stats_i_received_ball_{dist}m,stats_opponent_intercepted_ball,stats_opponent_intercepted_ball_{dist}m.MultiObservablesAdder-- Composes a list ofObservablesAdderinstances and applies them sequentially to each player.
Usage
The default CoreObservablesAdder is used automatically when no custom observables argument is provided to the Task constructor. To include interception observables, combine adders using MultiObservablesAdder.
Code Reference
| Attribute | Value |
|---|---|
| Source Location | dm_control/locomotion/soccer/observables.py, lines 24--451
|
| Signature (CoreObservablesAdder) | class CoreObservablesAdder(ObservablesAdder): def __call__(self, task, player)
|
| Signature (InterceptionObservablesAdder) | class InterceptionObservablesAdder(ObservablesAdder): def __call__(self, task, player)
|
| Signature (MultiObservablesAdder) | class MultiObservablesAdder(ObservablesAdder): def __init__(self, observables: list[ObservablesAdder])
|
| Import | from dm_control.locomotion.soccer import CoreObservablesAdder, InterceptionObservablesAdder, MultiObservablesAdder
|
I/O Contract
Inputs (__call__):
| Parameter | Type | Description |
|---|---|---|
task |
soccer.Task |
The task instance providing access to task.players, task.ball, and task.arena.
|
player |
Player |
The specific player to which observables will be attached. |
Outputs (observables added to player.walker.observables):
| Observable Name Pattern | Type | Shape / Notes |
|---|---|---|
joints_pos, sensors_gyro, etc. |
Proprioception | Walker-specific; enabled by setting .enabled = True.
|
ball_ego_position |
MJCFFeature |
(3,) -- ball position in player frame.
|
ball_ego_linear_velocity |
MJCFFeature |
(3,) -- ball linear velocity in player frame.
|
ball_ego_angular_velocity |
MJCFFeature |
(3,) -- ball angular velocity in player frame.
|
{prefix}_ego_position |
MJCFFeature |
(3,) -- other player root body position in player frame.
|
{prefix}_ego_linear_velocity |
MJCFFeature |
(3,) -- other player velocity in player frame.
|
{prefix}_ego_orientation |
Generic |
(9,) -- concatenated x/y/z axis vectors.
|
{prefix}_ego_end_effectors_pos |
Generic |
(N_eff * 3,) -- end effector positions in player frame.
|
team_goal_back_right, opponent_goal_mid, etc. |
Egocentric vector | (2,) or (3,) -- pitch landmark directions.
|
stats_vel_to_ball |
Generic |
() -- scalar velocity toward ball.
|
stats_i_received_ball_10m |
Generic |
() -- binary interception event (InterceptionObservablesAdder only).
|
Usage Examples
from dm_control.locomotion import soccer
# Default: CoreObservablesAdder is used automatically.
env = soccer.load(team_size=2)
timestep = env.reset()
# Each player gets an independent observation dict.
for i, obs in enumerate(timestep.observation):
print(f"Player {i} observables: {sorted(obs.keys())}")
# Include interception observables alongside core observables.
combined = soccer.MultiObservablesAdder([
soccer.CoreObservablesAdder(),
soccer.InterceptionObservablesAdder(),
])
players = soccer._make_players(team_size=2, walker_type=soccer.WalkerType.BOXHEAD)
arena = soccer.RandomizedPitch(min_size=(32, 24), max_size=(48, 36))
task = soccer.Task(players=players, arena=arena, observables=combined)
# Verify interception observables are present.
obs_dict = task.observables[0]
assert 'stats_i_received_ball' in obs_dict
assert 'stats_opponent_intercepted_ball_10m' in obs_dict