Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

type mismatch - vector

Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-26-2006 15:58
Why doesn't this work?

CODE
vector vel = llDetectedVel(0);
if(vel > ZERO_VECTOR)
...
Gives me type mismatch error but I don't see why since both are vectors...
Seifert Surface
Mathematician
Join date: 14 Jun 2005
Posts: 912
02-26-2006 16:16
There is no ordering on vectors. Perhaps you want llVecMag(vel) > 0?
_____________________
-Seifert Surface
2G!tGLf 2nLt9cG
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-26-2006 16:28
There isn't? Why does this work then?:

CODE
vector vel = llGetVel();
while(vel.z < 0) jump loop;
...
Seifert Surface
Mathematician
Join date: 14 Jun 2005
Posts: 912
02-26-2006 16:38
Because vel.z is a float (the z component of the vector).
_____________________
-Seifert Surface
2G!tGLf 2nLt9cG
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-26-2006 18:28
Why wouldn't there be vector ordering? How else does it return a vector then if it's not in the form <x,y,z>?
Seifert Surface
Mathematician
Join date: 14 Jun 2005
Posts: 912
02-26-2006 18:41
By an "ordering" I mean a rule to say which of two vectors is "bigger", which is what you want to know if you ask if a < b. Looking at the magnitudes of the vectors would be one way to try to do it, but then how do you decide how to order two vectors of the same magnitude?

There just isn't a nice way to do it that works well with addition of vectors, so it isn't generally defined. It is possible to come up with orderings (e.g. the lexicographical ordering) on vectors, but such an ordering just isn't very useful.

I'm not sure what you mean by "How else does it return a vector then if it's not in the form <x,y,z>?". Vectors (in SL at least) are always of the form <x,y,z>, but that doesn't give you an ordering.
_____________________
-Seifert Surface
2G!tGLf 2nLt9cG
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-26-2006 19:23
Er, how wouldn't it give an ordering? <x,y,z> is just that: x-axis float, y-axis float, z-axis float--that's an order to me! I don't want to know which vector is bigger (an operation on a vector); I simply want the vector. Ah well...I got what I wanted with just the z-axis float. Thanks anyway.
Seifert Surface
Mathematician
Join date: 14 Jun 2005
Posts: 912
02-26-2006 19:36
Sorry, I'm using the word "ordering" in it's technical meaning, an ordering meaning a relation "<" that tells you the order in which elements come. So 1 < 3, 3 < PI etc. It works nicely with floats (well, real numbers), it doesn't work nicely with (3d) vectors.
_____________________
-Seifert Surface
2G!tGLf 2nLt9cG
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-26-2006 20:01
Well, however "ordering" means, I don't see why llDetectedVel can't return the vector in the x,y,z order. But, anyway, I think the problem might've been because I wasn't calling it inside an event as per the note on llDetectedVel:
From: someone
Note: The llDetected* functions will only return a meaningful value in the collision, collision_start, collision_end, sensor, touch, touch_start, or touch_end events.
Even though the call to the user-defined function WAS in a touch_start event. The error message put the cursor after "ZERO_VECTOR" and before the ";)" so it could'nt've been ZERO_VECTOR because I was trying to compare a vector to a vector... Ah well. I just don't get how "ordering" would matter if ZERO_VECTOR is <0,0,0> anyway so why would order matter?
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
02-26-2006 20:18
*blinks*
to put what Seifert said another way, vector-vector operations lack "<" and ">" operators. You cannot use "<" or ">" for compairing vectors. As you will see on the boolean operators page of the wiki, that "<" & ">" can only be used on floats and integers.

how would you define a vector-vector greater than operation?
is <1,0,0> > <0,0,0>?
is <-1,0,0> > <0,0,0>?
is <-1,0,0> > <1,0,0>?
is <1,-1,0> > <-1,1,0>?
is <1,-1,1> > <-1,1,1>?
is <1,-1,-1> > <-1,-1,1>?

You can use the llDetected* functions in user functions if they are called by events that support the llDetected* functions. If called otherwise they will return default values.
_____________________
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
Kayla Stonecutter
Scripting Oncalupen
Join date: 9 Sep 2005
Posts: 224
02-27-2006 15:15
Eep, if all you want is to make sure you're getting some kind of velocity, use this:
CODE
if(vel != ZERO_VECTOR) ...
_____________________
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-27-2006 15:36
From: Kayla Stonecutter
Eep, if all you want is to make sure you're getting some kind of velocity, use this:
CODE
if(vel != ZERO_VECTOR) ...
That doesn't work. What I'm trying to do is have an object disable physics and move down a bit to settle into place (to compensate for the physics collision 10cm buffer):
CODE
settle()
{
if(llGetStatus(STATUS_PHYSICS) == 1)
{
vector vel = llGetVel();
while(vel != ZERO_VECTOR);//(vel.z < 0)
{
// llSetText("velocity: "+(string)vel,<1,1,1>,1);
llSetStatus(STATUS_PHYSICS,1);
llSleep(1);
if(vel == ZERO_VECTOR) jump break;
}
@break;
llSetStatus(STATUS_PHYSICS,0);
llSetPos(llGetPos()-<0,0,.1>);
}
}

default
{
state_entry()
{
settle();
}

moving_end()
{
settle();
}
}
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
02-27-2006 15:57
That's cause you're dealing with floats. You'll never get exactly down to 0. Even if vel.z is 0.000001, it won't be 0.0, so it won't break.

When working with floats, you need to work with margins of error, not absolute values. So you say, "I'll consider the object to have stopped moving if it's velocity is less than 0.1 m/s". Or 0.01, or 0.001 - basically, you need to set the tolerance level you're willing to accept. Then:

CODE
if (vel == ZERO_VECTOR)


gets replaced by:

CODE

float tolerance = 0.01; // Or whatever

...

if (llVecMag(vel) <= tolerance)


As you've found, if you try to compare it with exactly 0, you'll probably end up waiting a very long time. Doing it this way changes that to 'is it close enough to 0 that I don't care about the error", and that will converge much faster.

Edit: Ditto for the while() check that creates the loop. And while (ha ha) on that topic... you don't really need both the while check and the if check, but you can ignore that for now, it's probably not what's causing your problem.
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-27-2006 21:21
From: Ziggy Puff
That's cause you're dealing with floats. You'll never get exactly down to 0. Even if vel.z is 0.000001, it won't be 0.0, so it won't break.

...

Edit: Ditto for the while() check that creates the loop. And while (ha ha) on that topic... you don't really need both the while check and the if check, but you can ignore that for now, it's probably not what's causing your problem.
Actually, floats aren't my problem because this works fine:
CODE
@loop;
llSetStatus(STATUS_PHYSICS,1);
llSleep(1);
vector vel = llGetVel();
//llSetText("velocity: "+(string)vel,<1,1,1>,1);
while(vel.z < 0) jump loop;
llSetStatus(STATUS_PHYSICS,0);
llSetPos(llGetPos()-<0,0,.1>);
But I would rather not have to use llSleep and use the moving_end event.
Starax Statosky
Unregistered User
Join date: 23 Dec 2003
Posts: 1,099
02-27-2006 23:40
Eep. I found the moving_end event very unpredictable. I use a timer event to check the velocity with something like:

If (llVecMag(llGetVel())<0.1 && llVecMag(llGetOmega())<0.1)

I tried a few methods and that was the best one that I came up with. I'm sure there are better ways but that was the first one that worked reliably and so I ran with it.

I didn't like the idea of testing for zero velocity because the physics engine can sometimes make an object jiggle around for quite sometime before finally coming to an halt. If indeed it ever does really stop.


Now this is where Jeff Gomez comes in and says "You can test for zero velocity with just a single function call and have it make you ice cream too.".


Cue Jeff!!!.
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
02-28-2006 08:59
CODE
while(vel.z < 0) jump loop; 


That's a completely different check, because you're not checking for equality with 0. If the object hits the ground and bounces up, vel.z will be positive. If your code happens to wake up from its sleep during one of these upward motion stages, that check will pass, and it will break out of the loop. This loop will break for 0 and positive numbers, while your previous loop would only break on 0, it would continue for negative and positive vectors. The equivalent of your:

CODE
 while(vel != ZERO_VECTOR)


would be:

CODE
while (vel.z != 0)


Try that and see how long it takes. That waits for it to be exactly 0, and ignores both positive and negative values.

And yes, I exaggerated, it's not true that it'll *never* be equal to 0, but it'll take a long time.

Try a simple test. Without trying to stop the object, just set a 1 second timer and have it llSay its velocity. See how long it takes for it to report <0.00000, 0.00000, 0.00000> as its velocity.
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
02-28-2006 22:20
Again, the issue isn't with floats or vectors anymore...
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
03-01-2006 01:40
Can you explain what the problem is so us mere mortals can understand it then?

I'm also confused about your script fragment - in a "while vel.z !=0" loop you've got a if(vel.z==0) jump line... I know you could get the condition momentarily, but it strikes me as more than likely the if statement will never evaluate as true, because the while will first.
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
03-01-2006 02:45
From: Eloise Pasteur
Can you explain what the problem is so us mere mortals can understand it then?

I'm also confused about your script fragment - in a "while vel.z !=0" loop you've got a if(vel.z==0) jump line... I know you could get the condition momentarily, but it strikes me as more than likely the if statement will never evaluate as true, because the while will first.
That's the problem. :P How do I structure the flow control to make a physical-only object settle if it does/doesn't have velocity without using a timer and, instead, using the moving_end event? I don't want moved non-physical objects to settle.
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
03-01-2006 02:54
From: Starax Statosky
I didn't like the idea of testing for zero velocity because the physics engine can sometimes make an object jiggle around for quite sometime before finally coming to an halt. If indeed it ever does really stop.
A physical object will definitely come to a halt (settle)--and even lose its physical status if it interpenetrates something in the process of settling--but it depends on the object's velocity and/or bouyancy. An object with a continuous impulse/collision will tend to never settle (unless it interpenetrates something). A negatively buoyant object proportionally bounces around more before it settles. A physical joint sometimes never settles or can settle quickly depending on what's around (still researching it but joints are flaky).
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
03-01-2006 03:02
I'm still not getting it.

Non phsyical objects don't settle, they're non-physical so they ignore gravity.

Physical objects do settle, by their very nature.

Moving non-physical objects requires things like llSetPos(), or editing, moving physical ones either llMoveToTarget() or llPushObject/llApplyImpulse type commands.

So there are scripting differences.

If you want to automatically toggle a physical object to be non-physical once it's settled, something like:

CODE
while(llVecMag(velocity)<0.001)
{
llSetStatus(STATUS_PHYSICS, FALSE);
}


ought to do the trick I think?

Something using a double variable system might be friendlier on the sim:

CODE
integer moving=TRUE;
while(moving)
{
if(llVecMag(velocity) < 0.001)
{
llSetStatus(STATUS_PHYSICS, FALSE);
moving=FALSE;
}
}
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
03-01-2006 23:19
From: Eloise Pasteur
I'm still not getting it.

Non phsyical objects don't settle, they're non-physical so they ignore gravity.

Physical objects do settle, by their very nature.

Moving non-physical objects requires things like llSetPos(), or editing, moving physical ones either llMoveToTarget() or llPushObject/llApplyImpulse type commands.

So there are scripting differences.
Um, no shit? I've already made the distinction between physical and non-physical objects. What I WANT is a PHYSICAL object to SETTLE (PLUS move down the collision boundary offset). Please see my code in this post.

From: Eloise Pasteur
If you want to automatically toggle a physical object to be non-physical once it's settled, something like:

CODE
while(llVecMag(velocity)<0.001)
{
llSetStatus(STATUS_PHYSICS, FALSE);
}


ought to do the trick I think?
You think? Why do so many people post code without actually testing it? <eyeroll> Anyway, as my code shows, I already do something like this and it doesn't work for what I want (as described above), which I tire of trying to explain...
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
03-01-2006 23:51
I posted untested code because:

1) I was at work and can't get into SL from work
2) You were obviously getting more and more worked up and I figured some attempt at help was better than none. Obviously I was wrong.

As you really ought to know code that is similar but not identical often does different things.

It might, of course, simply not be possible.

You've put two strictures in that don't make obvious sense - you want to avoid moving_end() (which can be quirky, but does seem like an obvious place to start) and timers to run your check - which is how I'd probably do it, just poll every second or two to see if it's still moving. It's easy enough to change the status that way, and to turn the timer off too.

Good luck with it anyway.
Sky Honey
Coder
Join date: 16 May 2005
Posts: 105
03-02-2006 04:43
From: Eep Quirk
Um, no shit? I've already made the distinction between physical and non-physical objects. What I WANT is a PHYSICAL object to SETTLE (PLUS move down the collision boundary offset). Please see my code in this post.

You think? Why do so many people post code without actually testing it? <eyeroll> Anyway, as my code shows, I already do something like this and it doesn't work for what I want (as described above), which I tire of trying to explain...

Noooo!!! Don't let Scripting Tips go the way of other forums! It's a rudeness-free zone. :)
_____________________
Eep Quirk
Absolutely Relative
Join date: 15 Dec 2004
Posts: 1,211
03-02-2006 04:57
Hey, I said "please". :P

Anyway, this works good enough:

CODE
moving_end()
{
if(llGetStatus(STATUS_PHYSICS) == 0) return;
vector vel = llGetVel();
if(vel.z == 0)
{
llSetStatus(STATUS_PHYSICS,0);
llSetPos(llGetPos()-<0,0,.1>);
}
}
1 2