Class: RoadToRubykaigi::SignalWindow::StepCadence
- Inherits:
-
Data
- Object
- Data
- RoadToRubykaigi::SignalWindow::StepCadence
- Defined in:
- lib/road_to_rubykaigi/signal_window.rb
Constant Summary collapse
- WINDOW_SECONDS =
2.0- MIN_STEP_INTERVAL_SECONDS =
min gap between steps (caps cadence at ~6.7Hz)
0.15- MIN_SAMPLES_FOR_LOCAL_MAXIMUM =
need prev/current/next to detect a local maximum
3
Instance Attribute Summary collapse
-
#recent_magnitudes ⇒ Object
readonly
Returns the value of attribute recent_magnitudes.
Instance Method Summary collapse
-
#hz ⇒ Object
Step cadence in Hz: count of local maxima in the recent magnitudes divided by the window duration.
- #ready? ⇒ Boolean
- #record(sample) ⇒ Object
Instance Attribute Details
#recent_magnitudes ⇒ Object (readonly)
Returns the value of attribute recent_magnitudes
6 7 8 |
# File 'lib/road_to_rubykaigi/signal_window.rb', line 6 def recent_magnitudes @recent_magnitudes end |
Instance Method Details
#hz ⇒ Object
Step cadence in Hz: count of local maxima in the recent magnitudes divided by the window duration. Walking produce one peak per footstrike, so cadence tracks step frequency.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/road_to_rubykaigi/signal_window.rb', line 21 def hz return 0.0 if recent_magnitudes.size < MIN_SAMPLES_FOR_LOCAL_MAXIMUM magnitudes = recent_magnitudes.map { |entry| entry[:magnitude] } mean = magnitudes.sum / magnitudes.size step_count = 0 last_step_time = nil (1...(recent_magnitudes.size - 1)).each do |i| time = recent_magnitudes[i][:time] magnitude = recent_magnitudes[i][:magnitude] prev_magnitude = recent_magnitudes[i - 1][:magnitude] next_magnitude = recent_magnitudes[i + 1][:magnitude] is_local_maximum = magnitude > prev_magnitude && magnitude > next_magnitude above_mean = magnitude > mean # only count bumps stronger than the average enough_gap_from_last_step = last_step_time.nil? || (time - last_step_time) >= MIN_STEP_INTERVAL_SECONDS if is_local_maximum && above_mean && enough_gap_from_last_step step_count += 1 last_step_time = time end end duration = recent_magnitudes.last[:time] - recent_magnitudes.first[:time] return 0.0 if duration <= 0 # guard against division by zero (just in case) step_count / duration end |
#ready? ⇒ Boolean
48 49 50 51 |
# File 'lib/road_to_rubykaigi/signal_window.rb', line 48 def ready? return false if recent_magnitudes.size < MIN_SAMPLES_FOR_LOCAL_MAXIMUM (recent_magnitudes.last[:time] - recent_magnitudes.first[:time]) >= WINDOW_SECONDS * READY_FILL_RATIO end |
#record(sample) ⇒ Object
11 12 13 14 15 16 17 |
# File 'lib/road_to_rubykaigi/signal_window.rb', line 11 def record(sample) magnitude = Math.sqrt(sample[0] ** 2 + sample[1] ** 2 + sample[2] ** 2) now = Time.now recent_magnitudes << { time: now, magnitude: magnitude } window_start = now - WINDOW_SECONDS recent_magnitudes.shift while recent_magnitudes.first[:time] < window_start end |