mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-09-06 01:13:42 +08:00
Compare commits
203 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5360beb1ef | |||
| d0ab77cf2e | |||
| 50d7f75bfc | |||
| 15c7f52e40 | |||
| 8dfe04a318 | |||
| 9648ac2f04 | |||
| a03a11e333 | |||
| 53b1070b09 | |||
| 68bf6d8162 | |||
| 8b472291d0 | |||
| 797c8d4293 | |||
| 7568528507 | |||
| 6665c3acf6 | |||
| 3b13eb4d0d | |||
| f7eb4c2561 | |||
| be9255358c | |||
| f48ccb5d7a | |||
| 99559d6749 | |||
| 4b6f0ffb46 | |||
| 55415382ce | |||
| 9f30901eb6 | |||
| d2045d24fb | |||
| 6488a11e4d | |||
| 7b22b65313 | |||
| b59a50101e | |||
| 3e30962bd3 | |||
| 3274043063 | |||
| c624550d2e | |||
| 6759038671 | |||
| aa636e75c8 | |||
| 5ff3c3bd8d | |||
| 1e11b52290 | |||
| 76e0204025 | |||
| cc88f2cbd6 | |||
| ee0ac199a4 | |||
| d5ed828eaa | |||
| 9fca585f2a | |||
| bb1259303e | |||
| e135051ca8 | |||
| 12bef55d8a | |||
| 2f7a45e6c8 | |||
| 936ebfc12b | |||
| aa0c9dc0eb | |||
| 7476a866e7 | |||
| 610d857e33 | |||
| d2f47407d0 | |||
| db75ec76ea | |||
| 24066465d7 | |||
| a7abbd6e25 | |||
| 878982447c | |||
| 576527a36b | |||
| ef8c35da24 | |||
| 85688b1040 | |||
| 0fb2199130 | |||
| d48d756c1d | |||
| 2ed298a0c9 | |||
| d68f038949 | |||
| 7231571e57 | |||
| b37f1419d3 | |||
| cd85a66790 | |||
| 305ea87daf | |||
| 4bbfc793e0 | |||
| d5d983676e | |||
| de8a96a398 | |||
| 0cbf45f699 | |||
| 0d68a3a2ab | |||
| 9e85a85059 | |||
| 0373c327c0 | |||
| efe9e5c200 | |||
| 8a249a45dc | |||
| bdbefe67f6 | |||
| 675bb166ad | |||
| 1b717a7e88 | |||
| 86f55a8ba9 | |||
| 629392d2f7 | |||
| bc414bdc8b | |||
| 7ca5649f2c | |||
| 641ee8fa87 | |||
| 56c276158c | |||
| c65308a8bd | |||
| 994e526460 | |||
| 1defae36b7 | |||
| 8f029fd0ef | |||
| ddb46284dc | |||
| 9effc754d9 | |||
| e49ffc2a2d | |||
| 2cacd0b3e5 | |||
| c4b8859dff | |||
| 8fb0953205 | |||
| 63d1c8835f | |||
| 17a185606d | |||
| da10131392 | |||
| 7107c2ba14 | |||
| 95b6e877ac | |||
| eb02c6570e | |||
| 1be8ae31c4 | |||
| 04dcd38856 | |||
| 22ccf0d72f | |||
| 3c969bb627 | |||
| 20f8011feb | |||
| 9cf17e74a1 | |||
| 2c4efdf557 | |||
| 4cd3d3c16c | |||
| 637f3ae9c8 | |||
| 464ee80f71 | |||
| 2743a04613 | |||
| 7f9978d001 | |||
| 4b83961c67 | |||
| c00eaf428a | |||
| 0a9993e8d4 | |||
| 0af214a985 | |||
| af43385e3a | |||
| 0ab2b8c590 | |||
| 67ab18a0de | |||
| e87dc15b30 | |||
| 192d08516c | |||
| 3cf001c59c | |||
| f2ccd021da | |||
| c9fc900f64 | |||
| 3c37c5ce5d | |||
| 7c45889e4e | |||
| 2aabb7aee8 | |||
| 3859e9962f | |||
| 810efbab72 | |||
| ec27bec326 | |||
| 250d553157 | |||
| cea54a0ca8 | |||
| 8e72d783bd | |||
| 1b0dc103dc | |||
| 6c364d292b | |||
| bcdec2ce84 | |||
| 3deaeb3759 | |||
| c669f0984a | |||
| 46dd946740 | |||
| 9da4b3653e | |||
| 4e21ae7c50 | |||
| bb91e92237 | |||
| 14b4c4f85b | |||
| 0660b542c3 | |||
| 2b893b90c9 | |||
| f5139178ed | |||
| fb43b755f2 | |||
| 07f5b967d8 | |||
| ea19c7d3bb | |||
| e461842cbb | |||
| a73c9659d5 | |||
| cb796fbc76 | |||
| 6bf75fc557 | |||
| 9a1fc28819 | |||
| 0741d05e92 | |||
| 1ad008107d | |||
| feebd9df93 | |||
| c2e5ced3e5 | |||
| 15e5d2efb9 | |||
| a3929d0b54 | |||
| 794f8f9991 | |||
| 68fa5e3f21 | |||
| 86c6cc1f48 | |||
| eb7ffbf093 | |||
| 3919095752 | |||
| 74d63be1c3 | |||
| 8894486a1a | |||
| 810599315d | |||
| 6f3ab810c8 | |||
| 230f78b8d3 | |||
| f1affec088 | |||
| 97d8ef242c | |||
| a63fff9b45 | |||
| cb3893daaa | |||
| 29f60df74b | |||
| c6c072e1f4 | |||
| d101cbb83e | |||
| 1536d59633 | |||
| dc99b865ae | |||
| e59bc027ff | |||
| cf7e5efaca | |||
| 4b44f2eb31 | |||
| 107d2ab400 | |||
| 5432d9062c | |||
| f533f6c843 | |||
| 58e9ac763c | |||
| cb50d54169 | |||
| bd5de4ed0a | |||
| 0d4073fadb | |||
| ebc70dcb52 | |||
| 4d0426999e | |||
| 286da42573 | |||
| 8a836710a9 | |||
| 5d515bcf33 | |||
| 1c7f6d5133 | |||
| 05d57c7aeb | |||
| e4b0eaf352 | |||
| a710276472 | |||
| af086db671 | |||
| 0d9eb0e25e | |||
| 0616caed6d | |||
| 095337b3c1 | |||
| 1edec2d22c | |||
| affabb9ee0 | |||
| dc27e8711c | |||
| cf7329a264 | |||
| 5ee5ecd820 | |||
| b064f730dd |
@@ -0,0 +1,11 @@
|
||||
* @sunnypilot/dev-internal
|
||||
/.github/ @devtekve @sunnyhaibin
|
||||
/release/ci/ @devtekve @sunnyhaibin
|
||||
/tinygrad_repo @devtekve @Discountchubbs
|
||||
/tinygrad/ @devtekve @Discountchubbs
|
||||
/selfdrive/controls/lib/longitudinal_planner.py @devtekve @Discountchubbs
|
||||
/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @devtekve @Discountchubbs
|
||||
/selfdrive/modeld/ @devtekve @Discountchubbs
|
||||
/sunnypilot/model* @devtekve @Discountchubbs
|
||||
/sunnypilot/sunnylink/ @devtekve
|
||||
/system/athena/ @devtekve
|
||||
@@ -78,7 +78,6 @@ jobs:
|
||||
- name: Get next recompiled dir number
|
||||
id: create-recompiled-dir
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
||||
HF_REPO: ${{ github.event.inputs.hf_repo }}
|
||||
run: |
|
||||
pip install huggingface_hub
|
||||
|
||||
@@ -30,7 +30,6 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
model_name: ${{ steps.resolve.outputs.model_name }}
|
||||
safe_model_name: ${{ steps.resolve.outputs.safe_model_name }}
|
||||
onnx_ref: ${{ steps.resolve.outputs.onnx_ref }}
|
||||
onnx_path: ${{ steps.resolve.outputs.onnx_path }}
|
||||
hf_defaults_path: ${{ steps.resolve.outputs.hf_defaults_path }}
|
||||
@@ -65,9 +64,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SAFE_NAME="${NAME// /-}"
|
||||
echo "model_name=${NAME}" >> $GITHUB_OUTPUT
|
||||
echo "safe_model_name=${SAFE_NAME}" >> $GITHUB_OUTPUT
|
||||
echo "onnx_ref=${ONNX_REF}" >> $GITHUB_OUTPUT
|
||||
echo "onnx_path=${ONNX_PATH}" >> $GITHUB_OUTPUT
|
||||
echo "hf_defaults_path=${HF_DEFAULTS_PATH}" >> $GITHUB_OUTPUT
|
||||
@@ -138,7 +135,7 @@ jobs:
|
||||
|
||||
- name: Prepare output
|
||||
env:
|
||||
MODEL_NAME: ${{ needs.resolve.outputs.safe_model_name }}
|
||||
MODEL_NAME: ${{ needs.resolve.outputs.model_name }}
|
||||
run: |
|
||||
source ${UV_PROJECT_ENVIRONMENT}/bin/activate
|
||||
export PYTHONPATH=${{ github.workspace }}
|
||||
@@ -161,13 +158,13 @@ jobs:
|
||||
- name: Upload small model artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: model-${{ needs.resolve.outputs.safe_model_name }}-${{ github.run_number }}
|
||||
name: model-${{ needs.resolve.outputs.model_name }}-${{ github.run_number }}
|
||||
path: ${{ github.workspace }}/small_output/
|
||||
|
||||
- name: Upload artifact name file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifact-name-${{ needs.resolve.outputs.safe_model_name }}
|
||||
name: artifact-name-${{ needs.resolve.outputs.model_name }}
|
||||
path: ${{ github.workspace }}/small_output/artifact_name.txt
|
||||
|
||||
- name: Re-enable powersave
|
||||
@@ -257,7 +254,7 @@ jobs:
|
||||
|
||||
- name: Prepare output
|
||||
env:
|
||||
MODEL_NAME: ${{ needs.resolve.outputs.safe_model_name }}
|
||||
MODEL_NAME: ${{ needs.resolve.outputs.model_name }}
|
||||
run: |
|
||||
source ${UV_PROJECT_ENVIRONMENT}/bin/activate
|
||||
export PYTHONPATH=${{ github.workspace }}
|
||||
@@ -280,13 +277,13 @@ jobs:
|
||||
- name: Upload big model artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: model-${{ needs.resolve.outputs.safe_model_name }}-${{ github.run_number }}
|
||||
name: model-${{ needs.resolve.outputs.model_name }}-${{ github.run_number }}
|
||||
path: ${{ github.workspace }}/big_output/
|
||||
|
||||
- name: Upload artifact name file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifact-name-${{ needs.resolve.outputs.safe_model_name }}
|
||||
name: artifact-name-${{ needs.resolve.outputs.model_name }}
|
||||
path: ${{ github.workspace }}/big_output/artifact_name.txt
|
||||
|
||||
- name: Re-enable powersave
|
||||
@@ -321,7 +318,7 @@ jobs:
|
||||
if: ${{ inputs.target == 'small' || inputs.target == 'big' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: artifact-name-${{ needs.resolve.outputs.safe_model_name }}
|
||||
name: artifact-name-${{ needs.resolve.outputs.model_name }}
|
||||
path: artifact_name
|
||||
|
||||
- name: Read artifact name
|
||||
@@ -341,7 +338,7 @@ jobs:
|
||||
- name: Upload model to HF
|
||||
if: ${{ inputs.target == 'small' || inputs.target == 'big' }}
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
||||
HF_OIDC_RESOURCE: datasets/${{ env.HF_REPO }}
|
||||
ARTIFACT_NAME: ${{ steps.artifact.outputs.artifact_name }}
|
||||
run: |
|
||||
rm -f output/artifact_name.txt
|
||||
@@ -367,7 +364,7 @@ jobs:
|
||||
- name: Generate DM metadata and upload to HF
|
||||
if: ${{ inputs.target == 'dm' }}
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
||||
HF_OIDC_RESOURCE: datasets/${{ env.HF_REPO }}
|
||||
run: |
|
||||
export PYTHONPATH=$(pwd)
|
||||
python3 -c "
|
||||
@@ -484,29 +481,11 @@ jobs:
|
||||
print(f'Chunked {pkl} into {len(targets)} chunks')
|
||||
"
|
||||
|
||||
- name: Compile DM warp
|
||||
run: |
|
||||
source ${UV_PROJECT_ENVIRONMENT}/bin/activate
|
||||
export PYTHONPATH="${PYTHONPATH}:${{ github.workspace }}/tinygrad_repo:${{ github.workspace }}"
|
||||
|
||||
TG_FLAGS="DEV=QCOM IMAGE=1 FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 OPENPILOT_HACKS=1"
|
||||
MODEL_DIR="${{ github.workspace }}/openpilot/selfdrive/modeld"
|
||||
DM_SIZE=$(python3 -c "from openpilot.common.transformations.model import DM_INPUT_SIZE as s; print(f'{s[0]}x{s[1]}')")
|
||||
|
||||
for res in $(python3 -c "from openpilot.common.transformations.camera import _ar_ox_fisheye as a, _os_fisheye as o; print(f'{a.width}x{a.height} {o.width}x{o.height}')"); do
|
||||
WARP_PKL="${MODEL_DIR}/models/dm_warp_${res}_tinygrad.pkl"
|
||||
taskset -c 7 env ${TG_FLAGS} python3 ${MODEL_DIR}/compile_dm_warp.py \
|
||||
--camera-resolution ${res} \
|
||||
--warp-to ${DM_SIZE} \
|
||||
--output ${WARP_PKL}
|
||||
done
|
||||
|
||||
- name: Prepare DM output
|
||||
run: |
|
||||
mkdir -p dm_output
|
||||
cp ${{ github.workspace }}/${{ env.DM_PKL }}.chunk* dm_output/
|
||||
cp ${{ github.workspace }}/${{ env.DM_PKL }}.chunkmanifest dm_output/
|
||||
cp ${{ github.workspace }}/openpilot/selfdrive/modeld/models/dm_warp_* dm_output/
|
||||
|
||||
- name: Upload DM artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
|
||||
- name: Validate hf_repo and JSON version
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
||||
HF_OIDC_RESOURCE: datasets/${{ inputs.hf_repo }}
|
||||
run: |
|
||||
if [ ! -f "$JSON_FILE" ]; then
|
||||
echo "JSON file $JSON_FILE does not exist!"
|
||||
@@ -155,8 +155,13 @@ jobs:
|
||||
python3 -c "
|
||||
import sys
|
||||
from huggingface_hub import HfApi
|
||||
HfApi().repo_info(repo_id=sys.argv[1], repo_type='dataset')
|
||||
print(f'Success: Repo {sys.argv[1]} exists.')
|
||||
try:
|
||||
api = HfApi()
|
||||
api.repo_info(repo_id=sys.argv[1], repo_type='dataset')
|
||||
print(f'Success: Repo {sys.argv[1]} exists.')
|
||||
except Exception as e:
|
||||
print('HF validation failed:', e)
|
||||
sys.exit(1)
|
||||
" "${{ inputs.hf_repo }}"
|
||||
|
||||
- name: Download artifact name file
|
||||
@@ -187,7 +192,7 @@ jobs:
|
||||
|
||||
- name: Upload to Hugging Face
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
||||
HF_OIDC_RESOURCE: datasets/${{ inputs.hf_repo }}
|
||||
ARTIFACT_NAME: ${{ steps.read-artifact-name.outputs.artifact_name }}
|
||||
run: |
|
||||
hf upload ${{ inputs.hf_repo }} \
|
||||
|
||||
@@ -46,13 +46,6 @@ runs:
|
||||
printf '%s\t%s\n' "$ENCODED_URL" "${DEST_DIR}/${CANONICAL}.chunk${CHUNK_IDX}" >> "$DOWNLOAD_LIST"
|
||||
done < <(echo "$ARTIFACT" | jq -r '.chunks[].file_name')
|
||||
echo "$NUM_CHUNKS" > "${DEST_DIR}/${CANONICAL}.chunkmanifest"
|
||||
|
||||
if [ "$CANONICAL" = "dmonitoring_model_tinygrad.pkl" ]; then
|
||||
for warp in dm_warp_1928x1208_tinygrad.pkl dm_warp_1344x760_tinygrad.pkl; do
|
||||
ENCODED_URL=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${BASE_URL}/${warp}', safe=':/'))")
|
||||
printf '%s\t%s\n' "$ENCODED_URL" "${DEST_DIR}/${warp}" >> "$DOWNLOAD_LIST"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
echo "$MODELS_JSON" | jq -c '.[]' | while IFS= read -r model; do
|
||||
|
||||
@@ -188,7 +188,7 @@ jobs:
|
||||
if [ "${{ inputs.target_hardware }}" == "chestnut" ]; then
|
||||
echo "CHESTNUT build"
|
||||
export CHESTNUT=1
|
||||
TG_FLAGS="DEBUG=1 DEV=USB+AMD:LLVM FLOAT16=1 JIT_BATCH_SIZE=0 GMMU=0 TC_OPT=2"
|
||||
TG_FLAGS="DEBUG=1 DEV=USB+AMD:LLVM WARP_DEV=QCOM FLOAT16=1 JIT_BATCH_SIZE=0 GMMU=0 TC_OPT=2"
|
||||
OUTPUT_PKL="${{ env.MODELS_DIR }}/big_driving_tinygrad.pkl"
|
||||
else
|
||||
echo "QCOM build"
|
||||
|
||||
@@ -216,9 +216,6 @@ jobs:
|
||||
needs: [ prepare_strategy ]
|
||||
runs-on: ubuntu-24.04
|
||||
if: ${{ needs.prepare_strategy.outputs.include_big_model == 'true' }}
|
||||
concurrency:
|
||||
group: prepare-chestnut
|
||||
cancel-in-progress: false
|
||||
outputs:
|
||||
onnx_sha256: ${{ steps.resolve.outputs.onnx_sha256 }}
|
||||
env:
|
||||
@@ -231,10 +228,8 @@ jobs:
|
||||
run: |
|
||||
REF="${{ github.head_ref || github.ref_name }}"
|
||||
|
||||
BLOB_SHA=$(gh api "repos/${GH_REPO}/contents/openpilot/selfdrive/modeld/models/big_driving_supercombo.onnx?ref=${REF}" --jq '.sha')
|
||||
ONNX_HASH=$(gh api "repos/${GH_REPO}/git/blobs/${BLOB_SHA}" --jq '.content' | base64 -d | grep '^oid sha256:' | cut -d: -f2)
|
||||
ONNX_HASH=$(gh api "repos/${GH_REPO}/contents/openpilot/selfdrive/modeld/models/big_driving_supercombo.onnx?ref=${REF}" --jq '.content' | base64 -d | grep '^oid sha256:' | cut -d: -f2)
|
||||
echo "ONNX hash: $ONNX_HASH"
|
||||
[ -n "$ONNX_HASH" ] || { echo "::error::Failed to extract ONNX hash"; exit 1; }
|
||||
echo "onnx_sha256=$ONNX_HASH" >> $GITHUB_OUTPUT
|
||||
|
||||
TINYGRAD_REF=$(gh api "repos/${GH_REPO}/contents/tinygrad_repo?ref=${REF}" --jq '.sha')
|
||||
@@ -243,7 +238,7 @@ jobs:
|
||||
JSON_URL="https://huggingface.co/datasets/${HF_REPO}/resolve/main/${HF_DEFAULTS_PATH}/default_models.json"
|
||||
|
||||
check_defaults() {
|
||||
DEFAULTS=$(curl -fsSL "${JSON_URL}?t=$(date +%s)" 2>/dev/null) || return 1
|
||||
DEFAULTS=$(curl -fsSL "$JSON_URL" 2>/dev/null) || return 1
|
||||
TINYGRAD_MATCH=$(echo "$DEFAULTS" | jq -r --arg ref "$TINYGRAD_REF" '.tinygrad_ref == $ref' 2>/dev/null)
|
||||
[ "$TINYGRAD_MATCH" = "true" ] || return 1
|
||||
BUNDLE=$(echo "$DEFAULTS" | jq --arg hash "$ONNX_HASH" '.bundles[] | select(.onnx_sha256 == $hash)' 2>/dev/null)
|
||||
@@ -257,35 +252,18 @@ jobs:
|
||||
|
||||
echo "No matching model on HF — dispatching build"
|
||||
gh workflow run build-default-models.yaml --ref "$REF" -f target=big
|
||||
sleep 10
|
||||
|
||||
BUILD_RUN_ID=$(gh run list --workflow build-default-models.yaml --branch "$REF" --limit 1 --json databaseId --jq '.[0].databaseId')
|
||||
echo "Dispatched build run: $BUILD_RUN_ID"
|
||||
|
||||
echo "Waiting for build run to complete..."
|
||||
echo "Polling HF for big model availability..."
|
||||
for i in $(seq 1 90); do
|
||||
sleep 30
|
||||
STATUS=$(gh api "repos/${GH_REPO}/actions/runs/${BUILD_RUN_ID}" --jq '.status')
|
||||
CONCLUSION=$(gh api "repos/${GH_REPO}/actions/runs/${BUILD_RUN_ID}" --jq '.conclusion')
|
||||
echo "Poll $i/90: status=$STATUS conclusion=$CONCLUSION"
|
||||
if [ "$STATUS" = "completed" ]; then
|
||||
if [ "$CONCLUSION" = "success" ]; then
|
||||
echo "Build run succeeded, verifying HF..."
|
||||
sleep 10
|
||||
if check_defaults; then
|
||||
echo "Big model verified on HF"
|
||||
exit 0
|
||||
fi
|
||||
echo "::error::Build succeeded but model not found on HF"
|
||||
exit 1
|
||||
else
|
||||
echo "::error::Build run failed with conclusion=$CONCLUSION"
|
||||
exit 1
|
||||
fi
|
||||
if check_defaults; then
|
||||
echo "Big model available on HF after $((i * 30))s"
|
||||
exit 0
|
||||
fi
|
||||
echo "Poll $i/90: not yet available"
|
||||
done
|
||||
|
||||
echo "::error::Build run did not complete within 45 minutes"
|
||||
echo "::error::Big model not available on HF after 45 minutes"
|
||||
exit 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -299,9 +277,6 @@ jobs:
|
||||
prepare_small_model:
|
||||
needs: [ prepare_strategy ]
|
||||
runs-on: ubuntu-24.04
|
||||
concurrency:
|
||||
group: prepare-small-model
|
||||
cancel-in-progress: false
|
||||
outputs:
|
||||
driving_onnx_sha256: ${{ steps.resolve.outputs.driving_onnx_sha256 }}
|
||||
env:
|
||||
@@ -314,10 +289,8 @@ jobs:
|
||||
run: |
|
||||
REF="${{ github.head_ref || github.ref_name }}"
|
||||
|
||||
BLOB_SHA=$(gh api "repos/${GH_REPO}/contents/openpilot/selfdrive/modeld/models/driving_supercombo.onnx?ref=${REF}" --jq '.sha')
|
||||
DRIVING_HASH=$(gh api "repos/${GH_REPO}/git/blobs/${BLOB_SHA}" --jq '.content' | base64 -d | grep '^oid sha256:' | cut -d: -f2)
|
||||
DRIVING_HASH=$(gh api "repos/${GH_REPO}/contents/openpilot/selfdrive/modeld/models/driving_supercombo.onnx?ref=${REF}" --jq '.content' | base64 -d | grep '^oid sha256:' | cut -d: -f2)
|
||||
echo "Driving ONNX hash: $DRIVING_HASH"
|
||||
[ -n "$DRIVING_HASH" ] || { echo "::error::Failed to extract driving ONNX hash"; exit 1; }
|
||||
echo "driving_onnx_sha256=$DRIVING_HASH" >> $GITHUB_OUTPUT
|
||||
|
||||
TINYGRAD_REF=$(gh api "repos/${GH_REPO}/contents/tinygrad_repo?ref=${REF}" --jq '.sha')
|
||||
@@ -326,7 +299,7 @@ jobs:
|
||||
JSON_URL="https://huggingface.co/datasets/${HF_REPO}/resolve/main/${HF_DEFAULTS_PATH}/default_models.json"
|
||||
|
||||
check_defaults() {
|
||||
DEFAULTS=$(curl -fsSL "${JSON_URL}?t=$(date +%s)" 2>/dev/null) || return 1
|
||||
DEFAULTS=$(curl -fsSL "$JSON_URL" 2>/dev/null) || return 1
|
||||
TINYGRAD_MATCH=$(echo "$DEFAULTS" | jq -r --arg ref "$TINYGRAD_REF" '.tinygrad_ref == $ref' 2>/dev/null)
|
||||
[ "$TINYGRAD_MATCH" = "true" ] || return 1
|
||||
DRIVING=$(echo "$DEFAULTS" | jq --arg hash "$DRIVING_HASH" '.bundles[] | select(.onnx_sha256 == $hash)' 2>/dev/null)
|
||||
@@ -340,35 +313,18 @@ jobs:
|
||||
|
||||
echo "No matching model on HF — dispatching build"
|
||||
gh workflow run build-default-models.yaml --ref "$REF" -f target=small
|
||||
sleep 10
|
||||
|
||||
BUILD_RUN_ID=$(gh run list --workflow build-default-models.yaml --branch "$REF" --limit 1 --json databaseId --jq '.[0].databaseId')
|
||||
echo "Dispatched build run: $BUILD_RUN_ID"
|
||||
|
||||
echo "Waiting for build run to complete..."
|
||||
echo "Polling HF for model availability..."
|
||||
for i in $(seq 1 60); do
|
||||
sleep 30
|
||||
STATUS=$(gh api "repos/${GH_REPO}/actions/runs/${BUILD_RUN_ID}" --jq '.status')
|
||||
CONCLUSION=$(gh api "repos/${GH_REPO}/actions/runs/${BUILD_RUN_ID}" --jq '.conclusion')
|
||||
echo "Poll $i/60: status=$STATUS conclusion=$CONCLUSION"
|
||||
if [ "$STATUS" = "completed" ]; then
|
||||
if [ "$CONCLUSION" = "success" ]; then
|
||||
echo "Build run succeeded, verifying HF..."
|
||||
sleep 10
|
||||
if check_defaults; then
|
||||
echo "Small model verified on HF"
|
||||
exit 0
|
||||
fi
|
||||
echo "::error::Build succeeded but model not found on HF"
|
||||
exit 1
|
||||
else
|
||||
echo "::error::Build run failed with conclusion=$CONCLUSION"
|
||||
exit 1
|
||||
fi
|
||||
if check_defaults; then
|
||||
echo "Model available on HF after $((i * 30))s"
|
||||
exit 0
|
||||
fi
|
||||
echo "Poll $i/60: not yet available"
|
||||
done
|
||||
|
||||
echo "::error::Small model build did not complete within 30 minutes"
|
||||
echo "::error::Small driving model not available on HF after 30 minutes"
|
||||
exit 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -382,9 +338,6 @@ jobs:
|
||||
prepare_dm_model:
|
||||
needs: [ prepare_strategy ]
|
||||
runs-on: ubuntu-24.04
|
||||
concurrency:
|
||||
group: prepare-dm-model
|
||||
cancel-in-progress: false
|
||||
outputs:
|
||||
dm_onnx_sha256: ${{ steps.resolve.outputs.dm_onnx_sha256 }}
|
||||
env:
|
||||
@@ -397,10 +350,8 @@ jobs:
|
||||
run: |
|
||||
REF="${{ github.head_ref || github.ref_name }}"
|
||||
|
||||
BLOB_SHA=$(gh api "repos/${GH_REPO}/contents/openpilot/selfdrive/modeld/models/dmonitoring_model.onnx?ref=${REF}" --jq '.sha')
|
||||
DM_HASH=$(gh api "repos/${GH_REPO}/git/blobs/${BLOB_SHA}" --jq '.content' | base64 -d | grep '^oid sha256:' | cut -d: -f2)
|
||||
DM_HASH=$(gh api "repos/${GH_REPO}/contents/openpilot/selfdrive/modeld/models/dmonitoring_model.onnx?ref=${REF}" --jq '.content' | base64 -d | grep '^oid sha256:' | cut -d: -f2)
|
||||
echo "DM ONNX hash: $DM_HASH"
|
||||
[ -n "$DM_HASH" ] || { echo "::error::Failed to extract DM ONNX hash"; exit 1; }
|
||||
echo "dm_onnx_sha256=$DM_HASH" >> $GITHUB_OUTPUT
|
||||
|
||||
TINYGRAD_REF=$(gh api "repos/${GH_REPO}/contents/tinygrad_repo?ref=${REF}" --jq '.sha')
|
||||
@@ -409,7 +360,7 @@ jobs:
|
||||
JSON_URL="https://huggingface.co/datasets/${HF_REPO}/resolve/main/${HF_DEFAULTS_PATH}/default_models.json"
|
||||
|
||||
check_defaults() {
|
||||
DEFAULTS=$(curl -fsSL "${JSON_URL}?t=$(date +%s)" 2>/dev/null) || return 1
|
||||
DEFAULTS=$(curl -fsSL "$JSON_URL" 2>/dev/null) || return 1
|
||||
TINYGRAD_MATCH=$(echo "$DEFAULTS" | jq -r --arg ref "$TINYGRAD_REF" '.tinygrad_ref == $ref' 2>/dev/null)
|
||||
[ "$TINYGRAD_MATCH" = "true" ] || return 1
|
||||
DM=$(echo "$DEFAULTS" | jq --arg hash "$DM_HASH" '.bundles[] | select(.onnx_sha256 == $hash)' 2>/dev/null)
|
||||
@@ -423,35 +374,18 @@ jobs:
|
||||
|
||||
echo "No matching DM model on HF — dispatching build"
|
||||
gh workflow run build-default-models.yaml --ref "$REF" -f target=dm
|
||||
sleep 10
|
||||
|
||||
BUILD_RUN_ID=$(gh run list --workflow build-default-models.yaml --branch "$REF" --limit 1 --json databaseId --jq '.[0].databaseId')
|
||||
echo "Dispatched build run: $BUILD_RUN_ID"
|
||||
|
||||
echo "Waiting for build run to complete..."
|
||||
echo "Polling HF for DM model availability..."
|
||||
for i in $(seq 1 60); do
|
||||
sleep 30
|
||||
STATUS=$(gh api "repos/${GH_REPO}/actions/runs/${BUILD_RUN_ID}" --jq '.status')
|
||||
CONCLUSION=$(gh api "repos/${GH_REPO}/actions/runs/${BUILD_RUN_ID}" --jq '.conclusion')
|
||||
echo "Poll $i/60: status=$STATUS conclusion=$CONCLUSION"
|
||||
if [ "$STATUS" = "completed" ]; then
|
||||
if [ "$CONCLUSION" = "success" ]; then
|
||||
echo "Build run succeeded, verifying HF..."
|
||||
sleep 10
|
||||
if check_defaults; then
|
||||
echo "DM model verified on HF"
|
||||
exit 0
|
||||
fi
|
||||
echo "::error::Build succeeded but DM model not found on HF"
|
||||
exit 1
|
||||
else
|
||||
echo "::error::Build run failed with conclusion=$CONCLUSION"
|
||||
exit 1
|
||||
fi
|
||||
if check_defaults; then
|
||||
echo "DM model available on HF after $((i * 30))s"
|
||||
exit 0
|
||||
fi
|
||||
echo "Poll $i/60: not yet available"
|
||||
done
|
||||
|
||||
echo "::error::DM model build did not complete within 30 minutes"
|
||||
echo "::error::DM model not available on HF after 30 minutes"
|
||||
exit 1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
+1
-1
Submodule opendbc_repo updated: f95f996f59...0819b0e8e0
@@ -41,6 +41,7 @@ from tinygrad.tensor import Tensor
|
||||
MODEL_TYPES = ('vision_policy', 'supercombo', 'vision_multi_policy')
|
||||
WARP_INPUTS = ['tfm', 'big_tfm']
|
||||
POLICY_INPUTS = ['img_q', 'big_img_q', 'feat_q', 'desire_q', 'packed_npy_inputs']
|
||||
WARP_DEV = os.getenv('WARP_DEV')
|
||||
|
||||
|
||||
def _detect_desire_key(shapes: dict) -> str | None:
|
||||
@@ -153,10 +154,11 @@ def make_warp_queues(device=Device.DEFAULT):
|
||||
|
||||
def make_warp(nv12: NV12Frame, model_w: int, model_h: int):
|
||||
frame_prepare = make_frame_prepare(nv12, model_w, model_h)
|
||||
WARP_DEV = os.getenv('WARP_DEV', Device.DEFAULT)
|
||||
|
||||
def warp(tfm, big_tfm, frame, big_frame):
|
||||
tfm = tfm.to(Device.DEFAULT)
|
||||
big_tfm = big_tfm.to(Device.DEFAULT)
|
||||
tfm = tfm.to(WARP_DEV)
|
||||
big_tfm = big_tfm.to(WARP_DEV)
|
||||
Tensor.realize(tfm, big_tfm)
|
||||
|
||||
warped_frame = frame_prepare(frame, tfm).unsqueeze(0)
|
||||
@@ -366,18 +368,16 @@ if __name__ == "__main__":
|
||||
run_policy_func = make_run_policy(vision_runner, policy_runners, features_slice, derived_frame_skip, all_shapes)
|
||||
run_policy_jit = TinyJit(run_policy_func, prune=True)
|
||||
make_policy_queues = partial(generate_queues_and_npy, all_shapes, derived_frame_skip, is_supercombo=is_supercombo)
|
||||
make_random_model_inputs = partial(make_random_images, keys=['warped'], shape=(2, 6, model_h // 2, model_w // 2), device=Device.DEFAULT)
|
||||
make_random_model_inputs = partial(make_random_images, keys=['warped'], shape=(2, 6, model_h // 2, model_w // 2), device=WARP_DEV)
|
||||
output_data['run_policy'] = compile_jit(run_policy_jit, make_random_model_inputs, POLICY_INPUTS, make_policy_queues)
|
||||
|
||||
for cam_w, cam_h in args.camera_resolutions:
|
||||
print(f"Compiling warp JIT for {cam_w}x{cam_h}...")
|
||||
nv12 = NV12Frame(cam_w, cam_h, *get_nv12_info(cam_w, cam_h))
|
||||
make_random_warp_inputs = partial(make_random_images, keys=['frame', 'big_frame'], shape=nv12.size, device=Device.DEFAULT)
|
||||
make_random_warp_inputs = partial(make_random_images, keys=['frame', 'big_frame'], shape=nv12.size, device=WARP_DEV)
|
||||
warp = TinyJit(make_warp(nv12, model_w, model_h), prune=True)
|
||||
output_data[(cam_w, cam_h)] = compile_jit(warp, make_random_warp_inputs, WARP_INPUTS, make_warp_queues)
|
||||
|
||||
output_data['metadata']['warp_dev'] = Device.DEFAULT
|
||||
|
||||
with open(args.output, "wb") as file:
|
||||
dump_oob(output_data, file)
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ This file is part of sunnypilot and is licensed under the MIT License.
|
||||
See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
|
||||
from collections.abc import Callable
|
||||
import os
|
||||
os.environ['GMMU'] = '0'
|
||||
import numpy as np
|
||||
@@ -111,12 +110,18 @@ class ModelState(ModelStateBase):
|
||||
cloudlog.warning(f"loading combined pkl: {pkl_path}")
|
||||
jits = load_oob(open_file_chunked(pkl_path))
|
||||
|
||||
metadata = jits['metadata']
|
||||
self.WARP_DEV = metadata.get('warp_dev', 'QCOM' if COMMA_HARDWARE else 'CPU')
|
||||
self.DEV = 'AMD' if self.chestnut else ('QCOM' if COMMA_HARDWARE else 'CPU')
|
||||
self.WARP_DEV = 'QCOM' if COMMA_HARDWARE else 'CPU'
|
||||
self.DEV = 'AMD' if self.chestnut else self.WARP_DEV
|
||||
self.QUEUE_DEV = self.DEV
|
||||
self.run_policy = jits['run_policy']
|
||||
self.warp = jits[(cam_w, cam_h)]
|
||||
metadata = jits['metadata']
|
||||
|
||||
self.is_legacy_model = 'run_policy' not in jits # remove after next recompile
|
||||
if self.is_legacy_model:
|
||||
self.warp = jits[(cam_w, cam_h)]['warp_enqueue']
|
||||
self.run_policy = jits[(cam_w, cam_h)]['run_policy']
|
||||
else:
|
||||
self.run_policy = jits['run_policy']
|
||||
self.warp = jits[(cam_w, cam_h)]
|
||||
|
||||
if 'model' in metadata:
|
||||
model_metadata = metadata['model']
|
||||
@@ -175,7 +180,11 @@ class ModelState(ModelStateBase):
|
||||
yuv_size = self.frame_buf_params[self._road_key][3]
|
||||
frame_tensor = Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.WARP_DEV).contiguous().realize()
|
||||
big_frame_tensor = Tensor(np.zeros(yuv_size, dtype=np.uint8), device=self.WARP_DEV).contiguous().realize()
|
||||
self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=frame_tensor, big_frame=big_frame_tensor)
|
||||
|
||||
if self.is_legacy_model: # Remove this conditional hack after recompile
|
||||
self.warp(**self.input_queues, frame=frame_tensor, big_frame=big_frame_tensor)
|
||||
else:
|
||||
self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=frame_tensor, big_frame=big_frame_tensor)
|
||||
|
||||
def warmup(self) -> None:
|
||||
dummy_frames = {k: np.zeros(self.frame_buf_params[k][3], dtype=np.uint8) for k in self._vision_input_names}
|
||||
@@ -208,8 +217,7 @@ class ModelState(ModelStateBase):
|
||||
return self._desire_key
|
||||
|
||||
def run(self, bufs: dict[str, VisionBuf], transforms: dict[str, np.ndarray],
|
||||
inputs: dict[str, np.ndarray], prepare_only: bool,
|
||||
after_enqueue: Callable[[], None] | None = None) -> dict[str, np.ndarray] | None:
|
||||
inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None:
|
||||
for key in bufs.keys():
|
||||
ptr = np.frombuffer(bufs[key].data, dtype=np.uint8).ctypes.data
|
||||
yuv_size = self.frame_buf_params[key][3]
|
||||
@@ -231,18 +239,20 @@ class ModelState(ModelStateBase):
|
||||
self.numpy_inputs['tfm'][:, :] = transforms[road_key].reshape(3, 3)
|
||||
self.numpy_inputs['big_tfm'][:, :] = transforms[wide_key].reshape(3, 3)
|
||||
|
||||
if prepare_only:
|
||||
self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=self.full_frames[road_key], big_frame=self.full_frames[wide_key])
|
||||
return None
|
||||
warped = self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=self.full_frames[road_key], big_frame=self.full_frames[wide_key])
|
||||
raw_outputs = self.run_policy(**{k: self.input_queues[k] for k in POLICY_INPUTS if k in self.input_queues}, warped=warped)
|
||||
if after_enqueue is not None:
|
||||
after_enqueue()
|
||||
if self.is_legacy_model: # remove after next recompile
|
||||
if prepare_only:
|
||||
self.warp(**self.input_queues, frame=self.full_frames[road_key], big_frame=self.full_frames[wide_key])
|
||||
return None
|
||||
raw_outputs = self.run_policy(**self.input_queues, frame=self.full_frames[road_key], big_frame=self.full_frames[wide_key])
|
||||
else:
|
||||
if prepare_only:
|
||||
self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=self.full_frames[road_key], big_frame=self.full_frames[wide_key])
|
||||
return None
|
||||
warped = self.warp(**{k: self.input_queues[k] for k in WARP_INPUTS}, frame=self.full_frames[road_key], big_frame=self.full_frames[wide_key])
|
||||
raw_outputs = self.run_policy(**{k: self.input_queues[k] for k in POLICY_INPUTS if k in self.input_queues}, warped=warped)
|
||||
|
||||
if self._combined_model_type == 'supercombo':
|
||||
model_output = raw_outputs.numpy().flatten()
|
||||
if self.chestnut and not np.all(np.isfinite(model_output)):
|
||||
raise RuntimeError("model output not finite")
|
||||
sliced = {k: model_output[np.newaxis, v] for k, v in self.vision_output_slices.items()}
|
||||
outputs = self.parser.parse_outputs(sliced)
|
||||
if 'prev_feat' in self.numpy_inputs:
|
||||
@@ -275,6 +285,9 @@ class ModelState(ModelStateBase):
|
||||
buf[0, :-1] = buf[0, 1:]
|
||||
buf[0, -1, :] = outputs['desired_curvature'][0, :] if not self.mlsim else 0
|
||||
|
||||
if self.chestnut and not np.all(np.isfinite(outputs.get('plan', np.array([0.])))):
|
||||
raise RuntimeError("model output not finite")
|
||||
|
||||
return outputs
|
||||
|
||||
def get_action_from_model(self, model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action,
|
||||
@@ -499,9 +512,7 @@ def main(demo=False):
|
||||
|
||||
mt1 = time.perf_counter()
|
||||
try:
|
||||
send_chestnut = (chestnut_state is not None and
|
||||
run_count % round(model.constants.MODEL_FREQ / SERVICE_LIST['chestnutState'].frequency) == 0)
|
||||
model_output = model.run(bufs, transforms, inputs, prepare_only, chestnut_state.send if send_chestnut else None)
|
||||
model_output = model.run(bufs, transforms, inputs, prepare_only)
|
||||
except Exception:
|
||||
if not params.get_bool("ChestnutActive"):
|
||||
raise
|
||||
@@ -548,6 +559,9 @@ def main(demo=False):
|
||||
pm.send('modelDataV2SP', mdv2sp_send)
|
||||
last_vipc_frame_id = meta_main.frame_id
|
||||
|
||||
if chestnut_state is not None and run_count % round(model.constants.MODEL_FREQ / SERVICE_LIST['chestnutState'].frequency) == 0:
|
||||
chestnut_state.send()
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
import argparse
|
||||
|
||||
@@ -139,7 +139,7 @@ class ModelCache:
|
||||
class ModelFetcher:
|
||||
"""Handles fetching and caching of model data from remote source"""
|
||||
MODEL_URL = "https://raw.githubusercontent.com/sunnypilot/sunnypilot-models/refs/heads/gh-pages/docs/driving_models_v22.json"
|
||||
MODEL_URL_CHESTNUT = "https://raw.githubusercontent.com/sunnypilot/sunnypilot-models/refs/heads/gh-pages/docs/driving_models_chestnut_v24.json"
|
||||
MODEL_URL_CHESTNUT = "https://raw.githubusercontent.com/sunnypilot/sunnypilot-models/refs/heads/gh-pages/docs/driving_models_chestnut_v23.json"
|
||||
|
||||
MODEL_SOURCES = {
|
||||
"qcom": (MODEL_URL, ""),
|
||||
|
||||
+1
-1
Submodule panda updated: 74a0adced4...42643dec15
@@ -38,8 +38,7 @@ def main():
|
||||
api = HfApi()
|
||||
onnx_sha256 = hash_file(args.onnx_path)
|
||||
short_ref = args.onnx_ref[:8]
|
||||
safe_name = args.model_name.replace(" ", "-")
|
||||
folder_name = f"model-{safe_name}-{short_ref}-{args.run_number}"
|
||||
folder_name = f"model-{args.model_name}-{short_ref}-{args.run_number}"
|
||||
|
||||
print(f"ONNX hash: {onnx_sha256}")
|
||||
print(f"ONNX ref: {args.onnx_ref} (short: {short_ref})")
|
||||
|
||||
Reference in New Issue
Block a user