Legal Entity: Ceradon Systems, LLC (West Haven, UT)
CAGE Code: 179U9 (Active)
Unique Entity ID (UEI): UZA9PFJ9RDL6
Status: Commercial Proprietary Asset. All rights assigned per the
Intellectual Property Assignment Agreement (Sept 2025).
Vantage Scanner demo node. Streams WiFi CSI from an Intel AX210 via FeitCSI and outputs presence, direction and a coarse pose estimate (standing / crouching / prone).
Absolute Boundary Principle: "Ceradon Vantage is a proprietary commercial product of Ceradon Systems, LLC. It is architecturally and legally independent from open-source planning tools".
Core logic: planning tools produce hypotheses; Vantage produces authoritative sensing decisions.
- Passive ISR flagship: zero-emission through-wall human sensing.
- Problem solved: detects human presence, pose, and movement without active radar signatures or visible/IR emissions, reducing operator RF footprint ("glowing") in contested environments.
- Battle drill support: supports Breach Operations (SOSRA) and "Enter and Clear" maneuvers by providing visibility into structures before the breach force crosses the threshold.
- Sensing engine: WiFi Channel State Information (CSI) for posture-aware alerts and skeletal movement tracking.
- Form factors: modular Tripod Nodes (long-duration overwatch), Handheld Kits (breaching teams), and UxS Payloads.
- Edge architecture: offline, edge-only pipelines on Pi or Jetson-class hardware.
- ATAK readiness: output (presence zones and skeletal overlays) is designed to integrate directly into ATAK to make sensing data part of the map.
- Standardized telemetry: future compatibility with Telemetry Forge schemas to unify data language across Ceradon products.
- Intel AX210 NIC with two antennas
- Kali/Linux or similar with kernel iwlwifi driver
- Optional: display for curses TUI
The setup.sh script installs dependencies, builds FeitCSI and creates a Python
virtual environment:
./setup.sh
source .venv/bin/activate-
Grant FeitCSI capabilities once so capture can run without sudo prompts:
sudo setcap cap_net_admin,cap_net_raw+eip /usr/local/bin/feitcsi
-
If your desktop asks for passwords during capture, use the GUI’s Tools → “Setup Passwordless sudo…” to add a limited sudoers entry. This lets the app bring the NIC up/down, mount debugfs, and run FeitCSI without blocking prompts.
-
If reconnection to Wi‑Fi profiles is flaky after stopping capture, use Tools → “Fix Wi‑Fi Profile…” to clear stale interface bindings and reconnect.
Verify the install with the bundled demo which captures for ten seconds and prints JSON results:
./scripts/demo.sh --with-poseStart live capture using the Python interface (replace wlan0 with your AX210
interface):
python run.py --iface wlan0 --tui --poseFor offline playback of a saved log:
python run.py --replay data/sample_csi.b64 --tui --poseEach window emits a JSON object like:
{"timestamp": "2024-01-01T00:00:00", "presence": true,
"pose": "standing", "direction": "left", "distance_m": 1.6,
"confidence": 0.78}Logs are written to data/presence_log.jsonl and rotate when exceeding 1 MB.
Baseline amplitudes for an empty room improve stability:
python -m csi_node.baseline --duration 60Follow this checklist for reliable results:
- Use the GUI and click Tools → “Through‑Wall Preset”. This sets 2.4 GHz
channel 1, 20 MHz, enables Dat mode, applies an RSSI offset, and uses a
steadier 2.5 s window. Direction threshold (
rssi_delta) is raised for stability. - Start capture in Dat mode (press “Start”) and wait until the log shows “JSON log active: data/csi_raw.log”. Keep it running throughout baseline and calibration.
- Capture a baseline in an empty room:
- GUI: Tools → “Capture Baseline (60s)”. Keep the room still while it runs.
- Why: improves presence stability and reduces idle false positives by subtracting the empty‑room CSI.
- Calibrate distance in the same environment:
- In the GUI: Tools → “Calibrate Distance…”, supply two short logs at known
distances (e.g., 1.0 m and 3.0 m). The GUI writes
tx_power_dbmandpath_loss_exponentintocsi_node/config.yamland shows a calibration badge.
- In the GUI: Tools → “Calibrate Distance…”, supply two short logs at known
distances (e.g., 1.0 m and 3.0 m). The GUI writes
- Use the “Live Tracking” window for audience display:
- Tools → “Show Tracking Window” — this shows only the latest frame (presence, direction, distance, confidence) without log spam.
- If direction flickers, raise
rssi_delta(e.g., 3.5 → 4.5 dB). If presence is too sensitive, raisevariance_thresholdandpca_thresholda notch.
Troubleshooting quick fixes:
- If distance looks too small or doesn’t change with motion, (re)run calibration in the demo location.
- If presence stays true when nobody moves, record a baseline (ensure capture
is running so the JSON log is active) and increase
variance_threshold/pca_threshold. A longer window (2.5–3.0 s) also helps. - Prefer 2.4 GHz (ch1/20 MHz) through one interior wall for stronger signals.
- Presence: detects motion-induced changes in Wi‑Fi channels using CSI variance and PCA. It will respond strongly to a moving person, but also to moving objects (e.g., doors, fans). It does not classify “human vs object”. When a person becomes completely still, presence confidence will fall over time.
- Direction: coarse left/center/right based on the difference between the two antenna chains’ average RSSI. This is a relative left/right cue, not an absolute angle.
- Distance: ballpark estimate from average RSSI using a log‑distance model. Requires calibration for your room to be meaningful. It is not centimeter‑ accurate ranging, but a rough “nearer/farther” indicator.
- Through‑wall: Wi‑Fi penetrates most interior walls; presence and coarse direction typically still work through one wall, but confidence and distance accuracy degrade. Prefer 2.4 GHz (e.g., channel 1, 20 MHz) for better penetration. Results depend on construction and interference.
- Multiple people: the current demo is single‑target. Multiple movers will produce a combined response; it cannot count people or track them independently.
- Confidence: an exponential moving average (EMA) of the binary presence signal (0/1). It is a stability score, not a calibrated probability.
For safety‑critical or security use, additional sensing and validation are recommended. This repo is a demo/prototype.
- Direction is inferred from per‑chain RSSI delta. In file/"Dat mode", the converter now estimates RSSI per chain from CSI magnitudes so direction works without the live extractor.
- Distance uses a crude log‑distance model driven by average RSSI; tune it for your room via calibration below.
Collect two short CSI logs at known distances (e.g., 1.0 m and 3.0 m):
# Start capture (Dat mode creates data/csi_raw.log with rssi values)
./scripts/10_csi_capture.sh &
sleep 8; cp data/csi_raw.log data/csi_raw_d1.log # at distance d1
# Move to distance d2, wait a few seconds
sleep 8; cp data/csi_raw.log data/csi_raw_d2.log # at distance d2
kill %1 || true
# Estimate parameters and write them to config
python -m csi_node.calibrate \
--log1 data/csi_raw_d1.log --d1 1.0 \
--log2 data/csi_raw_d2.log --d2 3.0 \
--config csi_node/config.yamlThe pipeline reads tx_power_dbm and path_loss_exponent from
csi_node/config.yaml to map RSSI to meters.
Calibration here is not “training a model” — it sets two parameters for the RSSI→distance curve and optionally establishes a static CSI baseline:
- Baseline:
python -m csi_node.baseline --duration 60records empty‑room CSI to subtract static structure. Improves presence stability. - Distance calibration:
python -m csi_node.calibrate(also available from the GUI Tools menu) computes:path_loss_exponentn from two positions at distances d1, d2tx_power_dbm(expected RSSI at 1 m) These are written intocsi_node/config.yaml. Re‑running calibration updates the parameters; it does not accumulate a dataset.
You can also “replay” saved logs via the GUI (Replay mode) or CLI to validate changes. Replay does not change calibration by itself — only the calibrator script writes new parameters.
Most behavior is controlled by a few intuitive thresholds (editable from the GUI: Tools → “Edit Thresholds…”):
variance_threshold(default 5.0): motion sensitivity from raw CSI amplitude variance. Increase to reduce false positives; decrease to catch subtler motion.pca_threshold(default 1.0): motion sensitivity from the first PCA component; complements variance. Increase to be stricter.rssi_delta(default 2.0 dB): direction sensitivity. Larger values make left/right decisions fewer and more stable; smaller values make the system switch sides more readily.tx_power_dbmandpath_loss_exponent: set by the calibration helper. These control the mapping from RSSI to meters.dat_rssi_offset(GUI field “RSSI offset”): shifts the derived RSSI scale in Dat mode so numbers look dBm‑ish. It does not affect relative direction but does affect distance unless you calibrate; after calibration, this offset is less important.window_size/window_hop: temporal smoothing vs. responsiveness. Larger windows are stabler; smaller windows respond faster.
Recommended starting points for through‑wall demos:
- Channel: 1 (2.412 GHz), Width: 20 MHz — better penetration, less DFS.
- Run baseline with no people moving.
- Calibrate distance once at ~1 m and ~3 m on your demo path.
- If direction flickers, raise
rssi_deltato ~3–4 dB. - If presence is too jumpy, raise
variance_thresholdslightly (e.g., +1).
- Open the GUI. In Live Settings, check “Dat mode”. Set “RSSI offset” ≈ −60.
- Tools → “Edit Thresholds…” if you want to pre‑tune
rssi_deltaor others. - Click Start. Verify presence toggles with motion and left/right flips as you move.
- Tools → “Calibrate Distance…”: select two short logs at 1 m and 3 m, enter distances, and apply. Distance numbers will be more meaningful.
- For through‑wall, set Channel 1 / Width 20 MHz and place the device so it receives traffic passing through the wall; repeat calibration if the setting changes.
- Live Settings: pick device, channel, width, and toggle Dat mode; set RSSI offset (Dat mode only) and optional pose.
- Controls: Start/Stop, Autoscroll, copy/save/clear log. A status line shows passwordless sudo, calibration status, and baseline status.
- Tools menu:
- Diagnostics: collects a detailed system/driver/capture log file under
data/. - Setup Passwordless sudo…: guided sudoers entry for smoother capture.
- Fix Wi‑Fi Profile…: clears stale interface bindings then reconnects.
- Through‑Wall Preset: applies stable through‑wall defaults.
- Calibrate Distance…: estimates
tx_power_dbmandpath_loss_exponentfrom two logs at known distances and writes them to the config. - Calibration Wizard…: prompts for two distances and auto‑records timestamped calibration segments before computing parameters.
- Edit Thresholds…: updates
variance_threshold,pca_threshold,rssi_delta,tx_power_dbm,path_loss_exponent, anddat_rssi_offset. - Show Tracking Window: opens a clean live view of the latest frame.
- Capture Baseline (60s): records a timestamped baseline and selects it.
- Import Baseline…: picks an existing
baseline.npzfor use. - Instructions: opens this README for quick guidance.
- Diagnostics: collects a detailed system/driver/capture log file under
A minimal Tk GUI is included to start/stop capture and replay without the terminal.
Run it:
# Install Tk if missing (Debian/Ubuntu/Kali)
sudo apt-get install -y python3-tk
# Launch the GUI (uses the project virtualenv if present)
./scripts/launch_gui.shAdd a desktop shortcut:
# If your checkout path differs, edit Exec/Path inside:
sed -n '1,120p' scripts/csi-presence-gui.desktop
# Then copy to your user applications dir
cp scripts/csi-presence-gui.desktop ~/.local/share/applications/Notes:
- Live capture requires the FeitCSI binary and NIC privileges. Grant caps once
to avoid sudo:
sudo setcap cap_net_admin,cap_net_raw+eip /usr/local/bin/feitcsi. - The GUI streams logs and JSON outputs; it avoids the curses TUI.
- Auto‑preflight: in Live mode the GUI will automatically disable Wi‑Fi,
unblock rfkill, load
iwlwifi, set the reg domain, and attempt to grant capabilities to FeitCSI before starting capture. It retries widths (chosen → 80 → 40 → 20 MHz) untildata/csi_raw.logis detected. - Auto‑postflight: when you click Stop, the GUI re‑enables Wi‑Fi, restarts NetworkManager (via systemd or service), turns networking back on, and tries to reconnect to your previously active Wi‑Fi connection(s).
- Diagnostics: click “Diagnostics” to generate
data/diagnostics-YYYYMMDD-HHMMSS.txtwith system info, Wi‑Fi state, FeitCSI caps, recent logs, and filtered kernel messages. The GUI opens the file after saving.
FeitCSI relies on iwlwifi debugfs at /sys/kernel/debug/iwlwifi and wireless
privileges. The GUI tries to run preflight and capture with pkexec (GUI
authorization) or sudo -n where possible. To minimize prompts:
-
Grant FeitCSI capabilities (once):
sudo setcap cap_net_admin,cap_net_raw+eip /usr/local/bin/feitcsi
-
Ensure debugfs is mounted (the GUI attempts this):
sudo mount -t debugfs debugfs /sys/kernel/debug
-
Optional: allow passwordless sudo for specific commands. Create a file via
sudo visudo -f /etc/sudoers.d/csi-presence-nodewith:Cmnd_Alias CSI_CMDS =
/usr/sbin/rfkill unblock all,
/usr/sbin/modprobe iwlwifi,
/usr/sbin/setcap cap_net_admin,cap_net_raw+eip /usr/local/bin/feitcsi,
/usr/bin/iw reg set US,
/bin/systemctl restart NetworkManager,
/bin/systemctl start NetworkManager,
/usr/bin/mount -t debugfs debugfs /sys/kernel/debug,
/usr/local/bin/feitcsi *yourusername ALL=(root) NOPASSWD: CSI_CMDS
Replace yourusername with your login name. Reopen the GUI after changes.
If reconnection does not happen automatically
- Your desktop may require interactive authorization for restarting
NetworkManager. In that case, either approve the
pkexecprompt or pre‑grant permissions, or reconnect manually with:nmcli networking on && nmcli radio wifi onnmcli connection up id <YourSSID>(ornmcli connection up uuid <UUID>)
demo.sh runs a quick self‑test: it checks the FeitCSI binary, captures CSI for
10 s and tails the JSON log. Use --replay <file> to run the pipeline on a
recorded capture instead.
An offline regression test is included:
python tests/test_offline.pyEdit csi_node/config.yaml for thresholds and file paths. Results include
presence flag, left/center/right direction, coarse pose label and a crude
RSSI‑based distance estimate.
MIT