diff --git a/Makefile b/Makefile index bc429ce..f3caf5f 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,22 @@ BIN_DIR := $(BUILD_DIR)/bin # --- gpr_cpp: external C++/CUDA 3D SAR library (VNA_AlGo). Build it first with # `bash $(GPR_CPP_DIR)/build_cmake.sh`; it is NOT built by this Makefile. CUDA # headers and libnvrtc come from the pip nvidia-* packages inside the VNA_AlGo -# venv (same detection as build_cmake.sh); libcuda is the system driver. -GPR_CPP_DIR ?= /home/awe/Documents/VNA_AlGo/gpr_cpp +# venv (same detection as build_cmake.sh); when those are absent (e.g. Jetson, +# where CUDA comes with JetPack) the system toolkit at /usr/local/cuda is used. +# libcuda is always the system driver. +GPR_CPP_DIR ?= $(HOME)/Documents/VNA_AlGo/gpr_cpp GPR_CPP_LIB ?= $(GPR_CPP_DIR)/build/libgpr_core_cpp.a GPR_VENV ?= $(GPR_CPP_DIR)/../.venv GPR_CUDA_INC_DIR ?= $(dir $(firstword $(wildcard $(GPR_VENV)/lib/python*/site-packages/nvidia/*/include/nvrtc.h))) GPR_NVRTC_LIB ?= $(firstword $(wildcard $(GPR_VENV)/lib/python*/site-packages/nvidia/*/lib/libnvrtc.so*)) +# System-CUDA fallback. An empty GPR_CUDA_INC_DIR would also corrupt the compile +# command: a bare `-I` swallows the next argument. +ifeq ($(strip $(GPR_CUDA_INC_DIR)),) +GPR_CUDA_INC_DIR := /usr/local/cuda/include +endif +ifeq ($(strip $(GPR_NVRTC_LIB)),) +GPR_NVRTC_LIB := $(firstword $(wildcard /usr/local/cuda/lib64/libnvrtc.so*)) +endif GPR_CUDA_LIB_DIR := $(dir $(GPR_NVRTC_LIB)) # libnvrtc from pip ships only as libnvrtc.so.N (no .so symlink), so link the # full path; the rpath makes the binary find it without LD_LIBRARY_PATH. diff --git a/README.md b/README.md index 595b484..5e3b5cb 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,10 @@ controls plus a pixel-identical live plot through an embedded web UI. - For the `sar3d` processor (3D SAR): an NVIDIA GPU with the driver installed (`libcuda`) and the external `gpr_cpp` library from the VNA_AlGo project. It must be built **before** `make` (see below); its location is configurable via - the `GPR_CPP_DIR` make variable (default `/home/awe/Documents/VNA_AlGo/gpr_cpp`). + the `GPR_CPP_DIR` make variable (default `$HOME/Documents/VNA_AlGo/gpr_cpp`). + CUDA headers/libnvrtc are taken from the pip `nvidia-*` packages in the + VNA_AlGo venv when present, otherwise from the system toolkit at + `/usr/local/cuda` (Jetson/JetPack, apt `cuda-toolkit`). ## Build and run @@ -87,8 +90,9 @@ From the repository root: python3 -m venv .venv .venv/bin/python -m pip install --upgrade pip .venv/bin/python -m pip install -r requirements.txt -# 3D SAR library (external, CMake + NVRTC; CUDA headers come from pip nvidia-* packages): -bash /home/awe/Documents/VNA_AlGo/gpr_cpp/build_cmake.sh +# 3D SAR library (external, CMake + NVRTC; CUDA headers come from the pip +# nvidia-* packages in the VNA_AlGo venv, or /usr/local/cuda as a fallback): +bash ~/Documents/VNA_AlGo/gpr_cpp/build_cmake.sh make # build the C++ binaries into build/bin/ ``` @@ -114,6 +118,34 @@ Run the desktop GUI: `./start.sh --help`. The acquisition device (LibreVNA, Kamil ADC, …) is detected automatically from the active config's `radar.model` — there is no per-device flag. +## Jetson (aarch64) bring-up + +Ubuntu 22.04 on Jetson has glibc 2.35, and PyQt6 6.8+ ships only +`manylinux_2_39` aarch64 wheels — `requirements.txt` therefore pins PyQt6 to +`<6.8` on aarch64 (6.7.1 is the last release with a compatible wheel). With +that pin the stock `./start.sh` provisioning works; the extra steps are only +for the CUDA-backed `sar3d` processor: + +```bash +# 1. gpr_cpp against the JetPack system CUDA (no pip nvidia-* packages needed): +git clone ~/Documents/VNA_AlGo +GPR_BUILD_PYTHON=OFF bash ~/Documents/VNA_AlGo/gpr_cpp/build_cmake.sh +# build_cmake.sh falls back to /usr/local/cuda automatically; override with +# CUDA_INC=... CUDA_LIB=... if the toolkit lives elsewhere. + +# 2. copy the replay dataset (for dataset-replay profiles) and point +# radar.replay.dataset_dir in the profile at the local copy — the path in +# run_config_examples/*.json is machine-specific. + +# 3. normal launch; make picks up /usr/local/cuda when the VNA_AlGo venv has +# no pip nvidia-* packages: +./start.sh --profile run_config_examples/run_config_replay_vna.example.json +``` + +If linking fails with `cannot find -lcuda`, the driver stub lives at +`/usr/local/cuda/lib64/stubs/libcuda.so`; on JetPack the real driver is +`/usr/lib/aarch64-linux-gnu/nvidia/libcuda.so.1` (present after boot). + ## Running without hardware (emulation) Two ways to run the full pipeline with no radar attached: diff --git a/requirements.txt b/requirements.txt index 8630215..e525707 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,11 @@ libusb1>=3.1 pyserial>=3.5,<4 pyvisa>=1.14 PyVISA-py>=0.7 # pure-Python VISA backend ("@py"), required by the SN9000 (and any visa_library="@py") path -PyQt6>=6.6 +# PyQt6 6.8+ ships only manylinux_2_39 aarch64 wheels (glibc >= 2.39); Jetson / +# Ubuntu 22.04 has glibc 2.35, so pip would fall back to a source build that +# dies on qmake. 6.7.1 is the last release with a manylinux_2_28 aarch64 wheel. +PyQt6>=6.6,<6.8; platform_machine == "aarch64" +PyQt6>=6.6; platform_machine != "aarch64" pyqtgraph>=0.13.7 rpi-hardware-pwm>=0.2.2,<1 fastapi>=0.110 # embedded web UI (browser view + controls), served in-process diff --git a/start.sh b/start.sh index 255b25b..726d617 100755 --- a/start.sh +++ b/start.sh @@ -225,14 +225,29 @@ run_privileged() { } ensure_system_dependencies() { - if command -v pkg-config >/dev/null 2>&1 && pkg-config --exists libusb-1.0; then + # Qt >= 6.5 xcb platform plugin needs libxcb-cursor0; aarch64/Jetson images + # (and some minimal desktops) ship without it, and the GUI then dies at + # startup with "could not load the Qt platform plugin xcb". apt-only: other + # distros/managers name these differently and usually have them preinstalled. + local qt_gui_packages_missing=0 + if command -v apt-get >/dev/null 2>&1 && command -v dpkg-query >/dev/null 2>&1; then + local package + for package in libxcb-cursor0 libxkbcommon-x11-0; do + if ! dpkg-query -W -f='${Status}' "${package}" 2>/dev/null | grep -q "install ok installed"; then + qt_gui_packages_missing=1 + fi + done + fi + + if command -v pkg-config >/dev/null 2>&1 && pkg-config --exists libusb-1.0 \ + && ((qt_gui_packages_missing == 0)); then return fi echo "[start.sh] Installing system dependency: libusb-1.0 dev headers..." if command -v apt-get >/dev/null 2>&1; then run_privileged apt-get update - run_privileged apt-get install -y pkg-config libusb-1.0-0-dev + run_privileged apt-get install -y pkg-config libusb-1.0-0-dev libxcb-cursor0 libxkbcommon-x11-0 elif command -v dnf >/dev/null 2>&1; then run_privileged dnf install -y pkgconf-pkg-config libusb1-devel elif command -v yum >/dev/null 2>&1; then