Merge branch 'upstream/openpilot/master' into sync-20250215

# Conflicts:
#	common/params.cc
#	opendbc_repo
#	panda
#	selfdrive/car/tests/test_models.py
#	selfdrive/modeld/fill_model_msg.py
#	selfdrive/test/process_replay/process_replay.py
#	selfdrive/test/process_replay/ref_commit
#	selfdrive/ui/qt/offroad/developer_panel.cc
#	selfdrive/ui/tests/test_ui/run.py
#	selfdrive/ui/translations/main_ar.ts
#	selfdrive/ui/translations/main_de.ts
#	selfdrive/ui/translations/main_es.ts
#	selfdrive/ui/translations/main_fr.ts
#	selfdrive/ui/translations/main_ja.ts
#	selfdrive/ui/translations/main_ko.ts
#	selfdrive/ui/translations/main_pt-BR.ts
#	selfdrive/ui/translations/main_th.ts
#	selfdrive/ui/translations/main_tr.ts
#	selfdrive/ui/translations/main_zh-CHS.ts
#	selfdrive/ui/translations/main_zh-CHT.ts
#	system/athena/athenad.py
This commit is contained in:
Jason Wen
2025-02-15 20:19:43 -05:00
141 changed files with 2619 additions and 1336 deletions
+1 -1
View File
@@ -322,7 +322,7 @@ jobs:
run: | run: |
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \ ${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
source selfdrive/test/setup_vsound.sh && \ source selfdrive/test/setup_vsound.sh && \
CI=1 pytest tools/sim/tests/test_metadrive_bridge.py" CI=1 pytest -s tools/sim/tests/test_metadrive_bridge.py"
create_ui_report: create_ui_report:
# This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml # This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml
Vendored
+2 -2
View File
@@ -103,7 +103,7 @@ def deviceStage(String stageName, String deviceType, List extra_env, def steps)
def diffPaths = args.diffPaths ?: [] def diffPaths = args.diffPaths ?: []
def cmdTimeout = args.timeout ?: 9999 def cmdTimeout = args.timeout ?: 9999
if (branch != "master" && diffPaths && !hasPathChanged(gitDiff, diffPaths)) { if (branch != "master" && !branch.contains("__jenkins_loop_") && diffPaths && !hasPathChanged(gitDiff, diffPaths)) {
println "Skipping ${name}: no changes in ${diffPaths}." println "Skipping ${name}: no changes in ${diffPaths}."
return return
} else { } else {
@@ -170,7 +170,7 @@ node {
'testing-closet*', 'hotfix-*'] 'testing-closet*', 'hotfix-*']
def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*') def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*')
if (env.BRANCH_NAME != 'master') { if (env.BRANCH_NAME != 'master' && !env.BRANCH_NAME.contains('__jenkins_loop_')) {
properties([ properties([
disableConcurrentBuilds(abortPrevious: true) disableConcurrentBuilds(abortPrevious: true)
]) ])
+13 -14
View File
@@ -1,23 +1,22 @@
Version 0.9.9 (2025-03-30) Version 0.9.8 (2025-02-27)
======================== ========================
* New driving model
* Model now gates applying positive acceleration in Chill mode
* New driving monitoring model
* Reduced false positives related to passengers
* Image processing pipeline moved to the ISP
* More GPU time for bigger driving models
* Power draw reduced 0.5W, which means your device runs cooler
* Added toggle to enable driver monitoring even when openpilot is not engaged
* FIREHOSE mode
* Allows you to maximize your training data uploads to improve the models
* Enable openpilot longitudinal control for Ford Q3 vehicles
* New Toyota TSS2 longitudinal tune
* Coming soon * Coming soon
* Rivian support * Rivian support
* F-150 & Mach-E support * F-150 & Mach-E support
* Tesla Model 3 support * Tesla Model 3 support
Version 0.9.8 (2025-01-30)
========================
* New driving monitoring model
* Reduced false positives related to passengers
* Image processing pipeline moved to the ISP
* More GPU time for driving models
* Power draw reduced 0.5W, which means your device runs cooler
* Added toggle to enable driver monitoring even when openpilot is not engaged
* Enable openpilot longitudinal control for Ford Q3 vehicles
* New Toyota TSS2 longitudinal tune
* Coming soon
* New driving model with gas gating
* Training data upload mode
Version 0.9.7 (2024-06-13) Version 0.9.7 (2024-06-13)
======================== ========================
+1 -2
View File
@@ -361,7 +361,7 @@ SConscript(['opendbc_repo/SConscript'], exports={'env': env_swaglog})
SConscript(['cereal/SConscript']) SConscript(['cereal/SConscript'])
Import('socketmaster', 'msgq') Import('socketmaster', 'msgq')
messaging = [socketmaster, msgq, 'zmq', 'capnp', 'kj',] messaging = [socketmaster, msgq, 'capnp', 'kj',]
Export('messaging') Export('messaging')
@@ -373,7 +373,6 @@ SConscript(['rednose/SConscript'])
# Build system services # Build system services
SConscript([ SConscript([
'system/ui/SConscript',
'system/proclogd/SConscript', 'system/proclogd/SConscript',
'system/ubloxd/SConscript', 'system/ubloxd/SConscript',
'system/loggerd/SConscript', 'system/loggerd/SConscript',
+4 -4
View File
@@ -29,7 +29,7 @@ _services: dict[str, tuple] = {
"pandaStates": (True, 10., 1), "pandaStates": (True, 10., 1),
"peripheralState": (True, 2., 1), "peripheralState": (True, 2., 1),
"radarState": (True, 20., 5), "radarState": (True, 20., 5),
"roadEncodeIdx": (False, 20., 1), "roadEncodeIdx": (False, 20., 20),
"liveTracks": (True, 20.), "liveTracks": (True, 20.),
"sendcan": (True, 100., 139), "sendcan": (True, 100., 139),
"logMessage": (True, 0.), "logMessage": (True, 0.),
@@ -53,15 +53,15 @@ _services: dict[str, tuple] = {
"livePose": (True, 20., 4), "livePose": (True, 20., 4),
"liveParameters": (True, 20., 5), "liveParameters": (True, 20., 5),
"cameraOdometry": (True, 20., 10), "cameraOdometry": (True, 20., 10),
"thumbnail": (True, 0.2, 1), "thumbnail": (True, 1 / 60., 1),
"onroadEvents": (True, 1., 1), "onroadEvents": (True, 1., 1),
"carParams": (True, 0.02, 1), "carParams": (True, 0.02, 1),
"roadCameraState": (True, 20., 20), "roadCameraState": (True, 20., 20),
"driverCameraState": (True, 20., 20), "driverCameraState": (True, 20., 20),
"driverEncodeIdx": (False, 20., 1), "driverEncodeIdx": (False, 20., 20),
"driverStateV2": (True, 20., 10), "driverStateV2": (True, 20., 10),
"driverMonitoringState": (True, 20., 10), "driverMonitoringState": (True, 20., 10),
"wideRoadEncodeIdx": (False, 20., 1), "wideRoadEncodeIdx": (False, 20., 20),
"wideRoadCameraState": (True, 20., 20), "wideRoadCameraState": (True, 20., 20),
"drivingModelData": (True, 20., 10), "drivingModelData": (True, 20., 10),
"modelV2": (True, 20.), "modelV2": (True, 20.),
+21
View File
@@ -1,6 +1,10 @@
import io
import os import os
import tempfile import tempfile
import contextlib import contextlib
import zstandard as zstd
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
class CallbackReader: class CallbackReader:
@@ -35,3 +39,20 @@ def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encodin
yield tmp_file yield tmp_file
tmp_file_name = tmp_file.name tmp_file_name = tmp_file.name
os.replace(tmp_file_name, path) os.replace(tmp_file_name, path)
def get_upload_stream(filepath: str, should_compress: bool) -> tuple[io.BufferedIOBase, int]:
if not should_compress:
file_size = os.path.getsize(filepath)
file_stream = open(filepath, "rb")
return file_stream, file_size
# Compress the file on the fly
compressed_stream = io.BytesIO()
compressor = zstd.ZstdCompressor(level=LOG_COMPRESSION_LEVEL)
with open(filepath, "rb") as f:
compressor.copy_stream(f, compressed_stream)
compressed_size = compressed_stream.tell()
compressed_stream.seek(0)
return compressed_stream, compressed_size
+1 -1
View File
@@ -1 +1 @@
#define DEFAULT_MODEL "Notre Dame (Default)" #define DEFAULT_MODEL "Not Too Shabby (Default)"
+1
View File
@@ -120,6 +120,7 @@ std::unordered_map<std::string, uint32_t> keys = {
{"ExperimentalLongitudinalEnabled", PERSISTENT | DEVELOPMENT_ONLY | BACKUP}, {"ExperimentalLongitudinalEnabled", PERSISTENT | DEVELOPMENT_ONLY | BACKUP},
{"ExperimentalMode", PERSISTENT | BACKUP}, {"ExperimentalMode", PERSISTENT | BACKUP},
{"ExperimentalModeConfirmed", PERSISTENT | BACKUP}, {"ExperimentalModeConfirmed", PERSISTENT | BACKUP},
{"FirehoseMode", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"FirmwareQueryDone", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION}, {"FirmwareQueryDone", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"ForcePowerDown", PERSISTENT}, {"ForcePowerDown", PERSISTENT},
{"GitBranch", PERSISTENT}, {"GitBranch", PERSISTENT},
+2 -6
View File
@@ -27,11 +27,6 @@ class Priority:
CTRL_HIGH = 53 CTRL_HIGH = 53
def set_realtime_priority(level: int) -> None:
if not PC:
os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(level))
def set_core_affinity(cores: list[int]) -> None: def set_core_affinity(cores: list[int]) -> None:
if not PC: if not PC:
os.sched_setaffinity(0, cores) os.sched_setaffinity(0, cores)
@@ -39,7 +34,8 @@ def set_core_affinity(cores: list[int]) -> None:
def config_realtime_process(cores: int | list[int], priority: int) -> None: def config_realtime_process(cores: int | list[int], priority: int) -> None:
gc.disable() gc.disable()
set_realtime_priority(priority) if not PC:
os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(priority))
c = cores if isinstance(cores, list) else [cores, ] c = cores if isinstance(cores, list) else [cores, ]
set_core_affinity(c) set_core_affinity(c)
+1 -1
View File
@@ -184,7 +184,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Lexus|RX Hybrid 2016|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2016">Buy Here</a></sub></details>|| |Lexus|RX Hybrid 2016|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2016">Buy Here</a></sub></details>||
|Lexus|RX Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2017-19">Buy Here</a></sub></details>|| |Lexus|RX Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2017-19">Buy Here</a></sub></details>||
|Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2020-22">Buy Here</a></sub></details>|| |Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2020-22">Buy Here</a></sub></details>||
|Lexus|UX Hybrid 2019-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=UX Hybrid 2019-23">Buy Here</a></sub></details>|| |Lexus|UX Hybrid 2019-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=UX Hybrid 2019-24">Buy Here</a></sub></details>||
|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator 2020-24">Buy Here</a></sub></details>|| |Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator 2020-24">Buy Here</a></sub></details>||
|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator Plug-in Hybrid 2020-24">Buy Here</a></sub></details>|| |Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator Plug-in Hybrid 2020-24">Buy Here</a></sub></details>||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>| |MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
+1 -1
View File
@@ -7,7 +7,7 @@ export OPENBLAS_NUM_THREADS=1
export VECLIB_MAXIMUM_THREADS=1 export VECLIB_MAXIMUM_THREADS=1
if [ -z "$AGNOS_VERSION" ]; then if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="11.6" export AGNOS_VERSION="11.8"
fi fi
export STAGING_ROOT="/data/safe_staging" export STAGING_ROOT="/data/safe_staging"
+1 -1
Submodule panda updated: 4ca963345a...44a9806bfb
+1
View File
@@ -111,6 +111,7 @@ dev = [
"tabulate", "tabulate",
"types-requests", "types-requests",
"types-tabulate", "types-tabulate",
"raylib",
] ]
tools = [ tools = [
+145
View File
@@ -0,0 +1,145 @@
#!/usr/bin/env bash
set -e
YELLOW='\033[0;33m'
GREEN='\033[0;32m'
UNDERLINE='\033[4m'
BOLD='\033[1m'
NC='\033[0m'
BRANCH="master"
RUNS="20"
COOKIE_JAR=/tmp/cookies
CRUMB=$(curl -s --cookie-jar $COOKIE_JAR 'https://jenkins.comma.life/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
function loop() {
JENKINS_BRANCH="__jenkins_loop_${BRANCH}"
API_ROUTE="https://jenkins.comma.life/job/openpilot/job/$JENKINS_BRANCH"
for run in $(seq 1 $((RUNS / 2))); do
N=2
TEST_BUILDS=()
# Try to find previous builds
ALL_BUILDS=( $(curl -s $API_ROUTE/api/json | jq .builds.[].number 2> /dev/null || :) )
# No builds. Create branch
if [[ ${#ALL_BUILDS[@]} -eq 0 ]]; then
TEMP_DIR=$(mktemp -d)
GIT_LFS_SKIP_SMUDGE=1 git clone --quiet -b $BRANCH --depth=1 --no-tags git@github.com:commaai/openpilot $TEMP_DIR
git -C $TEMP_DIR checkout --quiet -b $JENKINS_BRANCH
echo "TESTING" >> $TEMP_DIR/testing_jenkins
git -C $TEMP_DIR add testing_jenkins
git -C $TEMP_DIR commit --quiet -m "testing"
git -C $TEMP_DIR push --quiet -f origin $JENKINS_BRANCH
rm -rf $TEMP_DIR
FIRST_BUILD=1
echo ''
echo 'waiting on Jenkins...'
echo ''
sleep 90
else
# Found some builds. Wait for them to end if they are still running
for i in ${ALL_BUILDS[@]}; do
running=$(curl -s $API_ROUTE/$i/api/json/ | jq .inProgress)
if [[ $running == "false" ]]; then
continue
fi
TEST_BUILDS=( ${ALL_BUILDS[@]} )
N=${#TEST_BUILDS[@]}
break
done
fi
# No running builds found
if [[ ${#TEST_BUILDS[@]} -eq 0 ]]; then
FIRST_BUILD=$(curl -s $API_ROUTE/api/json | jq .nextBuildNumber)
LAST_BUILD=$((FIRST_BUILD+N-1))
TEST_BUILDS=( $(seq $FIRST_BUILD $LAST_BUILD) )
# Start N new builds
for i in ${TEST_BUILDS[@]};
do
echo "Starting build $i"
curl -s --output /dev/null --cookie $COOKIE_JAR -H "$CRUMB" -X POST $API_ROUTE/build?delay=0sec
sleep 5
done
echo ""
fi
# Wait for all builds to end
while true; do
sleep 30
count=0
for i in ${TEST_BUILDS[@]};
do
RES=$(curl -s -w "\n%{http_code}" --cookie $COOKIE_JAR -H "$CRUMB" $API_ROUTE/$i/api/json)
HTTP_CODE=$(tail -n1 <<< "$RES")
JSON=$(sed '$ d' <<< "$RES")
if [[ $HTTP_CODE == "200" ]]; then
STILL_RUNNING=$(echo $JSON | jq .inProgress)
if [[ $STILL_RUNNING == "true" ]]; then
echo -e "Build $i: ${YELLOW}still running${NC}"
continue
else
count=$((count+1))
echo -e "Build $i: ${GREEN}done${NC}"
fi
else
echo "No status for build $i"
fi
done
echo "See live results: ${API_ROUTE}/buildTimeTrend"
echo ""
if [[ $count -ge $N ]]; then
break
fi
done
done
}
function usage() {
echo ""
echo "Run the Jenkins tests multiple times on a specific branch"
echo ""
echo -e "${BOLD}${UNDERLINE}Options:${NC}"
echo -e " ${BOLD}-n, --n${NC}"
echo -e " Specify how many runs to do (default to ${BOLD}20${NC})"
echo -e " ${BOLD}-b, --branch${NC}"
echo -e " Specify which branch to run the tests against (default to ${BOLD}master${NC})"
echo ""
}
function _looper() {
if [[ $# -eq 0 ]]; then
usage
exit 0
fi
# parse Options
while [[ $# -gt 0 ]]; do
case $1 in
-n | --n ) shift 1; RUNS="$1"; shift 1 ;;
-b | --b | --branch | -branch ) shift 1; BRANCH="$1"; shift 1 ;;
* ) usage; exit 0 ;;
esac
done
echo ""
echo -e "You are about to start $RUNS Jenkins builds against the $BRANCH branch."
echo -e "If you expect this to run overnight, ${UNDERLINE}${BOLD}unplug the cold reboot power switch${NC} from the testing closet before."
echo ""
read -p "Press (y/Y) to confirm: " choice
if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
loop
fi
}
_looper $@
-1
View File
@@ -53,7 +53,6 @@ function run_tests() {
run "check_shebang_scripts_are_executable" python3 -m pre_commit_hooks.check_shebang_scripts_are_executable $ALL_FILES run "check_shebang_scripts_are_executable" python3 -m pre_commit_hooks.check_shebang_scripts_are_executable $ALL_FILES
run "check_shebang_format" $DIR/check_shebang_format.sh $ALL_FILES run "check_shebang_format" $DIR/check_shebang_format.sh $ALL_FILES
run "check_nomerge_comments" $DIR/check_nomerge_comments.sh $ALL_FILES run "check_nomerge_comments" $DIR/check_nomerge_comments.sh $ALL_FILES
run "check_raylib_includes" $DIR/check_raylib_includes.sh $ALL_FILES
if [[ -z "$FAST" ]]; then if [[ -z "$FAST" ]]; then
run "mypy" mypy $PYTHON_FILES run "mypy" mypy $PYTHON_FILES
+7 -16
View File
@@ -45,9 +45,6 @@ class CarSpecificEvents:
if self.CP.brand in ('body', 'mock'): if self.CP.brand in ('body', 'mock'):
events = Events() events = Events()
elif self.CP.brand in ('subaru', 'mazda'):
events = self.create_common_events(CS, CS_prev)
elif self.CP.brand == 'ford': elif self.CP.brand == 'ford':
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.manumatic]) events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.manumatic])
@@ -102,13 +99,9 @@ class CarSpecificEvents:
events.add(EventName.manualRestart) events.add(EventName.manualRestart)
elif self.CP.brand == 'gm': elif self.CP.brand == 'gm':
# The ECM allows enabling on falling edge of set, but only rising edge of resume
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.sport, GearShifter.low, events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.sport, GearShifter.low,
GearShifter.eco, GearShifter.manumatic], GearShifter.eco, GearShifter.manumatic],
pcm_enable=self.CP.pcmCruise, enable_buttons=(ButtonType.decelCruise,)) pcm_enable=self.CP.pcmCruise)
if not self.CP.pcmCruise:
if any(b.type == ButtonType.accelCruise and b.pressed for b in CS.buttonEvents):
events.add(EventName.buttonEnable)
# Enabling at a standstill with brake is allowed # Enabling at a standstill with brake is allowed
# TODO: verify 17 Volt can enable for the first time at a stop and allow for all GMs # TODO: verify 17 Volt can enable for the first time at a stop and allow for all GMs
@@ -122,8 +115,7 @@ class CarSpecificEvents:
elif self.CP.brand == 'volkswagen': elif self.CP.brand == 'volkswagen':
events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic], events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic],
pcm_enable=self.CP.pcmCruise, pcm_enable=self.CP.pcmCruise)
enable_buttons=(ButtonType.setCruise, ButtonType.resumeCruise))
# Low speed steer alert hysteresis logic # Low speed steer alert hysteresis logic
if (self.CP.minSteerSpeed - 1e-3) > VWCarControllerParams.DEFAULT_MIN_STEER_SPEED and CS.vEgo < (self.CP.minSteerSpeed + 1.): if (self.CP.minSteerSpeed - 1e-3) > VWCarControllerParams.DEFAULT_MIN_STEER_SPEED and CS.vEgo < (self.CP.minSteerSpeed + 1.):
@@ -160,12 +152,12 @@ class CarSpecificEvents:
events.add(EventName.belowSteerSpeed) events.add(EventName.belowSteerSpeed)
else: else:
raise ValueError(f"Unsupported car: {self.CP.brand}") events = self.create_common_events(CS, CS_prev)
return events return events
def create_common_events(self, CS: structs.CarState, CS_prev: car.CarState, extra_gears=None, pcm_enable=True, def create_common_events(self, CS: structs.CarState, CS_prev: car.CarState, extra_gears=None, pcm_enable=True,
allow_enable=True, allow_button_cancel=True, enable_buttons=(ButtonType.accelCruise, ButtonType.decelCruise)): allow_enable=True, allow_button_cancel=True):
events = Events() events = Events()
if CS.doorOpen: if CS.doorOpen:
@@ -209,12 +201,11 @@ class CarSpecificEvents:
events.add(EventName.invalidLkasSetting) events.add(EventName.invalidLkasSetting)
if CS.lowSpeedAlert: if CS.lowSpeedAlert:
events.add(EventName.belowSteerSpeed) events.add(EventName.belowSteerSpeed)
if CS.buttonEnable:
events.add(EventName.buttonEnable)
# Handle button presses # Handle cancel button presses
for b in CS.buttonEvents: for b in CS.buttonEvents:
# Enable OP long on falling edge of enable buttons (defaults to accelCruise and decelCruise, overridable per-port)
if not self.CP.pcmCruise and (b.type in enable_buttons and not b.pressed):
events.add(EventName.buttonEnable)
# Disable on rising and falling edge of cancel for both stock and OP long # Disable on rising and falling edge of cancel for both stock and OP long
# TODO: only check the cancel button with openpilot longitudinal on all brands to match panda safety # TODO: only check the cancel button with openpilot longitudinal on all brands to match panda safety
if b.type == ButtonType.cancel and (allow_button_cancel or not self.CP.pcmCruise): if b.type == ButtonType.cancel and (allow_button_cancel or not self.CP.pcmCruise):
+3 -3
View File
@@ -8,17 +8,17 @@ import cereal.messaging as messaging
from cereal import car, log, custom from cereal import car, log, custom
from panda import ALTERNATIVE_EXPERIENCE
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper
from openpilot.common.swaglog import cloudlog, ForwardingHandler from openpilot.common.swaglog import cloudlog, ForwardingHandler
from opendbc.car import DT_CTRL, carlog, structs from opendbc.car import DT_CTRL, structs
from opendbc.car.can_definitions import CanData, CanRecvCallable, CanSendCallable from opendbc.car.can_definitions import CanData, CanRecvCallable, CanSendCallable
from opendbc.car.carlog import carlog
from opendbc.car.fw_versions import ObdCallback from opendbc.car.fw_versions import ObdCallback
from opendbc.car.car_helpers import get_car, get_radar_interface from opendbc.car.car_helpers import get_car, get_radar_interface
from opendbc.car.interfaces import CarInterfaceBase, RadarInterfaceBase from opendbc.car.interfaces import CarInterfaceBase, RadarInterfaceBase
from opendbc.safety import ALTERNATIVE_EXPERIENCE
from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp
from openpilot.selfdrive.car.cruise import VCruiseHelper from openpilot.selfdrive.car.cruise import VCruiseHelper
from openpilot.selfdrive.car.car_specific import MockCarState from openpilot.selfdrive.car.car_specific import MockCarState
+10 -22
View File
@@ -1,3 +1,4 @@
import time
import capnp import capnp
import copy import copy
import os import os
@@ -10,17 +11,15 @@ import hypothesis.strategies as st
from hypothesis import Phase, given, settings from hypothesis import Phase, given, settings
from parameterized import parameterized_class from parameterized import parameterized_class
from cereal import messaging, log, car
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params
from opendbc.car import DT_CTRL, gen_empty_fingerprint, structs from opendbc.car import DT_CTRL, gen_empty_fingerprint, structs
from opendbc.car.fingerprints import all_known_cars, MIGRATION from opendbc.car.can_definitions import CanData
from opendbc.car.car_helpers import FRAME_FINGERPRINT, interfaces from opendbc.car.car_helpers import FRAME_FINGERPRINT, interfaces
from opendbc.car.fingerprints import all_known_cars, MIGRATION
from opendbc.car.honda.values import CAR as HONDA, HondaFlags from opendbc.car.honda.values import CAR as HONDA, HondaFlags
from opendbc.car.values import Platform from opendbc.car.structs import car
from opendbc.car.tests.routes import non_tested_cars, routes, CarTestRoute from opendbc.car.tests.routes import non_tested_cars, routes, CarTestRoute
from openpilot.selfdrive.selfdrived.events import ET from opendbc.car.values import Platform
from openpilot.selfdrive.selfdrived.selfdrived import SelfdriveD from openpilot.common.basedir import BASEDIR
from openpilot.selfdrive.pandad import can_capnp_to_list from openpilot.selfdrive.pandad import can_capnp_to_list
from openpilot.selfdrive.test.helpers import read_segment_list from openpilot.selfdrive.test.helpers import read_segment_list
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
@@ -30,8 +29,6 @@ from openpilot.tools.lib.route import SegmentName
from panda.tests.libpanda import libpanda_py from panda.tests.libpanda import libpanda_py
EventName = log.OnroadEvent.EventName
PandaType = log.PandaState.PandaType
SafetyModel = car.CarParams.SafetyModel SafetyModel = car.CarParams.SafetyModel
NUM_JOBS = int(os.environ.get("NUM_JOBS", "1")) NUM_JOBS = int(os.environ.get("NUM_JOBS", "1"))
@@ -174,8 +171,6 @@ class TestCarModelBase(unittest.TestCase):
self.CI = self.CarInterface(self.CP.copy(), copy.deepcopy(self.CP_SP), self.CarController, self.CarState) self.CI = self.CarInterface(self.CP.copy(), copy.deepcopy(self.CP_SP), self.CarController, self.CarState)
assert self.CI assert self.CI
Params().put_bool("OpenpilotEnabledToggle", self.openpilot_enabled)
# TODO: check safetyModel is in release panda build # TODO: check safetyModel is in release panda build
self.safety = libpanda_py.libpanda self.safety = libpanda_py.libpanda
@@ -344,10 +339,8 @@ class TestCarModelBase(unittest.TestCase):
to_send = libpanda_py.make_CANPacket(address, bus, dat) to_send = libpanda_py.make_CANPacket(address, bus, dat)
self.safety.safety_rx_hook(to_send) self.safety.safety_rx_hook(to_send)
can = messaging.new_message('can', 1) can = [(int(time.monotonic() * 1e9), [CanData(address=address, dat=dat, src=bus)])]
can.can = [log.CanData(address=address, dat=dat, src=bus)] CS = self.CI.update(can)
CS = self.CI.update(can_capnp_to_list((can.to_bytes(),)))
if self.safety.get_gas_pressed_prev() != prev_panda_gas: if self.safety.get_gas_pressed_prev() != prev_panda_gas:
self.assertEqual(CS.gasPressed, self.safety.get_gas_pressed_prev()) self.assertEqual(CS.gasPressed, self.safety.get_gas_pressed_prev())
@@ -392,8 +385,6 @@ class TestCarModelBase(unittest.TestCase):
controls_allowed_prev = False controls_allowed_prev = False
CS_prev = car.CarState.new_message() CS_prev = car.CarState.new_message()
checks = defaultdict(int) checks = defaultdict(int)
selfdrived = SelfdriveD(CP=self.CP, CP_SP=self.CP_SP)
selfdrived.initialized = True
for idx, can in enumerate(self.can_msgs): for idx, can in enumerate(self.can_msgs):
CS = self.CI.update(can_capnp_to_list((can.as_builder().to_bytes(), ))).as_reader() CS = self.CI.update(can_capnp_to_list((can.as_builder().to_bytes(), ))).as_reader()
for msg in filter(lambda m: m.src in range(64), can.can): for msg in filter(lambda m: m.src in range(64), can.can):
@@ -437,11 +428,8 @@ class TestCarModelBase(unittest.TestCase):
if not self.CP.notCar: if not self.CP.notCar:
checks['cruiseState'] += CS.cruiseState.enabled != self.safety.get_cruise_engaged_prev() checks['cruiseState'] += CS.cruiseState.enabled != self.safety.get_cruise_engaged_prev()
else: else:
# Check for enable events on rising edge of controls allowed # Check for user button enable on rising edge of controls allowed
selfdrived.update_events(CS) button_enable = CS.buttonEnable and (not CS.brakePressed or CS.standstill)
selfdrived.CS_prev = CS
button_enable = (selfdrived.events.contains(ET.ENABLE) and
EventName.pedalPressed not in selfdrived.events.names)
mismatch = button_enable != (self.safety.get_controls_allowed() and not controls_allowed_prev) mismatch = button_enable != (self.safety.get_controls_allowed() and not controls_allowed_prev)
checks['controlsAllowed'] += mismatch checks['controlsAllowed'] += mismatch
controls_allowed_prev = self.safety.get_controls_allowed() controls_allowed_prev = self.safety.get_controls_allowed()
@@ -3,7 +3,7 @@ import os
import time import time
import numpy as np import numpy as np
from cereal import log from cereal import log
from opendbc.car.interfaces import ACCEL_MIN from opendbc.car.interfaces import ACCEL_MIN, ACCEL_MAX
from openpilot.common.realtime import DT_MDL from openpilot.common.realtime import DT_MDL
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
# WARNING: imports outside of constants will not trigger a rebuild # WARNING: imports outside of constants will not trigger a rebuild
@@ -55,6 +55,8 @@ FCW_IDXS = T_IDXS < 5.0
T_DIFFS = np.diff(T_IDXS, prepend=[0.]) T_DIFFS = np.diff(T_IDXS, prepend=[0.])
COMFORT_BRAKE = 2.5 COMFORT_BRAKE = 2.5
STOP_DISTANCE = 6.0 STOP_DISTANCE = 6.0
CRUISE_MIN_ACCEL = -1.2
CRUISE_MAX_ACCEL = 1.6
def get_jerk_factor(personality=log.LongitudinalPersonality.standard): def get_jerk_factor(personality=log.LongitudinalPersonality.standard):
if personality==log.LongitudinalPersonality.relaxed: if personality==log.LongitudinalPersonality.relaxed:
@@ -281,7 +283,7 @@ class LongitudinalMpc:
elif self.mode == 'blended': elif self.mode == 'blended':
a_change_cost = 40.0 if prev_accel_constraint else 0 a_change_cost = 40.0 if prev_accel_constraint else 0
cost_weights = [0., 0.1, 0.2, 5.0, a_change_cost, 1.0] cost_weights = [0., 0.1, 0.2, 5.0, a_change_cost, 1.0]
constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, 50.0] constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, DANGER_ZONE_COST]
else: else:
raise NotImplementedError(f'Planner mode {self.mode} not recognized in planner cost set') raise NotImplementedError(f'Planner mode {self.mode} not recognized in planner cost set')
self.set_cost_weights(cost_weights, constraint_cost_weights) self.set_cost_weights(cost_weights, constraint_cost_weights)
@@ -325,12 +327,6 @@ class LongitudinalMpc:
lead_xv = self.extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau) lead_xv = self.extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau)
return lead_xv return lead_xv
def set_accel_limits(self, min_a, max_a):
# TODO this sets a max accel limit, but the minimum limit is only for cruise decel
# needs refactor
self.cruise_min_a = min_a
self.max_a = max_a
def update(self, radarstate, v_cruise, x, v, a, j, personality=log.LongitudinalPersonality.standard): def update(self, radarstate, v_cruise, x, v, a, j, personality=log.LongitudinalPersonality.standard):
t_follow = get_T_FOLLOW(personality) t_follow = get_T_FOLLOW(personality)
v_ego = self.x0[1] v_ego = self.x0[1]
@@ -346,8 +342,7 @@ class LongitudinalMpc:
lead_1_obstacle = lead_xv_1[:,0] + get_stopped_equivalence_factor(lead_xv_1[:,1]) lead_1_obstacle = lead_xv_1[:,0] + get_stopped_equivalence_factor(lead_xv_1[:,1])
self.params[:,0] = ACCEL_MIN self.params[:,0] = ACCEL_MIN
# negative accel constraint causes problems because negative speed is not allowed self.params[:,1] = ACCEL_MAX
self.params[:,1] = max(0.0, self.max_a)
# Update in ACC mode or ACC/e2e blend # Update in ACC mode or ACC/e2e blend
if self.mode == 'acc': if self.mode == 'acc':
@@ -355,9 +350,9 @@ class LongitudinalMpc:
# Fake an obstacle for cruise, this ensures smooth acceleration to set speed # Fake an obstacle for cruise, this ensures smooth acceleration to set speed
# when the leads are no factor. # when the leads are no factor.
v_lower = v_ego + (T_IDXS * self.cruise_min_a * 1.05) v_lower = v_ego + (T_IDXS * CRUISE_MIN_ACCEL * 1.05)
# TODO does this make sense when max_a is negative? # TODO does this make sense when max_a is negative?
v_upper = v_ego + (T_IDXS * self.max_a * 1.05) v_upper = v_ego + (T_IDXS * CRUISE_MAX_ACCEL * 1.05)
v_cruise_clipped = np.clip(v_cruise * np.ones(N+1), v_cruise_clipped = np.clip(v_cruise * np.ones(N+1),
v_lower, v_lower,
v_upper) v_upper)
+21 -18
View File
@@ -18,7 +18,6 @@ from openpilot.common.swaglog import cloudlog
from openpilot.sunnypilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlannerSP from openpilot.sunnypilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlannerSP
LON_MPC_STEP = 0.2 # first step is 0.2s LON_MPC_STEP = 0.2 # first step is 0.2s
A_CRUISE_MIN = -1.2
A_CRUISE_MAX_VALS = [1.6, 1.2, 0.8, 0.6] A_CRUISE_MAX_VALS = [1.6, 1.2, 0.8, 0.6]
A_CRUISE_MAX_BP = [0., 10.0, 25., 40.] A_CRUISE_MAX_BP = [0., 10.0, 25., 40.]
CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N] CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N]
@@ -79,7 +78,10 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
self.a_desired = init_a self.a_desired = init_a
self.v_desired_filter = FirstOrderFilter(init_v, 2.0, self.dt) self.v_desired_filter = FirstOrderFilter(init_v, 2.0, self.dt)
self.prev_accel_clip = [ACCEL_MIN, ACCEL_MAX]
self.v_model_error = 0.0 self.v_model_error = 0.0
self.output_a_target = 0.0
self.output_should_stop = False
self.v_desired_trajectory = np.zeros(CONTROL_N) self.v_desired_trajectory = np.zeros(CONTROL_N)
self.a_desired_trajectory = np.zeros(CONTROL_N) self.a_desired_trajectory = np.zeros(CONTROL_N)
@@ -134,17 +136,16 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
prev_accel_constraint = not (reset_state or sm['carState'].standstill) prev_accel_constraint = not (reset_state or sm['carState'].standstill)
if self.mpc.mode == 'acc': if self.mpc.mode == 'acc':
accel_limits = [A_CRUISE_MIN, get_max_accel(v_ego)] accel_clip = [ACCEL_MIN, get_max_accel(v_ego)]
steer_angle_without_offset = sm['carState'].steeringAngleDeg - sm['liveParameters'].angleOffsetDeg steer_angle_without_offset = sm['carState'].steeringAngleDeg - sm['liveParameters'].angleOffsetDeg
accel_limits_turns = limit_accel_in_turns(v_ego, steer_angle_without_offset, accel_limits, self.CP) accel_clip = limit_accel_in_turns(v_ego, steer_angle_without_offset, accel_clip, self.CP)
else: else:
accel_limits = [ACCEL_MIN, ACCEL_MAX] accel_clip = [ACCEL_MIN, ACCEL_MAX]
accel_limits_turns = [ACCEL_MIN, ACCEL_MAX]
if reset_state: if reset_state:
self.v_desired_filter.x = v_ego self.v_desired_filter.x = v_ego
# Clip aEgo to cruise limits to prevent large accelerations when becoming active # Clip aEgo to cruise limits to prevent large accelerations when becoming active
self.a_desired = np.clip(sm['carState'].aEgo, accel_limits[0], accel_limits[1]) self.a_desired = np.clip(sm['carState'].aEgo, accel_clip[0], accel_clip[1])
# Prevent divergence, smooth in current v_ego # Prevent divergence, smooth in current v_ego
self.v_desired_filter.x = max(0.0, self.v_desired_filter.update(v_ego)) self.v_desired_filter.x = max(0.0, self.v_desired_filter.update(v_ego))
@@ -155,18 +156,14 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
self.allow_throttle = throttle_prob > ALLOW_THROTTLE_THRESHOLD or v_ego <= MIN_ALLOW_THROTTLE_SPEED self.allow_throttle = throttle_prob > ALLOW_THROTTLE_THRESHOLD or v_ego <= MIN_ALLOW_THROTTLE_SPEED
if not self.allow_throttle: if not self.allow_throttle:
clipped_accel_coast = max(accel_coast, accel_limits_turns[0]) clipped_accel_coast = max(accel_coast, accel_clip[0])
clipped_accel_coast_interp = np.interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_limits_turns[1], clipped_accel_coast]) clipped_accel_coast_interp = np.interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_clip[1], clipped_accel_coast])
accel_limits_turns[1] = min(accel_limits_turns[1], clipped_accel_coast_interp) accel_clip[1] = min(accel_clip[1], clipped_accel_coast_interp)
if force_slow_decel: if force_slow_decel:
v_cruise = 0.0 v_cruise = 0.0
# clip limits, cannot init MPC outside of bounds
accel_limits_turns[0] = min(accel_limits_turns[0], self.a_desired + 0.05)
accel_limits_turns[1] = max(accel_limits_turns[1], self.a_desired - 0.05)
self.mpc.set_weights(prev_accel_constraint, personality=sm['selfdriveState'].personality) self.mpc.set_weights(prev_accel_constraint, personality=sm['selfdriveState'].personality)
self.mpc.set_accel_limits(accel_limits_turns[0], accel_limits_turns[1])
self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired) self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired)
self.mpc.update(sm['radarState'], v_cruise, x, v, a, j, personality=sm['selfdriveState'].personality) self.mpc.update(sm['radarState'], v_cruise, x, v, a, j, personality=sm['selfdriveState'].personality)
@@ -184,6 +181,15 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
self.a_desired = float(np.interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory)) self.a_desired = float(np.interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory))
self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0 self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0
action_t = self.CP.longitudinalActuatorDelay + DT_MDL
output_a_target, self.output_should_stop = get_accel_from_plan(self.v_desired_trajectory, self.a_desired_trajectory,
action_t=action_t, vEgoStopping=self.CP.vEgoStopping)
for idx in range(2):
accel_clip[idx] = np.clip(accel_clip[idx], self.prev_accel_clip[idx] - 0.05, self.prev_accel_clip[idx] + 0.05)
self.output_a_target = np.clip(output_a_target, accel_clip[0], accel_clip[1])
self.prev_accel_clip = accel_clip
def publish(self, sm, pm): def publish(self, sm, pm):
plan_send = messaging.new_message('longitudinalPlan') plan_send = messaging.new_message('longitudinalPlan')
@@ -202,11 +208,8 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
longitudinalPlan.longitudinalPlanSource = self.mpc.source longitudinalPlan.longitudinalPlanSource = self.mpc.source
longitudinalPlan.fcw = self.fcw longitudinalPlan.fcw = self.fcw
action_t = self.CP.longitudinalActuatorDelay + DT_MDL longitudinalPlan.aTarget = float(self.output_a_target)
a_target, should_stop = get_accel_from_plan(longitudinalPlan.speeds, longitudinalPlan.accels, longitudinalPlan.shouldStop = bool(self.output_should_stop)
action_t=action_t, vEgoStopping=self.CP.vEgoStopping)
longitudinalPlan.aTarget = float(a_target)
longitudinalPlan.shouldStop = bool(should_stop)
longitudinalPlan.allowBrake = True longitudinalPlan.allowBrake = True
longitudinalPlan.allowThrottle = bool(self.allow_throttle) longitudinalPlan.allowThrottle = bool(self.allow_throttle)
+1 -1
View File
@@ -11,5 +11,5 @@ if __name__ == "__main__":
time.sleep(1) time.sleep(1)
# honda bosch radar disable # honda bosch radar disable
disabled = disable_ecu(*can_callbacks, bus=1, addr=0x18DAB0F1, com_cont_req=b'\x28\x83\x03', timeout=0.5, debug=False) disabled = disable_ecu(*can_callbacks, bus=1, addr=0x18DAB0F1, com_cont_req=b'\x28\x83\x03', timeout=0.5)
print(f"disabled: {disabled}") print(f"disabled: {disabled}")
+5 -1
View File
@@ -2,6 +2,7 @@
import argparse import argparse
import time import time
import cereal.messaging as messaging import cereal.messaging as messaging
from opendbc.car.carlog import carlog
from opendbc.car.ecu_addrs import get_all_ecu_addrs from opendbc.car.ecu_addrs import get_all_ecu_addrs
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.selfdrive.car.card import can_comm_callbacks, obd_callback from openpilot.selfdrive.car.card import can_comm_callbacks, obd_callback
@@ -15,6 +16,9 @@ if __name__ == "__main__":
parser.add_argument('--timeout', type=float, default=1.0) parser.add_argument('--timeout', type=float, default=1.0)
args = parser.parse_args() args = parser.parse_args()
if args.debug:
carlog.setLevel('DEBUG')
logcan = messaging.sub_sock('can') logcan = messaging.sub_sock('can')
sendcan = messaging.pub_sock('sendcan') sendcan = messaging.pub_sock('sendcan')
can_callbacks = can_comm_callbacks(logcan, sendcan) can_callbacks = can_comm_callbacks(logcan, sendcan)
@@ -29,7 +33,7 @@ if __name__ == "__main__":
obd_callback(params)(not args.no_obd) obd_callback(params)(not args.no_obd)
print("Getting ECU addresses ...") print("Getting ECU addresses ...")
ecu_addrs = get_all_ecu_addrs(*can_callbacks, args.bus, args.timeout, debug=args.debug) ecu_addrs = get_all_ecu_addrs(*can_callbacks, args.bus, args.timeout)
print() print()
print("Found ECUs on rx addresses:") print("Found ECUs on rx addresses:")
+6 -2
View File
@@ -3,6 +3,7 @@ import time
import argparse import argparse
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal import car from cereal import car
from opendbc.car.carlog import carlog
from opendbc.car.fw_versions import get_fw_versions, match_fw_to_car from opendbc.car.fw_versions import get_fw_versions, match_fw_to_car
from opendbc.car.vin import get_vin from opendbc.car.vin import get_vin
from openpilot.common.params import Params from openpilot.common.params import Params
@@ -18,6 +19,9 @@ if __name__ == "__main__":
parser.add_argument('--brand', help='Only query addresses/with requests for this brand') parser.add_argument('--brand', help='Only query addresses/with requests for this brand')
args = parser.parse_args() args = parser.parse_args()
if args.debug:
carlog.setLevel('DEBUG')
logcan = messaging.sub_sock('can') logcan = messaging.sub_sock('can')
pandaStates_sock = messaging.sub_sock('pandaStates') pandaStates_sock = messaging.sub_sock('pandaStates')
sendcan = messaging.pub_sock('sendcan') sendcan = messaging.pub_sock('sendcan')
@@ -46,13 +50,13 @@ if __name__ == "__main__":
t = time.time() t = time.time()
print("Getting vin...") print("Getting vin...")
set_obd_multiplexing(True) set_obd_multiplexing(True)
vin_rx_addr, vin_rx_bus, vin = get_vin(*can_callbacks, (0, 1), debug=args.debug) vin_rx_addr, vin_rx_bus, vin = get_vin(*can_callbacks, (0, 1))
print(f'RX: {hex(vin_rx_addr)}, BUS: {vin_rx_bus}, VIN: {vin}') print(f'RX: {hex(vin_rx_addr)}, BUS: {vin_rx_bus}, VIN: {vin}')
print(f"Getting VIN took {time.time() - t:.3f} s") print(f"Getting VIN took {time.time() - t:.3f} s")
print() print()
t = time.time() t = time.time()
fw_vers = get_fw_versions(*can_callbacks, set_obd_multiplexing, query_brand=args.brand, extra=extra, num_pandas=num_pandas, debug=args.debug, progress=True) fw_vers = get_fw_versions(*can_callbacks, set_obd_multiplexing, query_brand=args.brand, extra=extra, num_pandas=num_pandas, progress=True)
_, candidates = match_fw_to_car(fw_vers, vin) _, candidates = match_fw_to_car(fw_vers, vin)
print() print()
+5 -1
View File
@@ -2,6 +2,7 @@
import argparse import argparse
import time import time
import cereal.messaging as messaging import cereal.messaging as messaging
from opendbc.car.carlog import carlog
from opendbc.car.vin import get_vin from opendbc.car.vin import get_vin
from openpilot.selfdrive.car.card import can_comm_callbacks from openpilot.selfdrive.car.card import can_comm_callbacks
@@ -13,10 +14,13 @@ if __name__ == "__main__":
parser.add_argument('--retry', type=int, default=5) parser.add_argument('--retry', type=int, default=5)
args = parser.parse_args() args = parser.parse_args()
if args.debug:
carlog.setLevel('DEBUG')
sendcan = messaging.pub_sock('sendcan') sendcan = messaging.pub_sock('sendcan')
logcan = messaging.sub_sock('can') logcan = messaging.sub_sock('can')
can_callbacks = can_comm_callbacks(logcan, sendcan) can_callbacks = can_comm_callbacks(logcan, sendcan)
time.sleep(1) time.sleep(1)
vin_rx_addr, vin_rx_bus, vin = get_vin(*can_callbacks, (args.bus,), args.timeout, args.retry, debug=args.debug) vin_rx_addr, vin_rx_bus, vin = get_vin(*can_callbacks, (args.bus,), args.timeout, args.retry)
print(f'RX: {hex(vin_rx_addr)}, BUS: {vin_rx_bus}, VIN: {vin}') print(f'RX: {hex(vin_rx_addr)}, BUS: {vin_rx_bus}, VIN: {vin}')
+7 -2
View File
@@ -2,7 +2,9 @@
import sys import sys
import argparse import argparse
from subprocess import check_output, CalledProcessError from subprocess import check_output, CalledProcessError
from opendbc.car.carlog import carlog
from opendbc.car.uds import UdsClient, MessageTimeoutError, SESSION_TYPE, DTC_GROUP_TYPE from opendbc.car.uds import UdsClient, MessageTimeoutError, SESSION_TYPE, DTC_GROUP_TYPE
from opendbc.safety import Safety
from panda import Panda from panda import Panda
parser = argparse.ArgumentParser(description="clear DTC status") parser = argparse.ArgumentParser(description="clear DTC status")
@@ -11,6 +13,9 @@ parser.add_argument("--bus", type=int, default=0)
parser.add_argument('--debug', action='store_true') parser.add_argument('--debug', action='store_true')
args = parser.parse_args() args = parser.parse_args()
if args.debug:
carlog.setLevel('DEBUG')
try: try:
check_output(["pidof", "pandad"]) check_output(["pidof", "pandad"])
print("pandad is running, please kill openpilot before running this script! (aborted)") print("pandad is running, please kill openpilot before running this script! (aborted)")
@@ -20,8 +25,8 @@ except CalledProcessError as e:
raise e raise e
panda = Panda() panda = Panda()
panda.set_safety_mode(Panda.SAFETY_ELM327) panda.set_safety_mode(Safety.SAFETY_ELM327)
uds_client = UdsClient(panda, args.addr, bus=args.bus, debug=args.debug) uds_client = UdsClient(panda, args.addr, bus=args.bus)
print("extended diagnostic session ...") print("extended diagnostic session ...")
try: try:
uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC)
@@ -16,7 +16,9 @@ import argparse
from typing import NamedTuple from typing import NamedTuple
from subprocess import check_output, CalledProcessError from subprocess import check_output, CalledProcessError
from opendbc.car.carlog import carlog
from opendbc.car.uds import UdsClient, SESSION_TYPE, DATA_IDENTIFIER_TYPE from opendbc.car.uds import UdsClient, SESSION_TYPE, DATA_IDENTIFIER_TYPE
from opendbc.safety import Safety
from panda.python import Panda from panda.python import Panda
class ConfigValues(NamedTuple): class ConfigValues(NamedTuple):
@@ -78,6 +80,9 @@ if __name__ == "__main__":
parser.add_argument('--bus', type=int, default=0, help='can bus to use (default: 0)') parser.add_argument('--bus', type=int, default=0, help='can bus to use (default: 0)')
args = parser.parse_args() args = parser.parse_args()
if args.debug:
carlog.setLevel('DEBUG')
try: try:
check_output(["pidof", "pandad"]) check_output(["pidof", "pandad"])
print("pandad is running, please kill openpilot before running this script! (aborted)") print("pandad is running, please kill openpilot before running this script! (aborted)")
@@ -92,8 +97,8 @@ if __name__ == "__main__":
sys.exit(0) sys.exit(0)
panda = Panda() panda = Panda()
panda.set_safety_mode(Panda.SAFETY_ELM327) panda.set_safety_mode(Safety.SAFETY_ELM327)
uds_client = UdsClient(panda, 0x7D0, bus=args.bus, debug=args.debug) uds_client = UdsClient(panda, 0x7D0, bus=args.bus)
print("\n[START DIAGNOSTIC SESSION]") print("\n[START DIAGNOSTIC SESSION]")
session_type : SESSION_TYPE = 0x07 # type: ignore session_type : SESSION_TYPE = 0x07 # type: ignore
+1 -1
View File
@@ -6,7 +6,7 @@ from collections import defaultdict
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
from openpilot.system.loggerd.uploader import LOG_COMPRESSION_LEVEL from openpilot.common.file_helpers import LOG_COMPRESSION_LEVEL
from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.logreader import LogReader
from tqdm import tqdm from tqdm import tqdm
+7 -2
View File
@@ -2,7 +2,9 @@
import sys import sys
import argparse import argparse
from subprocess import check_output, CalledProcessError from subprocess import check_output, CalledProcessError
from opendbc.car.carlog import carlog
from opendbc.car.uds import UdsClient, SESSION_TYPE, DTC_REPORT_TYPE, DTC_STATUS_MASK_TYPE, get_dtc_num_as_str, get_dtc_status_names from opendbc.car.uds import UdsClient, SESSION_TYPE, DTC_REPORT_TYPE, DTC_STATUS_MASK_TYPE, get_dtc_num_as_str, get_dtc_status_names
from opendbc.safety import Safety
from panda import Panda from panda import Panda
parser = argparse.ArgumentParser(description="read DTC status") parser = argparse.ArgumentParser(description="read DTC status")
@@ -11,6 +13,9 @@ parser.add_argument("--bus", type=int, default=0)
parser.add_argument('--debug', action='store_true') parser.add_argument('--debug', action='store_true')
args = parser.parse_args() args = parser.parse_args()
if args.debug:
carlog.setLevel('DEBUG')
try: try:
check_output(["pidof", "pandad"]) check_output(["pidof", "pandad"])
print("pandad is running, please kill openpilot before running this script! (aborted)") print("pandad is running, please kill openpilot before running this script! (aborted)")
@@ -20,8 +25,8 @@ except CalledProcessError as e:
raise e raise e
panda = Panda() panda = Panda()
panda.set_safety_mode(Panda.SAFETY_ELM327) panda.set_safety_mode(Safety.SAFETY_ELM327)
uds_client = UdsClient(panda, args.addr, bus=args.bus, debug=args.debug) uds_client = UdsClient(panda, args.addr, bus=args.bus)
print("extended diagnostic session ...") print("extended diagnostic session ...")
uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC)
print("read diagnostic codes ...") print("read diagnostic codes ...")
+7 -2
View File
@@ -3,8 +3,10 @@
import argparse import argparse
import struct import struct
from enum import IntEnum from enum import IntEnum
from opendbc.car.carlog import carlog
from opendbc.car.uds import UdsClient, MessageTimeoutError, NegativeResponseError, SESSION_TYPE,\ from opendbc.car.uds import UdsClient, MessageTimeoutError, NegativeResponseError, SESSION_TYPE,\
DATA_IDENTIFIER_TYPE, ACCESS_TYPE DATA_IDENTIFIER_TYPE, ACCESS_TYPE
from opendbc.safety import Safety
from panda import Panda from panda import Panda
from datetime import date from datetime import date
@@ -33,10 +35,13 @@ if __name__ == "__main__":
parser.add_argument("action", choices={"show", "enable", "disable"}, help="show or modify current EPS HCA config") parser.add_argument("action", choices={"show", "enable", "disable"}, help="show or modify current EPS HCA config")
args = parser.parse_args() args = parser.parse_args()
if args.debug:
carlog.setLevel('DEBUG')
panda = Panda() panda = Panda()
panda.set_safety_mode(Panda.SAFETY_ELM327) panda.set_safety_mode(Safety.SAFETY_ELM327)
bus = 1 if panda.has_obd() else 0 bus = 1 if panda.has_obd() else 0
uds_client = UdsClient(panda, MQB_EPS_CAN_ADDR, MQB_EPS_CAN_ADDR + RX_OFFSET, bus, timeout=0.2, debug=args.debug) uds_client = UdsClient(panda, MQB_EPS_CAN_ADDR, MQB_EPS_CAN_ADDR + RX_OFFSET, bus, timeout=0.2)
try: try:
uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC)
+2 -4
View File
@@ -6,7 +6,6 @@ While the roll calibration is a real value that can be estimated, here we assume
and the image input into the neural network is not corrected for roll. and the image input into the neural network is not corrected for roll.
''' '''
import gc
import os import os
import capnp import capnp
import numpy as np import numpy as np
@@ -16,7 +15,7 @@ from cereal import log
import cereal.messaging as messaging import cereal.messaging as messaging
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.realtime import set_realtime_priority from openpilot.common.realtime import config_realtime_process
from openpilot.common.transformations.orientation import rot_from_euler, euler_from_rot from openpilot.common.transformations.orientation import rot_from_euler, euler_from_rot
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
@@ -256,8 +255,7 @@ class Calibrator:
def main() -> NoReturn: def main() -> NoReturn:
gc.disable() config_realtime_process([0, 1, 2, 3], 5)
set_realtime_priority(1)
pm = messaging.PubMaster(['liveCalibration']) pm = messaging.PubMaster(['liveCalibration'])
sm = messaging.SubMaster(['cameraOdometry', 'carState', 'carParams'], poll='cameraOdometry') sm = messaging.SubMaster(['cameraOdometry', 'carState', 'carParams'], poll='cameraOdometry')
+7 -7
View File
@@ -12,6 +12,7 @@ from cereal.services import SERVICE_LIST
from openpilot.common.transformations.orientation import rot_from_euler from openpilot.common.transformations.orientation import rot_from_euler
from openpilot.common.realtime import config_realtime_process from openpilot.common.realtime import config_realtime_process
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.swaglog import cloudlog
from openpilot.selfdrive.locationd.helpers import rotate_std from openpilot.selfdrive.locationd.helpers import rotate_std
from openpilot.selfdrive.locationd.models.pose_kf import PoseKalman, States from openpilot.selfdrive.locationd.models.pose_kf import PoseKalman, States
from openpilot.selfdrive.locationd.models.constants import ObservationKind, GENERATED_DIR from openpilot.selfdrive.locationd.models.constants import ObservationKind, GENERATED_DIR
@@ -78,20 +79,20 @@ class LocationEstimator:
# sensor time and log time should be close # sensor time and log time should be close
sensor_time_invalid = abs(sensor_time - t) > MAX_SENSOR_TIME_DIFF sensor_time_invalid = abs(sensor_time - t) > MAX_SENSOR_TIME_DIFF
if sensor_time_invalid: if sensor_time_invalid:
print("Sensor reading ignored, sensor timestamp more than 100ms off from log time") cloudlog.warning("Sensor reading ignored, sensor timestamp more than 100ms off from log time")
return not sensor_time_invalid return not sensor_time_invalid
def _validate_timestamp(self, t: float): def _validate_timestamp(self, t: float):
kf_t = self.kf.t kf_t = self.kf.t
invalid = not np.isnan(kf_t) and (kf_t - t) > MAX_FILTER_REWIND_TIME invalid = not np.isnan(kf_t) and (kf_t - t) > MAX_FILTER_REWIND_TIME
if invalid: if invalid:
print("Observation timestamp is older than the max rewind threshold of the filter") cloudlog.warning("Observation timestamp is older than the max rewind threshold of the filter")
return not invalid return not invalid
def _finite_check(self, t: float, new_x: np.ndarray, new_P: np.ndarray): def _finite_check(self, t: float, new_x: np.ndarray, new_P: np.ndarray):
all_finite = np.isfinite(new_x).all() and np.isfinite(new_P).all() all_finite = np.isfinite(new_x).all() and np.isfinite(new_P).all()
if not all_finite: if not all_finite:
print("Non-finite values detected, kalman reset") cloudlog.error("Non-finite values detected, kalman reset")
self.reset(t) self.reset(t)
def handle_log(self, t: float, which: str, msg: capnp._DynamicStructReader) -> HandleLogResult: def handle_log(self, t: float, which: str, msg: capnp._DynamicStructReader) -> HandleLogResult:
@@ -308,13 +309,12 @@ def main():
continue continue
if res == HandleLogResult.TIMING_INVALID: if res == HandleLogResult.TIMING_INVALID:
print(f"Observation {which} ignored due to failed timing check") cloudlog.warning(f"Observation {which} ignored due to failed timing check")
observation_input_invalid[which] += 1 observation_input_invalid[which] += 1
print(observation_input_invalid[which])
elif res == HandleLogResult.INPUT_INVALID: elif res == HandleLogResult.INPUT_INVALID:
print(f"Observation {which} ignored due to failed sanity check") cloudlog.warning(f"Observation {which} ignored due to failed sanity check")
observation_input_invalid[which] += 1 observation_input_invalid[which] += 1
else: elif res == HandleLogResult.SUCCESS:
observation_input_invalid[which] *= input_invalid_decay[which] observation_input_invalid[which] *= input_invalid_decay[which]
else: else:
filter_initialized = sm.all_checks() and sensor_all_checks(acc_msgs, gyro_msgs, sensor_valid, sensor_recv_time, sensor_alive, SIMULATION) filter_initialized = sm.all_checks() and sensor_all_checks(acc_msgs, gyro_msgs, sensor_valid, sensor_recv_time, sensor_alive, SIMULATION)
+10 -10
View File
@@ -31,7 +31,6 @@ class ModelConstants:
DISENGAGE_WIDTH = 5 DISENGAGE_WIDTH = 5
POSE_WIDTH = 6 POSE_WIDTH = 6
WIDE_FROM_DEVICE_WIDTH = 3 WIDE_FROM_DEVICE_WIDTH = 3
SIM_POSE_WIDTH = 6
LEAD_WIDTH = 4 LEAD_WIDTH = 4
LANE_LINES_WIDTH = 2 LANE_LINES_WIDTH = 2
ROAD_EDGES_WIDTH = 2 ROAD_EDGES_WIDTH = 2
@@ -72,13 +71,14 @@ class Plan:
class Meta: class Meta:
ENGAGED = slice(0, 1) ENGAGED = slice(0, 1)
# next 2, 4, 6, 8, 10 seconds # next 2, 4, 6, 8, 10 seconds
GAS_DISENGAGE = slice(1, 36, 7) GAS_DISENGAGE = slice(1, 31, 6)
BRAKE_DISENGAGE = slice(2, 36, 7) BRAKE_DISENGAGE = slice(2, 31, 6)
STEER_OVERRIDE = slice(3, 36, 7) STEER_OVERRIDE = slice(3, 31, 6)
HARD_BRAKE_3 = slice(4, 36, 7) HARD_BRAKE_3 = slice(4, 31, 6)
HARD_BRAKE_4 = slice(5, 36, 7) HARD_BRAKE_4 = slice(5, 31, 6)
HARD_BRAKE_5 = slice(6, 36, 7) HARD_BRAKE_5 = slice(6, 31, 6)
GAS_PRESS = slice(7, 36, 7)
# next 0, 2, 4, 6, 8, 10 seconds # next 0, 2, 4, 6, 8, 10 seconds
LEFT_BLINKER = slice(36, 48, 2) GAS_PRESS = slice(31, 55, 4)
RIGHT_BLINKER = slice(37, 48, 2) BRAKE_PRESS = slice(32, 55, 4)
LEFT_BLINKER = slice(33, 55, 4)
RIGHT_BLINKER = slice(34, 55, 4)
+2 -4
View File
@@ -8,7 +8,6 @@ if TICI:
os.environ['QCOM'] = '1' os.environ['QCOM'] = '1'
else: else:
from openpilot.selfdrive.modeld.runners.ort_helpers import make_onnx_cpu_runner from openpilot.selfdrive.modeld.runners.ort_helpers import make_onnx_cpu_runner
import gc
import math import math
import time import time
import pickle import pickle
@@ -21,7 +20,7 @@ from cereal import messaging
from cereal.messaging import PubMaster, SubMaster from cereal.messaging import PubMaster, SubMaster
from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
from openpilot.common.realtime import set_realtime_priority from openpilot.common.realtime import config_realtime_process
from openpilot.common.transformations.model import dmonitoringmodel_intrinsics, DM_INPUT_SIZE from openpilot.common.transformations.model import dmonitoringmodel_intrinsics, DM_INPUT_SIZE
from openpilot.common.transformations.camera import _ar_ox_fisheye, _os_fisheye from openpilot.common.transformations.camera import _ar_ox_fisheye, _os_fisheye
from openpilot.selfdrive.modeld.models.commonmodel_pyx import CLContext, MonitoringModelFrame from openpilot.selfdrive.modeld.models.commonmodel_pyx import CLContext, MonitoringModelFrame
@@ -140,9 +139,8 @@ def get_driverstate_packet(model_output: np.ndarray, frame_id: int, location_ts:
def main(): def main():
gc.disable()
setproctitle(PROCESS_NAME) setproctitle(PROCESS_NAME)
set_realtime_priority(1) config_realtime_process([0, 1, 2, 3], 5)
sentry.set_tag("daemon", PROCESS_NAME) sentry.set_tag("daemon", PROCESS_NAME)
cloudlog.bind(daemon=PROCESS_NAME) cloudlog.bind(daemon=PROCESS_NAME)
+4 -4
View File
@@ -112,10 +112,10 @@ def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._D
# temporal pose # temporal pose
temporal_pose = modelV2.temporalPose temporal_pose = modelV2.temporalPose
temporal_pose.trans = net_output_data['plan'][0,0,Plan.VELOCITY].tolist() temporal_pose.trans = net_output_data['sim_pose'][0,:ModelConstants.POSE_WIDTH//2].tolist()
temporal_pose.transStd = net_output_data['plan_stds'][0,0,Plan.VELOCITY].tolist() temporal_pose.transStd = net_output_data['sim_pose_stds'][0,:ModelConstants.POSE_WIDTH//2].tolist()
temporal_pose.rot = net_output_data['plan'][0,0,Plan.ORIENTATION_RATE].tolist() temporal_pose.rot = net_output_data['sim_pose'][0,ModelConstants.POSE_WIDTH//2:].tolist()
temporal_pose.rotStd = net_output_data['plan_stds'][0,0,Plan.ORIENTATION_RATE].tolist() temporal_pose.rotStd = net_output_data['sim_pose_stds'][0,ModelConstants.POSE_WIDTH//2:].tolist()
# poly path # poly path
fill_xyz_poly(driving_model_data.path, ModelConstants.POLY_PATH_DEGREE, *net_output_data['plan'][0,:,Plan.POSITION].T) fill_xyz_poly(driving_model_data.path, ModelConstants.POLY_PATH_DEGREE, *net_output_data['plan'][0,:,Plan.POSITION].T)
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:39786068cae1ed8c0dc34ef80c281dfcc67ed18a50e06b90765c49bcfdbf7db4 oid sha256:d21daa542227ecc5972da45df4e26f018ba113c0461f270e367d57e3ad89221a
size 51453312 size 51461700
+1
View File
@@ -91,6 +91,7 @@ class Parser:
self.parse_mdn('road_edges', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_ROAD_EDGES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH)) self.parse_mdn('road_edges', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_ROAD_EDGES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))
self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,)) self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
self.parse_mdn('road_transform', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,)) self.parse_mdn('road_transform', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
self.parse_mdn('sim_pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,))
self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,)) self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,))
self.parse_mdn('lead', outs, in_N=ModelConstants.LEAD_MHP_N, out_N=ModelConstants.LEAD_MHP_SELECTION, self.parse_mdn('lead', outs, in_N=ModelConstants.LEAD_MHP_N, out_N=ModelConstants.LEAD_MHP_SELECTION,
out_shape=(ModelConstants.LEAD_TRAJ_LEN,ModelConstants.LEAD_WIDTH)) out_shape=(ModelConstants.LEAD_TRAJ_LEN,ModelConstants.LEAD_WIDTH))
+2 -5
View File
@@ -1,15 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import gc
import cereal.messaging as messaging import cereal.messaging as messaging
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.realtime import set_realtime_priority from openpilot.common.realtime import config_realtime_process
from openpilot.selfdrive.monitoring.helpers import DriverMonitoring from openpilot.selfdrive.monitoring.helpers import DriverMonitoring
def dmonitoringd_thread(): def dmonitoringd_thread():
gc.disable() config_realtime_process([0, 1, 2, 3], 5)
set_realtime_priority(2)
params = Params() params = Params()
pm = messaging.PubMaster(['driverMonitoringState']) pm = messaging.PubMaster(['driverMonitoringState'])
-7
View File
@@ -2,10 +2,3 @@
from openpilot.selfdrive.pandad.pandad_api_impl import can_list_to_can_capnp, can_capnp_to_list from openpilot.selfdrive.pandad.pandad_api_impl import can_list_to_can_capnp, can_capnp_to_list
assert can_list_to_can_capnp assert can_list_to_can_capnp
assert can_capnp_to_list assert can_capnp_to_list
def can_capnp_to_can_list(can, src_filter=None):
ret = []
for msg in can:
if src_filter is None or msg.src in src_filter:
ret.append((msg.address, msg.dat, msg.src))
return ret
+1 -2
View File
@@ -1,8 +1,7 @@
#include "cereal/messaging/messaging.h" #include "cereal/messaging/messaging.h"
#include "selfdrive/pandad/panda.h"
#include "opendbc/can/common.h" #include "opendbc/can/common.h"
void can_list_to_can_capnp_cpp(const std::vector<can_frame> &can_list, std::string &out, bool sendcan, bool valid) { void can_list_to_can_capnp_cpp(const std::vector<CanFrame> &can_list, std::string &out, bool sendcan, bool valid) {
MessageBuilder msg; MessageBuilder msg;
auto event = msg.initEvent(valid); auto event = msg.initEvent(valid);
+3 -9
View File
@@ -6,12 +6,6 @@ from libcpp.string cimport string
from libcpp cimport bool from libcpp cimport bool
from libc.stdint cimport uint8_t, uint32_t, uint64_t from libc.stdint cimport uint8_t, uint32_t, uint64_t
cdef extern from "panda.h":
cdef struct can_frame:
long address
string dat
long src
cdef extern from "opendbc/can/common.h": cdef extern from "opendbc/can/common.h":
cdef struct CanFrame: cdef struct CanFrame:
long src long src
@@ -23,12 +17,12 @@ cdef extern from "opendbc/can/common.h":
vector[CanFrame] frames vector[CanFrame] frames
cdef extern from "can_list_to_can_capnp.cc": cdef extern from "can_list_to_can_capnp.cc":
void can_list_to_can_capnp_cpp(const vector[can_frame] &can_list, string &out, bool sendcan, bool valid) void can_list_to_can_capnp_cpp(const vector[CanFrame] &can_list, string &out, bool sendcan, bool valid)
void can_capnp_to_can_list_cpp(const vector[string] &strings, vector[CanData] &can_data, bool sendcan) void can_capnp_to_can_list_cpp(const vector[string] &strings, vector[CanData] &can_data, bool sendcan)
def can_list_to_can_capnp(can_msgs, msgtype='can', valid=True): def can_list_to_can_capnp(can_msgs, msgtype='can', valid=True):
cdef can_frame *f cdef CanFrame *f
cdef vector[can_frame] can_list cdef vector[CanFrame] can_list
can_list.reserve(len(can_msgs)) can_list.reserve(len(can_msgs))
for can_msg in can_msgs: for can_msg in can_msgs:
+2 -3
View File
@@ -7,7 +7,7 @@ import cereal.messaging as messaging
from cereal import car, log, custom from cereal import car, log, custom
from msgq.visionipc import VisionIpcClient, VisionStreamType from msgq.visionipc import VisionIpcClient, VisionStreamType
from panda import ALTERNATIVE_EXPERIENCE from opendbc.safety import ALTERNATIVE_EXPERIENCE
from openpilot.common.params import Params from openpilot.common.params import Params
@@ -31,7 +31,6 @@ from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
REPLAY = "REPLAY" in os.environ REPLAY = "REPLAY" in os.environ
SIMULATION = "SIMULATION" in os.environ SIMULATION = "SIMULATION" in os.environ
TESTING_CLOSET = "TESTING_CLOSET" in os.environ TESTING_CLOSET = "TESTING_CLOSET" in os.environ
IGNORE_PROCESSES = {"loggerd", "encoderd", "statsd"}
LONGITUDINAL_PERSONALITY_MAP = {v: k for k, v in log.LongitudinalPersonality.schema.enumerants.items()} LONGITUDINAL_PERSONALITY_MAP = {v: k for k, v in log.LongitudinalPersonality.schema.enumerants.items()}
ThermalStatus = log.DeviceState.ThermalStatus ThermalStatus = log.DeviceState.ThermalStatus
@@ -284,7 +283,7 @@ class SelfdriveD(CruiseHelper):
if not_running != self.not_running_prev: if not_running != self.not_running_prev:
cloudlog.event("process_not_running", not_running=not_running, error=True) cloudlog.event("process_not_running", not_running=not_running, error=True)
self.not_running_prev = not_running self.not_running_prev = not_running
if self.sm.recv_frame['managerState'] and (not_running - IGNORE_PROCESSES): if self.sm.recv_frame['managerState'] and not_running:
self.events.add(EventName.processNotRunning) self.events.add(EventName.processNotRunning)
else: else:
if not SIMULATION and not self.rk.lagging: if not SIMULATION and not self.rk.lagging:
@@ -66,7 +66,7 @@ class Maneuver:
print("Crashed!!!!") print("Crashed!!!!")
valid = False valid = False
if self.ensure_start and log['v_rel'] > 0 and log['speeds'][-1] <= 0.1: if self.ensure_start and log['v_rel'] > 0 and log['acceleration'] < 1e-3:
print('LongitudinalPlanner not starting!') print('LongitudinalPlanner not starting!')
valid = False valid = False
@@ -30,8 +30,8 @@ class Plant:
self.distance = 0. self.distance = 0.
self.speed = speed self.speed = speed
self.should_stop = False
self.acceleration = 0.0 self.acceleration = 0.0
self.speeds = []
# lead car # lead car
self.lead_relevancy = lead_relevancy self.lead_relevancy = lead_relevancy
@@ -134,9 +134,9 @@ class Plant:
'liveParameters': lp.liveParameters, 'liveParameters': lp.liveParameters,
'modelV2': model.modelV2} 'modelV2': model.modelV2}
self.planner.update(sm) self.planner.update(sm)
self.speed = self.planner.v_desired_filter.x self.acceleration = self.planner.output_a_target
self.acceleration = self.planner.a_desired self.speed = self.speed + self.acceleration * self.ts
self.speeds = self.planner.v_desired_trajectory.tolist() self.should_stop = self.planner.output_should_stop
fcw = self.planner.fcw fcw = self.planner.fcw
self.distance_lead = self.distance_lead + v_lead * self.ts self.distance_lead = self.distance_lead + v_lead * self.ts
@@ -168,7 +168,7 @@ class Plant:
"distance": self.distance, "distance": self.distance,
"speed": self.speed, "speed": self.speed,
"acceleration": self.acceleration, "acceleration": self.acceleration,
"speeds": self.speeds, "should_stop": self.should_stop,
"distance_lead": self.distance_lead, "distance_lead": self.distance_lead,
"fcw": fcw, "fcw": fcw,
} }
@@ -150,10 +150,7 @@ def create_maneuvers(kwargs):
enabled=False, enabled=False,
**kwargs, **kwargs,
), ),
] Maneuver(
if not kwargs['e2e']:
# allow_throttle won't trigger with e2e
maneuvers.append(Maneuver(
"slow to 5m/s with allow_throttle = False and pitch = +0.1", "slow to 5m/s with allow_throttle = False and pitch = +0.1",
duration=30., duration=30.,
initial_speed=20., initial_speed=20.,
@@ -164,7 +161,7 @@ def create_maneuvers(kwargs):
breakpoints=[0.0, 2., 2.01], breakpoints=[0.0, 2., 2.01],
ensure_slowdown=True, ensure_slowdown=True,
**kwargs, **kwargs,
)) )]
if not kwargs['force_decel']: if not kwargs['force_decel']:
# controls relies on planner commanding to move for stock-ACC resume spamming # controls relies on planner commanding to move for stock-ACC resume spamming
maneuvers.append(Maneuver( maneuvers.append(Maneuver(
+8 -8
View File
@@ -6,15 +6,15 @@ import traceback
from cereal import messaging, car, log from cereal import messaging, car, log
from opendbc.car.fingerprints import MIGRATION from opendbc.car.fingerprints import MIGRATION
from opendbc.car.toyota.values import EPS_SCALE from opendbc.car.toyota.values import EPS_SCALE, ToyotaSafetyFlags
from opendbc.car.ford.values import CAR as FORD, FordFlags from opendbc.car.ford.values import CAR as FORD, FordFlags, FordSafetyFlags
from opendbc.car.hyundai.values import HyundaiSafetyFlags
from openpilot.selfdrive.modeld.constants import ModelConstants from openpilot.selfdrive.modeld.constants import ModelConstants
from openpilot.selfdrive.modeld.fill_model_msg import fill_xyz_poly, fill_lane_line_meta from openpilot.selfdrive.modeld.fill_model_msg import fill_xyz_poly, fill_lane_line_meta
from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_encode_index from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_encode_index
from openpilot.selfdrive.controls.lib.longitudinal_planner import get_accel_from_plan from openpilot.selfdrive.controls.lib.longitudinal_planner import get_accel_from_plan
from openpilot.system.manager.process_config import managed_processes from openpilot.system.manager.process_config import managed_processes
from openpilot.tools.lib.logreader import LogIterable from openpilot.tools.lib.logreader import LogIterable
from panda import Panda
MessageWithIndex = tuple[int, capnp.lib.capnp._DynamicStructReader] MessageWithIndex = tuple[int, capnp.lib.capnp._DynamicStructReader]
MigrationOps = tuple[list[tuple[int, capnp.lib.capnp._DynamicStructReader]], list[capnp.lib.capnp._DynamicStructReader], list[int]] MigrationOps = tuple[list[tuple[int, capnp.lib.capnp._DynamicStructReader]], list[capnp.lib.capnp._DynamicStructReader], list[int]]
@@ -269,19 +269,19 @@ def migrate_carOutput(msgs):
def migrate_pandaStates(msgs): def migrate_pandaStates(msgs):
# TODO: safety param migration should be handled automatically # TODO: safety param migration should be handled automatically
safety_param_migration = { safety_param_migration = {
"TOYOTA_PRIUS": EPS_SCALE["TOYOTA_PRIUS"] | Panda.FLAG_TOYOTA_STOCK_LONGITUDINAL, "TOYOTA_PRIUS": EPS_SCALE["TOYOTA_PRIUS"] | ToyotaSafetyFlags.FLAG_TOYOTA_STOCK_LONGITUDINAL,
"TOYOTA_RAV4": EPS_SCALE["TOYOTA_RAV4"] | Panda.FLAG_TOYOTA_ALT_BRAKE, "TOYOTA_RAV4": EPS_SCALE["TOYOTA_RAV4"] | ToyotaSafetyFlags.FLAG_TOYOTA_ALT_BRAKE,
"KIA_EV6": Panda.FLAG_HYUNDAI_EV_GAS | Panda.FLAG_HYUNDAI_CANFD_HDA2, "KIA_EV6": HyundaiSafetyFlags.FLAG_HYUNDAI_EV_GAS | HyundaiSafetyFlags.FLAG_HYUNDAI_CANFD_HDA2,
} }
# TODO: get new Ford route # TODO: get new Ford route
safety_param_migration |= {car: Panda.FLAG_FORD_LONG_CONTROL for car in (set(FORD) - FORD.with_flags(FordFlags.CANFD))} safety_param_migration |= {car: FordSafetyFlags.FLAG_FORD_LONG_CONTROL for car in (set(FORD) - FORD.with_flags(FordFlags.CANFD))}
# Migrate safety param base on carParams # Migrate safety param base on carParams
CP = next((m.carParams for _, m in msgs if m.which() == 'carParams'), None) CP = next((m.carParams for _, m in msgs if m.which() == 'carParams'), None)
assert CP is not None, "carParams message not found" assert CP is not None, "carParams message not found"
fingerprint = MIGRATION.get(CP.carFingerprint, CP.carFingerprint) fingerprint = MIGRATION.get(CP.carFingerprint, CP.carFingerprint)
if fingerprint in safety_param_migration: if fingerprint in safety_param_migration:
safety_param = safety_param_migration[fingerprint] safety_param = safety_param_migration[fingerprint].value
elif len(CP.safetyConfigs): elif len(CP.safetyConfigs):
safety_param = CP.safetyConfigs[0].safetyParam safety_param = CP.safetyConfigs[0].safetyParam
if CP.safetyConfigs[0].safetyParamDEPRECATED != 0: if CP.safetyConfigs[0].safetyParamDEPRECATED != 0:
+15 -12
View File
@@ -33,7 +33,7 @@ GITHUB = GithubUtils(API_TOKEN, DATA_TOKEN)
EXEC_TIMINGS = [ EXEC_TIMINGS = [
# model, instant max, average max # model, instant max, average max
("modelV2", 0.03, 0.025), ("modelV2", 0.035, 0.025),
("driverStateV2", 0.02, 0.015), ("driverStateV2", 0.02, 0.015),
] ]
@@ -57,21 +57,24 @@ def get_event(logs, event):
def zl(array, fill): def zl(array, fill):
return zip_longest(array, [], fillvalue=fill) return zip_longest(array, [], fillvalue=fill)
def get_idx_if_non_empty(l, idx=None):
return l if idx is None else (l[idx] if len(l) > 0 else None)
def generate_report(proposed, master, tmp, commit): def generate_report(proposed, master, tmp, commit):
ModelV2_Plots = zl([ ModelV2_Plots = zl([
(lambda x: x.velocity.x[0], "velocity.x"), (lambda x: get_idx_if_non_empty(x.velocity.x, 0), "velocity.x"),
(lambda x: x.action.desiredCurvature, "desiredCurvature"), (lambda x: get_idx_if_non_empty(x.action.desiredCurvature), "desiredCurvature"),
(lambda x: x.leadsV3[0].x[0], "leadsV3.x"), (lambda x: get_idx_if_non_empty(x.leadsV3[0].x, 0), "leadsV3.x"),
(lambda x: x.laneLines[1].y[0], "laneLines.y"), (lambda x: get_idx_if_non_empty(x.laneLines[1].y, 0), "laneLines.y"),
#(lambda x: x.meta.disengagePredictions.gasPressProbs[1], "gasPressProbs") (lambda x: get_idx_if_non_empty(x.meta.disengagePredictions.gasPressProbs, 1), "gasPressProbs")
], "modelV2") ], "modelV2")
DriverStateV2_Plots = zl([ DriverStateV2_Plots = zl([
(lambda x: x.wheelOnRightProb, "wheelOnRightProb"), (lambda x: get_idx_if_non_empty(x.wheelOnRightProb), "wheelOnRightProb"),
(lambda x: x.leftDriverData.faceProb, "leftDriverData.faceProb"), (lambda x: get_idx_if_non_empty(x.leftDriverData.faceProb), "leftDriverData.faceProb"),
(lambda x: x.leftDriverData.faceOrientation[0], "leftDriverData.faceOrientation0"), (lambda x: get_idx_if_non_empty(x.leftDriverData.faceOrientation, 0), "leftDriverData.faceOrientation0"),
(lambda x: x.leftDriverData.leftBlinkProb, "leftDriverData.leftBlinkProb"), (lambda x: get_idx_if_non_empty(x.leftDriverData.leftBlinkProb), "leftDriverData.leftBlinkProb"),
(lambda x: x.leftDriverData.notReadyProb[0], "leftDriverData.notReadyProb0"), (lambda x: get_idx_if_non_empty(x.leftDriverData.notReadyProb, 0), "leftDriverData.notReadyProb0"),
(lambda x: x.rightDriverData.faceProb, "rightDriverData.faceProb"), (lambda x: get_idx_if_non_empty(x.rightDriverData.faceProb), "rightDriverData.faceProb"),
], "driverStateV2") ], "driverStateV2")
return [plot(map(v[0], get_event(proposed, event)), \ return [plot(map(v[0], get_event(proposed, event)), \
@@ -18,11 +18,11 @@ from cereal import car
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
from msgq.visionipc import VisionIpcServer, get_endpoint_name as vipc_get_endpoint_name from msgq.visionipc import VisionIpcServer, get_endpoint_name as vipc_get_endpoint_name
from opendbc.car.car_helpers import get_car, interfaces from opendbc.car.car_helpers import get_car, interfaces
from opendbc.safety import ALTERNATIVE_EXPERIENCE
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.prefix import OpenpilotPrefix from openpilot.common.prefix import OpenpilotPrefix
from openpilot.common.timeout import Timeout from openpilot.common.timeout import Timeout
from openpilot.common.realtime import DT_CTRL from openpilot.common.realtime import DT_CTRL
from panda.python import ALTERNATIVE_EXPERIENCE
from openpilot.selfdrive.car.card import can_comm_callbacks, convert_to_capnp from openpilot.selfdrive.car.card import can_comm_callbacks, convert_to_capnp
from openpilot.system.manager.process_config import managed_processes from openpilot.system.manager.process_config import managed_processes
from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_camera_state, available_streams from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_camera_state, available_streams
+27 -45
View File
@@ -8,7 +8,6 @@ import shutil
import subprocess import subprocess
import time import time
import numpy as np import numpy as np
import zstandard as zstd
from collections import Counter, defaultdict from collections import Counter, defaultdict
from pathlib import Path from pathlib import Path
from tabulate import tabulate from tabulate import tabulate
@@ -23,7 +22,6 @@ from openpilot.selfdrive.selfdrived.events import EVENTS, ET
from openpilot.selfdrive.test.helpers import set_params_enabled, release_only from openpilot.selfdrive.test.helpers import set_params_enabled, release_only
from openpilot.system.hardware import HARDWARE from openpilot.system.hardware import HARDWARE
from openpilot.system.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
from openpilot.system.loggerd.uploader import LOG_COMPRESSION_LEVEL
from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.logreader import LogReader
""" """
@@ -36,7 +34,7 @@ CPU usage budget
TEST_DURATION = 25 TEST_DURATION = 25
LOG_OFFSET = 8 LOG_OFFSET = 8
MAX_TOTAL_CPU = 275. # total for all 8 cores MAX_TOTAL_CPU = 280. # total for all 8 cores
PROCS = { PROCS = {
# Baseline CPU usage by process # Baseline CPU usage by process
"selfdrive.controls.controlsd": 16.0, "selfdrive.controls.controlsd": 16.0,
@@ -44,7 +42,7 @@ PROCS = {
"selfdrive.car.card": 26.0, "selfdrive.car.card": 26.0,
"./loggerd": 14.0, "./loggerd": 14.0,
"./encoderd": 17.0, "./encoderd": 17.0,
"./camerad": 14.5, "./camerad": 10.0,
"selfdrive.controls.plannerd": 9.0, "selfdrive.controls.plannerd": 9.0,
"./ui": 18.0, "./ui": 18.0,
"selfdrive.locationd.paramsd": 9.0, "selfdrive.locationd.paramsd": 9.0,
@@ -101,12 +99,12 @@ TIMINGS = {
"wideRoadCameraState": [1.5, 0.35], "wideRoadCameraState": [1.5, 0.35],
} }
LOGS_SIZE_RATE = { LOGS_SIZE = { # MB per segment
"qlog": 0.0083, "qlog.zst": 0.5,
"rlog": 0.135, "rlog.zst": 8.1,
"qcamera.ts": 0.03828, "qcamera.ts": 2.3,
} }
LOGS_SIZE_RATE.update(dict.fromkeys(['ecamera.hevc', 'fcamera.hevc'], 1.2740)) LOGS_SIZE.update(dict.fromkeys(['ecamera.hevc', 'fcamera.hevc', 'dcamera.hevc'], 76.5))
def cputime_total(ct): def cputime_total(ct):
@@ -119,15 +117,16 @@ class TestOnroad:
@classmethod @classmethod
def setup_class(cls): def setup_class(cls):
if "DEBUG" in os.environ: if "DEBUG" in os.environ:
segs = filter(lambda x: os.path.exists(os.path.join(x, "rlog")), Path(Paths.log_root()).iterdir()) segs = filter(lambda x: os.path.exists(os.path.join(x, "rlog.zst")), Path(Paths.log_root()).iterdir())
segs = sorted(segs, key=lambda x: x.stat().st_mtime) segs = sorted(segs, key=lambda x: x.stat().st_mtime)
print(segs[-3]) print(segs[-3])
cls.lr = list(LogReader(os.path.join(segs[-3], "rlog"))) cls.lr = list(LogReader(os.path.join(segs[-3], "rlog.zst")))
return return
# setup env # setup env
params = Params() params = Params()
params.remove("CurrentRoute") params.remove("CurrentRoute")
params.put_bool("RecordFront", True)
set_params_enabled() set_params_enabled()
os.environ['REPLAY'] = '1' os.environ['REPLAY'] = '1'
os.environ['TESTING_CLOSET'] = '1' os.environ['TESTING_CLOSET'] = '1'
@@ -173,18 +172,15 @@ class TestOnroad:
if proc.wait(60) is None: if proc.wait(60) is None:
proc.kill() proc.kill()
cls.lrs = [list(LogReader(os.path.join(str(s), "rlog"))) for s in cls.segments] cls.lrs = [list(LogReader(os.path.join(str(s), "rlog.zst"))) for s in cls.segments]
cls.lr = list(LogReader(os.path.join(str(cls.segments[0]), "rlog"))) cls.lr = list(LogReader(os.path.join(str(cls.segments[0]), "rlog.zst")))
cls.log_path = cls.segments[0] cls.log_path = cls.segments[0]
cls.log_sizes = {} cls.log_sizes = {}
for f in cls.log_path.iterdir(): for f in cls.log_path.iterdir():
assert f.is_file() assert f.is_file()
cls.log_sizes[f] = f.stat().st_size / 1e6 cls.log_sizes[f] = f.stat().st_size / 1e6
if f.name in ("qlog", "rlog"):
with open(f, 'rb') as ff:
cls.log_sizes[f] = len(zstd.compress(ff.read(), LOG_COMPRESSION_LEVEL)) / 1e6
cls.msgs = defaultdict(list) cls.msgs = defaultdict(list)
for m in cls.lr: for m in cls.lr:
@@ -217,12 +213,14 @@ class TestOnroad:
big_logs = [f for f, n in cnt.most_common(3) if n / sum(cnt.values()) > 30.] big_logs = [f for f, n in cnt.most_common(3) if n / sum(cnt.values()) > 30.]
assert len(big_logs) == 0, f"Log spam: {big_logs}" assert len(big_logs) == 0, f"Log spam: {big_logs}"
def test_log_sizes(self): def test_log_sizes(self, subtests):
# TODO: this isn't super stable between different devices
for f, sz in self.log_sizes.items(): for f, sz in self.log_sizes.items():
rate = LOGS_SIZE_RATE[f.name] rate = LOGS_SIZE[f.name]/60.
minn = rate * TEST_DURATION * 0.8 minn = rate * TEST_DURATION * 0.5
maxx = rate * TEST_DURATION * 1.2 maxx = rate * TEST_DURATION * 1.5
assert minn < sz < maxx with subtests.test(file=f.name):
assert minn < sz < maxx
def test_ui_timings(self): def test_ui_timings(self):
result = "\n" result = "\n"
@@ -316,37 +314,21 @@ class TestOnroad:
def test_gpu_usage(self): def test_gpu_usage(self):
assert self.gpu_procs == {"weston", "ui", "camerad", "selfdrive.modeld.modeld", "selfdrive.modeld.dmonitoringmodeld"} assert self.gpu_procs == {"weston", "ui", "camerad", "selfdrive.modeld.modeld", "selfdrive.modeld.dmonitoringmodeld"}
def test_camera_processing_time(self): def test_camera_frame_timings(self, subtests):
result = "\n" result = "\n"
result += "------------------------------------------------\n" result += "------------------------------------------------\n"
result += "-------------- ImgProc Timing ------------------\n" result += "----------------- SOF Timing ------------------\n"
result += "------------------------------------------------\n"
ts = []
for s in ['roadCameraState', 'driverCameraState', 'wideCameraState']:
ts.extend(getattr(m, s).processingTime for m in self.msgs[s])
assert min(ts) < 0.025, f"high execution time: {min(ts)}"
result += f"execution time: min {min(ts):.5f}s\n"
result += f"execution time: max {max(ts):.5f}s\n"
result += f"execution time: mean {np.mean(ts):.5f}s\n"
result += "------------------------------------------------\n"
print(result)
@pytest.mark.skip("TODO: enable once timings are fixed")
def test_camera_frame_timings(self):
result = "\n"
result += "------------------------------------------------\n"
result += "----------------- SoF Timing ------------------\n"
result += "------------------------------------------------\n" result += "------------------------------------------------\n"
for name in ['roadCameraState', 'wideRoadCameraState', 'driverCameraState']: for name in ['roadCameraState', 'wideRoadCameraState', 'driverCameraState']:
ts = [getattr(m, m.which()).timestampSof for m in self.lr if name in m.which()] ts = [getattr(m, m.which()).timestampSof for m in self.lr if name in m.which()]
d_ms = np.diff(ts) / 1e6 d_ms = np.diff(ts) / 1e6
d50 = np.abs(d_ms-50) d50 = np.abs(d_ms-50)
assert max(d50) < 1.0, f"high sof delta vs 50ms: {max(d50)}" result += f"{name} sof delta vs 50ms: min {min(d50):.2f}ms\n"
result += f"{name} sof delta vs 50ms: min {min(d50):.5f}s\n" result += f"{name} sof delta vs 50ms: max {max(d50):.2f}ms\n"
result += f"{name} sof delta vs 50ms: max {max(d50):.5f}s\n" result += f"{name} sof delta vs 50ms: mean {d50.mean():.2f}ms\n"
result += f"{name} sof delta vs 50ms: mean {d50.mean():.5f}s\n" with subtests.test(camera=name):
result += "------------------------------------------------\n" assert max(d50) < 5.0, f"high SOF delta vs 50ms: {max(d50)}"
result += "------------------------------------------------\n"
print(result) print(result)
def test_mpc_execution_timings(self): def test_mpc_execution_timings(self):
+1 -4
View File
@@ -1,9 +1,5 @@
#include <QDebug>
#include <QProcess>
#include "selfdrive/ui/qt/offroad/developer_panel.h" #include "selfdrive/ui/qt/offroad/developer_panel.h"
#include "selfdrive/ui/qt/widgets/ssh_keys.h" #include "selfdrive/ui/qt/widgets/ssh_keys.h"
#include "common/util.h"
#ifdef SUNNYPILOT #ifdef SUNNYPILOT
#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" #include "selfdrive/ui/sunnypilot/qt/widgets/controls.h"
@@ -114,6 +110,7 @@ void DeveloperPanel::updateToggles(bool _offroad) {
experimentalLongitudinalToggle->setVisible(false); experimentalLongitudinalToggle->setVisible(false);
hyundaiRadarTracksToggle->setVisible(false); hyundaiRadarTracksToggle->setVisible(false);
} }
experimentalLongitudinalToggle->refresh();
offroad = _offroad; offroad = _offroad;
} }
+1 -1
View File
@@ -20,7 +20,7 @@ private:
ParamControl* experimentalLongitudinalToggle; ParamControl* experimentalLongitudinalToggle;
ParamControl* hyundaiRadarTracksToggle; ParamControl* hyundaiRadarTracksToggle;
bool is_release; bool is_release;
bool offroad; bool offroad = false;
private slots: private slots:
void updateToggles(bool _offroad); void updateToggles(bool _offroad);
+14
View File
@@ -42,6 +42,20 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
tr("When enabled, pressing the accelerator pedal will disengage openpilot."), tr("When enabled, pressing the accelerator pedal will disengage openpilot."),
"../assets/offroad/icon_disengage_on_accelerator.svg", "../assets/offroad/icon_disengage_on_accelerator.svg",
}, },
{
"FirehoseMode",
tr("FIREHOSE Mode"),
tr("Enable <b>FIREHOSE Mode</b> to get your driving data in the training set.<br><br>"
"Follow these steps to get your device ready:<br>"
" 1. Bring your device inside and connect to a good USB-C adapter<br>"
" 2. Connect to Wi-Fi<br>"
" 3. Enable this toggle<br>"
" 4. Leave it connected for at least 30 minutes<br>"
"<br>"
"This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness."
""),
"../assets/offroad/icon_warning.png",
},
{ {
"IsLdwEnabled", "IsLdwEnabled",
tr("Enable Lane Departure Warnings"), tr("Enable Lane Departure Warnings"),
View File
+8
View File
@@ -1553,6 +1553,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1537,6 +1537,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1537,6 +1537,14 @@ Esto puede tardar un minuto.</translation>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1537,6 +1537,14 @@ Cela peut prendre jusqu&apos;à une minute.</translation>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1533,6 +1533,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1533,6 +1533,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1537,6 +1537,14 @@ Isso pode levar até um minuto.</translation>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1533,6 +1533,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1531,6 +1531,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1533,6 +1533,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+8
View File
@@ -1533,6 +1533,14 @@ This may take up to a minute.</source>
<source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source> <source>Enable toggle to allow the model to determine when to use sunnypilot ACC or sunnypilot End to End Longitudinal.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>FIREHOSE Mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable &lt;b&gt;FIREHOSE Mode&lt;/b&gt; to get your driving data in the training set.&lt;br&gt;&lt;br&gt;Follow these steps to get your device ready:&lt;br&gt; 1. Bring your device inside and connect to a good USB-C adapter&lt;br&gt; 2. Connect to Wi-Fi&lt;br&gt; 3. Enable this toggle&lt;br&gt; 4. Leave it connected for at least 30 minutes&lt;br&gt;&lt;br&gt;This toggle turns off once you restart your device. Repeat once a week for maximum effectiveness.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>Updater</name> <name>Updater</name>
+3 -3
View File
@@ -24,10 +24,10 @@ THE SOFTWARE.
Last updated: July 29, 2024 Last updated: July 29, 2024
""" """
from panda import Panda, ALTERNATIVE_EXPERIENCE
from openpilot.common.params import Params from openpilot.common.params import Params
from opendbc.safety import ALTERNATIVE_EXPERIENCE
from opendbc.car.hyundai.values import HyundaiSafetyFlags
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP
@@ -55,7 +55,7 @@ class MadsParams:
hyundai_cruise_main_toggleable = True hyundai_cruise_main_toggleable = True
if hyundai_cruise_main_toggleable: if hyundai_cruise_main_toggleable:
CP_SP.flags |= HyundaiFlagsSP.LONGITUDINAL_MAIN_CRUISE_TOGGLEABLE.value CP_SP.flags |= HyundaiFlagsSP.LONGITUDINAL_MAIN_CRUISE_TOGGLEABLE.value
CP.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_LONG_MAIN_CRUISE_TOGGLEABLE CP.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.FLAG_HYUNDAI_LONG_MAIN_CRUISE_TOGGLEABLE.value
# MADS is currently not supported in Tesla due to lack of consistent states to engage controls # MADS is currently not supported in Tesla due to lack of consistent states to engage controls
# TODO-SP: To enable MADS for Tesla, identify consistent signals for MADS toggling # TODO-SP: To enable MADS for Tesla, identify consistent signals for MADS toggling
+1 -1
View File
@@ -1 +1 @@
39786068cae1ed8c0dc34ef80c281dfcc67ed18a50e06b90765c49bcfdbf7db4 d21daa542227ecc5972da45df4e26f018ba113c0461f270e367d57e3ad89221a
+18 -14
View File
@@ -15,7 +15,6 @@ import tempfile
import threading import threading
import time import time
import gzip import gzip
import zstandard as zstd
from dataclasses import asdict, dataclass, replace from dataclasses import asdict, dataclass, replace
from datetime import datetime from datetime import datetime
from functools import partial from functools import partial
@@ -32,11 +31,10 @@ import cereal.messaging as messaging
from cereal import log from cereal import log
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
from openpilot.common.api import Api from openpilot.common.api import Api
from openpilot.common.file_helpers import CallbackReader from openpilot.common.file_helpers import CallbackReader, get_upload_stream
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.common.realtime import set_core_affinity from openpilot.common.realtime import set_core_affinity
from openpilot.system.hardware import HARDWARE, PC from openpilot.system.hardware import HARDWARE, PC
from openpilot.system.loggerd.uploader import LOG_COMPRESSION_LEVEL
from openpilot.system.loggerd.xattr_cache import getxattr, setxattr from openpilot.system.loggerd.xattr_cache import getxattr, setxattr
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
from openpilot.system.version import get_build_metadata from openpilot.system.version import get_build_metadata
@@ -147,6 +145,9 @@ def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None:
threading.Thread(target=ws_recv, args=(ws, end_event), name='ws_recv'), threading.Thread(target=ws_recv, args=(ws, end_event), name='ws_recv'),
threading.Thread(target=ws_send, args=(ws, end_event), name='ws_send'), threading.Thread(target=ws_send, args=(ws, end_event), name='ws_send'),
threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler'), threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler'),
threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler2'),
threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler3'),
threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler4'),
threading.Thread(target=log_handler, args=(end_event,), name='log_handler'), threading.Thread(target=log_handler, args=(end_event,), name='log_handler'),
threading.Thread(target=stat_handler, args=(end_event,), name='stat_handler'), threading.Thread(target=stat_handler, args=(end_event,), name='stat_handler'),
] + [ ] + [
@@ -293,17 +294,17 @@ def _do_upload(upload_item: UploadItem, callback: Callable = None) -> requests.R
path = strip_zst_extension(path) path = strip_zst_extension(path)
compress = True compress = True
with open(path, "rb") as f: stream = None
content = f.read() try:
if compress: stream, content_length = get_upload_stream(path, compress)
cloudlog.event("athena.upload_handler.compress", fn=path, fn_orig=upload_item.path) response = requests.put(upload_item.url,
content = zstd.compress(content, LOG_COMPRESSION_LEVEL) data=CallbackReader(stream, callback, content_length) if callback else stream,
headers={**upload_item.headers, 'Content-Length': str(content_length)},
with io.BytesIO(content) as data: timeout=30)
return requests.put(upload_item.url, return response
data=CallbackReader(data, callback, len(content)) if callback else data, finally:
headers={**upload_item.headers, 'Content-Length': str(len(content))}, if stream:
timeout=30) stream.close()
# security: user should be able to request any message from their car # security: user should be able to request any message from their car
@@ -522,6 +523,9 @@ def getSshAuthorizedKeys() -> str:
def getGithubUsername() -> str: def getGithubUsername() -> str:
return Params().get("GithubUsername", encoding='utf8') or '' return Params().get("GithubUsername", encoding='utf8') or ''
@dispatcher.add_method
def getFirehoseMode() -> bool:
return Params().get_bool("FirehoseMode") or False
@dispatcher.add_method @dispatcher.add_method
def getSimInfo(): def getSimInfo():
+1 -1
View File
@@ -138,7 +138,7 @@ class TestAthenadMethods:
route = '2021-03-29--13-32-47' route = '2021-03-29--13-32-47'
segments = [0, 1, 2, 3, 11] segments = [0, 1, 2, 3, 11]
filenames = ['qlog', 'qcamera.ts', 'rlog', 'fcamera.hevc', 'ecamera.hevc', 'dcamera.hevc'] filenames = ['qlog.zst', 'qcamera.ts', 'rlog.zst', 'fcamera.hevc', 'ecamera.hevc', 'dcamera.hevc']
files = [f'{route}--{s}/{f}' for s in segments for f in filenames] files = [f'{route}--{s}/{f}' for s in segments for f in filenames]
for file in files: for file in files:
self._create_file(file) self._create_file(file)
+1 -1
View File
@@ -1,6 +1,6 @@
Import('env', 'arch', 'messaging', 'common', 'gpucommon', 'visionipc') Import('env', 'arch', 'messaging', 'common', 'gpucommon', 'visionipc')
libs = ['pthread', common, 'jpeg', 'OpenCL', messaging, visionipc, gpucommon] libs = ['pthread', common, 'OpenCL', messaging, visionipc, gpucommon]
if arch != "Darwin": if arch != "Darwin":
camera_obj = env.Object(['cameras/camera_qcom2.cc', 'cameras/camera_common.cc', 'cameras/spectra.cc', camera_obj = env.Object(['cameras/camera_qcom2.cc', 'cameras/camera_common.cc', 'cameras/spectra.cc',
File diff suppressed because one or more lines are too long
+2 -93
View File
@@ -3,8 +3,6 @@
#include <cassert> #include <cassert>
#include <string> #include <string>
#include <jpeglib.h>
#include "common/clutil.h" #include "common/clutil.h"
#include "common/swaglog.h" #include "common/swaglog.h"
@@ -64,11 +62,11 @@ void CameraBuf::init(cl_device_id device_id, cl_context context, SpectraCamera *
const SensorInfo *sensor = cam->sensor.get(); const SensorInfo *sensor = cam->sensor.get();
is_raw = cam->is_raw; is_raw = cam->output_type == ISP_RAW_OUTPUT;
frame_metadata = std::make_unique<FrameMetadata[]>(frame_buf_count); frame_metadata = std::make_unique<FrameMetadata[]>(frame_buf_count);
// RAW frames from ISP // RAW frames from ISP
if (is_raw) { if (cam->output_type != ISP_IFE_PROCESSED) {
camera_bufs_raw = std::make_unique<VisionBuf[]>(frame_buf_count); camera_bufs_raw = std::make_unique<VisionBuf[]>(frame_buf_count);
const int raw_frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride; const int raw_frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride;
@@ -150,95 +148,6 @@ kj::Array<uint8_t> get_raw_frame_image(const CameraBuf *b) {
return kj::mv(frame_image); return kj::mv(frame_image);
} }
static kj::Array<capnp::byte> yuv420_to_jpeg(const CameraBuf *b, int thumbnail_width, int thumbnail_height) {
int downscale = b->cur_yuv_buf->width / thumbnail_width;
assert(downscale * thumbnail_height == b->cur_yuv_buf->height);
int in_stride = b->cur_yuv_buf->stride;
// make the buffer big enough. jpeg_write_raw_data requires 16-pixels aligned height to be used.
std::unique_ptr<uint8_t[]> buf(new uint8_t[(thumbnail_width * ((thumbnail_height + 15) & ~15) * 3) / 2]);
uint8_t *y_plane = buf.get();
uint8_t *u_plane = y_plane + thumbnail_width * thumbnail_height;
uint8_t *v_plane = u_plane + (thumbnail_width * thumbnail_height) / 4;
{
// subsampled conversion from nv12 to yuv
for (int hy = 0; hy < thumbnail_height/2; hy++) {
for (int hx = 0; hx < thumbnail_width/2; hx++) {
int ix = hx * downscale + (downscale-1)/2;
int iy = hy * downscale + (downscale-1)/2;
y_plane[(hy*2 + 0)*thumbnail_width + (hx*2 + 0)] = b->cur_yuv_buf->y[(iy*2 + 0) * in_stride + ix*2 + 0];
y_plane[(hy*2 + 0)*thumbnail_width + (hx*2 + 1)] = b->cur_yuv_buf->y[(iy*2 + 0) * in_stride + ix*2 + 1];
y_plane[(hy*2 + 1)*thumbnail_width + (hx*2 + 0)] = b->cur_yuv_buf->y[(iy*2 + 1) * in_stride + ix*2 + 0];
y_plane[(hy*2 + 1)*thumbnail_width + (hx*2 + 1)] = b->cur_yuv_buf->y[(iy*2 + 1) * in_stride + ix*2 + 1];
u_plane[hy*thumbnail_width/2 + hx] = b->cur_yuv_buf->uv[iy*in_stride + ix*2 + 0];
v_plane[hy*thumbnail_width/2 + hx] = b->cur_yuv_buf->uv[iy*in_stride + ix*2 + 1];
}
}
}
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
uint8_t *thumbnail_buffer = nullptr;
size_t thumbnail_len = 0;
jpeg_mem_dest(&cinfo, &thumbnail_buffer, &thumbnail_len);
cinfo.image_width = thumbnail_width;
cinfo.image_height = thumbnail_height;
cinfo.input_components = 3;
jpeg_set_defaults(&cinfo);
jpeg_set_colorspace(&cinfo, JCS_YCbCr);
// configure sampling factors for yuv420.
cinfo.comp_info[0].h_samp_factor = 2; // Y
cinfo.comp_info[0].v_samp_factor = 2;
cinfo.comp_info[1].h_samp_factor = 1; // U
cinfo.comp_info[1].v_samp_factor = 1;
cinfo.comp_info[2].h_samp_factor = 1; // V
cinfo.comp_info[2].v_samp_factor = 1;
cinfo.raw_data_in = TRUE;
jpeg_set_quality(&cinfo, 50, TRUE);
jpeg_start_compress(&cinfo, TRUE);
JSAMPROW y[16], u[8], v[8];
JSAMPARRAY planes[3]{y, u, v};
for (int line = 0; line < cinfo.image_height; line += 16) {
for (int i = 0; i < 16; ++i) {
y[i] = y_plane + (line + i) * cinfo.image_width;
if (i % 2 == 0) {
int offset = (cinfo.image_width / 2) * ((i + line) / 2);
u[i / 2] = u_plane + offset;
v[i / 2] = v_plane + offset;
}
}
jpeg_write_raw_data(&cinfo, planes, 16);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
kj::Array<capnp::byte> dat = kj::heapArray<capnp::byte>(thumbnail_buffer, thumbnail_len);
free(thumbnail_buffer);
return dat;
}
void publish_thumbnail(PubMaster *pm, const CameraBuf *b) {
auto thumbnail = yuv420_to_jpeg(b, b->out_img_width / 4, b->out_img_height / 4);
if (thumbnail.size() == 0) return;
MessageBuilder msg;
auto thumbnaild = msg.initEvent().initThumbnail();
thumbnaild.setFrameId(b->cur_frame_data.frame_id);
thumbnaild.setTimestampEof(b->cur_frame_data.timestamp_eof);
thumbnaild.setThumbnail(thumbnail);
pm->send("thumbnail", msg);
}
float set_exposure_target(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_skip) { float set_exposure_target(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_skip) {
int lum_med; int lum_med;
uint32_t lum_binning[256] = {0}; uint32_t lum_binning[256] = {0};
-1
View File
@@ -52,5 +52,4 @@ public:
void camerad_thread(); void camerad_thread();
kj::Array<uint8_t> get_raw_frame_image(const CameraBuf *b); kj::Array<uint8_t> get_raw_frame_image(const CameraBuf *b);
float set_exposure_target(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_skip); float set_exposure_target(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_skip);
void publish_thumbnail(PubMaster *pm, const CameraBuf *b);
int open_v4l_by_name_and_index(const char name[], int index = 0, int flags = O_RDWR | O_NONBLOCK); int open_v4l_by_name_and_index(const char name[], int index = 0, int flags = O_RDWR | O_NONBLOCK);
+3 -12
View File
@@ -55,7 +55,7 @@ public:
float fl_pix = 0; float fl_pix = 0;
CameraState(SpectraMaster *master, const CameraConfig &config) : camera(master, config, true /*config.stream_type == VISION_STREAM_ROAD*/) {}; CameraState(SpectraMaster *master, const CameraConfig &config) : camera(master, config, config.stream_type == VISION_STREAM_DRIVER ? ISP_BPS_PROCESSED : ISP_IFE_PROCESSED) {};
~CameraState(); ~CameraState();
void init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx); void init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx);
void update_exposure_score(float desired_ev, int exp_t, int exp_g_idx, float exp_gain); void update_exposure_score(float desired_ev, int exp_t, int exp_g_idx, float exp_gain);
@@ -231,9 +231,7 @@ void CameraState::set_camera_exposure(float grey_frac) {
void CameraState::run() { void CameraState::run() {
util::set_thread_name(camera.cc.publish_name); util::set_thread_name(camera.cc.publish_name);
std::vector<const char*> pubs = {camera.cc.publish_name}; PubMaster pm(std::vector{camera.cc.publish_name});
if (camera.cc.stream_type == VISION_STREAM_ROAD) pubs.push_back("thumbnail");
PubMaster pm(pubs);
for (uint32_t cnt = 0; !do_exit; ++cnt) { for (uint32_t cnt = 0; !do_exit; ++cnt) {
// Acquire the buffer; continue if acquisition fails // Acquire the buffer; continue if acquisition fails
@@ -263,17 +261,10 @@ void CameraState::run() {
framed.setImage(get_raw_frame_image(&camera.buf)); framed.setImage(get_raw_frame_image(&camera.buf));
} }
// Process camera registers and set camera exposure
if (camera.is_raw) {
camera.sensor->processRegisters((uint8_t *)camera.buf.cur_camera_buf->addr, framed);
}
set_camera_exposure(set_exposure_target(&camera.buf, ae_xywh, 2, camera.cc.stream_type != VISION_STREAM_DRIVER ? 2 : 4)); set_camera_exposure(set_exposure_target(&camera.buf, ae_xywh, 2, camera.cc.stream_type != VISION_STREAM_DRIVER ? 2 : 4));
// Send the message // Send the message
pm.send(camera.cc.publish_name, msg); pm.send(camera.cc.publish_name, msg);
if (camera.cc.stream_type == VISION_STREAM_ROAD && cnt % 100 == 3) {
publish_thumbnail(&pm, &camera.buf); // this takes 10ms???
}
} }
} }
@@ -292,7 +283,7 @@ void camerad_thread() {
// *** per-cam init *** // *** per-cam init ***
std::vector<std::unique_ptr<CameraState>> cams; std::vector<std::unique_ptr<CameraState>> cams;
for (const auto &config : {WIDE_ROAD_CAMERA_CONFIG, DRIVER_CAMERA_CONFIG, ROAD_CAMERA_CONFIG}) { for (const auto &config : {WIDE_ROAD_CAMERA_CONFIG, ROAD_CAMERA_CONFIG, DRIVER_CAMERA_CONFIG}) {
auto cam = std::make_unique<CameraState>(&m, config); auto cam = std::make_unique<CameraState>(&m, config);
cam->init(&v, device_id, ctx); cam->init(&v, device_id, ctx);
cams.emplace_back(std::move(cam)); cams.emplace_back(std::move(cam));
@@ -16,6 +16,7 @@ struct CameraConfig {
cereal::FrameData::Builder (cereal::Event::Builder::*init_camera_state)(); cereal::FrameData::Builder (cereal::Event::Builder::*init_camera_state)();
bool enabled; bool enabled;
uint32_t phy; uint32_t phy;
bool vignetting_correction;
}; };
// 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
@@ -28,6 +29,7 @@ const CameraConfig WIDE_ROAD_CAMERA_CONFIG = {
.init_camera_state = &cereal::Event::Builder::initWideRoadCameraState, .init_camera_state = &cereal::Event::Builder::initWideRoadCameraState,
.enabled = !getenv("DISABLE_WIDE_ROAD"), .enabled = !getenv("DISABLE_WIDE_ROAD"),
.phy = CAM_ISP_IFE_IN_RES_PHY_0, .phy = CAM_ISP_IFE_IN_RES_PHY_0,
.vignetting_correction = false,
}; };
const CameraConfig ROAD_CAMERA_CONFIG = { const CameraConfig ROAD_CAMERA_CONFIG = {
@@ -38,6 +40,7 @@ const CameraConfig ROAD_CAMERA_CONFIG = {
.init_camera_state = &cereal::Event::Builder::initRoadCameraState, .init_camera_state = &cereal::Event::Builder::initRoadCameraState,
.enabled = !getenv("DISABLE_ROAD"), .enabled = !getenv("DISABLE_ROAD"),
.phy = CAM_ISP_IFE_IN_RES_PHY_1, .phy = CAM_ISP_IFE_IN_RES_PHY_1,
.vignetting_correction = true,
}; };
const CameraConfig DRIVER_CAMERA_CONFIG = { const CameraConfig DRIVER_CAMERA_CONFIG = {
@@ -48,4 +51,5 @@ const CameraConfig DRIVER_CAMERA_CONFIG = {
.init_camera_state = &cereal::Event::Builder::initDriverCameraState, .init_camera_state = &cereal::Event::Builder::initDriverCameraState,
.enabled = !getenv("DISABLE_DRIVER"), .enabled = !getenv("DISABLE_DRIVER"),
.phy = CAM_ISP_IFE_IN_RES_PHY_2, .phy = CAM_ISP_IFE_IN_RES_PHY_2,
.vignetting_correction = false,
}; };
+57 -53
View File
@@ -2,13 +2,46 @@
#include "cdm.h" #include "cdm.h"
#include "system/camerad/cameras/tici.h" #include "system/camerad/cameras/hw.h"
#include "system/camerad/sensors/sensor.h" #include "system/camerad/sensors/sensor.h"
int build_common_ife_bps(uint8_t *dst, const CameraConfig cam, const SensorInfo *s, std::vector<uint32_t> &patches, bool ife) {
int build_update(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t> &patches, int camera_num) {
uint8_t *start = dst; uint8_t *start = dst;
/*
Common between IFE and BPS.
*/
// IFE -> BPS addresses
/*
std::map<uint32_t, uint32_t> addrs = {
{0xf30, 0x3468},
};
*/
// YUV
dst += write_cont(dst, ife ? 0xf30 : 0x3468, {
0x00680208,
0x00000108,
0x00400000,
0x03ff0000,
0x01c01ed8,
0x00001f68,
0x02000000,
0x03ff0000,
0x1fb81e88,
0x000001c0,
0x02000000,
0x03ff0000,
});
return dst - start;
}
int build_update(uint8_t *dst, const CameraConfig cam, const SensorInfo *s, std::vector<uint32_t> &patches) {
uint8_t *start = dst;
// init sequence
dst += write_random(dst, { dst += write_random(dst, {
0x2c, 0xffffffff, 0x2c, 0xffffffff,
0x30, 0xffffffff, 0x30, 0xffffffff,
@@ -17,6 +50,7 @@ int build_update(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t> &patch
0x3c, 0xffffffff, 0x3c, 0xffffffff,
}); });
// demux cfg
dst += write_cont(dst, 0x560, { dst += write_cont(dst, 0x560, {
0x00000001, 0x00000001,
0x04440444, 0x04440444,
@@ -35,36 +69,29 @@ int build_update(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t> &patch
0x00000000, 0x00000000,
}); });
// module config/enables (e.g. enable debayer, white balance, etc.)
dst += write_cont(dst, 0x40, { dst += write_cont(dst, 0x40, {
0x00000c06 | ((uint32_t)(camera_num == 1) << 8), 0x00000c06 | ((uint32_t)(cam.vignetting_correction) << 8),
}); });
dst += write_cont(dst, 0x48, {
(1 << 3) | (1 << 1),
});
dst += write_cont(dst, 0x4c, {
0x00000019,
});
dst += write_cont(dst, 0xe0c, {
0x00000e00,
});
dst += write_cont(dst, 0xe2c, {
0x00000e00,
});
dst += write_cont(dst, 0x44, { dst += write_cont(dst, 0x44, {
0x00000000, 0x00000000,
}); });
dst += write_cont(dst, 0x48, {
dst += write_cont(dst, 0xaac, { (1 << 3) | (1 << 1),
});
dst += write_cont(dst, 0x4c, {
0x00000019,
});
dst += write_cont(dst, 0xf00, {
0x00000000, 0x00000000,
}); });
dst += write_cont(dst, 0xf00, { // cropping
0x00000000, dst += write_cont(dst, 0xe0c, {
0x00000e00,
});
dst += write_cont(dst, 0xe2c, {
0x00000e00,
}); });
// black level scale + offset // black level scale + offset
@@ -78,11 +105,11 @@ int build_update(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t> &patch
} }
int build_initial_config(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t> &patches, int camera_num) { int build_initial_config(uint8_t *dst, const CameraConfig cam, const SensorInfo *s, std::vector<uint32_t> &patches) {
uint8_t *start = dst; uint8_t *start = dst;
// start with the every frame config // start with the every frame config
dst += build_update(dst, s, patches, camera_num); dst += build_update(dst, cam, s, patches);
uint64_t addr; uint64_t addr;
@@ -115,15 +142,6 @@ int build_initial_config(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t
// TODO: this is DMI64 in the dump, does that matter? // TODO: this is DMI64 in the dump, does that matter?
dst += write_dmi(dst, &addr, s->linearization_lut.size()*sizeof(uint32_t), 0xc24, 9); dst += write_dmi(dst, &addr, s->linearization_lut.size()*sizeof(uint32_t), 0xc24, 9);
patches.push_back(addr - (uint64_t)start); patches.push_back(addr - (uint64_t)start);
/* TODO
cdm_dmi_cmd_t 248
.length = 287
.reserved = 33
.cmd = 11
.addr = 0
.DMIAddr = 3108
.DMISel = 9
*/
// vignetting correction // vignetting correction
dst += write_cont(dst, 0x6bc, { dst += write_cont(dst, 0x6bc, {
@@ -164,23 +182,7 @@ int build_initial_config(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t
dst += write_dmi(dst, &addr, s->gamma_lut_rgb.size()*sizeof(uint32_t), 0xc24, 30); // R dst += write_dmi(dst, &addr, s->gamma_lut_rgb.size()*sizeof(uint32_t), 0xc24, 30); // R
patches.push_back(addr - (uint64_t)start); patches.push_back(addr - (uint64_t)start);
// YUV // output size/scaling
dst += write_cont(dst, 0xf30, {
0x00680208,
0x00000108,
0x00400000,
0x03ff0000,
0x01c01ed8,
0x00001f68,
0x02000000,
0x03ff0000,
0x1fb81e88,
0x000001c0,
0x02000000,
0x03ff0000,
});
// TODO: remove this
dst += write_cont(dst, 0xa3c, { dst += write_cont(dst, 0xa3c, {
0x00000003, 0x00000003,
((s->frame_width - 1) << 16) | (s->frame_width - 1), ((s->frame_width - 1) << 16) | (s->frame_width - 1),
@@ -226,6 +228,8 @@ int build_initial_config(uint8_t *dst, const SensorInfo *s, std::vector<uint32_t
0x00000017, 0x00000017,
}); });
dst += build_common_ife_bps(dst, cam, s, patches, true);
return dst - start; return dst - start;
} }
+377 -75
View File
@@ -17,10 +17,9 @@
#include "common/swaglog.h" #include "common/swaglog.h"
#include "system/camerad/cameras/ife.h" #include "system/camerad/cameras/ife.h"
#include "system/camerad/cameras/spectra.h" #include "system/camerad/cameras/spectra.h"
#include "system/camerad/cameras/bps_blobs.h"
#include "third_party/linux/include/msm_media_info.h" #include "third_party/linux/include/msm_media_info.h"
// For debugging:
// echo "4294967295" > /sys/module/cam_debug_util/parameters/debug_mdl
// ************** low level camera helpers **************** // ************** low level camera helpers ****************
@@ -194,11 +193,11 @@ void SpectraMaster::init() {
// looks like there's only one of these // looks like there's only one of these
isp_fd = open_v4l_by_name_and_index("cam-isp"); isp_fd = open_v4l_by_name_and_index("cam-isp");
assert(isp_fd >= 0); assert(isp_fd >= 0);
LOGD("opened isp"); LOGD("opened isp %d", (int)isp_fd);
icp_fd = open_v4l_by_name_and_index("cam-icp"); icp_fd = open_v4l_by_name_and_index("cam-icp");
assert(icp_fd >= 0); assert(icp_fd >= 0);
LOGD("opened icp"); LOGD("opened icp %d", (int)icp_fd);
// query ISP for MMU handles // query ISP for MMU handles
LOG("-- Query for MMU handles"); LOG("-- Query for MMU handles");
@@ -234,14 +233,14 @@ void SpectraMaster::init() {
// *** SpectraCamera *** // *** SpectraCamera ***
SpectraCamera::SpectraCamera(SpectraMaster *master, const CameraConfig &config, bool raw) SpectraCamera::SpectraCamera(SpectraMaster *master, const CameraConfig &config, SpectraOutputType out)
: m(master), : m(master),
enabled(config.enabled), enabled(config.enabled),
cc(config), cc(config),
is_raw(raw) { output_type(out) {
mm.init(m->video0_fd); mm.init(m->video0_fd);
ife_buf_depth = is_raw ? 4 : VIPC_BUFFER_COUNT; ife_buf_depth = (out != ISP_IFE_PROCESSED) ? 4 : VIPC_BUFFER_COUNT;
assert(ife_buf_depth < MAX_IFE_BUFS); assert(ife_buf_depth < MAX_IFE_BUFS);
} }
@@ -257,11 +256,22 @@ int SpectraCamera::clear_req_queue() {
req_mgr_flush_request.link_hdl = link_handle; req_mgr_flush_request.link_hdl = link_handle;
req_mgr_flush_request.flush_type = CAM_REQ_MGR_FLUSH_TYPE_ALL; req_mgr_flush_request.flush_type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_FLUSH_REQ, &req_mgr_flush_request, sizeof(req_mgr_flush_request)); int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_FLUSH_REQ, &req_mgr_flush_request, sizeof(req_mgr_flush_request));
// LOGD("flushed all req: %d", ret); LOGD("flushed all req: %d", ret);
if (icp_dev_handle) {
struct cam_flush_dev_cmd cmd = {
.session_handle = session_handle,
.dev_handle = icp_dev_handle,
.flush_type = CAM_FLUSH_TYPE_ALL,
};
int err = do_cam_control(m->icp_fd, CAM_FLUSH_REQ, &cmd, sizeof(cmd));
assert(err == 0);
}
for (int i = 0; i < MAX_IFE_BUFS; ++i) { for (int i = 0; i < MAX_IFE_BUFS; ++i) {
destroySyncObjectAt(i); destroySyncObjectAt(i);
} }
return ret; return ret;
} }
@@ -279,7 +289,7 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c
uv_height = VENUS_UV_SCANLINES(COLOR_FMT_NV12, sensor->frame_height); uv_height = VENUS_UV_SCANLINES(COLOR_FMT_NV12, sensor->frame_height);
uv_offset = stride*y_height; uv_offset = stride*y_height;
yuv_size = uv_offset + stride*uv_height; yuv_size = uv_offset + stride*uv_height;
if (!is_raw) { if (output_type != ISP_RAW_OUTPUT) {
uv_offset = ALIGNED_SIZE(uv_offset, 0x1000); uv_offset = ALIGNED_SIZE(uv_offset, 0x1000);
yuv_size = uv_offset + ALIGNED_SIZE(stride*uv_height, 0x1000); yuv_size = uv_offset + ALIGNED_SIZE(stride*uv_height, 0x1000);
} }
@@ -288,7 +298,7 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c
open = true; open = true;
configISP(); configISP();
//configICP(); // needs the new AGNOS kernel if (output_type == ISP_BPS_PROCESSED) configICP();
configCSIPHY(); configCSIPHY();
linkDevices(); linkDevices();
@@ -300,8 +310,9 @@ void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_c
void SpectraCamera::enqueue_req_multi(uint64_t start, int n, bool dp) { void SpectraCamera::enqueue_req_multi(uint64_t start, int n, bool dp) {
for (uint64_t i = start; i < start + n; ++i) { for (uint64_t i = start; i < start + n; ++i) {
request_ids[(i - 1) % ife_buf_depth] = i; uint64_t idx = (i - 1) % ife_buf_depth;
enqueue_buffer((i - 1) % ife_buf_depth, dp); request_ids[idx] = i;
enqueue_buffer(idx, dp);
} }
} }
@@ -454,22 +465,245 @@ int SpectraCamera::sensors_init() {
return ret; return ret;
} }
void add_patch(struct cam_packet *pkt, int32_t dst_hdl, uint32_t dst_offset, int32_t src_hdl, uint32_t src_offset) {
void *ptr = (char*)&pkt->payload + pkt->patch_offset;
struct cam_patch_desc *p = (struct cam_patch_desc *)((unsigned char*)ptr + sizeof(struct cam_patch_desc)*pkt->num_patches);
p->dst_buf_hdl = dst_hdl;
p->src_buf_hdl = src_hdl;
p->dst_offset = dst_offset;
p->src_offset = src_offset;
pkt->num_patches++;
};
void SpectraCamera::config_bps(int idx, int request_id) { void SpectraCamera::config_bps(int idx, int request_id) {
/* /*
Handles per-frame BPS config. Handles per-frame BPS config.
* BPS = Bayer Processing Segment * BPS = Bayer Processing Segment
*/ */
(void)idx;
(void)request_id;
}
void add_patch(void *ptr, int n, int32_t dst_hdl, uint32_t dst_offset, int32_t src_hdl, uint32_t src_offset) { int size = sizeof(struct cam_packet) + sizeof(struct cam_cmd_buf_desc)*2 + sizeof(struct cam_buf_io_cfg)*2;
struct cam_patch_desc *p = (struct cam_patch_desc *)((unsigned char*)ptr + sizeof(struct cam_patch_desc)*n); size += sizeof(struct cam_patch_desc)*9;
p->dst_buf_hdl = dst_hdl;
p->src_buf_hdl = src_hdl; uint32_t cam_packet_handle = 0;
p->dst_offset = dst_offset; auto pkt = mm.alloc<struct cam_packet>(size, &cam_packet_handle);
p->src_offset = src_offset;
}; pkt->header.op_code = CSLDeviceTypeBPS | CAM_ICP_OPCODE_BPS_UPDATE;
pkt->header.request_id = request_id;
pkt->header.size = size;
typedef struct {
struct {
uint32_t ptr[2];
uint32_t unknown[2];
} frames[9];
uint32_t unknown1;
uint32_t unknown2;
uint32_t unknown3;
uint32_t unknown4;
uint32_t cdm_addr;
uint32_t cdm_size;
uint32_t settings_addr;
uint32_t striping_addr;
uint32_t cdm_addr2;
uint32_t req_id;
uint64_t handle;
} bps_tmp;
typedef struct {
uint32_t a;
uint32_t n;
unsigned base : 32;
unsigned unused : 12;
unsigned length : 20;
uint32_t p;
uint32_t u;
uint32_t h;
uint32_t b;
} cdm_tmp;
// *** cmd buf ***
std::vector<uint32_t> patches;
struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload;
{
pkt->num_cmd_buf = 2;
pkt->kmd_cmd_buf_index = -1;
pkt->kmd_cmd_buf_offset = 0;
buf_desc[0].meta_data = 0;
buf_desc[0].mem_handle = bps_cmd.handle;
buf_desc[0].type = CAM_CMD_BUF_FW;
buf_desc[0].offset = bps_cmd.aligned_size()*idx;
buf_desc[0].length = sizeof(bps_tmp) + sizeof(cdm_tmp);
buf_desc[0].size = buf_desc[0].length;
// rest gets patched in
bps_tmp *fp = (bps_tmp *)((unsigned char *)bps_cmd.ptr + buf_desc[0].offset);
memset(fp, 0, buf_desc[0].length);
fp->handle = (uint64_t)icp_dev_handle;
fp->cdm_size = bps_cdm_striping_bl.size; // this comes from the striping lib create call
fp->req_id = 0; // why always 0?
cdm_tmp *pa = (cdm_tmp *)((unsigned char *)fp + sizeof(bps_tmp));
pa->a = 0;
pa->n = 1;
pa->p = 20; // GENERIC
pa->u = 0;
pa->h = 0;
pa->b = 0;
pa->unused = 0;
pa->base = 0; // this gets patched
int cdm_len = 0;
if (bps_lin_reg.size() == 0) {
for (int i = 0; i < 4; i++) {
bps_lin_reg.push_back(((sensor->linearization_pts[i] & 0xffff) << 0x10) | (sensor->linearization_pts[i] >> 0x10));
}
}
if (bps_ccm_reg.size() == 0) {
for (int i = 0; i < 3; i++) {
bps_ccm_reg.push_back(sensor->color_correct_matrix[i] | (sensor->color_correct_matrix[i+3] << 0x10));
bps_ccm_reg.push_back(sensor->color_correct_matrix[i+6]);
}
}
// white balance
cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x2868, {
0x04000400,
0x00000400,
0x00000000,
0x00000000,
});
// debayer
cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x2878, {
0x00000080,
0x00800066,
});
// linearization, EN=0
cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1868, bps_lin_reg);
cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1878, bps_lin_reg);
cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1888, bps_lin_reg);
cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1898, bps_lin_reg);
/*
uint8_t *start = (unsigned char *)bps_cdm_program_array.ptr + cdm_len;
uint64_t addr;
cdm_len += write_dmi((unsigned char *)bps_cdm_program_array.ptr + cdm_len, &addr, sensor->linearization_lut.size()*sizeof(uint32_t), 0x1808, 1);
patches.push_back(addr - (uint64_t)start);
*/
// color correction
cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x2e68, bps_ccm_reg);
cdm_len += build_common_ife_bps((unsigned char *)bps_cdm_program_array.ptr + cdm_len, cc, sensor.get(), patches, false);
pa->length = cdm_len - 1;
// *** second command ***
// parsed by cam_icp_packet_generic_blob_handler
struct isp_packet {
uint32_t header;
struct cam_icp_clk_bw_request clk;
} __attribute__((packed)) tmp;
tmp.header = CAM_ICP_CMD_GENERIC_BLOB_CLK;
tmp.header |= (sizeof(cam_icp_clk_bw_request)) << 8;
tmp.clk.budget_ns = 0x1fca058;
tmp.clk.frame_cycles = 2329024; // comes from the striping lib
tmp.clk.rt_flag = 0x0;
tmp.clk.uncompressed_bw = 0x38512180;
tmp.clk.compressed_bw = 0x38512180;
buf_desc[1].size = sizeof(tmp);
buf_desc[1].offset = 0;
buf_desc[1].length = buf_desc[1].size - buf_desc[1].offset;
buf_desc[1].type = CAM_CMD_BUF_GENERIC;
buf_desc[1].meta_data = CAM_ICP_CMD_META_GENERIC_BLOB;
auto buf2 = mm.alloc<uint32_t>(buf_desc[1].size, (uint32_t*)&buf_desc[1].mem_handle);
memcpy(buf2.get(), &tmp, sizeof(tmp));
}
// *** io config ***
pkt->num_io_configs = 2;
pkt->io_configs_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf;
struct cam_buf_io_cfg *io_cfg = (struct cam_buf_io_cfg *)((char*)&pkt->payload + pkt->io_configs_offset);
{
// input frame
io_cfg[0].offsets[0] = 0;
io_cfg[0].mem_handle[0] = buf_handle_raw[idx];
io_cfg[0].planes[0] = (struct cam_plane_cfg){
.width = sensor->frame_width,
.height = sensor->frame_height + sensor->extra_height,
.plane_stride = sensor->frame_stride,
.slice_height = sensor->frame_height + sensor->extra_height,
};
io_cfg[0].format = sensor->mipi_format;
io_cfg[0].color_space = CAM_COLOR_SPACE_BASE;
io_cfg[0].color_pattern = 0x5;
io_cfg[0].bpp = (sensor->mipi_format == CAM_FORMAT_MIPI_RAW_10 ? 0xa : 0xc);
io_cfg[0].resource_type = CAM_ICP_BPS_INPUT_IMAGE;
io_cfg[0].fence = sync_objs_ife[idx];
io_cfg[0].direction = CAM_BUF_INPUT;
io_cfg[0].subsample_pattern = 0x1;
io_cfg[0].framedrop_pattern = 0x1;
// output frame
io_cfg[1].mem_handle[0] = buf_handle_yuv[idx];
io_cfg[1].mem_handle[1] = buf_handle_yuv[idx];
io_cfg[1].planes[0] = (struct cam_plane_cfg){
.width = sensor->frame_width,
.height = sensor->frame_height,
.plane_stride = stride,
.slice_height = y_height,
};
io_cfg[1].planes[1] = (struct cam_plane_cfg){
.width = sensor->frame_width,
.height = sensor->frame_height/2,
.plane_stride = stride,
.slice_height = uv_height,
};
io_cfg[1].offsets[1] = ALIGNED_SIZE(io_cfg[1].planes[0].plane_stride*io_cfg[1].planes[0].slice_height, 0x1000);
assert(io_cfg[1].offsets[1] == uv_offset);
io_cfg[1].format = CAM_FORMAT_NV12; // TODO: why is this 21 in the dump? should be 12
io_cfg[1].color_space = CAM_COLOR_SPACE_BT601_FULL;
io_cfg[1].resource_type = CAM_ICP_BPS_OUTPUT_IMAGE_FULL;
io_cfg[1].fence = sync_objs_bps[idx];
io_cfg[1].direction = CAM_BUF_OUTPUT;
io_cfg[1].subsample_pattern = 0x1;
io_cfg[1].framedrop_pattern = 0x1;
}
// *** patches ***
{
assert(patches.size() == 0 | patches.size() == 1);
pkt->patch_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf + sizeof(struct cam_buf_io_cfg)*pkt->num_io_configs;
if (patches.size() > 0) {
add_patch(pkt.get(), bps_cmd.handle, patches[0], bps_linearization_lut.handle, 0);
}
// input frame
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, frames[0].ptr[0]), buf_handle_raw[idx], 0);
// output frame
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, frames[1].ptr[0]), buf_handle_yuv[idx], 0);
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, frames[1].ptr[1]), buf_handle_yuv[idx], io_cfg[1].offsets[1]);
// rest of buffers
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, settings_addr), bps_iq.handle, 0);
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, cdm_addr2), bps_cmd.handle, sizeof(bps_tmp));
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + 0xc8, bps_cdm_program_array.handle, 0);
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, striping_addr), bps_striping.handle, 0);
add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, cdm_addr), bps_cdm_striping_bl.handle, 0);
}
int ret = device_config(m->icp_fd, session_handle, icp_dev_handle, cam_packet_handle);
assert(ret == 0);
}
void SpectraCamera::config_ife(int idx, int request_id, bool init) { void SpectraCamera::config_ife(int idx, int request_id, bool init) {
/* /*
@@ -509,11 +743,12 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
buf_desc[0].offset = ife_cmd.aligned_size()*idx; buf_desc[0].offset = ife_cmd.aligned_size()*idx;
// stream of IFE register writes // stream of IFE register writes
bool is_raw = output_type != ISP_IFE_PROCESSED;
if (!is_raw) { if (!is_raw) {
if (init) { if (init) {
buf_desc[0].length = build_initial_config((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, sensor.get(), patches, cc.camera_num); buf_desc[0].length = build_initial_config((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, cc, sensor.get(), patches);
} else { } else {
buf_desc[0].length = build_update((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, sensor.get(), patches, cc.camera_num); buf_desc[0].length = build_update((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, cc, sensor.get(), patches);
} }
} }
@@ -597,8 +832,7 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
pkt->io_configs_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf; pkt->io_configs_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf;
struct cam_buf_io_cfg *io_cfg = (struct cam_buf_io_cfg *)((char*)&pkt->payload + pkt->io_configs_offset); struct cam_buf_io_cfg *io_cfg = (struct cam_buf_io_cfg *)((char*)&pkt->payload + pkt->io_configs_offset);
if (output_type != ISP_IFE_PROCESSED) {
if (is_raw) {
io_cfg[0].mem_handle[0] = buf_handle_raw[idx]; io_cfg[0].mem_handle[0] = buf_handle_raw[idx];
io_cfg[0].planes[0] = (struct cam_plane_cfg){ io_cfg[0].planes[0] = (struct cam_plane_cfg){
.width = sensor->frame_width, .width = sensor->frame_width,
@@ -611,7 +845,7 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
io_cfg[0].color_pattern = 0x5; io_cfg[0].color_pattern = 0x5;
io_cfg[0].bpp = (sensor->mipi_format == CAM_FORMAT_MIPI_RAW_10 ? 0xa : 0xc); io_cfg[0].bpp = (sensor->mipi_format == CAM_FORMAT_MIPI_RAW_10 ? 0xa : 0xc);
io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_RDI_0; io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_RDI_0;
io_cfg[0].fence = sync_objs[idx]; io_cfg[0].fence = sync_objs_ife[idx];
io_cfg[0].direction = CAM_BUF_OUTPUT; io_cfg[0].direction = CAM_BUF_OUTPUT;
io_cfg[0].subsample_pattern = 0x1; io_cfg[0].subsample_pattern = 0x1;
io_cfg[0].framedrop_pattern = 0x1; io_cfg[0].framedrop_pattern = 0x1;
@@ -636,7 +870,7 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
io_cfg[0].color_pattern = 0x0; io_cfg[0].color_pattern = 0x0;
io_cfg[0].bpp = 0; io_cfg[0].bpp = 0;
io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_FULL; io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_FULL;
io_cfg[0].fence = sync_objs[idx]; io_cfg[0].fence = sync_objs_ife[idx];
io_cfg[0].direction = CAM_BUF_OUTPUT; io_cfg[0].direction = CAM_BUF_OUTPUT;
io_cfg[0].subsample_pattern = 0x1; io_cfg[0].subsample_pattern = 0x1;
io_cfg[0].framedrop_pattern = 0x1; io_cfg[0].framedrop_pattern = 0x1;
@@ -649,21 +883,18 @@ void SpectraCamera::config_ife(int idx, int request_id, bool init) {
// order here corresponds to the one in build_initial_config // order here corresponds to the one in build_initial_config
assert(patches.size() == 6 || patches.size() == 0); assert(patches.size() == 6 || patches.size() == 0);
pkt->num_patches = patches.size();
pkt->patch_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf + sizeof(struct cam_buf_io_cfg)*pkt->num_io_configs; pkt->patch_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf + sizeof(struct cam_buf_io_cfg)*pkt->num_io_configs;
if (pkt->num_patches > 0) { if (patches.size() > 0) {
void *p = (char*)&pkt->payload + pkt->patch_offset;
// linearization LUT // linearization LUT
add_patch(p, 0, ife_cmd.handle, patches[0], ife_linearization_lut.handle, 0); add_patch(pkt.get(), ife_cmd.handle, patches[0], ife_linearization_lut.handle, 0);
// vignetting correction LUTs // vignetting correction LUTs
add_patch(p, 1, ife_cmd.handle, patches[1], ife_vignetting_lut.handle, 0); add_patch(pkt.get(), ife_cmd.handle, patches[1], ife_vignetting_lut.handle, 0);
add_patch(p, 2, ife_cmd.handle, patches[2], ife_vignetting_lut.handle, ife_vignetting_lut.size); add_patch(pkt.get(), ife_cmd.handle, patches[2], ife_vignetting_lut.handle, ife_vignetting_lut.size);
// gamma LUTs // gamma LUTs
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
add_patch(p, i+3, ife_cmd.handle, patches[i+3], ife_gamma_lut.handle, ife_gamma_lut.size*i); add_patch(pkt.get(), ife_cmd.handle, patches[i+3], ife_gamma_lut.handle, ife_gamma_lut.size*i);
} }
} }
} }
@@ -676,23 +907,46 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
int ret; int ret;
uint64_t request_id = request_ids[i]; uint64_t request_id = request_ids[i];
if (sync_objs[i]) { // Before queuing up a new frame, wait for the
// SOF has come in, wait until readout is complete // previous one in this slot (index) to come in.
if (sync_objs_ife[i]) {
// TODO: write a test to stress test w/ a low timeout and check camera frame ids match
struct cam_sync_wait sync_wait = {0}; struct cam_sync_wait sync_wait = {0};
sync_wait.sync_obj = sync_objs[i];
// *** Wait for IFE ***
// in RAW_OUTPUT mode, this is just the frame readout from the sensor
// in IFE_PROCESSED mode, this is both frame readout and image processing (~1ms)
sync_wait.sync_obj = sync_objs_ife[i];
sync_wait.timeout_ms = 100; sync_wait.timeout_ms = 100;
ret = do_sync_control(m->cam_sync_fd, CAM_SYNC_WAIT, &sync_wait, sizeof(sync_wait)); ret = do_sync_control(m->cam_sync_fd, CAM_SYNC_WAIT, &sync_wait, sizeof(sync_wait));
if (ret != 0) { if (ret != 0) {
// TODO: handle frame drop cleanly LOGE("failed to wait for IFE sync: %d %d", ret, sync_wait.sync_obj);
// when this happens, it messes up future frames
LOGE("failed to wait for sync: %d %d", ret, sync_wait.sync_obj);
} }
buf.frame_metadata[i].timestamp_end_of_isp = (uint64_t)nanos_since_boot();
// *** Wait for BPS ***
if (ret == 0 && sync_objs_bps[i]) {
sync_wait.sync_obj = sync_objs_bps[i];
sync_wait.timeout_ms = 50; // typically 7ms
ret = do_sync_control(m->cam_sync_fd, CAM_SYNC_WAIT, &sync_wait, sizeof(sync_wait));
if (ret != 0) {
LOGE("failed to wait for BPS sync: %d %d", ret, sync_wait.sync_obj);
}
}
// in IFE_PROCESSED mode, we can't know the true EOF, so recover it with sensor readout time
buf.frame_metadata[i].timestamp_eof = buf.frame_metadata[i].timestamp_sof + sensor->readout_time_ns; buf.frame_metadata[i].timestamp_eof = buf.frame_metadata[i].timestamp_sof + sensor->readout_time_ns;
if (dp) { buf.frame_metadata[i].timestamp_end_of_isp = (uint64_t)nanos_since_boot();
// all good, hand off frame
if (dp && ret == 0) {
buf.queue(i); buf.queue(i);
} }
if (ret != 0) {
clear_req_queue();
}
destroySyncObjectAt(i); destroySyncObjectAt(i);
} }
@@ -703,14 +957,14 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
if (ret != 0) { if (ret != 0) {
LOGE("failed to create fence: %d %d", ret, sync_create.sync_obj); LOGE("failed to create fence: %d %d", ret, sync_create.sync_obj);
} }
sync_objs[i] = sync_create.sync_obj; sync_objs_ife[i] = sync_create.sync_obj;
if (icp_dev_handle > 0) { if (icp_dev_handle > 0) {
ret = do_cam_control(m->cam_sync_fd, CAM_SYNC_CREATE, &sync_create, sizeof(sync_create)); ret = do_cam_control(m->cam_sync_fd, CAM_SYNC_CREATE, &sync_create, sizeof(sync_create));
if (ret != 0) { if (ret != 0) {
LOGE("failed to create fence: %d %d", ret, sync_create.sync_obj); LOGE("failed to create fence: %d %d", ret, sync_create.sync_obj);
} }
sync_objs_bps_out[i] = sync_create.sync_obj; sync_objs_bps[i] = sync_create.sync_obj;
} }
// schedule request with camera request manager // schedule request with camera request manager
@@ -728,7 +982,7 @@ void SpectraCamera::enqueue_buffer(int i, bool dp) {
// submit request to IFE and BPS // submit request to IFE and BPS
config_ife(i, request_id); config_ife(i, request_id);
config_bps(i, request_id); if (output_type == ISP_BPS_PROCESSED) config_bps(i, request_id);
} }
void SpectraCamera::destroySyncObjectAt(int index) { void SpectraCamera::destroySyncObjectAt(int index) {
@@ -744,14 +998,14 @@ void SpectraCamera::destroySyncObjectAt(int index) {
sync_obj = 0; // Reset the sync object to 0 sync_obj = 0; // Reset the sync object to 0
}; };
destroy_sync_obj(m->cam_sync_fd, sync_objs[index]); destroy_sync_obj(m->cam_sync_fd, sync_objs_ife[index]);
destroy_sync_obj(m->cam_sync_fd, sync_objs_bps_out[index]); destroy_sync_obj(m->cam_sync_fd, sync_objs_bps[index]);
} }
void SpectraCamera::camera_map_bufs() { void SpectraCamera::camera_map_bufs() {
int ret; int ret;
for (int i = 0; i < ife_buf_depth; i++) { for (int i = 0; i < ife_buf_depth; i++) {
// configure ISP to put the image in place // map our VisionIPC bufs into ISP memory
struct cam_mem_mgr_map_cmd mem_mgr_map_cmd = {0}; struct cam_mem_mgr_map_cmd mem_mgr_map_cmd = {0};
mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE; mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE;
mem_mgr_map_cmd.mmu_hdls[0] = m->device_iommu; mem_mgr_map_cmd.mmu_hdls[0] = m->device_iommu;
@@ -761,14 +1015,16 @@ void SpectraCamera::camera_map_bufs() {
mem_mgr_map_cmd.mmu_hdls[1] = m->icp_device_iommu; mem_mgr_map_cmd.mmu_hdls[1] = m->icp_device_iommu;
} }
if (is_raw) { if (output_type != ISP_IFE_PROCESSED) {
// RAW bayer images // RAW bayer images
mem_mgr_map_cmd.fd = buf.camera_bufs_raw[i].fd; mem_mgr_map_cmd.fd = buf.camera_bufs_raw[i].fd;
ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd)); ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd));
assert(ret == 0); assert(ret == 0);
LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs_raw[i].fd, mem_mgr_map_cmd.out.buf_handle, ret); LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs_raw[i].fd, mem_mgr_map_cmd.out.buf_handle, ret);
buf_handle_raw[i] = mem_mgr_map_cmd.out.buf_handle; buf_handle_raw[i] = mem_mgr_map_cmd.out.buf_handle;
} else { }
if (output_type != ISP_RAW_OUTPUT) {
// final processed images // final processed images
VisionBuf *vb = buf.vipc_server->get_buffer(buf.stream_type, i); VisionBuf *vb = buf.vipc_server->get_buffer(buf.stream_type, i);
mem_mgr_map_cmd.fd = vb->fd; mem_mgr_map_cmd.fd = vb->fd;
@@ -865,7 +1121,7 @@ void SpectraCamera::configISP() {
}, },
}; };
if (is_raw) { if (output_type != ISP_IFE_PROCESSED) {
in_port_info.line_start = 0; in_port_info.line_start = 0;
in_port_info.line_stop = sensor->frame_height + sensor->extra_height - 1; in_port_info.line_stop = sensor->frame_height + sensor->extra_height - 1;
in_port_info.height = sensor->frame_height + sensor->extra_height; in_port_info.height = sensor->frame_height + sensor->extra_height;
@@ -890,7 +1146,7 @@ void SpectraCamera::configISP() {
ife_cmd.init(m, 67984, 0x20, ife_cmd.init(m, 67984, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE,
m->device_iommu, m->cdm_iommu, ife_buf_depth); m->device_iommu, m->cdm_iommu, ife_buf_depth);
if (!is_raw) { if (output_type == ISP_IFE_PROCESSED) {
assert(sensor->gamma_lut_rgb.size() == 64); assert(sensor->gamma_lut_rgb.size() == 64);
ife_gamma_lut.init(m, sensor->gamma_lut_rgb.size()*sizeof(uint32_t), 0x20, ife_gamma_lut.init(m, sensor->gamma_lut_rgb.size()*sizeof(uint32_t), 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE,
@@ -920,11 +1176,19 @@ void SpectraCamera::configICP() {
Configures both the ICP and BPS. Configures both the ICP and BPS.
*/ */
int cfg_handle;
uint32_t cfg_size = sizeof(bps_cfg[0]) / sizeof(bps_cfg[0][0]);
void *cfg = alloc_w_mmu_hdl(m->video0_fd, cfg_size, (uint32_t*)&cfg_handle, 0x1,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu);
memcpy(cfg, bps_cfg[sensor->num()], cfg_size);
struct cam_icp_acquire_dev_info icp_info = { struct cam_icp_acquire_dev_info icp_info = {
.scratch_mem_size = 0x0, .scratch_mem_size = 0x0,
.dev_type = 0x1, // BPS .dev_type = CAM_ICP_RES_TYPE_BPS,
.io_config_cmd_size = 0, .io_config_cmd_size = cfg_size,
.io_config_cmd_handle = 0, .io_config_cmd_handle = cfg_handle,
.secure_mode = 0, .secure_mode = 0,
.num_out_res = 1, .num_out_res = 1,
.in_res = (struct cam_icp_res_info){ .in_res = (struct cam_icp_res_info){
@@ -945,26 +1209,45 @@ void SpectraCamera::configICP() {
icp_dev_handle = *h; icp_dev_handle = *h;
LOGD("acquire icp dev"); LOGD("acquire icp dev");
// BPS CMD buffer release(m->video0_fd, cfg_handle);
unsigned char striping_out[] = "\x00";
bps_cmd.init(m, ife_buf_depth*ALIGNED_SIZE(464, 0x20), 0x20, // BPS has a lot of buffers to init
bps_cmd.init(m, 464, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu); m->icp_device_iommu, 0, ife_buf_depth);
bps_iq.init(m, 560, 0x20, // BPSIQSettings struct
uint32_t settings_size = sizeof(bps_settings[0]) / sizeof(bps_settings[0][0]);
bps_iq.init(m, settings_size, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu); m->icp_device_iommu);
bps_cdm_program_array.init(m, 0x40, 0x20, memcpy(bps_iq.ptr, bps_settings[sensor->num()], settings_size);
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu);
bps_striping.init(m, sizeof(striping_out), 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu);
memcpy(bps_striping.ptr, striping_out, sizeof(striping_out));
bps_cdm_striping_bl.init(m, 65216, 0x20, // for cdm register writes, just make it bigger than you need
bps_cdm_program_array.init(m, 0x1000, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu);
// striping lib output
uint32_t striping_size = sizeof(bps_striping_output[0]) / sizeof(bps_striping_output[0][0]);
bps_striping.init(m, striping_size, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu);
memcpy(bps_striping.ptr, bps_striping_output[sensor->num()], striping_size);
// used internally by the BPS, we just allocate it.
// size comes from the BPSStripingLib
bps_cdm_striping_bl.init(m, 0xa100, 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS, CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu); m->icp_device_iommu);
// LUTs
/*
bps_linearization_lut.init(m, sensor->linearization_lut.size()*sizeof(uint32_t), 0x20,
CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE | CAM_MEM_FLAG_HW_SHARED_ACCESS,
m->icp_device_iommu);
memcpy(bps_linearization_lut.ptr, sensor->linearization_lut.data(), bps_linearization_lut.size);
*/
} }
void SpectraCamera::configCSIPHY() { void SpectraCamera::configCSIPHY() {
@@ -1015,6 +1298,7 @@ void SpectraCamera::linkDevices() {
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;
int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_LINK, &req_mgr_link_info, sizeof(req_mgr_link_info)); int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_LINK, &req_mgr_link_info, sizeof(req_mgr_link_info));
assert(ret == 0);
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);
@@ -1028,9 +1312,15 @@ void SpectraCamera::linkDevices() {
ret = device_control(csiphy_fd, CAM_START_DEV, session_handle, csiphy_dev_handle); ret = device_control(csiphy_fd, CAM_START_DEV, session_handle, csiphy_dev_handle);
LOGD("start csiphy: %d", ret); LOGD("start csiphy: %d", ret);
assert(ret == 0);
ret = device_control(m->isp_fd, CAM_START_DEV, session_handle, isp_dev_handle); ret = device_control(m->isp_fd, CAM_START_DEV, session_handle, isp_dev_handle);
LOGD("start isp: %d", ret); LOGD("start isp: %d", ret);
assert(ret == 0); assert(ret == 0);
if (output_type == ISP_BPS_PROCESSED) {
ret = device_control(m->icp_fd, CAM_START_DEV, session_handle, icp_dev_handle);
LOGD("start icp: %d", ret);
assert(ret == 0);
}
} }
void SpectraCamera::camera_close() { void SpectraCamera::camera_close() {
@@ -1041,8 +1331,13 @@ void SpectraCamera::camera_close() {
// LOGD("stop sensor: %d", ret); // LOGD("stop sensor: %d", ret);
int ret = device_control(m->isp_fd, CAM_STOP_DEV, session_handle, isp_dev_handle); int ret = device_control(m->isp_fd, CAM_STOP_DEV, session_handle, isp_dev_handle);
LOGD("stop isp: %d", ret); LOGD("stop isp: %d", ret);
if (output_type == ISP_BPS_PROCESSED) {
ret = device_control(m->icp_fd, CAM_STOP_DEV, session_handle, icp_dev_handle);
LOGD("stop icp: %d", ret);
}
ret = device_control(csiphy_fd, CAM_STOP_DEV, session_handle, csiphy_dev_handle); ret = device_control(csiphy_fd, CAM_STOP_DEV, session_handle, csiphy_dev_handle);
LOGD("stop csiphy: %d", ret); LOGD("stop csiphy: %d", ret);
// link control stop // link control stop
LOG("-- Stop link control"); LOG("-- Stop link control");
struct cam_req_mgr_link_control req_mgr_link_control = {0}; struct cam_req_mgr_link_control req_mgr_link_control = {0};
@@ -1063,17 +1358,22 @@ void SpectraCamera::camera_close() {
// release devices // release devices
LOGD("-- Release devices"); LOGD("-- Release devices");
if (icp_dev_handle > 0) { ret = device_control(m->isp_fd, CAM_RELEASE_DEV, session_handle, isp_dev_handle);
LOGD("release isp: %d", ret);
if (output_type == ISP_BPS_PROCESSED) {
ret = device_control(m->icp_fd, CAM_RELEASE_DEV, session_handle, icp_dev_handle); ret = device_control(m->icp_fd, CAM_RELEASE_DEV, session_handle, icp_dev_handle);
LOGD("release icp: %d", ret); LOGD("release icp: %d", ret);
} }
ret = device_control(m->isp_fd, CAM_RELEASE_DEV, session_handle, isp_dev_handle);
LOGD("release isp: %d", ret);
ret = device_control(csiphy_fd, CAM_RELEASE_DEV, session_handle, csiphy_dev_handle); ret = device_control(csiphy_fd, CAM_RELEASE_DEV, session_handle, csiphy_dev_handle);
LOGD("release csiphy: %d", ret); LOGD("release csiphy: %d", ret);
for (int i = 0; i < ife_buf_depth; i++) { for (int i = 0; i < ife_buf_depth; i++) {
release(m->video0_fd, is_raw ? buf_handle_raw[i] : buf_handle_yuv[i]); if (buf_handle_raw[i]) {
release(m->video0_fd, buf_handle_raw[i]);
}
if (buf_handle_yuv[i]) {
release(m->video0_fd, buf_handle_yuv[i]);
}
} }
LOGD("released buffers"); LOGD("released buffers");
} }
@@ -1095,7 +1395,9 @@ void SpectraCamera::handle_camera_event(const cam_req_mgr_message *event_data) {
uint64_t real_id = event_data->u.frame_msg.request_id; uint64_t real_id = event_data->u.frame_msg.request_id;
if (real_id != 0) { // next ready if (real_id != 0) { // next ready
if (real_id == 1) {idx_offset = main_id;} if (real_id == 1) {
idx_offset = main_id;
}
int buf_idx = (real_id - 1) % ife_buf_depth; int buf_idx = (real_id - 1) % ife_buf_depth;
// check for skipped frames // check for skipped frames
+14 -5
View File
@@ -9,7 +9,7 @@
#include "media/cam_req_mgr.h" #include "media/cam_req_mgr.h"
#include "common/util.h" #include "common/util.h"
#include "system/camerad/cameras/tici.h" #include "system/camerad/cameras/hw.h"
#include "system/camerad/cameras/camera_common.h" #include "system/camerad/cameras/camera_common.h"
#include "system/camerad/sensors/sensor.h" #include "system/camerad/sensors/sensor.h"
@@ -29,6 +29,12 @@ const int MIPI_SETTLE_CNT = 33; // Calculated by camera_freqs.py
#define OpcodesIFEInitialConfig 0x0 #define OpcodesIFEInitialConfig 0x0
#define OpcodesIFEUpdate 0x1 #define OpcodesIFEUpdate 0x1
typedef enum {
ISP_RAW_OUTPUT, // raw frame from sensor
ISP_IFE_PROCESSED, // fully processed image through the IFE
ISP_BPS_PROCESSED, // fully processed image through the BPS
} SpectraOutputType;
std::optional<int32_t> device_acquire(int fd, int32_t session_handle, void *data, uint32_t num_resources=1); std::optional<int32_t> device_acquire(int fd, int32_t session_handle, void *data, uint32_t num_resources=1);
int device_config(int fd, int32_t session_handle, int32_t dev_handle, uint64_t packet_handle); int device_config(int fd, int32_t session_handle, int32_t dev_handle, uint64_t packet_handle);
int device_control(int fd, int op_code, int session_handle, int dev_handle); int device_control(int fd, int op_code, int session_handle, int dev_handle);
@@ -103,7 +109,7 @@ public:
class SpectraCamera { class SpectraCamera {
public: public:
SpectraCamera(SpectraMaster *master, const CameraConfig &config, bool raw); SpectraCamera(SpectraMaster *master, const CameraConfig &config, SpectraOutputType out);
~SpectraCamera(); ~SpectraCamera();
void camera_open(VisionIpcServer *v, cl_device_id device_id, cl_context ctx); void camera_open(VisionIpcServer *v, cl_device_id device_id, cl_context ctx);
@@ -166,18 +172,21 @@ public:
SpectraBuf bps_cdm_striping_bl; SpectraBuf bps_cdm_striping_bl;
SpectraBuf bps_iq; SpectraBuf bps_iq;
SpectraBuf bps_striping; SpectraBuf bps_striping;
SpectraBuf bps_linearization_lut;
std::vector<uint32_t> bps_lin_reg;
std::vector<uint32_t> bps_ccm_reg;
int buf_handle_yuv[MAX_IFE_BUFS] = {}; int buf_handle_yuv[MAX_IFE_BUFS] = {};
int buf_handle_raw[MAX_IFE_BUFS] = {}; int buf_handle_raw[MAX_IFE_BUFS] = {};
int sync_objs[MAX_IFE_BUFS] = {}; int sync_objs_ife[MAX_IFE_BUFS] = {};
int sync_objs_bps_out[MAX_IFE_BUFS] = {}; int sync_objs_bps[MAX_IFE_BUFS] = {};
uint64_t request_ids[MAX_IFE_BUFS] = {}; uint64_t request_ids[MAX_IFE_BUFS] = {};
uint64_t request_id_last = 0; uint64_t request_id_last = 0;
uint64_t frame_id_last = 0; uint64_t frame_id_last = 0;
uint64_t idx_offset = 0; uint64_t idx_offset = 0;
bool skipped = true; bool skipped = true;
bool is_raw; SpectraOutputType output_type;
CameraBuf buf; CameraBuf buf;
MemoryManager mm; MemoryManager mm;
-86
View File
@@ -1,7 +1,6 @@
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include "common/swaglog.h"
#include "system/camerad/sensors/sensor.h" #include "system/camerad/sensors/sensor.h"
namespace { namespace {
@@ -16,64 +15,6 @@ const float sensor_analog_gains_AR0231[] = {
5.0 / 4.0, 6.0 / 4.0, 6.0 / 3.0, 7.0 / 3.0, // 8, 9, 10, 11 5.0 / 4.0, 6.0 / 4.0, 6.0 / 3.0, 7.0 / 3.0, // 8, 9, 10, 11
7.0 / 2.0, 8.0 / 2.0, 8.0 / 1.0}; // 12, 13, 14, 15 = bypass 7.0 / 2.0, 8.0 / 2.0, 8.0 / 1.0}; // 12, 13, 14, 15 = bypass
std::map<uint16_t, std::pair<int, int>> ar0231_build_register_lut(const AR0231 *s, uint8_t *data) {
// This function builds a lookup table from register address, to a pair of indices in the
// buffer where to read this address. The buffer contains padding bytes,
// as well as markers to indicate the type of the next byte.
//
// 0xAA is used to indicate the MSB of the address, 0xA5 for the LSB of the address.
// Every byte of data (MSB and LSB) is preceded by 0x5A. Specifying an address is optional
// for contiguous ranges. See page 27-29 of the AR0231 Developer guide for more information.
int max_i[] = {1828 / 2 * 3, 1500 / 2 * 3};
auto get_next_idx = [](int cur_idx) {
return (cur_idx % 3 == 1) ? cur_idx + 2 : cur_idx + 1; // Every third byte is padding
};
std::map<uint16_t, std::pair<int, int>> registers;
for (int register_row = 0; register_row < 2; register_row++) {
uint8_t *registers_raw = data + s->frame_stride * register_row;
assert(registers_raw[0] == 0x0a); // Start of line
int value_tag_count = 0;
int first_val_idx = 0;
uint16_t cur_addr = 0;
for (int i = 1; i <= max_i[register_row]; i = get_next_idx(get_next_idx(i))) {
int val_idx = get_next_idx(i);
uint8_t tag = registers_raw[i];
uint16_t val = registers_raw[val_idx];
if (tag == 0xAA) { // Register MSB tag
cur_addr = val << 8;
} else if (tag == 0xA5) { // Register LSB tag
cur_addr |= val;
cur_addr -= 2; // Next value tag will increment address again
} else if (tag == 0x5A) { // Value tag
// First tag
if (value_tag_count % 2 == 0) {
cur_addr += 2;
first_val_idx = val_idx;
} else {
registers[cur_addr] = std::make_pair(first_val_idx + s->frame_stride * register_row, val_idx + s->frame_stride * register_row);
}
value_tag_count++;
}
}
}
return registers;
}
float ar0231_parse_temp_sensor(uint16_t calib1, uint16_t calib2, uint16_t data_reg) {
// See AR0231 Developer Guide - page 36
float slope = (125.0 - 55.0) / ((float)calib1 - (float)calib2);
float t0 = 55.0 - slope * (float)calib2;
return t0 + slope * (float)data_reg;
}
} // namespace } // namespace
AR0231::AR0231() { AR0231::AR0231() {
@@ -169,33 +110,6 @@ AR0231::AR0231() {
}; };
} }
void AR0231::processRegisters(uint8_t *cur_buf, cereal::FrameData::Builder &framed) const {
const uint8_t expected_preamble[] = {0x0a, 0xaa, 0x55, 0x20, 0xa5, 0x55};
uint8_t *data = cur_buf + registers_offset;
if (memcmp(data, expected_preamble, std::size(expected_preamble)) != 0) {
LOGE("unexpected register data found");
return;
}
if (ar0231_register_lut.empty()) {
ar0231_register_lut = ar0231_build_register_lut(this, data);
}
std::map<uint16_t, uint16_t> registers;
for (uint16_t addr : {0x2000, 0x2002, 0x20b0, 0x20b2, 0x30c6, 0x30c8, 0x30ca, 0x30cc}) {
auto offset = ar0231_register_lut[addr];
registers[addr] = ((uint16_t)data[offset.first] << 8) | data[offset.second];
}
uint32_t frame_id = ((uint32_t)registers[0x2000] << 16) | registers[0x2002];
framed.setFrameIdSensor(frame_id);
float temp_0 = ar0231_parse_temp_sensor(registers[0x30c6], registers[0x30c8], registers[0x20b0]);
float temp_1 = ar0231_parse_temp_sensor(registers[0x30ca], registers[0x30cc], registers[0x20b2]);
framed.setTemperaturesC({temp_0, temp_1});
}
std::vector<i2c_random_wr_payload> AR0231::getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { std::vector<i2c_random_wr_payload> AR0231::getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const {
uint16_t analog_gain_reg = 0xFF00 | (new_exp_g << 4) | new_exp_g; uint16_t analog_gain_reg = 0xFF00 | (new_exp_g << 4) | new_exp_g;
return { return {
+4 -2
View File
@@ -22,7 +22,6 @@ public:
virtual std::vector<i2c_random_wr_payload> getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { return {}; } virtual std::vector<i2c_random_wr_payload> getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { return {}; }
virtual float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const {return 0; } virtual float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const {return 0; }
virtual int getSlaveAddress(int port) const { assert(0); } virtual int getSlaveAddress(int port) const { assert(0); }
virtual void processRegisters(uint8_t *cur_buf, cereal::FrameData::Builder &framed) const {}
cereal::FrameData::ImageSensor image_sensor = cereal::FrameData::ImageSensor::UNKNOWN; cereal::FrameData::ImageSensor image_sensor = cereal::FrameData::ImageSensor::UNKNOWN;
float pixel_size_mm; float pixel_size_mm;
@@ -82,6 +81,10 @@ public:
std::vector<uint32_t> linearization_lut; // length 36 std::vector<uint32_t> linearization_lut; // length 36
std::vector<uint32_t> linearization_pts; // length 4 std::vector<uint32_t> linearization_pts; // length 4
std::vector<uint32_t> vignetting_lut; // length 221 std::vector<uint32_t> vignetting_lut; // length 221
const int num() const {
return static_cast<int>(image_sensor);
};
}; };
class AR0231 : public SensorInfo { class AR0231 : public SensorInfo {
@@ -90,7 +93,6 @@ public:
std::vector<i2c_random_wr_payload> getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const override; std::vector<i2c_random_wr_payload> getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const override;
float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const override; float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const override;
int getSlaveAddress(int port) const override; int getSlaveAddress(int port) const override;
void processRegisters(uint8_t *cur_buf, cereal::FrameData::Builder &framed) const override;
private: private:
mutable std::map<uint16_t, std::pair<int, int>> ar0231_register_lut; mutable std::map<uint16_t, std::pair<int, int>> ar0231_register_lut;
+1 -1
View File
@@ -5,7 +5,7 @@ set -e
# no CCI and UTIL, very spammy # no CCI and UTIL, very spammy
echo 0xfffdbfff | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl echo 0xfffdbfff | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl
echo 0 | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl #echo 0 | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl
sudo dmesg -C sudo dmesg -C
scons -u -j8 --minimal . scons -u -j8 --minimal .
+51 -39
View File
@@ -1,24 +1,4 @@
[ [
{
"name": "boot",
"url": "https://commadist.azureedge.net/agnosupdate/boot-5679a04c7cb08ab2f6bdb26b7f807d2a5819d2055151a9d3c89e65c7f24a85d8.img.xz",
"hash": "5679a04c7cb08ab2f6bdb26b7f807d2a5819d2055151a9d3c89e65c7f24a85d8",
"hash_raw": "5679a04c7cb08ab2f6bdb26b7f807d2a5819d2055151a9d3c89e65c7f24a85d8",
"size": 16422912,
"sparse": false,
"full_check": true,
"has_ab": true
},
{
"name": "system",
"url": "https://commadist.azureedge.net/agnosupdate/system-5a11d6b2588ddb562b69cf2c27d7a8feae2ef0693f73a01cf6536b2cd9a09a29.img.xz",
"hash": "5a11d6b2588ddb562b69cf2c27d7a8feae2ef0693f73a01cf6536b2cd9a09a29",
"hash_raw": "5a11d6b2588ddb562b69cf2c27d7a8feae2ef0693f73a01cf6536b2cd9a09a29",
"size": 4404019200,
"sparse": false,
"full_check": false,
"has_ab": true
},
{ {
"name": "xbl", "name": "xbl",
"url": "https://commadist.azureedge.net/agnosupdate/xbl-468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c.img.xz", "url": "https://commadist.azureedge.net/agnosupdate/xbl-468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c.img.xz",
@@ -27,17 +7,8 @@
"size": 3282256, "size": 3282256,
"sparse": false, "sparse": false,
"full_check": true, "full_check": true,
"has_ab": true "has_ab": true,
}, "ondevice_hash": "d35a86e7b8ddd9279b513a6f27da1521aa0f89fb93987ea74d57d0f0bbbbd247"
{
"name": "abl",
"url": "https://commadist.azureedge.net/agnosupdate/abl-32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6.img.xz",
"hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6",
"hash_raw": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6",
"size": 274432,
"sparse": false,
"full_check": true,
"has_ab": true
}, },
{ {
"name": "xbl_config", "name": "xbl_config",
@@ -47,17 +18,19 @@
"size": 98124, "size": 98124,
"sparse": false, "sparse": false,
"full_check": true, "full_check": true,
"has_ab": true "has_ab": true,
"ondevice_hash": "623f1568072ee2d687ba8449a3d894c1c83dc4131b2e79eff35696885f70a419"
}, },
{ {
"name": "devcfg", "name": "abl",
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180.img.xz", "url": "https://commadist.azureedge.net/agnosupdate/abl-32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6.img.xz",
"hash": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180", "hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6",
"hash_raw": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180", "hash_raw": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6",
"size": 40336, "size": 274432,
"sparse": false, "sparse": false,
"full_check": true, "full_check": true,
"has_ab": true "has_ab": true,
"ondevice_hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6"
}, },
{ {
"name": "aop", "name": "aop",
@@ -67,6 +40,45 @@
"size": 184364, "size": 184364,
"sparse": false, "sparse": false,
"full_check": true, "full_check": true,
"has_ab": true "has_ab": true,
"ondevice_hash": "bf74feca486f650589f6b7c90eab73274e35a68b5e00bfc1de0ed5f5484d4b3d"
},
{
"name": "devcfg",
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180.img.xz",
"hash": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
"hash_raw": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
"size": 40336,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "70f682b59ca0fe2f197d1486bd8be7b9b7e560798ad40ddef83b9f0a2f497938"
},
{
"name": "boot",
"url": "https://commadist.azureedge.net/agnosupdate/boot-c7cba1ce64bf85384241fa063971855c5ffcb4d90a0d07bed4733d46b94d4170.img.xz",
"hash": "c7cba1ce64bf85384241fa063971855c5ffcb4d90a0d07bed4733d46b94d4170",
"hash_raw": "c7cba1ce64bf85384241fa063971855c5ffcb4d90a0d07bed4733d46b94d4170",
"size": 18475008,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "6a9a71bf01f2013f35bda9594cefe3cb4a3835402a6cb0e95306fe4decf261c5"
},
{
"name": "system",
"url": "https://commadist.azureedge.net/agnosupdate/system-cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625.img.xz",
"hash": "990ff7005a5bee8e759c96ddba23f1258f043fb038cf74083bf7d2d9c9a29e39",
"hash_raw": "cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625",
"size": 4404019200,
"sparse": true,
"full_check": false,
"has_ab": true,
"ondevice_hash": "d922fffe1b5f02898465a2d6625294abb70d22643ebf2d6a94f5d7512291d1a4",
"alt": {
"hash": "cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625",
"url": "https://commadist.azureedge.net/agnosupdate/system-cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625.img",
"size": 4404019200
}
} }
] ]
+400
View File
@@ -0,0 +1,400 @@
[
{
"name": "gpt_main_0",
"url": "https://commadist.azureedge.net/agnosupdate/gpt_main_0-8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd.img.xz",
"hash": "8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd",
"hash_raw": "8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd",
"size": 24576,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd",
"gpt": {
"lun": 0,
"start_sector": 0,
"num_sectors": 6
}
},
{
"name": "gpt_main_1",
"url": "https://commadist.azureedge.net/agnosupdate/gpt_main_1-fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6.img.xz",
"hash": "fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6",
"hash_raw": "fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6",
"size": 24576,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6",
"gpt": {
"lun": 1,
"start_sector": 0,
"num_sectors": 6
}
},
{
"name": "gpt_main_2",
"url": "https://commadist.azureedge.net/agnosupdate/gpt_main_2-5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21.img.xz",
"hash": "5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21",
"hash_raw": "5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21",
"size": 24576,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21",
"gpt": {
"lun": 2,
"start_sector": 0,
"num_sectors": 6
}
},
{
"name": "gpt_main_3",
"url": "https://commadist.azureedge.net/agnosupdate/gpt_main_3-c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159.img.xz",
"hash": "c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159",
"hash_raw": "c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159",
"size": 24576,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159",
"gpt": {
"lun": 3,
"start_sector": 0,
"num_sectors": 6
}
},
{
"name": "gpt_main_4",
"url": "https://commadist.azureedge.net/agnosupdate/gpt_main_4-e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e.img.xz",
"hash": "e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e",
"hash_raw": "e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e",
"size": 24576,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e",
"gpt": {
"lun": 4,
"start_sector": 0,
"num_sectors": 6
}
},
{
"name": "gpt_main_5",
"url": "https://commadist.azureedge.net/agnosupdate/gpt_main_5-21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3.img.xz",
"hash": "21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3",
"hash_raw": "21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3",
"size": 24576,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3",
"gpt": {
"lun": 5,
"start_sector": 0,
"num_sectors": 6
}
},
{
"name": "persist",
"url": "https://commadist.azureedge.net/agnosupdate/persist-9814b07851292f510f3794b767489f38ab379a99f0ea75dc620ad2d3a496d54d.img.xz",
"hash": "9814b07851292f510f3794b767489f38ab379a99f0ea75dc620ad2d3a496d54d",
"hash_raw": "9814b07851292f510f3794b767489f38ab379a99f0ea75dc620ad2d3a496d54d",
"size": 33554432,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "9814b07851292f510f3794b767489f38ab379a99f0ea75dc620ad2d3a496d54d"
},
{
"name": "systemrw",
"url": "https://commadist.azureedge.net/agnosupdate/systemrw-8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e.img.xz",
"hash": "8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e",
"hash_raw": "8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e",
"size": 16777216,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e"
},
{
"name": "cache",
"url": "https://commadist.azureedge.net/agnosupdate/cache-ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4.img.xz",
"hash": "ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4",
"hash_raw": "ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4",
"size": 134217728,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4"
},
{
"name": "xbl",
"url": "https://commadist.azureedge.net/agnosupdate/xbl-468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c.img.xz",
"hash": "468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c",
"hash_raw": "468f1ad6ab55e198647ff9191f91bd2918db9c0a3e27bae5673b4c5575c1254c",
"size": 3282256,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "d35a86e7b8ddd9279b513a6f27da1521aa0f89fb93987ea74d57d0f0bbbbd247"
},
{
"name": "xbl_config",
"url": "https://commadist.azureedge.net/agnosupdate/xbl_config-92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b.img.xz",
"hash": "92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b",
"hash_raw": "92b675dc2862ed15c732d91d9eb307d7e852e349217db8bee8f8829db543686b",
"size": 98124,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "623f1568072ee2d687ba8449a3d894c1c83dc4131b2e79eff35696885f70a419"
},
{
"name": "abl",
"url": "https://commadist.azureedge.net/agnosupdate/abl-32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6.img.xz",
"hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6",
"hash_raw": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6",
"size": 274432,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "32a2174b5f764e95dfc54cf358ba01752943b1b3b90e626149c3da7d5f1830b6"
},
{
"name": "aop",
"url": "https://commadist.azureedge.net/agnosupdate/aop-f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5.img.xz",
"hash": "f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5",
"hash_raw": "f0fcf7611d0890a72984f15a516dd37fa532dfcb70d428a8406838cf74ce23d5",
"size": 184364,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "bf74feca486f650589f6b7c90eab73274e35a68b5e00bfc1de0ed5f5484d4b3d"
},
{
"name": "bluetooth",
"url": "https://commadist.azureedge.net/agnosupdate/bluetooth-9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533.img.xz",
"hash": "9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533",
"hash_raw": "9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533",
"size": 1048576,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533"
},
{
"name": "cmnlib64",
"url": "https://commadist.azureedge.net/agnosupdate/cmnlib64-1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3.img.xz",
"hash": "1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3",
"hash_raw": "1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3",
"size": 524288,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3"
},
{
"name": "cmnlib",
"url": "https://commadist.azureedge.net/agnosupdate/cmnlib-63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82.img.xz",
"hash": "63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82",
"hash_raw": "63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82",
"size": 524288,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82"
},
{
"name": "devcfg",
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180.img.xz",
"hash": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
"hash_raw": "225b24ea7b1d2fee7f7d2da21386920ddacac2e33e9e938168436292f4eae180",
"size": 40336,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "70f682b59ca0fe2f197d1486bd8be7b9b7e560798ad40ddef83b9f0a2f497938"
},
{
"name": "devinfo",
"url": "https://commadist.azureedge.net/agnosupdate/devinfo-143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3.img.xz",
"hash": "143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3",
"hash_raw": "143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3",
"size": 4096,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3"
},
{
"name": "dsp",
"url": "https://commadist.azureedge.net/agnosupdate/dsp-4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248.img.xz",
"hash": "4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248",
"hash_raw": "4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248",
"size": 33554432,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248"
},
{
"name": "hyp",
"url": "https://commadist.azureedge.net/agnosupdate/hyp-ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927.img.xz",
"hash": "ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927",
"hash_raw": "ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927",
"size": 524288,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927"
},
{
"name": "keymaster",
"url": "https://commadist.azureedge.net/agnosupdate/keymaster-5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04.img.xz",
"hash": "5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04",
"hash_raw": "5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04",
"size": 524288,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04"
},
{
"name": "limits",
"url": "https://commadist.azureedge.net/agnosupdate/limits-94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1.img.xz",
"hash": "94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1",
"hash_raw": "94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1",
"size": 4096,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1"
},
{
"name": "logfs",
"url": "https://commadist.azureedge.net/agnosupdate/logfs-b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220.img.xz",
"hash": "b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220",
"hash_raw": "b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220",
"size": 8388608,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220"
},
{
"name": "modem",
"url": "https://commadist.azureedge.net/agnosupdate/modem-a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994.img.xz",
"hash": "a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994",
"hash_raw": "a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994",
"size": 125829120,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994"
},
{
"name": "qupfw",
"url": "https://commadist.azureedge.net/agnosupdate/qupfw-64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a.img.xz",
"hash": "64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a",
"hash_raw": "64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a",
"size": 65536,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a"
},
{
"name": "splash",
"url": "https://commadist.azureedge.net/agnosupdate/splash-5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08.img.xz",
"hash": "5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08",
"hash_raw": "5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08",
"size": 34226176,
"sparse": false,
"full_check": true,
"has_ab": false,
"ondevice_hash": "5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08"
},
{
"name": "storsec",
"url": "https://commadist.azureedge.net/agnosupdate/storsec-4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce.img.xz",
"hash": "4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce",
"hash_raw": "4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce",
"size": 131072,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce"
},
{
"name": "tz",
"url": "https://commadist.azureedge.net/agnosupdate/tz-e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16.img.xz",
"hash": "e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16",
"hash_raw": "e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16",
"size": 2097152,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16"
},
{
"name": "boot",
"url": "https://commadist.azureedge.net/agnosupdate/boot-c7cba1ce64bf85384241fa063971855c5ffcb4d90a0d07bed4733d46b94d4170.img.xz",
"hash": "c7cba1ce64bf85384241fa063971855c5ffcb4d90a0d07bed4733d46b94d4170",
"hash_raw": "c7cba1ce64bf85384241fa063971855c5ffcb4d90a0d07bed4733d46b94d4170",
"size": 18475008,
"sparse": false,
"full_check": true,
"has_ab": true,
"ondevice_hash": "6a9a71bf01f2013f35bda9594cefe3cb4a3835402a6cb0e95306fe4decf261c5"
},
{
"name": "system",
"url": "https://commadist.azureedge.net/agnosupdate/system-cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625.img.xz",
"hash": "990ff7005a5bee8e759c96ddba23f1258f043fb038cf74083bf7d2d9c9a29e39",
"hash_raw": "cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625",
"size": 4404019200,
"sparse": true,
"full_check": false,
"has_ab": true,
"ondevice_hash": "d922fffe1b5f02898465a2d6625294abb70d22643ebf2d6a94f5d7512291d1a4",
"alt": {
"hash": "cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625",
"url": "https://commadist.azureedge.net/agnosupdate/system-cd03486f6c7333dee21f59af771f9992ea90a9a04271c1506a663d658f391625.img",
"size": 4404019200
}
},
{
"name": "userdata_90",
"url": "https://commadist.azureedge.net/agnosupdate/userdata_90-554a22697b356cb150c2c803b4cb1de79403849e9be451c844d218d38b5bc236.img.xz",
"hash": "4f0a862e3aff4980e697ece63afaef6f9869d013ac2ca4c45193e41089ee4f5c",
"hash_raw": "554a22697b356cb150c2c803b4cb1de79403849e9be451c844d218d38b5bc236",
"size": 96636764160,
"sparse": true,
"full_check": true,
"has_ab": false,
"ondevice_hash": "5d780092d51c569e6b8a28ab73f4029bcc3517698f496af5801f863c9865060f"
},
{
"name": "userdata_89",
"url": "https://commadist.azureedge.net/agnosupdate/userdata_89-6045b9a3f1ae6e0ee09b95da039b697ab8d8447cdd0796fa31afa9c7d324ee80.img.xz",
"hash": "ba49fef48573e9befdfb6334181753855cb83d3e1d8c6d4d83d510ea0141ec3f",
"hash_raw": "6045b9a3f1ae6e0ee09b95da039b697ab8d8447cdd0796fa31afa9c7d324ee80",
"size": 95563022336,
"sparse": true,
"full_check": true,
"has_ab": false,
"ondevice_hash": "19b63b184063c25ff2fc9f1c8d1c919c140c3e1295ebac6cb66e64c5cb609abe"
},
{
"name": "userdata_30",
"url": "https://commadist.azureedge.net/agnosupdate/userdata_30-498358c1e5347dc3f8c369523bd77b94ef73d6c6729b40f376209d0d32b356fe.img.xz",
"hash": "828d0911713af02de7fae4c583a2274783e344939f296c7c016866a8cf2cb63f",
"hash_raw": "498358c1e5347dc3f8c369523bd77b94ef73d6c6729b40f376209d0d32b356fe",
"size": 32212254720,
"sparse": true,
"full_check": true,
"has_ab": false,
"ondevice_hash": "4beb60ffceff88b05daa014db50cb2f4e9acec3ed7ae1b89a8d3c84cfc3c1c92"
}
]
+6 -6
View File
@@ -76,7 +76,7 @@ def sudo_write(val, path):
def sudo_read(path: str) -> str: def sudo_read(path: str) -> str:
try: try:
return subprocess.check_output(f"sudo cat {path}", shell=True, encoding='utf8') return subprocess.check_output(f"sudo cat {path}", shell=True, encoding='utf8').strip()
except Exception: except Exception:
return "" return ""
@@ -371,7 +371,7 @@ class Tici(HardwareBase):
# *** CPU config *** # *** CPU config ***
# offline big cluster, leave core 4 online for pandad # offline big cluster
for i in range(4, 8): for i in range(4, 8):
val = '0' if powersave_enabled else '1' val = '0' if powersave_enabled else '1'
sudo_write(val, f'/sys/devices/system/cpu/cpu{i}/online') sudo_write(val, f'/sys/devices/system/cpu/cpu{i}/online')
@@ -384,13 +384,13 @@ class Tici(HardwareBase):
# *** IRQ config *** # *** IRQ config ***
# GPU # GPU, modeld core
affine_irq(5, "kgsl-3d0") affine_irq(7, "kgsl-3d0")
# camerad core # camerad core
camera_irqs = ("cci", "cpas_camnoc", "cpas-cdm", "csid", "ife", "csid-lite", "ife-lite") camera_irqs = ("a5", "cci", "cpas_camnoc", "cpas-cdm", "csid", "ife", "csid-lite", "ife-lite")
for n in camera_irqs: for n in camera_irqs:
affine_irq(5, n) affine_irq(6, n)
def get_gpu_usage_percent(self): def get_gpu_usage_percent(self):
try: try:
@@ -31,7 +31,7 @@ class Proc:
PROCS = [ PROCS = [
Proc(['camerad'], 2.1, msgs=['roadCameraState', 'wideRoadCameraState', 'driverCameraState']), Proc(['camerad'], 1.75, msgs=['roadCameraState', 'wideRoadCameraState', 'driverCameraState']),
Proc(['modeld'], 1.12, atol=0.2, msgs=['modelV2']), Proc(['modeld'], 1.12, atol=0.2, msgs=['modelV2']),
Proc(['dmonitoringmodeld'], 0.6, msgs=['driverStateV2']), Proc(['dmonitoringmodeld'], 0.6, msgs=['driverStateV2']),
Proc(['encoderd'], 0.23, msgs=[]), Proc(['encoderd'], 0.23, msgs=[]),
+5 -5
View File
@@ -1,10 +1,10 @@
Import('env', 'arch', 'messaging', 'common', 'visionipc') Import('env', 'arch', 'messaging', 'common', 'visionipc')
libs = [common, messaging, visionipc, libs = [common, messaging, visionipc,
'z', 'avformat', 'avcodec', 'swscale', 'avformat', 'avcodec', 'avutil',
'avutil', 'yuv', 'OpenCL', 'pthread'] 'yuv', 'OpenCL', 'pthread', 'zstd']
src = ['logger.cc', 'video_writer.cc', 'encoder/encoder.cc', 'encoder/v4l_encoder.cc'] src = ['logger.cc', 'zstd_writer.cc', 'video_writer.cc', 'encoder/encoder.cc', 'encoder/v4l_encoder.cc', 'encoder/jpeg_encoder.cc']
if arch != "larch64": if arch != "larch64":
src += ['encoder/ffmpeg_encoder.cc'] src += ['encoder/ffmpeg_encoder.cc']
@@ -19,8 +19,8 @@ logger_lib = env.Library('logger', src)
libs.insert(0, logger_lib) libs.insert(0, logger_lib)
env.Program('loggerd', ['loggerd.cc'], LIBS=libs) env.Program('loggerd', ['loggerd.cc'], LIBS=libs)
env.Program('encoderd', ['encoderd.cc'], LIBS=libs) env.Program('encoderd', ['encoderd.cc'], LIBS=libs + ["jpeg"])
env.Program('bootlog.cc', LIBS=libs) env.Program('bootlog.cc', LIBS=libs)
if GetOption('extras'): if GetOption('extras'):
env.Program('tests/test_logger', ['tests/test_runner.cc', 'tests/test_logger.cc'], LIBS=libs + ['curl', 'crypto']) env.Program('tests/test_logger', ['tests/test_runner.cc', 'tests/test_logger.cc', 'tests/test_zstd_writer.cc'], LIBS=libs + ['curl', 'crypto'])
+3 -2
View File
@@ -5,6 +5,7 @@
#include "common/params.h" #include "common/params.h"
#include "common/swaglog.h" #include "common/swaglog.h"
#include "system/loggerd/logger.h" #include "system/loggerd/logger.h"
#include "system/loggerd/zstd_writer.h"
static kj::Array<capnp::word> build_boot_log() { static kj::Array<capnp::word> build_boot_log() {
@@ -50,14 +51,14 @@ static kj::Array<capnp::word> build_boot_log() {
int main(int argc, char** argv) { int main(int argc, char** argv) {
const std::string id = logger_get_identifier("BootCount"); const std::string id = logger_get_identifier("BootCount");
const std::string path = Path::log_root() + "/boot/" + id; const std::string path = Path::log_root() + "/boot/" + id + ".zst";
LOGW("bootlog to %s", path.c_str()); LOGW("bootlog to %s", path.c_str());
// Open bootlog // Open bootlog
bool r = util::create_directories(Path::log_root() + "/boot/", 0775); bool r = util::create_directories(Path::log_root() + "/boot/", 0775);
assert(r); assert(r);
RawFile file(path.c_str()); ZstdFileWriter file(path, LOG_COMPRESSION_LEVEL);
// Write initdata // Write initdata
file.write(logger_build_init_data().asBytes()); file.write(logger_build_init_data().asBytes());
// Write bootlog // Write bootlog
+1 -17
View File
@@ -6,12 +6,7 @@ VideoEncoder::VideoEncoder(const EncoderInfo &encoder_info, int in_width, int in
out_width = encoder_info.frame_width > 0 ? encoder_info.frame_width : in_width; out_width = encoder_info.frame_width > 0 ? encoder_info.frame_width : in_width;
out_height = encoder_info.frame_height > 0 ? encoder_info.frame_height : in_height; out_height = encoder_info.frame_height > 0 ? encoder_info.frame_height : in_height;
pm.reset(new PubMaster(std::vector{encoder_info.publish_name}));
std::vector pubs = {encoder_info.publish_name};
if (encoder_info.thumbnail_name != NULL) {
pubs.push_back(encoder_info.thumbnail_name);
}
pm.reset(new PubMaster(pubs));
} }
void VideoEncoder::publisher_publish(int segment_num, uint32_t idx, VisionIpcBufExtra &extra, void VideoEncoder::publisher_publish(int segment_num, uint32_t idx, VisionIpcBufExtra &extra,
@@ -45,15 +40,4 @@ void VideoEncoder::publisher_publish(int segment_num, uint32_t idx, VisionIpcBuf
kj::ArrayOutputStream output_stream(kj::ArrayPtr<capnp::byte>(msg_cache.data(), bytes_size)); kj::ArrayOutputStream output_stream(kj::ArrayPtr<capnp::byte>(msg_cache.data(), bytes_size));
capnp::writeMessage(output_stream, msg); capnp::writeMessage(output_stream, msg);
pm->send(encoder_info.publish_name, msg_cache.data(), bytes_size); pm->send(encoder_info.publish_name, msg_cache.data(), bytes_size);
// Publish keyframe thumbnail
if ((flags & V4L2_BUF_FLAG_KEYFRAME) && encoder_info.thumbnail_name != NULL) {
MessageBuilder tm;
auto thumbnail = tm.initEvent().initThumbnail();
thumbnail.setFrameId(extra.frame_id);
thumbnail.setTimestampEof(extra.timestamp_eof);
thumbnail.setThumbnail(dat);
thumbnail.setEncoding(cereal::Thumbnail::Encoding::KEYFRAME);
pm->send(encoder_info.thumbnail_name, tm);
}
} }
-2
View File
@@ -30,8 +30,6 @@ public:
void publisher_publish(int segment_num, uint32_t idx, VisionIpcBufExtra &extra, unsigned int flags, kj::ArrayPtr<capnp::byte> header, kj::ArrayPtr<capnp::byte> dat); void publisher_publish(int segment_num, uint32_t idx, VisionIpcBufExtra &extra, unsigned int flags, kj::ArrayPtr<capnp::byte> header, kj::ArrayPtr<capnp::byte> dat);
protected: protected:
void publish_thumbnail(uint32_t frame_id, uint64_t timestamp_eof, kj::ArrayPtr<capnp::byte> dat);
int in_width, in_height; int in_width, in_height;
int out_width, out_height; int out_width, out_height;
const EncoderInfo encoder_info; const EncoderInfo encoder_info;
+4 -1
View File
@@ -48,7 +48,10 @@ FfmpegEncoder::~FfmpegEncoder() {
} }
void FfmpegEncoder::encoder_open(const char* path) { void FfmpegEncoder::encoder_open(const char* path) {
const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_FFVHUFF); auto codec_id = encoder_info.encode_type == cereal::EncodeIndex::Type::QCAMERA_H264
? AV_CODEC_ID_H264
: AV_CODEC_ID_FFVHUFF;
const AVCodec *codec = avcodec_find_encoder(codec_id);
this->codec_ctx = avcodec_alloc_context3(codec); this->codec_ctx = avcodec_alloc_context3(codec);
assert(this->codec_ctx); assert(this->codec_ctx);
+105
View File
@@ -0,0 +1,105 @@
#include "system/loggerd/encoder/jpeg_encoder.h"
#include <cassert>
#include <cstring>
JpegEncoder::JpegEncoder(const std::string &pusblish_name, int width, int height)
: publish_name(pusblish_name), thumbnail_width(width), thumbnail_height(height) {
yuv_buffer.resize((thumbnail_width * ((thumbnail_height + 15) & ~15) * 3) / 2);
pm = std::make_unique<PubMaster>(std::vector{pusblish_name.c_str()});
}
JpegEncoder::~JpegEncoder() {
if (out_buffer) {
free(out_buffer);
}
}
void JpegEncoder::pushThumbnail(VisionBuf *buf, const VisionIpcBufExtra &extra) {
generateThumbnail(buf->y, buf->uv, buf->width, buf->height, buf->stride);
MessageBuilder msg;
auto thumbnaild = msg.initEvent().initThumbnail();
thumbnaild.setFrameId(extra.frame_id);
thumbnaild.setTimestampEof(extra.timestamp_eof);
thumbnaild.setThumbnail({out_buffer, out_size});
pm->send(publish_name.c_str(), msg);
}
void JpegEncoder::generateThumbnail(const uint8_t *y_addr, const uint8_t *uv_addr, int width, int height, int stride) {
int downscale = width / thumbnail_width;
assert(downscale * thumbnail_height == height);
// make the buffer big enough. jpeg_write_raw_data requires 16-pixels aligned height to be used.
uint8_t *y_plane = yuv_buffer.data();
uint8_t *u_plane = y_plane + thumbnail_width * thumbnail_height;
uint8_t *v_plane = u_plane + (thumbnail_width * thumbnail_height) / 4;
{
// subsampled conversion from nv12 to yuv
for (int hy = 0; hy < thumbnail_height / 2; hy++) {
for (int hx = 0; hx < thumbnail_width / 2; hx++) {
int ix = hx * downscale + (downscale - 1) / 2;
int iy = hy * downscale + (downscale - 1) / 2;
y_plane[(hy * 2 + 0) * thumbnail_width + (hx * 2 + 0)] = y_addr[(iy * 2 + 0) * stride + ix * 2 + 0];
y_plane[(hy * 2 + 0) * thumbnail_width + (hx * 2 + 1)] = y_addr[(iy * 2 + 0) * stride + ix * 2 + 1];
y_plane[(hy * 2 + 1) * thumbnail_width + (hx * 2 + 0)] = y_addr[(iy * 2 + 1) * stride + ix * 2 + 0];
y_plane[(hy * 2 + 1) * thumbnail_width + (hx * 2 + 1)] = y_addr[(iy * 2 + 1) * stride + ix * 2 + 1];
u_plane[hy * thumbnail_width / 2 + hx] = uv_addr[iy * stride + ix * 2 + 0];
v_plane[hy * thumbnail_width / 2 + hx] = uv_addr[iy * stride + ix * 2 + 1];
}
}
}
compressToJpeg(y_plane, u_plane, v_plane);
}
void JpegEncoder::compressToJpeg(uint8_t *y_plane, uint8_t *u_plane, uint8_t *v_plane) {
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if (out_buffer) {
free(out_buffer);
out_buffer = nullptr;
out_size = 0;
}
jpeg_mem_dest(&cinfo, &out_buffer, &out_size);
cinfo.image_width = thumbnail_width;
cinfo.image_height = thumbnail_height;
cinfo.input_components = 3;
jpeg_set_defaults(&cinfo);
jpeg_set_colorspace(&cinfo, JCS_YCbCr);
// configure sampling factors for yuv420.
cinfo.comp_info[0].h_samp_factor = 2; // Y
cinfo.comp_info[0].v_samp_factor = 2;
cinfo.comp_info[1].h_samp_factor = 1; // U
cinfo.comp_info[1].v_samp_factor = 1;
cinfo.comp_info[2].h_samp_factor = 1; // V
cinfo.comp_info[2].v_samp_factor = 1;
cinfo.raw_data_in = TRUE;
jpeg_set_quality(&cinfo, 50, TRUE);
jpeg_start_compress(&cinfo, TRUE);
JSAMPROW y[16], u[8], v[8];
JSAMPARRAY planes[3]{y, u, v};
for (int line = 0; line < cinfo.image_height; line += 16) {
for (int i = 0; i < 16; ++i) {
y[i] = y_plane + (line + i) * cinfo.image_width;
if (i % 2 == 0) {
int offset = (cinfo.image_width / 2) * ((i + line) / 2);
u[i / 2] = u_plane + offset;
v[i / 2] = v_plane + offset;
}
}
jpeg_write_raw_data(&cinfo, planes, 16);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <cstdio>
#include <cstdlib>
#include <cstddef>
#include <cstdint>
#include <jpeglib.h>
#include <vector>
#include <memory>
#include "cereal/messaging/messaging.h"
#include "msgq/visionipc/visionbuf.h"
class JpegEncoder {
public:
JpegEncoder(const std::string &pusblish_name, int width, int height);
~JpegEncoder();
void pushThumbnail(VisionBuf *buf, const VisionIpcBufExtra &extra);
private:
void generateThumbnail(const uint8_t *y, const uint8_t *uv, int width, int height, int stride);
void compressToJpeg(uint8_t *y_plane, uint8_t *u_plane, uint8_t *v_plane);
int thumbnail_width;
int thumbnail_height;
std::string publish_name;
std::vector<uint8_t> yuv_buffer;
std::unique_ptr<PubMaster> pm;
// JPEG output buffer
unsigned char* out_buffer = nullptr;
unsigned long out_size = 0;
};
+1 -1
View File
@@ -155,7 +155,7 @@ void V4LEncoder::dequeue_handler(V4LEncoder *e) {
V4LEncoder::V4LEncoder(const EncoderInfo &encoder_info, int in_width, int in_height) V4LEncoder::V4LEncoder(const EncoderInfo &encoder_info, int in_width, int in_height)
: VideoEncoder(encoder_info, in_width, in_height) { : VideoEncoder(encoder_info, in_width, in_height) {
fd = open("/dev/v4l/by-path/platform-aa00000.qcom_vidc-video-index1", O_RDWR|O_NONBLOCK); fd = HANDLE_EINTR(open("/dev/v4l/by-path/platform-aa00000.qcom_vidc-video-index1", O_RDWR|O_NONBLOCK));
assert(fd >= 0); assert(fd >= 0);
struct v4l2_capability cap; struct v4l2_capability cap;
+12
View File
@@ -1,6 +1,7 @@
#include <cassert> #include <cassert>
#include "system/loggerd/loggerd.h" #include "system/loggerd/loggerd.h"
#include "system/loggerd/encoder/jpeg_encoder.h"
#ifdef QCOM2 #ifdef QCOM2
#include "system/loggerd/encoder/v4l_encoder.h" #include "system/loggerd/encoder/v4l_encoder.h"
@@ -50,6 +51,8 @@ void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) {
std::vector<std::unique_ptr<Encoder>> encoders; std::vector<std::unique_ptr<Encoder>> encoders;
VisionIpcClient vipc_client = VisionIpcClient("camerad", cam_info.stream_type, false); VisionIpcClient vipc_client = VisionIpcClient("camerad", cam_info.stream_type, false);
std::unique_ptr<JpegEncoder> jpeg_encoder;
int cur_seg = 0; int cur_seg = 0;
while (!do_exit) { while (!do_exit) {
if (!vipc_client.connect(false)) { if (!vipc_client.connect(false)) {
@@ -67,6 +70,11 @@ void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) {
auto &e = encoders.emplace_back(new Encoder(encoder_info, buf_info.width, buf_info.height)); auto &e = encoders.emplace_back(new Encoder(encoder_info, buf_info.width, buf_info.height));
e->encoder_open(nullptr); e->encoder_open(nullptr);
} }
// Only one thumbnail can be generated per camera stream
if (auto thumbnail_name = cam_info.encoder_infos[0].thumbnail_name) {
jpeg_encoder = std::make_unique<JpegEncoder>(thumbnail_name, buf_info.width / 4, buf_info.height / 4);
}
} }
bool lagging = false; bool lagging = false;
@@ -108,6 +116,10 @@ void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) {
LOGE("Failed to encode frame. frame_id: %d", extra.frame_id); LOGE("Failed to encode frame. frame_id: %d", extra.frame_id);
} }
} }
if (jpeg_encoder && (extra.frame_id % 1200 == 100)) {
jpeg_encoder->pushThumbnail(buf, extra);
}
} }
} }
} }
+39 -4
View File
@@ -113,6 +113,42 @@ std::string logger_get_identifier(std::string key) {
return util::string_format("%08x--%s", cnt, ss.str().c_str()); return util::string_format("%08x--%s", cnt, ss.str().c_str());
} }
std::string zstd_decompress(const std::string &in) {
ZSTD_DCtx *dctx = ZSTD_createDCtx();
assert(dctx != nullptr);
// Initialize input and output buffers
ZSTD_inBuffer input = {in.data(), in.size(), 0};
// Estimate and reserve memory for decompressed data
size_t estimatedDecompressedSize = ZSTD_getFrameContentSize(in.data(), in.size());
if (estimatedDecompressedSize == ZSTD_CONTENTSIZE_ERROR || estimatedDecompressedSize == ZSTD_CONTENTSIZE_UNKNOWN) {
estimatedDecompressedSize = in.size() * 2; // Use a fallback size
}
std::string decompressedData;
decompressedData.reserve(estimatedDecompressedSize);
const size_t bufferSize = ZSTD_DStreamOutSize(); // Recommended output buffer size
std::string outputBuffer(bufferSize, '\0');
while (input.pos < input.size) {
ZSTD_outBuffer output = {outputBuffer.data(), bufferSize, 0};
size_t result = ZSTD_decompressStream(dctx, &output, &input);
if (ZSTD_isError(result)) {
break;
}
decompressedData.append(outputBuffer.data(), output.pos);
}
ZSTD_freeDCtx(dctx);
decompressedData.shrink_to_fit();
return decompressedData;
}
static void log_sentinel(LoggerState *log, SentinelType type, int exit_signal = 0) { static void log_sentinel(LoggerState *log, SentinelType type, int exit_signal = 0) {
MessageBuilder msg; MessageBuilder msg;
auto sen = msg.initEvent().initSentinel(); auto sen = msg.initEvent().initSentinel();
@@ -144,12 +180,11 @@ bool LoggerState::next() {
bool ret = util::create_directories(segment_path, 0775); bool ret = util::create_directories(segment_path, 0775);
assert(ret == true); assert(ret == true);
const std::string rlog_path = segment_path + "/rlog"; lock_file = segment_path + "/rlog.lock";
lock_file = rlog_path + ".lock";
std::ofstream{lock_file}; std::ofstream{lock_file};
rlog.reset(new RawFile(rlog_path)); rlog.reset(new ZstdFileWriter(segment_path + "/rlog.zst", LOG_COMPRESSION_LEVEL));
qlog.reset(new RawFile(segment_path + "/qlog")); qlog.reset(new ZstdFileWriter(segment_path + "/qlog.zst", LOG_COMPRESSION_LEVEL));
// log init data & sentinel type. // log init data & sentinel type.
write(init_data.asBytes(), true); write(init_data.asBytes(), true);
+4 -22
View File
@@ -7,31 +7,12 @@
#include "cereal/messaging/messaging.h" #include "cereal/messaging/messaging.h"
#include "common/util.h" #include "common/util.h"
#include "system/hardware/hw.h" #include "system/hardware/hw.h"
#include "system/loggerd/zstd_writer.h"
class RawFile { constexpr int LOG_COMPRESSION_LEVEL = 10;
public:
RawFile(const std::string &path) {
file = util::safe_fopen(path.c_str(), "wb");
assert(file != nullptr);
}
~RawFile() {
util::safe_fflush(file);
int err = fclose(file);
assert(err == 0);
}
inline void write(void* data, size_t size) {
int written = util::safe_fwrite(data, 1, size, file);
assert(written == size);
}
inline void write(kj::ArrayPtr<capnp::byte> array) { write(array.begin(), array.size()); }
private:
FILE* file = nullptr;
};
typedef cereal::Sentinel::SentinelType SentinelType; typedef cereal::Sentinel::SentinelType SentinelType;
class LoggerState { class LoggerState {
public: public:
LoggerState(const std::string& log_root = Path::log_root()); LoggerState(const std::string& log_root = Path::log_root());
@@ -48,8 +29,9 @@ protected:
int part = -1, exit_signal = 0; int part = -1, exit_signal = 0;
std::string route_path, route_name, segment_path, lock_file; std::string route_path, route_name, segment_path, lock_file;
kj::Array<capnp::word> init_data; kj::Array<capnp::word> init_data;
std::unique_ptr<RawFile> rlog, qlog; std::unique_ptr<ZstdFileWriter> rlog, qlog;
}; };
kj::Array<capnp::word> logger_build_init_data(); kj::Array<capnp::word> logger_build_init_data();
std::string logger_get_identifier(std::string key); std::string logger_get_identifier(std::string key);
std::string zstd_decompress(const std::string &in);
+1
View File
@@ -56,6 +56,7 @@ public:
const EncoderInfo main_road_encoder_info = { const EncoderInfo main_road_encoder_info = {
.publish_name = "roadEncodeData", .publish_name = "roadEncodeData",
.thumbnail_name = "thumbnail",
.filename = "fcamera.hevc", .filename = "fcamera.hevc",
INIT_ENCODE_FUNCTIONS(RoadEncode), INIT_ENCODE_FUNCTIONS(RoadEncode),
}; };
+1 -1
View File
@@ -106,7 +106,7 @@ class TestEncoder:
# Check encodeIdx # Check encodeIdx
if encode_idx_name is not None: if encode_idx_name is not None:
rlog_path = f"{route_prefix_path}--{i}/rlog" rlog_path = f"{route_prefix_path}--{i}/rlog.zst"
msgs = [m for m in LogReader(rlog_path) if m.which() == encode_idx_name] msgs = [m for m in LogReader(rlog_path) if m.which() == encode_idx_name]
encode_msgs = [getattr(m, encode_idx_name) for m in msgs] encode_msgs = [getattr(m, encode_idx_name) for m in msgs]
+3 -2
View File
@@ -9,12 +9,13 @@ void verify_segment(const std::string &route_path, int segment, int max_segment,
SentinelType end_sentinel = segment == max_segment - 1 ? SentinelType::END_OF_ROUTE : SentinelType::END_OF_SEGMENT; SentinelType end_sentinel = segment == max_segment - 1 ? SentinelType::END_OF_ROUTE : SentinelType::END_OF_SEGMENT;
REQUIRE(!util::file_exists(segment_path + "/rlog.lock")); REQUIRE(!util::file_exists(segment_path + "/rlog.lock"));
for (const char *fn : {"/rlog", "/qlog"}) { for (const char *fn : {"/rlog.zst", "/qlog.zst"}) {
const std::string log_file = segment_path + fn; const std::string log_file = segment_path + fn;
std::string log = util::read_file(log_file); std::string log = util::read_file(log_file);
REQUIRE(!log.empty()); REQUIRE(!log.empty());
std::string decompressed_log = zstd_decompress(log);
int event_cnt = 0, i = 0; int event_cnt = 0, i = 0;
kj::ArrayPtr<const capnp::word> words((capnp::word *)log.data(), log.size() / sizeof(capnp::word)); kj::ArrayPtr<const capnp::word> words((capnp::word *)decompressed_log.data(), decompressed_log.size() / sizeof(capnp::word));
while (words.size() > 0) { while (words.size() > 0) {
try { try {
capnp::FlatArrayMessageReader reader(words); capnp::FlatArrayMessageReader reader(words);
+3 -3
View File
@@ -142,7 +142,7 @@ class TestLoggerd:
Params().put("RecordFront", "1") Params().put("RecordFront", "1")
d = DEVICE_CAMERAS[("tici", "ar0231")] d = DEVICE_CAMERAS[("tici", "ar0231")]
expected_files = {"rlog", "qlog", "qcamera.ts", "fcamera.hevc", "dcamera.hevc", "ecamera.hevc"} expected_files = {"rlog.zst", "qlog.zst", "qcamera.ts", "fcamera.hevc", "dcamera.hevc", "ecamera.hevc"}
streams = [(VisionStreamType.VISION_STREAM_ROAD, (d.fcam.width, d.fcam.height, 2048*2346, 2048, 2048*1216), "roadCameraState"), streams = [(VisionStreamType.VISION_STREAM_ROAD, (d.fcam.width, d.fcam.height, 2048*2346, 2048, 2048*1216), "roadCameraState"),
(VisionStreamType.VISION_STREAM_DRIVER, (d.dcam.width, d.dcam.height, 2048*2346, 2048, 2048*1216), "driverCameraState"), (VisionStreamType.VISION_STREAM_DRIVER, (d.dcam.width, d.dcam.height, 2048*2346, 2048, 2048*1216), "driverCameraState"),
(VisionStreamType.VISION_STREAM_WIDE_ROAD, (d.ecam.width, d.ecam.height, 2048*2346, 2048, 2048*1216), "wideRoadCameraState")] (VisionStreamType.VISION_STREAM_WIDE_ROAD, (d.ecam.width, d.ecam.height, 2048*2346, 2048, 2048*1216), "wideRoadCameraState")]
@@ -229,7 +229,7 @@ class TestLoggerd:
random.sample(no_qlog_services, random.randint(2, min(10, len(no_qlog_services)))) random.sample(no_qlog_services, random.randint(2, min(10, len(no_qlog_services))))
sent_msgs = self._publish_random_messages(services) sent_msgs = self._publish_random_messages(services)
qlog_path = os.path.join(self._get_latest_log_dir(), "qlog") qlog_path = os.path.join(self._get_latest_log_dir(), "qlog.zst")
lr = list(LogReader(qlog_path)) lr = list(LogReader(qlog_path))
# check initData and sentinel # check initData and sentinel
@@ -255,7 +255,7 @@ class TestLoggerd:
services = random.sample(CEREAL_SERVICES, random.randint(5, 10)) services = random.sample(CEREAL_SERVICES, random.randint(5, 10))
sent_msgs = self._publish_random_messages(services) sent_msgs = self._publish_random_messages(services)
lr = list(LogReader(os.path.join(self._get_latest_log_dir(), "rlog"))) lr = list(LogReader(os.path.join(self._get_latest_log_dir(), "rlog.zst")))
# check initData and sentinel # check initData and sentinel
self._check_init_data(lr) self._check_init_data(lr)

Some files were not shown because too many files have changed in this diff Show More