AI Agent Control         Seek and Flee using a physics engine

Programming Game AI by Example - Resource Page

ai-junkie

Seek and Flee

Using a physics engine

Author:' Van'

Discussion: Computing course correction (steering)

Discussion: Solving for rotation difference with quaternions

Also see: Ogre wiki on Newton Game Dynamics

We use the newton physics engine. We utilize the same input controls that humans use. We use a scalar, -1.0 to +1.0 for torque and 0.0 to +1.0 for thrust, to determine how much of the "engine controls" to apply into the physics engine. Therefore it doesn't matter if the the input is keyboard, mouse, joystick or computed (i.e. AI) the input to our physics system is always a scalar that represents the amount power/torque to apply. For example:

void SetThrust(float Scalar)
{
  float mMaxEngineThrust = 400.00; 
  float mThrustToUse = mScalar * mMaxEngineThrust;
  ..// make call to physics engine
} // SetThrust


Here are the Seek() and Flee() functions. These functions solve for a torque scalar.

//------------------------------- Seek -----------------------------------
//
//  Given a target, this behavior returns a steering force which will
//  direct the agent towards the target
//------------------------------------------------------------------------
void Seek(Ogre::Vector3 TargetPosition, Ogre::Quaternion TargetOrientation)
{
    Ogre::Vector3 mAgentPosition        = mGlobalResource->LocalPlayerObjectScene->getInventoryPosition();
    Ogre::Quaternion mAgentOrientation    = mGlobalResource->LocalPlayerObjectScene->getInventoryOrientation();
    Ogre::Vector3 mVectorToTarget        = TargetPosition - mAgentPosition; // A-B = B->A
    mAgentPosition.normalise();
    mAgentOrientation.normalise();

    Ogre::Vector3 mAgentHeading        = mAgentOrientation * mAgentPosition;
    Ogre::Vector3 mTargetHeading        = TargetOrientation * TargetPosition;
    mAgentHeading.normalise();
    mTargetHeading.normalise();

    // Orientation control - Ogre::Vector3::UNIT_Y is common up vector.
    Ogre::Vector3 mAgentVO        = mAgentOrientation.Inverse() * Ogre::Vector3::UNIT_Y;
    Ogre::Vector3 mTargetVO        = TargetOrientation * Ogre::Vector3::UNIT_Y;

    // Compute new torque scalar (-1.0 to 1.0) based on heading vector to target.
    Ogre::Vector3 mSteeringForce = mAgentOrientation.Inverse() * mVectorToTarget;
    mSteeringForce.normalise();

    float mYaw    = mSteeringForce.x;
    float mPitch    = mSteeringForce.y;
    float mRoll    = mTargetVO.getRotationTo( mAgentVO ).getRoll().valueRadians();

    clsSystemControls::getSingleton().setPitchControl( mPitch );
    clsSystemControls::getSingleton().setYawControl( mYaw );
    clsSystemControls::getSingleton().setRollControl( mRoll );

} // Seek

//----------------------------- Flee -------------------------------------
//
//  Does the opposite of Seek
//------------------------------------------------------------------------
void Flee(Ogre::Vector3 TargetPosition, Ogre::Quaternion TargetOrientation)
{
    Ogre::Vector3 mAgentPosition        = mGlobalResource->LocalPlayerObjectScene->getInventoryPosition();
    Ogre::Quaternion mAgentOrientation    = mGlobalResource->LocalPlayerObjectScene->getInventoryOrientation();
    Ogre::Vector3 mVectorToTarget        = TargetPosition - mAgentPosition; // A-B = B->A
    mAgentPosition.normalise();
    mAgentOrientation.normalise();

    Ogre::Vector3 mAgentHeading        = mAgentOrientation * mAgentPosition;
    Ogre::Vector3 mTargetHeading        = TargetOrientation * TargetPosition;
    mAgentHeading.normalise();
    mTargetHeading.normalise();

    // Orientation control - Ogre::Vector3::UNIT_Y is common up vector.
    Ogre::Vector3 mAgentVO        = mAgentOrientation.Inverse() * Ogre::Vector3::UNIT_Y;
    Ogre::Vector3 mTargetVO        = TargetOrientation * Ogre::Vector3::UNIT_Y;

    // Compute new torque scalar (-1.0 to 1.0) based on heading vector to target.
    Ogre::Vector3 mSteeringForce = mAgentOrientation * mVectorToTarget;
    mSteeringForce.normalise();

    float mYaw    = mSteeringForce.x;
    float mPitch    = mSteeringForce.y;
    float mRoll    = mTargetVO.getRotationTo( mAgentVO ).getRoll().valueRadians();

    clsSystemControls::getSingleton().setPitchControl( mPitch );
    clsSystemControls::getSingleton().setYawControl( mYaw );
    clsSystemControls::getSingleton().setRollControl( mRoll );

} // Flee


Alias: AI_Agent_Control