Rename kamil_adc to rph_radar and fix its data path

This commit is contained in:
Ayzen
2026-10-06 18:15:18 +03:00
parent aef549ea76
commit a185e61495
94 changed files with 2851 additions and 9485 deletions
+46 -14
View File
@@ -19,7 +19,7 @@ skips overwritten frames and continues from the retained tail:
1. **Acquisition** — Python producers configure the radar, acquire frequency sweeps,
and publish raw S21 traces. Both single and multi-device LibreVNA use
`matrix_raw_producer`; Kamil ADC uses `kamil_adc_raw_producer` with its C++ collector.
`matrix_raw_producer`; RadioPhotonic radar (RPH) uses `rph_radar_raw_producer` with its C++ collector.
2. **Preprocessing** — `data_preprocessor` applies through calibration,
reference subtraction, optional frequency-domain notch filtering, and an
optional object-based MIMO correction of S21.
@@ -45,8 +45,11 @@ controls, processing settings and a copy of the live plot through an embedded we
- **librevna** — single LibreVNA.
- **librevna_multi** — synchronized multi-device LibreVNA.
- **kamil_adc** — [Kamil ADC collector](data_acq_and_processing/kamil_adc_collector/README.md),
with optional laser control and [temperature monitoring](python_app/hardware_full/laser_control/monitoring/README.md).
- **rph_radar** — [RadioPhotonic radar (RPH) collector](data_acq_and_processing/rph_radar_collector/README.md),
with manual laser setpoints or LD1 current variation via **Apply Radar**.
The application owns the collector and exchanges complete sweeps over a PTY.
Switching to a different antenna pair starts a fresh ADC session after settling;
queued samples and an initial partial sweep are discarded before using that pair.
- **mock / simulator** — driver-less mode for development without hardware.
## Processing modes
@@ -86,7 +89,7 @@ so an older in-flight result cannot overwrite new geometry.
| Path | Contents |
| --- | --- |
| `data_acq_and_processing/` | C++ pipeline: `preprocessing/`, `processing/` (including `locator/`), `kamil_adc_collector/`, shared `common_cpp/` (config, IPC rings, H7992 driver), and vendored `third_party/` (Eigen, nlohmann/json). |
| `data_acq_and_processing/` | C++ pipeline: `preprocessing/`, `processing/` (including `locator/`), `rph_radar_collector/`, shared `common_cpp/` (config, IPC rings, H7992 driver), and vendored `third_party/` (Eigen, nlohmann/json). |
| `python_app/` | Python application: `gui/`, `orchestration/` (process supervisor, shared-memory readers, config), `hardware_full/` (device drivers and services), `webui/`, `storage/`, `models/`, `workflows/`, `scripts/` (producers and tools), and `tests/`. |
| `run_config_examples/` | Ready-made configuration profiles, one per hardware setup. |
| `deploy/` | systemd daemon installer, and the USB update kit for the Pi and Jetson (`pack-usb.sh`, `update.sh`). |
@@ -96,8 +99,7 @@ so an older in-flight result cannot overwrite new geometry.
## Requirements
- Linux (POSIX shared memory; GPIO on Raspberry Pi). The deployment target is a
**Raspberry Pi 5**; hardware PWM gating for the generator sweep is Pi 5
specific (GPIO12/13/18/19, `dtoverlay=pwm-2chan`).
**Raspberry Pi 5**.
- A C++20 compiler and `make`; Eigen and nlohmann/json are vendored.
- `libusb-1.0` runtime and `libatomic.so.1` (`libatomic1` on Debian/Ubuntu).
Python ring readers/writers use lock-free atomic loads, stores and cursor CAS
@@ -121,7 +123,7 @@ python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -r requirements.txt
make # data_preprocessor and data_processor in build/bin/
make kamil_adc_collector # also required for Kamil ADC acquisition
make rph_radar_collector # also required for RadioPhotonic radar (RPH) acquisition
```
`make` builds the sar3d GPU code when it finds CUDA (see Requirements) and
@@ -163,7 +165,7 @@ not need to be replaced.
The default `run_config.json` already sets `radar.driver_mode: "mock"`, so the
producer generates synthetic S-parameters and no radar is needed. Mock acquisition
supports the LibreVNA models; Kamil ADC needs native acquisition.
supports the LibreVNA models; RadioPhotonic radar (RPH) needs native acquisition.
Both LibreVNA modes share one simulator: a point reflector moves back and forth
along the antenna array and between depths 3.25–4.25 m over an eight-second cycle.
Each S21 uses the actual transmitter–target–receiver distance from the configured
@@ -250,9 +252,9 @@ are never overwritten; missing raw/preprocessed counterparts produce empty array
and stages pair only by the exact acquisition key. Its `vna_config_profile.json` companion
leaves the NumPy dataset's `config_profile.json` intact. A streaming write failure
keeps all collections already published; only the incomplete collection is discarded.
The offline snapshot converter uses this same exporter. Legacy snapshots without
capture windows retain repeated IDs through one-to-one time/index matching;
processing completion timestamps are not compared with acquisition timestamps.
Legacy snapshots without capture windows retain repeated IDs through one-to-one
time/index matching; processing completion timestamps are not compared with
acquisition timestamps.
### Calibration and reference sets
@@ -342,8 +344,38 @@ back to the root profile. **Load Config** and **Save Config** manage desktop pro
Hardware examples are in `run_config_examples/`. The root `run_config.json` is
intentionally mock; select a hardware profile explicitly on a real device. A
change of model, serials or sweep parameters changes the `radar_key` used to find
calibration/reference sets; select or capture matching sets before **Start**.
change of model, serials, sweep parameters or multi-device switch positions changes
the `radar_key` used to find calibration/reference sets; select or capture matching
sets before **Start**. Changing the multi-device reference-clock source also resets
display history. For RadioPhotonic radar (RPH), identity follows the phase anchors, output
band and acquisition/laser settings; executable/TTY paths and LibreVNA-only sweep
fields do not affect it. RPH processing frequency controls use its output band.
Phase, band and timeout errors are rejected before a running pipeline is stopped.
Profiles with model `kamil_adc` are rejected with an explicit error: use
`rph_radar` and the `radar.rph_radar` section. An inactive `radar.kamil_adc`
section left in older saved profiles is ignored; there are no aliases or automatic
data migrations. Old RPH calibration/reference sets use a different
measurement key and are not selected by the renamed mode.
### RPH phase calibration
Use `run_config_examples/run_config_rph_radar.example.json` for **RadioPhotonic radar (RPH)**.
Apply the desired laser settings with **Apply Radar**, then stop acquisition before
running the calibration tool:
```bash
.venv/bin/python -m python_app.scripts.rph_radar_calibrate --config run_config.json --sweeps 200
.venv/bin/python -m python_app.scripts.rph_radar_calibrate --config run_config.json --sweeps 200 --apply
```
Pass the path to your active RPH profile. The first command reports measured phase
anchors; `--apply` captures again and writes only `phase0_rad` and `phase1_rad` in
`radar.rph_radar.phase_calibration`. Frequency anchors must already describe the
known sweep endpoints. The tool uses current acquisition settings, sends no laser
commands, preserves every other JSON byte, and refuses to overwrite a profile
edited during capture. Band and point count stay unchanged. `--warmup` controls
how many initial sweeps to discard (default 10).
## Deployment
@@ -394,7 +426,7 @@ ASAN_OPTIONS=detect_leaks=0 make check-native NATIVE_SANITIZERS=address,undefine
The tests cover failed writes and settings commits, recordings during manual Save,
repeated Start/Stop/Close, web-action cancellation, malformed IPC frames, hardware
resource cleanup with mock failures, and an isolated deployment update. Native tests
also exercise mutated frames, ring concurrency, locator input and ADC spool recovery.
also exercise mutated frames, ring concurrency, locator input and ADC whole-sweep PTY overflow recovery.
Firmware host tests check cart timer rollover and SBUS packing; they do not validate
physical timing. Real devices, GPIO and the CUDA backend need their own hardware run.