Add a short intro with a link to Discussions, a dropdown for what the
idea is about, example answers in each box, and an optional pick of
the knock kinds the person uses.
Two knocks on a leg spread wider than two knocks on a desk. In a run of
about 40 leg doubles, 7 pairs landed 3.5 to 8.3 cm apart, and the 3 cm
same-spot rule dropped them. At 6 cm, 25 doubles count instead of 20.
play, noise, and straps still give no actions at twice that distance.
tests/data/leg-doubles.csv.gz holds that run.
Knocks on a leg come in faster than knocks on a desk. Most right-hand
leg knocks moved faster than 1.8 m/s 30 ms before the spike, so the
detector threw them out as arm swings. Surface knocks now get their own
limit of 2.2 m/s. Together and headset knocks keep 1.8 m/s, because at
2.2 m/s a together calibration counted one knock in the noise recording.
tests/data/leg.csv.gz holds doubles and triples knocked on a leg with
each hand, headset worn. It gives 16 actions at 2.2 m/s and 9 at 1.8 m/s.
Development builds read commands appended to
~/.config/knockthru/test-commands: open or close the panel, click a
panel pixel, press a button by name, feed a knock or a double or triple
knock, and save the panel as a PNG. Releases leave it out:
build-arm64.sh adds it only with KNOCKTHRU_TEST_HOOK=1, and the release
workflow never sets that. The host build always has it, so CI compiles it.
On the Frame it drove calibration, the bug report and its recording,
the factory reset and tour, and an update from 1.0.1 to a local
1.0.2-test release through Install and Restart.
Nothing referenced it, and it read only uncompressed CSV files while the
recordings are gzipped. detector_test with KNOCKTHRU_TEST_VERBOSE=1 prints
every knock in a recording.
Five settings repeated the same three lines. A test now loads each of
them and rejects a value that is not true or false. The test that named
the update check weekly now says daily, which is what the app does.
Ten places wrapped a string and drew its lines one by one with the same
loop. Panel::paragraph does it once. All panel_preview images are
byte-identical.
run() was one 721-line function whose 15 lambdas shared its locals. It is
now an App class in app.cpp with one method per job: slow checks, panel
clicks, knocks, background jobs, and drawing. The shared SteamVR helpers,
pose sampling, haptics, the bug report, and install commands move to
their own files. main.cpp keeps the command-line commands.
Behavior is unchanged. The order of steps in the main loop is the same,
except that a finished recording is collected after the knocks of that
loop instead of before.
An opaque color replaces the pixels under it, so each row's covered run
is now written directly. Most of a panel frame is tile fill. The main
screen renders in half the time on the PC, and all panel_preview images
are byte-identical.
run() read the Room View style and started the update check job in two
places each. calibrate() repeated the thresholds() format, and three
sites spelled out "double" or "triple".
The pose-to-vector extraction, the CSV row format, the device names, and
the HOME fallback each had two or three copies. Recordings keep the same
bytes: rows without angular velocity still end in 0,0,0.
The detector judges knocks 50 ms after they happen, so a 1 ms loop gains
nothing while nobody looks at the panel. The pose thread still samples
every millisecond. On the Frame the main thread drops from 4.3% to 1.1%
of one core.
History is sorted by time, so poll() starts at the first unjudged sample
and the window helpers start at their window instead of scanning all
0.8 s of samples. Detector output is identical on every recording, and
detector_test runs in 2.2 s instead of 3.6 s.
docs/calibration-plan.md was a working plan for local branches, and
docs/knock-signal.md was the tuning log. Both stay in git history.
The README and two code comments no longer point at them.
CLAUDE.md is now in .gitignore, so it stays as a local file only.
The version defaults in CMakeLists.txt, build-arm64.sh, and package.mjs
say 1.0.0, and so do the README's manual install and build examples.
The README's update GIF goes from 1.0.0 to 1.1.0, not 0.1.0 to 0.2.0.
SteamVR starts the resident app with STEAMVR_APPKEY=local.knockthru.
Restart in Settings starts knockthru-ctl --install, which inherited it,
so SteamVR filed the restarter as KnockThru itself. It then found its
own PID, stopped nothing, and failed with ApplicationAlreadyRunning.
Management commands now clear STEAMVR_APPKEY, find the resident app
through /proc, and write their errors to application.log.
The switch swapped the icon image at once, but the bar's tint followed
only at the next 2 s check. For up to 2 s the old tint showed over the
new icon.
An update with --update on the Frame stopped KnockThru 0.1.0 at
13:22:12.599, then failed to start 0.1.1 with ApplicationAlreadyRunning.
SteamVR cleared the old PID at 12.635, after the launch call. Restarts
now wait up to 3 s for SteamVR to clear it.
The double and triple knock steps cycled through all three kinds, so a
card listing only together and table knocks still showed a headset
knock. With every kind off, the steps still show all three.
The Reset label is too small to win an entry in the 127-color GIF palette,
so it came out mustard. An extra solid frame of the error red, seen only
by palettegen, gives it its own entry.