Jump to content

llSetTimerEvent in listen


GManB
 Share

You are about to reply to a thread that has been inactive for 1417 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Should I be able to successfully call llSetTimerEvent from within a listen event handler? Code snippet below. Setting the timer works fine from touch_start but not from listen.

    touch_start(integer num) {
        if(isSwinging) {
            isSwinging = FALSE;
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_ROOT, [PRIM_ROTATION,initialRot]);
            llSetTouchText("Swing");
        } else {
            isSwinging = TRUE;
            llSetTimerEvent(0.02);
            llSetTouchText("Stop");
        }
    }
    timer()
    {
        integer stepIndex = 0;
        llSetTimerEvent(0.0);
        for(stepIndex=0;stepIndex<fullPeriodSteps;stepIndex++)
            {
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION,llList2Rot(rotList,stepIndex)]);
                if (llList2Integer(sleepList,stepIndex) == TRUE) llSleep(0.01);
            }
        llSetTimerEvent(0.1);
    }
    listen(integer channel, string name, key id, string message)
    {
        list arguments = llParseString2List(message,["|"],[""]);
        if(channel == privateChannel && llList2String(arguments,0) == "startSwing");
        {
            isSwinging = TRUE;
            llSetTimerEvent(0.02);
        }
        if(channel == privateChannel && llList2String(arguments,0) == "stopSwing");
        {
            isSwinging = FALSE;
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_ROOT, [PRIM_ROTATION,initialRot]);
        }

......

 

Thanks,

G

Link to comment
Share on other sites

I suspect that the problem is that you are firing the timer very fast and are resetting it way too often.  I doubt that you can get a timer to trigger at all if you set it with 

llSetTimerEvent(0.02);

There's even a note to that effect in the wiki:

If you repeatedly call this function at some interval less than sec the timer event will never fire.

As a minor point, you may find it helpful to add parentheses in if tests that include more than one condition. They aren't technically necessary and the compiler should parse things correctly, but if nothing else, extra parentheses make things more human-readable. So, for example....

if( (channel == privateChannel ) && ( lList2String(arguments,0) == "startSwing"))

BTW, you have repeated the same fatal error in both if tests in the listen event. Get rid of the semicolon at the end of both. Your script will run as written,. but it will ignore the stuff after each test (or misinterpret it).  😎

Link to comment
Share on other sites

2 minutes ago, Rolig Loon said:

I suspect that the problem is that you are firing the timer very fast and are resetting it way too often.  I doubt that you can get a timer to trigger at all if you set it with 

llSetTimerEvent(0.02);

There's even a note to that effect in the wiki:

If you repeatedly call this function at some interval less than sec the timer event will never fire.

As a minor point, you may find it helpful to add parentheses in if tests that include more than one condition. They aren't technically necessary and the compiler should parse things correctly, but if nothing else, extra parentheses make things more human-readable. So, for example....

if( (channel == privateChannel ) && ( lList2String(arguments,0) == "startSwing"))

BTW, you have repeated the same fatal error in both if tests in the listen event. Get rid of the semicolon at the end of both. Your script will run as written,. but it will ignore the stuff after each test (or misinterpret it).  😎

Added parens... semi's were cut-n-paste error :)

"If you repeatedly call this function at some interval less than sec the timer event will never fire."

I interpreted this statement to mean, given that 'sec' is bold and dotted-underlined, that if I have calls to llSetTimerEvent in code that causes llSetTimerEvent to be executed at an interval less than the _value_ of the sec argument to llSetTimerEvent. In my specific case my interpretation would mean I would have to be careful to not to call llSetTimerEvent sooner than 0.02 seconds after the initial call. Since I do not call llSetTimerEvent in the code path from listen except from within timer which should be ok because the timer fired. Finally, the values to llSetTimerEvent work fine with called from within touch_start.

Does my interpretation seem reasonable or should I take 'sec' to me 1.0 seconds?

Also, I did test llSetTimerEvent from within the listen with an argument of 1.0 and that did not change behavior.

 

G

Link to comment
Share on other sites

Continuing testing I tried using 1.0 as an argument to llSetTimerEvent in _both_ the llSetTimerEvent calls (one in touch_start and one in listen) and now both touching and menu driven start/stop work fine.

G

Link to comment
Share on other sites

I'm glad that worked.  LSL isn't always as predictable as we might hope.  I suspect resident gremlins.  Kidding aside, though, debugging even something as simple as this can be confusing because there may be more than one thing creating problems.  If you're lucky enough to clear up one issue, there may be another lurking below the surface. Until you do enough testing to be sure, you can't tell whether you've really found the root of the problem.  It often helps to add debug messages at key spots, just to be sure that you know what values are being tossed around.

Link to comment
Share on other sites

Plenty of debug print stmts that I removed from pasted code :)

Yeah. Every execution environment has it's seemingly goofy idiosyncrasies. I think I am over the hump wrt the overall execution model. I am certain bits of goofiness remain.

Just finished watching the launch... wheeee.. what fun!!

G

Link to comment
Share on other sites

Rolig,

BTW, referencing a couple other threads, I am now happy with having the frame both rez and re-position any time after rez, the swing at the proper relative position and rotation. And with the swing motion always being correct relative to the frame. Things seemed to make a lot more sense once I got the frame and swing local axes correct for SL when exporting from Maya and using llRezAtRoot (instead of llRezObject).

And I am almost certain that, for now, I will be going with a fully manual process to align the swing and frame (via llDialog menu from frame). Just, it seems to me, too many weird corner cases to cover to try to do that automatically... Maybe once I am more proficient.

Thanks for your help!

G

Link to comment
Share on other sites

7 hours ago, GManB said:

"If you repeatedly call this function at some interval less than sec the timer event will never fire."

I interpreted this statement to mean, given that 'sec' is bold and dotted-underlined, that if I have calls to llSetTimerEvent in code that causes llSetTimerEvent to be executed at an interval less than the _value_ of the sec argument to llSetTimerEvent. In my specific case my interpretation would mean I would have to be careful to not to call llSetTimerEvent sooner than 0.02 seconds after the initial call. Since I do not call llSetTimerEvent in the code path from listen except from within timer which should be ok because the timer fired. Finally, the values to llSetTimerEvent work fine with called from within touch_start.

Does my interpretation seem reasonable or should I take 'sec' to me 1.0 seconds?

You're correct. When you call llSetTimerEvent(1), the timer-event won't be triggered until one second has passed. If you call llSetTimerEvent(1) again after only 0.5 seconds, the timer-event is pushed back and won't be triggered until one second has passed since the new call.

I consider this a useful feature, it would be way more inconvenient if you couldn't update and avoid the timer event being triggered after the first call.

Edit: @Mollymews 1/45 = 0.0222...

Edited by Wulfie Reanimator
  • Like 2
Link to comment
Share on other sites

1 hour ago, Wulfie Reanimator said:

You're correct. When you call llSetTimerEvent(1), the timer-event won't be triggered until one second has passed. If you call llSetTimerEvent(1) again after only 0.5 seconds, the timer-event is pushed back and won't be triggered until one second has passed since the new call.

I consider this a useful feature, it would be way more inconvenient if you couldn't update and avoid the timer event being triggered after the first call.

Ok, I see that. And I agree it's a useful feature. But, in the original situation when things were not working as I expected I was calling llSetTimerEvent(0.02). And, as far as I could determine, there should be no calls to llSetTimerEvent until it fired. So, potentially, two things could cause this. 1. As Rolig said, things just might get squirrelly with such a small value as an argument, or, 2. something happening in my code that I didn't understand was causing fast repeated calls to llSetTimerEvent(0.02).  As much as I dislike just saying it it's probably 1 since *increasing* the interval fixed the issue... sighs...

Maybe something to do with this 'frame time' of 22ms... but, that's another discussion :)

G

Link to comment
Share on other sites

2 hours ago, GManB said:

Maybe something to do with this 'frame time' of 22ms... but, that's another discussion :)

each type of event fires once per frame. A frame is nominally 1/45 of a second  (0.222). When the server lags then frame rate slows

in another post I typoed 0.0222 instead of 0.222. Which might have led you to work wrongly

we can check for the server frame rate with

http://wiki.secondlife.com/wiki/LlGetRegionFPS

and/or

http://wiki.secondlife.com/wiki/LlGetRegionTimeDilation

 

edit oops

what Wulfie said. Is Sunday morning and I cant count anymore

 

 

Edited by Mollymews
  • Like 1
  • Confused 1
Link to comment
Share on other sites

6 minutes ago, Mollymews said:

everything is a typo at the moment

lol...but seriously...

first, 1/45th of a sec is 0.0222 or 22.2ms ... so 0.0222 is not a typo.

but, events fire only once a frame? Ugh... why? Then llSetTimerEvent(x) where x is less than 0.0222 will result in oddness... ..in my original code I set x to 0.02 which is slightly less than 0.0222 so oddness could occur...

btw, my academic and professional background is in real-time OSs, VM, scheduling, and scheduling theory... working in this environment is new for me and I can see we do need to be very clever about things.

G

Link to comment
Share on other sites

yes GManB, the SL realtime engine comes with its own set of nuances. We have to get inventive sometimes

like a way to ameliorate jitter is to run a timer and a sensorrepeat simultaneously. When the server is running normally then we get up to 2 timed events every frame

when this gets really critical then we can add another script.  Now up to 4 timed events every frame. And so on

 

Link to comment
Share on other sites

11 minutes ago, Mollymews said:

yes GManB, the SL realtime engine comes with its own set of nuances. We have to get inventive sometimes

like a way to ameliorate jitter is to run a timer and a sensorrepeat simultaneously. When the server is running normally then we get up to 2 timed events every frame

when this gets really critical then we can add another script.  Now up to 4 timed events every frame. And so on

 

I see. So we get one timed event *type* per frame. Sensor and timer are different types so we get two. What about asynchronous events like, touch_start?

G

 

Link to comment
Share on other sites

6 minutes ago, GManB said:

I see. So we get one timed event *type* per frame. Sensor and timer are different types so we get two. What about asynchronous events like, touch_start?

G

 

touch_start's parameter (the integer) enumerates all of the people who touched it during the same frame, 0 being the first index.

Link to comment
Share on other sites

Another important thing is that LSL scripts only have a single execution pointer, your timer() will only be able to fire after the current event is completed.

In addition, events are not guaranteed to fire on the frame they are scheduled, I believe that is what the "missed event" region stat is.

Edited by Kyrah Abattoir
Link to comment
Share on other sites

On 5/30/2020 at 7:51 PM, Rolig Loon said:

I suspect that the problem is that you are firing the timer very fast and are resetting it way too often.  I doubt that you can get a timer to trigger at all if you set it with 

llSetTimerEvent(0.02);

There's even a note to that effect in the wiki:

If you repeatedly call this function at some interval less than sec the timer event will never fire.

As a minor point, you may find it helpful to add parentheses in if tests that include more than one condition. They aren't technically necessary and the compiler should parse things correctly, but if nothing else, extra parentheses make things more human-readable. So, for example....

if( (channel == privateChannel ) && ( lList2String(arguments,0) == "startSwing"))

BTW, you have repeated the same fatal error in both if tests in the listen event. Get rid of the semicolon at the end of both. Your script will run as written,. but it will ignore the stuff after each test (or misinterpret it).  😎

You can. It’s negligible whether you notice the difference under 0.05 but they do fire down to 0.01 and possibly below and do run code

Link to comment
Share on other sites

7 hours ago, ItHadToComeToThis said:

You can. It’s negligible whether you notice the difference under 0.05 but they do fire down to 0.01 and possibly below and do run code

Referencing the two diagrams attached. This is how I think llSTE behaves in reference to the line in the wiki that Rolig referenced, "f you repeatedly call this function at some interval less than sec the timer event will never fire."

In diag A things work out as expected llSTE(x) is executed at time t0, the timer() event handler is executed at time t1. llSTE(y) is called at time t2 and time timer() event handler is called at time t3. All find and dandy.

In diag B llSTE(x) is called again at time t0 but due to whatever concurrency issues llSTE(y) is called before t1. In this case the timing code is *reset* to t2+y and the timer() event handler is executed only once at t3.

Note that the magnitude of x and y are irrelevant to the behavior in scenarios A and B. x could be 48 hours and y 50 hours or x could be 10m and y 20ms..same behavior... what we do not know is the lower bound on llSTE. ItHadToComeToThis says that giving 10ms as a argument to llSTE has observably correct behavior..

What is clear to me now is that there is only a single 'timer' and llSTE called before the expiration of the previous call actually resets that single 'timer'.

Agree or disagree?

 

G

Screen Shot 2020-06-07 at 19.40.34.png

Screen Shot 2020-06-07 at 19.40.46.png

Link to comment
Share on other sites

5 hours ago, Lucia Nightfire said:

Setting another timer value will reset the current timer. If a timer() event is already queued, it will remain queued.

Setting a timer of 0.0 will cull a queued timer() event.

When does a timer() event get queued? At the expiration of the time given as an argument to llSTE?

Link to comment
Share on other sites

10 hours ago, GManB said:

When does a timer() event get queued? At the expiration of the time given as an argument to llSTE?

In general, yes.

The target global end time(set & checked in the background) is updated when calling llSetTimerEvent() and again when the a timer event is queued, not when the actual timer() is triggered.

This means for example, if you set a 5.0 second timer, then either do work in a long loop or a sleep that consumes 9 seconds of script time,  your next two timer events will be 1.0 seconds apart, given whatever event delay time follows.

  • Like 1
Link to comment
Share on other sites

7 minutes ago, Lucia Nightfire said:

In general, yes.

The target global end time(set & checked in the background) is updated when calling llSetTimerEvent() and again when the a timer event is queued, not when the actual timer() is triggered.

This means for example, if you set a 5.0 second timer, then either do work in a long loop or a sleep that consumes 9 seconds of script time,  your next two timer events will be 1.0 seconds apart, given whatever event delay time follows.

Thanks. This gives me a much more complete model of the behavior.

G

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1417 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...