This commit is contained in:
firestar5683
2026-04-11 19:01:10 -05:00
parent 7ceb47eb23
commit 8c93f6b896
8 changed files with 89 additions and 54 deletions
@@ -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"
@@ -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]
+1 -1
View File
@@ -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";
+1 -1
View File
@@ -1 +1 @@
DEV-e0cf4fd9-DEBUG
DEV-7ceb47eb-DEBUG
+55 -24
View File
@@ -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 = {
BIN
View File
Binary file not shown.
+22 -26
View File
@@ -5,13 +5,10 @@
#include <cerrno>
#include <cmath>
#include <chrono>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <execinfo.h>
#include <fcntl.h>
#include <mutex>
#include <pthread.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <thread>
@@ -48,8 +45,7 @@ std::atomic<uint64_t> ui_stall_frame{0};
std::atomic<bool> ui_stall_reported{false};
std::atomic<uint64_t> ui_stall_reported_ns{0};
std::atomic<int> ui_stall_reported_phase{static_cast<int>(UIStallPhase::INIT)};
std::atomic<int> ui_stall_dump_fd{-1};
pthread_t ui_main_thread{};
std::atomic<pid_t> 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() ? "<unavailable>\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", "<unavailable>");
return;
}
char header[256];
const pid_t tid = static_cast<pid_t>(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<pid_t>(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,
+8 -1
View File
@@ -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()],