Skip to content

Motion controls: the full six-axis state as Eden builds it (follow-ups to #1114) - #1237

Merged
hckrman101 merged 12 commits into
NotRexed:mainfrom
wyatt-poole:hid/motion-followups
Nov 10, 2026
Merged

hckrman101 merged 12 commits into
NotRexed:mainfrom
wyatt-poole:hid/motion-followups

Conversation

@wyatt-poole

Copy link
Copy Markdown
Contributor

Follow-ups to #1114, found in a second review of the merged code (none of them reported in game yet):

  • Tilt pull past half a turn: at a sensitivity that isn't a whole number (most of the menu's 10% steps), the pull's target was wrap(wrap(tilt - tilt0) * sv). That target jumps by about pi once the pad turns past half a turn from its anchor. The pull now accumulates the tilt unwrapped since the anchor and scales that.
  • Settings changed mid-aim: changing Motion sensitivity Y or Invert motion Y while holding the pad tilted made the aim slide to the new scale, or swing to the mirrored side for the invert, with the pad held still. A change of sv now re-anchors the pull.
  • Stillness and steady turns: stillness looked only at the accelerometer's magnitude, so a pad turning at a steady rate counted as still and its turn was learned as bias. It now uses the variance of the accelerometer's vector.
  • Noisier sensors: the gyro threshold is raised to 0.015 rad/s summed over the three axes (about 0.009 per axis), leaving room for noisier third-party sensors. A pad that hasn't read still for 30 s now says so once in the log.
  • Delta time cap: the delta_time handed to the game is capped at 100 ms, the same cap the filter uses for its own dt.
  • Sampling numbers: they now move a whole history (32) forward at each switch between live and at-rest data, so no two entries ever share a number.

Tests cover each of these: a sensitivity change and an invert change while held tilted, a pitch of 3.5 rad at 50%, and a 0.0067 rad/s noisy sensor learning its bias on a table. test_motion.py passes with gcc and clang. run_all.py passes apart from test_output_resolution.py, which already fails on main before #1114, and nx2/test_nup_read_name.py, which needs zstandard.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW

…ampling)

- The tilt pull follows the tilt unwrapped since its anchor and scales
  that, so at a sensitivity that is not a whole number the target no
  longer jumps by about pi once the pad turns past half a turn.
- Changing Motion sensitivity Y or Invert motion Y re-anchors the pull:
  the aim stays where it is rather than sliding to the new scale with
  the pad held still.
- Stillness reads the accelerometer's direction as well as its size: a
  pad turning at a steady rate is no longer still, so the turn is not
  learned as bias. The gyro threshold is 0.015 rad/s over the three
  axes (about 0.009 on each), room for noisier third-party sensors, and
  a pad that has not read still for 30 s says so in the log once.
- The delta time handed to the game is capped at 100 ms, as the filter
  caps its own: a stalled pad's next reading is no jump.
- Sampling numbers move a whole history on at each switch between live
  and at rest, so no two entries ever share one.
- Tests: a sensitivity and an invert change while held tilted, a
  half-turn and more at 50%, a 0.0067 rad/s noisy sensor learning its
  bias on a table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@Link-22

Link-22 commented Nov 9, 2026

Copy link
Copy Markdown

@wyatt-poole one more for this list. I posted it on #1114 just after it was merged, so it may have been missed: my retest of 76fc99b, with a HOS_MOTION_DEBUG log attached.

The vertical aim depends on the pad's pose when the filter starts. If Motion controls starts while the pad is rolled and pitched, the vertical aim stays about 0.9 rad off from a level start, with the same hold afterwards. That happens at game start, on toggling the setting, and on switching pads. It feels almost inverted in game. Starting with the pad flat on the desk fixes it.

From the log, pitch starts at 0 in whatever pose the pad is in. The tilt pull is off while rolled, and the anchor (tilt - pitch / sv) then keeps that offset once the pad comes level. A possible fix: start pitch from the measured tilt when up is first set (e.g. sv * asin(-up[2])), and anchor the pull to the absolute tilt. I'm happy to retest on the T3 Pro.

…xed#1237

- The vertical aim is absolute: it starts at the pad's tilt from flat
  (at the nose's angle above level while rolled), and the tilt pull's
  anchor is that tilt itself, so how the pad is held when the filter
  starts no longer offsets the aim for good (Link-22: a start held
  rolled and pitched aimed about 0.9 rad off). A new sensitivity or
  invert rescales the aim to match the tilt at the new scale.
- HOS_MOTION_STILL_ACCEL is 0.0173 G summed over the three axes (0.01 G
  on each), like the gyro's, so the accelerometer side is no stricter
  than before; the noisy-sensor test adds 5 mG of accelerometer noise.
- The stillness comment says what the accelerometer's vector catches
  (a steady pitch or roll past about 5 degrees a second, not a turn
  about gravity), with a test for a steady, noiseless pitch.
- The 30 s log line leads with setting the pad down.
- Motion controls' row is preset-exempt like the four under it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole

wyatt-poole commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor Author

@Link-22 @hckrman101 thanks, both of you. Everything is in the latest commit on this PR:

  • Start pose (Link-22): the vertical aim is now absolute, measured from the pad lying flat. When the filter starts, pitch starts at the pad's tilt from flat, sv * atan2(-up[2], up[1]). If the pad is rolled at that moment, it starts at the nose's angle above level, sv * asin(-up[2]), as you suggested, and the tilt pull settles it once the pad is level. The pull's anchor is that tilt itself (tilt_acc = tilt), not the current pitch, so a start held tilted no longer offsets the aim for good. A new test reproduces your start 3: a pose with the nose up 0.6 rad, reached rolled 40° before the filter starts, then rolled level. It now aims the same as reaching that pose from a flat start (-0.6). On main it lands near 0 (+0.12).
    • Because the aim stays measured from flat, a change of Motion sensitivity Y or Invert motion Y now rescales the aim to the pad's tilt at the new scale straight away (the menu is open at that point), instead of re-anchoring.
    • One trade-off to flag: a pad held upright (portrait, face to the player) now aims about 90° up, because flat is level. Before, the level was whatever pose the filter started in. If upright holds matter, a "level" choice (flat or upright) could follow.
  • Accelerometer threshold (hckrman101): HOS_MOTION_STILL_ACCEL is now 0.0173 G summed over the three axes, 0.01 G per axis, the same convention as the gyro's. The noisy-sensor test now adds 5 mG of accelerometer noise per axis on top of the 0.0067 rad/s gyro noise.
  • What the vector catches: I reworded the comment. It now says the accelerometer vector catches a steady pitch or roll faster than about 5°/s but not a turn about gravity, and that the hand's tremor is what keeps aiming from being learned as bias. There's a test for a steady, noiseless 0.2 rad/s pitch, which is not learned as bias here (on main it learns 0.18).
  • 30 s log line: it now leads with setting the pad down on a table. A noisy sensor is mentioned only as a possibility.
  • Motion controls row: it's preset-exempt now (the missing , true from your Motion controls: gyro aiming from SDL pads, with sensitivity and inverts #1114 note).

test_motion.py passes with gcc and clang. run_all.py passes apart from the same two failures main has (test_output_resolution.py, and test_nup_read_name.py, which needs zstandard). Link-22, a retest of the start-tilted case would be great.

…its angle

The vertical aim is the pad's real tilt from flat, as a Switch reports
it. Motion sensitivity Y and Invert motion Y now scale only the tilt's
change from where the filter started (tilt_ref): at rest in that hold
the aim is the real tilt at any setting, and with the defaults it is
the real tilt everywhere. Scaling the whole angle from flat moved a
normal 0.7 rad hold to about vertical at 200% and mirrored it with the
invert (hckrman101). Test: a 0.7 rad hold at 200% and inverted.

The readme and the header no longer say the vertical aim works held
upright: the turn does, the tilt is from flat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole

Copy link
Copy Markdown
Contributor Author

@hckrman101 good catch, thanks. Fixed in the latest commit:

  • Sensitivity and invert as an offset: Motion sensitivity Y and Invert motion Y now scale only the tilt's change from where the filter started (tilt_ref, the pad's tilt from flat at that moment). The aim is -tilt_ref + (tilt - tilt_ref) * sv. At rest in that hold, the aim is the pad's real tilt at any setting. With the defaults, it's the real tilt everywhere, as a Switch reports it. A new test checks a 0.7 rad hold: at 200% it aims at 0.7, not near vertical, and a further 0.1 rad moves the aim by 0.2. With Invert Y it also aims at 0.7, not mirrored, and the same 0.1 rad moves the aim 0.1 the other way.
  • Readme and header: I dropped "held flat or upright" for the vertical aim. The turn still works in either hold, and the tilt is measured from flat.

A correction to my upright note above: since the game recenters the aim from the matrix each time it aims, an upright hold should behave like a real Switch controller held upright, not aim at the sky. That's my reading, though, and I haven't tested it.

@Link-22 when you retest, could you try 200% and Invert Y as well as the start-tilted case?

test_motion.py passes with gcc and clang. run_all.py shows the same two failures as main and nothing else.

tilt_ref (the hold Motion sensitivity Y and Invert motion Y scale the
tilt's change from) was taken only when the filter started, so a start
with the pad lying on the desk left them measured from flat: lifted to
a 0.7 rad hold, the aim rested at -1.4 at 200% and mirrored with the
invert (hckrman101). A pad that was set down (still on a table) and is
then held steady in the hand (the gyro's spread a hand's, not turning)
for 0.5 s has that hold eased in as tilt_ref over about 0.3 s. At the
defaults this moves nothing.

Also: the pull's tilt_acc starts on tilt_ref's branch (near face-down
the wrapped atan2 could be a turn away), and the stillness window
starts from a small variance, so a pad set down is still in about
1.3 s instead of 2.2 s. Test: a flat start lifted to 0.7 rad at 200%
and with the invert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole

Copy link
Copy Markdown
Contributor Author

@hckrman101 both fixed in the latest commit:

  • Start on the desk: tilt_ref is now taken again once the pad has been set down and then picked up. The pad counts as set down while it's still on a table. It counts as picked up once it's held steady in the hand for 0.5 s, meaning the gyro's spread is under a hand's (0.05 rad/s) and it isn't turning, so a smooth sweep doesn't count as a hold. The new hold is eased in over about 0.3 s. At the defaults the aim doesn't move (it changes by -(1 + sv) per radian of ref). At other settings the resting aim eases to the real tilt in the new hold. I added the test you asked for: a flat start on the desk, then lifted to 0.7 rad with a hand's tremor and held. At 200% it rests at 0.7 (on main this gives -1.4), and with Invert Y it rests at 0.7 too (main gives a mirrored +0.7). A further 0.1 rad then moves the aim 0.2, or 0.1 the other way with the invert.
  • Branch nit: tilt_acc now starts as tilt_ref + wrap(tilt - tilt_ref).
  • Also: the stillness window now starts from a small variance instead of 1, so a pad that has just been set down counts as still after about 1.3 s instead of 2.2 s.
  • Readme: it now says that Y sensitivity and the invert scale the tilt's change from your playing hold, and that the hold is taken again a moment after the pad is picked up off a table.

test_motion.py passes with gcc and clang. run_all.py shows only the two failures main also has.

@Link-22

Link-22 commented Nov 9, 2026

Copy link
Copy Markdown

@wyatt-poole @hckrman101 retested 775ca01 on the T3 Pro (Switch Pro mode, Linux, built on the v2.0.10 AppImage). Everything works:

  • Start pose (my bug): turning Motion controls off and on with the pad rolled and pitched now aims correctly. It's the same as starting flat on the desk, so the toggle-on-the-desk workaround is no longer needed.
  • Motion sensitivity Y 200%: the resting aim is normal, both when motion starts with the pad already in my hand and when it starts on the desk and I pick it up.
  • Invert motion Y: up/down is inverted as expected and the resting aim is not mirrored, again for both starts.
  • Defaults: direction, speed and calibration are as before. Turning away and back returns the aim to the same point.

Thanks for the quick turnaround on this. From my side #1237 is good to merge.

Replaces the partial state (a yaw rate in the y slot and a tilt matrix,
the rest neutral) and the cases it needed for how the pad is held when
motion starts. The game now gets what Eden, the emulator it aims right
with, gives it: acceleration (G) and angular velocity (turns a second)
in the Switch's frame, the rotation summed, and the orientation matrix
from Mahony's filter, following Eden's motion_input.cpp and
sdl_driver.cpp (yuzu GPL-2.0-or-later, Eden GPL-3.0-or-later). The game
does its own aiming and recentering, so the start pose does not matter.

Kept: the bias learned on a table (stillness of both sensors), the
console's 0.007 turns/s zero-drift threshold (Eden's standard), the
per-reading history and sampling numbers, three six-axis handles, and
Motion sensitivity X/Y and Invert motion X/Y, which scale the angular
velocity's part about the world's up (turn) and the rest (tilt) before
it is used; at 100% the state is Eden's.

Tests: the frame and units, the rotation sum, the same orientation for
a start flat-then-tilted and a start in that pose (also rolled and
pitched), bias learning (small, large, noisy) and what is not learned,
the threshold, the sensitivities and inverts, repeats and stalls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole wyatt-poole changed the title Motion controls: follow-ups to #1114 (tilt pull, stillness, sampling) Motion controls: the full six-axis state as Eden builds it (follow-ups to #1114) Nov 9, 2026
@wyatt-poole

Copy link
Copy Markdown
Contributor Author

@Link-22 @hckrman101 I've changed approach here. Instead of adding another case for each way the pad can be held, this PR now sends the game the full six-axis state, built the way Eden builds it. Link-22 said Eden aims right with this game, and a real Switch works however you hold the pad (in bed, at a desk, anywhere), because the game recenters on the camera every time it aims.

What changed:

  • Frame and units: acceleration in G and angular velocity in turns per second, in the Switch's frame, mapped from SDL exactly as Eden's sdl_driver.cpp maps them.
  • Rotation: the angular velocity summed.
  • Direction: the orientation matrix from Mahony's filter, following Eden's motion_input.cpp: kp 0.3, ki 0.005, the same quaternion integration and the same GetOrientation signs. It also includes the reset from the accelerometer when the filter loses track.
  • Kept from before: bias learning on a table, Eden's standard zero-drift threshold (0.007 turns/s), the per-reading history and sampling numbers, and the three six-axis handles.
  • Sensitivity and invert: Motion sensitivity X/Y and Invert motion X/Y scale the angular velocity's part about the world's up (X, the turn) and the rest (Y, the tilt) before the filter uses it. At 100% and not inverted, the state matches Eden's.

The tests now check:

  • the frame and units
  • the rotation sum
  • that a start flat followed by a tilt gives the same orientation as a start in that pose, including a start that's rolled and pitched (Link-22's case)
  • bias learning: small, large and noisy, plus what shouldn't be learned
  • the threshold
  • the sensitivities and inverts
  • repeated readings and stalls

test_motion.py passes with gcc and clang. run_all.py shows only main's two failures.

The code is attributed in hos_motion.h (yuzu GPL-2.0-or-later, Eden GPL-3.0-or-later; this project is GPL-3.0).

Two things I can't check from here:

  1. The real test is the game against Eden. @Link-22, could you compare this head with Eden on the T3 Pro: aim feel, starting in different poses, lying back, and 200% / Invert Y?
  2. spluton's earlier note (Support for gyro aiming? #112) said a "naive" full state looked dead. I think that was because of the frame (axes and signs) not matching, since Eden sends a full state and works, but only the game can confirm it.

wyatt-poole and others added 2 commits November 9, 2026 15:14
…ntation

Scaling the rate before Mahony's filter let its gravity correction undo
Motion sensitivity Y and Invert motion Y once the pad was held still: at
200% a 0.5 rad tilt sagged back to 0.5, and inverted it swung over to
the non-inverted side (hckrman101). The filter now runs on the real
rates (Eden's own), and the orientation handed out is a second
quaternion integrated from the scaled rates plus the real filter's
correction term, so it loses the gyro's drift but keeps a scaled or
inverted move. At 100% the two are the same. Test: 0.5 rad at 200% held
3 s matches a real 1.0 rad tilt, and inverted a real -0.5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
Conflict in gpu/vk/vk_menu.cpp: main reworked Row (help, hint, restart,
preset_exempt); the Motion controls row keeps main's hn_gyro and is
preset-exempt (hn_gyro, false, true).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole

Copy link
Copy Markdown
Contributor Author

@hckrman101 thanks for checking the port against Eden. Both points are fixed:

  • Y sensitivity / invert undone by gravity (d68db5b): the filter now runs on the real, unscaled rates, exactly as Eden does. The orientation that's handed out is a second quaternion, integrated from the scaled rates plus the real filter's correction term. It loses the gyro's drift but keeps a scaled or inverted move. At 100% the two quaternions are identical. out.gyro and rotation are scaled as before. New test, as you suggested: 0.5 rad nose up, held 3 s. At 200% it matches the matrix of a real 1.0 rad tilt, and with Invert Y it matches a real -0.5. Both fail on the previous head.
  • Conflict (8f9b8e1, merged main): the Motion controls row keeps main's hn_gyro and is preset-exempt as hn_gyro, false, true}.

run_all.py on Linux: 161 passed. The only failure is nx2/test_nup_read_name.py (needs zstandard). test_output_resolution.py passes again on main.

@Link-22 this head is ready for the comparison with Eden on the T3 Pro: 200% and Invert Y with the pad held still on a target for a few seconds, plus the start poses.

@Link-22

Link-22 commented Nov 9, 2026

Copy link
Copy Markdown

@wyatt-poole @hckrman101 a first, short result on the Eden-style approach. I only had time for a quick try of 5e2f904 (before d68db5b), on the T3 Pro, Linux, menu defaults:

  • Holding still: the aim jitters slightly with the pad held still on a target. I checked the same thing in Eden (Lichii build 125, an Eden fork) and it jitters slightly there too, so this looks like the same behaviour as Eden, not a regression.

I haven't run the full comparison yet. I'll build 8f9b8e1 and come back with the rest: start poses, lying back, and 200% / Invert Y held still on a target for a few seconds.

…s tab

The five motion rows (Motion controls, Motion sensitivity X and Y,
Invert motion X and Y) move off the Controls tab onto a page of their
own, opened by a Motion row just above Controls, the way the Controls
row opens the bindings page. The page is drawn and driven like a tab
(TAB_MOTION, not on the strip): the tab strip shows Controls, Esc or a
right click goes back to the Controls tab, and Q/E or the bumpers move
on from Controls. The options file's keys are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole

Copy link
Copy Markdown
Contributor Author

@hckrman101 @Link-22 one more change, in 0b221fc, and the in-game result:

  • Motion page: the five motion rows (Motion controls, Motion sensitivity X/Y, Invert motion X/Y) moved off the Controls tab onto a page of their own. A Motion row just above Controls opens it, the same way the Controls row opens the bindings page. The Controls tab had grown to 14 rows. The page uses the normal row drawing and input (TAB_MOTION, a hidden tab), so the sliders, mouse and wheel all work as before. The tab strip keeps Controls highlighted, Esc or a right click goes back to the Controls tab, and Q/E or the bumpers move on from Controls. The options file's keys are unchanged. The readme table now lists the page.
  • In game: I've tested this head on Windows with an 8BitDo Ultimate 2 in Switch mode (the Eden-style state, d68db5b's Y fix included). The defaults aim right, holding the pad in different poses doesn't matter, and the inverts and both sensitivities behave as intended.

run_all.py on Linux passes apart from nx2/test_nup_read_name.py, which needs zstandard.

…t modes)

The rate under which the pad counts as still was fixed at Eden's
standard 0.007 turns a second. The Motion page now has a Motion deadzone
row with the console's three zero-drift modes: Low (tight, 0.002),
Standard (0.007, the default and the console's own) and High (loose,
0.01), for a pad that jitters when held still on a target (Link-22) or,
the other way, to keep the smallest movements. Option 23
(HOS_OPT_GYRO_DEADZONE); the filter takes it as HosMotion.threshold.
Test: Low lets a 0.005 turns/s turn through, High drops 0.008.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole

Copy link
Copy Markdown
Contributor Author

@Link-22 thanks for the quick check, and for comparing against Eden. A note from my side: I got around to testing the Eden-style build on my 8BitDo Ultimate 2 (Switch mode, Windows). I didn't notice any jitter, but I was mostly checking the motion itself and looking for drift, so I didn't spend long holding it dead still on a target. Your report is probably the better data point there.

What I changed for it (latest commit):

  • Motion deadzone: there's a new row on the Motion page with the console's three zero-drift modes:

    • Low: the tight mode, 0.002 turns/s.
    • Standard: 0.007 turns/s. This is the default and what Eden and the console use, so nothing changes unless you pick another setting.
    • High: the loose mode, 0.01 turns/s.

    Any rate under the threshold counts as no movement. If the pad jitters when held still, High should steady it. Low goes the other way and keeps the smallest movements. It's option 23 (HOS_OPT_GYRO_DEADZONE), and there's a test that Low lets a 0.005 turns/s turn through and High drops 0.008.

  • What I ruled out: I also checked whether the accelerometer feeding the gravity correction could cause the jitter. In the simulation, with 10 mG of accelerometer noise per axis and the gyro in use, the matrix moves by about 0.0003 rad, which is far too small to see. So I didn't add any smoothing there and kept Eden's filter as it is. The jitter you saw (and Eden's) is more likely the gyro's own noise, or a hand's tremor, crossing the deadzone threshold now and then. The deadzone is what addresses that.

When you do the full run on 8f9b8e1 or later, it would be great to try High on the target hold too.

wyatt-poole and others added 2 commits November 9, 2026 19:15
Conflicts in gpu/vk/vk_menu.cpp with main's Audio output row (NotRexed#1240) and
the Restart/Quit confirm (NotRexed#1266, NotRexed#1255): tx_deadzone and tx_audio_output
both kept; Esc on the Motion page goes back before the pending confirm
is cancelled; the Motion row opens its page after the Cheats row's test
in main's confirm chain. TAB_MOTION is now TAB_COUNT itself (one past
the strip), and tab_selected is sized by it, so a tab added before
TAB_COUNT (NotRexed#1270) moves the Motion page along instead of colliding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
…ments

The handed-out orientation took the rate split by the accelerometer's
up in the pad's frame, so at a sensitivity or invert other than 100%
a turn while tilted turned quat_out about an axis off its own vertical
and tipped it (hckrman101). The real rate is now taken to the world by
the real orientation, its vertical part scaled by sh and the rest by
sv, and brought back to the pad by quat_out, so quat_out turns about
its own vertical. At 100% the two are still the same. Test: 0.5 rad
nose up at 200%, then a quarter turn at 200%: the world's up seen from
the pad still matches a real 1.0 rad tilt (0.54 before).

vk_api.h: the motion options' comments name all six (18 to 23).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@wyatt-poole

Copy link
Copy Markdown
Contributor Author

@hckrman101 thanks, all three are fixed:

  • World-frame scaling (11d915c): this works as you suggested. The real rate goes to the world through the real orientation. There, the vertical part (the turn) is scaled by sh and the rest (the tilt) by sv. It then comes back to the pad through quat_out, so a scaled turn while tilted turns quat_out about its own vertical. At 100%, quat and quat_out stay identical. Your test is in: 0.5 rad nose up at 200%, then a quarter turn about the vertical at 200%. The world's up seen from the pad (the third column) still matches a real 1.0 rad tilt, with a dot product of 1 within 2e-3. Before the fix it was 0.54.
  • Tab index (cf9c774): TAB_MOTION = TAB_COUNT, and tab_selected is sized TAB_MOTION + 1, so a tab added before TAB_COUNT (feat: Audio tab in the Insert menu with Volume and Mute in background #1270) moves the Motion page along with it.
  • Conflict with main (cf9c774, main at bbdc370): tx_deadzone and main's tx_audio_output are both kept. On the Motion page, Esc goes back to Controls before it touches main's pending Restart/Quit confirm. The Motion row opens its page right after the Cheats row's test in main's confirm chain.
  • vk_api.h: the motion options' comments now cover all six (18 to 23), including the deadzone.

run_all.py on Linux: 165 passed. The only failure is nx2/test_nup_read_name.py, which needs zstandard. test_motion.py passes with gcc and clang.

Conflicts with NotRexed#1298 (stick dead zone row) and the wider Motion
sensitivity X (10% to 600%) on main: tx_deadzone and tx_stick_dead_zone
both kept; the motion rows stay on the Motion page with X's new 600%
top; the readme's Motion row lists X's range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW
@NotRexed

Copy link
Copy Markdown
Owner

This landed in the v2.0.12 branch (merged there for testing; it reaches main with that release), so closing. Thanks!

@NotRexed NotRexed closed this Nov 10, 2026
@NotRexed

Copy link
Copy Markdown
Owner

Reopened: closing this was a mistake on my side. It was tested in the v2.0.12 branch, and it will be merged into main here, so it shows as merged. Sorry for the noise.

@NotRexed NotRexed reopened this Nov 10, 2026
@hckrman101
hckrman101 merged commit 7b36659 into NotRexed:main Nov 10, 2026
18 checks passed
@NotRexed NotRexed mentioned this pull request Nov 10, 2026
3 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants