import numpy as np
import os
import pyopencl as cl
import pyopencl . array as cl_array
from cereal . visionipc import VisionIpcServer , VisionStreamType
from cereal import messaging
from openpilot . common . basedir import BASEDIR
from openpilot . tools . sim . lib . common import W , H
class Camerad :
""" Simulates the camerad daemon """
def __init__ ( self , dual_camera ) :
self . pm = messaging . PubMaster ( [ ' roadCameraState ' , ' wideRoadCameraState ' ] )
self . frame_road_id = 0
self . frame_wide_id = 0
self . vipc_server = VisionIpcServer ( " camerad " )
self . vipc_server . create_buffers ( VisionStreamType . VISION_STREAM_ROAD , 5 , False , W , H )
if dual_camera :
self . vipc_server . create_buffers ( VisionStreamType . VISION_STREAM_WIDE_ROAD , 5 , False , W , H )
self . vipc_server . start_listener ( )
# set up for pyopencl rgb to yuv conversion
self . ctx = cl . create_some_context ( )
self . queue = cl . CommandQueue ( self . ctx )
cl_arg = f " -DHEIGHT= { H } -DWIDTH= { W } -DRGB_STRIDE= { W * 3 } -DUV_WIDTH= { W / / 2 } -DUV_HEIGHT= { H / / 2 } -DRGB_SIZE= { W * H } -DCL_DEBUG "
kernel_fn = os . path . join ( BASEDIR , " tools/sim/rgb_to_nv12.cl " )
with open ( kernel_fn ) as f :
prg = cl . Program ( self . ctx , f . read ( ) ) . build ( cl_arg )
self . krnl = prg . rgb_to_nv12
self . Wdiv4 = W / / 4 if ( W % 4 == 0 ) else ( W + ( 4 - W % 4 ) ) / / 4
self . Hdiv4 = H / / 4 if ( H % 4 == 0 ) else ( H + ( 4 - H % 4 ) ) / / 4
def cam_send_yuv_road ( self , yuv ) :
self . _send_yuv ( yuv , self . frame_road_id , ' roadCameraState ' , VisionStreamType . VISION_STREAM_ROAD )
self . frame_road_id + = 1
def cam_send_yuv_wide_road ( self , yuv ) :
self . _send_yuv ( yuv , self . frame_wide_id , ' wideRoadCameraState ' , VisionStreamType . VISION_STREAM_WIDE_ROAD )
self . frame_wide_id + = 1
# Returns: yuv bytes
def rgb_to_yuv ( self , rgb ) :
assert rgb . shape == ( H , W , 3 ) , f " { rgb . shape } "
assert rgb . dtype == np . uint8
rgb_cl = cl_array . to_device ( self . queue , rgb )
yuv_cl = cl_array . empty_like ( rgb_cl )
self . krnl ( self . queue , ( self . Wdiv4 , self . Hdiv4 ) , None , rgb_cl . data , yuv_cl . data ) . wait ( )
yuv = np . resize ( yuv_cl . get ( ) , rgb . size / / 2 )
return yuv . data . tobytes ( )
def _send_yuv ( self , yuv , frame_id , pub_type , yuv_type ) :
eof = int ( frame_id * 0.05 * 1e9 )
self . vipc_server . send ( yuv_type , yuv , frame_id , eof , eof )
dat = messaging . new_message ( pub_type , valid = True )
msg = {
" frameId " : frame_id ,
" transform " : [ 1.0 , 0.0 , 0.0 ,
0.0 , 1.0 , 0.0 ,
0.0 , 0.0 , 1.0 ]
}
setattr ( dat , pub_type , msg )
self . pm . send ( pub_type , dat )