Question about applyForce and applyTorque

What is the time interval over which the force or torque is applied? Is it a fixed interval, or one physics frame, or what?

Since the change in velocity of a moving object receiving a force is a function of the amplitude of the force and the time interval over which it’s applied, one kind of needs to know

Should there be a way to specify the time? If it’s variable, is there some way to read out the time?

Thanks!

@RonJeffries I think it’s applied each frame if it is on that frame and not if it’s off. I have a program where I apply force using the touch function. As long as I’m touching the screen, force is being applied.

@RonJeffries Heres an example to show sleeping allowed and apply force. The apply force seems to work the way it should. The sleeping allowed also seems to work the way it should. The problem is the awake variable. It shows awake if it’s awake, sleeping when it’s sleeping, but it doesn’t change from sleeping to awake when it should. Run the code. Tap or hold the screen above the middle to apply an upward force. When the falling ball is allowed to rest on the fixed ball for about 2 seconds, it will sleep. Applying a force will not move it. Tap the screen below the middle and sleeping allowed is set to false, but the awake variable will still show sleeping even though tapping above the middle will apply force to move the ball.

viewer.mode=FULLSCREEN

function setup()
    fill(0,0,255)
    scene = craft.scene()
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(0, 62, 255, 255)
    skyMaterial.horizon=color(99, 255, 0, 255)
    scene.surotation=quat.eulerAngles(20,45,-30)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 60, 0, 1000)

    a=scene:entity()
    s1=a:add(craft.rigidbody,DYNAMIC)
    s1.sleepingAllowed=true
    a.position=vec3(0,20,0)
    a:add(craft.shape.sphere,1)
    a.model = craft.model.icosphere(1,2)
    a.material = craft.material(asset.builtin.Materials.Specular)
    a.material.diffuse=color(255,0,0)

    b=scene:entity()
    s2=b:add(craft.rigidbody,STATIC)
    b.position=vec3(0,-15,0)
    b:add(craft.shape.sphere,1)
    b.model = craft.model.icosphere(1,2)
    b.material = craft.material(asset.builtin.Materials.Specular)
    b.material.diffuse=color(255,0,0)
end

function draw()
    update(DeltaTime)
    scene:draw() 
    a.material.diffuse=color(255,0,0)
    if apply then
        s1:applyForce(vec3(0,20,0))
        a.material.diffuse=color(0,0,255)
    end
    if s1.awake==false then
        text("sleeping",WIDTH/2,HEIGHT/2)
    else
        text("awake",WIDTH/2,HEIGHT/2)
    end
    text("tap or hold screen to apply an up force ",WIDTH/2,HEIGHT/2+50)
end
 
function update(dt)
    scene:update(dt)
end

function touched(t)
    if t.state==BEGAN then
        if t.y<HEIGHT/4 then
            s1.sleepingAllowed=false
        else
            apply=true
        end
    end
    if t.state==ENDED then
        apply=false
    end
end

since physics is probably framed somehow, there’s some implicit time in there. to make things work on all hardware, i think knowing what the code actually does is of value.

@RonJeffries For me, I think things are working OK except the awake variable. When an object is awake, I can move it. When sleeping I can’t. I can wake it up and then move it again. The awake variable isn’t showing what it should.

The entity.add documentation says that added members will have both update() and fixedUpdate() called, with fixedUpdate() called at each update of the physics engine. Does that help?

@dave1707 yes. sometimes i get no response to an apply, as some of the vids show in my latest article.

@UberGoober i noticed that, and wonder it it might be useful for getting the impulse time. i’m like to see the physics code …

@RonJeffries Heres a demo showing some force values. It looks like a force value of 1 is equal to deltaTime. Tap the screen once to start. Each time you tap the screen, you increase the force.

viewer.mode=STANDARD

function setup()
    fill(0,0,255)
    scene = craft.scene()
    scene.physics.gravity=vec3(0,0,0)
    skyMaterial=scene.sky.material
    skyMaterial.sky=color(0, 62, 255, 255)
    skyMaterial.horizon=color(99, 255, 0, 255)
    scene.surotation=quat.eulerAngles(20,45,-30)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 60, 0, 1000)
    
    a=scene:entity()
    s1=a:add(craft.rigidbody,DYNAMIC)
    s1.sleepingAllowed=false
    a.position=vec3(0,-10,0)
    a:add(craft.shape.sphere,1)
    a.model = craft.model.icosphere(1,2)
    a.material = craft.material(asset.builtin.Materials.Specular)
    a.material.diffuse=color(255,0,0)
    cnt=0
    v=0
    force=1
end

function draw()
    update(DeltaTime)
    scene:draw() 
    cnt=cnt+v
    text("tap screen to apply an UP force ",WIDTH/2,HEIGHT-50)
    text(s1.linearVelocity.y.."  (force) units per sec",WIDTH/2,HEIGHT-100)
    text(10+a.position.y.."  units moved since force started",WIDTH/2,HEIGHT-150)
    text((cnt/60).."  seconds since force started",WIDTH/2,HEIGHT-200)
    scene.debug:line(vec3(-10,-11,0,0),vec3(10,-11,0),color(255))  
end

function update(dt)
    scene:update(dt)
end

function touched(t)
    if t.state==BEGAN then
        s1:applyForce(vec3(0,force,0))
        v=1
    end
end

interesting. if i understand your understanding :smile: the force is applied for a period delta t? except … on this ipad, on the first tap, the ball doesn’t move at all. on the second, it starts moving. the distance moved, though, is displaying some small number of pixels moved. when the ball is one ball width up, it says 1.57 pixels moved, so i don’t understand that.

and what is scene.debug?? and when i tap, the force value does not always change to be higher.

oh?? those really are pixels somehow? or whatever craft units are?

@RonJeffries if you tap once, the ball is given a force of 1 which is a value of deltaTime. If you don’t tap again, that’s it’s speed each draw cycle. If you wait long enough, it will eventually move enough to see.

Each time you tap the screen, it increases the force on the ball. So it’s speed should be x2. If you tap again, x3, etc.

If you change the code so the force is 2, you’ll get a force of 2 x deltaTime.

The scene.debug just allows me to draw a line in Craft. I drew it across the screen so you can see where the ball started and if you wait long enough, you’ll see it moving up from it.

when i tap the screen one time, it still shows 0, and the time counts but nothing else. Often, not always.

@RonJeffries Are you running at 60 or 120 FPS. Try changing the force variable to either 60 or 120. That should increase the force to 1 pixel per second.

PS. I have to look at this more. I don’t think it’s pixels per second but units per second. I’m getting confused on this between Craft physics and regular physics.

My iPads run at 120 sometimes, 60 other times. I’ve seen the speed number be 0.0083 sometimes, when it’s running at 120.

Yes, it’s not pixels, it’s Craft units per second, I’m rather sure. “Newtons” according to typical physics documentation.

Very important: it is an impulse, that is a force applied for a finite time and then turned off, not a continuous application of power that goes on forever. If it were, the object would accelerate without bound, as if propelled by a rocket.

I think your test above is quite enlightening. I’ll play with it today in an article. One thing that I want to check is the physics update cycle time, which might be the thing that controls the time, i.e. it might be that applyForce uses one physics tick rather than a draw tick.

Very useful experiment. Thanks!

@RonJeffries Heres a physics version that uses pixel instead of unit.

viewer.mode=STANDARD

function setup()
    s1=physics.body(CIRCLE,10)
    s1.x=WIDTH/2
    s1.y=100
    s1.gravityScale=0
    cnt,v=0,0
    force=1
    stroke(255)
    strokeWidth(1)
end

function draw()
    background(40,40,50)
    fill(255)
    ellipse(s1.x,s1.y,20)
    cnt=cnt+v
    text("tap screen to apply an UP force ",WIDTH/2,HEIGHT-50)
    text(s1.linearVelocity.y.."  (force) pixels per sec",WIDTH/2,HEIGHT-100)
    text((s1.position.y-100).."  pixels moved since force started",WIDTH/2,HEIGHT-150)
    text((cnt/60).."  seconds since force started",WIDTH/2,HEIGHT-200)
    line(0,90,WIDTH,90)
end

function touched(t)
    if t.state==BEGAN then
        v=1
        s1:applyForce(vec2(0,force))
    end
end

Interesting. I get a velocity of 1.738 per touch, which isn’t any kind of time that I recognize. Of course this is 2D physics. I’m not sure whether that’s the same engine or not.

And the numbers don’t add up: I’ve got a pic showing
1.738 pixels/sec, 76.68 seconds, and 100.02 total pixels moved, after one touch.

Oh. that is probably because the program assumes 1/60th. Hm, no, accumulating DeltaTime still doesn’t foot. Weird.

I sure wish we could get some facts here. It’s hard to document what seems to be action by spirits. :smile:

@RonJeffries I’m running at 60 fps and my times are

1.73839 → velocity
100.345 → pixels moved
57.72 → seconds

So velocity x seconds = pixels moved turns out to be close enough. Not sure what’s happening on your device.

Are you running at 60 or 120 fps. Can your device be varying the fps.

PS. I’m waiting to watch the Ohio State / Michigan game coming on soon. I’ll be playing with Codea while I’m watching it.

it does vary, but when i accumulate delta time it still doesn’t add up. maybe i have to use elapsed. my ipads update at 1/120 sometimes, 1/60 more often, and i think it can change in either direction, but not sure.

M Go Blue!

I have a program, which I’ll try to clean up as a real bug report if needed, that seems to be telling me these things:

  1. When `applyForce is used inside an added object’s update, it seems to have no effect at all, almost always. (But possibly sometimes.)
  2. When applyForce is used in the draw event, it has effect almost always. If scaled by 1/DeltaTime, it is about 2x what it would need to be to provide the expected change in momentum. Sometimes, however, it has no effect.

I am becoming more and more certain that something is funky with it. I suspect that what is funky has to do with the time interval over which it is applied. I further suspect that the effect is worse on faster equipment, but that’s just based on the fact that @Dave1707 's programs work on his hardware more reliably than they do on mine.

As it stands, I have not yet devised a reliable way to use the famous F = M*a equations to move things in Craft. I have not quite given up, but it’s starting to look as if I might just as well change velocity directly as try to adjust it using force.

Is this interesting enough to try to produce a simple bug report program? (I probably will anyway.)