Physics: body falls with anti-gravity force applied

Hi everyone.
I’ve made a little phys test and discovered, that if I apply (0, 9.81) force at my 1kg phys body, it is not freezes in space as I expected, but it falls with velocity slowly decreasing. What I misunderstood or did wrong? Here is the code:



-- Gravtest

function setup()
    s=physics.body(CIRCLE, 50)
    s.mass=1
    s.x=WIDTH/2
    s.y=HEIGHT/2
end

function draw()
    background(30, 45, 124, 255)
    output.clear()
    print(s.linearVelocity.y) --just to look at how speed changes
s:applyForce(vec2(0, 9.81))
    ellipse(s.x,s.y,50)
end


Thank you.

@M_Serhio You need to multiply it by the pixelToMeterRatio which I believe is 32 by default. That should do it. Another way is to do s.gravityScale = 0.

@M_Serhio I think there’s too much of a variable difference to freeze it. Here’s an example that changes the force based on its linearVelocity. I still can’t apply the correct negative force to freeze it.


-- Gravtest

function setup()
    s=physics.body(CIRCLE, 50)
    s.mass=1
    s.x=WIDTH/2
    s.y=HEIGHT/2
end

function draw()
    background(30, 45, 124, 255)
    output.clear()
    a=s.linearVelocity  -- get downward velocity
    print(s.linearVelocity.y) --just to look at how speed changes
    s:applyForce(vec2(0,-a.y))  -- apply current velocity
    ellipse(s.x,s.y,50)
end

Is there a reason you need to freeze it instead of turning gravity off for the object?
Or if you weren’t aware that was an option it is done like so:

s.gravityScale = 0

@M_Serhio — You could also just set s.linearVelocity=vec2(0, 0) to freeze the body.

@Saturn031000 I tried you’re suggestion and it doesn’t freeze the body. The only way to freeze the body is to set the gravityScale to 0 as @Luatee suggested. But was that what @M_Serhio wanted or was he trying to come up with a constant up force value to counter the gravity force.

@dave1707 Sorry, it was untested code.

@Saturn031000 No problem. I thought it was going to work also, that’s why I tried it and was surprised that it wasn’t freezing the object.

f physics runs before you set the linear velocity to zero, it moves the 4.9 meters (how many pixels?) and then you set the velocity to zero. And if physics runs after you set the velocity to zero then it’d still move the 4.9 meters after…unless I’m totally off base, in which case please tell me

Wow! Guys, thank you very much for paying attention, really appreciate this!

@Luatee, after such a multiplication, the body flies like a rocket :slight_smile: As I understand, this Scale Factor is required to convert physics calculations which is in meter-second-newton-kilogramm to Codea coordinate system which is in pixels; so originally, we have to define forces in newton.

However, it doesn’t works as expected - at least, with built-in gravity. But there is a fairly simple way to bypass this problem.

As @Monkeyman32123 and @dave1707 mentioned, I can use gravityScale=0 to make the body not to be influenced by world gravity. And after that, I can create custom g force that simulates gravity - vec2(0, -9.81*body.mass). And it looks work fine - here is the code:

-- Gravtest v1.01

function setup()
    --antigrav control
    parameter.number("fUp", 9.5, 10, 9.81)             
  
    s=physics.body(CIRCLE, 50)
    s.mass=1
    s.x=WIDTH/2
    s.y=HEIGHT/2

   --set built-in Gravity off as it acts strange
    s.gravityScale=0                                   

    --set custom Gravity  
    gForce=vec2(0, -9.81*s.mass)                       
end

function draw()
    background(30, 45, 124, 255)
    output.clear()
    aForce=vec2(0, fUp)
    s:applyForce(gForce+aForce)
    ellipse(s.x,s.y,50)
  
    --control acceleration in m/s
    print(math.floor(s.linearVelocity.y/32) .. " m/s")
end

…but there is must be an explanation why built-in gravity acts like this. Hope that anybody from develop team will read it and say a word.

Thank everybody again.

@M_Serhio — Good job. But this is really interesting. Theoretically, this should work, right?

-- Gravtest

function setup()
    physics.pixelToMeterRatio=1
    s=physics.body(CIRCLE, 50)
    s.mass=1
    s.x=WIDTH/2
    s.y=HEIGHT/2
    physics.gravity=vec2(0, -9.81)
end

function draw()
    background(30, 45, 124, 255)
    output.clear()
    s:applyForce(vec2(0, 9.81))
    ellipse(s.x,s.y,50)
    print(string.format( "%0.5f", s.linearVelocity.y).." m/s")
end

Glad you got it all sorted out @M_Serhio. Unfortunately, I can’t take credit for saying s.gravityScale = 0 as @Luatee was actually the first one to say it (I just didn’t read all the way through his when I posted it). That said, best of luck to you on your project!

@M_Serhio Ahh maybe not then thanks for clarifying, I also forgot to include Mass so it was bound to mess up :expressionless:

I’m sure all the physics routines used by Codea have been well tested and anything we come up with that seems strange is because we’re not taking everything into account.

@Saturn031000 - theoretically - yes, but it doesn’t. It works like in the first case: body moves down with slowly decreasing velocity. Moreover, setting pix/m to 1 changes coords scale for phys bodies: to place the body in the center of the screen, I had to set x,y=12000 manually.

@dave1707 - I’m sure you’re right. Maybe the grav calculates not in draw() call, or user-defined forces converts/calculates in some different way than expected, or something else… I’ll try to write to development, maybe they make things clear.

Anyway, thank you again for paying attention, guys.

@M_Serhio - the physics engine is the third party box2D library, added into Codea (ie not developed here). If you google box2D, you may get some answers.

@Ignatz, I know. I’ve searched some examples of defining the world in b2d - and every time world gravity has been defined like vec2(0, -9.81). Moreover, as I mentioned above, if I define custom gForce like vec2(0, -9.81), it works just fine. That’s why I think that the deal in a way how Codea interacts with b2d…