Repository navigation
Motion controls: the full six-axis state as Eden builds it (follow-ups to #1114) - #1237
Conversation
…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
|
@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 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, |
…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
|
@Link-22 @hckrman101 thanks, both of you. Everything is in the latest commit on this PR:
|
…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
|
@hckrman101 good catch, thanks. Fixed in the latest commit:
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?
|
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
|
@hckrman101 both fixed in the latest commit:
|
|
@wyatt-poole @hckrman101 retested 775ca01 on the T3 Pro (Switch Pro mode, Linux, built on the v2.0.10 AppImage). Everything works:
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
|
@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:
The tests now check:
The code is attributed in Two things I can't check from here:
|
…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
|
@hckrman101 thanks for checking the port against Eden. Both points are fixed:
@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. |
|
@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:
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
|
@hckrman101 @Link-22 one more change, in 0b221fc, and the in-game result:
|
…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
|
@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):
When you do the full run on 8f9b8e1 or later, it would be great to try High on the target hold too. |
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
|
@hckrman101 thanks, all three are fixed:
|
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
|
This landed in the v2.0.12 branch (merged there for testing; it reaches |
|
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. |
Follow-ups to #1114, found in a second review of the merged code (none of them reported in game yet):
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.svnow re-anchors the pull.delta_timehanded to the game is capped at 100 ms, the same cap the filter uses for its own dt.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.pypasses with gcc and clang.run_all.pypasses apart fromtest_output_resolution.py, which already fails on main before #1114, andnx2/test_nup_read_name.py, which needszstandard.🤖 Generated with Claude Code
https://claude.ai/code/session_01BsKC8mjbyEUFAv6uy3SQiW