mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 03:00:06 +02:00
Spread the Own tracker's calibration dots over the practice area
Its fit goes wrong past its dots, and the ring (limited by the window's height) never reached the sides, where frame-eyes' worst practice clicks were. With the Own tracker the calibration now uses the centre, corners, and side middles of the practice area. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
30a9d15072
commit
b76a8c50e0
2 files changed
+15
-4
No files matched your search
+1
-1
@@ -32,7 +32,7 @@ Lessons are logged to `pointer-lessons.jsonl`: the raw gaze, the true direction,
|
|||||||
| SteamVR action | An `eyetracking` action bound to `/user/head/eyetracking` (`actions/`), read with `IVRInput::GetEyeTrackingDataRelativeToNow`. This is the supported way. |
|
| SteamVR action | An `eyetracking` action bound to `/user/head/eyetracking` (`actions/`), read with `IVRInput::GetEyeTrackingDataRelativeToNow`. This is the supported way. |
|
||||||
| mmap set 1, set 2 | `/dev/shm/eye-server.mmap`, which SteamVR's eyetracking process writes for the HMD driver (`driver_cv.so`). It has two sets of per-eye directions in head space: set 1 is filtered, and its two eyes always share one pitch; set 2 is each eye's own reading. After each set come the tracker's variances for each eye, and at the end each eye's raw measurement and its variance (the tracker's confidence in that frame), which ft-gaze passes on for the fit check. |
|
| mmap set 1, set 2 | `/dev/shm/eye-server.mmap`, which SteamVR's eyetracking process writes for the HMD driver (`driver_cv.so`). It has two sets of per-eye directions in head space: set 1 is filtered, and its two eyes always share one pitch; set 2 is each eye's own reading. After each set come the tracker's variances for each eye, and at the end each eye's raw measurement and its variance (the tracker's confidence in that frame), which ft-gaze passes on for the fit check. |
|
||||||
| Left eye, right eye | Each eye alone, from set 2: calibrate and test them to see what one eye is worth against both. The layout is undocumented (offsets are in `ft-gaze.cpp`) and may change with a SteamVR update. ft-gaze maps it read-only; the file also carries calibration clicks to the tracker and must never be written. |
|
| Left eye, right eye | Each eye alone, from set 2: calibrate and test them to see what one eye is worth against both. The layout is undocumented (offsets are in `ft-gaze.cpp`) and may change with a SteamVR update. ft-gaze maps it read-only; the file also carries calibration clicks to the tracker and must never be written. |
|
||||||
| Own tracker | Our own tracker, from `~/Desktop/Projects/frame-eyes` (experimental). `tools/fe-live` runs it: a root helper copies the eye-camera frames out of SteamVR's buffers (read-only) and `fe-trackd` finds the pupils and glints and publishes the gaze in `/dev/shm/frame-eyes-gaze`. It keeps its own calibration, not SteamVR's: the probe's calibration with the tracker toggle on Own tracker fits it, and practice clicks teach it how far the headset has moved on your face since. With Own tracker on, the probe hides SteamVR's gaze and draws a red dot where each eye alone puts it. ft-gaze reports it as `own` while it's running, and as `{"ok":0}` otherwise. |
|
| Own tracker | Our own tracker, from `~/Desktop/Projects/frame-eyes` (experimental). `tools/fe-live` runs it: a root helper copies the eye-camera frames out of SteamVR's buffers (read-only) and `fe-trackd` finds the pupils and glints and publishes the gaze in `/dev/shm/frame-eyes-gaze`. It keeps its own calibration, not SteamVR's: the probe's calibration with the tracker toggle on Own tracker fits it (its dots cover the corners and sides of the practice area, since the fit goes wrong past its dots), and practice clicks teach it how far the headset has moved on your face since. With Own tracker on, the probe hides SteamVR's gaze and draws a red dot where each eye alone puts it. ft-gaze reports it as `own` while it's running, and as `{"ok":0}` otherwise. |
|
||||||
|
|
||||||
The tracker stops when the headset is off your head. SteamVR also calibrates gaze on its own from laser-mouse clicks, treating each click as a spot you were looking at. That includes mouse clicks through the Frametop pointer, so a click where the pointer's dot isn't what you're looking at teaches SteamVR a wrong sample (it only takes clicks within 5 degrees of your gaze). In the probe, use Enter or Space as the trigger: keys don't go through SteamVR's laser. See `Accept usercal` in `~/.local/share/Steam/logs/eyetracking.txt`. When the tracker loses an eye, the same log says `CEyePoseUKF L: Large dt` (or `R`) as it starts that eye over.
|
The tracker stops when the headset is off your head. SteamVR also calibrates gaze on its own from laser-mouse clicks, treating each click as a spot you were looking at. That includes mouse clicks through the Frametop pointer, so a click where the pointer's dot isn't what you're looking at teaches SteamVR a wrong sample (it only takes clicks within 5 degrees of your gaze). In the probe, use Enter or Space as the trigger: keys don't go through SteamVR's laser. See `Accept usercal` in `~/.local/share/Steam/logs/eyetracking.txt`. When the tracker loses an eye, the same log says `CEyePoseUKF L: Large dt` (or `R`) as it starts that eye over.
|
||||||
|
|
||||||
|
|||||||
+14
-3
@@ -1826,9 +1826,20 @@ class Probe(Adw.ApplicationWindow):
|
|||||||
def calib_points(self, rnd):
|
def calib_points(self, rnd):
|
||||||
"""The centre, then six on a ring of `Calibration ring` degrees (as much of it as fits
|
"""The centre, then six on a ring of `Calibration ring` degrees (as much of it as fits
|
||||||
in the window), turned 20 degrees per round, and half the size in the middle round,
|
in the window), turned 20 degrees per round, and half the size in the middle round,
|
||||||
so the fit sees the middle, halfway out, and the edge of your view."""
|
so the fit sees the middle, halfway out, and the edge of your view.
|
||||||
|
|
||||||
|
For the Own tracker: the centre, then the corners and the middle of each side of the
|
||||||
|
area practice targets use, half the size in the middle round. Its fit is quadratic and
|
||||||
|
goes wrong past its dots, and the ring (limited by the window's height) left the sides
|
||||||
|
out: in frame-eyes' practice2 the worst clicks were all past the ring."""
|
||||||
w, h = self.canvas_size()
|
w, h = self.canvas_size()
|
||||||
cx, cy = w / 2, h / 2
|
cx, cy = w / 2, h / 2
|
||||||
|
if self.source == "own":
|
||||||
|
s = self.RING_SCALE[rnd]
|
||||||
|
left, right, bottom = cx - (cx - 80) * s, cx + (cx - 80) * s, cy + (cy - 80) * s
|
||||||
|
top = cy - (cy - 150) * s # clear of the round and dot text at the top
|
||||||
|
return [(cx, cy), (left, top), (cx, top), (right, top), (right, cy), (right, bottom),
|
||||||
|
(cx, bottom), (left, bottom), (left, cy)]
|
||||||
r = self.raw.get(self.source)
|
r = self.raw.get(self.source)
|
||||||
px_per_deg = 1 / r[5] if r and r[5] else 32.0
|
px_per_deg = 1 / r[5] if r and r[5] else 32.0
|
||||||
radius = min(self.w_ring.get_value() * px_per_deg, w / 2 - 60, h / 2 - 60) * self.RING_SCALE[rnd]
|
radius = min(self.w_ring.get_value() * px_per_deg, w / 2 - 60, h / 2 - 60) * self.RING_SCALE[rnd]
|
||||||
@@ -2084,8 +2095,8 @@ class Probe(Adw.ApplicationWindow):
|
|||||||
cr.arc(x, y, 7, 0, 2 * math.pi)
|
cr.arc(x, y, 7, 0, 2 * math.pi)
|
||||||
cr.stroke()
|
cr.stroke()
|
||||||
GLib.idle_add(self.area.queue_draw) # the pulse
|
GLib.idle_add(self.area.queue_draw) # the pulse
|
||||||
total = len(self.ROUND_BG) * 7
|
total = len(self.ROUND_BG) * len(c["points"])
|
||||||
n = c["round"] * 7 + c["index"] + 1
|
n = c["round"] * len(c["points"]) + c["index"] + 1
|
||||||
self.text(cr, 60, 70, f"Calibration: round {c['round'] + 1} of 3 ({self.ROUND_NAMES[c['round']]}), dot {n} of {total}",
|
self.text(cr, 60, 70, f"Calibration: round {c['round'] + 1} of 3 ({self.ROUND_NAMES[c['round']]}), dot {n} of {total}",
|
||||||
ink, 26)
|
ink, 26)
|
||||||
hint = "Face the centre dot, look at the highlighted dot, and press. Esc cancels, S skips a dot."
|
hint = "Face the centre dot, look at the highlighted dot, and press. Esc cancels, S skips a dot."
|
||||||
|
|||||||
Reference in new issue
Block a user