14 KiB
IQPilot Model Compile Guide
This guide documents the current, working IQPilot flow for compiling and publishing tinygrad supercombo model artifacts for comma 3X/4 class devices.
It is written to be usable by either a human operator or another agent without needing outside context.
Scope
This guide covers:
- compiling
supercomboONNX models into prebuiltQCOMtinygrad.pklartifacts - matching IQPilot's current pinned compile path
- validating artifacts on-device before publishing
- updating the
IQModelsrepo and selector manifests - common failure modes seen in current IQPilot
This guide is specifically for the current IQPilot model stack:
- compiler script: iqpilot/selfdrive/iqmodeld/tools/compile_supercombo.py
- runtime: iqpilot/selfdrive/iqmodeld/daemon.py
- tinygrad compile flags: iqpilot/selfdrive/iqmodeld/SConscript
- on-device harness: iqpilot/selfdrive/iqmodeld/tools/force_onroad_iqmodeld_test.py
Current Known-Good QCOM Compile Flags
IQPilot should compile QCOM supercombo artifacts with the same important flags stock openpilot uses for the proven QCOM tinygrad path:
DEV=QCOM
WARP_DEV=QCOM
IMAGE=2
FLOAT16=1
NOLOCALS=1
JIT_BATCH_SIZE=0
OPENPILOT_HACKS=1
The critical correction was OPENPILOT_HACKS=1.
Without that, models can compile into artifacts that look valid but behave differently from stock openpilot builds, including:
- PoseNET/JIT shape mismatches
- freezes when going onroad
iqmodelddeath or stall after model startup- artifacts that drive on stock but fail on IQPilot
Current Expected Device Context
These instructions assume:
- IQPilot lives at
/data/openpilot - the repo on your Mac is
/Users/t/Developer/iqpilot/iqpilot - the target device is reachable over SSH as
iq@<ip> - the device has a working venv at
/usr/local/venv - tinygrad is available under
/data/openpilot/tinygrad_repo
If your paths differ, adjust the commands accordingly.
1. Confirm IQPilot Source Is Using the Correct Flags
Before compiling anything, verify iqpilot/selfdrive/iqmodeld/SConscript is returning the current QCOM flags for larch64.
The effective flag set for the QCOM path should include:
DEV=QCOM IMAGE=2 FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 OPENPILOT_HACKS=1
If you edit the file locally, copy it to the device before recompiling:
scp /Users/t/Developer/iqpilot/iqpilot/iqpilot/selfdrive/iqmodeld/SConscript \
iq@<ip>:/data/openpilot/iqpilot/selfdrive/iqmodeld/SConscript
2. Identify the Source ONNX and Target Artifact Name
For each model, determine:
- source ONNX file
- published artifact filename
- selector entry in
IQModels
Examples from recent working flow:
TobyRL- source:
driving_supercombo.onnx - artifact:
driving_supercombo_tobyrl.pkl
- source:
NoPP- source:
driving_supercombo.onnx - artifact:
driving_supercombo_nopp.pkl
- source:
DRLV3- source:
driving_supercombo.onnx - artifact:
driving_supercombo_drl3.pkl
- source:
3. Copy the Source ONNX to the Device
Copy the chosen ONNX to a neutral working path on-device:
scp /path/to/driving_supercombo.onnx \
iq@<ip>:/data/media/0/driving_supercombo_<name>_source.onnx
Example:
scp '/Volumes/New New Vault/IQModels/models/recompiled16/model-No PP (June 26, 2026)-165/driving_supercombo.onnx' \
iq@192.168.173.10:/data/media/0/driving_supercombo_nopp_source.onnx
4. Prepare Writable Cache Directories on the Device
Do this once per session before compiling.
This avoids tinygrad falling back to unwritable root-owned cache paths and prevents failures caused by:
/root/.cachewrite problems- temporary directory permission failures
- unstable shell environments
ssh iq@<ip> "sudo mkdir -p /data/root-home /data/root-cache /data/root-uv-cache /data/root-tmp"
5. Compile the Model On-Device
Use the exact compile environment below.
This is the current known-good command:
ssh iq@<ip> "sudo env \
HOME=/data/root-home \
XDG_CACHE_HOME=/data/root-cache \
UV_CACHE_DIR=/data/root-uv-cache \
TMPDIR=/data/root-tmp \
PYTHONPATH=/data/openpilot:/data/openpilot/tinygrad_repo \
PATH=/usr/local/venv/bin:/usr/sbin:/usr/bin:/sbin:/bin \
VIRTUAL_ENV=/usr/local/venv \
DEV=QCOM \
WARP_DEV=QCOM \
IMAGE=2 \
FLOAT16=1 \
NOLOCALS=1 \
JIT_BATCH_SIZE=0 \
OPENPILOT_HACKS=1 \
/usr/local/venv/bin/python \
/data/openpilot/iqpilot/selfdrive/iqmodeld/tools/compile_supercombo.py \
--model-size 512x256 \
--camera-resolutions 1344x760 1928x1208 \
--onnx /data/media/0/driving_supercombo_<name>_source.onnx \
--output /data/media/0/models/driving_supercombo_<name>.recompiled.pkl \
--frame-skip 4 \
--expected-device QCOM"
Example: NoPP
ssh iq@192.168.173.10 "sudo env \
HOME=/data/root-home \
XDG_CACHE_HOME=/data/root-cache \
UV_CACHE_DIR=/data/root-uv-cache \
TMPDIR=/data/root-tmp \
PYTHONPATH=/data/openpilot:/data/openpilot/tinygrad_repo \
PATH=/usr/local/venv/bin:/usr/sbin:/usr/bin:/sbin:/bin \
VIRTUAL_ENV=/usr/local/venv \
DEV=QCOM \
WARP_DEV=QCOM \
IMAGE=2 \
FLOAT16=1 \
NOLOCALS=1 \
JIT_BATCH_SIZE=0 \
OPENPILOT_HACKS=1 \
/usr/local/venv/bin/python \
/data/openpilot/iqpilot/selfdrive/iqmodeld/tools/compile_supercombo.py \
--model-size 512x256 \
--camera-resolutions 1344x760 1928x1208 \
--onnx /data/media/0/driving_supercombo_nopp_source.onnx \
--output /data/media/0/models/driving_supercombo_nopp.recompiled.pkl \
--frame-skip 4 \
--expected-device QCOM"
6. What Success Looks Like
On success, the compile ends with output similar to:
Saved JITs to /data/media/0/models/driving_supercombo_<name>.recompiled.pkl (119.07 MB)
Current good rebuilt supercombo artifacts have been around 114M to 119 MB.
If you get a tiny file, do not publish it.
Always verify both size and hash:
ssh iq@<ip> "ls -lh /data/media/0/models/driving_supercombo_<name>.recompiled.pkl"
ssh iq@<ip> "sha256sum /data/media/0/models/driving_supercombo_<name>.recompiled.pkl"
7. Expected Warnings During Compile
These warnings have appeared during successful builds and are not by themselves proof of a bad artifact:
input desire_pulse has mismatch on dtype. Expected dtypes.half, received dtypes.float.
input traffic_convention has mismatch on dtype. Expected dtypes.half, received dtypes.float.
input action_t has mismatch on dtype. Expected dtypes.half, received dtypes.float.
input features_buffer has mismatch on dtype. Expected dtypes.half, received dtypes.float.
Treat them as informational unless the resulting model fails runtime validation.
8. Install the Rebuilt Artifact On the Device
Before publishing to IQModels, install the rebuilt artifact locally on the device being tested.
Back up the current file first:
ssh iq@<ip> "cp /data/media/0/models/driving_supercombo_<name>.pkl /data/media/0/models/driving_supercombo_<name>.pkl.bak.\$(date +%s)"
Then replace it:
ssh iq@<ip> "sudo cp /data/media/0/models/driving_supercombo_<name>.recompiled.pkl /data/media/0/models/driving_supercombo_<name>.pkl"
Verify the active file hash:
ssh iq@<ip> "sha256sum /data/media/0/models/driving_supercombo_<name>.pkl"
9. Validate the Model Before Publishing
Do not push a model just because it compiled.
Current IQPilot validation should include both of these:
9.1 Offroad/on-device iqmodeld harness validation
Use the current harness:
iqpilot/selfdrive/iqmodeld/tools/force_onroad_iqmodeld_test.py
This script creates a minimal fake onroad environment and starts iqmodeld.
Run it on-device from the normal IQPilot tree:
ssh iq@<ip> "cd /data/openpilot && /usr/local/venv/bin/python /data/openpilot/iqpilot/selfdrive/iqmodeld/tools/force_onroad_iqmodeld_test.py --speed 15.0"
What you want:
iqmodeldstays alive- no PoseNET/JIT mismatch crash
- no immediate deadlock
- no model startup freeze
9.2 Real launcher / real device validation
The harness is necessary, but not sufficient.
Also validate through the actual launcher/runtime:
- boot IQPilot normally
- select the model through the selector
- clear model cache if required by your workflow
- confirm the model loads
- confirm it survives transition to onroad
- confirm
modelV2,livePose,iqPlan, and related services stay alive - confirm the UI does not freeze
For any model intended for release, a real onroad validation pass is strongly recommended before publishing.
10. Runtime Signals to Watch
When a model is bad, the system often does not fail cleanly.
Useful checks:
ssh iq@<ip> "tmux capture-pane -pt 0"
ssh iq@<ip> "cat /data/community/crashes/error.log"
ssh iq@<ip> "ls -1t /data/community/crashes | head"
Common bad signals:
tinygrad.engine.jit.JitError: args mismatch in JITexpected_input_infoshowingCPUon one side andQCOMon the other- shape mismatch like
arg=2vsarg=5 iqmodelddisappearing or zombifyingmodelV2,livePose, oriqPlandying- UI frozen onroad
commIssuespam caused by model pipeline collapse
11. Common Failure Modes and Meaning
Failure: args mismatch in JIT
Typical causes:
- compiled artifact does not match current runtime expectations
- wrong
frame_skip - wrong device capture path
- CPU-built artifact being used on QCOM runtime
- stale/old artifact still being loaded
Failure: artifact references CPU in crash output
Typical cause:
- artifact compiled on the wrong backend or with the wrong compile environment
Fix:
- rebuild on-device with
DEV=QCOM,WARP_DEV=QCOM, andOPENPILOT_HACKS=1
Failure: tiny file after scp
Typical cause:
- interrupted copy
- partial transfer
Fix:
- verify local file size
- verify local hash
- do not publish until the copied file matches the device hash exactly
Failure: tinygrad cache or permission errors
Typical causes:
/root/.cacheunwritable- shell launched outside the expected manager environment
Fix:
- use the writable cache dirs from this guide
- use the exact
sudo env ...compile command above
Failure: model compiles but freezes onroad
Possible causes:
- wrong compile flags despite a successful build
- artifact differs from stock QCOM compile assumptions
- runtime deadlock only visible under real launch conditions
Fix:
- recompile with the current known-good flags
- run the harness
- then validate through normal IQPilot startup and onroad transition
12. Pull the Final Artifact Back to the Workstation
Once the device artifact is validated, pull it back locally:
scp -o StrictHostKeyChecking=no \
iq@<ip>:/data/media/0/models/driving_supercombo_<name>.pkl \
/tmp/driving_supercombo_<name>.recompiled.full
Verify locally:
ls -lh /tmp/driving_supercombo_<name>.recompiled.full
sha256sum /tmp/driving_supercombo_<name>.recompiled.full
The local hash must match the device hash exactly.
13. Publish to IQModels
Mounted example path:
/Volumes/New New Vault/IQModels
Replace the existing artifact in the model directory:
cp /tmp/driving_supercombo_<name>.recompiled.full \
'/Volumes/New New Vault/IQModels/models/recompiled16/model-<Model Name>/driving_supercombo_<name>.pkl'
Then update both:
docs/model_selector_b.jsondocs/model_fetcher_b.json
Update the sha256 values to the rebuilt artifact hash. If the file path and artifact filename stay the same, the URL does not need to change.
14. Verify Published Repo State
Before committing:
git -C '/Volumes/New New Vault/IQModels' status --short
git -C '/Volumes/New New Vault/IQModels' diff -- docs/model_selector_b.json docs/model_fetcher_b.json
sha256sum '/Volumes/New New Vault/IQModels/models/recompiled16/model-<Model Name>/driving_supercombo_<name>.pkl'
Make sure:
- repo artifact hash matches the rebuilt local hash
- selector SHA matches the repo artifact hash
- only intended model files and manifest files are changed
15. Commit and Push
Example:
git -C '/Volumes/New New Vault/IQModels' add -- \
docs/model_selector_b.json \
docs/model_fetcher_b.json \
'models/recompiled16/model-<Model Name>/driving_supercombo_<name>.pkl'
git -C '/Volumes/New New Vault/IQModels' commit -m 'Recompile <Model Name> with corrected QCOM flags'
git -C '/Volumes/New New Vault/IQModels' push
16. Post-Publish Validation
After pushing:
- redownload the model through the selector on a device
- confirm the downloaded file SHA matches the published selector SHA
- confirm the device loads the rebuilt model
- confirm the model survives onroad entry
Useful command:
python3 - <<'PY'
from openpilot.common.params import Params
print(Params().get("ModelManager_ActiveBundle"))
PY
17. Recommended Release Checklist
Use this every time.
- Confirm
SConscriptcontains the current QCOM flags, especiallyOPENPILOT_HACKS=1. - Copy the source ONNX to the device.
- Compile on-device with the exact environment from this guide.
- Verify artifact size is full-sized, not truncated.
- Verify artifact hash.
- Install the rebuilt artifact on the test device.
- Run the
force_onroad_iqmodeld_test.pyharness. - Validate under the real launcher path.
- Confirm no crash logs, no PoseNET/JIT mismatch, no freeze.
- Pull the artifact back locally and verify hash match.
- Replace the published IQModels artifact.
- Update selector and fetcher SHA values.
- Verify repo hash, manifest hash, and git diff.
- Commit and push.
- Redownload through selector and validate one more time.
18. Notes for Future Agents
- Do not assume a successful compile means the model is good.
- Do not assume a selector SHA mismatch is the only cause of failure.
- Do not publish partially copied
.pklfiles. - Do not skip the real launcher/onroad validation path.
- If a model works on stock openpilot but fails on IQPilot, compare the QCOM compile path first.
- When in doubt, rebuild on-device with the exact current flags in this guide and validate again.