camerad.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import numpy as np
  2. import os
  3. import pyopencl as cl
  4. import pyopencl.array as cl_array
  5. from msgq.visionipc import VisionIpcServer, VisionStreamType
  6. from cereal import messaging
  7. from openpilot.common.basedir import BASEDIR
  8. from openpilot.tools.sim.lib.common import W, H
  9. class Camerad:
  10. """Simulates the camerad daemon"""
  11. def __init__(self, dual_camera):
  12. self.pm = messaging.PubMaster(['roadCameraState', 'wideRoadCameraState'])
  13. self.frame_road_id = 0
  14. self.frame_wide_id = 0
  15. self.vipc_server = VisionIpcServer("camerad")
  16. self.vipc_server.create_buffers(VisionStreamType.VISION_STREAM_ROAD, 5, False, W, H)
  17. if dual_camera:
  18. self.vipc_server.create_buffers(VisionStreamType.VISION_STREAM_WIDE_ROAD, 5, False, W, H)
  19. self.vipc_server.start_listener()
  20. # set up for pyopencl rgb to yuv conversion
  21. self.ctx = cl.create_some_context()
  22. self.queue = cl.CommandQueue(self.ctx)
  23. 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 "
  24. kernel_fn = os.path.join(BASEDIR, "tools/sim/rgb_to_nv12.cl")
  25. with open(kernel_fn) as f:
  26. prg = cl.Program(self.ctx, f.read()).build(cl_arg)
  27. self.krnl = prg.rgb_to_nv12
  28. self.Wdiv4 = W // 4 if (W % 4 == 0) else (W + (4 - W % 4)) // 4
  29. self.Hdiv4 = H // 4 if (H % 4 == 0) else (H + (4 - H % 4)) // 4
  30. def cam_send_yuv_road(self, yuv):
  31. self._send_yuv(yuv, self.frame_road_id, 'roadCameraState', VisionStreamType.VISION_STREAM_ROAD)
  32. self.frame_road_id += 1
  33. def cam_send_yuv_wide_road(self, yuv):
  34. self._send_yuv(yuv, self.frame_wide_id, 'wideRoadCameraState', VisionStreamType.VISION_STREAM_WIDE_ROAD)
  35. self.frame_wide_id += 1
  36. # Returns: yuv bytes
  37. def rgb_to_yuv(self, rgb):
  38. assert rgb.shape == (H, W, 3), f"{rgb.shape}"
  39. assert rgb.dtype == np.uint8
  40. rgb_cl = cl_array.to_device(self.queue, rgb)
  41. yuv_cl = cl_array.empty_like(rgb_cl)
  42. self.krnl(self.queue, (self.Wdiv4, self.Hdiv4), None, rgb_cl.data, yuv_cl.data).wait()
  43. yuv = np.resize(yuv_cl.get(), rgb.size // 2)
  44. return yuv.data.tobytes()
  45. def _send_yuv(self, yuv, frame_id, pub_type, yuv_type):
  46. eof = int(frame_id * 0.05 * 1e9)
  47. self.vipc_server.send(yuv_type, yuv, frame_id, eof, eof)
  48. dat = messaging.new_message(pub_type, valid=True)
  49. msg = {
  50. "frameId": frame_id,
  51. "transform": [1.0, 0.0, 0.0,
  52. 0.0, 1.0, 0.0,
  53. 0.0, 0.0, 1.0]
  54. }
  55. setattr(dat, pub_type, msg)
  56. self.pm.send(pub_type, dat)