|
|
|
@ -1,5 +1,6 @@ |
|
|
|
|
import numpy as np |
|
|
|
|
import pyray as rl |
|
|
|
|
from enum import Enum |
|
|
|
|
|
|
|
|
|
from cereal import messaging, log |
|
|
|
|
from msgq.visionipc import VisionStreamType |
|
|
|
@ -10,8 +11,15 @@ from openpilot.common.transformations.camera import DEVICE_CAMERAS, DeviceCamera |
|
|
|
|
from openpilot.common.transformations.orientation import rot_from_euler |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OpState = log.SelfdriveState.OpenpilotState |
|
|
|
|
CALIBRATED = log.LiveCalibrationData.Status.calibrated |
|
|
|
|
DEFAULT_DEVICE_CAMERA = DEVICE_CAMERAS["tici", "ar0231"] |
|
|
|
|
UI_BORDER_SIZE = 30 |
|
|
|
|
|
|
|
|
|
class BorderStatus(Enum): |
|
|
|
|
DISENGAGED = rl.Color(0x17, 0x33, 0x49, 0xc8) # Blue for disengaged state |
|
|
|
|
OVERRIDE = rl.Color(0x91, 0x9b, 0x95, 0xf1) # Gray for override state |
|
|
|
|
ENGAGED = rl.Color(0x17, 0x86, 0x44, 0xf1) # Green for engaged state |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AugmentedRoadView(CameraView): |
|
|
|
@ -29,6 +37,7 @@ class AugmentedRoadView(CameraView): |
|
|
|
|
self._last_calib_time: float = 0 |
|
|
|
|
self._last_rect_dims = (0.0, 0.0) |
|
|
|
|
self._cached_matrix: np.ndarray | None = None |
|
|
|
|
self._content_rect = rl.Rectangle() |
|
|
|
|
|
|
|
|
|
self.model_renderer = ModelRenderer() |
|
|
|
|
|
|
|
|
@ -36,6 +45,26 @@ class AugmentedRoadView(CameraView): |
|
|
|
|
# Update calibration before rendering |
|
|
|
|
self._update_calibration() |
|
|
|
|
|
|
|
|
|
# Create inner content area with border padding |
|
|
|
|
self._content_rect = rl.Rectangle( |
|
|
|
|
rect.x + UI_BORDER_SIZE, |
|
|
|
|
rect.y + UI_BORDER_SIZE, |
|
|
|
|
rect.width - 2 * UI_BORDER_SIZE, |
|
|
|
|
rect.height - 2 * UI_BORDER_SIZE, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
# Draw colored border based on driving state |
|
|
|
|
self._draw_border(rect) |
|
|
|
|
|
|
|
|
|
# Enable scissor mode to clip all rendering within content rectangle boundaries |
|
|
|
|
# This creates a rendering viewport that prevents graphics from drawing outside the border |
|
|
|
|
rl.begin_scissor_mode( |
|
|
|
|
int(self._content_rect.x), |
|
|
|
|
int(self._content_rect.y), |
|
|
|
|
int(self._content_rect.width), |
|
|
|
|
int(self._content_rect.height) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
# Render the base camera view |
|
|
|
|
super().render(rect) |
|
|
|
|
|
|
|
|
@ -44,7 +73,21 @@ class AugmentedRoadView(CameraView): |
|
|
|
|
# - Path prediction |
|
|
|
|
# - Lead vehicle indicators |
|
|
|
|
# - Additional features |
|
|
|
|
self.model_renderer.draw(rect, self.sm) |
|
|
|
|
self.model_renderer.draw(self._content_rect, self.sm) |
|
|
|
|
|
|
|
|
|
# End clipping region |
|
|
|
|
rl.end_scissor_mode() |
|
|
|
|
|
|
|
|
|
def _draw_border(self, rect: rl.Rectangle): |
|
|
|
|
state = self.sm["selfdriveState"] |
|
|
|
|
if state.state in (OpState.preEnabled, OpState.overriding): |
|
|
|
|
status = BorderStatus.OVERRIDE |
|
|
|
|
elif state.enabled: |
|
|
|
|
status = BorderStatus.ENGAGED |
|
|
|
|
else: |
|
|
|
|
status = BorderStatus.DISENGAGED |
|
|
|
|
|
|
|
|
|
rl.draw_rectangle_lines_ex(rect, UI_BORDER_SIZE, status.value) |
|
|
|
|
|
|
|
|
|
def _update_calibration(self): |
|
|
|
|
# Update device camera if not already set |
|
|
|
@ -71,7 +114,7 @@ class AugmentedRoadView(CameraView): |
|
|
|
|
def _calc_frame_matrix(self, rect: rl.Rectangle) -> np.ndarray: |
|
|
|
|
# Check if we can use cached matrix |
|
|
|
|
calib_time = self.sm.recv_frame.get('liveCalibration', 0) |
|
|
|
|
current_dims = (rect.width, rect.height) |
|
|
|
|
current_dims = (self._content_rect.width, self._content_rect.height) |
|
|
|
|
if (self._last_calib_time == calib_time and |
|
|
|
|
self._last_rect_dims == current_dims and |
|
|
|
|
self._cached_matrix is not None): |
|
|
|
@ -89,7 +132,8 @@ class AugmentedRoadView(CameraView): |
|
|
|
|
kep = calib_transform @ inf_point |
|
|
|
|
|
|
|
|
|
# Calculate center points and dimensions |
|
|
|
|
w, h = current_dims |
|
|
|
|
x, y = self._content_rect.x, self._content_rect.y |
|
|
|
|
w, h = self._content_rect.width, self._content_rect.height |
|
|
|
|
cx, cy = intrinsic[0, 2], intrinsic[1, 2] |
|
|
|
|
|
|
|
|
|
# Calculate max allowed offsets with margins |
|
|
|
@ -117,8 +161,8 @@ class AugmentedRoadView(CameraView): |
|
|
|
|
]) |
|
|
|
|
|
|
|
|
|
video_transform = np.array([ |
|
|
|
|
[zoom, 0.0, (w / 2 - x_offset) - (cx * zoom)], |
|
|
|
|
[0.0, zoom, (h / 2 - y_offset) - (cy * zoom)], |
|
|
|
|
[zoom, 0.0, (w / 2 + x - x_offset) - (cx * zoom)], |
|
|
|
|
[0.0, zoom, (h / 2 + y - y_offset) - (cy * zoom)], |
|
|
|
|
[0.0, 0.0, 1.0] |
|
|
|
|
]) |
|
|
|
|
self.model_renderer.set_transform(video_transform @ calib_transform) |
|
|
|
|