Feedback Control Algorithm assist...

Hey geniuses :)

I'm trying to figure out how to use force to move a rigidbody to a target position. I found a feedback control algorithm, and it works pretty much how I want it to, BUT it moves slower than I would like it to.

So I tweaked all the values WAY up and it still doesn't move nearly as fast as I'd like it to.

The four variables tweak the behaviour, and they all started fairly low with the original algorithm I found. I tweaked them WAY up to try and raise the speed/adherence of the object to destination, but it just doesn't work.

public float toVel = 10000f;
	public float maxVel = 50000f;
	public float maxForce = 50000f;
	public float gain = 5000f;

	Vector3 dist = rayHit.point - PlayerShip.position;
	dist.z = 0; // ignore depth differences, my object is locked in Z
	// calc a target vel proportional to distance (clamped to maxVel)
	Vector3 tgtVel = Vector3.ClampMagnitude(toVel * dist, maxVel);
	// calculate the velocity error
	Vector3 error = tgtVel - PlayerShipRigid.velocity;
	// calc a force proportional to the error (clamped to maxForce)
	Vector3 force = Vector3.ClampMagnitude(gain * error, maxForce);
	PlayerShipRigid.AddForce(force);


Any suggestions? Thanks!

Comments

  • This is just a silly hack but maybe you could increase time scale and or fixed time step so the physics just runs faster ?
  • Control systems are notorious for being one of the most difficult subjects ever, so don't worry that it's not working (also trying to give myself some room for mistakes here ;) ).

    That looks like basic proportional control. There are numerous ways to improve it and they are not always win-win - it's mostly a trade-off. If you make it faster it'll often overshoot the target, or even oscillate around it, but for now let's just get it faster.

    Without a sense of the scale in your game it's difficult to say for sure what sensible constants would be. It's also not 100% clear that you need to be adjusting force and you can't just adjust velocity directly, but I'll assume that for now. When you say it "just doesn't work" it's difficult to know what you mean by that: does it get faster, but just not fast enough? Is there no noticeable difference? What sort of range have you tried?

    The code itself seems fine, so after those above questions, what I'd try are things like:

    1. Change it to a simple "bang-bang" control: if you're more than a certain amount away from your target, just adjust your velocity directly. You either going towards your target with max speed, or you're stationery (I'm not actually even sure if you have friction in this world?? that could be negating any control you attempt if you're at either extreme). See what is a good value for that speed (yes I know you'll have to make your object a kinematic body, which is probably not what you want, but this is just to get a reasonable baseline). You want to be pointing in the same direction as "dist" in your snippet, but with a fixed magnitude, either the max speed or zero.

    2. Use that snippet, but plot some of the value and see if you get sensible things. If you can actually plot stuff to a graph that's great, but just plonking stuff out with printf should work well enough. What stuff is happening at runtime in that function?

    3. Use the values from #2 to figure out if your body is always accelerating or it's actually achieving its desired speed. You can look at the direction of "error" to figure that out.

    Hope at lest some of that rambling is helpful. Good luck!
  • As francoisvn mentioned control systems are really complicated. I have been meaning to get a better grip on them because I know that they can be very useful (just never quite found the time). You could use what is called a PID controller (Proportional-Integral-Derivative). It is a really simple yet powerful controller that can be used quite widely.

    Here is a tutorial that I found a while back: http://www.habrador.com/tutorials/pid-controller/

    Hope it helps!
  • Omg I'm an idiot.

    The reason that adjusting those values didn't work was because they're public values and I've been changing the values in script while the inspector values didn't change.

    <insert shy monkey emoji>

    False alarm guys! The values do work and I have to hack around them!! Thanks for all your input though!!! >_<
  • Feedback Control THE SEQUEL

    So I adopted the same algorithm to do angles, and weirdly enough it works, BUT only correctly for angles between 0 - 180, over 180 it goes into some weird jitters. You can see it in the gif below - the z is the EulerAngles.z that it's basing the output from. It's the toAngle in the code below.

    image

    The code: I run this in fixedupdate.
    Vector3 diff = toAngle - fromAngle;
    		Vector3 tgtTorque = Vector3.ClampMagnitude(ftoVel * diff, fmaxVel);
    		Vector3 error = tgtTorque - targetRigid.angularVelocity;
    		Vector3 force = Vector3.ClampMagnitude(fgain * error, fmaxForce);
    		targetRigid.AddTorque(0f,0f,force.z);


    Help? Thanks!
    ZspinCut.gif
    405 x 246 - 1M
    Thanked by 1Elyaradine
  • Mostly guessing here, but you're probably not dealing with angle wrapping correctly. IOW, 180 = -180, 0 = 360, 90 = -270, etc. You just need to take that into account when looking at angles, angular velocity, etc., and you won't be able to just say "diff = toAngle - fromAngle" (you need a step afterwards that get's the angle into some known range, often (-180; 180).
    Thanked by 1Tuism
  • Jittering bug aside, that looks pretty cool. :P
    Thanked by 1Tuism
  • Jittering bug aside, that looks pretty cool. :P
    lulz thanks, it's for daydream, which is financial suicide but..... I WANNA XD
    Mostly guessing here, but you're probably not dealing with angle wrapping correctly. IOW, 180 = -180, 0 = 360, 90 = -270, etc. You just need to take that into account when looking at angles, angular velocity, etc., and you won't be able to just say "diff = toAngle - fromAngle" (you need a step afterwards that get's the angle into some known range, often (-180; 180).
    Thanks! I'll try and make sense of that, I mean it makes sense to me, but in code... Dunno. Right now I'm cheating it and just directly setting the transform instead of using force, but it'll do for now :P
Sign In or Register to comment.