Incorrect speed reported from HUD attachment
|
Cubey Terra
Aircraft Builder
Join date: 6 Sep 2003
Posts: 1,725
|
11-12-2005 19:00
(Originally incorrectly posted in feature feedback. Oops. Sorry for the cross posting.)
Hello. I'm having a really weird problem with my speedometer HUD and I can't tell if it's something I'm doing wrong, or if there's a bug.
I put these lines in a timer in a HUD attachment:
integer speed = (integer)(llVecMag(llGetVel())); llOwnerSay((string)speed);
The exact same lines are in a timer in a vehicle.
When I cross a border, the speed in the HUD suddenly jumps wildly off the scale. Each time it crosses the border, the reported HUD speed jumps, until it's wildly inaccurate. I come to a complete stop and the HUD reports that I'm travelling at high speed. Meanwhile, the vehicle's script still reports the correct speed.
Am I doing something wrong, or is this a bug?
_____________________
C U B E Y · T E R R A planes · helicopters · blimps · balloons · skydiving · submarines Available at Abbotts Aerodrome and XstreetSL.com 
|
Sean Martin
Yesnomaybe.
Join date: 13 Sep 2005
Posts: 584
|
Bug
11-12-2005 19:26
I've noticed this happening with my ships I've built also. Not the hud problem but the speed suddenly jumping after a border cross. So I would say its a bug maybe. I dunno about the HUD problem thou.
|
Serendipity Poppy
Registered User
Join date: 12 Nov 2005
Posts: 19
|
11-12-2005 21:31
I think it's buggy, I noticed the same thing in the Dominus Shadow when driving like craaazy. Speedometer jumped to like 50, and wouldn't settle down!
|
Travis Lambert
White dog, red collar
Join date: 3 Jun 2004
Posts: 2,819
|
11-12-2005 22:22
Could you potentially work around it by doing a check for the sim name, and if the name changes since the last speed check, hard reset the speed value to 0?
_____________________
------------------ The ShelterThe Shelter is a non-profit recreation center for new residents, and supporters of new residents. Our goal is to provide a positive & supportive social environment for those looking for one in our overwhelming world.
|
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
|
11-13-2005 00:09
I've noticed a lot in my tinkering with scripts that things go nuts when crossing sim borders, and sometimes break information scripts if I cross too many too fast (say 4 sim borders in less than 5 seconds). I've a big hunch that it may be a fundamental flaw in the way sim border crossing is handled, as there is a 5 second update lag on sensor functions across borders.
|
Francis Chung
This sentence no verb.
Join date: 22 Sep 2003
Posts: 918
|
11-14-2005 08:17
This is a bug that affects all attachments, not just HUDs, and existed prior to 1.7. If your avatar is seated, and you cross a sim, sometimes the calls returned by llGetVel() cease to make any sense.
If you unseat yourself, the values returned by llGetVel() should make sense again.
I bug reported this a while ago, but no response from LL.
The Dominus Shadow HUD does not rely on llGetVel(), due to this bug, and you should not be able to observe "the needle getting stuck" problem if you're using my HUD.
My workaround has been to construct my own getVel() function from llGetPos(), with an exponential decay to to try and smooth out velocity spikes.
_____________________
-- ~If you lived here, you would be home by now~
|
Cubey Terra
Aircraft Builder
Join date: 6 Sep 2003
Posts: 1,725
|
11-14-2005 08:42
From: Francis Chung This is a bug that affects all attachments, not just HUDs, and existed prior to 1.7.
...
I bug reported this a while ago, but no response from LL
...
My workaround has been to construct my own getVel() function from llGetPos(), with an exponential decay to to try and smooth out velocity spikes. Ugh. I'm not so clever with those number thingies. 
_____________________
C U B E Y · T E R R A planes · helicopters · blimps · balloons · skydiving · submarines Available at Abbotts Aerodrome and XstreetSL.com 
|
Cid Jacobs
Theoretical Meteorologist
Join date: 18 Jul 2004
Posts: 4,304
|
11-14-2005 10:29
From: Cubey Terra Ugh. I'm not so clever with those number thingies.  Urg, it's still kinda early in the morn here, but maybe this is something like what you are looking for? timer() { new = llGetPos(); if ( new. x < current .x) { xvalue = current .x - new .x; } if ( new .x > current .x) { xvalue = new .x - current .x ; } if ( new .x == current .x) { xvalue = new .x - current .x ; } if ( new.y < current .y) { yvalue = current .y - new .y ; } if ( new .y > current .y) { yvalue = new .y - current .y ; } if ( new .y == current .y) { yvalue = new .y - current .y ; } if ( new.z < current .z) { zvalue = current .z - new .z ; } if ( new .z > current .z) { zvalue = new .z - current .z ; } if ( new .z == current .z) { zvalue = new .z - current .z ; } float beforevalue = llSqrt((yvalue * yvalue) + (xvalue * xvalue)); float aftervalue = llSqrt((beforevalue * beforevalue) + (zvalue * zvalue)); llSetText((string)llRound((2.4 * aftervalue)) + " kph/" + (string)llRound((1.488 * aftervalue)) + " mph", <1,1,1>, 1); current = new; } Hope that's 1/2 accurate and hope it helps. Good Luck  .
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
11-14-2005 12:05
From: Cid Jacobs timer() { new = llGetPos(); if ( new. x < current .x) { xvalue = current .x - new .x; } ...
Hope that's 1/2 accurate and hope it helps. Good Luck  . *Head Tilt* i suppose you don't know about llVecDist timer() { new = llGetPos(); float time = llGetWallclock(); float speed = llVecDist(new, old_pos)/(time - old_time); llSetText((string)llRound((2.4 * speed)) + " kph/" + (string)llRound((1.488 * speed)) + " mph", <1,1,1>, 1); old_pos = new; old_time = time; }
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Cid Jacobs
Theoretical Meteorologist
Join date: 18 Jul 2004
Posts: 4,304
|
11-14-2005 12:17
From: Strife Onizuka *Head Tilt* i suppose you don't know about llVecDist I do, but i thought the idea was to do it with as much math and as little LSL as possible 
|
Huns Valen
Don't PM me here.
Join date: 3 May 2003
Posts: 2,749
|
11-14-2005 13:25
llGetVel() is also not aware of whether physics are turned on or off, and will continue to report that you are in fact moving at some nonzero velocity even though you are nailed in place. I told them about that ages ago.
|
Cubey Terra
Aircraft Builder
Join date: 6 Sep 2003
Posts: 1,725
|
11-15-2005 07:52
From: Cid Jacobs Urg, it's still kinda early in the morn here, but maybe this is something like what you are looking for? Hope that's 1/2 accurate and hope it helps. Good Luck  . Cid wins! It works like a charm. Unfortunately, Strife, your version results in a math error (possibly divide by zero), which I'm sure is fixable. It's interesting to note that for about a second after each border crossing, this too reports a huge increase in velocity, but then returns to normal. Thank you, Cid and Strife. I'll send you both my speed indicator HUD when it's done!
_____________________
C U B E Y · T E R R A planes · helicopters · blimps · balloons · skydiving · submarines Available at Abbotts Aerodrome and XstreetSL.com 
|
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
|
11-15-2005 08:58
From: Cubey Terra Cid wins! It works like a charm. Unfortunately, Strife, your version results in a math error (possibly divide by zero), which I'm sure is fixable.
It's interesting to note that for about a second after each border crossing, this too reports a huge increase in velocity, but then returns to normal. Remember that llGetPos() is in local coordinates, you need to add llGetRegionCorner() to get it in global coordinates so that pos(t+1) isn't suddenly 127.8 meters away from pos(t) instead of 0.2 meters away.
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
11-15-2005 12:01
From: Cubey Terra Unfortunately, Strife, your version results in a math error (possibly divide by zero), which I'm sure is fixable.
I was worried about that, some of the time functions round off the number of seconds to an integer value (and return it in a float). The issue is then is if you poll it faster then once per second the time differences will register as zero. //This will return a bad value when you first cross a sim boundary do to the time reset //Since this value is already bad why should we care about the sim position? //This will also be adversely effected by timedilation, it will report a higher velocity then actually is occurring. timer() { new = llGetPos();// + llGetRegionCorner(); float speed = llVecDist(new, old_pos)/(llGetAndResetTime()); llSetText((string)llRound((2.4 * speed)) + " kph/" + (string)llRound((1.488 * speed)) + " mph", <1,1,1>, 1); old_pos = new; }
or timer() { new = llGetPos() + llGetRegionCorner(); string timestamp = llGetSubString(llGetTimeStamp(),11,-1); float time = (integer) timestamp * 3600 + (integer) llGetSubString(timestamp, 3, 4) * 60 + (float) llGetSubString(timestamp, 6, -1); float speed = llVecDist(new, old_pos)/(time - old_time); llSetText((string)llRound((2.4 * speed)) + " kph/" + (string)llRound((1.488 * speed)) + " mph", <1,1,1>, 1); old_pos = new; old_time = time; }
Since we want accurate results we don't rely on the timer event triggering at regular intervals; which is what Cid is doing. Cid's function, like my first in this post will be effected by time dilation. But if you want to execution time you want to use llVecDist instead of chained if statements (which you don't need) or the two square roots (which you only need one). Basically the math he does simplifies down to to the definition of llVecDist. I guaranty that the LSL function will be faster then his code, and more importantly, more accurate (VM will do the math in a full register, probably a double or long double and then truncate it to a float, this will result in a number with every bit being accurate; doing the math in LSL will result in accumulated errors by forcing intermediate results to be put into floats). Trust the LSL math functions, LL would have to have done something really bad to screw them up. timer() { new = llGetPos() + llGetRegionCorner(); string timestamp = llGetSubString(llGetTimeStamp(),11,-1); float speed = llVecDist(new, old_pos); llSetText((string)llRound((2.4 * speed)) + " kph/" + (string)llRound((1.488 * speed)) + " mph", <1,1,1>, 1); old_pos = new; }
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Cubey Terra
Aircraft Builder
Join date: 6 Sep 2003
Posts: 1,725
|
11-15-2005 13:07
From: Strife Onizuka
Trust the LSL math functions, LL would have to have done something really bad to screw them up.
Great! I'll try this out tonight. As for trusting the LSL math functions, isn't that the reason why we're having this problem in the first place? 
_____________________
C U B E Y · T E R R A planes · helicopters · blimps · balloons · skydiving · submarines Available at Abbotts Aerodrome and XstreetSL.com 
|
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
|
11-15-2005 13:20
Why not start by checking the time difference, and if the time difference is less than some fraction of the expected time difference you bail out and pick up on the next cycle?
|
Cubey Terra
Aircraft Builder
Join date: 6 Sep 2003
Posts: 1,725
|
11-15-2005 18:06
From: Strife Onizuka timer() { new = llGetPos() + llGetRegionCorner(); string timestamp = llGetSubString(llGetTimeStamp(),11,-1); float speed = llVecDist(new, old_pos); llSetText((string)llRound((2.4 * speed)) + " kph/" + (string)llRound((1.488 * speed)) + " mph", <1,1,1>, 1); old_pos = new; }
Still confused. Your line "float speed = llVecDist(new, old_pos);" doesn't seem to calculate speed, but only the meters travelled since the last timer interval. Did you mean to divide that by the number of seconds that has actually elapsed since the last timer interval (which you don't include)? Here's my attempt: timer() { pos = llGetPos() + llGetRegionCorner(); float currentSec = (float)(llGetSubString(llGetTimestamp(),17,20)); float secDiff = (currentSec - oldSec);
float speed = (llVecDist(pos, oldPos)) / secDiff; // speed in meters per second llSetText((string)llRound((2.4 * speed)) + " kph\n" + (string)llRound((1.488 * speed)) + " mph\n" + (string)llRound(1.94384449 * speed) +" kts", <1,1,1>, 1); oldPos = pos; oldSec = currentSec; }
_____________________
C U B E Y · T E R R A planes · helicopters · blimps · balloons · skydiving · submarines Available at Abbotts Aerodrome and XstreetSL.com 
|
Jillian Callahan
Rotary-winged Neko Girl
Join date: 24 Jun 2004
Posts: 3,766
|
11-15-2005 19:00
vector old_pos; float interval = 0.5; float getVel() { vector new = llGetPos(); float speed = llVecDist(new, old_pos) / interval; old_pos = new; return speed; } default { state_entry() { old_pos = llGetPos(); llSetTimerEvent(interval); } timer() { float vel = getVel(); llSetText((string)vel, <1,1,1>, 1.0); } } Strife's version gets the div/zero error if you check again in less than one second.
|
Cubey Terra
Aircraft Builder
Join date: 6 Sep 2003
Posts: 1,725
|
11-15-2005 19:19
From: Jillian Callahan Strife's version gets the div/zero error if you check again in less than one second.
Your version is vulnerable to time dilation too, since there's no guarantee that the timer will actually trigger exactly by the amount specified by interval.
_____________________
C U B E Y · T E R R A planes · helicopters · blimps · balloons · skydiving · submarines Available at Abbotts Aerodrome and XstreetSL.com 
|
Jillian Callahan
Rotary-winged Neko Girl
Join date: 24 Jun 2004
Posts: 3,766
|
11-15-2005 19:40
From: Cubey Terra Your version is vulnerable to time dilation too, since there's no guarantee that the timer will actually trigger exactly by the amount specified by interval. Yep. Thus far I'm unable to think of a way about that.
|
Kala Bijoux
Material Squirrel
Join date: 16 Nov 2004
Posts: 112
|
11-15-2005 21:56
I would get a timestamp on each timer call. On pretty much any system, that will be more reliable than expecting an event to be received at a specific time. And from my experience, the "real-time-ness" of the SL scripting environment is pretty poor, which makes it even more risky to rely on timers firing at the right time.
I'd also incorporate Argent's advice - if the time difference is too small for reliable floating point math, I would skip the update for that cycle, but leave the old position/time variables unchanged, so on the next cycle you pick up new values and do the math for the distance travelled in two time cycles. I don't think it matters that much if the speed display doesn't update on each and every tick.
|
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
|
11-18-2005 14:32
From: Jillian Callahan Yep. Thus far I'm unable to think of a way about that. This is a standard SCADA problem. If you know that you're periodically going to get bad values in a stream of data, and you can detect when they happen, you just ignore those values and interpolate from previous data. For a HUD, this is pretty easy... decide what will be an impossible value (time change less than the delay time, for example) and either keep displaying the previous value, or interpolate what the correct value should be from the previous TWO values. More than two values, even, but that would mean you'd have to get into the "using a list as an array" game. if (new_time <= last_time) { if(num_bad++ > TOO_MANY_BAD) { llOwnerSay("Wah! I am all messed up! I die!"); llResetScript(); } float last_change = current_val - last_val; last_val = current_val; current_val = current_val + last_change; } else { num_bad = 0; //calculate new value code goes here; // and apply it... last_val = current_val; current_val = new_val; } //now display the new current val
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
11-18-2005 15:33
From: Cubey Terra Great! I'll try this out tonight. As for trusting the LSL math functions, isn't that the reason why we're having this problem in the first place?  math != physics The only math functions that will have a large margin of error are llEuler2Rot and Rot2Euler, the other functions should be pretty safe.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river. - Cyril Connolly
Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence. - James Nachtwey
|
Seifert Surface
Mathematician
Join date: 14 Jun 2005
Posts: 912
|
11-19-2005 01:35
This almost certainly isn't a related issue, but is another example of llGetVel behaving strangely. I have a simple readout prim that checks llGetVel every half second, worn on my avatar (I don't think it matters where). Standing on a flat surface, if I then turn on the spot (hold down the left or right arrow, no walking anywhere), the velocity seems to hover around <0.0,0.0,-0.2>. This happens when turning either direction. When standing on a slope the other coordinates get in on the act too, in a way that I haven't been able to work out. This is very strange. For one, turning on the spot is at least partially a client side thing, because you can do it when the connection has gone down but SL hasn't noticed it. Ah, I think I have an explanation... whenever one moves, even just turning, then one can see gravity "turn on" (as in the acceleration readout goes to <0.0,0.0,-9.8> - when standing still it goes to <0.0,0.0,0.0> as the physics engine efficiently ignores me). When gravity is on, I am presumably always trying to fall, but the floor is always resetting my position upwards. Or perhaps the llGetVel function is doing some lookahead which then becomes inaccurate when the floor takes effect. Interesting anyway 
_____________________
-Seifert Surface 2G!tGLf 2nLt9cG
|
Jay Edelbrock
Registered User
Join date: 19 Feb 2005
Posts: 19
|
11-20-2005 04:37
you all may look at me, point, and laugh for suggesting this, but do you have:
on_rez(integer s_param) { llResetScript(); }
|