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.
Any suggestions? Thanks!
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
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!
Here is a tutorial that I found a while back: http://www.habrador.com/tutorials/pid-controller/
Hope it helps!
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!!! >_<
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.
The code: I run this in fixedupdate.
Help? Thanks!