nxbt icon indicating copy to clipboard operation
nxbt copied to clipboard

Skipping inputs when using macros

Open Pegoku opened this issue 1 year ago • 16 comments

When i use macros, it sometimes doesn't send a key, why does it happen

Pegoku avatar Jun 02 '23 22:06 Pegoku

Could you send us the script you're using?

Dummydud3 avatar Jun 03 '23 12:06 Dummydud3

Also, what command are you using to run th escript? Are you using the Command Line?

Dummydud3 avatar Jun 03 '23 12:06 Dummydud3

Could you send us the script you're using?

A 0.1s
1.0s
A 0.1s
1.0s
A 0.1s
1.0s
A 0.1s
1.0s    
LOOP 198
    PLUS 0.1s
    0.4s
    X 0.1s
    0.2s
    LOOP 5
        A 0.1s
        0.1s
    Y && B 0.1s
    0.4s
    LOOP 6
        A 0.1s
        0.1s
    0.25s

Pegoku avatar Jun 03 '23 14:06 Pegoku

Also, what command are you using to run th escript? Are you using the Command Line?

Comand Line, in ubuntu 22.04

Pegoku avatar Jun 03 '23 14:06 Pegoku

Looks good on first look. What kind of device are you using? Last question, are you using an external bluetooth dongle?

Dummydud3 avatar Jun 03 '23 21:06 Dummydud3

I'm using an USB Bluetooth from TP-link connected to my pc(running ubuntu 22.04)

Pegoku avatar Jun 04 '23 08:06 Pegoku

After some troubleshooting, I think the problem is your script. This is the broken segment:

 LOOP 5
        A 0.1s
        0.1s
    Y && B 0.1s
    0.4s 

To press 2 buttons simultaneously, you use a macro command like: Y B 0.1s. So just remove the && in your script and tell me what happens. If you want to see Brikwerks documentation on Macros, here's the file. https://github.com/Brikwerk/nxbt/blob/master/docs/Macros.md

Dummydud3 avatar Jun 04 '23 17:06 Dummydud3

After some troubleshooting, I think the problem is your script. This is the broken segment:

 LOOP 5
        A 0.1s
        0.1s
    Y && B 0.1s
    0.4s 

To press 2 buttons simultaneously, you use a macro command like: Y B 0.1s. So just remove the && in your script and tell me what happens. If you want to see Brikwerks documentation on Macros, here's the file. https://github.com/Brikwerk/nxbt/blob/master/docs/Macros.md

changed it and does the same, it doesn't work

Pegoku avatar Jun 13 '23 18:06 Pegoku

could you send is a demonstration of your script? A recording or replay would be nice as well

Dummydud3 avatar Jun 20 '23 16:06 Dummydud3

could you send is a demonstration of your script? A recording or replay would be nice as well

https://imgur.com/a/fgX8KTW

Pegoku avatar Jun 20 '23 17:06 Pegoku

Unfortunately I don't know much about BotW, but i can tell that random chance seems to be messing with it. Last question (i think), what input was skipped in this clip? P.S. you can text me more directly on discord. username: dummydude_

Dummydud3 avatar Jun 21 '23 23:06 Dummydud3

X was skipped

Pegoku avatar Jun 22 '23 05:06 Pegoku

I have been trying to find out what causes it too as I had the same problem with inputs being suddenly skipped at seemingly random, just like you.

From what I can see it might be a logic error in controller/server.py, specifically with how command durations longer than one tick are handled. This error occurs in line 184 to 186:

sleep_time = 1/132 - duration_elapsed if sleep_time >= 0: time.sleep(sleep_time)

You might notice that there is no else statement following this for the case that the duration is longer than a tick, as mentioned. To fix the input skipping: insert the following lines and reinstall the local package:

  • after line 121: time_program_start = time.perf_counter() startup_time = 10 # Choose a number in seconds for how long it takes to get in the game from the Change Grip menu

-after line 186: elif (duration_start - time_program_start > startup_time): modified_sleep_time = int(duration_elapsed/(1/132))*1/132 + sleep_time time.sleep(modified_sleep_time)

Also, do note that the refresh rate of a Switch Pro Controller might actually be 132 as this file suggests, so pick the macro input times corresponding to that. I hope that resolves your issue, but I'm in the same boat as you are, so if you find any issues with this, please let me know.

PolarisingEntity avatar Jul 22 '23 17:07 PolarisingEntity

Was this issue fixed for you after making those changes @PolarisingEntity ? I make the same changes and it doesn't not seem to help.

alexargo avatar Jul 29 '23 04:07 alexargo

Sorry this has taken a bit for me to get around to. From my testing, the biggest culprits for input skipping are primarily caused by the following two factors:

  1. The timing behaviour present in the main branch.
  2. Operating system behaviour.

I've attempted to address the first point in the dev branch with an overhauled timing system. The second point is trickier to address and, largely, comes down to process scheduling behaviour in the host OS.

To provide context, NXBT is attempting to share a given CPU's resources with other processes. Maintaining a fast loop with consistent latency can be challenging since NXBT can get preempted (essentially, put to sleep temporarily) by other processes that want a fair share of their time on the CPU.

The problem with the current timing strategy in the main branch is that NXBT is "trusting" the time.sleep function call. Sleeping, unfortunately, can be inaccurate, which results in large latency spikes and skipped or cut-short inputs. The new timing loop in the dev branch uses busy waiting, instead of sleeping, for increased accuracy between ticks. This should hopefully reduce the amount of skipped inputs people are encountering.

As an aside, Windows, unfortunately, seems to be the least friendly platform for running fast loops on (results and discussion here). Inherent timing inaccuracies on Windows seem to result in NXBT skipping inputs more often than on macOS or Linux. Busy waiting still helps on Windows, but there might be some OS quirks that need to be worked around for Windows specifically.

I'm going to make a few more adjustments to the dev branch before merging and slicing off a new version for PyPi. In the meantime, you can test the dev branch (if you want) by installing this version using the following commands:

sudo pip install git+https://github.com/Brikwerk/nxbt@dev

Brikwerk avatar Aug 14 '23 00:08 Brikwerk

I am running into this as well, with some additional context:

Platform: Linux Running the process with sudo nice -20 so it has a high CPU priority

It is still skipping inputs. I have tried this using the dev branch with the busy-loops instead of sleep, didn't see any difference.

My Macro
0.5s
A 0.1s
0.4s
DPAD_UP 0.1s
0.2s
DPAD_UP 0.1s
0.2s
A 0.2s
1.5s
A 0.2s
0.2s
A 0.2s
3.5s
A 0.3s
1s
DPAD_RIGHT 0.1s
0.2s
DPAD_DOWN 0.1s
0.2s
DPAD_DOWN 0.1s
0.2s
A 0.2s
4s
X 0.2s
0.2s
X 0.2s
0.2s
L 0.2s
0.8s
A 0.2s
0.8s
DPAD_UP 0.25s
0.25s
DPAD_UP 0.25s
0.25s
DPAD_UP 0.25s
0.25s
A 0.2s
1.6s
B 0.2s
2.5s
DPAD_LEFT 0.2s
0.3s
DPAD_DOWN 0.2s
0.3s
DPAD_DOWN 0.2s
0.3s
DPAD_DOWN 0.2s
0.3s
DPAD_DOWN 0.2s
0.3s

I am running that macro in a loop (python while loop, not a macro LOOP). I often get around 2-9 iterations through before it misses a button, and then the sequence is out of sync and I have to kill it.


Edit:

I adjusted the timings in my macro so buttons are held a little longer (but not long enough to register as a long-held button, to move two menu-entries for instance). And I am also running the process as a linux real-time process with chrt -r 60 ... so it can't be preempted. I can get more loops, about 20-40 (using the dev busy-loop branch) before it misses a button press.

Not sure there's much more I can improve for the running environment here, giving it CPU priority on a realtime kernel.

Edited macro
0.2s
A 0.25s
0.4s
DPAD_UP 0.23s
0.2s
DPAD_UP 0.23s
0.2s
A 0.23s
1.5s
A 0.23s
0.2s
A 0.23s
3.5s
A 0.23s
1s
DPAD_RIGHT 0.23s
0.2s
DPAD_DOWN 0.23s
0.2s
DPAD_DOWN 0.23s
0.2s
A 0.23s
4s
X 0.23s
0.2s
X 0.23s
0.2s
L 0.23s
0.8s
A 0.23s
0.6s
DPAD_UP 0.25s
0.25s
DPAD_UP 0.25s
0.25s
DPAD_UP 0.25s
0.25s
A 0.23s
1.4s
B 0.23s
2.5s
DPAD_LEFT 0.23s
0.3s
DPAD_DOWN 0.23s
0.3s
DPAD_DOWN 0.23s
0.3s
DPAD_DOWN 0.23s
0.3s
DPAD_DOWN 0.23s
0.3s

pzl avatar Jan 19 '24 14:01 pzl