Deploy the base profile (VSS Warehouse + Safety Core, no Isaac Sim / closed loop) on an
IGX Thor device. The safety decision (MUTE / UNMUTE) renders as the VST halo_safety
overlay, exactly like the x86 base profile — only the Safety Core runs on the Thor instead
of as an x86 container.
On x86, base runs the Safety Core as a single container via docker compose
(profiles/base.env). On Thor the Safety Core is hybrid — an nv-psf container (event
integration + decision gateway) plus host binaries (the SDM and the AI monitor)
orchestrated by launch_hoisa.sh. It is therefore launched by a helper script that reads an
env file, not by docker compose.
| Platform | Where the SDM runs | Mechanism |
|---|---|---|
| x86 | x86 container | docker compose --env-file profiles/base.env (the standard base) |
| IGX Thor | Thor application cores | launch_thor_safety.sh → launch_hoisa.sh --sdm-target ccplex |
The same Thor Safety Core launch path is reused by the (forthcoming) HIL profile — HIL adds the x86 stimulus side (Isaac Sim + comm-layer + ROS) and points the safety command at the comm-layer instead of the VST overlay.
- IGX Thor flashed with a current IGX SW GA release (RT kernel
6.8.0-1019-nvidia-tegra-rt). No manual DeepStream edits are needed on VSS 3.2.x: selectingHARDWARE_PROFILE=IGX-THOR(thevss-deploy-profileskill sets it) makes the blueprint-configurator apply the Thor-specific tuning automatically — including using the VIC for tracker scaling (compute-hw=2, the path the GA RT release fixed). (Pre-GA non-RT stacks needed a hand-setcompute-hwplus a camera-count reduction.) - NVIDIA driver, Container Toolkit, and Docker per
prerequisites.md. - The nv-psf container image — multi-arch (arm64 + amd64) under one tag; Docker on Thor
(arm64) auto-selects the arm64 variant, so it is the same tag as the x86
baseprofile. Set viaPSF_IMAGEinbase-thor.env. (The architecture-specific parts are the host binaries from thepsf-tegrapackage — see the next bullet.) - Safety Core host binaries from the
psf-tegrapackage installed under/opt/nvidia/psf/(ngc_artifacts.md§4): provideslaunch_hoisa.sh, the SDM apps (atl_sdm),safety_monitor, and the sensor config.
Deploy VSS Warehouse 3.2.1 (2D) on the Thor via the vss-deploy-profile skill (set
HARDWARE_PROFILE=IGX-THOR; the profile applies the Thor DeepStream tuning for you — §1). Wait
until perception serves all cameras (Active sources : 3) and the mdx-events Kafka topic has
data. See vss_2d_overrides.md for the base-vs-SIL override notes.
⚠ Two IGX-Thor VSS workarounds. These apply to the VSS Warehouse deployment itself, but are noted here because they otherwise block the Safety Core from receiving any perception data:
nvstreamer-2dneedsruntime: nvidia. Inindustry-profiles/warehouse-operations/warehouse-2d-app/warehouse-2d-app.yml, thenvstreamer-2dservice shipsruntime: nvidiacommented out (perception /rtvi-cvhas it set). On IGX Thor the baredeploy.resources.reservations.devicesGPU path does not inject the GPU, sonvstreamer-2dfails to start —vss-rtvi-cvthen runs but reportsActive sources : 0. Uncommentruntime: nvidiaonnvstreamer-2d, or — sturdier — add adeploy/docker/docker-compose.override.ymldeclaringruntime: nvidiafor the service and pass it atup(-f compose.yml -f docker-compose.override.yml, per the HOISA Quick Start Guide, Annex A): the override file survives the VSS state wipes that revert an in-place edit (down -v, or the datalog cleanup restoring the stock config), which otherwise must be re-applied before eachup.- Docker Hub rate limit (HTTP 429) with
--pull always. Public base-image pulls (e.g.alpine) can hittoomanyrequests. Drop--pull alwaysafter the first successful pull, or use an authenticated / mirrored pull.
Edit deployments/profiles/base-thor.env (fill the # change me fields):
HOST_IP— this Thor's IP.SDM_TARGET— where the SDM runs:ccplex, the Thor application cores.PSF_IMAGE— the nv-psf container (multi-arch; same tag as x86base, Docker selects arm64 on Thor).PSF_CMD_RX_PORT—12345, the VSThalo_safetyoverlay port (see §6).PSF_LAUNCH_MODE—active(full stack) orskip(omit the AI monitor; use only if the perception source codec is incompatible with the monitor).
Then point the Safety Core at this host's VST streams. The AI monitor reads the camera RTSP directly; on Thor those are the VST live URLs. Copy the template and fill in the URLs:
cp closed-loop-testing/safety-core/configs/sensor_config_thor.conf \
/opt/nvidia/psf/bin/sensor_config_thor.conf
# replace <thor_ip> and each <UUID> with values from:
# curl http://<thor_ip>:30888/vst/api/v1/sensor/list⚠ VST UUIDs change whenever VST state is wiped/redeployed — refresh
sensor_config_thor.confafter each VST reset.
If running the AI monitor (PSF_LAUNCH_MODE=active), generate per-camera baselines first
with launch_hoisa.sh --mode learn … (it reads the same sensor config as §3). Skip when using
PSF_LAUNCH_MODE=skip.
launch_thor_safety.sh reads base-thor.env and invokes launch_hoisa.sh.
bash closed-loop-testing/scripts/launch_thor_safety.sh base-thorVerify:
docker ps --filter name=nv-psf # nv-psf container Up
ps -eo comm | grep -x atl_sdm # SDM runningThe checks above confirm the components are up. To confirm the decision chain is actually
flowing, check the logs — the Thor host install writes to /var/log/psf/ (the launcher
prints the exact paths on start). Run while VSS perception is serving and the forklift/people
are moving:
# PSF ingested perception events and invoked the decision gateway:
sudo grep -E "Safety event reported|DecisionRequest|FUSED|PASSTHROUGH" /var/log/psf/psf.log | tail
# The SDM emitted MUTE/UNMUTE to the overlay port and got an ACK back:
sudo grep -E "Sending decision command|Received acknowledgment" /var/log/psf/atl_sdm.log | tailA healthy chain shows DecisionRequest lines in psf.log and matching pairs in
atl_sdm.log: Sending decision command: UNMUTE/MUTE … → 127.0.0.1:12345 immediately
followed by Received acknowledgment … (SeqNo: N) for the same SeqNo.
- No
DecisionRequestinpsf.log→ perception isn't feeding events: re-checkActive sourcesand that themdx-eventsKafka topic has data (§2). - Commands sent in
atl_sdm.logbut no acknowledgment → the overlay isn't listening on the port: check thehalo_safety_udp_portwiring (§6).
Same as the x86 base: in the VSS 2D vst_config.json, set halo_safety_udp_port to
12345 (ships -1 / disabled) — it must equal PSF_CMD_RX_PORT. Restart VST. The overlay
then shows "Standard Mode" (MUTE) / "Efficient Mode" (UNMUTE) + the forklift proximity
bubble.
⚠ validate on your hardware. Confirm the Thor launch emits the safety command to
127.0.0.1:12345in the form the VST overlay consumes. If the overlay stays blank while decisions are being logged, check this wiring first.
bash closed-loop-testing/scripts/stop_thor_safety.sh| Symptom | Fix |
|---|---|
nvstreamer-2d stuck Created / Runtime=runc, Active sources : 0 after a VSS down -v or datalog cleanup |
The runtime: nvidia fix on nvstreamer-2d (§2) was reverted to stock when VSS state was wiped. Re-uncomment it in warehouse-2d-app.yml, then docker compose --env-file … up -d --force-recreate --no-deps nvstreamer-2d. Re-apply after every down -v / cleanup, before up. |
nv-psf / perception can't get the GPU after a reboot |
The CDI spec lives on tmpfs — regenerate: sudo nvidia-ctk cdi generate --output=/var/run/cdi/nvidia.yaml && sudo systemctl restart docker |
| AI monitor reads no frames | sensor_config_thor.conf URLs/UUIDs are stale — refresh from the VST sensor list |
| Overlay blank but decisions are logged | Port mismatch — halo_safety_udp_port ≠ PSF_CMD_RX_PORT (both must be 12345) |
For perception / STALE / SEI issues, see troubleshooting.md.