mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-10-20 03:03:46 +08:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f7f9a3efae | |||
| 5d7fb82291 | |||
| 6433886a65 | |||
| 723ebf374e | |||
| b24f546a0f | |||
| ddf83be52b | |||
| 3163577bc9 | |||
| 84fda467b5 | |||
| 2a84e1481c | |||
| 04a8fb81ab | |||
| 05099ae19c | |||
| e6d035b639 | |||
| 45bfd88e7e | |||
| 86f2e7b255 | |||
| eb7a6fc0f8 | |||
| 033ba0d973 | |||
| 32460cd5b1 | |||
| 0042016791 | |||
| f6e2fb1c33 | |||
| 43cbdc65cd | |||
| 5823cf4f84 | |||
| 023ef9419a | |||
| 374659bf43 | |||
| 07f755a4c7 | |||
| f4996a0529 | |||
| 2f6e2560ea | |||
| 0414843e2f | |||
| 5acb9d2c8e | |||
| 2bf8f88978 | |||
| e6e5b1c165 | |||
| b7d06aa440 | |||
| a9ccd8fedf | |||
| 6220734b2d | |||
| f3f7296776 | |||
| 9f3a2607ee | |||
| b4c3a19db1 | |||
| 04098893d9 | |||
| bc064e892f | |||
| be51bc793d | |||
| f7c65f7d6a | |||
| bd27f3b54f | |||
| d7c1827134 | |||
| 1344824746 | |||
| 75b5926f4f |
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user