diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 45a8af0aaf..9e9f6af61d 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,14 +1,11 @@ blank_issues_enabled: false contact_links: + - name: Join the Discord + url: https://discord.comma.ai + about: The community Discord is for both openpilot development and experience discussion - name: Report model bugs - url: https://github.com/commaai/openpilot/discussions/categories/model-feedback - about: Provide feedback for the driving or driver monitoring models - - name: Discussions - url: https://github.com/commaai/openpilot/discussions - about: For questions and general discussion about openpilot + url: https://discord.com/channels/469524606043160576/1254834193066623017 + about: Feedback for the driving and driver monitoring models goes in the #driving-feedback in Discord - name: Community Wiki url: https://github.com/commaai/openpilot/wiki about: Check out our community wiki - - name: Community Discord - url: https://discord.comma.ai - about: Check out our community discord diff --git a/.github/workflows/ui_preview.yaml b/.github/workflows/ui_preview.yaml index bc19e23778..c678abb276 100644 --- a/.github/workflows/ui_preview.yaml +++ b/.github/workflows/ui_preview.yaml @@ -6,6 +6,7 @@ on: - 'master' paths: - 'selfdrive/ui/**' + workflow_dispatch: env: UI_JOB_NAME: "Create UI Report" @@ -78,11 +79,10 @@ jobs: - + - diff --git a/cereal/car.capnp b/cereal/car.capnp index 3df23d9921..cbfb330c22 100644 --- a/cereal/car.capnp +++ b/cereal/car.capnp @@ -196,6 +196,7 @@ struct CarState { accFaulted @42 :Bool; carFaultedNonCritical @47 :Bool; # some ECU is faulted, but car remains controllable espActive @51 :Bool; + vehicleSensorsInvalid @52 :Bool; # invalid steering angle readings, etc. # cruise state cruiseState @10 :CruiseState; diff --git a/selfdrive/car/body/interface.py b/selfdrive/car/body/interface.py index d8d4fdd962..a3dc0a5a04 100644 --- a/selfdrive/car/body/interface.py +++ b/selfdrive/car/body/interface.py @@ -1,6 +1,5 @@ import math -from cereal import car -from openpilot.selfdrive.car import DT_CTRL, get_safety_config, structs +from openpilot.selfdrive.car import get_safety_config, structs from openpilot.selfdrive.car.interfaces import CarInterfaceBase from openpilot.selfdrive.car.body.carstate import CarState from openpilot.selfdrive.car.body.values import SPEED_FROM_RPM @@ -30,12 +29,4 @@ class CarInterface(CarInterfaceBase): def _update(self, c) -> structs.CarState: ret = self.CS.update(self.cp) - # # wait for everything to init first - # if self.frame > int(5. / DT_CTRL): - # # body always wants to enable - # ret.init('events', 1) - # ret.events[0].name = car.CarEvent.EventName.pcmEnable - # ret.events[0].enable = True - # self.frame += 1 - return ret diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py index 2601e7c64b..15a13626c9 100755 --- a/selfdrive/car/card.py +++ b/selfdrive/car/card.py @@ -184,6 +184,12 @@ class Car: # self.events.add_from_msg(CS.events) + if self.CP.notCar: + # wait for everything to init first + if self.sm.frame > int(5. / DT_CTRL) and self.initialized_prev: + # body always wants to enable + self.events.add(EventName.pcmEnable) + # Disable on rising edge of accelerator or brake. Also disable on brake when speed > 0 if (CS.gasPressed and not self.CS_prev.gasPressed and self.disengage_on_accelerator) or \ (CS.brakePressed and (not self.CS_prev.brakePressed or not CS.standstill)) or \ diff --git a/selfdrive/car/ford/carstate.py b/selfdrive/car/ford/carstate.py index fd7f7ad594..f43ce14bec 100644 --- a/selfdrive/car/ford/carstate.py +++ b/selfdrive/car/ford/carstate.py @@ -17,8 +17,6 @@ class CarState(CarStateBase): if CP.transmissionType == TransmissionType.automatic: self.shifter_values = can_define.dv["PowertrainData_10"]["TrnRng_D_Rq"] - self.vehicle_sensors_valid = False - self.prev_distance_button = 0 self.distance_button = 0 @@ -27,7 +25,7 @@ class CarState(CarStateBase): # Occasionally on startup, the ABS module recalibrates the steering pinion offset, so we need to block engagement # The vehicle usually recovers out of this state within a minute of normal driving - self.vehicle_sensors_valid = cp.vl["SteeringPinion_Data"]["StePinCompAnEst_D_Qf"] == 3 + ret.vehicleSensorsInvalid = cp.vl["SteeringPinion_Data"]["StePinCompAnEst_D_Qf"] != 3 # car speed ret.vEgoRaw = cp.vl["BrakeSysFeatures"]["Veh_V_ActlBrk"] * CV.KPH_TO_MS diff --git a/selfdrive/car/ford/interface.py b/selfdrive/car/ford/interface.py index bd1a5e7aca..9ac42e5760 100644 --- a/selfdrive/car/ford/interface.py +++ b/selfdrive/car/ford/interface.py @@ -76,8 +76,6 @@ class CarInterface(CarInterfaceBase): ret.buttonEvents = create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}) events = self.create_common_events(ret, extra_gears=[GearShifter.manumatic]) - if not self.CS.vehicle_sensors_valid: - events.add(car.CarEvent.EventName.vehicleSensorsInvalid) # ret.events = events.to_msg() diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 76c466d00c..eab260a499 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -303,6 +303,8 @@ class CarInterfaceBase(ABC): events.add(EventName.preEnableStandstill) if cs_out.gasPressed: events.add(EventName.gasPressedOverride) + if cs_out.vehicleSensorsInvalid: + events.add(EventName.vehicleSensorsInvalid) # Handle button presses for b in cs_out.buttonEvents: diff --git a/selfdrive/car/mock/carstate.py b/selfdrive/car/mock/carstate.py index ece908b51c..41a298e24e 100644 --- a/selfdrive/car/mock/carstate.py +++ b/selfdrive/car/mock/carstate.py @@ -1,4 +1,7 @@ +from cereal import car from openpilot.selfdrive.car.interfaces import CarStateBase + class CarState(CarStateBase): - pass + def update(self, *args) -> car.CarState: + pass diff --git a/selfdrive/car/toyota/carstate.py b/selfdrive/car/toyota/carstate.py index 6088f89f30..7b1aa66b92 100644 --- a/selfdrive/car/toyota/carstate.py +++ b/selfdrive/car/toyota/carstate.py @@ -111,6 +111,10 @@ class CarState(CarStateBase): ret.steerFaultTemporary = ret.steerFaultTemporary or cp.vl["EPS_STATUS"]["LTA_STATE"] in TEMP_STEER_FAULTS ret.steerFaultPermanent = ret.steerFaultPermanent or cp.vl["EPS_STATUS"]["LTA_STATE"] in PERM_STEER_FAULTS + # Lane Tracing Assist control is unavailable (EPS_STATUS->LTA_STATE=0) until + # the more accurate angle sensor signal is initialized + ret.vehicleSensorsInvalid = not self.accurate_steer_angle_seen + if self.CP.carFingerprint in UNSUPPORTED_DSU_CAR: # TODO: find the bit likely in DSU_CRUISE that describes an ACC fault. one may also exist in CLUTCH ret.cruiseState.available = cp.vl["DSU_CRUISE"]["MAIN_ON"] != 0 diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index e8fcb70309..6bc26a4cbf 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -156,11 +156,6 @@ class CarInterface(CarInterfaceBase): # events events = self.create_common_events(ret) - # Lane Tracing Assist control is unavailable (EPS_STATUS->LTA_STATE=0) until - # the more accurate angle sensor signal is initialized - if self.CP.steerControlType == SteerControlType.angle and not self.CS.accurate_steer_angle_seen: - events.add(EventName.vehicleSensorsInvalid) - if self.CP.openpilotLongitudinalControl: if ret.cruiseState.standstill and not ret.brakePressed: events.add(EventName.resumeRequired) diff --git a/selfdrive/ui/tests/test_ui/run.py b/selfdrive/ui/tests/test_ui/run.py index 0b1d842499..15b97511bc 100644 --- a/selfdrive/ui/tests/test_ui/run.py +++ b/selfdrive/ui/tests/test_ui/run.py @@ -13,7 +13,6 @@ from cereal import messaging, car, log from msgq.visionipc import VisionIpcServer, VisionStreamType from cereal.messaging import SubMaster, PubMaster -from openpilot.common.mock import mock_messages from openpilot.common.params import Params from openpilot.common.realtime import DT_MDL from openpilot.common.transformations.camera import DEVICE_CAMERAS @@ -92,16 +91,8 @@ def setup_onroad(click, pm: PubMaster): pm.send(msg.which(), msg) server.send(cam_meta.stream, IMG_BYTES, cs.frameId, cs.timestampSof, cs.timestampEof) -@mock_messages(['liveLocationKalman']) -def setup_onroad_map(click, pm: PubMaster): - setup_onroad(click, pm) - - click(500, 500) - - time.sleep(UI_DELAY) # give time for the map to render - def setup_onroad_sidebar(click, pm: PubMaster): - setup_onroad_map(click, pm) + setup_onroad(click, pm) click(500, 500) CASES = { @@ -109,7 +100,6 @@ CASES = { "settings_device": setup_settings_device, "settings_network": setup_settings_network, "onroad": setup_onroad, - "onroad_map": setup_onroad_map, "onroad_sidebar": setup_onroad_sidebar } diff --git a/tools/cabana/README.md b/tools/cabana/README.md index dbbdd8020c..27829979c0 100644 --- a/tools/cabana/README.md +++ b/tools/cabana/README.md @@ -96,5 +96,3 @@ cabana ## Additional Information For more information, see the [openpilot wiki](https://github.com/commaai/openpilot/wiki/Cabana) - -If you encounter any issues or have feature requests, please contribute bug reports or discussions at: [new cabana feedback](https://github.com/commaai/openpilot/discussions/26091) \ No newline at end of file diff --git a/tools/lib/filereader.py b/tools/lib/filereader.py index 3bfdc75feb..963d7a8cdb 100644 --- a/tools/lib/filereader.py +++ b/tools/lib/filereader.py @@ -7,10 +7,10 @@ from openpilot.tools.lib.url_file import URLFile DATA_ENDPOINT = os.getenv("DATA_ENDPOINT", "http://data-raw.comma.internal/") -def internal_source_available(): +def internal_source_available(url=DATA_ENDPOINT): try: - hostname = urlparse(DATA_ENDPOINT).hostname - port = urlparse(DATA_ENDPOINT).port or 80 + hostname = urlparse(url).hostname + port = urlparse(url).port or 80 with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s: s.connect((hostname, port)) return True diff --git a/tools/lib/logreader.py b/tools/lib/logreader.py index 2487cb2825..815bd4b796 100755 --- a/tools/lib/logreader.py +++ b/tools/lib/logreader.py @@ -174,6 +174,12 @@ def comma_car_segments_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths: return [get_comma_segments_url(sr.route_name, seg) for seg in sr.seg_idxs] +def testing_closet_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths: + if not internal_source_available('http://testing.comma.life'): + raise InternalUnavailableException + return [f"http://testing.comma.life/download/{sr.route_name.replace('|', '/')}/{seg}/rlog" for seg in sr.seg_idxs] + + def direct_source(file_or_url: str) -> LogPaths: return [file_or_url] @@ -195,7 +201,7 @@ def auto_source(sr: SegmentRange, mode=ReadMode.RLOG) -> LogPaths: if mode == ReadMode.SANITIZED: return comma_car_segments_source(sr, mode) - SOURCES: list[Source] = [internal_source, internal_source_zst, openpilotci_source, comma_api_source, comma_car_segments_source,] + SOURCES: list[Source] = [internal_source, internal_source_zst, openpilotci_source, comma_api_source, comma_car_segments_source, testing_closet_source,] exceptions = {} # for automatic fallback modes, auto_source needs to first check if rlogs exist for any source