yggvault ratatoskr-space connected via regular web
Color theme
also available via yggdrasil mesh http://[203:b338:2a84:a18f:986:47ae:1a4:d8d3]/pkg/ruview/v1613
vault / ruview / v1613

ruview @ v1613

integrity

size
61.1 MiB
downloaded
last checked
source https://github.com/ruvnet/RuView · available · github

release notes

Automated release from CI pipeline

Changes: fix(firmware): correct ESP32 edge heart rate — sample-rate + harmonic lock (#987) (#988)

The edge vitals HR was stuck at ~45 BPM regardless of true heart rate (Apple Watch ground truth 87 BPM read as ~45) and "dropped a lot" between frames. Two root causes:

  1. Stale fixed sample rate. estimate_bpm_zero_crossing() used a hardcoded sample_rate = 10.0f (and the biquads a separate fs = 20.0f). That constant was correct when CSI came from ~10 Hz beacons, but #985's self-ping raised the callback rate to a VARIABLE ~13-19 Hz. BPM scales as (assumed_rate / actual_rate) x true, so a true 87 read ~45, and because the real rate fluctuates with CSI yield while the code assumed a fixed value, the reported HR swung frame-to-frame (the "drops").

  2. Breathing-harmonic lock. Zero-crossing HR estimation locked onto a breathing harmonic — a 0.25 Hz breathing fundamental puts its 3rd harmonic at ~0.74 Hz ~= 44 BPM, right in the HR band — so it parked at ~45 BPM independent of the real heartbeat.

Fix:

Validated on hardware (ESP32-S3, COM8/192.168.1.80) vs an unmodified board (192.168.1.67) and an Apple Watch (87 BPM):

Known limitation: under subject motion (motion=Y) HR is still noisy because the breathing estimate degrades and misguides harmonic rejection; motion gating + breathing robustness are follow-ups.

Co-Authored-By: claude-flow ruv@ruv.net

Follow-up to 332c2a98d. The HR harmonic rejection was fed the noisy zero-crossing breathing estimate, which under motion notched the wrong frequencies and let the autocorr lock onto the ~0.75 Hz breathing harmonic (~45 BPM). Generalize estimate_hr_autocorr -> estimate_periodicity_autocorr and drive HR harmonic rejection from a robust autocorrelation breathing period instead; widen the HR median smoother to N=13.

Hardware A/B (fixed .80 vs unmodified control .67, both edge_tier=2, subject in motion 100% of frames):

Reported breathing is unchanged (still zero-crossing); the autocorr breathing period is used only internally for HR harmonic rejection.

Co-Authored-By: claude-flow ruv@ruv.net

Co-Authored-By: claude-flow ruv@ruv.net

Docker Image: ghcr.io/ruvnet/RuView:992c2b25cb6c6fcf3ba4d80d2be906920831f54c

download

unix · zip
curl -fL -o v1613.zip https://ratatoskr.space/pkg/ruview/v1613.zip
                    printf '%s  %s\n' 'b4626903532516503563fa7167b8ffa976995cdeeef66c9b99149db200c60314' 'v1613.zip' | sha256sum -c -
windows · zip
$url = "https://ratatoskr.space/pkg/ruview/v1613.zip"
$out = "v1613.zip"
Invoke-WebRequest -Uri $url -OutFile $out
if ((Get-FileHash $out -Algorithm SHA256).Hash.ToLowerInvariant() -ne "b4626903532516503563fa7167b8ffa976995cdeeef66c9b99149db200c60314") { throw "sha256 mismatch" }
unix · tar.gz
curl -fL -o v1613.tar.gz https://ratatoskr.space/pkg/ruview/v1613.tar.gz
                    printf '%s  %s\n' 'fd57318d03ac72dfef36a99ff3257eb6917c3ee15aae6eec23f7c6165d5b6fa4' 'v1613.tar.gz' | sha256sum -c -
windows · tar.gz
$url = "https://ratatoskr.space/pkg/ruview/v1613.tar.gz"
$out = "v1613.tar.gz"
Invoke-WebRequest -Uri $url -OutFile $out
if ((Get-FileHash $out -Algorithm SHA256).Hash.ToLowerInvariant() -ne "fd57318d03ac72dfef36a99ff3257eb6917c3ee15aae6eec23f7c6165d5b6fa4") { throw "sha256 mismatch" }
download via yggdrasil mesh
unix · zip
curl -fL -o v1613.zip http://14cc7d57b5e70f679b851fe5b272ce17c70632ff4beb5b35ab64bc706b2485af.pk.ygg/pkg/ruview/v1613.zip
                    printf '%s  %s\n' 'b4626903532516503563fa7167b8ffa976995cdeeef66c9b99149db200c60314' 'v1613.zip' | sha256sum -c -
windows · zip
$url = "http://14cc7d57b5e70f679b851fe5b272ce17c70632ff4beb5b35ab64bc706b2485af.pk.ygg/pkg/ruview/v1613.zip"
$out = "v1613.zip"
Invoke-WebRequest -Uri $url -OutFile $out
if ((Get-FileHash $out -Algorithm SHA256).Hash.ToLowerInvariant() -ne "b4626903532516503563fa7167b8ffa976995cdeeef66c9b99149db200c60314") { throw "sha256 mismatch" }
unix · tar.gz
curl -fL -o v1613.tar.gz http://14cc7d57b5e70f679b851fe5b272ce17c70632ff4beb5b35ab64bc706b2485af.pk.ygg/pkg/ruview/v1613.tar.gz
                    printf '%s  %s\n' 'fd57318d03ac72dfef36a99ff3257eb6917c3ee15aae6eec23f7c6165d5b6fa4' 'v1613.tar.gz' | sha256sum -c -
windows · tar.gz
$url = "http://14cc7d57b5e70f679b851fe5b272ce17c70632ff4beb5b35ab64bc706b2485af.pk.ygg/pkg/ruview/v1613.tar.gz"
$out = "v1613.tar.gz"
Invoke-WebRequest -Uri $url -OutFile $out
if ((Get-FileHash $out -Algorithm SHA256).Hash.ToLowerInvariant() -ne "fd57318d03ac72dfef36a99ff3257eb6917c3ee15aae6eec23f7c6165d5b6fa4") { throw "sha256 mismatch" }
artifact format size hashes
v1613.zip zip 61.1 MiB
blake3-24 744d05a6323a0b86c8e9bdb26cb93d6762904bd99df3844c
sha256 b4626903532516503563fa7167b8ffa976995cdeeef66c9b99149db200c60314
sha1 3f904e165a81bc1b73791f08cabd624f2fda5fea
v1613.tar.gz tar.gz 59.3 MiB
blake3-24 19140eabed52b5c8875da8d7107c49cc5f3ae5909183ad53
sha256 fd57318d03ac72dfef36a99ff3257eb6917c3ee15aae6eec23f7c6165d5b6fa4
sha1 c1de9e744fcf043d9e4d98092d7ed34104e69bf5

install

bazel
http_archive(
    name = "ruview",
    urls = ["https://ratatoskr.space/pkg/ruview/v1613.tar.gz"],
    integrity = "sha256-/VcxjQOsct/vNqmf8yV+tpF8PuFarm7sI/fGFl1bb6Q=",
    strip_prefix = "ruview-v1613",
)
zig
.url = "https://ratatoskr.space/pkg/ruview/v1613.tar.gz",
install via yggdrasil mesh
bazel
http_archive(
    name = "ruview",
    urls = ["http://14cc7d57b5e70f679b851fe5b272ce17c70632ff4beb5b35ab64bc706b2485af.pk.ygg/pkg/ruview/v1613.tar.gz"],
    integrity = "sha256-/VcxjQOsct/vNqmf8yV+tpF8PuFarm7sI/fGFl1bb6Q=",
    strip_prefix = "ruview-v1613",
)
zig
.url = "http://14cc7d57b5e70f679b851fe5b272ce17c70632ff4beb5b35ab64bc706b2485af.pk.ygg/pkg/ruview/v1613.tar.gz",
← v1647v1611 →