diff --git a/opendbc_repo/opendbc/car/torque_data/substitute.toml b/opendbc_repo/opendbc/car/torque_data/substitute.toml index df3fa8d4a..9f67cac72 100644 --- a/opendbc_repo/opendbc/car/torque_data/substitute.toml +++ b/opendbc_repo/opendbc/car/torque_data/substitute.toml @@ -96,6 +96,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] "CADILLAC_CT6_CC" = "CHEVROLET_VOLT" "CADILLAC_XT5_CC" = "GMC_ACADIA" +"BUICK_BABYENCLAVE" = "GMC_ACADIA" "CHEVROLET_EQUINOX_CC" = "CHEVROLET_EQUINOX" "GMC_YUKON_CC" = "CHEVROLET_SILVERADO" "CHEVROLET_TRAILBLAZER_CC" = "CHEVROLET_TRAILBLAZER" diff --git a/opendbc_repo/opendbc/car/toyota/carcontroller.py b/opendbc_repo/opendbc/car/toyota/carcontroller.py index c79b5e34f..b3f94e64d 100644 --- a/opendbc_repo/opendbc/car/toyota/carcontroller.py +++ b/opendbc_repo/opendbc/car/toyota/carcontroller.py @@ -49,7 +49,7 @@ def get_long_tune(CP, params): k_f = 1.0 if CP.carFingerprint == CAR.TOYOTA_PRIUS: - k_f = 0.4 + k_f = 0.7 elif CP.carFingerprint not in TSS2_CAR: kiBP = [0., 5., 35.] kiV = [3.6, 2.4, 1.5] diff --git a/panda/board/obj/gitversion.h b/panda/board/obj/gitversion.h index b0dcbb6bb..bce1bd4a4 100644 --- a/panda/board/obj/gitversion.h +++ b/panda/board/obj/gitversion.h @@ -1,2 +1,2 @@ extern const uint8_t gitversion[19]; -const uint8_t gitversion[19] = "DEV-e0cf4fd9-DEBUG"; +const uint8_t gitversion[19] = "DEV-7ceb47eb-DEBUG"; diff --git a/panda/board/obj/version b/panda/board/obj/version index 1d14da961..2c9480331 100644 --- a/panda/board/obj/version +++ b/panda/board/obj/version @@ -1 +1 @@ -DEV-e0cf4fd9-DEBUG \ No newline at end of file +DEV-7ceb47eb-DEBUG \ No newline at end of file diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py index 1f118e7e8..b62d444b5 100644 --- a/selfdrive/ui/soundd.py +++ b/selfdrive/ui/soundd.py @@ -249,6 +249,25 @@ class Soundd: sd._initialize() return sd.OutputStream(channels=1, samplerate=SAMPLE_RATE, callback=self.callback, blocksize=SAMPLE_BUFFER) + def start_stream(self, sd): + stream = self.get_stream(sd) + stream.start() + cloudlog.info(f"soundd stream started: {stream.samplerate=} {stream.channels=} {stream.dtype=} {stream.device=}, {stream.blocksize=}") + return stream + + def describe_stream(self, stream) -> str: + attrs = { + "active": getattr(stream, "active", None), + "stopped": getattr(stream, "stopped", None), + "closed": getattr(stream, "closed", None), + "samplerate": getattr(stream, "samplerate", None), + "channels": getattr(stream, "channels", None), + "dtype": getattr(stream, "dtype", None), + "device": getattr(stream, "device", None), + "blocksize": getattr(stream, "blocksize", None), + } + return " ".join(f"{k}={v!r}" for k, v in attrs.items()) + def soundd_thread(self): # sounddevice must be imported after forking processes import sounddevice as sd @@ -257,39 +276,51 @@ class Soundd: sm = sm.extend(['starpilotSelfdriveState', 'starpilotPlan']) - with self.get_stream(sd) as stream: - rk = Ratekeeper(20) + while True: + stream = None + try: + stream = self.start_stream(sd) + rk = Ratekeeper(20) - cloudlog.info(f"soundd stream started: {stream.samplerate=} {stream.channels=} {stream.dtype=} {stream.device=}, {stream.blocksize=}") - while True: - sm.update(0) + while True: + sm.update(0) - if sm.updated['soundPressure'] and self.current_alert == AudibleAlert.none: # only update volume filter when not playing alert - self.spl_filter_weighted.update(sm["soundPressure"].soundPressureWeightedDb) - self.current_volume = self.calculate_volume(float(self.spl_filter_weighted.x)) + if sm.updated['soundPressure'] and self.current_alert == AudibleAlert.none: # only update volume filter when not playing alert + self.spl_filter_weighted.update(sm["soundPressure"].soundPressureWeightedDb) + self.current_volume = self.calculate_volume(float(self.spl_filter_weighted.x)) - if self.starpilot_toggles.alert_volume_controller: - self.auto_volume = self.current_volume - self.current_volume = 0.0 + if self.starpilot_toggles.alert_volume_controller: + self.auto_volume = self.current_volume + self.current_volume = 0.0 - elif self.current_alert != AudibleAlert.none and self.starpilot_toggles.alert_volume_controller: - self.current_volume = self.get_volume_override() - if self.current_volume == 1.01: - self.current_volume = self.auto_volume + elif self.current_alert != AudibleAlert.none and self.starpilot_toggles.alert_volume_controller: + self.current_volume = self.get_volume_override() + if self.current_volume == 1.01: + self.current_volume = self.auto_volume - self.get_audible_alert(sm) + self.get_audible_alert(sm) - rk.keep_time() + rk.keep_time() - assert stream.active + if not stream.active: + raise RuntimeError(f"soundd stream inactive: {self.describe_stream(stream)}") - starpilot_toggles = get_starpilot_toggles(sm) - if starpilot_toggles != self.starpilot_toggles: - self.starpilot_toggles = starpilot_toggles + starpilot_toggles = get_starpilot_toggles(sm) + if starpilot_toggles != self.starpilot_toggles: + self.starpilot_toggles = starpilot_toggles - stream = self.update_starpilot_sounds(sd, stream) - elif rk.frame % 5 == 0: - stream = self.update_starpilot_sounds(sd, stream) + stream = self.update_starpilot_sounds(sd, stream) + elif rk.frame % 5 == 0: + stream = self.update_starpilot_sounds(sd, stream) + except Exception: + cloudlog.exception("soundd: stream failed, restarting") + time.sleep(1) + finally: + if stream is not None: + try: + stream.close() + except Exception: + cloudlog.exception("soundd: failed to close stream") def update_starpilot_sounds(self, sd=None, stream=None): self.volume_map = { diff --git a/selfdrive/ui/ui b/selfdrive/ui/ui index f533c00b5..e8007c101 100755 Binary files a/selfdrive/ui/ui and b/selfdrive/ui/ui differ diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 0b9601a08..fd13e7396 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -5,13 +5,10 @@ #include #include #include -#include #include #include -#include #include #include -#include #include #include #include @@ -48,8 +45,7 @@ std::atomic ui_stall_frame{0}; std::atomic ui_stall_reported{false}; std::atomic ui_stall_reported_ns{0}; std::atomic ui_stall_reported_phase{static_cast(UIStallPhase::INIT)}; -std::atomic ui_stall_dump_fd{-1}; -pthread_t ui_main_thread{}; +std::atomic ui_main_tid{0}; double read_env_double(const char *name, double default_value) { const char *value = std::getenv(name); @@ -84,25 +80,29 @@ std::string ui_stall_dump_dir() { return access("/data/log", W_OK) == 0 ? "/data/log" : "/tmp"; } -void ui_stall_signal_handler(int sig) { - const int fd = ui_stall_dump_fd.load(std::memory_order_relaxed); - if (fd < 0) { +void write_stall_dump_section(int fd, const std::string &title, const std::string &body) { + std::string output = "== " + title + " ==\n"; + output += body.empty() ? "\n" : body; + if (!output.empty() && output.back() != '\n') { + output += '\n'; + } + HANDLE_EINTR(write(fd, output.data(), output.size())); +} + +void write_ui_thread_snapshot(int fd) { + const pid_t tid = ui_main_tid.load(std::memory_order_relaxed); + if (tid <= 0) { + write_stall_dump_section(fd, "main_thread", ""); return; } - char header[256]; - const pid_t tid = static_cast(syscall(SYS_gettid)); - const int header_len = std::snprintf(header, sizeof(header), - "=== UI stall backtrace (signal=%d pid=%d tid=%d) ===\n", - sig, getpid(), tid); - if (header_len > 0) { - write(fd, header, header_len); - } + write_stall_dump_section(fd, "main_thread", util::string_format("pid=%d tid=%d", getpid(), tid)); - void *frames[128]; - const int frame_count = backtrace(frames, 128); - backtrace_symbols_fd(frames, frame_count, fd); - write(fd, "\n", 1); + const std::string task_dir = "/proc/self/task/" + std::to_string(tid); + write_stall_dump_section(fd, "main_thread status", util::read_file(task_dir + "/status")); + write_stall_dump_section(fd, "main_thread wchan", util::read_file(task_dir + "/wchan")); + write_stall_dump_section(fd, "main_thread syscall", util::read_file(task_dir + "/syscall")); + write_stall_dump_section(fd, "main_thread kernel_stack", util::read_file(task_dir + "/stack")); } void ui_stall_progress(UIStallPhase phase, uint64_t frame = 0) { @@ -126,8 +126,7 @@ void ui_stall_progress(UIStallPhase phase, uint64_t frame = 0) { void start_ui_stall_monitor() { static std::once_flag once; std::call_once(once, [] { - ui_main_thread = pthread_self(); - std::signal(SIGUSR1, ui_stall_signal_handler); + ui_main_tid.store(static_cast(syscall(SYS_gettid)), std::memory_order_relaxed); ui_stall_progress(UIStallPhase::INIT, 0); const double stall_probe_dt = read_env_double("UI_STALL_PROBE_MAX_DT", 5.0); @@ -176,10 +175,7 @@ void start_ui_stall_monitor() { write(fd, header, header_len); } - ui_stall_dump_fd.store(fd, std::memory_order_relaxed); - pthread_kill(ui_main_thread, SIGUSR1); - std::this_thread::sleep_for(50ms); - ui_stall_dump_fd.store(-1, std::memory_order_relaxed); + write_ui_thread_snapshot(fd); close(fd); LOGE("UI main thread stalled for %.1fs (phase=%s frame=%llu dump=%s)", stalled_for_s, diff --git a/starpilot/navigation/mapd_wrapper.py b/starpilot/navigation/mapd_wrapper.py index 7c7727950..0d98e242b 100644 --- a/starpilot/navigation/mapd_wrapper.py +++ b/starpilot/navigation/mapd_wrapper.py @@ -101,7 +101,14 @@ def terminate_child(proc: subprocess.Popen[str]) -> None: def run_mapd_once() -> int: - OFFLINE_ROOT.mkdir(parents=True, exist_ok=True) + try: + OFFLINE_ROOT.mkdir(parents=True, exist_ok=True) + except PermissionError: + cloudlog.exception(f"mapd_wrapper cannot create offline directory: {OFFLINE_ROOT}") + return 2 + except OSError: + cloudlog.exception(f"mapd_wrapper failed to prepare offline directory: {OFFLINE_ROOT}") + return 2 proc = subprocess.Popen( [MAPD_BIN.as_posix()],