The Handy vs the OSRs at Playing Scripts - An Observation

Studied my toys’ behavior so I could make better scripts for them.

If you have multiple devices feel free to load this “stress test” script I’ve made and note down their behavior. It will also be helpful if you can record other devices playing this (Launch, KEON, A10) so we can study their behavior:
:bookmark_tabs: Stroker_Stress_Test.funscript (138.4 KB)

I’ve done some recordings of the Handy vs the SSR1 playing this script in this topic. I’m not going to post them here as to avoid turning this post into another ad.
🏗️[Review] FunSR1 In Action: Beats the Handy?

:carpentry_saw: Vibrations

High frequenct small actions intended to add flavor.

  • Works well on the Handy (online).
  • Works well on the Handy (BLE), but has frequency limits, will skip actions.
  • For the OSRs this seems to largely dependent on the servo speed. My OSR2 & SR6 seems to vibrate to a less extend.
  • Seems to work well on the SSR1 with its GM4108H-120T motor.

:part_alternation_mark: Interpolation Points

Middle points added to make the motion more natural.

  • Works well on the Handy (online). But speed change becomes very abrupt at faster actions.
  • Doesn’t work well on the Handy (BLE). There’s a microstutter after each point which makes it less smooth.
  • Works well on the OSRs no matter what speed or density.

:snail: Actions To Slow

  • The Handy (online) takes the liberty of modifying the script to play it in the smoothest possible way. It may remove a middle point or shift the timing of the turning point to increase the stroke speed so it can play it without stopping. The threshold for this to happen is somewhere around 33 unit/s in OFS. If the action is too slow to be cheesed, it will react around the

  • The Handy (BLE) tries its best to replicate the action with its slowest possible speed. It stops when it prematurely reaches the position and waits for the next command.

  • The OSRs plays the action as it is.

:rocket: Actions Too Fast

  • The Handy (online) proactively change the script content so the speed fall within its hardware capability, it does so by changing the position of the action thus shortening the stroke. This happens around 500 unit/s in OFS. The action is shortened towards its starting point.

  • The way the Handy deals with this can be visualized on’s “Modify script” tab, by adding a “Limiter” with the “Handy” preset.

  • The Handy (BLE) will play the action at its fastest possible speed. If the next command comes in before it reaches the position, it abort and attend the next one. Interestingly, under BLE mode it can move visibly faster than online mode.

  • The OSRs will play the action at its fastest possible speed. If the next command comes in before it reaches the position, it abort and attend the next one. The maximum speed limit depends on the turning speed of its servo / motor.

What does this mean to scripting?

  • Makes vibrations a situational technique because whereas it is practically easier for the Handy to handle vibrations than a slow, long stroke, it apparently doesn’t do well on other devices.

  • Slow actions should not be changed as there are devices that can play it without problem.

  • Maximum speed cap should probably also be revised.

  • Don’t be Handy-centric.



make use of the speed limit and interpolation functionality in MFP and it will handle it fine IMO

1 Like

I don’t think so… Yes Pchip could smooth out the saw teeth but this won’t enable the device to be better at vibrating.

For me that means the T-devices cant play the full speed either if they can not finish the curve and skip. That is my observation on the SSR1 also I script it to 600U/s but I dont think it can do it. Meaning it can do 600U/sec in one direction but not reversing the speed. Puts up the question if a second motor would help and each motor runs into one direction only.

guess this is just a servo problem. ive never used cheap reds so none of my devices struggled with vibration. it was the handy that i had that would overheat with such scripts.

Yeah too much variables in the osr to be able to say for sure

My suspicion is that it simply doesnt ask for the server to adjust the script and just tries to play what it can with only firmware limitations.

If that is true, there could also be diffirences between scriptplayer, mfp and handycontrol in behaviour here. And maybe some have diffirent speed limits with it.

For a while (havent tested it recently) handycontrol was well capable of causing the handy to error out on a desync (several seconds of strokes with 1000 units/s is a common cause). It needs some points to be in sync again.
Yet in scriptplayer it just limited the script.

This might also influence test results.

1 Like

What speed limit has worked best for you?

i adjust it up and down. depends on your servos and stroke length. for me, much faster than .250 gets scary lol.

1 Like

@handyAlexander If you are reading please forward this to your software engineer.


  1. Online mode w/ slow actions - it cheeses slow actions by shifting the timing of points. I’ve covered this in Handy's Firmware Blends Slow Actions. This is bad as the timing and speed of downward strokes are completely altered.

  2. Online mode w/ fast actions - the FW is active capping and shortening the stroke to keep it within a certain speed. The way this is handled tends to ruin a downward stroke by shortening it towards the top. This is detrimental to many videos where thrusts are emphasized.
    -e.g. this is a script made for a CH video where each downward stroke are synced to the beat, but they’re 600 unit/s which is considered too fast for the FW,

    As a result the FW moves the bottom point upwards, turning the subsequent green stroke into a downward stroke too. Now the strokes are not in sync with the beat - what is originally an intermediate point becomes the bottom point.

  3. Please, please improve BLE mode! - there is a microstutter after each point which makes it uncapable of playing high-def scripts with middle points such as this:

Here’s some video to illustrate what I’m saying:

Online mode w/ slow actions:

Online mode w/ fast actions:

BLE mode w/ middle points:
Note the “steps” of the movement.

As i can imagine why it works this way, i think it could be usefull to give an idea of how this potentialy could be fixed in such way that i think in programming logic isnt too hard.

The first step is identifying direction as key point. If it changes, it must preserve the change. Either by just stopping movement entirely, or by just slowing down the next stroke to allow synching again.

Using the provided example i can think of a few methods/checks that should make it work smoothly without requiring too much looking ahead in the script.

From the current points, if its a change in the other direction, it must ensure it wont move further. This affects the 80 and 0 points. Even if this point isnt reached, it at least must halt.

For the 80 point (lets say it stopped at 70 already), since the next node is still the opposite direction, it just handles it the normal way and moves to it.
For the 0 point (lets say it stopped at 20), as the next point requires moving further, but it being a direction change, the device wont use the 10 node and just ignores it for moving toward it.

If the speed then ends up being too low (from the 20-80 position), it can decide to delay it, in which case it first looks at nodes in between that can indicate timing, so it tries to wait until the 10 node to see if this takes it within an acceptable speed range. If so, it just starts there at moving again. If not, it waits longer (current behaviour).

If the speed ends up too fast, it just continues in the other direction and tries to get as close as possible to the 80 position (in this case skipping the 10 anyway).

Now the edge case of demanding a halt in the middle of a stroke, while not being a direction change on its own, its still seen as one. So the device will perform a stop in motion, even if its shorter than required. Lets say we have 100->50->50->0. it could mean that it stops at 60 already, and that the 60 is only 1 frame in duration instead of the 4 that the script actualy desired.

If the halt was only a slight speed change, it is deemed a single stroke so it can decide to skip the slower portion and just go full speed towards the end point (so 100->60->40->0 becomes a plain 100->0).

I also had an idea how slow strokes can be resolved a bit nicer, but i dont think its going to be as effective as the fast stroke solutions.

If the stroke (for some reason) has over 10 nodes in it, and this was set as look ahead limit (it makes no sense to make it look infinitely). It just figures out the action based on the last node it can detect. As while moving it shifts ahead, it can adjust.

So if a stroke went from 0-100 with steps of 5. It might only see the 45 node. If the movement goes below the limit, it just follows the current behaviour by delaying movement until its needed.
If its faster, then it looks ahead to see if later on it wont need to slow down again, and just compensates for a speed which doesnt need halting. If it does, it halts whenever it thinks its optimal (it barely matters when as it cannot perform the action accurately).

The look ahead only goes as far as the direction change. So if this is just 1 node, it will still perform movement to it, but it just waits until the last moment. The idea here is that it at least will try to move towards the node after a large break. As now the handy often skips these nodes entirely.

1 Like

Noted! FW4 takes more care of almost all your pain point :open_mouth:

We working as hard as possible to get FW4 to a place that more people can join in on the testing.


i bought the Funsr1 one personally because the handy is not usable recently i got disconnected so often from server and apparently its too complicated to run local script. this sound even easier