|
|
|
@ -6,6 +6,7 @@ import time |
|
|
|
|
import ctypes |
|
|
|
|
import numpy as np |
|
|
|
|
from pathlib import Path |
|
|
|
|
from setproctitle import setproctitle |
|
|
|
|
|
|
|
|
|
from cereal import messaging |
|
|
|
|
from cereal.messaging import PubMaster, SubMaster |
|
|
|
@ -14,16 +15,19 @@ from openpilot.common.swaglog import cloudlog |
|
|
|
|
from openpilot.common.params import Params |
|
|
|
|
from openpilot.common.realtime import set_realtime_priority |
|
|
|
|
from openpilot.selfdrive.modeld.runners import ModelRunner, Runtime |
|
|
|
|
from openpilot.selfdrive.modeld.models.commonmodel_pyx import CLContext |
|
|
|
|
from openpilot.selfdrive.modeld.parse_model_outputs import sigmoid |
|
|
|
|
|
|
|
|
|
CALIB_LEN = 3 |
|
|
|
|
REG_SCALE = 0.25 |
|
|
|
|
MODEL_WIDTH = 1440 |
|
|
|
|
MODEL_HEIGHT = 960 |
|
|
|
|
OUTPUT_SIZE = 84 |
|
|
|
|
FEATURE_LEN = 512 |
|
|
|
|
OUTPUT_SIZE = 84 + FEATURE_LEN |
|
|
|
|
|
|
|
|
|
PROCESS_NAME = "selfdrive.modeld.dmonitoringmodeld" |
|
|
|
|
SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') |
|
|
|
|
MODEL_PATHS = { |
|
|
|
|
ModelRunner.SNPE: Path(__file__).parent / 'models/dmonitoring_model_q.dlc', |
|
|
|
|
ModelRunner.THNEED: Path(__file__).parent / 'models/dmonitoring_model.thneed', |
|
|
|
|
ModelRunner.ONNX: Path(__file__).parent / 'models/dmonitoring_model.onnx'} |
|
|
|
|
|
|
|
|
|
class DriverStateResult(ctypes.Structure): |
|
|
|
@ -49,21 +53,22 @@ class DMonitoringModelResult(ctypes.Structure): |
|
|
|
|
("driver_state_lhd", DriverStateResult), |
|
|
|
|
("driver_state_rhd", DriverStateResult), |
|
|
|
|
("poor_vision_prob", ctypes.c_float), |
|
|
|
|
("wheel_on_right_prob", ctypes.c_float)] |
|
|
|
|
("wheel_on_right_prob", ctypes.c_float), |
|
|
|
|
("features", ctypes.c_float*FEATURE_LEN)] |
|
|
|
|
|
|
|
|
|
class ModelState: |
|
|
|
|
inputs: dict[str, np.ndarray] |
|
|
|
|
output: np.ndarray |
|
|
|
|
model: ModelRunner |
|
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
|
def __init__(self, cl_ctx): |
|
|
|
|
assert ctypes.sizeof(DMonitoringModelResult) == OUTPUT_SIZE * ctypes.sizeof(ctypes.c_float) |
|
|
|
|
self.output = np.zeros(OUTPUT_SIZE, dtype=np.float32) |
|
|
|
|
self.inputs = { |
|
|
|
|
'input_img': np.zeros(MODEL_HEIGHT * MODEL_WIDTH, dtype=np.uint8), |
|
|
|
|
'calib': np.zeros(CALIB_LEN, dtype=np.float32)} |
|
|
|
|
|
|
|
|
|
self.model = ModelRunner(MODEL_PATHS, self.output, Runtime.DSP, True, None) |
|
|
|
|
self.model = ModelRunner(MODEL_PATHS, self.output, Runtime.GPU, False, cl_ctx) |
|
|
|
|
self.model.addInput("input_img", None) |
|
|
|
|
self.model.addInput("calib", self.inputs['calib']) |
|
|
|
|
|
|
|
|
@ -76,17 +81,17 @@ class ModelState: |
|
|
|
|
input_data = self.inputs['input_img'].reshape(MODEL_HEIGHT, MODEL_WIDTH) |
|
|
|
|
input_data[:] = buf_data[v_offset:v_offset+MODEL_HEIGHT, h_offset:h_offset+MODEL_WIDTH] |
|
|
|
|
|
|
|
|
|
t1 = time.perf_counter() |
|
|
|
|
self.model.setInputBuffer("input_img", self.inputs['input_img'].view(np.float32)) |
|
|
|
|
t1 = time.perf_counter() |
|
|
|
|
self.model.execute() |
|
|
|
|
t2 = time.perf_counter() |
|
|
|
|
return self.output, t2 - t1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fill_driver_state(msg, ds_result: DriverStateResult): |
|
|
|
|
msg.faceOrientation = [x * REG_SCALE for x in ds_result.face_orientation] |
|
|
|
|
msg.faceOrientation = list(ds_result.face_orientation) |
|
|
|
|
msg.faceOrientationStd = [math.exp(x) for x in ds_result.face_orientation_std] |
|
|
|
|
msg.facePosition = [x * REG_SCALE for x in ds_result.face_position[:2]] |
|
|
|
|
msg.facePosition = list(ds_result.face_position[:2]) |
|
|
|
|
msg.facePositionStd = [math.exp(x) for x in ds_result.face_position_std[:2]] |
|
|
|
|
msg.faceProb = float(sigmoid(ds_result.face_prob)) |
|
|
|
|
msg.leftEyeProb = float(sigmoid(ds_result.left_eye_prob)) |
|
|
|
@ -98,13 +103,13 @@ def fill_driver_state(msg, ds_result: DriverStateResult): |
|
|
|
|
msg.readyProb = [float(sigmoid(x)) for x in ds_result.ready_prob] |
|
|
|
|
msg.notReadyProb = [float(sigmoid(x)) for x in ds_result.not_ready_prob] |
|
|
|
|
|
|
|
|
|
def get_driverstate_packet(model_output: np.ndarray, frame_id: int, location_ts: int, execution_time: float, dsp_execution_time: float): |
|
|
|
|
def get_driverstate_packet(model_output: np.ndarray, frame_id: int, location_ts: int, execution_time: float, gpu_execution_time: float): |
|
|
|
|
model_result = ctypes.cast(model_output.ctypes.data, ctypes.POINTER(DMonitoringModelResult)).contents |
|
|
|
|
msg = messaging.new_message('driverStateV2', valid=True) |
|
|
|
|
ds = msg.driverStateV2 |
|
|
|
|
ds.frameId = frame_id |
|
|
|
|
ds.modelExecutionTime = execution_time |
|
|
|
|
ds.dspExecutionTime = dsp_execution_time |
|
|
|
|
ds.gpuExecutionTime = gpu_execution_time |
|
|
|
|
ds.poorVisionProb = float(sigmoid(model_result.poor_vision_prob)) |
|
|
|
|
ds.wheelOnRightProb = float(sigmoid(model_result.wheel_on_right_prob)) |
|
|
|
|
ds.rawPredictions = model_output.tobytes() if SEND_RAW_PRED else b'' |
|
|
|
@ -115,14 +120,16 @@ def get_driverstate_packet(model_output: np.ndarray, frame_id: int, location_ts: |
|
|
|
|
|
|
|
|
|
def main(): |
|
|
|
|
gc.disable() |
|
|
|
|
setproctitle(PROCESS_NAME) |
|
|
|
|
set_realtime_priority(1) |
|
|
|
|
|
|
|
|
|
model = ModelState() |
|
|
|
|
cl_context = CLContext() |
|
|
|
|
model = ModelState(cl_context) |
|
|
|
|
cloudlog.warning("models loaded, dmonitoringmodeld starting") |
|
|
|
|
Params().put_bool("DmModelInitialized", True) |
|
|
|
|
|
|
|
|
|
cloudlog.warning("connecting to driver stream") |
|
|
|
|
vipc_client = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_DRIVER, True) |
|
|
|
|
vipc_client = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_DRIVER, True, cl_context) |
|
|
|
|
while not vipc_client.connect(False): |
|
|
|
|
time.sleep(0.1) |
|
|
|
|
assert vipc_client.is_connected() |
|
|
|
@ -144,10 +151,10 @@ def main(): |
|
|
|
|
calib[:] = np.array(sm["liveCalibration"].rpyCalib) |
|
|
|
|
|
|
|
|
|
t1 = time.perf_counter() |
|
|
|
|
model_output, dsp_execution_time = model.run(buf, calib) |
|
|
|
|
model_output, gpu_execution_time = model.run(buf, calib) |
|
|
|
|
t2 = time.perf_counter() |
|
|
|
|
|
|
|
|
|
pm.send("driverStateV2", get_driverstate_packet(model_output, vipc_client.frame_id, vipc_client.timestamp_sof, t2 - t1, dsp_execution_time)) |
|
|
|
|
pm.send("driverStateV2", get_driverstate_packet(model_output, vipc_client.frame_id, vipc_client.timestamp_sof, t2 - t1, gpu_execution_time)) |
|
|
|
|
# print("dmonitoring process: %.2fms, from last %.2fms\n" % (t2 - t1, t1 - last)) |
|
|
|
|
# last = t1 |
|
|
|
|
|
|
|
|
|