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