Observation System

The observation system uses a factory pattern to provide different observation types for different use cases.

Source: gymkhana/envs/observation.py

Observation types

"rl"

Standard RL observations suitable for general racing tasks.

"drift"

Extended observations including vehicle slip angle, yaw rate, and other states relevant to drift control. Supports normalization.

Configuration

config = {
    'observation_config': {'type': 'drift'},
    'lookahead_n_points': 10,     # Number of lookahead curvature/width points (default: 10)
    'lookahead_ds': 0.3,          # Spacing between lookahead points in metres (default: 0.3)
    'sparse_width_obs': False,    # False: all width values, True: only 1st and last
    'normalize_obs': True,        # Enable observation normalization (only for 'drift' type)
}

Lookahead observations

The observation can include curvature and track width samples at points ahead of the vehicle along the track centerline. The number of points and their spacing are configurable.

When sparse_width_obs is True, only the first and last lookahead width values are included in the observation. This is useful when track width varies very little.

Normalization

When normalize_obs is True, observation values are scaled to a bounded range. Normalization bounds are defined in the codebase and can be tuned by enabling record_obs_min_max in the config to record actual min/max values during training runs.

API reference

gymkhana.envs.observation.sample_lookahead_curvatures(track, current_s: float, n_points: int, ds: float) ndarray

Sample N curvature values ahead of vehicle at uniform intervals along centerline.

Sampling starts at ds meters ahead (not at current position) and proceeds forward. For closed tracks, sampling wraps around using modulo arithmetic.

Parameters

trackTrack

Track object with centerline (must not be None)

current_sfloat

Current arc length position on centerline (meters)

n_pointsint

Number of lookahead points to sample (default 10)

dsfloat

Spacing between points in meters (default 0.3m = 30cm)

Returns

curvaturesnp.ndarray (n_points,)

Curvature at each lookahead point (1/m)

Raises

ValueError

If track, centerline, or spline is None/invalid

gymkhana.envs.observation.sample_lookahead_curvatures_fast(track, current_s: float, n_points: int = 10, ds: float = 0.3) ndarray

High-performance version of sample_lookahead_curvatures using numba JIT compilation.

This function provides ~20x speedup for real-time applications by using numba to compile the curvature sampling loop. Use this when performance is critical (e.g., high-frequency control loops at 100Hz+).

Parameters

trackTrack

Track object with centerline (must not be None)

current_sfloat

Current arc length position on centerline (meters)

n_pointsint

Number of lookahead points to sample (default 10)

dsfloat

Spacing between points in meters (default 0.3m = 30cm)

Returns

curvaturesnp.ndarray (n_points,)

Curvature at each lookahead point (1/m)

Raises

ValueError

If track, centerline, or spline is None/invalid

gymkhana.envs.observation.sample_lookahead_widths(track, current_s: float, n_points: int, ds: float) ndarray

Sample N track width values ahead of vehicle at uniform intervals along centerline.

Sampling starts at ds meters ahead (not at current position) and proceeds forward. For closed tracks, sampling wraps around using modulo arithmetic.

Parameters

trackTrack

Track object with centerline (must not be None)

current_sfloat

Current arc length position on centerline (meters)

n_pointsint

Number of lookahead points to sample (default 10)

dsfloat

Spacing between points in meters (default 0.3m = 30cm)

Returns

widthsnp.ndarray (n_points,)

Total track width (w_left + w_right) at each lookahead point (meters)

Raises

ValueError

If track, centerline, or width data is None/invalid

gymkhana.envs.observation.sample_lookahead_widths_fast(track, current_s: float, n_points: int = 10, ds: float = 0.3) ndarray

High-performance version of sample_lookahead_widths using numba JIT compilation.

This function provides ~1.2x speedup for real-time applications by using numba to compile the width sampling loop. Use this when performance is critical (e.g., high-frequency control loops at 100Hz+).

Parameters

trackTrack

Track object with centerline (must not be None)

current_sfloat

Current arc length position on centerline (meters)

n_pointsint

Number of lookahead points to sample (default 10)

dsfloat

Spacing between points in meters (default 0.3m = 30cm)

Returns

widthsnp.ndarray (n_points,)

Total track width (w_left + w_right) at each lookahead point (meters)

Raises

ValueError

If track, centerline, or width data is None/invalid

class gymkhana.envs.observation.Observation(env)

Abstract class for observations. Each observation must implement the space and observe methods.

Parameters:
  • env – The environment.

  • vehicle_id – The id of the observer vehicle.

  • kwargs – Additional arguments.

abstractmethod space()

Defines the observation space structure for the gym env :return gym.spaces object that desribes shape, data types, and observation bounds

abstractmethod observe()

Generated the observation data at each time step :return current observation values as np array or dict

class gymkhana.envs.observation.OriginalObservation(env)
space()

Defines the observation space structure for the gym env :return gym.spaces object that desribes shape, data types, and observation bounds

observe()

Generated the observation data at each time step :return current observation values as np array or dict

class gymkhana.envs.observation.FeaturesObservation(env, features: List[str])
space()

Defines the observation space structure for the gym env :return gym.spaces object that desribes shape, data types, and observation bounds

observe()

Generated the observation data at each time step :return current observation values as np array or dict

class gymkhana.envs.observation.VectorObservation(env, features: List[str])
space()

Defines the observation space structure for the gym env :return gym.spaces object that desribes shape, data types, and observation bounds

observe()

Generated the observation data at each time step :return current observation values as np array or dict

gymkhana.envs.observation.observation_factory(env, type: str | None, **kwargs) Observation