Files
onepilot/selfdrive/sunnypilot/live_map_data/base_map_data.py
T
2024-07-02 01:20:51 +00:00

107 lines
4.3 KiB
Python

import math
from abc import abstractmethod, ABC
from cereal import custom, messaging
from openpilot.selfdrive.navd.helpers import Coordinate
from openpilot.selfdrive.sunnypilot.live_map_data import get_debug
class BaseMapData(ABC):
def __init__(self):
self._last_gps: Coordinate | None = None
self._gps_sock = None
self._data_type = custom.LiveMapDataSP.DataType.default
self._sub_master = messaging.SubMaster(['liveLocationKalman', 'carControl'])
self._pub_master = messaging.PubMaster(['liveMapDataSP'])
@abstractmethod
def update_location(self, current_location: Coordinate):
pass
@abstractmethod
def get_current_speed_limit(self) -> float:
pass
@abstractmethod
def get_next_speed_limit_and_distance(self) -> (float, float):
pass
@abstractmethod
def get_current_road_name(self) -> str:
pass
def _is_gps_data_valid(self) -> bool:
all_sock_alive = self._sub_master.all_alive(service_list=[self._gps_sock])
all_sock_valid = self._sub_master.all_valid(service_list=[self._gps_sock])
return all_sock_alive and all_sock_valid
def get_current_location(self) -> Coordinate | None:
self._gps_sock = "liveLocationKalman"
if not self._sub_master.updated[self._gps_sock] or not self._sub_master.valid[self._gps_sock]:
return None
_last_gps = self._sub_master[self._gps_sock]
# ignore the message if the fix is invalid
if not _last_gps.positionGeodetic.valid:
return None
kalman_bearing_deg = math.degrees(_last_gps.calibratedOrientationNED.value[2])
kalman_speed = _last_gps.velocityCalibrated.value[2]
kalman_latitude = _last_gps.positionGeodetic.value[0];
kalman_longitude = _last_gps.positionGeodetic.value[1]
result = Coordinate(kalman_latitude, kalman_longitude)
result.annotations['unixTimestampMillis'] = _last_gps.unixTimestampMillis
result.annotations['speed'] = kalman_speed
result.annotations['bearingDeg'] = kalman_bearing_deg
result.annotations['accuracy'] = 1 # Hardcoded since liveLocationKalman does not report this.
result.annotations['bearingAccuracyDeg'] = 1. # you'll need to assign this if available
return result
def get_live_map_data_sp(self, speed_limit, next_speed_limit, next_speed_limit_distance, current_road_name):
last_gps = self.get_current_location()
map_data_msg = messaging.new_message('liveMapDataSP')
map_data_msg.valid = self._is_gps_data_valid()
live_map_data = map_data_msg.liveMapDataSP
if last_gps:
live_map_data.lastGpsTimestamp = last_gps.annotations.get('unixTimestampMillis', 0)
live_map_data.lastGpsLatitude = last_gps.latitude
live_map_data.lastGpsLongitude = last_gps.longitude
live_map_data.lastGpsSpeed = last_gps.annotations.get('speed', 0)
live_map_data.lastGpsBearingDeg = last_gps.annotations.get('bearingDeg', 0)
live_map_data.lastGpsAccuracy = last_gps.annotations.get('accuracy', 0)
live_map_data.lastGpsBearingAccuracyDeg = last_gps.annotations.get('bearingAccuracyDeg', 0)
live_map_data.speedLimitValid = bool(speed_limit > 0)
live_map_data.speedLimit = speed_limit
live_map_data.speedLimitAheadValid = bool(next_speed_limit > 0)
live_map_data.speedLimitAhead = float(next_speed_limit)
live_map_data.speedLimitAheadDistance = float(next_speed_limit_distance)
live_map_data.currentRoadName = str(current_road_name)
live_map_data.dataType = self._data_type
return map_data_msg
def publish(self):
speed_limit = self.get_current_speed_limit()
current_road_name = self.get_current_road_name()
next_speed_limit, next_speed_limit_distance = self.get_next_speed_limit_and_distance()
live_map_data_sp = self.get_live_map_data_sp(
speed_limit,
next_speed_limit,
next_speed_limit_distance,
current_road_name
)
self._pub_master.send('liveMapDataSP', live_map_data_sp)
get_debug(f"SRC: [{self.__class__.__name__}] | SLC: [{speed_limit}] | NSL: [{next_speed_limit}] | NSLD: [{next_speed_limit_distance}] | CRN: [{current_road_name}] | GPS: [{self._last_gps}] Annotations: [{', '.join(f'{key}: {value}' for key, value in self._last_gps.annotations.items()) if self._last_gps else []}]")
def tick(self):
self._sub_master.update()
self._last_gps = self.get_current_location()
self.update_location(self._last_gps)
self.publish()