Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ Example: `docker run -e CSI_SOURCE=esp32 -p 3000:3000 -p 5005:5005/udp ruvnet/wi

### From Source (Rust)

On Debian/Ubuntu-based Linux systems, install the native desktop prerequisites before the first Rust release build:

```bash
sudo apt update
sudo apt install -y \
build-essential pkg-config \
libglib2.0-dev libgtk-3-dev \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.1-dev
```

This prepares the native GTK/WebKit dependencies used by the desktop/Tauri crates in this workspace.

```bash
git clone https://github.com/ruvnet/RuView.git
cd RuView/rust-port/wifi-densepose-rs
Expand Down Expand Up @@ -1582,6 +1596,28 @@ rustup update stable
rustc --version
```

### Build: Linux native desktop prerequisites

If you are compiling the Rust workspace on a Debian/Ubuntu-based Linux system, install the native desktop development packages first:

```bash
sudo apt update
sudo apt install -y \
build-essential pkg-config \
libglib2.0-dev libgtk-3-dev \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.1-dev
```

Then rerun:

```bash
cargo build --release
```

This is the same Linux pre-step referenced in the Rust source build section and covers the common GTK/WebKit `pkg-config` requirements used by the desktop build.

### Windows: RSSI mode shows no data

Run the terminal as Administrator (required for `netsh wlan` access). Verified working on Windows 10 and 11 with Intel AX201 and Intel BE201 adapters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ axum = { workspace = true }
tower-http = { version = "0.5", features = ["fs", "cors", "set-header"] }
tokio = { workspace = true, features = ["full", "process"] }
futures-util = "0.3"
ruvector-mincut = { workspace = true }

# Serialization
serde = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ pub mod vital_signs;
pub mod rvf_container;
pub mod rvf_pipeline;
pub mod graph_transformer;
#[allow(dead_code)]
pub mod trainer;
pub mod dataset;
pub mod sona;
pub mod sparse_inference;
#[allow(dead_code)]
pub mod embedding;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! - Serves the static UI files (port 8080)
//!
//! Replaces both ws_server.py and the Python HTTP server.
#![allow(dead_code)]

mod adaptive_classifier;
pub mod cli;
Expand Down Expand Up @@ -1658,9 +1659,11 @@ async fn windows_wifi_task(state: SharedState, tick_ms: u64) {

// Populate persons from the sensing update (Kalman-smoothed via tracker).
let raw_persons = derive_pose_from_sensing(&update);
let mut last_tracker_instant = s.last_tracker_instant.take();
let tracked = tracker_bridge::tracker_update(
&mut s.pose_tracker, &mut s.last_tracker_instant, raw_persons,
&mut s.pose_tracker, &mut last_tracker_instant, raw_persons,
);
s.last_tracker_instant = last_tracker_instant;
if !tracked.is_empty() {
update.persons = Some(tracked);
}
Expand Down Expand Up @@ -1794,9 +1797,11 @@ async fn windows_wifi_fallback_tick(state: &SharedState, seq: u32) {
};

let raw_persons = derive_pose_from_sensing(&update);
let mut last_tracker_instant = s.last_tracker_instant.take();
let tracked = tracker_bridge::tracker_update(
&mut s.pose_tracker, &mut s.last_tracker_instant, raw_persons,
&mut s.pose_tracker, &mut last_tracker_instant, raw_persons,
);
s.last_tracker_instant = last_tracker_instant;
if !tracked.is_empty() {
update.persons = Some(tracked);
}
Expand Down Expand Up @@ -3214,7 +3219,7 @@ async fn adaptive_status(State(state): State<SharedState>) -> Json<serde_json::V
"trained_frames": model.trained_frames,
"accuracy": model.training_accuracy,
"version": model.version,
"classes": adaptive_classifier::CLASSES,
"classes": model.class_names,
"class_stats": model.class_stats,
})),
None => Json(serde_json::json!({
Expand Down Expand Up @@ -3600,9 +3605,9 @@ async fn udp_receiver_task(state: SharedState, udp_port: u16) {
};

// Feed field model calibration if active (use per-node history for ESP32).
if let Some(ref mut fm) = s.field_model {
if let Some(ns) = s.node_states.get(&node_id) {
field_bridge::maybe_feed_calibration(fm, &ns.frame_history);
if let Some(frame_history) = s.node_states.get(&node_id).map(|ns| ns.frame_history.clone()) {
if let Some(ref mut fm) = s.field_model {
field_bridge::maybe_feed_calibration(fm, &frame_history);
}
}

Expand Down Expand Up @@ -3685,9 +3690,11 @@ async fn udp_receiver_task(state: SharedState, udp_port: u16) {
};

let raw_persons = derive_pose_from_sensing(&update);
let mut last_tracker_instant = s.last_tracker_instant.take();
let tracked = tracker_bridge::tracker_update(
&mut s.pose_tracker, &mut s.last_tracker_instant, raw_persons,
&mut s.pose_tracker, &mut last_tracker_instant, raw_persons,
);
s.last_tracker_instant = last_tracker_instant;
if !tracked.is_empty() {
update.persons = Some(tracked);
}
Expand Down Expand Up @@ -3848,9 +3855,9 @@ async fn udp_receiver_task(state: SharedState, udp_port: u16) {
};

// Feed field model calibration if active (use per-node history for ESP32).
if let Some(ref mut fm) = s.field_model {
if let Some(ns) = s.node_states.get(&node_id) {
field_bridge::maybe_feed_calibration(fm, &ns.frame_history);
if let Some(frame_history) = s.node_states.get(&node_id).map(|ns| ns.frame_history.clone()) {
if let Some(ref mut fm) = s.field_model {
field_bridge::maybe_feed_calibration(fm, &frame_history);
}
}

Expand Down Expand Up @@ -3895,9 +3902,11 @@ async fn udp_receiver_task(state: SharedState, udp_port: u16) {
};

let raw_persons = derive_pose_from_sensing(&update);
let mut last_tracker_instant = s.last_tracker_instant.take();
let tracked = tracker_bridge::tracker_update(
&mut s.pose_tracker, &mut s.last_tracker_instant, raw_persons,
&mut s.pose_tracker, &mut last_tracker_instant, raw_persons,
);
s.last_tracker_instant = last_tracker_instant;
if !tracked.is_empty() {
update.persons = Some(tracked);
}
Expand Down Expand Up @@ -4031,9 +4040,11 @@ async fn simulated_data_task(state: SharedState, tick_ms: u64) {

// Populate persons from the sensing update (Kalman-smoothed via tracker).
let raw_persons = derive_pose_from_sensing(&update);
let mut last_tracker_instant = s.last_tracker_instant.take();
let tracked = tracker_bridge::tracker_update(
&mut s.pose_tracker, &mut s.last_tracker_instant, raw_persons,
&mut s.pose_tracker, &mut last_tracker_instant, raw_persons,
);
s.last_tracker_instant = last_tracker_instant;
if !tracked.is_empty() {
update.persons = Some(tracked);
}
Expand Down