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

Observation types for the Gym-Khana environment.

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

Sample curvature values ahead of the vehicle along the centerline.

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

Parameters:
  • track – Track object with a valid centerline.

  • current_s – Current arc length position on centerline (meters).

  • n_points – Number of lookahead points to sample.

  • ds – Spacing between points in meters.

Returns:

Curvature at each lookahead point (1/m), shape (n_points,).

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

Numba-accelerated version of sample_lookahead_curvatures().

Bypasses the scipy CubicSpline interface and computes curvature directly from spline derivatives, providing a significant speedup for real-time use.

Parameters:
  • track – Track object with a valid centerline.

  • current_s – Current arc length position on centerline (meters).

  • n_points – Number of lookahead points to sample (default 10).

  • ds – Spacing between points in meters (default 0.3).

Returns:

Curvature at each lookahead point (1/m), shape (n_points,).

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 total track width values ahead of the vehicle along the centerline.

Sampling starts at ds meters ahead (not at current position) and proceeds forward at uniform intervals. Returns zeros if width data is unavailable.

Parameters:
  • track – Track object with a valid centerline.

  • current_s – Current arc length position on centerline (meters).

  • n_points – Number of lookahead points to sample.

  • ds – Spacing between points in meters.

Returns:

Total track width (w_left + w_right) at each point (meters), shape (n_points,).

Raises:

ValueError – If track or centerline is None/invalid.

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

Numba-accelerated version of sample_lookahead_widths().

Uses nearest-neighbor interpolation with binary search for efficient lookup.

Parameters:
  • track – Track object with a valid centerline.

  • current_s – Current arc length position on centerline (meters).

  • n_points – Number of lookahead points to sample (default 10).

  • ds – Spacing between points in meters (default 0.3).

Returns:

Total track width (w_left + w_right) at each point (meters), shape (n_points,).

Raises:

ValueError – If track or centerline is None/invalid.

class gymkhana.envs.observation.Observation(env)

Abstract base class for observation types.

Each subclass must implement space() and observe().

Parameters:

env – The Gymnasium environment instance.

abstractmethod space()

Return the Gymnasium observation space for this observation type.

abstractmethod observe()

Return the current observation as a numpy array or dict.

get_debug_features(agent_idx: int) dict

Return a flat {feature_name: value} dict for a single agent.

Used for debug overlay display. Subclasses override to handle their specific _last_raw_features format.

class gymkhana.envs.observation.OriginalObservation(env)

Dict-based observation with scans, poses, and velocities for all agents.

This is the legacy observation format compatible with the original f1tenth_gym. Returns a dict keyed by field name, each containing a per-agent array.

space()

Return the Gymnasium observation space for this observation type.

observe()

Return the current observation as a numpy array or dict.

get_debug_features(agent_idx: int) dict

Return a flat {feature_name: value} dict for a single agent.

Used for debug overlay display. Subclasses override to handle their specific _last_raw_features format.

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

Dict-based observation with a configurable subset of features per agent.

Each agent gets its own sub-dict keyed by feature name. Supported features include scan, pose_x, pose_y, pose_theta, linear_vel_x, linear_vel_y, ang_vel_z, delta, beta, collision, lap_time, and lap_count.

Parameters:
  • env – The Gymnasium environment instance.

  • features – List of feature names to include in the observation.

space()

Return the Gymnasium observation space for this observation type.

observe()

Return the current observation as a numpy array or dict.

get_debug_features(agent_idx: int) dict

Return a flat {feature_name: value} dict for a single agent.

Used for debug overlay display. Subclasses override to handle their specific _last_raw_features format.

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

Flat vector observation for single-agent RL training.

Concatenates selected features into a 1-D numpy array. Supports optional normalization to [-1, 1] when normalize_obs is enabled in the env config. Also supports Frenet coordinates and lookahead curvature/width.

Parameters:
  • env – The Gymnasium environment instance.

  • features – Ordered list of feature names to concatenate.

space()

Return the Gymnasium observation space for this observation type.

observe()

Return the current observation as a numpy array or dict.

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

Create an observation instance by type name.

Parameters:
  • env – The Gymnasium environment instance.

  • type – Observation type string. Supported values: "original", "features", "kinematic_state", "dynamic_state", "frenet_dynamic_state", "rl", "drift", "frenet", "race". Defaults to "original" if None.

  • **kwargs – Additional arguments forwarded to the observation constructor.

Returns:

An Observation subclass instance.

Raises:

ValueError – If the type string is not recognised.