import math
import numpy as np
from collections import namedtuple
from multiprocessing . connection import Connection
from metadrive . engine . core . engine_core import EngineCore
from metadrive . engine . core . image_buffer import ImageBuffer
from metadrive . envs . metadrive_env import MetaDriveEnv
from metadrive . obs . image_obs import ImageObservation
from openpilot . common . realtime import Ratekeeper
from openpilot . tools . sim . lib . common import vec3
from openpilot . tools . sim . lib . camerad import W , H
metadrive_state = namedtuple ( " metadrive_state " , [ " velocity " , " position " , " bearing " , " steering_angle " ] )
def apply_metadrive_patches ( ) :
# By default, metadrive won't try to use cuda images unless it's used as a sensor for vehicles, so patch that in
def add_image_sensor_patched ( self , name : str , cls , args ) :
if self . global_config [ " image_on_cuda " ] : # and name == self.global_config["vehicle_config"]["image_source"]:
sensor = cls ( * args , self , cuda = True )
else :
sensor = cls ( * args , self , cuda = False )
assert isinstance ( sensor , ImageBuffer ) , " This API is for adding image sensor "
self . sensors [ name ] = sensor
EngineCore . add_image_sensor = add_image_sensor_patched
# we aren't going to use the built-in observation stack, so disable it to save time
def observe_patched ( self , vehicle ) :
return self . state
ImageObservation . observe = observe_patched
def arrive_destination_patch ( self , vehicle ) :
return False
MetaDriveEnv . _is_arrive_destination = arrive_destination_patch
def metadrive_process ( dual_camera : bool , config : dict , camera_array , controls_recv : Connection , state_send : Connection , exit_event ) :
apply_metadrive_patches ( )
road_image = np . frombuffer ( camera_array . get_obj ( ) , dtype = np . uint8 ) . reshape ( ( H , W , 3 ) )
env = MetaDriveEnv ( config )
def reset ( ) :
env . reset ( )
env . vehicle . config [ " max_speed_km_h " ] = 1000
reset ( )
def get_cam_as_rgb ( cam ) :
cam = env . engine . sensors [ cam ]
img = cam . perceive ( env . vehicle , clip = False )
if type ( img ) != np . ndarray :
img = img . get ( ) # convert cupy array to numpy
return img
rk = Ratekeeper ( 100 , None )
steer_ratio = 15
vc = [ 0 , 0 ]
while not exit_event . is_set ( ) :
state = metadrive_state (
velocity = vec3 ( x = float ( env . vehicle . velocity [ 0 ] ) , y = float ( env . vehicle . velocity [ 1 ] ) , z = 0 ) ,
position = env . vehicle . position ,
bearing = float ( math . degrees ( env . vehicle . heading_theta ) ) ,
steering_angle = env . vehicle . steering * env . vehicle . MAX_STEERING
)
state_send . send ( state )
if controls_recv . poll ( 0 ) :
while controls_recv . poll ( 0 ) :
steer_angle , gas , should_reset = controls_recv . recv ( )
steer_metadrive = steer_angle * 1 / ( env . vehicle . MAX_STEERING * steer_ratio )
steer_metadrive = np . clip ( steer_metadrive , - 1 , 1 )
vc = [ steer_metadrive , gas ]
if should_reset :
reset ( )
if rk . frame % 5 == 0 :
obs , _ , terminated , _ , info = env . step ( vc )
if terminated :
reset ( )
#if dual_camera:
# wide_road_image = get_cam_as_rgb("rgb_wide")
road_image [ . . . ] = get_cam_as_rgb ( " rgb_road " )
rk . keep_time ( )