DEV Community

Anguo
Anguo

Posted on

Before you convert that ONNX model to RKNN, check whether it can convert at all

The standard RKNN conversion experience goes like this: set up the Toolkit environment, write the conversion script, run it, wait, read a wall of log, and discover — forty minutes in — that your model has a dynamic batch dimension, or an op the converter places badly, or an opset the toolchain doesn't love. None of those are conversion problems. They're pre-flight problems, discovered at landing time.

So I added a convert trio to RK Edge Doctor (zero-dependency, Python stdlib only). It deliberately does not convert anything — the official RKNN Toolkit2 does that. It does the three things around the conversion:

1. convert check — pre-flight. A hand-rolled ONNX structure parser (raw protobuf wire format, no onnx package) reads opset, input shapes and the op histogram, then checks:

  • dynamic input dimensions (fix them before quantization, not after)
  • control-flow operators — Loop / If / Scan cannot become a static RKNN graph, verdict LIKELY_TO_FAIL
  • operators known to need attention in Toolkit2 (NonMaxSuppression, Resize, GridSample, …) with the reason for each
  • quantization-sensitive tails (Sigmoid/Softmax at the graph end under int8)

Verdict: READY / RISKY / LIKELY_TO_FAIL.

2. convert recipe — a script worth running. Generates a ready-to-run Toolkit2 conversion script: target platform, int8 config + calibration dataset if you asked, and input_size_list pinned from the ONNX inputs themselves. You run it in your own Toolkit environment.

3. convert verify — post-conversion acceptance. The existing model diagnosis (CPU fallback list, PERF-counter latency, ONNX output drift) framed as the verification step.

First contact with a real file was humbling in the right way. I tested the checker on the official Ultralytics YOLOv8n ONNX export (PyTorch, opset 20, 233 nodes) and it immediately failed — because my parser assumed the textbook ModelProto field layout, and real PyTorch exports arrange producer/opset fields differently. Fixed by identifying fields by content, not by faith, and the same file now gets an honest verdict:

$ rkdoctor convert check yolov8n.onnx --target rk3588
+ parse: 233 nodes (opset 20, producer pytorch)
! opset: 20 (outside the commonly used 11-19 range)
! caution_ops: Resize (some modes convert with restrictions)
+ dynamic_dims: static
+ weights: 12.78 MB
RISKY
Enter fullscreen mode Exit fullscreen mode

That is the correct answer for that file, and it's the answer you want before the Toolkit run, not after.

With this release the tool's planned surface is complete: board (16 hardware checks), model (CPU-fallback diagnosis), rtsp (stream acceptance), and now convert. The model health table keeps growing weekly — custom conversions that check out RISKY, or run MIXED/CPU_HEAVY, are exactly the reports I want in issues.

Top comments (0)