Compare commits

..

44 Commits

Author SHA1 Message Date
discountchubbs f7f9a3efae ci: lfs pointers survive gc 2026-10-18 21:31:16 -07:00
discountchubbs 5d7fb82291 Merge branch 'master' into reimplement-nav 2026-10-18 19:50:10 -07:00
James Vecellio-Grant 6433886a65 Merge branch 'comma-pkl-converter' into reimplement-nav 2026-10-16 10:09:35 -07:00
James Vecellio-Grant 723ebf374e Merge branch 'rebuild-deep-rl' into comma-pkl-converter 2026-10-16 10:09:15 -07:00
James Vecellio-Grant b24f546a0f Merge branch 'master' into rebuild-deep-rl 2026-10-16 10:08:54 -07:00
discountchubbs ddf83be52b Merge remote-tracking branch 'origin/comma-pkl-converter' into reimplement-nav 2026-10-15 20:51:26 -07:00
discountchubbs 3163577bc9 Merge remote-tracking branch 'origin/rebuild-deep-rl' into comma-pkl-converter 2026-10-15 20:50:51 -07:00
James Vecellio-Grant 84fda467b5 caught on new icm comparison tool 2026-10-15 20:49:35 -07:00
discountchubbs 2a84e1481c modeld_v2: prep for nav models 2026-10-15 11:02:26 -07:00
discountchubbs 04a8fb81ab Merge remote-tracking branch 'origin/rebuild-deep-rl' into comma-pkl-converter 2026-10-15 08:15:22 -07:00
discountchubbs 05099ae19c Merge remote-tracking branch 'origin/master' into rebuild-deep-rl 2026-10-15 08:14:23 -07:00
discountchubbs e6d035b639 fix ci 2026-10-14 10:40:10 -07:00
discountchubbs 45bfd88e7e no more fw fetching just use decompress 2026-10-14 10:02:32 -07:00
discountchubbs 86f2e7b255 fw fetch to kernel 2026-10-14 09:53:31 -07:00
discountchubbs eb7a6fc0f8 converter fix 2026-10-14 09:18:40 -07:00
discountchubbs 033ba0d973 pkl warmup 2026-10-14 08:38:18 -07:00
discountchubbs 32460cd5b1 Merge remote-tracking branch 'origin/rebuild-deep-rl' into comma-pkl-converter 2026-10-14 08:10:34 -07:00
discountchubbs 0042016791 conflict res 2026-10-14 08:06:36 -07:00
discountchubbs f6e2fb1c33 Merge remote-tracking branch 'origin/master' into rebuild-deep-rl 2026-10-14 08:04:54 -07:00
James Vecellio-Grant 43cbdc65cd more 2026-10-13 23:32:01 -07:00
discountchubbs 5823cf4f84 lowers chestnut loading to 3ms faster than stock 2026-10-13 23:27:24 -07:00
discountchubbs 023ef9419a one packed contiguous buffer submit 2026-10-13 22:58:19 -07:00
discountchubbs 374659bf43 exec 2026-10-13 20:45:53 -07:00
James Vecellio-Grant 07f755a4c7 Merge branch 'rebuild-deep-rl' into comma-pkl-converter 2026-10-13 20:40:20 -07:00
James Vecellio-Grant f4996a0529 lint 2026-10-13 20:39:15 -07:00
discountchubbs 2f6e2560ea modeld_v2: create a compiled pkl -> gpu kernel artifact converter 2026-10-13 20:36:57 -07:00
James Vecellio-Grant 0414843e2f method() persistent_load 2026-10-13 20:09:00 -07:00
James Vecellio-Grant 5acb9d2c8e whoops 2026-10-13 20:01:23 -07:00
discountchubbs 2bf8f88978 bump 2026-10-13 14:39:33 -07:00
discountchubbs e6e5b1c165 bump tg to upstream tg/tg:master. no rebuild needed 2026-10-13 14:36:10 -07:00
discountchubbs b7d06aa440 publish faster 2026-10-13 11:21:32 -07:00
discountchubbs a9ccd8fedf zed compress 2026-10-13 10:44:41 -07:00
discountchubbs 6220734b2d parallel 2026-10-13 08:56:33 -07:00
discountchubbs f3f7296776 stream chunks for big models to save oom 2026-10-13 08:04:31 -07:00
discountchubbs 9f3a2607ee dedup chestnutty 2026-10-12 23:31:56 -07:00
discountchubbs b4c3a19db1 skip out on op modules 2026-10-12 23:22:02 -07:00
discountchubbs 04098893d9 run as bash: for when i wake up:
these models will fail, look at workflow, likely need env setup now that we use recursion
2026-10-12 23:14:11 -07:00
discountchubbs bc064e892f standin for chestnut linear_compile 2026-10-12 23:09:55 -07:00
discountchubbs be51bc793d 5ms speed up on qcom 2026-10-12 22:36:27 -07:00
discountchubbs f7c65f7d6a lint 2026-10-12 20:55:33 -07:00
discountchubbs bd27f3b54f offroad proc for cache warmup 2026-10-12 19:53:39 -07:00
discountchubbs d7c1827134 new revolution 2026-10-12 17:02:05 -07:00
discountchubbs 1344824746 modeld_v2: shes deeeeeep 2026-10-12 16:34:00 -07:00
discountchubbs 75b5926f4f models: fix qcom float16 overflow 2026-10-09 12:36:31 -07:00
6 changed files with 76 additions and 19 deletions
+9 -10
View File
@@ -33,7 +33,7 @@ jobs:
- name: LFS Fetch - name: LFS Fetch
run: | run: |
git lfs fetch || echo "::warning::some objects are missing on commaai/openpilot-lfs; mirroring the rest" git lfs fetch
- name: Set up Git - name: Set up Git
run: | run: |
@@ -68,7 +68,6 @@ jobs:
git config lfs.activitytimeout 300 git config lfs.activitytimeout 300
git config lfs.transfer.maxretries 5 git config lfs.transfer.maxretries 5
git config lfs.concurrenttransfers 4 git config lfs.concurrenttransfers 4
git config lfs.allowincompletepush true
- name: Push LFS - name: Push LFS
id: sync-and-commit id: sync-and-commit
@@ -109,19 +108,19 @@ jobs:
p = subprocess.Popen(["git", "-C", repo, "cat-file", "--batch=%(objectsize)"], p = subprocess.Popen(["git", "-C", repo, "cat-file", "--batch=%(objectsize)"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE) stdin=subprocess.PIPE, stdout=subprocess.PIPE)
def feed(): def feed():
for sha in small: for sha in small:
p.stdin.write(sha.encode() + b"\n") p.stdin.write(sha.encode() + b"\n")
p.stdin.close() p.stdin.close()
threading.Thread(target=feed, daemon=True).start() threading.Thread(target=feed, daemon=True).start()
rx = re.compile(rb"^version https://git-lfs\.github\.com/spec/v1\noid sha256:([0-9a-f]{64})\nsize ([0-9]+)\n") rx = re.compile(rb"^version https://git-lfs\.github\.com/spec/v1\noid sha256:([0-9a-f]{64})\nsize ([0-9]+)\n")
seen = {} seen = {}
for _ in small: for _ in small:
n = int(p.stdout.readline()); body = p.stdout.read(n); p.stdout.read(1) n = int(p.stdout.readline()); body = p.stdout.read(n); p.stdout.read(1)
m = rx.match(body) m = rx.match(body)
if m: if m:
seen.setdefault(m.group(1).decode(), m.group(2).decode()) seen.setdefault(m.group(1).decode(), m.group(2).decode())
for oid, size in sorted(seen.items()): for oid, size in sorted(seen.items()):
print(oid, size) print(oid, size)
EOF EOF
for repo in . sunnypilot; do for repo in . sunnypilot; do
python3 scan_pointers.py "$repo" python3 scan_pointers.py "$repo"
+1
View File
@@ -9,6 +9,7 @@ os.environ['GMMU'] = '0' # for chestnut fast loading, noop for qcom
os.environ.setdefault('AM_POWER_LIMIT', '100') os.environ.setdefault('AM_POWER_LIMIT', '100')
os.environ.setdefault('AM_PERF_LEVEL', 'high') os.environ.setdefault('AM_PERF_LEVEL', 'high')
from tinygrad.device import Buffer, Device from tinygrad.device import Buffer, Device
from tinygrad.engine.realize import lower_and_compile
from tinygrad.dtype import DType, dtypes from tinygrad.dtype import DType, dtypes
from tinygrad.engine.realize import lower_and_compile from tinygrad.engine.realize import lower_and_compile
from tinygrad.tensor import Tensor from tinygrad.tensor import Tensor
+34
View File
@@ -1,4 +1,7 @@
import time import time
from typing import Any
import numpy as np
def latest_gps_source(sm) -> str | None: def latest_gps_source(sm) -> str | None:
@@ -7,3 +10,34 @@ def latest_gps_source(sm) -> str | None:
sources = [s for s in ('gpsLocation', 'gpsLocationExternal') sources = [s for s in ('gpsLocation', 'gpsLocationExternal')
if sm.valid[s] and sm[s].hasFix and 0 <= now - sm.recv_time[s] < 2] if sm.valid[s] and sm[s].hasFix and 0 <= now - sm.recv_time[s] < 2]
return max(sources, key=lambda s: sm.logMonoTime[s]) if sources else None return max(sources, key=lambda s: sm.logMonoTime[s]) if sources else None
# convert mapbox steps to valhalla enums the model was trained on
VALHALLA_COMMAND_COUNT = 46
VALHALLA_SIDED_TYPES = { # (straight, right, left)
'depart': (1, 2, 3), 'arrive': (4, 5, 6),
'on ramp': (17, 18, 19), 'off ramp': (20, 20, 21), 'fork': (22, 23, 24),
'roundabout': (26, 26, 26), 'rotary': (26, 26, 26), 'roundabout turn': (26, 26, 26),
'exit roundabout': (27, 27, 27), 'exit rotary': (27, 27, 27), 'notification': (28, 28, 28),
}
VALHALLA_TURN_TYPES = {'straight': 8, 'slight right': 9, 'right': 10, 'sharp right': 11, 'uturn': 13,
'sharp left': 14, 'left': 15, 'slight left': 16} # turn, continue, new name, end of road
def valhalla_type(maneuver_type: str, modifier: str) -> int | None:
if maneuver_type == 'merge':
return None # Valhalla gives no maneuver at a merge, so the model never saw one
if maneuver_type in VALHALLA_SIDED_TYPES:
straight, right, left = VALHALLA_SIDED_TYPES[maneuver_type]
return right if 'right' in modifier else left if 'left' in modifier else straight
return VALHALLA_TURN_TYPES.get(modifier, 8)
def navigation_input(maneuvers: Any, traveled: float) -> np.ndarray:
navigation = np.zeros(VALHALLA_COMMAND_COUNT + 1, dtype=np.float32)
for maneuver in maneuvers:
command, distance = valhalla_type(maneuver.type, maneuver.modifier), maneuver.distance - traveled
if command is not None and command > 6 and distance >= 0:
navigation[command], navigation[-1] = 1, distance / 100
break
return navigation
@@ -9,14 +9,16 @@ import itertools
import math import math
from functools import partial from functools import partial
import numpy as np
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
from openpilot.sunnypilot.modeld_v2.helpers import _dtype, read_parts from openpilot.sunnypilot.modeld_v2.helpers import _dtype, read_parts
def pack_layout(shapes: dict[str, tuple], frame_size: int) -> tuple[dict[str, int], int]: def pack_layout(specs: dict[str, tuple], frame_size: int) -> tuple[dict[str, int], int]:
offsets, offset = {}, 0 offsets, offset = {}, 0
for name, shape in ({"tfm": (2, 3, 3)} | shapes).items(): for name, (shape, dtype) in ({"tfm": ((2, 3, 3), np.float32)} | specs).items():
offsets[name], offset = offset, offset + -(-math.prod(shape) * 4 // 128) * 128 offsets[name], offset = offset, offset + -(-math.prod(shape) * np.dtype(dtype).itemsize // 128) * 128
return offsets | {"frames": offset}, offset + 2 * frame_size return offsets | {"frames": offset}, offset + 2 * frame_size
@@ -38,7 +40,7 @@ def frame_part(warp_path: str, parts: dict, extras: dict) -> dict:
return {} return {}
(model, model_blob), (warp, warp_blob) = parts["run"], read_parts(warp_path)[0]["run"] (model, model_blob), (warp, warp_blob) = parts["run"], read_parts(warp_path)[0]["run"]
states = sorted(name for name in extras["input_specs"] if f"next_{name}" in extras["metadata"]["output_shapes"]) states = sorted(name for name in extras["input_specs"] if f"next_{name}" in extras["metadata"]["output_shapes"])
host = {name: shape for name, (shape, _, _) in extras["input_specs"].items() if name not in states and name != "new_img"} host = {name: (shape, dtype) for name, (shape, dtype, _) in extras["input_specs"].items() if name not in states and name != "new_img"}
frame_size = next(s["numel"] for s in warp["inputs"] if s["name"] == "input_frame") // 2 frame_size = next(s["numel"] for s in warp["inputs"] if s["name"] == "input_frame") // 2
offsets, packed = pack_layout(host, frame_size) offsets, packed = pack_layout(host, frame_size)
shift, upload, u8 = len(model_blob), len(model["buffers"]) + len(warp["buffers"]), repr(_dtype("dtypes.uint8")) shift, upload, u8 = len(model_blob), len(model["buffers"]) + len(warp["buffers"]), repr(_dtype("dtypes.uint8"))
@@ -172,12 +172,12 @@ class NativeTinygradAdapter(BaseModelAdapter):
self.input_queues = {name: Tensor(np.zeros(shape, dtype=dtype), device=self.model_device).realize() self.input_queues = {name: Tensor(np.zeros(shape, dtype=dtype), device=self.model_device).realize()
for name, (shape, dtype) in self.input_shapes.items() if name in self.state_pairs} for name, (shape, dtype) in self.input_shapes.items() if name in self.state_pairs}
shapes = {name: shape for name, (shape, _) in self.input_shapes.items() if name not in self.state_pairs and name != 'new_img'} specs = {name: spec for name, spec in self.input_shapes.items() if name not in self.state_pairs and name != 'new_img'}
offsets, packed = pack_layout(shapes, self.warp_frame_size) offsets, packed = pack_layout(specs, self.warp_frame_size)
self.packed_input = np.zeros(packed, dtype=np.uint8) self.packed_input = np.zeros(packed, dtype=np.uint8)
self.host = Tensor(self.packed_input, device='NPY') self.host = Tensor(self.packed_input, device='NPY')
self.numpy_inputs = {name: np.ndarray(shape, dtype=np.float32, buffer=self.packed_input, offset=offsets[name]) self.numpy_inputs = {name: np.ndarray(shape, dtype=dtype, buffer=self.packed_input, offset=offsets[name])
for name, shape in ({'tfm': (2, 3, 3)} | shapes).items()} for name, (shape, dtype) in ({'tfm': ((2, 3, 3), np.dtype(np.float32))} | specs).items()}
self.frames = self.packed_input[offsets['frames']:].reshape(2, self.warp_frame_size) self.frames = self.packed_input[offsets['frames']:].reshape(2, self.warp_frame_size)
self.outputs = {name: Tensor(np.zeros(shape, dtype=dtype), device=device).realize() for name, (shape, dtype, device) in self.jits['output_specs'].items()} self.outputs = {name: Tensor(np.zeros(shape, dtype=dtype), device=device).realize() for name, (shape, dtype, device) in self.jits['output_specs'].items()}
+22 -1
View File
@@ -35,6 +35,7 @@ from openpilot.common.transformations.camera import DEVICE_CAMERAS
from openpilot.common.transformations.model import get_warp_matrix from openpilot.common.transformations.model import get_warp_matrix
from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper
from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value
from openpilot.selfdrive.navigation.helpers import navigation_input
from openpilot.selfdrive.modeld.modeld import ChestnutGpuState from openpilot.selfdrive.modeld.modeld import ChestnutGpuState
from openpilot.sunnypilot.modeld_v2.fill_model_msg import fill_model_msg, fill_pose_msg, PublishState, get_curvature_from_output from openpilot.sunnypilot.modeld_v2.fill_model_msg import fill_model_msg, fill_pose_msg, PublishState, get_curvature_from_output
@@ -172,6 +173,9 @@ class ModelState(ModelStateBase):
for key in ('traffic_convention', 'lateral_control_params', 'action_t'): for key in ('traffic_convention', 'lateral_control_params', 'action_t'):
if key in self.numpy_inputs and key in inputs: if key in self.numpy_inputs and key in inputs:
self.numpy_inputs[key][:] = inputs[key] self.numpy_inputs[key][:] = inputs[key]
for name in ('nav_map', 'navigation'):
if name in self.numpy_inputs:
self.numpy_inputs[name][:] = inputs.get(name, 0)
if self.adapter.is_native: if self.adapter.is_native:
for i, key in enumerate(self._vision_input_names): for i, key in enumerate(self._vision_input_names):
@@ -253,6 +257,10 @@ class ModelState(ModelStateBase):
return log.ModelDataV2.Action(desiredCurvature=float(desired_curvature), desiredAcceleration=float(desired_accel), shouldStop=bool(stop)) return log.ModelDataV2.Action(desiredCurvature=float(desired_curvature), desiredAcceleration=float(desired_accel), shouldStop=bool(stop))
def takes_nav(*models) -> bool:
return any(name in m.numpy_inputs for m in models if m is not None for name in ('nav_map', 'navigation'))
def main(demo=False): def main(demo=False):
cloudlog.warning("modeld init") cloudlog.warning("modeld init")
@@ -282,6 +290,7 @@ def main(demo=False):
vipc_client_main_stream = VisionStreamType.VISION_STREAM_WIDE_ROAD if main_wide_camera else VisionStreamType.VISION_STREAM_NARROW_ROAD vipc_client_main_stream = VisionStreamType.VISION_STREAM_WIDE_ROAD if main_wide_camera else VisionStreamType.VISION_STREAM_NARROW_ROAD
vipc_client_main = VisionIpcClient("camerad", vipc_client_main_stream, True) vipc_client_main = VisionIpcClient("camerad", vipc_client_main_stream, True)
vipc_client_extra = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_WIDE_ROAD, False) vipc_client_extra = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_WIDE_ROAD, False)
vipc_client_map = VisionIpcClient("mapsd", VisionStreamType.VISION_STREAM_MAP, True)
cloudlog.warning(f"vision stream set up, main_wide_camera: {main_wide_camera}, use_extra_client: {use_extra_client}") cloudlog.warning(f"vision stream set up, main_wide_camera: {main_wide_camera}, use_extra_client: {use_extra_client}")
while not vipc_client_main.connect(False): while not vipc_client_main.connect(False):
@@ -332,8 +341,9 @@ def main(demo=False):
# messaging # messaging
pub_socks = ["modelV2", "drivingModelData", "cameraOdometry", "modelDataV2SP"] + (["chestnutGpuState"] if CHESTNUT else []) pub_socks = ["modelV2", "drivingModelData", "cameraOdometry", "modelDataV2SP"] + (["chestnutGpuState"] if CHESTNUT else [])
pm = PubMaster(pub_socks) pm = PubMaster(pub_socks)
nav = takes_nav(model, small_model)
sm = SubMaster(["deviceState", "carState", "narrowRoadCameraState", "extrinsicsCalibration", "driverMonitoringState", sm = SubMaster(["deviceState", "carState", "narrowRoadCameraState", "extrinsicsCalibration", "driverMonitoringState",
"carControl", "controlsState", "lateralDelay"]) "carControl", "controlsState", "lateralDelay"] + (["navInstruction"] if nav else []))
publish_state = PublishState() publish_state = PublishState()
chestnut_state = ChestnutGpuState(pm, model.chestnut) if CHESTNUT else None chestnut_state = ChestnutGpuState(pm, model.chestnut) if CHESTNUT else None
@@ -366,6 +376,7 @@ def main(demo=False):
DH = DesireHelper() DH = DesireHelper()
meta_constants = load_meta_constants() meta_constants = load_meta_constants()
RELC = RoadEdgeLaneChangeController() RELC = RoadEdgeLaneChangeController()
nav_map, nav_map_time = None, 0.
while True: while True:
# Keep receiving frames until we are at least 1 frame ahead of previous extra frame # Keep receiving frames until we are at least 1 frame ahead of previous extra frame
@@ -455,6 +466,16 @@ def main(demo=False):
if 'action_t' in model.numpy_inputs: if 'action_t' in model.numpy_inputs:
inputs['action_t'] = np.array([lat_action_t, long_action_t], dtype=np.float32) inputs['action_t'] = np.array([lat_action_t, long_action_t], dtype=np.float32)
now = time.monotonic()
if nav and (vipc_client_map.is_connected() or vipc_client_map.connect(False)):
if (buf_map := vipc_client_map.recv(0)) is not None:
nav_map = np.frombuffer(buf_map.data, dtype=np.uint8, count=buf_map.width * buf_map.height).reshape(buf_map.height, buf_map.width).copy()
nav_map_time = now
if nav_map is not None and now - nav_map_time < 0.5: # map timeout
inputs['nav_map'] = nav_map
if nav and sm.valid['navInstruction'] and now - sm.recv_time['navInstruction'] < 2:
inputs['navigation'] = navigation_input(sm['navInstruction'].allManeuvers, v_ego * (now - sm.recv_time['navInstruction']))
mt1 = time.perf_counter() mt1 = time.perf_counter()
try: try:
send_chestnut = (chestnut_state is not None and send_chestnut = (chestnut_state is not None and