diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index f5cc0d5003..7fe4263db5 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -29,7 +29,7 @@ jobs:
- name: Build docs
run: |
# TODO: can we install just the "docs" dependency group without the normal deps?
- pip install mkdocs mkdocs-terminal
+ pip install mkdocs==1.4.3 mkdocs-terminal mkdocs-plugin-commonmark
cd docs
mkdocs build
diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml
index 1154948ace..a178634321 100644
--- a/.github/workflows/selfdrive_tests.yaml
+++ b/.github/workflows/selfdrive_tests.yaml
@@ -96,7 +96,7 @@ jobs:
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 15 || 30) }} # allow more time when we missed the scons cache
build_mac:
- name: build macos
+ name: build macOS
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
@@ -106,7 +106,6 @@ jobs:
- name: Install dependencies
run: ./tools/mac_setup.sh
env:
- SKIP_PROMPT: 1
# package install has DeprecationWarnings
PYTHONWARNINGS: default
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
diff --git a/README.md b/README.md
index 5afaf6e7d6..8ebc733e63 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,32 @@
-[](https://comma.ai/shop/comma-3x)
+
-What is openpilot?
-------
+
openpilot
+
+
+ openpilot is an operating system for robotics.
+
+ Currently, it upgrades the driver assistance system in 275+ supported cars.
+
+
+
+
+Quick start: `curl -fsSL openpilot.comma.ai | bash`
-[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](docs/INTEGRATION.md) and [limitations](docs/LIMITATIONS.md).
+
+[](https://codecov.io/gh/commaai/openpilot)
+[](LICENSE)
+[](https://x.com/comma_ai)
+[](https://discord.comma.ai)
+
+
@@ -49,18 +72,6 @@ Safety and Testing
* panda has additional hardware-in-the-loop [tests](https://github.com/commaai/panda/blob/master/Jenkinsfile).
* We run the latest openpilot in a testing closet containing 10 comma devices continuously replaying routes.
-User Data and comma Account
-------
-
-By default, openpilot uploads the driving data to our servers. You can also access your data through [comma connect](https://connect.comma.ai/). We use your data to train better models and improve openpilot for everyone.
-
-openpilot is open source software: the user is free to disable data collection if they wish to do so.
-
-openpilot logs the road-facing cameras, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
-The driver-facing camera is only logged if you explicitly opt-in in settings. The microphone is not recorded.
-
-By using openpilot, you agree to [our Privacy Policy](https://comma.ai/privacy). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data.
-
Licensing
------
@@ -72,9 +83,14 @@ Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and i
YOU ARE RESPONSIBLE FOR COMPLYING WITH LOCAL LAWS AND REGULATIONS.
NO WARRANTY EXPRESSED OR IMPLIED.**
----
+User Data and comma Account
+------
-
+By default, openpilot uploads the driving data to our servers. You can also access your data through [comma connect](https://connect.comma.ai/). We use your data to train better models and improve openpilot for everyone.
-
-[](https://codecov.io/gh/commaai/openpilot)
+openpilot is open source software: the user is free to disable data collection if they wish to do so.
+
+openpilot logs the road-facing cameras, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
+The driver-facing camera is only logged if you explicitly opt-in in settings. The microphone is not recorded.
+
+By using openpilot, you agree to [our Privacy Policy](https://comma.ai/privacy). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data.
diff --git a/SConstruct b/SConstruct
index 1f83b1e43d..329ebe3308 100644
--- a/SConstruct
+++ b/SConstruct
@@ -169,7 +169,6 @@ if arch != "Darwin":
ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"]
# Enable swaglog include in submodules
-cflags += ['-DSWAGLOG="\\"common/swaglog.h\\""']
cxxflags += ['-DSWAGLOG="\\"common/swaglog.h\\""']
ccflags_option = GetOption('ccflags')
@@ -205,7 +204,6 @@ env = Environment(
"#third_party/json11",
"#third_party/linux/include",
"#third_party/snpe/include",
- "#third_party/qrcode",
"#third_party",
"#cereal",
"#msgq",
@@ -314,7 +312,7 @@ try:
except SCons.Errors.UserError:
qt_env.Tool('qt')
-qt_env['CPPPATH'] += qt_dirs# + ["#selfdrive/ui/qt/"]
+qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"]
qt_flags = [
"-D_REENTRANT",
"-DQT_NO_DEBUG",
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 45a1503b0c..92cb501b8b 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -5,6 +5,9 @@ site_url: https://docs.comma.ai
strict: true
+plugins:
+ - commonmark
+
theme:
name: terminal
features:
diff --git a/pyproject.toml b/pyproject.toml
index 1226c8345a..79034e25f0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -67,8 +67,9 @@ dependencies = [
[project.optional-dependencies]
docs = [
"Jinja2",
- "mkdocs",
+ "mkdocs==1.4.3", # needed for mkdocs-plugin-commonmark
"mkdocs-terminal",
+ "mkdocs-plugin-commonmark",
]
testing = [
@@ -110,6 +111,7 @@ dev = [
#pprofile = "*"
"pyautogui",
"pyopencl; platform_machine != 'aarch64'", # broken on arm64
+ "pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version
"pywinctl",
"pyprof2calltree",
"rerun-sdk",
@@ -227,7 +229,7 @@ lint.ignore = [
"UP038", # (x, y) -> x|y for isinstance
]
line-length = 160
-target-version="py311"
+target-version ="py311"
exclude = [
"body",
"cereal",
@@ -239,7 +241,8 @@ exclude = [
"teleoprtc_repo",
"third_party",
]
-lint.flake8-implicit-str-concat.allow-multiline=false
+lint.flake8-implicit-str-concat.allow-multiline = false
+
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"selfdrive".msg = "Use openpilot.selfdrive"
"common".msg = "Use openpilot.common"
@@ -251,5 +254,6 @@ lint.flake8-implicit-str-concat.allow-multiline=false
[tool.coverage.run]
concurrency = ["multiprocessing", "thread"]
+
[tool.ruff.format]
quote-style = "preserve"
diff --git a/selfdrive/car/hyundai/fingerprints.py b/selfdrive/car/hyundai/fingerprints.py
index 30e4b9ed74..5f959bd68d 100644
--- a/selfdrive/car/hyundai/fingerprints.py
+++ b/selfdrive/car/hyundai/fingerprints.py
@@ -765,9 +765,11 @@ FW_VERSIONS = {
],
(Ecu.abs, 0x7d1, None): [
b'\xf1\x00JF ESC \x0f 16 \x16\x06\x17 58920-D5080',
+ b'\xf1\x00JF ESC \t 17 \x16\x06# 58920-D4180',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00JFWGN LDWS AT USA LHD 1.00 1.02 95895-D4100 G21',
+ b'\xf1\x00JFWGN LKAS AT EUR LHD 1.00 1.01 95895-D4100 G20',
],
},
CAR.KIA_OPTIMA_G4_FL: {
diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py
index bbb99d13b9..1e4669fb0a 100644
--- a/selfdrive/test/test_onroad.py
+++ b/selfdrive/test/test_onroad.py
@@ -56,7 +56,7 @@ PROCS = {
"system.logmessaged": 0.2,
"system.tombstoned": 0,
"logcatd": 0,
- "system.micd": 6.0,
+ "system.micd": 5.0,
"system.timed": 0,
"selfdrive.pandad.pandad": 0,
"system.statsd": 0.4,
diff --git a/system/camerad/cameras/camera_common.cc b/system/camerad/cameras/camera_common.cc
index 9d82284d9f..542be29d80 100644
--- a/system/camerad/cameras/camera_common.cc
+++ b/system/camerad/cameras/camera_common.cc
@@ -244,7 +244,7 @@ static kj::Array yuv420_to_jpeg(const CameraBuf *b, int thumbnail_w
return dat;
}
-static void publish_thumbnail(PubMaster *pm, const CameraBuf *b) {
+void publish_thumbnail(PubMaster *pm, const CameraBuf *b) {
auto thumbnail = yuv420_to_jpeg(b, b->rgb_width / 4, b->rgb_height / 4);
if (thumbnail.size() == 0) return;
@@ -284,36 +284,6 @@ float set_exposure_target(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_sk
return lum_med / 256.0;
}
-void *processing_thread(MultiCameraState *cameras, CameraState *cs, process_thread_cb callback) {
- const char *thread_name = nullptr;
- if (cs == &cameras->road_cam) {
- thread_name = "RoadCamera";
- } else if (cs == &cameras->driver_cam) {
- thread_name = "DriverCamera";
- } else {
- thread_name = "WideRoadCamera";
- }
- util::set_thread_name(thread_name);
-
- uint32_t cnt = 0;
- while (!do_exit) {
- if (!cs->buf.acquire()) continue;
-
- callback(cameras, cs, cnt);
-
- if (cs == &(cameras->road_cam) && cameras->pm && cnt % 100 == 3) {
- // this takes 10ms???
- publish_thumbnail(cameras->pm, &(cs->buf));
- }
- ++cnt;
- }
- return NULL;
-}
-
-std::thread start_process_thread(MultiCameraState *cameras, CameraState *cs, process_thread_cb callback) {
- return std::thread(processing_thread, cameras, cs, callback);
-}
-
void camerad_thread() {
cl_device_id device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT);
#ifdef QCOM2
@@ -324,7 +294,7 @@ void camerad_thread() {
#endif
{
- MultiCameraState cameras = {};
+ MultiCameraState cameras;
VisionIpcServer vipc_server("camerad", device_id, context);
cameras_open(&cameras);
diff --git a/system/camerad/cameras/camera_common.h b/system/camerad/cameras/camera_common.h
index 555362ab8b..d58f4d3195 100644
--- a/system/camerad/cameras/camera_common.h
+++ b/system/camerad/cameras/camera_common.h
@@ -2,7 +2,6 @@
#include
#include
-#include
#include "cereal/messaging/messaging.h"
#include "msgq/visionipc/visionipc_server.h"
@@ -18,9 +17,6 @@ enum CameraType {
};
// for debugging
-const bool env_disable_road = getenv("DISABLE_ROAD") != NULL;
-const bool env_disable_wide_road = getenv("DISABLE_WIDE_ROAD") != NULL;
-const bool env_disable_driver = getenv("DISABLE_DRIVER") != NULL;
const bool env_debug_frames = getenv("DEBUG_FRAMES") != NULL;
const bool env_log_raw_frames = getenv("LOG_RAW_FRAMES") != NULL;
const bool env_ctrl_exp_from_params = getenv("CTRL_EXP_FROM_PARAMS") != NULL;
@@ -72,13 +68,10 @@ public:
void queue(size_t buf_idx);
};
-typedef void (*process_thread_cb)(MultiCameraState *s, CameraState *c, int cnt);
-
void fill_frame_data(cereal::FrameData::Builder &framed, const FrameMetadata &frame_data, CameraState *c);
kj::Array get_raw_frame_image(const CameraBuf *b);
float set_exposure_target(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_skip);
-std::thread start_process_thread(MultiCameraState *cameras, CameraState *cs, process_thread_cb callback);
-
+void publish_thumbnail(PubMaster *pm, const CameraBuf *b);
void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_id, cl_context ctx);
void cameras_open(MultiCameraState *s);
void cameras_run(MultiCameraState *s);
diff --git a/system/camerad/cameras/camera_qcom2.cc b/system/camerad/cameras/camera_qcom2.cc
index 7c1f8e44e7..2729aa264c 100644
--- a/system/camerad/cameras/camera_qcom2.cc
+++ b/system/camerad/cameras/camera_qcom2.cc
@@ -26,6 +26,16 @@ const int MIPI_SETTLE_CNT = 33; // Calculated by camera_freqs.py
extern ExitHandler do_exit;
+CameraState::CameraState(MultiCameraState *multi_camera_state, const CameraConfig &config)
+ : multi_cam_state(multi_camera_state),
+ camera_num(config.camera_num),
+ stream_type(config.stream_type),
+ focal_len(config.focal_len),
+ publish_name(config.publish_name),
+ init_camera_state(config.init_camera_state),
+ enabled(config.enabled) {
+}
+
int CameraState::clear_req_queue() {
struct cam_req_mgr_flush_info req_mgr_flush_request = {0};
req_mgr_flush_request.session_hdl = session_handle;
@@ -425,48 +435,38 @@ void CameraState::set_exposure_rect() {
}
void CameraState::sensor_set_parameters() {
- target_grey_fraction = 0.3;
-
- dc_gain_enabled = false;
dc_gain_weight = ci->dc_gain_min_weight;
gain_idx = ci->analog_gain_rec_idx;
- exposure_time = 5;
cur_ev[0] = cur_ev[1] = cur_ev[2] = (1 + dc_gain_weight * (ci->dc_gain_factor-1) / ci->dc_gain_max_weight) * ci->sensor_analog_gains[gain_idx] * exposure_time;
}
-void CameraState::camera_map_bufs(MultiCameraState *s) {
+void CameraState::camera_map_bufs() {
for (int i = 0; i < FRAME_BUF_COUNT; i++) {
// configure ISP to put the image in place
struct cam_mem_mgr_map_cmd mem_mgr_map_cmd = {0};
- mem_mgr_map_cmd.mmu_hdls[0] = s->device_iommu;
+ mem_mgr_map_cmd.mmu_hdls[0] = multi_cam_state->device_iommu;
mem_mgr_map_cmd.num_hdl = 1;
mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE;
mem_mgr_map_cmd.fd = buf.camera_bufs[i].fd;
- int ret = do_cam_control(s->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
+ int ret = do_cam_control(multi_cam_state->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs[i].fd, mem_mgr_map_cmd.out.buf_handle, ret);
buf_handle[i] = mem_mgr_map_cmd.out.buf_handle;
}
enqueue_req_multi(1, FRAME_BUF_COUNT, 0);
}
-void CameraState::camera_init(MultiCameraState *s, VisionIpcServer * v, cl_device_id device_id, cl_context ctx, VisionStreamType yuv_type, float focal_len) {
+void CameraState::camera_init(VisionIpcServer * v, cl_device_id device_id, cl_context ctx) {
if (!enabled) return;
LOGD("camera init %d", camera_num);
- request_id_last = 0;
- skipped = true;
-
- buf.init(device_id, ctx, this, v, FRAME_BUF_COUNT, yuv_type);
- camera_map_bufs(s);
+ buf.init(device_id, ctx, this, v, FRAME_BUF_COUNT, stream_type);
+ camera_map_bufs();
fl_pix = focal_len / ci->pixel_size_mm;
set_exposure_rect();
}
-void CameraState::camera_open(MultiCameraState *multi_cam_state_, int camera_num_, bool enabled_) {
- multi_cam_state = multi_cam_state_;
- camera_num = camera_num_;
- enabled = enabled_;
+void CameraState::camera_open() {
if (!enabled) return;
if (!openSensor()) {
@@ -660,9 +660,9 @@ void CameraState::linkDevices() {
}
void cameras_init(VisionIpcServer *v, MultiCameraState *s, cl_device_id device_id, cl_context ctx) {
- s->driver_cam.camera_init(s, v, device_id, ctx, VISION_STREAM_DRIVER, DRIVER_FL_MM);
- s->road_cam.camera_init(s, v, device_id, ctx, VISION_STREAM_ROAD, ROAD_FL_MM);
- s->wide_road_cam.camera_init(s, v, device_id, ctx, VISION_STREAM_WIDE_ROAD, WIDE_FL_MM);
+ s->driver_cam.camera_init(v, device_id, ctx);
+ s->road_cam.camera_init(v, device_id, ctx);
+ s->wide_road_cam.camera_init(v, device_id, ctx);
s->pm = new PubMaster({"roadCameraState", "driverCameraState", "wideRoadCameraState", "thumbnail"});
}
@@ -706,11 +706,11 @@ void cameras_open(MultiCameraState *s) {
ret = HANDLE_EINTR(ioctl(s->video0_fd, VIDIOC_SUBSCRIBE_EVENT, &sub));
LOGD("req mgr subscribe: %d", ret);
- s->driver_cam.camera_open(s, 2, !env_disable_driver);
+ s->driver_cam.camera_open();
LOGD("driver camera opened");
- s->road_cam.camera_open(s, 1, !env_disable_road);
+ s->road_cam.camera_open();
LOGD("road camera opened");
- s->wide_road_cam.camera_open(s, 0, !env_disable_wide_road);
+ s->wide_road_cam.camera_open();
LOGD("wide road camera opened");
}
@@ -943,41 +943,50 @@ void CameraState::set_camera_exposure(float grey_frac) {
sensors_i2c(exp_reg_array.data(), exp_reg_array.size(), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, ci->data_word);
}
-static void process_driver_camera(MultiCameraState *s, CameraState *c, int cnt) {
- c->set_camera_exposure(set_exposure_target(&c->buf, c->ae_xywh, 2, 4));
+void CameraState::run() {
+ util::set_thread_name(publish_name);
- MessageBuilder msg;
- auto framed = msg.initEvent().initDriverCameraState();
- fill_frame_data(framed, c->buf.cur_frame_data, c);
+ for (uint32_t cnt = 0; !do_exit; ++cnt) {
+ // Acquire the buffer; continue if acquisition fails
+ if (!buf.acquire()) continue;
- c->ci->processRegisters(c, framed);
- s->pm->send("driverCameraState", msg);
-}
+ MessageBuilder msg;
+ auto framed = (msg.initEvent().*init_camera_state)();
+ fill_frame_data(framed, buf.cur_frame_data, this);
-void process_road_camera(MultiCameraState *s, CameraState *c, int cnt) {
- const CameraBuf *b = &c->buf;
+ // Log raw frames for road camera
+ if (env_log_raw_frames && stream_type == VISION_STREAM_ROAD && cnt % 100 == 5) { // no overlap with qlog decimation
+ framed.setImage(get_raw_frame_image(&buf));
+ }
+ // Log frame id for road and wide road cameras
+ if (stream_type != VISION_STREAM_DRIVER) {
+ LOGT(buf.cur_frame_data.frame_id, "%s: Image set", publish_name);
+ }
- MessageBuilder msg;
- auto framed = c == &s->road_cam ? msg.initEvent().initRoadCameraState() : msg.initEvent().initWideRoadCameraState();
- fill_frame_data(framed, b->cur_frame_data, c);
- if (env_log_raw_frames && c == &s->road_cam && cnt % 100 == 5) { // no overlap with qlog decimation
- framed.setImage(get_raw_frame_image(b));
- }
- LOGT(c->buf.cur_frame_data.frame_id, "%s: Image set", c == &s->road_cam ? "RoadCamera" : "WideRoadCamera");
+ // Process camera registers and set camera exposure
+ ci->processRegisters(this, framed);
+ set_camera_exposure(set_exposure_target(&buf, ae_xywh, 2, stream_type != VISION_STREAM_DRIVER ? 2 : 4));
- c->ci->processRegisters(c, framed);
- s->pm->send(c == &s->road_cam ? "roadCameraState" : "wideRoadCameraState", msg);
+ // Send the message
+ multi_cam_state->pm->send(publish_name, msg);
+ if (stream_type == VISION_STREAM_ROAD && cnt % 100 == 3) {
+ publish_thumbnail(multi_cam_state->pm, &buf); // this takes 10ms???
+ }
+ }
+}
- const int skip = 2;
- c->set_camera_exposure(set_exposure_target(b, c->ae_xywh, skip, skip));
+MultiCameraState::MultiCameraState()
+ : driver_cam(this, DRIVER_CAMERA_CONFIG),
+ road_cam(this, ROAD_CAMERA_CONFIG),
+ wide_road_cam(this, WIDE_ROAD_CAMERA_CONFIG) {
}
void cameras_run(MultiCameraState *s) {
LOG("-- Starting threads");
std::vector threads;
- if (s->driver_cam.enabled) threads.push_back(start_process_thread(s, &s->driver_cam, process_driver_camera));
- if (s->road_cam.enabled) threads.push_back(start_process_thread(s, &s->road_cam, process_road_camera));
- if (s->wide_road_cam.enabled) threads.push_back(start_process_thread(s, &s->wide_road_cam, process_road_camera));
+ if (s->driver_cam.enabled) threads.emplace_back(&CameraState::run, &s->driver_cam);
+ if (s->road_cam.enabled) threads.emplace_back(&CameraState::run, &s->road_cam);
+ if (s->wide_road_cam.enabled) threads.emplace_back(&CameraState::run, &s->wide_road_cam);
// start devices
LOG("-- Starting devices");
diff --git a/system/camerad/cameras/camera_qcom2.h b/system/camerad/cameras/camera_qcom2.h
index b702d1bb69..1b27fb18b8 100644
--- a/system/camerad/cameras/camera_qcom2.h
+++ b/system/camerad/cameras/camera_qcom2.h
@@ -11,67 +11,105 @@
#define FRAME_BUF_COUNT 4
-#define ROAD_FL_MM 8.0f
-#define WIDE_FL_MM 1.71f
-#define DRIVER_FL_MM 1.71f
+struct CameraConfig {
+ int camera_num;
+ VisionStreamType stream_type;
+ float focal_len; // millimeters
+ const char *publish_name;
+ cereal::FrameData::Builder (cereal::Event::Builder::*init_camera_state)();
+ bool enabled;
+};
+
+const CameraConfig WIDE_ROAD_CAMERA_CONFIG = {
+ .camera_num = 0,
+ .stream_type = VISION_STREAM_WIDE_ROAD,
+ .focal_len = 1.71,
+ .publish_name = "wideRoadCameraState",
+ .init_camera_state = &cereal::Event::Builder::initWideRoadCameraState,
+ .enabled = !getenv("DISABLE_WIDE_ROAD"),
+};
+
+const CameraConfig ROAD_CAMERA_CONFIG = {
+ .camera_num = 1,
+ .stream_type = VISION_STREAM_ROAD,
+ .focal_len = 8.0,
+ .publish_name = "roadCameraState",
+ .init_camera_state = &cereal::Event::Builder::initRoadCameraState,
+ .enabled = !getenv("DISABLE_ROAD"),
+};
+
+const CameraConfig DRIVER_CAMERA_CONFIG = {
+ .camera_num = 2,
+ .stream_type = VISION_STREAM_DRIVER,
+ .focal_len = 1.71,
+ .publish_name = "driverCameraState",
+ .init_camera_state = &cereal::Event::Builder::initDriverCameraState,
+ .enabled = !getenv("DISABLE_DRIVER"),
+};
class CameraState {
public:
- MultiCameraState *multi_cam_state;
+ MultiCameraState *multi_cam_state = nullptr;
std::unique_ptr ci;
- bool enabled;
+ bool enabled = true;
+ VisionStreamType stream_type;
+ const char *publish_name = nullptr;
+ cereal::FrameData::Builder (cereal::Event::Builder::*init_camera_state)() = nullptr;
+ float focal_len = 0;
std::mutex exp_lock;
- int exposure_time;
- bool dc_gain_enabled;
- int dc_gain_weight;
- int gain_idx;
- float analog_gain_frac;
+ int exposure_time = 5;
+ bool dc_gain_enabled = false;
+ int dc_gain_weight = 0;
+ int gain_idx = 0;
+ float analog_gain_frac = 0;
- float cur_ev[3];
- float best_ev_score;
- int new_exp_g;
- int new_exp_t;
+ float cur_ev[3] = {};
+ float best_ev_score = 0;
+ int new_exp_g = 0;
+ int new_exp_t = 0;
- Rect ae_xywh;
- float measured_grey_fraction;
- float target_grey_fraction;
+ Rect ae_xywh = {};
+ float measured_grey_fraction = 0;
+ float target_grey_fraction = 0.3;
unique_fd sensor_fd;
unique_fd csiphy_fd;
- int camera_num;
- float fl_pix;
+ int camera_num = 0;
+ float fl_pix = 0;
+ CameraState(MultiCameraState *multi_camera_state, const CameraConfig &config);
void handle_camera_event(void *evdat);
void update_exposure_score(float desired_ev, int exp_t, int exp_g_idx, float exp_gain);
void set_camera_exposure(float grey_frac);
void sensors_start();
- void camera_open(MultiCameraState *multi_cam_state, int camera_num, bool enabled);
+ void camera_open();
void set_exposure_rect();
void sensor_set_parameters();
- void camera_map_bufs(MultiCameraState *s);
- void camera_init(MultiCameraState *s, VisionIpcServer *v, cl_device_id device_id, cl_context ctx, VisionStreamType yuv_type, float focal_len);
+ void camera_map_bufs();
+ void camera_init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx);
void camera_close();
+ void run();
- int32_t session_handle;
- int32_t sensor_dev_handle;
- int32_t isp_dev_handle;
- int32_t csiphy_dev_handle;
+ int32_t session_handle = -1;
+ int32_t sensor_dev_handle = -1;
+ int32_t isp_dev_handle = -1;
+ int32_t csiphy_dev_handle = -1;
- int32_t link_handle;
+ int32_t link_handle = -1;
- int buf0_handle;
- int buf_handle[FRAME_BUF_COUNT];
- int sync_objs[FRAME_BUF_COUNT];
- int request_ids[FRAME_BUF_COUNT];
- int request_id_last;
- int frame_id_last;
- int idx_offset;
- bool skipped;
+ int buf0_handle = 0;
+ int buf_handle[FRAME_BUF_COUNT] = {};
+ int sync_objs[FRAME_BUF_COUNT] = {};
+ int request_ids[FRAME_BUF_COUNT] = {};
+ int request_id_last = 0;
+ int frame_id_last = 0;
+ int idx_offset = 0;
+ bool skipped = true;
CameraBuf buf;
MemoryManager mm;
@@ -95,16 +133,19 @@ private:
Params params;
};
-typedef struct MultiCameraState {
+class MultiCameraState {
+public:
+ MultiCameraState();
+
unique_fd video0_fd;
unique_fd cam_sync_fd;
unique_fd isp_fd;
- int device_iommu;
- int cdm_iommu;
+ int device_iommu = -1;
+ int cdm_iommu = -1;
CameraState road_cam;
CameraState wide_road_cam;
CameraState driver_cam;
PubMaster *pm;
-} MultiCameraState;
+};
diff --git a/system/micd.py b/system/micd.py
index 8b738ebe93..af1aa31360 100755
--- a/system/micd.py
+++ b/system/micd.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import numpy as np
+from functools import cache
from cereal import messaging
from openpilot.common.realtime import Ratekeeper
@@ -10,7 +11,16 @@ RATE = 10
FFT_SAMPLES = 4096
REFERENCE_SPL = 2e-5 # newtons/m^2
SAMPLE_RATE = 44100
-SAMPLE_BUFFER = 4096 # (approx 100ms)
+SAMPLE_BUFFER = 4096 # approx 100ms
+
+
+@cache
+def get_a_weighting_filter():
+ # Calculate the A-weighting filter
+ # https://en.wikipedia.org/wiki/A-weighting
+ freqs = np.fft.fftfreq(FFT_SAMPLES, d=1 / SAMPLE_RATE)
+ A = 12194 ** 2 * freqs ** 4 / ((freqs ** 2 + 20.6 ** 2) * (freqs ** 2 + 12194 ** 2) * np.sqrt((freqs ** 2 + 107.7 ** 2) * (freqs ** 2 + 737.9 ** 2)))
+ return A / np.max(A)
def calculate_spl(measurements):
@@ -27,16 +37,8 @@ def apply_a_weighting(measurements: np.ndarray) -> np.ndarray:
# Generate a Hanning window of the same length as the audio measurements
measurements_windowed = measurements * np.hanning(len(measurements))
- # Calculate the frequency axis for the signal
- freqs = np.fft.fftfreq(measurements_windowed.size, d=1 / SAMPLE_RATE)
-
- # Calculate the A-weighting filter
- # https://en.wikipedia.org/wiki/A-weighting
- A = 12194 ** 2 * freqs ** 4 / ((freqs ** 2 + 20.6 ** 2) * (freqs ** 2 + 12194 ** 2) * np.sqrt((freqs ** 2 + 107.7 ** 2) * (freqs ** 2 + 737.9 ** 2)))
- A /= np.max(A) # Normalize the filter
-
# Apply the A-weighting filter to the signal
- return np.abs(np.fft.ifft(np.fft.fft(measurements_windowed) * A))
+ return np.abs(np.fft.ifft(np.fft.fft(measurements_windowed) * get_a_weighting_filter()))
class Mic:
diff --git a/tools/mac_setup.sh b/tools/mac_setup.sh
index 9823427e65..d19f1cae86 100755
--- a/tools/mac_setup.sh
+++ b/tools/mac_setup.sh
@@ -2,19 +2,12 @@
set -e
-if [ -z "$SKIP_PROMPT" ]; then
- echo "--------------- macOS support ---------------"
- echo "Running openpilot natively on macOS is not officially supported."
- echo "It might build, some parts of it might work, but it's not fully tested, so there might be some issues."
- echo
- echo "Check out devcontainers for a seamless experience (see tools/README.md)."
- echo "-------------------------------------------------"
- echo -n "Are you sure you want to continue? [y/N] "
- read -r response
- if [[ ! "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
- exit 1
- fi
-fi
+echo "--------------- macOS support ---------------"
+echo "Running openpilot natively on macOS is still a work-in-progress."
+echo "It might build, some parts of it might work, but it's not fully tested, so there might be some issues."
+echo
+echo "Check out devcontainers for a seamless experience (see tools/README.md)."
+echo "-------------------------------------------------"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
ROOT="$(cd $DIR/../ && pwd)"
diff --git a/tools/op.sh b/tools/op.sh
index 111a06e81c..42bbb1973d 100755
--- a/tools/op.sh
+++ b/tools/op.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
RED='\033[0;31m'
GREEN='\033[0;32m'
@@ -14,64 +14,66 @@ function op_first_install() {
if [ "$(uname)" == "Darwin" ] && [ $SHELL == "/bin/bash" ]; then
RC_FILE="$HOME/.bash_profile"
fi
- op_run_command printf "\nalias op='source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )/op.sh" \"\$@\"'\n" >> $RC_FILE
+ printf "\nalias op='source "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )/op.sh" \"\$@\"'\n" >> $RC_FILE
echo -e " ↳ [${GREEN}✔${NC}] op installed successfully. Open a new shell to use it.\n"
)
}
+function op_run_command() {
+ CMD="$@"
+ echo -e "${BOLD}Running:${NC} $CMD"
+ if [[ -z "$DRY" ]]; then
+ eval "$CMD"
+ fi
+}
+
# be default, assume openpilot dir is in current directory
OPENPILOT_ROOT=$(pwd)
function op_check_openpilot_dir() {
+ echo "Checking for openpilot directory..."
while [[ "$OPENPILOT_ROOT" != '/' ]];
do
if find "$OPENPILOT_ROOT/launch_openpilot.sh" -maxdepth 1 -mindepth 1 &> /dev/null; then
+ echo -e " ↳ [${GREEN}✔${NC}] openpilot found.\n"
return 0
fi
OPENPILOT_ROOT="$(readlink -f "$OPENPILOT_ROOT/"..)"
done
- echo "openpilot directory not found! Make sure that you are inside openpilot"
- echo "directory or specify one with the --dir option!"
+ echo -e " ↳ [${RED}✗${NC}] openpilot directory not found! Make sure that you are"
+ echo " inside the openpilot directory or specify one with the"
+ echo " --dir option!"
return 1
}
-function op_run_command() {
- CMD="$@"
- echo -e "${BOLD}Running:${NC} $CMD"
- if [[ -z "$DRY" ]]; then
- $CMD
- fi
-}
-
function op_check_git() {
(set -e
- cd $OPENPILOT_ROOT
-
echo "Checking for git..."
if ! command -v "git" > /dev/null 2>&1; then
- echo -e " ↳ [${RED}✗${NC}] git not found on your system!"
+ echo -e " ↳ [${RED}✗${NC}] git not found on your system!\n"
return 1
else
- echo -e " ↳ [${GREEN}✔${NC}] git found on your system.\n"
+ echo -e " ↳ [${GREEN}✔${NC}] git found.\n"
fi
echo "Checking for git lfs files..."
- if [[ $(file -b $(git lfs ls-files -n | grep "\.so" | head -n 1)) == "ASCII text" ]]; then
- echo -e " ↳ [${RED}✗${NC}] git lfs files not found! Run git lfs pull"
+ if [[ $(file -b $OPENPILOT_ROOT/selfdrive/modeld/models/supercombo.onnx) == "ASCII text" ]]; then
+ echo -e " ↳ [${RED}✗${NC}] git lfs files not found! Run 'git lfs pull'\n"
return 1
else
- echo -e " ↳ [${GREEN}✔${NC}] git lfs files found on your system.\n"
+ echo -e " ↳ [${GREEN}✔${NC}] git lfs files found.\n"
fi
echo "Checking for git submodules..."
- if $(git submodule foreach --quiet --recursive 'return 1' 2&> /dev/null); then
- echo -e " ↳ [${RED}✗${NC}] git submodules not found! Run 'git submodule update --init --recursive'"
- return 1
- else
- echo -e " ↳ [${GREEN}✔${NC}] git submodules found on your system.\n"
- fi
+ for name in body msgq_repo opendbc panda rednose_repo tinygrad_repo; do
+ if [[ -z $(ls $OPENPILOT_ROOT/$name) ]]; then
+ echo -e " ↳ [${RED}✗${NC}] git submodule $name not found! Run 'git submodule update --init --recursive'\n"
+ return 1
+ fi
+ done
+ echo -e " ↳ [${GREEN}✔${NC}] git submodules found.\n"
)
}
@@ -89,19 +91,19 @@ function op_check_os() {
echo -e " ↳ [${GREEN}✔${NC}] Ubuntu $VERSION_CODENAME detected.\n"
;;
* )
- echo -e " ↳ [${RED}✗${NC}] Incompatible Ubuntu version $VERSION_CODENAME detected!"
+ echo -e " ↳ [${RED}✗${NC}] Incompatible Ubuntu version $VERSION_CODENAME detected!\n"
return 1
;;
esac
else
- echo -e " ↳ [${RED}✗${NC}] No /etc/os-release on your system. Make sure you're running on Ubuntu, or similar!"
+ echo -e " ↳ [${RED}✗${NC}] No /etc/os-release on your system. Make sure you're running on Ubuntu, or similar!\n"
return 1
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo -e " ↳ [${GREEN}✔${NC}] macos detected.\n"
else
- echo -e " ↳ [${RED}✗${NC}] OS type $OSTYPE not supported!"
+ echo -e " ↳ [${RED}✗${NC}] OS type $OSTYPE not supported!\n"
return 1
fi
@@ -112,78 +114,109 @@ function op_check_python() {
(set -e
echo "Checking for compatible python version..."
- export REQUIRED_PYTHON_VERSION=$(grep "requires-python" pyproject.toml | cut -d= -f3- | tr -d '"' | tr -d ' ')
- if ! command -v "python3" > /dev/null 2>&1; then
- echo -e " ↳ [${RED}✗${NC}] python3 not found on your system. You need python version at least $REQUIRED_PYTHON_VERSION to continue!"
+ REQUIRED_PYTHON_VERSION=$(grep "requires-python" $OPENPILOT_ROOT/pyproject.toml)
+ INSTALLED_PYTHON_VERSION=$(python3 --version 2> /dev/null || true)
+
+ if [[ -z $INSTALLED_PYTHON_VERSION ]]; then
+ echo -e " ↳ [${RED}✗${NC}] python3 not found on your system. You need python version at least $(echo $REQUIRED_PYTHON_VERSION | tr -d -c '[0-9.]') to continue!\n"
return 1
+ elif [[ $(echo $INSTALLED_PYTHON_VERSION | tr -d -c '[0-9]') -ge $(($(echo $REQUIRED_PYTHON_VERSION | tr -d -c '[0-9]') * 10)) ]]; then
+ echo -e " ↳ [${GREEN}✔${NC}] $INSTALLED_PYTHON_VERSION detected.\n"
else
- if $(python3 -c "import sys; quit(not sys.version_info >= tuple(map(int, \"$REQUIRED_PYTHON_VERSION\".split('.'))))"); then
- echo -e " ↳ [${GREEN}✔${NC}] $(python3 --version) detected.\n"
- else
- echo -e " ↳ [${RED}✗${NC}] You need python version at least $REQUIRED_PYTHON_VERSION to continue!"
- return 1
- fi
+ echo -e " ↳ [${RED}✗${NC}] You need python version at least $(echo $REQUIRED_PYTHON_VERSION | tr -d -c '[0-9.]') to continue!\n"
+ return 1
fi
)
}
-# this must be run in the same shell as the user calling "op"
-function op_venv() {
- op_check_openpilot_dir || return 1
- op_run_command source $OPENPILOT_ROOT/.venv/bin/activate || (echo -e "\nCan't activate venv. Have you ran 'op install' ?" && return 1)
+function op_check_venv() {
+ echo "Checking for venv..."
+ if source $OPENPILOT_ROOT/.venv/bin/activate; then
+ echo -e " ↳ [${GREEN}✔${NC}] venv detected.\n"
+ else
+ echo -e " ↳ [${RED}✗${NC}] Can't activate venv in $OPENPILOT_ROOT. Assuming global env!\n"
+ fi
}
-function op_check() {
- (set -e
+function op_before_cmd() {
+ if [[ ! -z "$NO_VERIFY" ]]; then
+ return 0
+ fi
op_check_openpilot_dir
cd $OPENPILOT_ROOT
op_check_git
op_check_os
+ op_check_venv
op_check_python
-
- )
+ echo -e "-----------------------------\n"
}
-function op_run() {
+function op_install() {
(set -e
- op_venv
+ op_check_openpilot_dir
cd $OPENPILOT_ROOT
+ op_check_os
+ op_check_python
+
+ echo "Installing dependencies..."
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ op_run_command $OPENPILOT_ROOT/tools/ubuntu_setup.sh
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ op_run_command $OPENPILOT_ROOT/tools/mac_setup.sh
+ fi
+ echo -e " ↳ [${GREEN}✔${NC}] Dependencies installed successfully.\n"
- op_run_command $OPENPILOT_ROOT/launch_openpilot.sh
+ echo "Getting git submodules..."
+ op_run_command git submodule update --init --recursive
+ echo -e " ↳ [${GREEN}✔${NC}] Submodules installed successfully.\n"
+
+ echo "Pulling git lfs files..."
+ op_run_command git lfs pull
+ echo -e " ↳ [${GREEN}✔${NC}] Files pulled successfully.\n"
+
+ op_check
)
}
-function op_install() {
- (set -e
+function op_venv() {
+ ( set -e
- op_check_openpilot_dir
- cd $OPENPILOT_ROOT
+ op_before_cmd
- op_check_os
- op_check_python
+ )
- if [[ "$OSTYPE" == "linux-gnu"* ]]; then
- $OPENPILOT_ROOT/tools/ubuntu_setup.sh
- elif [[ "$OSTYPE" == "darwin"* ]]; then
- $OPENPILOT_ROOT/tools/mac_setup.sh
+ if [[ "$?" -eq 0 ]]; then
+ # this must be run in the same shell as the user calling "op"
+ op_check_openpilot_dir > /dev/null
+ op_run_command source $OPENPILOT_ROOT/.venv/bin/activate
fi
+}
+
+function op_check() {
+ (set -e
- git submodule update --init --recursive
- git lfs pull
+ op_before_cmd
)
}
-function op_build() {
+function op_run() {
(set -e
- op_venv
- cd $OPENPILOT_ROOT
+ op_before_cmd
+ op_run_command $OPENPILOT_ROOT/launch_openpilot.sh $@
+
+ )
+}
+function op_build() {
+ (set -e
+
+ op_before_cmd
op_run_command scons $@
)
@@ -192,9 +225,7 @@ function op_build() {
function op_juggle() {
(set -e
- op_venv
- cd $OPENPILOT_ROOT
-
+ op_before_cmd
op_run_command $OPENPILOT_ROOT/tools/plotjuggler/juggle.py $@
)
@@ -203,9 +234,7 @@ function op_juggle() {
function op_linter() {
(set -e
- op_venv
- cd $OPENPILOT_ROOT
-
+ op_before_cmd
op_run_command pre-commit run --all $@
)
@@ -213,14 +242,32 @@ function op_linter() {
function op_replay() {
(set -e
- op_check_openpilot_dir
- cd $OPENPILOT_ROOT
+ op_before_cmd
op_run_command $OPENPILOT_ROOT/tools/replay/replay $@
)
}
+function op_cabana() {
+ (set -e
+
+ op_before_cmd
+ op_run_command $OPENPILOT_ROOT/tools/cabana/cabana $@
+
+ )
+}
+
+function op_sim() {
+ (set -e
+
+ op_before_cmd
+ op_run_command exec $OPENPILOT_ROOT/tools/sim/run_bridge.py &
+ op_run_command exec $OPENPILOT_ROOT/tools/sim/launch_openpilot.sh
+
+ )
+}
+
function op_default() {
echo "An openpilot helper"
echo ""
@@ -242,8 +289,10 @@ function op_default() {
echo -e " ${BOLD}install${NC} Install requirements to use openpilot"
echo -e " ${BOLD}build${NC} Build openpilot"
echo -e " ${BOLD}run${NC} Run openpilot"
+ echo -e " ${BOLD}sim${NC} Run openpilot in a simulator"
echo -e " ${BOLD}juggle${NC} Run Plotjuggler"
echo -e " ${BOLD}replay${NC} Run replay"
+ echo -e " ${BOLD}cabana${NC} Run cabana"
echo -e " ${BOLD}linter${NC} Run all the pre-commit checks"
echo -e " ${BOLD}help${NC} Show this message"
echo -e " ${BOLD}--install${NC} Install this tool system wide"
@@ -253,6 +302,8 @@ function op_default() {
echo " Specify the openpilot directory you want to use"
echo -e " ${BOLD}--dry${NC}"
echo " Don't actually run anything, just print what would be"
+ echo -e " ${BOLD}-n, --no-verify${NC}"
+ echo " Don't run checks before running a command"
echo ""
echo -e "${BOLD}${UNDERLINE}Examples:${NC}"
echo " op --dir /tmp/openpilot check"
@@ -271,8 +322,9 @@ function op_default() {
function _op() {
# parse Options
case $1 in
- -d | --dir ) shift 1; OPENPILOT_ROOT="$1"; shift 1 ;;
- --dry ) shift 1; DRY="1" ;;
+ -d | --dir ) shift 1; OPENPILOT_ROOT="$1"; shift 1 ;;
+ --dry ) shift 1; DRY="1" ;;
+ -n | --no-verify ) shift 1; NO_VERIFY="1" ;;
esac
# parse Commands
@@ -283,8 +335,10 @@ function _op() {
build ) shift 1; op_build "$@" ;;
run ) shift 1; op_run "$@" ;;
juggle ) shift 1; op_juggle "$@" ;;
+ cabana ) shift 1; op_cabana "$@" ;;
linter ) shift 1; op_linter "$@" ;;
replay ) shift 1; op_replay "$@" ;;
+ sim ) shift 1; op_sim "$@" ;;
--install ) shift 1; op_first_install "$@" ;;
* ) op_default "$@" ;;
esac
@@ -309,5 +363,10 @@ unset -f op_default
unset -f op_run_command
unset -f op_linter
unset -f op_replay
+unset -f op_cabana
+unset -f op_check_venv
+unset -f op_before_cmd
+unset -f op_sim
unset DRY
unset OPENPILOT_ROOT
+unset NO_VERIFY
diff --git a/tools/setup.sh b/tools/setup.sh
index 22d10be80b..8aca889b8c 100755
--- a/tools/setup.sh
+++ b/tools/setup.sh
@@ -1,32 +1,59 @@
#!/usr/bin/env bash
-set -e
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+NC='\033[0m'
-if [ ! -f launch_openpilot.sh ]; then
- if [ ! -d openpilot ]; then
- git clone --single-branch --recurse-submodules https://github.com/commaai/openpilot.git
- fi
- cd openpilot
+if [ -z "$OPENPILOT_ROOT" ]; then
+ # default to current directory for installation
+ OPENPILOT_ROOT="$(pwd)/openpilot"
fi
-if [[ "$OSTYPE" == "darwin"* ]]; then
- tools/mac_setup.sh
-else
- tools/ubuntu_setup.sh
-fi
+function check_dir() {
+ echo "Checking for installation directory..."
+ if [ -d "$OPENPILOT_ROOT" ]; then
+ echo -e " ↳ [${RED}✗${NC}] can't install openpilot in $OPENPILOT_ROOT !"
+ return 1
+ fi
+
+ echo -e " ↳ [${GREEN}✔${NC}] Successfully chosen $OPENPILOT_ROOT as installation directory\n"
+}
+
+function check_git() {
+ echo "Checking for git..."
+ if ! command -v "git" > /dev/null 2>&1; then
+ echo -e " ↳ [${RED}✗${NC}] git not found on your system, can't continue!"
+ return 1
+ else
+ echo -e " ↳ [${GREEN}✔${NC}] git found.\n"
+ fi
+}
+
+function git_clone() {
+ echo "Cloning openpilot..."
+ if $(git clone --depth=1 https://github.com/commaai/openpilot.git "$OPENPILOT_ROOT"); then
+ if [[ -f $OPENPILOT_ROOT/launch_openpilot.sh ]]; then
+ echo -e " ↳ [${GREEN}✔${NC}] Successfully cloned openpilot.\n"
+ return 0
+ fi
+ fi
+
+ echo -e " ↳ [${RED}✗${NC}] failed to clone openpilot!"
+ return 1
+}
-git lfs pull
+function install_with_op() {
+ cd $OPENPILOT_ROOT
+ $OPENPILOT_ROOT/tools/op.sh --install
+ $OPENPILOT_ROOT/tools/op.sh install
-source .venv/bin/activate
+ # make op usable right now
+ alias op="source $OPENPILOT_ROOT/tools/op.sh \"\$@\""
+}
-echo "Building openpilot"
-scons -u -j$(nproc)
+check_dir && check_git && git_clone && install_with_op
-echo
-echo "---- OPENPILOT BUILDING DONE ----"
-echo "To push changes to your fork, run the following commands:"
-echo "git remote remove origin"
-echo "git remote add origin git@github.com:/openpilot.git"
-echo "git fetch"
-echo "git commit -m \"first commit\""
-echo "git push"
+unset OPENPILOT_ROOT
+unset RED
+unset GREEN
+unset NC
diff --git a/tools/ubuntu_setup.sh b/tools/ubuntu_setup.sh
index 1bdeb50e0d..f425e14cf2 100755
--- a/tools/ubuntu_setup.sh
+++ b/tools/ubuntu_setup.sh
@@ -8,8 +8,3 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
$DIR/install_ubuntu_dependencies.sh
$DIR/install_python_dependencies.sh
-
-echo
-echo "---- OPENPILOT SETUP DONE ----"
-echo "Open a new shell or configure your active shell env by running:"
-echo "source ~/.bashrc"
diff --git a/uv.lock b/uv.lock
index 8a0dc29b2a..7d4870c4b1 100644
--- a/uv.lock
+++ b/uv.lock
@@ -863,14 +863,14 @@ wheels = [
[[distribution]]
name = "importlib-metadata"
-version = "8.0.0"
+version = "8.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "zipp" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/20/ff/bd28f70283b9cca0cbf0c2a6082acbecd822d1962ae7b2a904861b9965f8/importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812", size = 52667 }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/a1/db39a513aa99ab3442010a994eef1cb977a436aded53042e69bee6959f74/importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d", size = 53907 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/dc/ef/38766b2edb096260d9b1b6ad35adaa0bce3b0567abb452b21eb074af88c4/importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f", size = 24769 },
+ { url = "https://files.pythonhosted.org/packages/82/47/bb25ec04985d0693da478797c3d8c1092b140f3a53ccb984fbbd38affa5b/importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369", size = 25920 },
]
[[distribution]]
@@ -1059,11 +1059,11 @@ wheels = [
[[distribution]]
name = "markdown"
-version = "3.6"
+version = "3.3.7"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/22/02/4785861427848cc11e452cc62bb541006a1087cf04a1de83aedd5530b948/Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224", size = 354715 }
+sdist = { url = "https://files.pythonhosted.org/packages/d6/58/79df20de6e67a83f0d0bbfe6c19bb82adf68cdf362885257eb01099f930a/Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874", size = 324130 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f", size = 105381 },
+ { url = "https://files.pythonhosted.org/packages/f3/df/ca72f352e15b6f8ce32b74af029f1189abffb906f7c137501ffe69c98a65/Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621", size = 97778 },
]
[[distribution]]
@@ -1196,9 +1196,18 @@ dependencies = [
{ name = "yapf" },
]
+[[distribution]]
+name = "mistletoe"
+version = "1.4.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/11/96/ea46a376a7c4cd56955ecdfff0ea68de43996a4e6d1aee4599729453bd11/mistletoe-1.4.0.tar.gz", hash = "sha256:1630f906e5e4bbe66fdeb4d29d277e2ea515d642bb18a9b49b136361a9818c9d", size = 107203 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/0f/b5e545f0c7962be90366af3418989b12cf441d9da1e5d89d88f2f3e5cf8f/mistletoe-1.4.0-py3-none-any.whl", hash = "sha256:44a477803861de1237ba22e375c6b617690a31d2902b47279d1f8f7ed498a794", size = 51304 },
+]
+
[[distribution]]
name = "mkdocs"
-version = "1.6.0"
+version = "1.4.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
@@ -1206,32 +1215,29 @@ dependencies = [
{ name = "ghp-import" },
{ name = "jinja2" },
{ name = "markdown" },
- { name = "markupsafe" },
{ name = "mergedeep" },
- { name = "mkdocs-get-deps" },
{ name = "packaging" },
- { name = "pathspec" },
{ name = "pyyaml" },
{ name = "pyyaml-env-tag" },
{ name = "watchdog" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/cc/6b/26b33cc8ad54e8bc0345cddc061c2c5c23e364de0ecd97969df23f95a673/mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512", size = 3888392 }
+sdist = { url = "https://files.pythonhosted.org/packages/b0/ef/49b4427e5eec761b77a3c3c421d3fd63010e2798b7401dc0fa2b875ef6b5/mkdocs-1.4.3.tar.gz", hash = "sha256:5955093bbd4dd2e9403c5afaf57324ad8b04f16886512a3ee6ef828956481c57", size = 3624951 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b8/c0/930dcf5a3e96b9c8e7ad15502603fc61d495479699e2d2c381e3d37294d1/mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7", size = 3862264 },
+ { url = "https://files.pythonhosted.org/packages/42/7a/5ed794942ace9d00bb77a8036c64c999cda6ebaab57e9b8a6ec1aa5fc900/mkdocs-1.4.3-py3-none-any.whl", hash = "sha256:6ee46d309bda331aac915cd24aab882c179a933bd9e77b80ce7d2eaaa3f689dd", size = 3654464 },
]
[[distribution]]
-name = "mkdocs-get-deps"
-version = "0.2.0"
+name = "mkdocs-plugin-commonmark"
+version = "0.0.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
- { name = "mergedeep" },
- { name = "platformdirs" },
- { name = "pyyaml" },
+ { name = "markdown" },
+ { name = "mistletoe" },
+ { name = "mkdocs" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239 }
+sdist = { url = "https://files.pythonhosted.org/packages/fa/a1/4aaa744deec61d75dbe3c67c18f6e4c1fa7699bc2661b6eff5f891e83023/mkdocs-plugin-commonmark-0.0.4.tar.gz", hash = "sha256:9034507af26646e95188a130782dd07d65c86507fddd3b47ea340c02683e85e7", size = 10805 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521 },
+ { url = "https://files.pythonhosted.org/packages/f9/4a/4333ef1eb57ff130c7715ba0847dbdae471d153d94507004c92c591cb3c5/mkdocs_plugin_commonmark-0.0.4-py3-none-any.whl", hash = "sha256:70a33394d86a04ec97877ca1b2dff6181de3ec01ef4c7add178fa45b327da535", size = 12532 },
]
[[distribution]]
@@ -1585,6 +1591,7 @@ dev = [
{ name = "pyopencl", marker = "platform_machine != 'aarch64'" },
{ name = "pyprof2calltree" },
{ name = "pyqt5", marker = "platform_machine == 'x86_64'" },
+ { name = "pytools", marker = "platform_machine != 'aarch64'" },
{ name = "pywinctl" },
{ name = "rerun-sdk" },
{ name = "tabulate" },
@@ -1594,6 +1601,7 @@ dev = [
docs = [
{ name = "jinja2" },
{ name = "mkdocs" },
+ { name = "mkdocs-plugin-commonmark" },
{ name = "mkdocs-terminal" },
]
testing = [
@@ -1705,15 +1713,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/31/13/fe468c8c7400a8eca204e6e160a29bf7dcd45a76e20f1c030f3eaa690d93/parameterized-0.8.1-py2.py3-none-any.whl", hash = "sha256:9cbb0b69a03e8695d68b3399a8a5825200976536fe1cb79db60ed6a4c8c9efe9", size = 26354 },
]
-[[distribution]]
-name = "pathspec"
-version = "0.12.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 },
-]
-
[[distribution]]
name = "pillow"
version = "10.4.0"
@@ -2042,15 +2041,15 @@ wheels = [
[[distribution]]
name = "pymdown-extensions"
-version = "10.8.1"
+version = "10.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "markdown" },
{ name = "pyyaml" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/09/11/0a1da270c1011194a6efee7ec1ac07d8b75a9706eed4a80675403f6a9d70/pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940", size = 812097 }
+sdist = { url = "https://files.pythonhosted.org/packages/85/71/5f48080bde77b07ca1eba6d7cb5c5598ac6c8f2a399846159b3c8b45e171/pymdown_extensions-10.4.tar.gz", hash = "sha256:bc46f11749ecd4d6b71cf62396104b4a200bad3498cb0f5dad1b8502fe461a35", size = 785151 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/c6/d7/e19f9bee2729a8d65b9bf822bb69ac364bf782bac8d761c62b4252769ae0/pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb", size = 250833 },
+ { url = "https://files.pythonhosted.org/packages/98/2d/2929de81618c7213176899dd6372d6ec9c8f24337841dd74634fb69864ae/pymdown_extensions-10.4-py3-none-any.whl", hash = "sha256:cfc28d6a09d19448bcbf8eee3ce098c7d17ff99f7bd3069db4819af181212037", size = 240838 },
]
[[distribution]]
@@ -4705,7 +4704,7 @@ wheels = [
[[distribution]]
name = "pytest"
-version = "8.3.1"
+version = "8.3.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
@@ -4713,9 +4712,9 @@ dependencies = [
{ name = "packaging" },
{ name = "pluggy" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/bc/7f/a6f79e033aa8318b6dfe2173fa6409ee75dafccf409d90884bf921433d88/pytest-8.3.1.tar.gz", hash = "sha256:7e8e5c5abd6e93cb1cc151f23e57adc31fcf8cfd2a3ff2da63e23f732de35db6", size = 1438997 }
+sdist = { url = "https://files.pythonhosted.org/packages/b4/8c/9862305bdcd6020bc7b45b1b5e7397a6caf1a33d3025b9a003b39075ffb2/pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce", size = 1439314 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b9/77/ccea391104f576a6e54a54334fc26d29c28aa0ec85714c781fbd2c34ac86/pytest-8.3.1-py3-none-any.whl", hash = "sha256:e9600ccf4f563976e2c99fa02c7624ab938296551f280835ee6516df8bc4ae8c", size = 341628 },
+ { url = "https://files.pythonhosted.org/packages/0f/f9/cf155cf32ca7d6fa3601bc4c5dd19086af4b320b706919d48a4c79081cf9/pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5", size = 341802 },
]
[[distribution]]
@@ -5049,27 +5048,27 @@ wheels = [
[[distribution]]
name = "ruff"
-version = "0.5.4"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/8e/1a/5955fa22ab088c1f4d8458b4cbc158c6db72143361e8d46e179c48576aab/ruff-0.5.4.tar.gz", hash = "sha256:2795726d5f71c4f4e70653273d1c23a8182f07dd8e48c12de5d867bfb7557eed", size = 2424702 }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/5b/34/2235ecce6794345f42ad334d1b14384c70b202f77509e5678b68a640fe78/ruff-0.5.4-py3-none-linux_armv6l.whl", hash = "sha256:82acef724fc639699b4d3177ed5cc14c2a5aacd92edd578a9e846d5b5ec18ddf", size = 9499774 },
- { url = "https://files.pythonhosted.org/packages/11/23/ffe51028ba274223191d3f96b059108cf7690eb93985a7fdb077c3d1191b/ruff-0.5.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:da62e87637c8838b325e65beee485f71eb36202ce8e3cdbc24b9fcb8b99a37be", size = 8550240 },
- { url = "https://files.pythonhosted.org/packages/28/75/843aa3d10a39ab60fbd63f65c825f647907a9732ac27e24d3f94dd2db618/ruff-0.5.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e98ad088edfe2f3b85a925ee96da652028f093d6b9b56b76fc242d8abb8e2059", size = 8160520 },
- { url = "https://files.pythonhosted.org/packages/19/88/3d0f5244905088cc2fd136fae8ce81f46d145e2449051313c462032d144d/ruff-0.5.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c55efbecc3152d614cfe6c2247a3054cfe358cefbf794f8c79c8575456efe19", size = 9911606 },
- { url = "https://files.pythonhosted.org/packages/1f/ff/6546020836408351e7558dedacc6e5ca7f652f76a9d05ac4882c787d45b1/ruff-0.5.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9b85eaa1f653abd0a70603b8b7008d9e00c9fa1bbd0bf40dad3f0c0bdd06793", size = 9286353 },
- { url = "https://files.pythonhosted.org/packages/b6/bf/51e0c5f12a9bf3c7596cf7f45e1b102f8b49f1da39943e03739890bbf6a4/ruff-0.5.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0cf497a47751be8c883059c4613ba2f50dd06ec672692de2811f039432875278", size = 10082929 },
- { url = "https://files.pythonhosted.org/packages/b5/0e/a44cb6edb629788de892fc7bb8ac8b47059df94d7ec9c4e52e04bab5be95/ruff-0.5.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:09c14ed6a72af9ccc8d2e313d7acf7037f0faff43cde4b507e66f14e812e37f7", size = 10832586 },
- { url = "https://files.pythonhosted.org/packages/97/ca/e3810f701ae472e5fe3180d56fe6fcc92ea94c7490097a0f731f5602f26f/ruff-0.5.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:628f6b8f97b8bad2490240aa84f3e68f390e13fabc9af5c0d3b96b485921cd60", size = 10421967 },
- { url = "https://files.pythonhosted.org/packages/01/47/a62df6ccd6e5d019271df203ea6564f2022c49f85c0bf6ada708cd7b4a5e/ruff-0.5.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3520a00c0563d7a7a7c324ad7e2cde2355733dafa9592c671fb2e9e3cd8194c1", size = 11371031 },
- { url = "https://files.pythonhosted.org/packages/a1/02/64f24893eea23c447460e6509e9dd0ae18d7a797f67fee1bafed964ebbae/ruff-0.5.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93789f14ca2244fb91ed481456f6d0bb8af1f75a330e133b67d08f06ad85b516", size = 10103164 },
- { url = "https://files.pythonhosted.org/packages/ca/78/683b6c6976fcc33e4a03a0e234e0b9f9b8682f807a661225c829b248de82/ruff-0.5.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:029454e2824eafa25b9df46882f7f7844d36fd8ce51c1b7f6d97e2615a57bbcc", size = 9920056 },
- { url = "https://files.pythonhosted.org/packages/78/3a/6c67c5d670aae2a51a11713aff819d729ed92cb0b1d962b8df27e4657650/ruff-0.5.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9492320eed573a13a0bc09a2957f17aa733fff9ce5bf00e66e6d4a88ec33813f", size = 9361286 },
- { url = "https://files.pythonhosted.org/packages/0d/f5/da3a0e2fd0bcbdb3d2ff579ef9cb3ca2af71b9bee97fa917c9a9e0500b67/ruff-0.5.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a6e1f62a92c645e2919b65c02e79d1f61e78a58eddaebca6c23659e7c7cb4ac7", size = 9720829 },
- { url = "https://files.pythonhosted.org/packages/4a/56/5062119a5c9e06d98cd6406bfc1eab7616a7c67494a4d05b6052d99dd147/ruff-0.5.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:768fa9208df2bec4b2ce61dbc7c2ddd6b1be9fb48f1f8d3b78b3332c7d71c1ff", size = 10143530 },
- { url = "https://files.pythonhosted.org/packages/e6/76/16f8f1c8d0cba6c96ab6f292146fc0acb6dd633a989f524d3b3ef1ee8364/ruff-0.5.4-py3-none-win32.whl", hash = "sha256:e1e7393e9c56128e870b233c82ceb42164966f25b30f68acbb24ed69ce9c3a4e", size = 7794271 },
- { url = "https://files.pythonhosted.org/packages/82/35/d6c3c83fb8817328db73c15b1836ccb0c3ce56b72d0d01d98b3a452bec58/ruff-0.5.4-py3-none-win_amd64.whl", hash = "sha256:58b54459221fd3f661a7329f177f091eb35cf7a603f01d9eb3eb11cc348d38c4", size = 8579021 },
- { url = "https://files.pythonhosted.org/packages/3c/ef/3e732c0152280775f728ab99691c718ee9a4ae79bf5af1dd9258f7fe7fef/ruff-0.5.4-py3-none-win_arm64.whl", hash = "sha256:bd53da65f1085fb5b307c38fd3c0829e76acf7b2a912d8d79cadcdb4875c1eb7", size = 8034239 },
+version = "0.5.5"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/95/15/3945cfecfd3de874633d2466327ebb01eabf4f61f962a0dd4bf5ce2dc997/ruff-0.5.5.tar.gz", hash = "sha256:cc5516bdb4858d972fbc31d246bdb390eab8df1a26e2353be2dbc0c2d7f5421a", size = 2434890 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2c/4d/f9e5e37369b22d74588fe496e82d2aa2fff508f0c05b34c38374194f5a8e/ruff-0.5.5-py3-none-linux_armv6l.whl", hash = "sha256:605d589ec35d1da9213a9d4d7e7a9c761d90bba78fc8790d1c5e65026c1b9eaf", size = 9505926 },
+ { url = "https://files.pythonhosted.org/packages/b3/48/ee53a87351dd03472cf1cb8073019a53a7282e4295e7ae62d7f5ae24202a/ruff-0.5.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00817603822a3e42b80f7c3298c8269e09f889ee94640cd1fc7f9329788d7bf8", size = 8585187 },
+ { url = "https://files.pythonhosted.org/packages/a2/ec/2c0bd5ec0965672bb2957abf6e44d93c2c7aab2ceb4251ea77eb9234ffd3/ruff-0.5.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:187a60f555e9f865a2ff2c6984b9afeffa7158ba6e1eab56cb830404c942b0f3", size = 8175846 },
+ { url = "https://files.pythonhosted.org/packages/8d/d7/e476f96c013d59af08b7b155f2beee03e7595915718573c724a01681bea8/ruff-0.5.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe26fc46fa8c6e0ae3f47ddccfbb136253c831c3289bba044befe68f467bfb16", size = 9948714 },
+ { url = "https://files.pythonhosted.org/packages/dd/da/00269f4905b5ceab77f64ec9ed2e8f848ccba68884b66b2423c9f8962878/ruff-0.5.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad25dd9c5faac95c8e9efb13e15803cd8bbf7f4600645a60ffe17c73f60779b", size = 9299822 },
+ { url = "https://files.pythonhosted.org/packages/c3/ce/8784906480809b5b43cfbb346bddcc3b9e8716fd73927e4d70fb5260c18e/ruff-0.5.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f70737c157d7edf749bcb952d13854e8f745cec695a01bdc6e29c29c288fc36e", size = 10100197 },
+ { url = "https://files.pythonhosted.org/packages/42/a4/4f4796e6b440ed42ec8486e19fe9b9489d94f13c2debf49e68ed58af5d0b/ruff-0.5.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:cfd7de17cef6ab559e9f5ab859f0d3296393bc78f69030967ca4d87a541b97a0", size = 10813891 },
+ { url = "https://files.pythonhosted.org/packages/a0/a4/9a0084212e0b2810beadd993f1b36f156438465a4d4193fd5bb2ab833892/ruff-0.5.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a09b43e02f76ac0145f86a08e045e2ea452066f7ba064fd6b0cdccb486f7c3e7", size = 10439725 },
+ { url = "https://files.pythonhosted.org/packages/8e/f7/4480e739af49f66f04edf2b1dd7ac6fa5e55639491e47267dbfa70d62488/ruff-0.5.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0b856cb19c60cd40198be5d8d4b556228e3dcd545b4f423d1ad812bfdca5884", size = 11358405 },
+ { url = "https://files.pythonhosted.org/packages/0e/fd/7a6e01b8098c3375ce694427956a8192c708941051cebd279b988304a753/ruff-0.5.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3687d002f911e8a5faf977e619a034d159a8373514a587249cc00f211c67a091", size = 10130793 },
+ { url = "https://files.pythonhosted.org/packages/2f/4a/ba83ca67da7e81a8a191da36f3f6a350243210518c78c2e809fb25cac6c4/ruff-0.5.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ac9dc814e510436e30d0ba535f435a7f3dc97f895f844f5b3f347ec8c228a523", size = 9910666 },
+ { url = "https://files.pythonhosted.org/packages/3f/6d/c982a93907559fa5cb62fd68c74b21662a4f088a09ad27f813244c7379c1/ruff-0.5.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:af9bdf6c389b5add40d89b201425b531e0a5cceb3cfdcc69f04d3d531c6be74f", size = 9365153 },
+ { url = "https://files.pythonhosted.org/packages/be/a6/b3dbdb4505086d80ab8202c8592ad90a811fc328dc4a5966e065cda12dcc/ruff-0.5.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d40a8533ed545390ef8315b8e25c4bb85739b90bd0f3fe1280a29ae364cc55d8", size = 9736802 },
+ { url = "https://files.pythonhosted.org/packages/4d/ba/b850fa0925ce59bc0bce412d18a9633a92126f23153f970437a51be711f0/ruff-0.5.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cab904683bf9e2ecbbe9ff235bfe056f0eba754d0168ad5407832928d579e7ab", size = 10198368 },
+ { url = "https://files.pythonhosted.org/packages/56/db/a9162178c90cada13f4c9bed9860947a1c5a79d7ecadd27250c67681dc81/ruff-0.5.5-py3-none-win32.whl", hash = "sha256:696f18463b47a94575db635ebb4c178188645636f05e934fdf361b74edf1bb2d", size = 7798506 },
+ { url = "https://files.pythonhosted.org/packages/c9/5b/13288039ea8190c121b70f1a11be2c4830cb3ebb57dc91d91fc5d3c65fc6/ruff-0.5.5-py3-none-win_amd64.whl", hash = "sha256:50f36d77f52d4c9c2f1361ccbfbd09099a1b2ea5d2b2222c586ab08885cf3445", size = 8611739 },
+ { url = "https://files.pythonhosted.org/packages/ba/b3/525847f73ab956053b130ec9f5d1ea078d94282b1d5eda90c09b8a81a935/ruff-0.5.5-py3-none-win_arm64.whl", hash = "sha256:3191317d967af701f1b73a31ed5788795936e423b7acce82a2b63e26eb3e89d6", size = 8039120 },
]
[[distribution]]
@@ -5124,15 +5123,15 @@ wheels = [
[[distribution]]
name = "sentry-sdk"
-version = "2.10.0"
+version = "2.11.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "urllib3" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/34/d8/ec3e43d4ce31e4f4cb6adb7210950362d71ce87a96c89934c4ac94f7110f/sentry_sdk-2.10.0.tar.gz", hash = "sha256:545fcc6e36c335faa6d6cda84669b6e17025f31efbf3b2211ec14efe008b75d1", size = 273996 }
+sdist = { url = "https://files.pythonhosted.org/packages/6d/b3/39e4cd04b75a1ada788342d0d30a781cf65b5e43da806d5bf2bad4846ea3/sentry_sdk-2.11.0.tar.gz", hash = "sha256:4ca16e9f5c7c6bc2fb2d5c956219f4926b148e511fffdbbde711dc94f1e0468f", size = 276242 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/4f/9e/9298785949269c8930e1fd3707b960da6e1a95a2442b747b8f8cca4578cb/sentry_sdk-2.10.0-py2.py3-none-any.whl", hash = "sha256:87b3d413c87d8e7f816cc9334bff255a83d8b577db2b22042651c30c19c09190", size = 302064 },
+ { url = "https://files.pythonhosted.org/packages/bc/3c/a8ab3309d22c1d7142f811882e7d45449696f87c6e4e723b1433b6069b84/sentry_sdk-2.11.0-py2.py3-none-any.whl", hash = "sha256:d964710e2dbe015d9dc4ff0ad16225d68c3b36936b742a6fe0504565b760a3b7", size = 303581 },
]
[[distribution]]