VR-Forces 4.0.4 Class Documentation
Retreat Controller

The DtRetreatController is a new class that implements the DtRetreatTask to cause an entity to retreat under user defined circumstances


Header file:

/*******************************************************************************
** Copyright (c) 2000 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
/*******************************************************************************
** $RCSfile: retreatCtrl.h,v $ $Revision: 1.2 $ $State: Exp $
*******************************************************************************/

//
//class DtRetreatController
//
//The retreating behavior of this controller was not intended to be
//intelligent; it is meant to be an example of a controller invoked by a 
//DtUserTask. Because the currentTarget is used to determine which way to
//flee, the behavior is best demonstrated tank vs. tank. Vehicles which do not 
//target other vehicles, such as utility vehicles, will simply flee towards 
//their current heading. Tanks will not flee from entities which they do
//not target, such as helicopters.
//
//The retreat DtUserTask takes one argument from the "Argument 1" box
//of the DtUserTask dialog. If it is set to "hold ground", entities set to
//retreat will not start moving untill their underFire flag is set.
//
//To enable an entity to retreat, there must be an entry for
//"retreat-controller" in its controller list in the object parameters
//database. The following sample can be used:
//
//       (controllers
//          ...
//          (retreat
//             (component-descriptor-type "component-descriptor")
//             (component-type  "retreat-controller")
//          )
//           ...
//       )
//
//     (connections
//        ....
//        (connect retreat:automotive-control powertrain:automotive-control)
//        ...
//     )
//

#include "vrfobjcore/singleTaskControllerComponent.h"
#include "vrfmodel/gndAutoCntlr.h"

//String which uniquely identifies this controller
const char TestRetreatControllerType[] = "retreat-controller";

class DtRetreatController : public DtGroundAutoControllerComponent
{
public:
   //constructor
   DtRetreatController(const DtString & name, DtVrfObject* owner, 
      DtSimManager * simManager, DtComponentDescriptor* desc = NULL,
      DtReaderWriterRegistry * parentRegistry = 0);

   //destructor
   virtual ~DtRetreatController();

   //copy constructor
   DtRetreatController(const DtRetreatController& orig);

   //assignment operator
   DtRetreatController& operator=(const DtRetreatController& orig);

   //This returns the string TestRetreatControllerType (defined above),
   //used to uniquely identify the type of component.
   virtual DtString type() const;

   //Register a callback for notification of DtUserTask tasks.
   virtual void registerTaskMsgCallbacks();

   //Callback function (registered in registerTaskMsgCallbacks()) for
   //DtRetreat task messages. Calls processRetreatTask() to actually handle
   //the task.
   static void retreatTaskCallback(DtSimMessage * msg, void * usr);

   //Callback function (registered in registerTaskMsgCallbacks()) for
   //DtUserTask messages. Calls processUserTask() to actually handle
   //the task.
   static void userTaskCallback(DtSimMessage * msg, void * usr);

   //Called by retreatTaskCallback() when a new DtRetreatTask message is
   //received.
   virtual void processRetreatTask(DtSimMessage * msg);

   //Called by userTaskCallback() when a new DtRetreatTask message is
   //received.
   virtual void processUserTask(DtSimMessage * msg);

   //Update control values
   virtual void tick();

   //This is called by the factory
   static DtSimComponent* creator(const DtString & name, DtVrfObject* owner,
      DtSimManager * simManager, DtComponentDescriptor* desc,
      DtReaderWriterRegistry * parentRegistry);

   //Determine which way to flee based on the current target
   virtual double getHeading();

   //Returns the amount of fuel left.  If no fuel left, can no longer retreat
   virtual double fuelLeft() const;

protected:
   DtReal myCurrentHeading;
   //determined by DtUserTask arg1, see above
   bool myHoldGround;
};


Implementation:

/*******************************************************************************
** Copyright (c) 2003 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
/*******************************************************************************
** $RCSfile: retreatCtrl.cxx,v $ $Revision: 1.3 $ $State: Exp $
*******************************************************************************/

//
//class DtRetreatController
//

#include "retreatCtrl.h"

#include "vrfobjcore/compTypes.h"
#include "vrfobjcore/conAnalogIOPort.h"
#include "vrfobjcore/conIntegerIOPort.h"
#include "vrfcore/exClock.h"
#include "vrfcore/simMgr.h"
#include "vrfobjcore/simRadio.h"
#include "vrftasks/taskTypes.h"
#include "vrfmsgs/taskMsg.h"
#include "vrftasks/userTask.h"
#include "retreatTask.h"
#include "vrfobjcore/outputPortGroup.h"
#include "vrfobjcore/vrfObject.h"
#include "vrfobjcore/vrfObjSR.h"
#include "vrfobjcore/vrfObjMgr.h"
#include "vrfobjcore/weaponPSR.h"

#include "vrfutil/rsrcTypes.h"
#include "vrfutil/intRsrc.h"
#include "vrfutil/realRsrc.h"
#include "vrfobjcore/gndVehSR.h"

//constructor
DtRetreatController::DtRetreatController(const DtString & name, 
   DtVrfObject* owner, DtSimManager * simManager, DtComponentDescriptor* desc,
   DtReaderWriterRegistry * parentRegistry) :
   DtGroundAutoControllerComponent(name, owner, simManager, desc, 
      parentRegistry)
{
   myHoldGround = false;
}

//destructor
DtRetreatController::~DtRetreatController()
{
}
//[The type function]
DtString DtRetreatController::type() const
{
   //Defined in retreatCtlr.h
   return TestRetreatControllerType;
}
//[The type function]

//[Registering a callback]
void DtRetreatController::registerTaskMsgCallbacks()
{
   //Register for any task messsages required by the base class
   DtSingleTaskControllerComponent::registerTaskMsgCallbacks();

   //Specify the task type, the callback function, and user data.
   addTaskProcessorCallback(DtUserTaskType, userTaskCallback, (void *) this);

   //Specify the task type, the callback function, and user data.
   addTaskProcessorCallback(DtRetreatTaskType, retreatTaskCallback, (void *) this);
}

void DtRetreatController::retreatTaskCallback(DtSimMessage * msg,
                                         void * usrData)
{
   DtRetreatController * controller = (DtRetreatController *) usrData;
   if (controller)
   {
      //Call processRetreatTask to handle the incoming retreat task message.
      controller->processRetreatTask(msg);
   }
}

void DtRetreatController::userTaskCallback(DtSimMessage * msg,
                                         void * usrData)
{
   DtRetreatController * controller = (DtRetreatController *) usrData;
   if (controller)
   {
      //Call processUserTask to handle the incoming user task message.
      controller->processUserTask(msg);
   }
}
//[Registering a callback]

//[Checking the task name]
void DtRetreatController::processRetreatTask(DtSimMessage * msg)
{
   if (msg)
   {
      //Retrieve the task from the task message.
      DtTaskMessage * tm = (DtTaskMessage *) msg;
      DtRetreatTask * retreatTask = (DtRetreatTask *) tm->task();

      //Check to see if the task is a user-defined retreat task. This
      //is the string that is matched against the User Task dialog.
      if(retreatTask->retreatKind() == "hold-ground")
      {
         myHoldGround = true;   
      };
   }
}

void DtRetreatController::processUserTask(DtSimMessage * msg)
{
   if (msg)
   {
      //Retrieve the task from the task message.
      DtTaskMessage * tm = (DtTaskMessage *) msg;
      DtUserTask * userTask = (DtUserTask *) tm->task();

      //Check to see if the task is a user-defined retreat task. This
      //is the string that is matched against the User Task dialog.
      if(userTask->userTaskName() != "retreat")
      {
         taskComplete(false);
         return;
      }
      
      //Extract parameters from arguments
      if (userTask->arg1Text() == "hold ground")
      {
         myHoldGround = true;   
      };
   }
}
//[Checking the task name]

double DtRetreatController::fuelLeft() const
{
  const DtSimResource *resource = resourceManager().lookupResource("fuel");

  if (resource)
  {
     DtString resourceType = resource->type();
     if (resourceType == DtRealResourceType)
     {
        const DtRealResource * realResource = (const DtRealResource *)resource;

        return realResource->amount();
     }

     else if (resourceType == DtIntegerResourceType)
     {
        const DtIntegerResource * intResource = (const DtIntegerResource *)resource;
        return (double) intResource->amount();
     }
  }

  //have plenty...
  return 1.0E8;
}

//calculate new control values
void DtRetreatController::tick()
{
   double dT = mySimManager->exerciseClock()->dT();

   if (tasked() && (dT > 0.0) && 
      myAutomotiveControlPortGroup->attemptToActivate())
   {
      double targetHeading = getHeading();
      double localHeading = entity()->vrfState()->localOrientation().psi();

      mySteeringPort->setValue(calculateSteering(localHeading, targetHeading));

      //if tasked to hold ground, don't start running until under fire
      if ((!myHoldGround || entity()->vrfState()->underFire()) && fuelLeft())
      {
         myThrottlePort->setValue(1.0);
         myBrakePort->setValue(0.0);
      }
      else
      {
         myThrottlePort->setValue(0.0);
         myBrakePort->setValue(1.0);
      }
   }
}

DtSimComponent* DtRetreatController::creator(const DtString& name, 
   DtVrfObject* owner, DtSimManager* simManager, DtComponentDescriptor* desc,
   DtReaderWriterRegistry* parentRegistry)
{
   return 
      new DtRetreatController(name, owner, simManager, desc, parentRegistry);
}

double DtRetreatController::getHeading()
{
   DtVector myPos;
   DtVector targetPos;
   DtVector vectorFromEntityToTarget;


   DtEntityIdentifier targetId = myLocalStateRepository->firstWeaponPSR()->
      currentTarget();
   DtVrfObject* target = 
      mySimManager->vrfObjectManager()->lookupVrfObject(targetId);

   if (target == NULL)
   {
      return myLocalStateRepository->currentHeading();
   }

   myPos = myLocalStateRepository->localPosition();
   targetPos = target->vrfState()->localPosition();

   DtVecSub(targetPos, myPos, vectorFromEntityToTarget);
   myCurrentHeading = atan2(vectorFromEntityToTarget[0], 
      vectorFromEntityToTarget[1]) + 3.14;


   return myCurrentHeading;
}


Document ID: Generated on Fri Jun 29 16:33:32 EDT 2012 from SVN revision 116588
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)