ptv3-p150 on Tenstorrent p150
Derived from AutowareFoundation/ptv3 (tag
v4.0), the Point Transformer V3 network that TIER IV trained for Autoware'sautoware_ptv3LiDAR segmentation and detection node, with unmodified weights. Point Transformer V3: Wu et al., arXiv:2312.10035. See the original model card for training details.
Point Transformer V3, a 34.0M-parameter LiDAR network: 0.12 m voxels serialized along two Morton curves, a 5-stage encoder (sparse-conv positional encoding, attention over patches of 512 voxels, grid pooling; about 0.36 TFLOPs on a 117,000-voxel frame), a segmentation decoder for 15 classes and a TransFusion-style BEV detection head (top-500 queries). One concatenated LiDAR cloud in base_link (x, y, z, intensity 0-255) goes in. Out come, per input point, a class, its probability, the normalised entropy, Autoware's PointCloudClassification value and the obstacle-cloud membership, and with the seg_det profile 3D boxes for 7 classes (CAR, TRUCK, BUS, BICYCLE, PEDESTRIAN, TRAFFIC_CONE, BARRIER), with the pre- and post-processing of the autoware_ptv3 node (crop, voxelization, serialization, source reconstruction, score threshold, NMS, class remapping).
Runs on Tenstorrent p150 β see the serving profiles below.
Packaged and published with tt-model-manager 0.1.0 (manifest schema 5.1).
At a glance
| Hardware | p150 |
| License | apache-2.0 |
Intended use
LiDAR semantic segmentation (Autoware's ML ground removal) and, with the seg_det profile, 3D object detection for Autoware-style concatenated clouds: research, prototyping and offline processing of recorded drives, with the outputs of the autoware_ptv3 node.
Prerequisites
- The Tenstorrent CLI,
tt:uv tool install tenstorrent(or use tt-model alone, see the Quickstart) - Docker
- Tenstorrent hardware: p150
- Time for the first start: on an empty kernel cache the server compiles the kernels of all 31 capacity buckets, about 40 minutes on an 8-vCPU host; later starts are ready in about 1 minute.
Quickstart
tt serve changh95/ptv3-p150
tt serve downloads the Docker image and the AutowareFoundation/ptv3 at 1673104843af3c740145ac74dc4af6b8a4502bf3 weights (into your HF cache; they are not in the image), then starts the model's own HTTP server on port 20000 (or the next free port, if that one is busy). The first start compiles kernels for your device, which takes several minutes; the server is ready when it logs Application startup complete.
Without tt-cli: tt-model serve changh95/ptv3-p150.
Send Autoware's own test cloud, shipped in this repo, to /predict, on the port tt serve reported (serve with
--profile seg_det to get boxes too):
curl -sLO https://huggingface.co/changh95/ptv3-p150/resolve/main/code/tt_ptv3/samples/test_pcd.npz
printf '{"points": {"format": "npz", "data": "%s"}}' "$(base64 -w0 test_pcd.npz)" > req.json
curl -s localhost:20000/predict -H 'Content-Type: application/json' -d @req.json
Serving profiles
Select a different serving profile using --profile.
| profile | hardware | mesh | description |
|---|---|---|---|
seg (default) |
p150 | P150 | encoder + segmentation head: per-point classes, no boxes (how Autoware wires the node) |
seg_det |
p150 | P150 | encoder + segmentation head + detection head: per-point classes and 3D boxes |
Capabilities
This package exposes the model's own HTTP server on port 20000, not an OpenAI-compatible chat API β its request and response shapes are the model's own. See the author's notes for the payload it expects.
POST /predict takes one LiDAR cloud as JSON and returns a class for every point (and boxes with seg_det).
GET /health and GET /info report the server and device state; GET /v1/models is a stub, not a chat API.
| request field | meaning |
|---|---|
points |
one concatenated cloud in base_link (metres, intensity 0-255): {"format": "bin" | "npy" | "npz" | "pcd", "data": "<base64 file bytes>"} (bin: float32 rows of fields, default x, y, z, intensity; npz: optional key, default points) |
params (optional) |
run_detection (default true; seg_det only), score_threshold (0.1), reconstruction ("full", "partial" or "none": which points get a label), neighbour_mode ("alias-first", the TensorRT engine's spconv key aliasing, or "exact"), min_voxels (16000, the node's minimum; 0 disables it) |
output_format (optional) |
json (default) or npz (adds the arrays as a lossless base64 npz) |
Response for the sample with seg_det (arrays are base64 npz, their data elided; class lists shortened):
{"model": "ptv3-p150", "frame_id": "base_link", "num_points": 48048,
"labels": {"format": "npz", "key": "labels", "dtype": "uint8", "shape": [48048], "data": "..."},
"scores": {"format": "npz", "key": "scores", "dtype": "float32", "shape": [48048], "data": "..."},
"classification": {"...": "uint8 [48048]"}, "entropy": {"...": "float32 [48048]"}, "filter_keep": {"...": "bool [48048]"},
"class_names": ["car", "truck", "bus", "bicycle", "pedestrian", "traffic_cone", "barrier", "debris", "drivable_flat", "non_drivable_flat", "vegetation", "building", "vertical_thin", "static_clutter", "noise"],
"class_counts": {"truck": 64, "debris": 1, "drivable_flat": 12, "non_drivable_flat": 17486, "vegetation": 24122, "building": 1789, "255": 4574, "...": 0},
"num_detections": 1,
"detections": [{"label": "TRUCK", "label_id": 1, "score": 0.1264, "center": [22.332, -0.724, 1.461], "size": [9.35, 2.567, 3.605], "yaw": -0.0085, "velocity": [0.0, 0.0], "autoware_label": "TRUCK"}],
"meta": {"frame": {"num_points": 48048, "num_unique_voxels": 27346, "...": "..."}, "neighbour_mode": "alias-first", "reconstruction": "full"},
"timing_ms": {"decode": "...", "preprocess": "...", "device": "...", "postprocess": "...", "total": "..."}}
- One row per input point, in input order. Points outside the crop (x, y in [-122.88, 122.88) m, z in [-3, 5) m) get label 255 (INVALID), probability 0 and entropy NaN, and stay in the obstacle cloud.
labelsare the 15 PTv3 classes;classificationis the node's mapping toPointCloudClassification;filter_keepis the membership of the node's filtered cloud (drivable_flat, non_drivable_flat and noise removed).detections(profileseg_det) are inbase_link, metres and radians, after the node's score threshold, NMS and class remapper;centeris the box centre;autoware_labelis the publishedObjectClassification(TRAFFIC_CONE and BARRIER become HAZARD). Thesegprofile returns nodetections.- A cloud with fewer than 16,000 voxels gets the node's empty output (
meta.rejected) unlessparams.min_voxelsis lowered. - A Python API with the same outputs (
tt_ptv3.PTv3) is described incode/PYTHON.md; it needs a tt-metal build with the two patches in this repo'spatches/directory.
Example output
Per-point classes (left) and 3D boxes (right) computed by this package (seg_det profile, min_voxels 0) on 50
LiDAR sweeps of nuScenes scene-1100 (night, pedestrians at a crosswalk, 10 Hz), bird's-eye view Β±32 m, also as
MP4. The video was rendered with this port's initial version (same weights).
Non-commercial use only: rendered from the nuScenes dataset, Β© Motional AD Inc.,
CC BY-NC-SA 4.0 and the nuScenes Terms of Use; Motional does not endorse
this work. Attributions for every file in media/: media/ATTRIBUTION.md.
Expected performance
Agreement with the fp32 CPU reference of the same network (same weights, same pre- and post-processing, identical
host index tables). Per-point outputs are identical in the two profiles; boxes come from seg_det only:
| eval | this package | fp32 CPU reference | clouds |
|---|---|---|---|
Points with the reference's class, shipped sample test.pcd (classification / obstacle filter) |
99.89 % (99.90 % / 99.95 %) | β | 1 |
Boxes matched (same class, centres within 0.5 m), test.pcd |
1 of 1, score difference 0.0038 | 1 | 1 |
| Points with the reference's class, gate frames (PandaSet, T4 sample dataset, nuScenes mini_val): minimum per frame | 99.21 % | β | 21 |
| Boxes matched, gate frames: recall / precision / max score difference | 0.994 / 0.997 / 0.032 | β | 21 |
The same with neighbour_mode: exact: minimum point agreement, recall / precision / max score difference |
99.34 %, 0.993 / 0.997 / 0.036 | β | 21 |
| Held-out PandaSet 019 frames: minimum point agreement, box recall / precision / max score difference | 99.45 %, 0.993 / 0.997 / 0.17 | β | 77 |
The 21 gate clouds are 12 PandaSet frames, 4 frames of the T4 sample dataset and 4 nuScenes mini_val key-frames (run
with min_voxels 0), plus the PandaSet sweep of the speed table, which is the same cloud as one of the 12 PandaSet
frames and so counts twice in the pooled numbers; the held-out frames are the other 77 frames of PandaSet sequence
019 (3 of their 10,072 matched boxes differ in score by more than 0.05). The weights were trained on TIER IV's T4 dataset with 15 / 7
classes that public datasets label differently, so no dataset metric is reported; the weights repo publishes none.
| speed (batch 1, warm) | profile | input | median | throughput |
|---|---|---|---|---|
| Device time per cloud, back-to-back trace replays | seg |
test.pcd (27,346 voxels) / PandaSet sweep (73,992 voxels) |
20.9 / 51.1 ms | 47.9 / 19.6 clouds/s |
| Device time per cloud, back-to-back trace replays | seg_det |
test.pcd / PandaSet sweep |
30.0 / 60.6 ms | 33.3 / 16.5 clouds/s |
Python model() call (pre-processing, tables, device, post-processing) |
seg |
test.pcd / PandaSet sweep |
59.9 / 142.8 ms | 16.7 / 7.0 clouds/s |
Python model() call |
seg_det |
test.pcd / PandaSet sweep |
73.9 / 166.0 ms | 13.5 / 6.0 clouds/s |
Served POST /predict, server timing_ms.total |
seg |
test.pcd / PandaSet sweep |
76-77 / 177-178 ms | β |
Served POST /predict, server timing_ms.total |
seg_det |
test.pcd / PandaSet sweep |
90-91 / 203-213 ms | β |
Served POST /predict, client round trip inside the container |
seg / seg_det |
test.pcd |
86-87 / 99-101 ms | β |
Measured with this package's code on one p150 in an 8-vCPU AMD EPYC-Rome host: code/scripts/bench.py (50 warm
iterations per stage) and, inside the container, 350 served requests per input and profile over 5 container
starts. Device time grows with the cloud: each cloud runs in the smallest of 31 capacity buckets that holds it.
The model() and served times are host-bound: pre-processing and index tables take about 30 ms of a test.pcd
call, and the PandaSet sweep (106,501 points) carries more.
Limitations
- Do not use it to drive or control a vehicle or as any safety function: it is not a certified Autoware component and has no functional-safety qualification. In Autoware, PTv3 is an opt-in segmentation / ML ground removal that is off by default, and its detection head is idle; no tagged Autoware release runs these v4.0 weights.
- Do not use its outputs as a PTv3 accuracy benchmark or on other LiDAR setups without checking: the weights are TIER IV's training on about 4,000 frames of the non-public T4 dataset, and accuracy on other sensors and domains is not characterized.
- Not a ROS 2 node: it serves HTTP and Python only. One concatenated cloud per request: no multi-sweep, camera or stream input (the v4.0 node has none).
- Batch 1, one cloud per request; requests are served one at a time; one profile per server. At most 256,000 voxels per cloud (the node's maximum).
- One p150 only. The image runs device dispatch on the chip's Ethernet cores, so multi-chip meshes are not supported.
- Outputs were compared with the fp32 CPU reference, not with the node's TensorRT engines (fp16 by default). The
sparse-conv neighbour tables reproduce spconv's key aliasing deterministically (
alias-first, the default) or use exact keys; the engine's GPU hash order is not reproduced bit for bit. - Outputs differ slightly from the fp32 reference: 0.1-0.8 % of point labels; boxes near the 0.1 score threshold, and NMS or top-k near-ties, can appear or disappear. On held-out PandaSet frames a matched box's score can differ by up to 0.17.
- Clouds below the node's 16,000-voxel minimum (every single-sweep nuScenes cloud) get the node's empty output
unless
min_voxelsis lowered. - On public LiDARs the weights themselves (on CPU and on p150 alike) do not transfer T4's fine static classes and give no traffic-cone or barrier detections.
Licensing
- Weights: AutowareFoundation/ptv3 at tag
v4.0(commit1673104843af3c740145ac74dc4af6b8a4502bf3), Apache-2.0 per its model card. Downloaded bytt serveat that commit, not redistributed here. Trained by TIER IV on the T4 dataset (about 4,000 frames); the training configuration is not public. - Pre- and post-processing ported from autoware_universe
perception/autoware_ptv3(Apache-2.0). - Port and serving code (
code/) and the tt-metal patches inpatches/: Apache-2.0. - Sample
code/tt_ptv3/samples/test_pcd.npz: thetest.pcdof the Autoware package (Apache-2.0), converted to npz. - Demo media in
media/are renders, not part of the package. The demo video andmedia/*_NC.*come from nuScenes: non-commercial use only, CC BY-NC-SA 4.0, Β© Motional AD Inc. The PandaSet renders: CC BY 4.0 and the PandaSet Dataset Terms (Scale AI and Hesai). Neither dataset owner endorses this work. Full attributions:media/ATTRIBUTION.md.
Related packages
- The Autoware collection: the other Autoware perception and planning models packaged for the p150.
Feedback
Questions or problems with this package: open a discussion at https://huggingface.co/changh95/ptv3-p150/discussions β that is what reaches its author. A problem with the tt tooling itself: tt report issue (collects your environment and opens a prefilled issue against tenstorrent/tt-cli). Product feedback: support@tenstorrent.com.
Provenance
The exact sources the image was built from β code/ in this repo is byte-identical to the model code inside the image:
| component | built from |
|---|---|
| tt-metal | 44d66500520fda9f2c7060c0f6b41ec48f7ab37e (dirty tree β the image includes uncommitted changes) |
code/ digest |
8ec79f67cc6097ce (sha256, first 16 hex digits) |
| built | 2026-10-17T04:55:12+00:00 by tt-model 0.1.0 |
Model tree for changh95/ptv3-p150
Base model
AutowareFoundation/ptv3