Merge remote-tracking branch 'upstream/master' into zstd-uploader

pull/32736/head
Shane Smiskol 11 months ago
commit 63fb36a2cc
  1. 45
      .github/workflows/jenkins-pr-trigger.yaml
  2. 55
      .github/workflows/selfdrive_tests.yaml
  3. 6
      .github/workflows/tools_tests.yaml
  4. 91
      .github/workflows/ui_preview.yaml
  5. 2
      README.md
  6. 1
      SConstruct
  7. 14
      selfdrive/controls/lib/longcontrol.py
  8. 56
      selfdrive/controls/tests/test_longcontrol.py
  9. 2
      selfdrive/modeld/models/commonmodel_pyx.pyx
  10. 2
      selfdrive/modeld/runners/runmodel_pyx.pyx
  11. 2
      selfdrive/modeld/runners/snpemodel_pyx.pyx
  12. 2
      selfdrive/modeld/runners/thneedmodel_pyx.pyx
  13. 4
      selfdrive/ui/qt/qt_window.cc
  14. 32
      system/camerad/cameras/camera_qcom2.cc
  15. 5
      system/camerad/cameras/camera_qcom2.h
  16. 2
      tools/install_python_dependencies.sh
  17. 313
      tools/op.sh
  18. 6
      tools/rerun/run.py

@ -0,0 +1,45 @@
name: jenkins scan
on:
issue_comment:
types: [created, edited]
jobs:
# TODO: gc old branches in a separate job in this workflow
scan-comments:
runs-on: ubuntu-latest
if: ${{ github.event.issue.pull_request }}
steps:
- name: Check for trigger phrase
id: check_comment
uses: actions/github-script@v7
with:
script: |
const triggerPhrase = "trigger-jenkins";
const comment = context.payload.comment.body;
const commenter = context.payload.comment.user.login;
const { data: permissions } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: commenter
});
const hasWriteAccess = permissions.permission === 'write' || permissions.permission === 'admin';
return (hasWriteAccess && comment.includes(triggerPhrase));
result-encoding: json
- name: Checkout repository
if: steps.check_comment.outputs.result == 'true'
uses: actions/checkout@v4
with:
ref: refs/pull/${{ github.event.issue.number }}/head
- name: Push to tmp-jenkins branch
if: steps.check_comment.outputs.result == 'true'
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b tmp-jenkins-${{ github.event.issue.number }}
GIT_LFS_SKIP_PUSH=1 git push -f origin tmp-jenkins-${{ github.event.issue.number }}

@ -338,6 +338,7 @@ jobs:
}) })
create_ui_report: create_ui_report:
# This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml
name: Create UI Report name: Create UI Report
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -355,55 +356,5 @@ jobs:
- name: Upload Test Report - name: Upload Test Report
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: report-${{ inputs.run_number || '1' }} name: report-${{ github.event.number }}
path: selfdrive/ui/tests/test_ui/report_${{ inputs.run_number || '1' }} path: selfdrive/ui/tests/test_ui/report_1/screenshots
- name: Get changes to selfdrive/ui
if: ${{ github.event_name == 'pull_request' }}
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
selfdrive/ui/**
- name: Checkout ci-artifacts
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
uses: actions/checkout@v4
with:
repository: commaai/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
path: ${{ github.workspace }}/ci-artifacts
ref: master
- name: Push Screenshots
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
working-directory: ${{ github.workspace }}/ci-artifacts
run: |
git checkout -b openpilot/pr-${{ github.event.pull_request.number }}
git config user.name "GitHub Actions Bot"
git config user.email "<>"
sudo mv ${{ github.workspace }}/selfdrive/ui/tests/test_ui/report_1/screenshots/* .
git add .
git commit -m "screenshots for PR #${{ github.event.pull_request.number }}"
git push origin openpilot/pr-${{ github.event.pull_request.number }} --force
- name: Comment Screenshots on PR
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
uses: thollander/actions-comment-pull-request@v2
with:
message: |
<!-- _(run_id_screenshots **${{ github.run_id }}**)_ -->
## UI Screenshots
<table>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/homescreen.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad_map.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad_sidebar.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/settings_network.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/settings_device.png"></td>
</tr>
</table>
comment_tag: run_id_screenshots
pr_number: ${{ github.event.pull_request.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

@ -73,12 +73,6 @@ jobs:
scons-${{ runner.arch }}-ubuntu2004 scons-${{ runner.arch }}-ubuntu2004
- name: Building openpilot - name: Building openpilot
run: uv run scons -u -j$(nproc) run: uv run scons -u -j$(nproc)
- name: Saving scons cache
uses: actions/cache/save@v4
if: github.ref == 'refs/heads/master'
with:
path: /tmp/scons_cache
key: scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
devcontainer: devcontainer:
name: devcontainer name: devcontainer

@ -0,0 +1,91 @@
name: "ui preview"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened, edited]
branches:
- 'master'
paths:
- 'selfdrive/ui/**'
env:
UI_JOB_NAME: "Create UI Report"
jobs:
preview:
if: github.repository == 'commaai/openpilot'
name: preview
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
actions: read
steps:
- name: Waiting for ui test to start
run: sleep 30
- name: Wait for ui report
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: ${{ env.UI_JOB_NAME }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
allowed-conclusions: success
wait-interval: 20
- name: Get workflow run ID
id: get_run_id
run: |
echo "run_id=$(curl https://api.github.com/repos/${{ github.repository }}/commits/${{ github.event.pull_request.head.sha }}/check-runs | jq -r '.check_runs[] | select(.name == "${{ env.UI_JOB_NAME }}") | .html_url | capture("(?<number>[0-9]+)") | .number')" >> $GITHUB_OUTPUT
- name: Checkout ci-artifacts
uses: actions/checkout@v4
with:
repository: commaai/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
path: ${{ github.workspace }}/ci-artifacts
ref: master
- name: Download artifact
id: download-artifact
uses: dawidd6/action-download-artifact@v6
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ steps.get_run_id.outputs.run_id }}
search_artifacts: true
name: report-${{ github.event.number }}
path: ${{ github.workspace }}/ci-artifacts
- name: Push Screenshots
working-directory: ${{ github.workspace }}/ci-artifacts
run: |
git checkout -b openpilot/pr-${{ github.event.number }}
git config user.name "GitHub Actions Bot"
git config user.email "<>"
git add ${{ github.workspace }}/ci-artifacts/*
git commit -m "screenshots for PR #${{ github.event.number }}"
git push origin openpilot/pr-${{ github.event.number }} --force
- name: Comment Screenshots on PR
uses: thollander/actions-comment-pull-request@v2
with:
message: |
<!-- _(run_id_screenshots **${{ github.run_id }}**)_ -->
## UI Screenshots
<table>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/homescreen.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/onroad.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/onroad_map.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/onroad_sidebar.png"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/settings_network.png"></td>
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.number }}/settings_device.png"></td>
</tr>
</table>
comment_tag: run_id_screenshots
pr_number: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

@ -19,7 +19,7 @@ To start using openpilot in a car
To use openpilot in a car, you need four things: To use openpilot in a car, you need four things:
1. **Supported Device:** a comma 3/3X, available at [comma.ai/shop](https://comma.ai/shop/comma-3x). 1. **Supported Device:** a comma 3/3X, available at [comma.ai/shop](https://comma.ai/shop/comma-3x).
2. **Software:** The setup procedure for the comma 3/3X allows users to enter a URL for custom software. Use the URL `openpilot.comma.ai` to install the release version. 2. **Software:** The setup procedure for the comma 3/3X allows users to enter a URL for custom software. Use the URL `openpilot.comma.ai` to install the release version.
3. **Supported Car:** Ensure that you have one of [the 250+ supported cars](docs/CARS.md). 3. **Supported Car:** Ensure that you have one of [the 275+ supported cars](docs/CARS.md).
4. **Car Harness:** You will also need a [car harness](https://comma.ai/shop/car-harness) to connect your comma 3/3X to your car. 4. **Car Harness:** You will also need a [car harness](https://comma.ai/shop/car-harness) to connect your comma 3/3X to your car.
We have detailed instructions for [how to install the harness and device in a car](https://comma.ai/setup). Note that it's possible to run openpilot on [other hardware](https://blog.comma.ai/self-driving-car-for-free/), although it's not plug-and-play. We have detailed instructions for [how to install the harness and device in a car](https://comma.ai/setup). Note that it's possible to run openpilot on [other hardware](https://blog.comma.ai/self-driving-car-for-free/), although it's not plug-and-play.

@ -102,7 +102,6 @@ if arch == "larch64":
libpath = [ libpath = [
"/usr/local/lib", "/usr/local/lib",
"/usr/lib",
"/system/vendor/lib64", "/system/vendor/lib64",
f"#third_party/acados/{arch}/lib", f"#third_party/acados/{arch}/lib",
] ]

@ -22,22 +22,26 @@ def long_control_state_trans(CP, active, long_control_state, v_ego,
long_control_state = LongCtrlState.off long_control_state = LongCtrlState.off
else: else:
if long_control_state in (LongCtrlState.off, LongCtrlState.pid): if long_control_state == LongCtrlState.off:
long_control_state = LongCtrlState.pid if not starting_condition:
if stopping_condition:
long_control_state = LongCtrlState.stopping long_control_state = LongCtrlState.stopping
else:
if starting_condition and CP.startingState:
long_control_state = LongCtrlState.starting
else:
long_control_state = LongCtrlState.pid
elif long_control_state == LongCtrlState.stopping: elif long_control_state == LongCtrlState.stopping:
if starting_condition and CP.startingState: if starting_condition and CP.startingState:
long_control_state = LongCtrlState.starting long_control_state = LongCtrlState.starting
elif starting_condition: elif starting_condition:
long_control_state = LongCtrlState.pid long_control_state = LongCtrlState.pid
elif long_control_state == LongCtrlState.starting: elif long_control_state in [LongCtrlState.starting, LongCtrlState.pid]:
if stopping_condition: if stopping_condition:
long_control_state = LongCtrlState.stopping long_control_state = LongCtrlState.stopping
elif started_condition: elif started_condition:
long_control_state = LongCtrlState.pid long_control_state = LongCtrlState.pid
return long_control_state return long_control_state
class LongControl: class LongControl:

@ -0,0 +1,56 @@
from cereal import car
from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState, long_control_state_trans
class TestLongControlStateTransition:
def test_stay_stopped(self):
CP = car.CarParams.new_message()
active = True
current_state = LongCtrlState.stopping
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=True, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=True, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=False, cruise_standstill=True)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.pid
active = False
next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.off
def test_engage():
CP = car.CarParams.new_message()
active = True
current_state = LongCtrlState.off
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=True, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=True, cruise_standstill=False)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=False, cruise_standstill=True)
assert next_state == LongCtrlState.stopping
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.pid
def test_starting():
CP = car.CarParams.new_message(startingState=True, vEgoStarting=0.5)
active = True
current_state = LongCtrlState.starting
next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.starting
next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0,
should_stop=False, brake_pressed=False, cruise_standstill=False)
assert next_state == LongCtrlState.pid

@ -1,5 +1,5 @@
# distutils: language = c++ # distutils: language = c++
# cython: c_string_encoding=ascii # cython: c_string_encoding=ascii, language_level=3
import numpy as np import numpy as np
cimport numpy as cnp cimport numpy as cnp

@ -1,5 +1,5 @@
# distutils: language = c++ # distutils: language = c++
# cython: c_string_encoding=ascii # cython: c_string_encoding=ascii, language_level=3
from libcpp.string cimport string from libcpp.string cimport string

@ -1,5 +1,5 @@
# distutils: language = c++ # distutils: language = c++
# cython: c_string_encoding=ascii # cython: c_string_encoding=ascii, language_level=3
import os import os
from libcpp cimport bool from libcpp cimport bool

@ -1,5 +1,5 @@
# distutils: language = c++ # distutils: language = c++
# cython: c_string_encoding=ascii # cython: c_string_encoding=ascii, language_level=3
from libcpp cimport bool from libcpp cimport bool
from libcpp.string cimport string from libcpp.string cimport string

@ -18,7 +18,9 @@ void setMainWindow(QWidget *w) {
wl_surface *s = reinterpret_cast<wl_surface*>(native->nativeResourceForWindow("surface", w->windowHandle())); wl_surface *s = reinterpret_cast<wl_surface*>(native->nativeResourceForWindow("surface", w->windowHandle()));
wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270); wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270);
wl_surface_commit(s); wl_surface_commit(s);
w->showFullScreen();
w->setWindowState(Qt::WindowFullScreen);
w->setVisible(true);
// ensure we have a valid eglDisplay, otherwise the ui will silently fail // ensure we have a valid eglDisplay, otherwise the ui will silently fail
void *egl = native->nativeResourceForWindow("egldisplay", w->windowHandle()); void *egl = native->nativeResourceForWindow("egldisplay", w->windowHandle());

@ -469,6 +469,16 @@ void CameraState::camera_open(MultiCameraState *multi_cam_state_, int camera_num
enabled = enabled_; enabled = enabled_;
if (!enabled) return; if (!enabled) return;
if (!openSensor()) {
return;
}
configISP();
configCSIPHY();
linkDevices();
}
bool CameraState::openSensor() {
sensor_fd = open_v4l_by_name_and_index("cam-sensor-driver", camera_num); sensor_fd = open_v4l_by_name_and_index("cam-sensor-driver", camera_num);
assert(sensor_fd >= 0); assert(sensor_fd >= 0);
LOGD("opened sensor for %d", camera_num); LOGD("opened sensor for %d", camera_num);
@ -493,7 +503,7 @@ void CameraState::camera_open(MultiCameraState *multi_cam_state_, int camera_num
!init_sensor_lambda(new OS04C10)) { !init_sensor_lambda(new OS04C10)) {
LOGE("** sensor %d FAILED bringup, disabling", camera_num); LOGE("** sensor %d FAILED bringup, disabling", camera_num);
enabled = false; enabled = false;
return; return false;
} }
LOGD("-- Probing sensor %d success", camera_num); LOGD("-- Probing sensor %d success", camera_num);
@ -512,7 +522,10 @@ void CameraState::camera_open(MultiCameraState *multi_cam_state_, int camera_num
LOG("-- Configuring sensor"); LOG("-- Configuring sensor");
sensors_i2c(ci->init_reg_array.data(), ci->init_reg_array.size(), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, ci->data_word); sensors_i2c(ci->init_reg_array.data(), ci->init_reg_array.size(), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, ci->data_word);
return true;
}
void CameraState::configISP() {
// NOTE: to be able to disable road and wide road, we still have to configure the sensor over i2c // NOTE: to be able to disable road and wide road, we still have to configure the sensor over i2c
// If you don't do this, the strobe GPIO is an output (even in reset it seems!) // If you don't do this, the strobe GPIO is an output (even in reset it seems!)
if (!enabled) return; if (!enabled) return;
@ -570,6 +583,13 @@ void CameraState::camera_open(MultiCameraState *multi_cam_state_, int camera_num
isp_dev_handle = *isp_dev_handle_; isp_dev_handle = *isp_dev_handle_;
LOGD("acquire isp dev"); LOGD("acquire isp dev");
// config ISP
alloc_w_mmu_hdl(multi_cam_state->video0_fd, 984480, (uint32_t*)&buf0_handle, 0x20, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS |
CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, multi_cam_state->device_iommu, multi_cam_state->cdm_iommu);
config_isp(0, 0, 1, buf0_handle, 0);
}
void CameraState::configCSIPHY() {
csiphy_fd = open_v4l_by_name_and_index("cam-csiphy-driver", camera_num); csiphy_fd = open_v4l_by_name_and_index("cam-csiphy-driver", camera_num);
assert(csiphy_fd >= 0); assert(csiphy_fd >= 0);
LOGD("opened csiphy for %d", camera_num); LOGD("opened csiphy for %d", camera_num);
@ -580,11 +600,6 @@ void CameraState::camera_open(MultiCameraState *multi_cam_state_, int camera_num
csiphy_dev_handle = *csiphy_dev_handle_; csiphy_dev_handle = *csiphy_dev_handle_;
LOGD("acquire csiphy dev"); LOGD("acquire csiphy dev");
// config ISP
alloc_w_mmu_hdl(multi_cam_state->video0_fd, 984480, (uint32_t*)&buf0_handle, 0x20, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS |
CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, multi_cam_state->device_iommu, multi_cam_state->cdm_iommu);
config_isp(0, 0, 1, buf0_handle, 0);
// config csiphy // config csiphy
LOG("-- Config CSI PHY"); LOG("-- Config CSI PHY");
{ {
@ -612,15 +627,16 @@ void CameraState::camera_open(MultiCameraState *multi_cam_state_, int camera_num
int ret_ = device_config(csiphy_fd, session_handle, csiphy_dev_handle, cam_packet_handle); int ret_ = device_config(csiphy_fd, session_handle, csiphy_dev_handle, cam_packet_handle);
assert(ret_ == 0); assert(ret_ == 0);
} }
}
// link devices void CameraState::linkDevices() {
LOG("-- Link devices"); LOG("-- Link devices");
struct cam_req_mgr_link_info req_mgr_link_info = {0}; struct cam_req_mgr_link_info req_mgr_link_info = {0};
req_mgr_link_info.session_hdl = session_handle; req_mgr_link_info.session_hdl = session_handle;
req_mgr_link_info.num_devices = 2; req_mgr_link_info.num_devices = 2;
req_mgr_link_info.dev_hdls[0] = isp_dev_handle; req_mgr_link_info.dev_hdls[0] = isp_dev_handle;
req_mgr_link_info.dev_hdls[1] = sensor_dev_handle; req_mgr_link_info.dev_hdls[1] = sensor_dev_handle;
ret = do_cam_control(multi_cam_state->video0_fd, CAM_REQ_MGR_LINK, &req_mgr_link_info, sizeof(req_mgr_link_info)); int ret = do_cam_control(multi_cam_state->video0_fd, CAM_REQ_MGR_LINK, &req_mgr_link_info, sizeof(req_mgr_link_info));
link_handle = req_mgr_link_info.link_hdl; link_handle = req_mgr_link_info.link_hdl;
LOGD("link: %d session: 0x%X isp: 0x%X sensors: 0x%X link: 0x%X", ret, session_handle, isp_dev_handle, sensor_dev_handle, link_handle); LOGD("link: %d session: 0x%X isp: 0x%X sensors: 0x%X link: 0x%X", ret, session_handle, isp_dev_handle, sensor_dev_handle, link_handle);

@ -86,6 +86,11 @@ public:
void sensors_i2c(const struct i2c_random_wr_payload* dat, int len, int op_code, bool data_word); void sensors_i2c(const struct i2c_random_wr_payload* dat, int len, int op_code, bool data_word);
private: private:
bool openSensor();
void configISP();
void configCSIPHY();
void linkDevices();
// for debugging // for debugging
Params params; Params params;
}; };

@ -34,7 +34,7 @@ update_uv
# TODO: remove --no-cache once this is fixed: https://github.com/astral-sh/uv/issues/4378 # TODO: remove --no-cache once this is fixed: https://github.com/astral-sh/uv/issues/4378
echo "installing python packages..." echo "installing python packages..."
uv --no-cache sync --all-extras uv --no-cache sync --frozen --all-extras
source .venv/bin/activate source .venv/bin/activate
echo "PYTHONPATH=${PWD}" > $ROOT/.env echo "PYTHONPATH=${PWD}" > $ROOT/.env

@ -0,0 +1,313 @@
#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
UNDERLINE='\033[4m'
BOLD='\033[1m'
NC='\033[0m'
function op_first_install() {
(set -e
echo "Installing op system-wide..."
RC_FILE="${HOME}/.$(basename ${SHELL})rc"
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
echo -e " ↳ [${GREEN}${NC}] op installed successfully. Open a new shell to use it.\n"
)
}
# be default, assume openpilot dir is in current directory
OPENPILOT_ROOT=$(pwd)
function op_check_openpilot_dir() {
while [[ "$OPENPILOT_ROOT" != '/' ]];
do
if find "$OPENPILOT_ROOT/launch_openpilot.sh" -maxdepth 1 -mindepth 1 &> /dev/null; then
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!"
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!"
return 1
else
echo -e " ↳ [${GREEN}${NC}] git found on your system.\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"
return 1
else
echo -e " ↳ [${GREEN}${NC}] git lfs files found on your system.\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
)
}
function op_check_os() {
(set -e
echo "Checking for compatible os version..."
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if [ -f "/etc/os-release" ]; then
source /etc/os-release
case "$VERSION_CODENAME" in
"jammy" | "kinetic" | "noble" | "focal")
echo -e " ↳ [${GREEN}${NC}] Ubuntu $VERSION_CODENAME detected.\n"
;;
* )
echo -e " ↳ [${RED}${NC}] Incompatible Ubuntu version $VERSION_CODENAME detected!"
return 1
;;
esac
else
echo -e " ↳ [${RED}${NC}] No /etc/os-release on your system. Make sure you're running on Ubuntu, or similar!"
return 1
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo -e " ↳ [${GREEN}${NC}] macos detected.\n"
else
echo -e " ↳ [${RED}${NC}] OS type $OSTYPE not supported!"
return 1
fi
)
}
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!"
return 1
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
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() {
(set -e
op_check_openpilot_dir
cd $OPENPILOT_ROOT
op_check_git
op_check_os
op_check_python
)
}
function op_run() {
(set -e
op_venv
cd $OPENPILOT_ROOT
op_run_command $OPENPILOT_ROOT/launch_openpilot.sh
)
}
function op_install() {
(set -e
op_check_openpilot_dir
cd $OPENPILOT_ROOT
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
fi
git submodule update --init --recursive
git lfs pull
)
}
function op_build() {
(set -e
op_venv
cd $OPENPILOT_ROOT
op_run_command scons $@
)
}
function op_juggle() {
(set -e
op_venv
cd $OPENPILOT_ROOT
op_run_command $OPENPILOT_ROOT/tools/plotjuggler/juggle.py $@
)
}
function op_linter() {
(set -e
op_venv
cd $OPENPILOT_ROOT
op_run_command pre-commit run --all $@
)
}
function op_replay() {
(set -e
op_check_openpilot_dir
cd $OPENPILOT_ROOT
op_run_command $OPENPILOT_ROOT/tools/replay/replay $@
)
}
function op_default() {
echo "An openpilot helper"
echo ""
echo -e "${BOLD}${UNDERLINE}Description:${NC}"
echo " op is your entry point for all things related to openpilot development."
echo " op is only a wrapper for scripts, tools and commands already existing."
echo " op will always show you what it will run on your system."
echo ""
echo " op will try to find your openpilot directory in the following order:"
echo " 1: use the directory specified with the --dir option"
echo " 2: use the current working directory"
echo " 3: go up the file tree non-recursively"
echo ""
echo -e "${BOLD}${UNDERLINE}Usage:${NC} op [OPTIONS] <COMMAND>"
echo ""
echo -e "${BOLD}${UNDERLINE}Commands:${NC}"
echo -e " ${BOLD}venv${NC} Activate the virtual environment"
echo -e " ${BOLD}check${NC} Check system requirements (git, os, python) to start using openpilot"
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}juggle${NC} Run Plotjuggler"
echo -e " ${BOLD}replay${NC} Run replay"
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"
echo ""
echo -e "${BOLD}${UNDERLINE}Options:${NC}"
echo -e " ${BOLD}-d, --dir${NC}"
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 ""
echo -e "${BOLD}${UNDERLINE}Examples:${NC}"
echo " op --dir /tmp/openpilot check"
echo " Run the check command on openpilot located in /tmp/openpilot"
echo ""
echo " op juggle --install"
echo " Install plotjuggler in the openpilot located in your current"
echo " working directory"
echo ""
echo " op --dir /tmp/openpilot build -j4"
echo " Run the build command on openpilot located in /tmp/openpilot"
echo " on 4 cores"
}
function _op() {
# parse Options
case $1 in
-d | --dir ) shift 1; OPENPILOT_ROOT="$1"; shift 1 ;;
--dry ) shift 1; DRY="1" ;;
esac
# parse Commands
case $1 in
venv ) shift 1; op_venv "$@" ;;
check ) shift 1; op_check "$@" ;;
install ) shift 1; op_install "$@" ;;
build ) shift 1; op_build "$@" ;;
run ) shift 1; op_run "$@" ;;
juggle ) shift 1; op_juggle "$@" ;;
linter ) shift 1; op_linter "$@" ;;
replay ) shift 1; op_replay "$@" ;;
--install ) shift 1; op_first_install "$@" ;;
* ) op_default "$@" ;;
esac
}
_op $@
# remove from env
unset -f _op
unset -f op_check
unset -f op_install
unset -f op_build
unset -f op_run
unset -f op_juggle
unset -f op_venv
unset -f op_check_openpilot_dir
unset -f op_check_git
unset -f op_check_python
unset -f op_check_os
unset -f op_first_install
unset -f op_default
unset -f op_run_command
unset -f op_linter
unset -f op_replay
unset DRY
unset OPENPILOT_ROOT

@ -18,6 +18,12 @@ RR_TIMELINE_NAME = "Timeline"
RR_WIN = "rerun_test" RR_WIN = "rerun_test"
"""
Relevant upstream Rerun issues:
- large time series: https://github.com/rerun-io/rerun/issues/5967
- loading videos directly: https://github.com/rerun-io/rerun/issues/6532
"""
class Rerunner: class Rerunner:
def __init__(self, route, segment_range, camera_config, enabled_services): def __init__(self, route, segment_range, camera_config, enabled_services):
self.enabled_services = [s.lower() for s in enabled_services] self.enabled_services = [s.lower() for s in enabled_services]

Loading…
Cancel
Save