Difference between revisions of "LlApplyImpulse"

From Second Life Wiki
Jump to navigation Jump to search
(Added caveats about the force vector.)
(Correct functional breakdown. Give expected units.)
 
(22 intermediate revisions by 8 users not shown)
Line 1: Line 1:
{{LSL_Function
{{LSL_Function
|inject-2={{Issues/SVC-8227}}{{LSL_Function/force|momentum|local=local}}{{LSL_Function/physical}}
|func=llApplyImpulse
|func=llApplyImpulse
|sort=ApplyImpulse
|sort=ApplyImpulse
|func_id=72|func_sleep=0.0|func_energy=10.0
|func_id=72|func_sleep=0.0|func_energy=10.0
|p1_type=vector
|p1_type=vector|p1_name=momentum
|p1_name=force
|p2_type=integer|p2_subtype=boolean|p2_name=local
|p2_type=integer
|func_footnote=Instantaneous impulse. [[llSetForce]] has continuous push. "Instantaneous" seems to mean a one second impulse.
|p2_name=local
 
|p2_hover=boolean, if TRUE, force is treated as a local directional vector instead of region directional vector.
This function actually expects {{LSLP|momentum}} to be expressed in '''{{HoverText|Lindograms|Value reported by llGetMass}} * meters per second'''.
|p2_desc=boolean, if [[TRUE]], '''force''' is treated as a [[Viewer coordinate frames#Local|local]] directional vector instead of [[Viewer coordinate frames#Region|region]] directional vector.
 
|func_footnote=Instantaneous impulse. [[llSetForce]] has continuous push. "Instantaneous" seems to mean a one second impulse, as an application of a force (in newtons) equal to the object's mass (in kg) for one second will accelerate it to a velocity of 1 (in meters per second), which appears to be what happens with this function.
See below for an example script to accelerate an object to a specific velocity. (Alternately, use [[llSetVelocity]])
|func_desc=Applies impulse to object
|func_desc=Applies impulse to object
|return_text|spec
|return_text|spec
|caveats=*Object must be physical.
|caveats=
*The force magnitude is capped at 20.000.
*Sets an initial momentum on the object applied to the center of Mass . Momentum is the mass*velocity needed to get an initial movement of velocity if the object is not affected by other forces ( such as gravity )
*The force magnitude is scaled by the object's energy.
*The [[llVecMag|magnitude]] of {{LSLP|momentum}} may be scaled back by the object's available energy. For heavy objects , the cap of momentum will be momentum = 20000 . ( and not 20 as told previously ). For fast objects , the velocity will be capped to 202 meters/second ( and so the momentum will reflect this cap )
|examples=
|examples=
<lsl>
<syntaxhighlight lang="lsl2">
//Rez an object, and drop this script in it.
//This script will apply an impulse to reach a target velocity value, regardless of object mass.
//This will launch it at the owner.
vector start;
default {
rotation startRot;
    state_entry() {
 
          list p = llGetObjectDetails(llGetOwner(), [OBJECT_POS]);
float Velocity = 13.0; //meters / second.
          if(p != []) {
 
              llSetStatus(STATUS_PHYSICS, TRUE);
default
              vector pos = llList2Vector(p, 0);
{
              vector direction = llVecNorm(pos - llGetPos());
    touch_start(integer total_number)
              llApplyImpulse(direction * 100, 0);
    {
          }
        llSay(0, "Launching!");
    }
        start = llGetPos();
        startRot = llGetRot();
        llSetStatus(STATUS_PHYSICS, TRUE);    // Make sure prim has physics enabled
        //vector targetVelo = <0,0,Velocity>*llGetMassMKS(); //Factor object mass into velocity calculation. Kg*m/s
        //vector adjVelo = targetVelo/100; //Convert targetVelo back to Lindograms (Lg), as momentum uses Lg*m/s and not Kg*m/s. (Without this, the object will ping off at 100* the speed! llGetVel will also report that instead of having an initial velocity of ~13 m/s, it will have an initial velocity of ~113 m/s).
 
        vector adjVelo = <0,0,Velocity>*llGetMass(); //Factor object mass (in Lindograms) into velocity calc. Lg*m/s. This replaces the above calculation.
 
        llApplyImpulse(adjVelo,TRUE);
        llSetTimerEvent(0.1);
    }
   
    land_collision_start(vector start)
    {
        llSetLinkPrimitiveParamsFast(LINK_ROOT,[PRIM_PHYSICS,FALSE,PRIM_POSITION,start,PRIM_ROTATION,startRot]);
        llSetTimerEvent(0);
    }
   
    timer()
    {
        llOwnerSay((string)llGetVel()); //Report velocity value back to owner.
    }
} //Jenna Huntsman
</syntaxhighlight>
 
<syntaxhighlight lang="lsl2">
// Rez an object, and drop this script in it.
// This will launch it at the owner.
 
default
{
    state_entry()
    {
        key ownerKey = llGetOwner();
        vector ownerPosition = llList2Vector(llGetObjectDetails(ownerKey, [OBJECT_POS]), 0);
 
//  if the owner is not in the sim, stop fooling around
        if (llGetAgentSize(ownerKey) == ZERO_VECTOR)
            return;
 
//  else
        llSetStatus(STATUS_PHYSICS, TRUE);
 
        vector objectPosition = llGetPos();
        vector direction = llVecNorm(ownerPosition - objectPosition);
 
        llApplyImpulse(direction * llGetMass(), 0);
    }
}
}
</lsl>
</syntaxhighlight>
Make yourself a beer can, drop this script into it, and have some target practice.
<syntaxhighlight lang="lsl2">
vector gHome;
integer gHit;
 
default
{
    collision_start(integer num)
    {
        if (!gHit)
        {
            llSetTimerEvent(15.0);
            gHome = llGetPos();
            gHit = TRUE;
        }
        llSetStatus(STATUS_PHYSICS, TRUE);
        llTriggerSound("b90ed62a-2737-b911-bb53-6b9228bbc933",1.0);
        llApplyImpulse(llGetMass()*<0,0,5.0>,TRUE);
        llApplyRotationalImpulse(llGetMass()*<llFrand(1.0),llFrand(1.0),llFrand(1.0)>,TRUE);
        llResetTime();
    }
   
    land_collision(vector where)
    {
        if (llGetTime() < 0.5)
        {
            llResetTime();
            llApplyImpulse(llGetMass()*<0,0,llFrand(1.0)>,TRUE);
            llApplyRotationalImpulse(llGetMass()*<llFrand(1.0),llFrand(1.0),llFrand(1.0)>,TRUE);
        }
    }
   
    timer()
    {
        llSetStatus(STATUS_PHYSICS,FALSE);
        gHit = FALSE;
        llSetRegionPos(gHome);  // Send the can home, even if more than 10m away
        llSetRot(ZERO_ROTATION);
        llSetTimerEvent(0.0);
    }
}
</syntaxhighlight>
<syntaxhighlight lang="lsl2">
// Useless script , just to demo that
// the parameter is a momentum not a force
// the initial velocity * mass = momentum when there are no other forces ( collisions, gravity )
// the momentum is not capped to 20
// momentum may be capped nevertheless because velocity is capped around 200 meters/second ; in this case it will be capped to 200m/s * mass
 
integer tid;
vector initPos;
vector Impulse;
default
{
    state_entry()
    {
        llSetPhysicsMaterial(GRAVITY_MULTIPLIER,0,0,0,0);
        llSetStatus(STATUS_PHANTOM, TRUE);     
        llSetStatus(STATUS_PHYSICS, TRUE);
 
 
    }
   
    touch_end(integer n)
    {
        tid=llTarget(initPos=llGetPos(),30);
        llSetStatus(STATUS_PHYSICS, TRUE);
        Impulse = llGetMass()*<0,0,25>;
        llOwnerSay(llList2Json(JSON_ARRAY, [ "Setup a Momentum=", Impulse  ]));
        llApplyImpulse( Impulse , FALSE);
    }
    moving_start()
    {
        llOwnerSay(llList2Json(JSON_ARRAY, [ "Velocity= ", llGetVel(), "Force=",llGetMass()*llGetAccel(), "Momentum=", llGetVel()*llGetMass()]));
    }
    not_at_target()
    {
        llSetTimerEvent(0.0);
        llTargetRemove(tid);
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetRegionPos(initPos);
     
    }
 
}
 
// Example of results
//  ["Setup a Momentum=","<0.000000, 0.000000, 183.181381>"]
//  [10:19] Object: ["Velocity=","<0.000000, 0.000000, 25.000002>","Force=","<0.000000, 0.000000, -0.171902>","Momentum=","<0.000000, 0.000000, 183.181396>"]
 
// And for an heavy object, the cap is 20000
//  ["Setup a Momentum=","<0.000000, 0.000000, 28244.332031>"]
//  [11:01] Object: ["Velocity=","<0.000000, 0.000000, 17.702671>","Force=","<0.000000, 0.000000, -28.363781>","Momentum=","<0.000000, 0.000000, 20000.005859>
</syntaxhighlight>
|helpers
|helpers
|also_functions=
|also_functions=
{{LSL DefineRow||[[llApplyRotationalImpulse]]|}}
{{LSL DefineRow||[[llApplyRotationalImpulse]]|}}
{{LSL DefineRow||[[llSetForce]]|Set continuous force}}
{{LSL DefineRow||[[llSetForce]]|Set continuous force}}
{{LSL DefineRow||[[llSetVelocity]]|Set instantaneous velocity. Spiritual successor to [[llApplyImpulse]]}}
{{LSL DefineRow||[[llGetMass]]|Get the mass of an object (in Lindograms)}}
{{LSL DefineRow||[[llGetMassMKS]]|Get the mass of an object (in Kilograms)}}
|notes
|notes
|deepnotes=
==== Unpredictability ====
Taken from [[Simulator User Group/Transcripts/2012.10.05]]
<blockquote>
[16:24] <font color=#440044><b>Andrew Linden</b><nowiki>: the llApplyImpulse() is even more unpredictable</nowiki></font><br>
[16:24] <font color=#440044><b>Andrew Linden</b><nowiki>: because it uses the legacy script "energy budget"</nowiki></font><br>
[16:25] <font color=#440044><b>Andrew Linden</b><nowiki>: which will attenuate the results if the scripted object doesn't have enough "energy" to execute the impulse that it wants</nowiki></font><br>
[16:25] <font color=#440044><b>Andrew Linden</b><nowiki>: also, that llApplyImpulse() has great griefing potential</nowiki></font><br>
[16:25] <font color=#440044><b>Andrew Linden</b><nowiki>: so we hobbled it a long time ago with a very high energy consumption rate</nowiki></font><br>
</blockquote>
|cat1=Physics
|cat1=Physics
|cat2=Movement
|cat2=Movement
|cat3
|cat3
|cat4
|cat4
|haiku={{Haiku|In this crazy world,|Force, momentum, energy|cease to be conserved}}
}}
}}

Latest revision as of 10:17, 8 July 2022

Summary

Function: llApplyImpulse( vector momentum, integer local );
0.0 Forced Delay
10.0 Energy

Applies impulse to object

• vector momentum
• integer local boolean, if TRUE momentum is treated as a local directional vector, if FALSE momentum is treated as a region directional vector

Instantaneous impulse. llSetForce has continuous push. "Instantaneous" seems to mean a one second impulse.

This function actually expects momentum to be expressed in Lindograms * meters per second.

See below for an example script to accelerate an object to a specific velocity. (Alternately, use llSetVelocity)

Caveats

  • Only works in physics-enabled objects.
  • Sets an initial momentum on the object applied to the center of Mass . Momentum is the mass*velocity needed to get an initial movement of velocity if the object is not affected by other forces ( such as gravity )
  • The magnitude of momentum may be scaled back by the object's available energy. For heavy objects , the cap of momentum will be momentum = 20000 . ( and not 20 as told previously ). For fast objects , the velocity will be capped to 202 meters/second ( and so the momentum will reflect this cap )

Examples

//This script will apply an impulse to reach a target velocity value, regardless of object mass.
vector start;
rotation startRot;

float Velocity = 13.0; //meters / second.

default
{
    touch_start(integer total_number)
    {
        llSay(0, "Launching!");
        start = llGetPos();
        startRot = llGetRot();
        llSetStatus(STATUS_PHYSICS, TRUE);     // Make sure prim has physics enabled
        //vector targetVelo = <0,0,Velocity>*llGetMassMKS(); //Factor object mass into velocity calculation. Kg*m/s
        //vector adjVelo = targetVelo/100; //Convert targetVelo back to Lindograms (Lg), as momentum uses Lg*m/s and not Kg*m/s. (Without this, the object will ping off at 100* the speed! llGetVel will also report that instead of having an initial velocity of ~13 m/s, it will have an initial velocity of ~113 m/s).

        vector adjVelo = <0,0,Velocity>*llGetMass(); //Factor object mass (in Lindograms) into velocity calc. Lg*m/s. This replaces the above calculation.

        llApplyImpulse(adjVelo,TRUE);
        llSetTimerEvent(0.1);
    }
    
    land_collision_start(vector start)
    {
        llSetLinkPrimitiveParamsFast(LINK_ROOT,[PRIM_PHYSICS,FALSE,PRIM_POSITION,start,PRIM_ROTATION,startRot]);
        llSetTimerEvent(0);
    }
    
    timer()
    {
        llOwnerSay((string)llGetVel()); //Report velocity value back to owner.
    }
} //Jenna Huntsman
//  Rez an object, and drop this script in it.
//  This will launch it at the owner.

default
{
    state_entry()
    {
        key ownerKey = llGetOwner();
        vector ownerPosition = llList2Vector(llGetObjectDetails(ownerKey, [OBJECT_POS]), 0);

//  if the owner is not in the sim, stop fooling around
        if (llGetAgentSize(ownerKey) == ZERO_VECTOR)
            return;

//  else
        llSetStatus(STATUS_PHYSICS, TRUE);

        vector objectPosition = llGetPos();
        vector direction = llVecNorm(ownerPosition - objectPosition);

        llApplyImpulse(direction * llGetMass(), 0);
    }
}

Make yourself a beer can, drop this script into it, and have some target practice.

vector gHome;
integer gHit;

default
{
    collision_start(integer num)
    {
        if (!gHit)
        {
            llSetTimerEvent(15.0);
            gHome = llGetPos();
            gHit = TRUE;
        }
        llSetStatus(STATUS_PHYSICS, TRUE);
        llTriggerSound("b90ed62a-2737-b911-bb53-6b9228bbc933",1.0);
        llApplyImpulse(llGetMass()*<0,0,5.0>,TRUE);
        llApplyRotationalImpulse(llGetMass()*<llFrand(1.0),llFrand(1.0),llFrand(1.0)>,TRUE);
        llResetTime();
    }
    
    land_collision(vector where)
    {
        if (llGetTime() < 0.5)
        {
            llResetTime();
            llApplyImpulse(llGetMass()*<0,0,llFrand(1.0)>,TRUE);
            llApplyRotationalImpulse(llGetMass()*<llFrand(1.0),llFrand(1.0),llFrand(1.0)>,TRUE);
        }
    }
    
    timer()
    {
        llSetStatus(STATUS_PHYSICS,FALSE);
        gHit = FALSE;
        llSetRegionPos(gHome);  // Send the can home, even if more than 10m away
        llSetRot(ZERO_ROTATION);
        llSetTimerEvent(0.0);
    }
}
// Useless script , just to demo that 
// the parameter is a momentum not a force
// the initial velocity * mass = momentum when there are no other forces ( collisions, gravity )
// the momentum is not capped to 20
// momentum may be capped nevertheless because velocity is capped around 200 meters/second ; in this case it will be capped to 200m/s * mass

 integer tid;
 vector initPos;
 vector Impulse;
default
{
    state_entry()
    {
        llSetPhysicsMaterial(GRAVITY_MULTIPLIER,0,0,0,0);
        llSetStatus(STATUS_PHANTOM, TRUE);      
        llSetStatus(STATUS_PHYSICS, TRUE);


    }
    
    touch_end(integer n)
    {
        tid=llTarget(initPos=llGetPos(),30);
        llSetStatus(STATUS_PHYSICS, TRUE);
        Impulse = llGetMass()*<0,0,25>;
         llOwnerSay(llList2Json(JSON_ARRAY, [ "Setup a Momentum=", Impulse  ]));
        llApplyImpulse( Impulse , FALSE);
    }
    moving_start()
    {
        llOwnerSay(llList2Json(JSON_ARRAY, [ "Velocity= ", llGetVel(), "Force=",llGetMass()*llGetAccel(), "Momentum=", llGetVel()*llGetMass()]));
    } 
    not_at_target()
    {
        llSetTimerEvent(0.0);
        llTargetRemove(tid);
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetRegionPos(initPos);
       
    } 

}

// Example of results
//  ["Setup a Momentum=","<0.000000, 0.000000, 183.181381>"]
//  [10:19] Object: ["Velocity=","<0.000000, 0.000000, 25.000002>","Force=","<0.000000, 0.000000, -0.171902>","Momentum=","<0.000000, 0.000000, 183.181396>"]

// And for an heavy object, the cap is 20000
//  ["Setup a Momentum=","<0.000000, 0.000000, 28244.332031>"]
//  [11:01] Object: ["Velocity=","<0.000000, 0.000000, 17.702671>","Force=","<0.000000, 0.000000, -28.363781>","Momentum=","<0.000000, 0.000000, 20000.005859>

See Also

Functions

•  llApplyRotationalImpulse
•  llSetForce Set continuous force
•  llSetVelocity Set instantaneous velocity. Spiritual successor to llApplyImpulse
•  llGetMass Get the mass of an object (in Lindograms)
•  llGetMassMKS Get the mass of an object (in Kilograms)

Deep Notes

Unpredictability

Taken from Simulator User Group/Transcripts/2012.10.05

[16:24] Andrew Linden: the llApplyImpulse() is even more unpredictable
[16:24] Andrew Linden: because it uses the legacy script "energy budget"
[16:25] Andrew Linden: which will attenuate the results if the scripted object doesn't have enough "energy" to execute the impulse that it wants
[16:25] Andrew Linden: also, that llApplyImpulse() has great griefing potential
[16:25] Andrew Linden: so we hobbled it a long time ago with a very high energy consumption rate

Signature

function void llApplyImpulse( vector momentum, integer local );

Haiku

In this crazy world,
Force, momentum, energy
cease to be conserved