mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-22 08:53:55 +08:00
* WIP try modeld all in python
* fix plan
* add lane lines stds
* fix lane lines prob
* add lead prob
* add meta
* simplify plan parsing
* add hard brake pred
* add confidence
* fix desire state and desire pred
* check this file for now
* rm prints
* rm debug
* add todos
* add plan_t_idxs
* same as cpp
* removed cython
* add wfd width - rm cpp code
* add new files rm old files
* get metadata at compile time
* forgot this file
* now uses more CPU
* not used
* update readme
* lint
* copy this too
* simplify disengage probs
* update model replay ref commit
* update again
* confidence: remove if statemens
* use publish_state.enqueue
* Revert "use publish_state.enqueue"
This reverts commit d8807c8348338a1f773a8de00fd796abb8181404.
* confidence: better shape defs
* use ModelConstants class
* fix confidence
* Parser
* slightly more power too
* no inline ifs :(
* confidence: just use if statements
old-commit-hash: cad17b1255
119 lines
4.1 KiB
Python
Executable File
119 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import gc
|
|
import math
|
|
import time
|
|
import ctypes
|
|
import numpy as np
|
|
from pathlib import Path
|
|
from typing import Tuple, Dict
|
|
|
|
from cereal import messaging
|
|
from cereal.messaging import PubMaster, SubMaster
|
|
from cereal.visionipc import VisionIpcClient, VisionStreamType
|
|
from openpilot.system.swaglog import cloudlog
|
|
from openpilot.common.params import Params
|
|
from openpilot.common.realtime import set_realtime_priority
|
|
from openpilot.selfdrive.modeld.constants import ModelConstants
|
|
from openpilot.selfdrive.modeld.runners import ModelRunner, Runtime
|
|
|
|
NAV_INPUT_SIZE = 256*256
|
|
NAV_FEATURE_LEN = 256
|
|
NAV_DESIRE_LEN = 32
|
|
NAV_OUTPUT_SIZE = 2*2*ModelConstants.IDX_N + NAV_DESIRE_LEN + NAV_FEATURE_LEN
|
|
MODEL_PATHS = {
|
|
ModelRunner.SNPE: Path(__file__).parent / 'models/navmodel_q.dlc',
|
|
ModelRunner.ONNX: Path(__file__).parent / 'models/navmodel.onnx'}
|
|
|
|
class NavModelOutputXY(ctypes.Structure):
|
|
_fields_ = [
|
|
("x", ctypes.c_float),
|
|
("y", ctypes.c_float)]
|
|
|
|
class NavModelOutputPlan(ctypes.Structure):
|
|
_fields_ = [
|
|
("mean", NavModelOutputXY*ModelConstants.IDX_N),
|
|
("std", NavModelOutputXY*ModelConstants.IDX_N)]
|
|
|
|
class NavModelResult(ctypes.Structure):
|
|
_fields_ = [
|
|
("plan", NavModelOutputPlan),
|
|
("desire_pred", ctypes.c_float*NAV_DESIRE_LEN),
|
|
("features", ctypes.c_float*NAV_FEATURE_LEN)]
|
|
|
|
class ModelState:
|
|
inputs: Dict[str, np.ndarray]
|
|
output: np.ndarray
|
|
model: ModelRunner
|
|
|
|
def __init__(self):
|
|
assert ctypes.sizeof(NavModelResult) == NAV_OUTPUT_SIZE * ctypes.sizeof(ctypes.c_float)
|
|
self.output = np.zeros(NAV_OUTPUT_SIZE, dtype=np.float32)
|
|
self.inputs = {'input_img': np.zeros(NAV_INPUT_SIZE, dtype=np.uint8)}
|
|
self.model = ModelRunner(MODEL_PATHS, self.output, Runtime.DSP, True, None)
|
|
self.model.addInput("input_img", None)
|
|
|
|
def run(self, buf:np.ndarray) -> Tuple[np.ndarray, float]:
|
|
self.inputs['input_img'][:] = buf
|
|
|
|
t1 = time.perf_counter()
|
|
self.model.setInputBuffer("input_img", self.inputs['input_img'].view(np.float32))
|
|
self.model.execute()
|
|
t2 = time.perf_counter()
|
|
return self.output, t2 - t1
|
|
|
|
def get_navmodel_packet(model_output: np.ndarray, valid: bool, frame_id: int, location_ts: int, execution_time: float, dsp_execution_time: float):
|
|
model_result = ctypes.cast(model_output.ctypes.data, ctypes.POINTER(NavModelResult)).contents
|
|
msg = messaging.new_message('navModel')
|
|
msg.valid = valid
|
|
msg.navModel.frameId = frame_id
|
|
msg.navModel.locationMonoTime = location_ts
|
|
msg.navModel.modelExecutionTime = execution_time
|
|
msg.navModel.dspExecutionTime = dsp_execution_time
|
|
msg.navModel.features = model_result.features[:]
|
|
msg.navModel.desirePrediction = model_result.desire_pred[:]
|
|
msg.navModel.position.x = [p.x for p in model_result.plan.mean]
|
|
msg.navModel.position.y = [p.y for p in model_result.plan.mean]
|
|
msg.navModel.position.xStd = [math.exp(p.x) for p in model_result.plan.std]
|
|
msg.navModel.position.yStd = [math.exp(p.y) for p in model_result.plan.std]
|
|
return msg
|
|
|
|
|
|
def main():
|
|
gc.disable()
|
|
set_realtime_priority(1)
|
|
|
|
# there exists a race condition when two processes try to create a
|
|
# SNPE model runner at the same time, wait for dmonitoringmodeld to finish
|
|
cloudlog.warning("waiting for dmonitoringmodeld to initialize")
|
|
if not Params().get_bool("DmModelInitialized", True):
|
|
return
|
|
|
|
model = ModelState()
|
|
cloudlog.warning("models loaded, navmodeld starting")
|
|
|
|
vipc_client = VisionIpcClient("navd", VisionStreamType.VISION_STREAM_MAP, True)
|
|
while not vipc_client.connect(False):
|
|
time.sleep(0.1)
|
|
assert vipc_client.is_connected()
|
|
cloudlog.warning(f"connected with buffer size: {vipc_client.buffer_len}")
|
|
|
|
sm = SubMaster(["navInstruction"])
|
|
pm = PubMaster(["navModel"])
|
|
|
|
while True:
|
|
buf = vipc_client.recv()
|
|
if buf is None:
|
|
continue
|
|
|
|
sm.update(0)
|
|
t1 = time.perf_counter()
|
|
model_output, dsp_execution_time = model.run(buf.data[:buf.uv_offset])
|
|
t2 = time.perf_counter()
|
|
|
|
valid = vipc_client.valid and sm.valid["navInstruction"]
|
|
pm.send("navModel", get_navmodel_packet(model_output, valid, vipc_client.frame_id, vipc_client.timestamp_sof, t2 - t1, dsp_execution_time))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|