Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

llPushObject physics help

Kayaker Magic
low carbonated footprint
Join date: 11 Sep 2008
Posts: 109
11-21-2008 13:48
I’m frustrated trying to figure out what llPushObject actually does! I’m considering going to a sandbox and repeating basic physics experiments from the 17th century. I’ll fire myself and various objects out of a llPushObject cannon and record the distances traveled. It should be possible to analyze the data to determine how much ‘energy’ is used and how to calculate the impulse needed to push and object a required distance. But before I do these experiments, hasn’t SOMEONE already done them? Can you save me the trouble and tell me your results?

I’m pushing (gently) avatars around on a moving platform. (The non-physical platform moves, I push avatars and physical objects to simulate friction). I’m assuming that the meaning of the llPushObject vector impulse is sort of the same as the force vector in llApplyImpulse, although they don’t say so. If this is ture, a push impulse of <1,0,0> should accelerate a 1kg mass to 1m/s after 1 second.

Then the LSL Wiki article on llPushObject warns that there is a 1/(r^3) falloff of llPushObject effectiveness. It suggests calculating the distance between the pusher and pushee, cubing this and multiplying the vector impulse to compensate. This seems to work reasonably well with avatars (barring that the legs move as if they are walking). However it sometimes pushes physical objects too much, sometimes too little. Could I be running out of energy with just a few llPushObject calls every second?

So I started displaying energy and saw some strange things. Pushing an avatar along with the platform uses very little energy most of the time. But sometimes the energy drops to near zero for no reason I can figure. Pushing a small physical object causes it to move too fast the first time, but then the energy drops to 0.05 and I run out of energy on the next push.

But then I noticed that the Second Life llPushObject page has a link to a “simplified code snippet” describing how push works. (https://wiki.secondlife.com/wiki/LlPushObject/Havok4Implementation) This seems to show that the cube term does not reduce the effectiveness of the push at all! Instead it increases the energy cost of the push. (Which potentially reduces the effectiveness of the push when you run low on energy). This suggests that the cube term should not be necessary when calculating my push impulse. But when I try this my push is below some minimum threshold, and it has no effect on avatars at all (friction?) I have to put the cube term back in.
The Second Life Wiki, the code snippet there, the LSL Wiki, and the comments there all give conflicting advice on how to use llPushObject, but NONE of them work. Hasn’t somebody figured this out yet? Please tell me, or I’ll fire this avatar out of a cannon! ;-)
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
11-21-2008 15:37
I've always gone by the explanation on lslwiki.net, though there hasn't been much need to lately (this function hasn't been deprecated yet? ;) ). That indicates that there is indeed a falloff of 1/r^3 with r being the distance between the pusher and the pushee. It also indicates that the effectiveness of the push is proportional to the mass of the pushing object. From there, I would assume that the basis is a change in momentum (like llApplyImpulse()). So if you have a desired change in velocity (call it 'vector dv'), try something like:

vector dp = llGetObjectMass(target)*dv;
vector push = (CALIBRATION_CONST*r*r*r/llGetMass())*dp;

where I would obtain CALIBRATION_CONST by just the sort of experimentation you imply. Perhaps test from there using different starting distances and masses to see if this really does play out. Be sure to publish your results! :)
Kayaker Magic
low carbonated footprint
Join date: 11 Sep 2008
Posts: 109
llPushObject is useless
11-22-2008 01:28
I noticed that energy use in llPushObject was reasonable if I was very close to the pusher, but went crazy from a meter or so away. To quantify this I stuck the script below into a small cube. The results varied a lot, so I had to run it a bunch of times and average the results. It also got different results on a busy sandbox than on a quiet island. I started with a llPushObject impulse large enough to toss the avatar into a parabola with the intent of calculating the height, time and force from the distance traveled. But air friction stopped him rapidly so I settled for using a small <10.0,0.0,10.0> impulse and just recording the distance. I would expect an impulse of 10 to push a 2KG mass (my avatar) 5m in one second. There is probably friction of several sorts and I’m not going ballistic so the typical distance of 1.2 meters seems reasonable.
//llPushObject physics experiment
float dist=0.125; //distance of llPushObject from center of avatar
default
{
touch_start(integer num)
{
key AV = llDetectedKey(0); //assume I’m the only one
vector pos = llDetectedPos(0);
llSetPos(pos+<-dist,0.0,0.0>;); //position near avatar
float energ=llGetEnergy(); //energy before
llPushObject(AV,<10.0,0.0,10.0>,<0.0,0.0,0.0>,FALSE);
energ = energ-llGetEnergy(); //change in energy
llSleep(2.0); //wait for avatar to move
//find distance avatar moved
list a = llGetObjectDetails(AV, ([OBJECT_POS]));
float dist = llVecDist(pos,llList2Vector(a,0));
llOwnerSay("e="+(string)energ+" "+(string)dist);
}
}
The first thing I noticed was when the distance between pusher and pushee was 0, the effect was different depending on what direction the avatar was facing. Face with the push and the avatar moves 1.2 meters. Face directly into the push and the avatar moves 0.60 meters IN THE WRONG DIRECTION. Yes, the avatar moved in the –x direction when I pushed in the +x direction. This went away when the distance was greater than zero, but I did all the rest of the tests with the avatar looking down the +x axis. (There is another physics experiment to do: Find out how to compensate the impulse or position to make this problem stop).

So if your pusher is very close to the pushee, it does look like llPushObject does something physical like llApplyImpulse. (See the table of results at the end). But what happens if you are farther away? The energy use goes up so eventually you run out and llPushObject stops behaving in a predictable physical way. But how far away?

I tried moving the pusher 1 meter away and the energy usage went from reasonable to completely crazy. Even at 0.5 meters a single push used up all the energy in a small prim. At 0.0 meters the exact same push used only 3% of the prim’s energy. When you run out of energy the distance pushed becomes less than what I predicted so llPushObject is totally useless from any distance over around 0.3 meters. Also at these burn rates you cannot push more than one object before you have to rest and recuperate. I wanted to push multiple avatars and objects so I’m SOL. Since llPushObject does something weird to avatars at a distance of 0.0 meters it is practically useless there as well. I’ve read some people keep a phantom invisible object around, move it to the center of the avatar and push from there. But since llSetPos has a 0.2 second delay, I cannot push a collection of avatars in a reasonable time frame this way so that trick is useless for me.

Useless, useless useless. Fix it, throw it out, or give us a new function that does something useful. OK, if you are pushing from a more massive prim the energy usage is smaller from distances over 1 meter. I haven’t quantified that but my 10x10 meter platform is where I saw this problem and I need it to work from the center to the corners, an impossibly large distance of 7 meters away. I don’t have enough energy. OK, if you only push occasionally your energy can recover. But I wanted to push perhaps a half a dozen avatars, the energy budget runs out on the first one. OK, if you llSetPos your pusher to the center of an avatar then llPushObject works great. But llSetPos has a 0.2 second delay and all my avatars would move out of sync. There are other problems with using llPushObject on avatars: Their legs move like they are walking when they are pushed and their heads bobble, to mention just two. LlPushObject is useless for my project and I have to abandon this approach. (I’ve also tried a physical platform, but so far it runs out of energy hovering and falls to the ground. I’ve also tried a vehicle and this has other problems I’m still working on).

Here are the results of my llPushObject physics experiment. The rise in energy is reasonably linear, perhaps with an r^3 curve in it but not really enough to be sure of given the noisiness of the results. Then at a distance of around 0.5 meters it clamps the energy and decreases the distance moved, invalidating my experiment.
Dist Energy
Pusher- Use
Pushee percent
0.0000 3%
0.1250 16%
0.1875 23%
0.2500 35%
0.3750 62%
0.4000 70%
0.4500 82%
0.5000 >100%
Atom Burma
Registered User
Join date: 30 May 2006
Posts: 685
11-22-2008 01:44
also don't discount the prim surface type either, be it wood, glass, metal, they all have different variables, especially when set to physical, for instance metal weighs more than wood, and glass has far less friction over wood, its only an option for unlinked prims, but don't skip that step.
Seifert Surface
Mathematician
Join date: 14 Jun 2005
Posts: 912
11-22-2008 12:29
llPushObject is currently somewhat broken as of Havok 4, although apparently it's on the list of things to get fixed. A few things:

Avatars, but not prims, currently have some sort of air resistance drag on their freefall motion. Prims fall in parabolas, avatars do not.

The interaction of a push with friction against the ground or some other surface is really unpredictable. Likewise how much energy is used.

I've only worked with llVolumeDetect prims that push you when you hit them. In these circumstances, when the pushee is very close to the pusher (intersecting with it), the push (often) seems to be what you want it to be (no r^3 term needed).

Lots of related jira entries about this here and related: http://jira.secondlife.com/browse/SVC-1179
_____________________
-Seifert Surface
2G!tGLf 2nLt9cG
Kayaker Magic
low carbonated footprint
Join date: 11 Sep 2008
Posts: 109
what I learned about llPushObject
11-25-2008 11:26
Well, if you restrict yourself to applications where you have time to move the pusher prim to the center of the pushee prim before you push, then llPushObject works very predictably and inexpensively.

In my physics experiment, I tried several different sized pusher prims to see what effect the mass of the pusher has. It has no effect on llPushObject at all when the distance between pusher and pushee is 0! The smallest pusher prim I made pushed the largest pushee prim with the same small loss of energy! If you move away from a distance of 0 then the energy use goes up. If you move too far away the amount of energy exceeds the amount you have and the push that you get becomes attenuated. But until this attenuation kicks in the effect on the pushee is the same, only the energy consumption goes up.

To push any physical object who’s MASS you know to SPEED meters per second in DIRECTION (a unit vector), you would write:

llPushObject(KEY,SPEED*MASS*DIRECTION, <0.0,0.0,0.0>,FALSE);

If you first moved the pusher to the center of the pushee, the amount of energy used (as reported by llGetEnergy()) will be: MASS*0.0007, a very reasonable amount.

Here is the complete script I used to calculate the energy usage:

//put this in a small phantom prim
//Click on it and it will move to the center (with a dist offset)
//of each nearby physical prim and toss it at speed meters/second
float dist=0.0; //distance of llPushObject from center of object
float speed=10.0; //velocity in m/s
vector direct=<1.0,0.0,1.0>; //vector direction (45 degrees up from the X axis)
//yeah, that isn't a unit vector, but I'm measuring speed in the x direction only
default
{
touch_start(integer num)
{
llSensor("","",PASSIVE,4,PI);
}

sensor (integer num)
{
integer i;
for (i=0;i<num;i++)
{
key KY = llDetectedKey(i);
float mass=llGetObjectMass(KY);
vector pos = llDetectedPos(i);
while (llGetEnergy()<0.9)
llSleep(1.0); //wait for energy to recover
llSetPos(pos-<dist,0.0,0.0>;); //position near object
float energ=llGetEnergy();
llPushObject(KY,speed*mass*direct,<0.0,0.0,0.0>,FALSE);
energ = energ-llGetEnergy(); //change in energy
llSleep(1.0); //wait for object to fly
//find distance object moved in 1 sec
list a = llGetObjectDetails(KY, ([OBJECT_POS]));
vector pos2=llList2Vector(a,0);
float dist = pos2.x - pos.x; //should equal speed
llOwnerSay((string)energ+" "+(string)dist+" "+(string)llGetMass()+" "+(string)mass);
}
}
}