Jump to content

Using llPushObject effectively


Judy Hynes
 Share

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

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

Recommended Posts

I'm experimenting with physical objects, and in particular with stopping their motion via an external script.  It looks to me like I can use llPushObject (on push-enabled land of course) to cancel out a moving object's momentum.  In this case, I'm only concerned with physical objects that apply no force or impulse of their own; that is, they are rezzed with some initial velocity and direction and then continue on that path subject to the usual operation of physics on them.  Ideally, the sensor would detect the object, calculate the perfect impulse to apply, and stop the object dead with one call to llPushObject.

It looks to me like I could use a sensor, detect the object's current velocity, then apply an impulse that's opposite to that using llPushObject.  However, I'm not entirely sure how to get the math for the impulse vector right.  I think I would need to know the object's mass in order to calculate the impulse to apply.  In addition, the wiki entry for llPushObject says: The push impact is diminished with distance by a factor of distance cubed. So I guess I would need to take distance to into account.

This is my best guess:

    sensor(integer num_detected)
    {
		key target = llDetectedKey(0);
		vector target_vel = llDetectedVel(0);
		vector target_pos = llDetectedPos(0);
		float dist = llVecDist(llGetPos(), target_pos);
		float target_mass = ?????

		vector push_impulse = -target_vel * target_mass * llPow(dist, 3);

		llSay(0, "Apply impulse to "+llDetectedName(0)+": "+(string)push_impulse);
		llPushObject(target, push_impulse, ZERO_VECTOR, FALSE);
    }

So I don't know how to get the right mass to use (or if I'm even understanding that part correctly).  I'm also not sure if "cube of distance" thing is actually relevant and if this is the correct way to account for it.  The basic technique (without the mass term since I don't know how to get that) seems to work for relatively small, slow-moving objects.  Larger, faster-moving ones, especially those traveling fast in a straight line, don't seem to get slowed down anywhere near enough.  I guess that's due to not accounting for mass.

Any suggestions?

Edited by Judy Hynes
Link to comment
Share on other sites

You may be overthinking things.  One way to cheat to a believable stop is to apply the llPushObject to slow the object down quite a bit and then use a fast repeating sensor to monitor the distance to the target and your speed.  When you are "close enough" or your velocity has dropped "far enough", go non-physical briefly.  You'll stop on a dime.  Then you can go back to being physical again, if that's what you want to do.

Link to comment
Share on other sites

Thanks for all the suggestions everyone.

6 hours ago, animats said:

If you just want to stop a physical object, set its velocity to ZERO_VECTOR.

 

5 hours ago, Rolig Loon said:

You may be overthinking things.  One way to cheat to a believable stop is to apply the llPushObject to slow the object down quite a bit and then use a fast repeating sensor to monitor the distance to the target and your speed.  When you are "close enough" or your velocity has dropped "far enough", go non-physical briefly.  You'll stop on a dime.  Then you can go back to being physical again, if that's what you want to do.

Both these suggestions would be great, but I'm trying to affect an object from a script in a different object.  I can't use llSetVelocity or llSetStatus(STATUS_PHYSICS) in this case.

5 hours ago, KT Kingsley said:

I guess llGetObjectMass might be part of what you're after. I can't help you with the physics maths, though.

Can't believe I overlooked this.  I'll give it a shot and see if I can affect things better when I have the correct mass in the mix.

 

Link to comment
Share on other sites

Is this just general tinkering or are you trying to make something practical, like an interceptor for projectiles (from weapons)? Is there an upper/lower limit for your target's speed? The answer can change a lot for context.

Without checking, my first instinct would be to just use the inverse (vector * -1) of the target's velocity. Then account for mass if that's not enough.

Link to comment
Share on other sites

After playing around for a while, I was able to get something that mostly works.  It doesn't meet my original goal of stopping an object in one push, but this technique will whittle most moving objects down to near zero velocity over several sensor detection cycles.

    sensor(integer num_detected)
    {
		key target = llDetectedKey(0);
		string target_name = llDetectedName(0);
		vector target_vel = llDetectedVel(0);
		vector target_pos = llDetectedPos(0);
		float dist = llVecDist(llGetPos(), target_pos);
		float target_mass = llGetObjectMass(target) * 5.0;   // for some reason this works

		vector push_impulse = -target_vel * target_mass * llPow(dist, 3);

		llSay(0, "Apply impulse to "+target_name+": "+(string)push_impulse);
		llPushObject(target, push_impulse, ZERO_VECTOR, FALSE);
    }

Some points I discovered:

  • Negating the velocity does create the right vector to push against the object's current motion.
  • The scaling of the impulse for distance, llPow(dist, 3), is the most important factor.  Not using this (or making it significantly smaller) results in the object's velocity reducing by very little each time.
  • There is some scaling needed for mass, and I found that llGetObjectMass() * 5 seems to work to reliably slow down the object each time through the sensor.  Using a factor larger than 5 tends to knock the object back the other direction rather than slow it down, and lower factors tend to take too long to dampen near zero.

I don't really get why mass times 5 works well.  The wiki says llGetObjectMass returns "lindograms", which are kg*100.  So the first thing I tried was mass * 100 to convert back to kg, but that applied way too much force.  I wish I understood why the magic constant 5 ends up working well.  All I know is this slowed down objects that were small and about 7 or 8 times larger mass than the small object, so it gets me something workable.

 

  • Thanks 1
Link to comment
Share on other sites

Energy transfer has been changed at least 3x since H1 days.

The first time was to prevent near infinite transfer with llPushObject() which would allow orbiting someone to millions of meters in altitude instantly. This was done when H1 was updated to H4.

The second was to prevent inf energy transfers from being received by LSO compiled scripted objects which would crash their scripts if hit by near inf spinning physical objects or near inf llPushObject() targeting an agent, LSO complied attachment or rezzed physical LSO compiled object. This was part of the "blitzing" combat/griefing tactics.

The third was to weaken energy transfers with pushes and collisions in preparation of pathfinding. IIRC, a reduction of 90% was made.

There was also an attempt to prevent the ground for becoming "viral" where inf energy transfer cause anything colliding with it to be stuck drifting along the ground to the east. This was never fully fixed and can still be achieved in some edge cases.

Edited by Lucia Nightfire
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 885 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...