ApplyLinearImpulse - Predicting Trajectory in a zero gravity environment [Part #2]

Corona has a great article showcasing how to predict a trajectory of a physics object:

http://www.coronalabs.com/blog/2013/04/09/physics-radial-gravity-and-predicting-trajectory/

I need to expand on that code to predict applying a linear impulse each frame.

I am wondering if anyone can give me some direction on how I can simulate applying a linear impulse on the object as it travels in the air?  I have an event listener on the actual physics object that applies the linear impulse each frame.  I want to be able to predict that trajectory.

Here is my basic code: (Note this code also allows linear damping)

local function getTrajectoryPoint (startingPosition, startingVelocity, n, linearDampingVar) function clamp( val, low, high ) if (val \< low) then return low end if (val \> high) then return high end return val end local dt = 1/30 stepVelocity = { x=dt\*startingVelocity.x, y=dt\*startingVelocity.y } local stepGravity = { x=dt\*xGravity, y=dt\*yGravity } d = clamp(1.0 - dt \* linearDampingVar, 0.0, 1.0); vd = 0; ad = 0; for i = 0,n do p = math.pow(d,i+1); vd = vd + p; ad = ad + ((n-i) \* p); end return { x = startingPosition.x + vd \* stepVelocity.x + ad \* stepGravity.x, y = startingPosition.y + vd \* stepVelocity.y + ad \* stepGravity.y } end local function updatePrediction( event ) Runtime:removeEventListener("enterFrame",moving); display.remove( prediction ) prediction = display.newGroup() ; prediction.alpha = 0.5 local startingVelocity = { x=xWeight, y=yWeight } for i = 1,180 do local s = { x=160, y=480 } local trajectoryPosition = getTrajectoryPoint( s, startingVelocity, i,.3) local circ = display.newCircle( prediction, trajectoryPosition.x, trajectoryPosition.y,5 ) end end

Any suggestions on where to start?  I’ve racked my brains on this one.

The simple fact is that you will not be able to accurately predict the trajectory of an object without knowing it’s actual velocity (this is both speed and direction.) As the object is not actually moving before you either call setLinearVelocity or applyLinearImpulse you will need to forget about using any impulse function, I’m afraid. Because you need to know the velocity I heartily recommend using setLinearVelocity, so that you can calculate the trajectory before calling it.

If you were to regularly apply impulses or set the velocity at intervals, you’d have to regularly re-calculate the trajectory at each interval, so I advise against this.

I’m not sure what you want an event listener on your physics object for. What is the purpose of doing that? Are you trying to define the trajectory or path the object will travel, rather than predict it?

One comment on your code snippet: Move the clamp function outside the enclosing function or make it local.

If you could provide a clear description of what you want from your code, I might be able to help more effectively.

Thanks Horace,

I need the event listener on the physics object to simulate an object curling on an ice surface over time.   The linear impulse on the object is changed based on the velocity of the object.  I can’t think of any other way to do it in a zero-gravity environment.

I have actually successfully implemented a solution for my problem.  The trick was to simulate gravity when predicting trajectory to match the linear impulse.  It works great, but changing the mass of the physics object obviously messes things up.  As the physics object stays consistent for all objects the code works well for me.

Below is the code I ended up using… maybe someone can refine it to improve it, but it works well for me. (Note: it also supports linear damping on the physics object)

Predicting Trajectory in zero gravity (With linear damping and ApplyLinearImpulse on physics object)

-- Note: zero gravity enviroment local function clamp( val, low, high ) if (val \< low) then return low end if (val \> high) then return high end return val end local mathPower = math.pow local function getTrajectoryPoint (startingPosition, startingVelocity, n, linearDamping, dt) stepVelocity = { x=dt\*startingVelocity.x, y=dt\*startingVelocity.y } local stepGravity = { x=dt\*.2, y=dt\*0 } -- added gravity to match linear impulse d = clamp(1.0 - dt \* linearDamping, 0.0, 1.0); vd = 0; ad = 0; for i = 0,n do p = mathPower(d,i+1); vd = vd + p; ad = ad + ((n-i) \* p); end return { x = startingPosition.x + vd \* stepVelocity.x + ad \* stepGravity.x, y = startingPosition.y + vd \* stepVelocity.y + ad \* stepGravity.y } end

In this example:

LinearDamping = .3

dt = 1/30

applyLinearImpulse = .02 (I fake a gravity force of .2 to match the impulse) 

density on physics object = 5

Any suggestions for improvement would be appreciated.

Byron

The simple fact is that you will not be able to accurately predict the trajectory of an object without knowing it’s actual velocity (this is both speed and direction.) As the object is not actually moving before you either call setLinearVelocity or applyLinearImpulse you will need to forget about using any impulse function, I’m afraid. Because you need to know the velocity I heartily recommend using setLinearVelocity, so that you can calculate the trajectory before calling it.

If you were to regularly apply impulses or set the velocity at intervals, you’d have to regularly re-calculate the trajectory at each interval, so I advise against this.

I’m not sure what you want an event listener on your physics object for. What is the purpose of doing that? Are you trying to define the trajectory or path the object will travel, rather than predict it?

One comment on your code snippet: Move the clamp function outside the enclosing function or make it local.

If you could provide a clear description of what you want from your code, I might be able to help more effectively.

Thanks Horace,

I need the event listener on the physics object to simulate an object curling on an ice surface over time.   The linear impulse on the object is changed based on the velocity of the object.  I can’t think of any other way to do it in a zero-gravity environment.

I have actually successfully implemented a solution for my problem.  The trick was to simulate gravity when predicting trajectory to match the linear impulse.  It works great, but changing the mass of the physics object obviously messes things up.  As the physics object stays consistent for all objects the code works well for me.

Below is the code I ended up using… maybe someone can refine it to improve it, but it works well for me. (Note: it also supports linear damping on the physics object)

Predicting Trajectory in zero gravity (With linear damping and ApplyLinearImpulse on physics object)

-- Note: zero gravity enviroment local function clamp( val, low, high ) if (val \< low) then return low end if (val \> high) then return high end return val end local mathPower = math.pow local function getTrajectoryPoint (startingPosition, startingVelocity, n, linearDamping, dt) stepVelocity = { x=dt\*startingVelocity.x, y=dt\*startingVelocity.y } local stepGravity = { x=dt\*.2, y=dt\*0 } -- added gravity to match linear impulse d = clamp(1.0 - dt \* linearDamping, 0.0, 1.0); vd = 0; ad = 0; for i = 0,n do p = mathPower(d,i+1); vd = vd + p; ad = ad + ((n-i) \* p); end return { x = startingPosition.x + vd \* stepVelocity.x + ad \* stepGravity.x, y = startingPosition.y + vd \* stepVelocity.y + ad \* stepGravity.y } end

In this example:

LinearDamping = .3

dt = 1/30

applyLinearImpulse = .02 (I fake a gravity force of .2 to match the impulse) 

density on physics object = 5

Any suggestions for improvement would be appreciated.

Byron