secondlife / jira-archive

2 stars 0 forks source link

[BUG-7777] Stuttering in llSetKeyframedMotion() #15451

Open sl-service-account opened 9 years ago

sl-service-account commented 9 years ago

Steps to Reproduce

I attempted to run an experiment using llSetKeyframedMotion() to create a very simple clock. This was constructed using a half cut box (path cut begin 0.125, path cut end 0.625) stretched to look like the hand on an analogue clock, with its rotation centre at its base, ready to rotate around it's Y-axis.

Into this I placed the following script:

list animation = [
    <0.00000, 0.99996, 0.00000, -0.00873>, 20.0,
    <0.00000, 0.99996, 0.00000, -0.00873>, 20.0,
    <0.00000, 0.99996, 0.00000, -0.00873>, 20.0
];

rotation normRot(rotation r) {
    float mag = llSqrt(r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s);
    return <r.x / mag, r.y / mag, r.z / mag, r.s / mag>;
}

default {
    state_entry() {
        llSetKeyframedMotion([], [KFM_COMMAND, KFM_CMD_STOP]);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, llEuler2Rot(<0.0, 270.0, 0.0> * DEG_TO_RAD)]);

        // Make sure rotations are normalized
        integer i; integer l = animation != [];
        for (i = 0; i < l; i += 2) 
            animation = llListReplaceList(animation, [normRot(llList2Rot(animation, i))], i, i);

//        float time = llGetTimeOfDay();
//        float wait = 60.0 - (time - ((integer)(time / 60.0) * 60.0));

//        if (wait > 0.0) llSleep(wait);
        llSetKeyframedMotion(animation, [KFM_MODE, KFM_LOOP, KFM_DATA, KFM_ROTATION]);
    }
}

The commented-out lines synchronise the hand to the next minute, but aren't necessary for testing this.

Actual Behavior

An animation using llSetKeyframedMotion() kept pausing and stuttering despite running on a simulator with time to spare and a constant 45.0 fps for the physics engine. The pauses are often several seconds, which seems a long time when the sim appears to be lag-free.

Expected Behavior

The animation should have continued smoothly, or at the very least any pauses should have been momentary.

Other information

I understand that keyframed motion doesn't guarantee perfectly smooth movement or timing (I submitted BUG-7767 for this reason), but these pauses seem unusual; as mentioned there was no sign of lag on the simulator when it happened, and I've tried the same script in other simulators as well and encounter similar stuttering. It seems to happen mostly towards the start, but can happen for longer running animations as well.

Links

Duplicates

Original Jira Fields | Field | Value | | ------------- | ------------- | | Issue | BUG-7777 | | Summary | Stuttering in llSetKeyframedMotion() | | Type | Bug | | Priority | Unset | | Status | Accepted | | Resolution | Accepted | | Reporter | Haravikk Mistral (haravikk.mistral) | | Created at | 2014-11-11T14:45:32Z | | Updated at | 2019-06-28T15:33:21Z | ``` { 'Business Unit': ['Platform'], 'Date of First Response': '2014-11-11T10:59:18.835-0600', "Is there anything you'd like to add?": "I understand that keyframed motion doesn't guarantee perfectly smooth movement or timing (I submitted BUG-7767 for this reason), but these pauses seem unusual; as mentioned there was no sign of lag on the simulator when it happened, and I've tried the same script in other simulators as well and encounter similar stuttering. It seems to happen mostly towards the start, but can happen for longer running animations as well.", 'Severity': 'Unset', 'System': 'SL Simulator', 'Target Viewer Version': 'viewer-development', 'What just happened?': 'An animation using [{{llSetKeyframedMotion()}}|https://wiki.secondlife.com/wiki/LlSetKeyframedMotion] kept pausing and stuttering despite running on a simulator with time to spare and a constant 45.0 fps for the physics engine. The pauses are often several seconds, which seems a long time when the sim appears to be lag-free.', 'What were you doing when it happened?': "I attempted to run an experiment using [{{llSetKeyframedMotion()}}|https://wiki.secondlife.com/wiki/LlSetKeyframedMotion] to create a very simple clock. This was constructed using a half cut box (path cut begin 0.125, path cut end 0.625) stretched to look like the hand on an analogue clock, with its rotation centre at its base, ready to rotate around it's Y-axis.\r\n\r\nInto this I placed the following script:\r\n\r\n{code}list animation = [\r\n <0.00000, 0.99996, 0.00000, -0.00873>, 20.0,\r\n <0.00000, 0.99996, 0.00000, -0.00873>, 20.0,\r\n <0.00000, 0.99996, 0.00000, -0.00873>, 20.0\r\n];\r\n\r\nrotation normRot(rotation r) {\r\n float mag = llSqrt(r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s);\r\n return ;\r\n}\r\n\r\ndefault {\r\n state_entry() {\r\n llSetKeyframedMotion([], [KFM_COMMAND, KFM_CMD_STOP]);\r\n llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, llEuler2Rot(<0.0, 270.0, 0.0> * DEG_TO_RAD)]);\r\n\r\n // Make sure rotations are normalized\r\n integer i; integer l = animation != [];\r\n for (i = 0; i < l; i += 2) \r\n animation = llListReplaceList(animation, [normRot(llList2Rot(animation, i))], i, i);\r\n\r\n// float time = llGetTimeOfDay();\r\n// float wait = 60.0 - (time - ((integer)(time / 60.0) * 60.0));\r\n \r\n// if (wait > 0.0) llSleep(wait);\r\n llSetKeyframedMotion(animation, [KFM_MODE, KFM_LOOP, KFM_DATA, KFM_ROTATION]);\r\n }\r\n}{code}\r\n\r\nThe commented-out lines synchronise the hand to the next minute, but aren't necessary for testing this.", 'What were you expecting to happen instead?': 'The animation should have continued smoothly, or at the very least any pauses should have been momentary.', } ```
sl-service-account commented 9 years ago

Whirly Fizzle commented at 2014-11-11T16:59:19Z

Probably BUG-1624 ?

sl-service-account commented 9 years ago

Haravikk Mistral commented at 2014-11-11T18:05:40Z

I don't seem to be able to access that bug, which may explain why I couldn't find it earlier. Is it protected by some kind of permissions, or is the ID perhaps incorrect?

sl-service-account commented 9 years ago

Haravikk Mistral commented at 2014-11-11T18:09:27Z

I also wanted to add that Dora Gustafson, who has been trying to help me in the LSL Scripting forum, had a go at this script, and seems to be able to get the same effect to work without stuttering when using translation, which implies the problem may be related to rotation-only motion?

I'm noticing the same in some of my other experiments which don't seem to exhibit the same stuttering, but which are using much shorter key-frames with both translation and rotation.

sl-service-account commented 9 years ago

Whirly Fizzle commented at 2014-11-11T18:12:48Z

Oh blarg. Yeah, older BUG reports filed before the JIRA was opened up again still have restricted permissions.

BUG-1624: http://awesomescreenshot.com/06f3tvk7c9

... and this is the attached script on that issue...

integer OPEN = FALSE;
integer MOVING = FALSE;
rotation startRot;

default
{
    state_entry()
    {
        llSetStatus(STATUS_BLOCK_GRAB_OBJECT,TRUE);
        llSetKeyframedMotion( [ZERO_VECTOR,ZERO_ROTATION,1.0], [] );
    }

    touch_start(integer total_number)
    {
        if(!MOVING)
        {
            if(OPEN)
            {
                OPEN = FALSE;
                MOVING = TRUE;
                llSetKeyframedMotion( [ZERO_VECTOR,llEuler2Rot(<0,0,-90>*DEG_TO_RAD),1.0], [] );
            }
            else
            {
                OPEN = TRUE;
                MOVING = TRUE;
                startRot = llGetRot();
                llSetKeyframedMotion( [ZERO_VECTOR,llEuler2Rot(<0,0,90>*DEG_TO_RAD),1.0], [] );
            }
        }
    }
    moving_end()
    {
        MOVING = FALSE;
        if(OPEN)
        {
            vector startRotVector = llRot2Euler(startRot)*RAD_TO_DEG;
            llSetLinkPrimitiveParamsFast(LINK_ROOT,[PRIM_ROTATION,llEuler2Rot((startRotVector+<0,0,90>)*DEG_TO_RAD)]);
        }
        else 
        {
            llSetLinkPrimitiveParamsFast(LINK_ROOT,[PRIM_ROTATION,startRot]);
        }
    }
}
sl-service-account commented 9 years ago

Haravikk Mistral commented at 2014-11-11T18:49:17Z

Ah, definitely one to fix, but it doesn't seem to be the same issue; in my case this is affecting a single-prim that I created fresh and placed the script within, not something I took into inventory.

The rotation plays out correctly, it just pauses/stutters every so often for no apparent reason (sim is running smoothly with time to spare, physics engine fps is a constant 45 etc.). I thought perhaps it was a viewer bug but the object definitely seems to stop moving during these pauses.

sl-service-account commented 9 years ago

Miranda Umino commented at 2014-11-12T00:11:22Z, updated at 2014-11-12T03:38:10Z

As said in the forum , the velocity of rotation is too small The cosinus of half-angle / frame is very closed to 1 ( > 0,99999849379559389750526410095037) , so the rotation may stop "cosinus half-angle / frame ", llCos( 0.5 * llRot2Angle(normRot(<0.00000, 0.99996, 0.00000, -0.00873>))/(20.0*45) )

or if you prefer , rotation r = <0.00000, 0.99996, 0.00000, -0.00873> r.s / (20 seconds * 45 frames/ seconds) < 1e-7 = limit of precision of 32 bit float

Watch https://jira.secondlife.com/browse/SVC-7471

It s the same problem for any physical rotations : there is a gap around 9 degrees per seconds ( or around 0.15 radians per seconds ) With llTargetOmega(<0,0,1>,PI / 20.0, 1.0) , a prim rotates infinitely. With llTargetOmega(<0,0,1>,PI / 21.0, 1.0) , a prim rotates a little then stops . With llSetAngularVelocity(<0,0,PI / 20.0> , TRUE) , a prim rotates infinitely. With llSetAngularVelocity(<0,0,PI / 21.0> , TRUE); , a prim rotates a little then stops . Maybe use 64 bits float and not 32 bits float may fix it There are plent of games who use Havok and make turning objects to values inferior to 0.15 radian/seconds ; how is it done ?

sl-service-account commented 9 years ago

Haravikk Mistral commented at 2014-11-12T11:28:01Z, updated at 2014-11-12T11:43:54Z

Hmm, that definitely seems related to this issue, but as Dora notes in the forum thread it may not be the actual issue (though it's certainly a possibility for improvement). Sorry for the multiple updates but I originally linked as a duplicate, but I downgraded it to relates to since I'm not completely sure it's the cause of this behaviour. That said, it could be rounding related, but the addition of a translation ensures the rounding doesn't halt the animation (since it's rounding both the rotation and the translation, and as long as one continues the effect still works).

64-bit precision definitely seems like it would solve the problem; I never even considered the precision being an issue, as I assumed that the SL sim already ran in 64-bits (I thought it was just scripting where we're still limited to 32-bit).

Another possible solution would be to round up troublesome values, but balance out the increased velocity by skipping frames, i.e - the velocity would be rounded up to something easily divisible by the frame-rate, with frames dropped to reduce the effective velocity. For example, if a velocity works out at 1e-8 then it's far too small, so it would be multiplied by 10 to 1e-7, but would skip 9 out of 10 frames. For such slow movement it shouldn't have any meaningful impact on the behaviour, but would be a lot better than simply stopping every time the rounding goes a bit weird.

sl-service-account commented 9 years ago

Dora Gustafson commented at 2014-11-12T11:55:09Z, updated at 2014-11-12T12:04:44Z

It is easy to specify a 1 RPM motion nowhere near causing rounding errors


integer S;
list KFMlist = [];

default
{
    state_entry()
    {
        integer frams = 3;
        list L = [llAxisAngle2Rot( <0.0, 1.0, 0.0>, TWO_PI/(float)frams), 60.0/(float)frams];
        llOwnerSay("Rotation and time per frame= "+llDumpList2String( L, ", ")+" by "+(string)frams+" frames");
        while ( frams-- ) KFMlist += L;
    }
    touch_end( integer n)
    {
        llSetKeyframedMotion( [], []);
        llSleep( 0.2 );
        S = !S;
        if ( S ) llSetKeyframedMotion( KFMlist, [KFM_DATA, KFM_ROTATION, KFM_MODE, KFM_LOOP]);
    }
}

You get these data Rotation and time per frame= <0.000000, 0.866025, 0.000000, 0.500000>, 20.000000 by 3 frames And still there is no rotation most of the time Try it with 36 frames(one for each 10 degrees) and you get: Rotation and time per frame= <0.000000, 0.087156, 0.000000, 0.996195>, 1.666667 by 36 frames Still nowhere near to rounding problems and still no smooth rotation

Funny because a script I posted previously has a frame for each 10 degrees and the object rotates nicely as it moves along a circle So obviously rotation and translation are linked

sl-service-account commented 9 years ago

Miranda Umino commented at 2014-11-12T21:23:52Z, updated at 2014-11-13T00:42:22Z

Dora , i am talking about frames of simulator ( so 45 frames per seconds ) ; i am not talking about frames as input/ parameters of llsetkeyframedmotion. If you prefer it s the time in seconds of your frame as input of llsetkeyframemotion multiplied by 45 :

if i take your script dated at 12/Nov/14 12:55 PM : rotation r = llAxisAngle2Rot( <0.0, 1.0, 0.0>, TWO_PI/(float)frams); float angle = llRot2Angle(r) * RAD_TO_DEG; float time = 60.0/(float)frams; float velocity_by_frame = angle / time; llOwnerSay(llList2CSV( [ "angle (deg)", angle, "time (seconds)", time, "velocity rotation (deg/frame )",velocity_by_frame ]));

=> will display angle (deg), 120.000008, time (seconds), 20.000000, velocity rotation (deg/frame ), 6.000000

you are at 6 deg per seconds< 9 deg per seconds => so , you meet the problem here

If i take you second daatas : rotation r = <0.000000, 0.087156, 0.000000, 0.996195>; float angle = llRot2Angle(r) * RAD_TO_DEG; float time = 1.666667 ; float velocity_by_seconds = angle / time; llOwnerSay(llList2CSV( [ "angle (deg)", angle, "time (seconds)", time, "velocity rotation (deg/seconds)",velocity_by_seconds ]));

=> will display
angle (deg), 9.999578, time (seconds), 1.666667, velocity rotation (deg/seconds), 5.999746 you are at 5.997 deg per seconds< 9 deg per seconds => so , you meet the problem here too

In your script in your link , your move does both a translation and a rotation . So to compute the velocity of rotation in the right coordinates ; in local coordinates the velocity is different of region coordinates. Change your linear( translation) Velocity vector Velocity = <0.0, -0.10471975512, 0.0>; by vector Velocity = <0.0, -0.01471975512, 0.0>; and you will watch your prim starting and stopping

And i repeat : with llTargetOmega , we meet the same problem , and with llSetAngularVelocity we meet the same problem. it stops too soon for low velocity

sl-service-account commented 9 years ago

Miranda Umino commented at 2014-11-13T00:34:36Z, updated at 2014-11-13T00:40:17Z

To demonstate better my opinion that the problem with llsetkeyframedmotion is the same with other physics rotations :

i ve done 2 seamless scripts : It fixes a rotation while 5 seconds and tests with different angular velocities . It returns when ( in frames of simulator ) the motion has been stopped ( more precisely when llGetOmega is null vector )

By defaut , an iteration of test is 0.5 seconds , so 0.5 * 45 FPS = 225 frames of simulator

Rez a prim ; move it to let it float on the air without friction with the ground or other objects ; put the script inside and touch it to start the tests


// we ll do succesive tests
// From an angularvelocity of INITIALANGULARVELOCITY =0.5, we are turning along STEPTIMETEST seconds.
// A timer is setup to count the number of frames in simulator :
// if STEPTIMETEST is reached , we stop the motion , wait until it stops rotation and  we go to the next test 
// If STEPTIMETEST is not reached and we reach a NULL llGetOmega before this,   we stop the current test and we start the next test .
// At every test , we display the angular velocity and the time in frames between the start of the current test and when the object has stopped to turn with llGetOmega  = ZERO_VECTOR

float STEPANGULARVELOCITY = 0.01;
float STEPTIMETEST = 5.0;
float INITIALANGULARVELOCITY = 0.5;

float angularvelocity;
integer count;

integer framestart;
integer frameend;

list keyframes;

list buildKeyframes(float seconds, float angular_velocity)
{
    list l;
    rotation r = llEuler2Rot(<0,0,PI_BY_TWO>);
    float totalangle = seconds * angular_velocity;
    while ( totalangle > PI_BY_TWO )
    {
        l +=  [ r, PI_BY_TWO  / angular_velocity ];
        totalangle -= PI_BY_TWO;
    }
    if ( totalangle > 0.0)
    {
        float timekeyframe  = totalangle / angular_velocity;
        if ( timekeyframe <= 0.111111 ) timekeyframe = 10/9.0;
        l +=  [ llEuler2Rot(<0,0,totalangle>), timekeyframe ] ;
    }
    return l;
}
default
{
    state_entry()
    {
        llSetObjectName("test keyframemotion - low angular velocity");
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetRot(ZERO_ROTATION);
        llSetStatus(STATUS_PHANTOM, TRUE);
        llSetStatus(STATUS_BLOCK_GRAB, TRUE);

    }

    touch_end(integer total_number)
    {
        llResetTime();
        llSetTimerEvent(2/45.0);
        angularvelocity = INITIALANGULARVELOCITY; 
        framestart = (integer)llGetEnv("frame_number");
        llSetKeyframedMotion( buildKeyframes( STEPTIMETEST, angularvelocity ) , [ KFM_DATA, KFM_ROTATION ] );
    }

    timer()
    {
        if ( llGetTime() > STEPTIMETEST )
        {

            llSetKeyframedMotion( [], [ ] );
            while ( llGetOmega() != ZERO_VECTOR ) llSleep( 1/45.0);
            llResetTime();
        }
        frameend = (integer)llGetEnv("frame_number");
        if ( ( llGetOmega() == ZERO_VECTOR ) && ( frameend - framestart > 3 ) )
        {

            llOwnerSay(llList2CSV(["angularvelocity", RAD_TO_DEG* angularvelocity, "frames", frameend-framestart ]));
            angularvelocity -= STEPANGULARVELOCITY; 

            if (  angularvelocity > 0.0 )
            {
                framestart = (integer)llGetEnv("frame_number");
                llSetKeyframedMotion( buildKeyframes( 5.0, angularvelocity ) , [ KFM_DATA, KFM_ROTATION ] );
            }
            else 
            {
                llSetTimerEvent(0.0);
                llOwnerSay("end test");
            }
        }

    }
}

Results with llSetKeyframemotion


angularvelocity, 28.647890, frames, 225
[16:16] test keyframemotion - low angular velocity: angularvelocity, 28.074932, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 27.501976, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 26.929018, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 26.356062, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 25.783104, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 25.210146, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 24.637190, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 24.064232, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 23.491274, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 22.918318, frames, 226
[16:16] test keyframemotion - low angular velocity: angularvelocity, 22.345360, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 21.772404, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 21.199446, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 20.626488, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 20.053532, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 19.480574, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 18.907618, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 18.334660, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 17.761702, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 17.188745, frames, 226
[16:17] test keyframemotion - low angular velocity: angularvelocity, 16.615788, frames, 225
[16:17] test keyframemotion - low angular velocity: angularvelocity, 16.042831, frames, 225
[16:17] test keyframemotion - low angular velocity: angularvelocity, 15.469873, frames, 224
[16:18] test keyframemotion - low angular velocity: angularvelocity, 14.896916, frames, 224
[16:18] test keyframemotion - low angular velocity: angularvelocity, 14.323958, frames, 225
[16:18] test keyframemotion - low angular velocity: angularvelocity, 13.751000, frames, 226
[16:18] test keyframemotion - low angular velocity: angularvelocity, 13.178042, frames, 226
[16:18] test keyframemotion - low angular velocity: angularvelocity, 12.605084, frames, 225
[16:18] test keyframemotion - low angular velocity: angularvelocity, 12.032126, frames, 225
[16:18] test keyframemotion - low angular velocity: angularvelocity, 11.459168, frames, 225
[16:18] test keyframemotion - low angular velocity: angularvelocity, 10.886210, frames, 226
[16:18] test keyframemotion - low angular velocity: angularvelocity, 10.313251, frames, 226
[16:18] test keyframemotion - low angular velocity: angularvelocity, 9.740294, frames, 226
[16:18] test keyframemotion - low angular velocity: angularvelocity, 9.167336, frames, 126
[16:18] test keyframemotion - low angular velocity: angularvelocity, 8.594378, frames, 100
[16:18] test keyframemotion - low angular velocity: angularvelocity, 8.021420, frames, 15
[16:18] test keyframemotion - low angular velocity: angularvelocity, 7.448462, frames, 72
[16:18] test keyframemotion - low angular velocity: angularvelocity, 6.875504, frames, 42
[16:18] test keyframemotion - low angular velocity: angularvelocity, 6.302546, frames, 48
[16:18] test keyframemotion - low angular velocity: angularvelocity, 5.729589, frames, 43
[16:18] test keyframemotion - low angular velocity: angularvelocity, 5.156631, frames, 4
[16:18] test keyframemotion - low angular velocity: angularvelocity, 4.583673, frames, 56
[16:18] test keyframemotion - low angular velocity: angularvelocity, 4.010715, frames, 50
[16:19] test keyframemotion - low angular velocity: angularvelocity, 3.437758, frames, 60
[16:19] test keyframemotion - low angular velocity: angularvelocity, 2.864800, frames, 36
[16:19] test keyframemotion - low angular velocity: angularvelocity, 2.291842, frames, 22
[16:19] test keyframemotion - low angular velocity: angularvelocity, 1.718884, frames, 25
[16:19] test keyframemotion - low angular velocity: angularvelocity, 1.145927, frames, 35
[16:19] test keyframemotion - low angular velocity: angularvelocity, 0.572969, frames, 34
[16:19] test keyframemotion - low angular velocity: angularvelocity, 0.000011, frames, 4
[16:19] test keyframemotion - low angular velocity: end test

The same test with llsetangularvelocity. Rez a prim ; move it to let it float on the air without friction with the ground or other objects ; put the script inside and touch it to start the tests . The script is lightly different because the motion is full physics , but it s the same algorithm


// we ll do succesive tests
// From an angularvelocity of INITIALANGULARVELOCITY =0.5, we are turning along STEPTIMETEST seconds.
// A timer is setup to count the number of frames in simulator :
// if STEPTIMETEST is reached , we stop the motion , wait until it stops rotation and  we go to the next test 
// If STEPTIMETEST is not reached and we reach a NULL llGetOmega before this,   we stop the current test and we start the next test .
// At every test , we display the angular velocity and the time in frames between the start of the current test and when the object has stopped to turn with llGetOmega  = ZERO_VECTOR
float STEPANGULARVELOCITY = 0.01;
float STEPTIMETEST = 5.0; 
float INITIALANGULARVELOCITY = 0.5;

float angularvelocity;
integer count;

integer framestart;
integer frameend;

default
{
    state_entry()
    {
        llSetObjectName("test setangularvelocity - low angular velocity");
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetRot(ZERO_ROTATION);
        llSetStatus(STATUS_PHYSICS, TRUE);
        llSetStatus(STATUS_PHANTOM, TRUE);
        llSetStatus(STATUS_BLOCK_GRAB, TRUE);
        llSetPhysicsMaterial(GRAVITY_MULTIPLIER, 0.0,0.0,0.0,0.0);

    }

    touch_end(integer total_number)
    {
        llResetTime();
        llSetTimerEvent(2/45.0);
        angularvelocity = INITIALANGULARVELOCITY; 
        framestart = (integer)llGetEnv("frame_number");
        llSetAngularVelocity(<0,0,angularvelocity>, TRUE);
    }

    timer()
    {
        if ( llGetTime() > STEPTIMETEST )
        {

             llSetAngularVelocity(ZERO_VECTOR,TRUE);
            while ( llGetOmega() != ZERO_VECTOR ) llSleep( 1/45.0);
            llResetTime();
        }
        frameend = (integer)llGetEnv("frame_number");
        if ( ( llGetOmega() == ZERO_VECTOR ) && ( frameend - framestart > 3 ) )
        {

            llOwnerSay(llList2CSV(["angularvelocity", RAD_TO_DEG* angularvelocity, "frames", frameend-framestart ]));
            angularvelocity -= STEPANGULARVELOCITY; 

            if (  angularvelocity > 0.0 )
            {
                framestart = (integer)llGetEnv("frame_number");
               llSetAngularVelocity(<0,0,angularvelocity>, TRUE);
            }
            else 
            {
                llSetTimerEvent(0.0);
                llOwnerSay("end test");
            }
        }

    }
}

Results


angularvelocity, 28.647890, frames, 228
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 28.074932, frames, 230
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 27.501976, frames, 229
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 26.929018, frames, 227
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 26.356062, frames, 228
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 25.783104, frames, 227
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 25.210146, frames, 210
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 24.637190, frames, 228
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 24.064232, frames, 227
[16:25] test setangularvelocity - low angular velocity: angularvelocity, 23.491274, frames, 227
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 22.918318, frames, 228
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 22.345360, frames, 226
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 21.772404, frames, 228
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 21.199446, frames, 227
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 20.626488, frames, 227
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 20.053532, frames, 227
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 19.480574, frames, 227
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 18.907618, frames, 228
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 18.334660, frames, 227
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 17.761702, frames, 228
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 17.188745, frames, 226
[16:26] test setangularvelocity - low angular velocity: angularvelocity, 16.615788, frames, 227
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 16.042831, frames, 228
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 15.469873, frames, 227
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 14.896916, frames, 227
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 14.323958, frames, 227
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 13.751000, frames, 228
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 13.178042, frames, 228
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 12.605084, frames, 226
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 12.032126, frames, 227
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 11.459168, frames, 228
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 10.886210, frames, 221
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 10.313251, frames, 6
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 9.740294, frames, 205
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 9.167336, frames, 22
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 8.594378, frames, 93
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 8.021420, frames, 114
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 7.448462, frames, 22
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 6.875504, frames, 49
[16:27] test setangularvelocity - low angular velocity: angularvelocity, 6.302546, frames, 40
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 5.729589, frames, 40
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 5.156631, frames, 48
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 4.583673, frames, 51
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 4.010715, frames, 63
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 3.437758, frames, 68
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 2.864800, frames, 68
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 2.291842, frames, 30
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 1.718884, frames, 5
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 1.145927, frames, 68
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 0.572969, frames, 36
[16:28] test setangularvelocity - low angular velocity: angularvelocity, 0.000011, frames, 36
[16:28] test setangularvelocity - low angular velocity: end test

In the both motions , with llsetangularvelocity or with llsetkeyframedmotion , the problems appear below 9 degrees per seconds of simulator. I ve not done a script with llTargetomega , but , by experience , i ve met the same comportment there too.