Difference between revisions of "LlApplyImpulse"

From Second Life Wiki
Jump to navigation Jump to search
(Added something to caveats.)
(Correct functional breakdown. Give expected units.)
 
(18 intermediate revisions by 7 users not shown)
Line 1: Line 1:
{{LSL_Function
{{LSL_Function
|inject-2={{LSL_Function/force|force|local=local}}{{LSL_Function/physical}}
|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_name=force
|p1_type=vector|p1_name=momentum
|p2_type=integer|p2_name=local
|p2_type=integer|p2_subtype=boolean|p2_name=local
|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.
|func_footnote=Instantaneous impulse. [[llSetForce]] has continuous push. "Instantaneous" seems to mean a one second impulse.
 
This function actually expects {{LSLP|momentum}} to be expressed in '''{{HoverText|Lindograms|Value reported by llGetMass}} * meters per second'''.
 
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=
|caveats=
*The [[llVecMag|magnitude]] of {{LSLP|force}} may be scaled back by the object's available energy.
*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 maximum magnitude of {{LSLP|force}} is 20.0 and if it exceeds that it will be scaled back.
*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 )
*Silently fails when not called from inside the root prim.
|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