libgdx / gdx-ai

Artificial Intelligence framework for games based on libGDX or not. Features: Steering Behaviors, Formation Motion, Pathfinding, Behavior Trees and Finite State Machines
Apache License 2.0
1.21k stars 243 forks source link

ReachOrientation should use control equation #16

Closed ollipekka closed 9 years ago

ollipekka commented 10 years ago

Reference: http://gamedev.stackexchange.com/questions/1885/target-tracking-when-to-accelerate-and-decelerate-a-rotating-turret

The control equation is vastly superior to the current method of deciding when to stop rotation. With high acceleration, the current method will cause oscillation, whereas the control equation one will halt in few small oscillations.

Would you like a pull request from it?

davebaol commented 10 years ago

Sure, but you'll have to take the deceleration radius (in fact is an interval) into consideration because the agent must be able to decelerate gradually (the user might not want it to stop rotating abruptly).

ollipekka commented 10 years ago

The control equation isn't required if unless there is a physics engine. I'm not sure if you have noticed, but combining LookWhereYouAreGoing and arrive produce quite undesirable results when using Box2d as the body keeps oscillating since the current angular velocity of the body isn't accounted for.

The control equation solves this and produces smooth tracking & gradual decelerations. Unfortunately according to my tests last night, it doesn't really play nicely with the smoothed rotation and high decelerationRadius as done here:

        // Use maximum rotation
        float targetRotation = actualLimiter.getMaxAngularSpeed();

        // If we are inside the slow down radius, then calculate a scaled rotation
        if (rotationSize <= decelerationRadius) targetRotation *= rotationSize / decelerationRadius;

        // The final target rotation combines
        // speed (already in the variable) and direction
        targetRotation *= rotation / rotationSize;

Fixing the control equation to account for the deceleration radius is beyond my capabilities.

However, as it stands, the behaviors producing angular acceleration are unusable with Box2d setTorque or similar physics engine functions unless some kind of method to account for the current angular velocity is implemented. Manipulating angular velocity outside of the physics simulation causes instability and may send objects flying abruptly on collision so doing that is not really recommended. This reduces the usefulness of the library with physics engines.

We probably need to create new set of behaviors that account for angular velocity or make ReachOrientation injectable. Any ideas how we could serve both physics engine & non-physics engine needs the same time?

davebaol commented 10 years ago

Current angular velocity is taken into account, see https://github.com/libgdx/gdx-ai/blob/master/gdx-ai/src/com/badlogic/gdx/ai/steer/behaviors/ReachOrientation.java#L101 I think you should "simply" try to tweak parameters more carefully. Usually you can limit oscillation by using an angular acceleration that is much higher than the angular speed. Also a deceleration radius near to PI might help. Please, experiment with the box2d Face test in order to understand how parameters value affects the final behavior. You can even change scene2d slider min/max/step values in code. Unfortunately, with steering behaviors manual tweaking in something you can't avoid. Sometimes you have to spend more time with tweaking than coding.

ollipekka commented 10 years ago

What does that line exactly do?

If it was properly taking into account the current angular acceleration, velocity and torque of the body, it'd be stopping without oscillation. This probably happens in a non-rigid body simulation. The reason why the face test works is that it is is trivial. A much better test would be where a turret tracks a target and fires at it, so that the turning properties of the turret and the speed of the target are configurable variables.

In current implementation, the turret is able to hit the target when both target and the turret are configured just right whereas with physics / control equation based solution the results will be predictable, turret fires more accurate and you are actually able to use sane values for angular acceleration and speed.

Essentially, the difference comes down to configuring A turret vs configuring multiple turrets that gradually get better and can engage faster targets.

Take a look at here: http://stackoverflow.com/questions/2617476/physics-game-programming-box2d-orientating-a-turret-like-object-using-torques

As you are suggesting it kludging it to work is certainly doable with the current Face / ReachOrientation implementations, but it isn't really an acceptable solution when these sorts of problems have actual mathematics / physics based solutions that are more precise and easier to configure.

Unless you are open to some sort of physics/mathematics based solution (either one that properly accounts for torque & angular velocity or uses a PID), I'll rather use my own implementation for these behaviors.

davebaol commented 10 years ago

In current implementation, the turret is able to hit the target when both target and the turret are configured just right whereas with physics / control equation based solution the results will be predictable, turret fires more accurate

Well, you can apply prediction to (almost) all steering behaviors. It's not something specific to your control equation, see the difference between seek an purse. I think you can add prediction to ReachOrientation#reachOrientation() quite easily.

and you are actually able to use sane values for angular acceleration and speed.

that's just because in control equation you are using multiplicative factors C0 and C1=2*sqrt(C0), I guess.

Unless you are open to some sort of physics/mathematics based solution (either one that properly accounts for torque & angular velocity or uses a PID), I'll rather use my own implementation for these behaviors.

I told you already, any PR is welcome.

PS: I've not looked into the link above. No time right now.

ollipekka commented 10 years ago

Well, you can apply prediction to (almost) all steering behaviors. It's not something specific to your >control equation, see the difference between seek an purse. I think you can add prediction to >ReachOrientation#reachOrientation() quite easily.

In this case prediction is required by torque or pid based solution as well. I am not really sure if its worth to bake it into ReachOrientation or just create a separate target adapter that does the predicting. Sometimes the prediction might not be desireable.

I'll try to see if I can do a pull request in the next few days.

davebaol commented 9 years ago

@ollipekka any progress on this?

davebaol commented 9 years ago

Closing this. PR is still welcome. :)