Spaces:
Sleeping
Sleeping
| """ | |
| Action and Observation types for the car racing environment. | |
| Observation design notes | |
| ------------------------ | |
| Dropped from original 7-float vector: | |
| x, y β absolute screen coords, track-specific, hurt generalisation | |
| gate_side β distance to start/finish gate, meaningless on unseen tracks | |
| on_track β binary (0/1), tells agent it crashed AFTER the fact; no lookahead | |
| sin/cos β absolute global heading; encodes track layout, hurts generalisation | |
| Kept: | |
| speed β controls braking/throttle decisions | |
| angular_velocity β egocentric turn rate; no global orientation leak | |
| Replaced on_track with 5 raycasts: | |
| ray_left β clearance 90Β° left of heading (lateral, right now) | |
| ray_front_left β clearance 45Β° left of heading (diagonal lookahead) | |
| ray_front β clearance straight ahead (forward lookahead) | |
| ray_front_right β clearance 45Β° right of heading (diagonal lookahead) | |
| ray_right β clearance 90Β° right of heading (lateral, right now) | |
| All rays: 1.0 = boundary MAX px away (clear), 0.0 = boundary at car (edge/off). | |
| Binary on_track told the agent it crashed AFTER crossing. | |
| Raycasts tell the agent HOW FAR it is from each boundary BEFORE crossing. | |
| Added: | |
| image β 64Γ64 RGB egocentric headlight view (car always faces up). | |
| CNN reads track shape ahead; generalises to any unseen layout. | |
| """ | |
| from typing import Any, Dict, List, Optional | |
| import numpy as np | |
| from pydantic import ConfigDict | |
| from openenv.core.env_server import Action, Observation, State | |
| class DriveAction(Action): | |
| """Continuous driving action.""" | |
| accel: float # -1 (brake) .. +1 (throttle) | |
| steer: float # -1 (left) .. +1 (right) | |
| class RaceObservation(Observation): | |
| """ | |
| Combined image + scalar observation. | |
| image : (64, 64, 3) uint8 numpy array β egocentric headlight view. | |
| None when use_image=False. | |
| speed : speed / max_speed (β 0..1) | |
| angular_velocity : degrees turned last step / STEER_DEG (β -1..1, egocentric) | |
| ray_left : clearance to left boundary (0=at edge, 1=MAX away) | |
| ray_front_left : clearance front-left diagonal | |
| ray_front : clearance straight ahead | |
| ray_front_right : clearance front-right diagonal | |
| ray_right : clearance to right boundary | |
| """ | |
| model_config = ConfigDict(arbitrary_types_allowed=True) | |
| image: Optional[Any] = None # np.ndarray (64, 64, 3) uint8 | |
| # scalar branch β 9 values total | |
| speed: float = 0.0 | |
| angular_velocity: float = 0.0 | |
| ray_left: float = 1.0 | |
| ray_front_left: float = 1.0 | |
| ray_front: float = 1.0 | |
| ray_front_right: float = 1.0 | |
| ray_right: float = 1.0 | |
| wp_sin: float = 0.0 # sin of angle to next waypoint (relative to heading) | |
| wp_cos: float = 1.0 # cos of angle to next waypoint (1.0 = straight ahead) | |
| def scalars(self) -> List[float]: | |
| """Convenience: flat list for feeding directly into the MLP encoder.""" | |
| return [ | |
| self.speed, | |
| self.angular_velocity, | |
| self.ray_left, | |
| self.ray_front_left, | |
| self.ray_front, | |
| self.ray_front_right, | |
| self.ray_right, | |
| self.wp_sin, | |
| self.wp_cos, | |
| ] | |
| class RaceState(State): | |
| """OpenEnv State for the car racing environment. | |
| Extends the base State (episode_id, step_count) with | |
| track and progress information. | |
| """ | |
| track_level: int = 0 | |
| track_name: str = "" | |
| laps: int = 0 | |