{"id":"c5b5c299-0a65-476d-9757-3034549d753b","slug":"tao-train-pointpillars","kind":"skill","name":"tao-train-pointpillars","summary":"PointPillars for 3D object detection from LiDAR point clouds. Encodes point clouds into a pseudo-image via a pillar-based representation, then applies 2D detection — used in autonomous driving and rob","owner":"NVIDIA","repoUrl":"https://github.com/NVIDIA/skills/tree/HEAD/skills/tao-train-pointpillars","license":"Apache-2.0","licenseTier":"permissive","trust":"official","stars":3586,"match":null,"fewStars":false,"format":"skill","createdAt":null,"addedAt":"2026-10-14T05:51:48.823Z","logoUrl":"https://avatars.githubusercontent.com/u/1728152?v=4","linkOnly":false,"collection":{"name":"skills","repo":"nvidia/skills"},"skillPath":"skills/tao-train-pointpillars","categories":["design-media","developer-tools"],"tags":["agentic-ai","ai-agents","claude-code","codex","coding-agents","cuda","developer-tools","llm"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-14T05:51:48.822Z","sample":false,"url":"https://conduits.dev/tools/tao-train-pointpillars","language":"Python","transports":[],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"> PointPillars for 3D object detection from LiDAR point clouds. Encodes point clouds into a pseudo-image via a pillar-based representation, then applies 2D detection — used in autonomous driving and robotics. Use when training, evaluating, exporting, pruning, retraining, or running inference for a TAO PointPillars model. Trigger phrases include \"train PointPillars\", \"LiDAR 3D detection\", \"point-cloud object detection\", \"pillar-based 3D detector\".\n\n# PointPillars\n\n> **Standalone install?** If this session was not initialized by the TAO skill bank plugin, run the `tao-setup` skill first (host preflight, credentials, cross-skill discovery).\n\nPointPillars for 3D object detection from LiDAR point clouds. Encodes point clouds into a pseudo-image via pillar-based representation, then applies 2D detection. Used in autonomous driving / robotics.\n\nTypically trained from scratch. Provide train.resume_training_checkpoint_path to resume.\n\nFor TAO Deploy TensorRT actions (`gen_trt_engine`, TensorRT `evaluate`, and TensorRT `inference`), read `references/tao-deploy-pointpillars.md` first. Deploy spec templates live in this skill's `references/` folder with the `spec_template_deploy_*.yaml` prefix.\n\nThe packaged PyTorch PointPillars CLI supports `dataset_convert`, `train`, `evaluate`, `inference`, `export`, and `prune`. It does not expose a parent-model `gen_trt_engine` action; TensorRT engine generation is deploy-only. It also does not expose a separate `retrain` subcommand. Retraining from a pruned model uses `pointpillars train -e ...` with `train.pruned_model_path` populated.\n\n## Dataclass Schemas\n\nGenerated TAO Core schemas are packaged in `schemas/<action>.schema.json`, with `schemas/manifest.json` listing available actions. Each generated schema also emits `references/spec_template_<action>.yaml` from the schema top-level `default` field. AutoML enablement is declared at the model layer in `references/skill_info.yaml` via `automl_enabled`. Runnable AutoML for an action requires `schemas/<action>.schema.json` and `references/spec_template_<action>.yaml` to exist and parse. Use the packaged selected-action schema for `automl_default_parameters`, `automl_disabled_parameters`, defaults, min/max bounds, enums, option weights, math conditions, dependencies, and popular parameters. Do not expect `~/tao-core` at runtime; maintainers regenerate schemas/templates before packaging the skill bank.\n\n## Train Action Policy\n\nThis model is AutoML-enabled at the model layer. Before handling any train-stage request, read `references/skill_info.yaml` and resolve the run override from either an explicit `automl_policy` value or the user's workflow request. Use `automl_policy: on` by default and only expose `on` / `off` in new launch prompts. Treat phrases like \"turn off AutoML\", \"disable AutoML\", \"no HPO\", or \"plain training\" as `automl_policy: off` for this run only. When `automl_policy: on`, `automl_enabled: true`, and both `schemas/train.schema.json` and `references/spec_template_train.yaml` are packaged, route the train action through `tao-skill-bank:tao-run-automl` by default with this model's `skill_dir`. Preserve workflow/application overrides for datasets, specs, output directories, GPU/platform settings, parent checkpoints, and `automl_policy`. Use direct model training only when `automl_policy: off` or the packaged train schema/template is missing; in the missing-schema case, report that AutoML is enabled but not runnable for this model until schemas are generated.\n\nNon-train actions such as `evaluate`, `inference`, `export`, and deploy flows stay in this model skill. The per-run `automl_policy` override does not change model metadata.\n\n## Training Requirements\n\n- **Dataset type:** pointpillars\n- **Formats:** default\n- **AutoML training metric:** `loss` (minimize). This is the per-epoch KPI emitted by the train action and is the metric AutoML must extract for trial ranking.\n- **Standalone evaluation metrics:** the evaluate action emits recall KPIs plus dataset-specific detection metrics. For the general point-cloud dataset, verify `bev mAP` and `3d mAP`; do not substitute an evaluation mAP for AutoML's emitted training `loss`.\n\n### Per-Action Dataset Requirements\n\n| Action | Spec Key | Source | Files | List? |\n|---|---|---|---|---|\n| dataset_convert | dataset.data_path | id |  | No |\n| evaluate | dataset.data_path | train_datasets |  | No |\n| evaluate | dataset.data_info_path | train_datasets | /results/{dataset_convert_job_id}/results_dir/data_info/ | No |\n| export | dataset.data_path | train_datasets |  | No |\n| export | dataset.data_info_path | train_datasets | /results/{dataset_convert_job_id}/results_dir/data_info/ | No |\n| inference | dataset.data_path | train_datasets |  | No |\n| inference | dataset.data_info_path | train_datasets | /results/{dataset_convert_job_id}/results_dir/data_info/ | No |\n| prune | dataset.data_path | train_datasets |  | No |\n| prune | dataset.data_info_path | train_datasets | /results/{dataset_convert_job_id}/results_dir/data_info/ | No |\n| retrain | dataset.data_path | train_datasets |  | No |\n| retrain | dataset.data_info_path | train_datasets | /results/{dataset_convert_job_id}/results_dir/data_info/ | No |\n| train | dataset.data_path | train_datasets |  | No |\n| train | dataset.data_info_path | train_datasets | /results/{dataset_convert_job_id}/results_dir/data_info/ | No |\n\n### Typical Spec Overrides\n\nData source overrides are **mandatory for every action** — the agent MUST construct data source paths from the Per-Action Dataset Requirements table above and include them in `spec_overrides`.\n\n```python\nDATA_ROOT = \"s3://bucket/data/pointpillars\"\nDATA_INFO = \"/results/{dataset_convert_job_id}/results_dir/data_info\"\nCHECKPOINT = \"/results/{train_job_id}/results_dir/checkpoint_epoch_1.pth\"\nPRUNED_MODEL = \"/results/{prune_job_id}/results_dir/pruned_0.1.tlt\"\n```\n\nThe raw PointPillars data root must be an extracted folder containing matching `train/lidar`, `train/label`, `val/lidar`, and `val/label` subfolders before `dataset_convert` runs. If the source dataset is packaged as separate train/val archives, extract both under the same mounted data root and point `dataset.data_path` at that root.\n\n**train (mandatory data sources):**\n```python\n{\n    \"train.num_epochs\": 30,\n    \"train.checkpoint_interval\": 10,\n    \"train.validation_interval\": 10,\n    \"train.num_gpus\": 1,\n    \"dataset.data_path\": DATA_ROOT,\n    \"dataset.data_info_path\": DATA_INFO,\n}\n```\n\n**resume train (mandatory checkpoint):**\n```python\n{\n    \"dataset.data_path\": DATA_ROOT,\n    \"dataset.data_info_path\": DATA_INFO,\n    \"train.resume_training_checkpoint_path\": CHECKPOINT,\n}\n```\n\n**evaluate (mandatory data sources):**\n```python\n{\n    \"dataset.data_path\": DATA_ROOT,\n    \"dataset.data_info_path\": DATA_INFO,\n    \"evaluate.checkpoint\": CHECKPOINT,\n}\n```\n\n**export (mandatory data sources):**\n```python\n{\n    \"dataset.data_path\": DATA_ROOT,\n    \"dataset.data_info_path\": DATA_INFO,\n    \"export.checkpoint\": CHECKPOINT,\n    \"export.onnx_file\": \"/results/{export_job_id}/results_dir/pointpillars.onnx\",\n}\n```\n\n**inference (mandatory data sources):**\n```python\n{\n    \"dataset.data_path\": DATA_ROOT,\n    \"dataset.data_info_path\": DATA_INFO,\n    \"inference.checkpoint\": CHECKPOINT,\n}\n```\n\n**prune (mandatory data sources):**\n```python\n{\n    \"dataset.data_path\": DATA_ROOT,\n    \"dataset.data_info_path\": DATA_INFO,\n    \"prune.model\": CHECKPOINT,\n}\n```\n\n**retrain (mandatory data sources):**\n```python\n{\n    \"dataset.data_path\": DATA_ROOT,\n    \"dataset.data_info_path\": DATA_INFO,\n    \"train.pruned_model_path\": PRUNED_MODEL,\n}\n```\n\nFor local Docker, `DATA_INFO` must be visible inside every train/evaluate/export/prune/retrain container. Use the dataset_convert job from the same results root, or mount/copy the converted `results_dir/data_info` folder into the current run and set `dataset.data_info_path` to that mounted container path. If the host scratch root is mounted at `/results` and the conversion artifacts live under host `scratch/results/<job_id>/results_dir/data_info`, the direct-job container path is `/results/results/<job_id>/results_dir/data_info`. Do not reuse a `/results/<job_id>/...` path from another run root unless that folder is mounted into the current job.\n\nFor AutoML train workflows, perform this as a launch preflight before calling `AutoMLRunner.run`: create or materialize the `dataset_convert` output under the current run's `RESULTS_ROOT`, set `dataset.data_info_path` to that current-run container path, and verify `dbinfos_train.pkl`, `infos_train.pkl`, and `infos_val.pkl` are present from the train container's point of view. If a runner is cloned or adapted from a prior AutoML algorithm, update the conversion artifact in the new run root; a stale `CONVERT_JOB_ID` from another results mount is not valid.\n## Eval Dataset\n\nOptional. Validation data (val.tar.gz) is separate from training. Used for mAP evaluation.\n\n## Important Parameters\n\n- **train.num_epochs**: Default 80 (much higher than other TAO models). PointPillars needs more epochs for convergence on 3D detection.\n- **train.lr**: Learning rate. Default 0.003 (adam_onecycle scheduler).\n- **dataset.class_names**: List of 3D object classes. Default 7 classes (KITTI-style). Modify to match your dataset.\n- **dataset.data_path**: Path to point cloud data directory.\n- **dataset.data_info_path**: Path to data info files from dataset_convert step.\n- **dataset.point_cloud_range**: Spatial extent of the point cloud to consider. Must match your sensor configuration.\n- **model.dense_head.anchor_generator_config**: Anchor configurations per class. Must be tuned for your object sizes and the point cloud range.\n\n## Multi-GPU / Multi-Node\n\n**Launch method:** `torchrun` (LIGHTNING_EXCLUDED_NETWORK). Uses PyTorch native `DistributedDataParallel` (NOT Lightning Trainer).\n\n| Spec Key | Description | Default |\n|----------|-------------|---------|\n| `train.num_gpus` | Number of GPUs per node | 1 |\n| `train.gpu_ids` | GPU device indices | [0] |\n| `train.num_nodes` | Number of nodes | 1 |\n\n- `CUDA_VISIBLE_DEVICES` is explicitly set from `TAO_VISIBLE_DEVICES`\n- Uses `nn.parallel.DistributedDataParallel` directly (not Lightning strategy)\n- `NODE_RANK` is copied to `RANK` if `RANK` is unset\n\n**Multi-node env vars** (set by orchestrator):\n\n| Variable | Purpose |\n|----------|---------|\n| `WORLD_SIZE` | Number of nodes |\n| `NODE_RANK` | This node's rank |\n| `MASTER_ADDR` | Rank-0 node IP |\n| `MASTER_PORT` | Rank-0 port (default 29500) |\n| `NUM_GPU_PER_NODE` | GPUs per node |\n\n## Hardware\n\nMinimum 1 GPU(s), recommended 4 GPU(s). 16GB+ (V100 or A100) VRAM per GPU. PointPillars is relatively efficient for 3D detection. The main bottleneck is data I/O for large point cloud datasets.\n\n## Error Patterns\n\n**dataset_convert required**: Training will fail if `dataset.data_info_path` is not populated from a prior `dataset_convert` job. Always run convert first, and verify the train container can see `dbinfos_train.pkl` and `infos_train.pkl` under `dataset.data_info_path`. A common local-Docker failure is a stale `/results/<old_job_id>/...` path from a different results root.\n\n**Point cloud range mismatch**: If point_cloud_range does not match the actual sensor data extent, detections will be poor or empty.\n\n**Epoch numbering**: PointPillars checkpoint epoch numbers may be offset by 1 from status.json reported epochs.\n\n**Checkpoint selection**: PointPillars training emits checkpoints named like `checkpoint_epoch_1.pth`. For evaluation, inference, export, prune, and resume, select the intended checkpoint through the model/job checkpoint resolver and pass that exact file to `evaluate.checkpoint`, `inference.checkpoint`, `export.checkpoint`, `prune.model`, or `train.resume_training_checkpoint_path`. Do not guess by taking the newest `model.pth`; this model does not use that filename.\n\n**Prune/retrain key**: PointPillars prune writes an encrypted `.tlt` artifact. Keep a non-empty `key` in the prune and retrain specs; the packaged templates use the TAO default `tlt_encode`. If `key` is omitted or `null`, the toolkit can still exit with a container success code while logging a passphrase error and creating an empty `pruned_0.1.tlt`. Always verify the pruned model is nonzero before using it for retrain.\n\n**Status files matter**: Some PointPillars failures can be followed by `Execution status: PASS` in the entrypoint footer and a Docker exit code of 0. Check `results_dir/status.json` and the expected artifact before marking an action as passed.\n\n**Local results_dir wiring**: For direct local-Docker specs, set the top-level `results_dir` as well as any action-specific `*.results_dir` field. If only `evaluate.results_dir` is set and the top-level field is left blank, evaluate can try to write under `/opt/nvidia/eval` and then still print the generic PASS footer. Treat that as a failed action unless the expected result directory and status/artifact files exist.\n\n## Spec Param / Parent Model Inference\n\nModel-specific inference mappings belong in this MD file, not in `config.json`. Generated runners should read this section and apply the mappings with SDK helpers before `create_job()`. This mirrors the old microservices `infer_params.py` flow.\n\nInference mappings from TAO Core `pointpillars.config.json`:\n\n| Action | Spec Field | Inference Function | Meaning |\n|---|---|---|---|\n| dataset_convert | `results_dir` | `output_dir` | current job results directory |\n| evaluate | `evaluate.checkpoint` | `parent_model` | model file inferred from the parent job results folder |\n| evaluate | `key` | `key` | encryption key |\n| evaluate | `results_dir` | `output_dir` | current job results directory |\n| export | `export.checkpoint` | `parent_model` | model file inferred from the parent job results folder |\n| export | `export.onnx_file` | `create_onnx_file` | output ONNX path |\n| export | `export.save_engine` | `create_engine_file` | output TensorRT engine path |\n| export | `key` | `key` | encryption key |\n| export | `results_dir` | `output_dir` | current job results directory |\n| inference | `inference.checkpoint` | `parent_model` | model file inferred from the parent job results folder |\n| inference | `inference.trt_engine` | `parent_model` | model file inferred from the parent job results folder |\n| inference | `key` | `key` | encryption key |\n| inference | `results_dir` | `output_dir` | current job results directory |\n| prune | `key` | `key` | encryption key |\n| prune | `prune.model` | `parent_model` | model file inferred from the parent job results folder |\n| prune | `results_dir` | `output_dir` | current job results directory |\n| retrain | `key` | `key` | encryption key |\n| retrain | `results_dir` | `output_dir` | current job results directory |\n| retrain | `train.pruned_model_path` | `parent_model` | model file inferred from the parent job results folder |\n| train | `key` | `key` | encryption key |\n| train | `model.pretrained_model_path` | `ptm_if_no_resume_model` | PTM when no resume checkpoint exists |\n| train | `results_dir` | `output_dir` | current job results directory |\n| train | `train.resume_training_checkpoint_path` | `resume_model` | model file inferred from the current job results folder |\n\nFor `parent_model` or `parent_model_folder`, pass the upstream train/export/AutoML child job id as `parent_job_id`. The SDK lists the parent result folder, filters checkpoint artifacts, and returns the selected model file or folder. Do not add these mappings back to `config.json` and do not patch generated runner scripts to guess checkpoint paths.\n\n## Deployment\n\n- [tao-deploy-pointpillars](references/tao-deploy-pointpillars.md)"}