Page 1 of 2

PID controller for Box2D movement/turning

Posted: Mon Jan 05, 2015 4:39 pm
by nfey
I've been reading this very interesting article on gamedev.net

http://www.gamedev.net/page/resources/_ ... dies-r3885

It's about applying natural movement and turning to your in-game entities, using box2D as the physics engine, in order to preserve the collision detection but also have smooth movement. I found out that using :setPosition() and :setAngle() doesn't work well for collisions.

My question is: does anyone know of a PID controller implemented in lua floating around? Or will I have to translate the PID in the article above from C++ to Lua?

Re: PID controller for Box2D movement/turning

Posted: Tue Jan 06, 2015 10:05 am
by ivan
Interesting. I suppose this is somewhat related to path following.
Reynolds has a nice path following algorithm and is not too hard to port it to Lua.

"setPosition" and "setAngle" basically teleport or instantly rotate the body which makes the physics look less realistic.

Re: PID controller for Box2D movement/turning

Posted: Tue Jan 06, 2015 1:07 pm
by nfey
I would say it's even worse than less realistic. When using forces, the collision detection and, most importantly, the collision feedback work out of the box and your entities behave naturally. When using :setPosition() and :setAngle(), collision detection still works but you can teleport one entity inside another and have all sorts of weird behavior, because (I guess) the system can't calculate where your body will end up in the next frame and apply the necessary forces to deny an invalid state.
In the best case scenario, with teleporting, you need to write your own code to keep entities from glitching. In the worst case scenario, collisions will simply not work properly.

Re: PID controller for Box2D movement/turning

Posted: Tue Jan 06, 2015 2:55 pm
by ivan
True but it depends on the gameplay 'feel' you are going for.
Also note that if you override the linear of angular velocity (using SetLinearVelocity or SetAngularVelocity) of a body then the collision response will not look realistic.
Collisions modify the velocity of bodies so you rarely want to change them to a constant value.
For example:

Code: Select all

body:setLinearVelocity(-gravity) -- assuming linear damping is off
Will not only make the object freeze in the air but it will make it non-responsive to collisions.
Under the hood, forces and impulses basically add acceleration to the current velocity, something along the lines of:

Code: Select all

acceleration = force / body.mass
body.velocity = body.velocity + acceleration

Re: PID controller for Box2D movement/turning

Posted: Tue Jan 06, 2015 5:05 pm
by nfey
Well I guess the system was meant to be used by applying forces to it's bodies (i.e. applyAngularImpulse()/applyForce()/etc.) and letting it manage the outcome.

I'm looking to use this for a top-down shooter, so the gravity is basically 0; I need to figure out what the restitution is and find a way to apply forces for natural movement and turning, but no wall glitching :P. If you're wondering why use love.physics at all, it's because I'm currently using it for raycasting (bullets), point testing (mouse clicks and other tests), rotation matrix related stuff (body.getWorldPoints()) and am looking to add some physics effects like walls blowing up and people flying around in grenade blasts (although I haven't yet defined the finer details and have no idea if it's doable in 2D without investing a lot in art and FX).

And by the activity on this topic it seems I'm going to have to implement that PID in Lua myself and see how it works :D

Re: PID controller for Box2D movement/turning

Posted: Fri Sep 02, 2022 9:39 am
by togFox
I appreciate this is a 7 year old thread but it is perfectly relevant. I have a top-down 2D zero-g box2D project and I need to apply force in a way that is smooth and then hold force at a certain value before slowing reducing to zero again.

Thinking some pid algorithm might be useful - just like the op. Google provides very little. Has anyone done a pid controller before?

Re: PID controller for Box2D movement/turning

Posted: Fri Sep 02, 2022 11:42 am
by pgimeno
togFox wrote: Fri Sep 02, 2022 9:39 am I appreciate this is a 7 year old thread but it is perfectly relevant. I have a top-down 2D zero-g box2D project and I need to apply force in a way that is smooth and then hold force at a certain value before slowing reducing to zero again.

Thinking some pid algorithm might be useful - just like the op. Google provides very little. Has anyone done a pid controller before?
I've worked with PIDs in industrial PLCs and implemented Proportional control myself (the P in PID). Your description is too vague - maybe you can open a new thread with more details on what you need.

Re: PID controller for Box2D movement/turning

Posted: Fri Sep 02, 2022 6:17 pm
by zorg
From discord by Keyslam:
"Stolen from Stormworks steam community" :3

Code: Select all

function pid(p,i,d)
    return{p=p,i=i,d=d,E=0,D=0,I=0,
        run=function(s,sp,pv)
            local E,D,A
            E = sp-pv
            D = E-s.E
            A = math.abs(D-s.D)
            s.E = E
            s.D = D
            s.I = A<E and s.I +E*s.i or s.I*0.5
            return E*s.p +(A<E and s.I or 0) +D*s.d
        end
    }
end

-- example
pid1 = pid(0.01,0.0005, 0.05)
pid2 = pid(0.1,0.00001, 0.005)
function onTick()
    setpoint = input.getNumber(1)
    pv1 = input.getNumber(2)
    pv2 = input.getNumber(3)
    output.setNumber(1,pid1:run(setpoint,pv1))
    output.setNumber(2,pid2:run(setpoint,pv2))
end

Re: PID controller for Box2D movement/turning

Posted: Sat Sep 03, 2022 2:00 pm
by pgimeno
I said:
pgimeno wrote: Fri Sep 02, 2022 11:42 am Your description is too vague - maybe you can open a new thread with more details on what you need.

Since you haven't opened a new thread, let me elaborate:
togFox wrote: Fri Sep 02, 2022 9:39 am I have a top-down 2D zero-g box2D project and I need to apply force in a way that is smooth and then hold force at a certain value before slowing reducing to zero again.
I have my doubts that this is what you actually want.

Force is mass times acceleration, so for an object of constant mass, if you keep force at a constant value, you'll apply a constant acceleration, i.e. the velocity will keep growing and growing. And while the force gets slowly reduced to zero, the velocity will still keep growing until it's zero, and then it will remain at the last value (that's unless there's drag, but drag needs to be applied separately by the user in box2d in most cases).

If it's for a spaceship in space, where there's no drag, then yes, it's correct that the velocity constantly grows as the engine applies force, but typically it's an on-off situation, i.e. the engine is either on (and you accelerate) or off (and you don't accelerate). The engine may take a little bit to get to full throttle (not too realistic, but plausible if it's fast) but to me it looks quite unrealistic for it to reduce power very slowly.

Even if that's really the situation you want, I don't see any need for a PID. You just use Body:applyForce(x, y) using a unit vector for the direction, multiplied by the magnitude of the force you want to apply; so if you want it to slowly rise, you can use a timer. Just remember that Body:applyForce() applies only to the next World:update(), so you need to keep calling it while you want to apply the force. It doesn't harm if you apply it every update, using a zero vector when you don't want to apply anything.

If you want the acceleration to follow a curve rather than be a straight line, you can use several strategies, e.g. tween or damp.

Re: PID controller for Box2D movement/turning

Posted: Sun Sep 04, 2022 7:32 am
by togFox
I did some reading and realised PID is a science in itself so I paused and re-considered. Tuning specifically is a black art.

For completeness, my vessel rotates in zero-g and the player can say "turn to face east" (x-axis). Assuming the vessel is pointing north then it needs to apply enough force to reach east but then to apply counter-force at the right time so that it 'settles' in a roughly easterly facing. So, the applyforce does indeed work - but it's when to apply the counter-force and the strength of the counterforce where I thought a PID might be useful, so much so it can even return to "east" if it overshot.