VR-Forces 4.1.1 Class Documentation
Turn And Move To Controller

This subclass of DtTaskControllerComponent will listen to front-end tasks and implement the subtasking mechanism for a turn and move to.


Header file:

/*******************************************************************************
** Copyright (c) 2005 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
/*******************************************************************************
** $RCSfile: turnAndMoveController.h,v $ $Revision: 1.3 $ $State: Exp $
*******************************************************************************/
#ifndef turnAndMoveController_H_
#define turnAndMoveController_H_
const char DtTurnAndMoveControllerType[] = "turn-and-move-controller";
//This example controller responds to a user task with the name "turn-and-move"
//and argument 1 specifying the name of a destination object (i.e. a waypoint).
//The task is carried out by first issuing a Turn To Heading subtask, and
//when that completes, issuing a Move To task.
//The controller registers for DtTaskCompletedReport messages from itself
//in order to find out when a subtask has completed.
{
private:
//Not Implemented.
//Not Implemented.
//Not Implemented.
public:
//\copydoc DtSimComponent(const DtString&,DtVrfObject*,DtSimManager*,
//DtComponentDescriptor*,DtReaderWriterRegistry* parentRegistry)
DtVrfObject* owner,
DtSimManager* simManager,
DtComponentDescriptor* desc = NULL,
DtReaderWriterRegistry* parentRegistry = NULL);
//Initial setup of component after creation.
virtual bool init();
//Creates the process state repository for this component.
virtual bool createPSR();
//\copydoc DtSimComponent::type()
//\return DtTurnAndMoveControllerType.
virtual DtString type() const;
//Overridden to register interest in user-task and task-completed
//radio messages.
virtual void registerTaskMsgCallbacks();
//Callback for DtUserTask. Calls the virtual processUserTask().
static void userTaskCallback(DtSimMessage * msg, void * usr);
//Starts this task.
//Looks for DtUserTasks with name of "turn-and-move" with
//the first argument being the name of the destination object.
virtual void processUserTask(DtSimMessage * msg);
//Callback for DtTaskCompletedReport.
//Calls the virtual processTaskCompleteReport().
static void taskCompleteReportCallback(DtSimMessage* msg, void* usr);
//Listens for task completed reports from the subtasks that
//are started by this task, and issues the next subtask,
//or completes the task as necessary when the reports arrive.
//Main processing for component.
virtual void tick();
protected:
//Calculates the heading to the destination and starts a
//turn to heading subtask.
virtual bool startTurningPhase();
//Starts a move to subtask.
virtual bool startMovingPhase();
//Overridden for any resource cleanup when task is cleared.
//For this example, only calls down to the base class.
virtual void clearTask();
public:
//\copydoc DtSimComponent(const DtString&,DtVrfObject*,DtSimManager*,
//DtComponentDescriptor*,DtReaderWriterRegistry* parentRegistry)
//\return New instance of this class.
static DtSimComponent * creator(const DtString& name,
DtVrfObject* owner,
DtSimManager* simManager,
DtReaderWriterRegistry* parentRegistry = 0);
protected:
{
};
//All state values for this controller are stored in a process state
//repository, so that if the scenario is saved during the execution
//of the task, it will resume correctly when the scenario is reloaded.
//See the addPSR example for more information specifically about
//using process state repositories.
};
#endif

Implementation:

/*******************************************************************************
** Copyright (c) 2005 MAK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
#include "vrfcore/simMgr.h"
DtVrfObject* owner, DtSimManager* simManager, DtComponentDescriptor* desc,
DtReaderWriterRegistry* parentRegistry) :
DtSingleTaskControllerComponent(name, owner, simManager, desc, parentRegistry),
myProcessState(0)
{
}
{
//Remove radio message callbacks.
if (myRadio)
{
}
//Remove and delete the PSR.
}
//Initial setup of component after creation.
{
//This will result in a call to registerTaskMsgCallbacks().
{
return false;
}
if (!createPSR())
{
return false;
}
return true;
}
//Creates the process state repository for this component.
//See the addPSR example for more explanation specifically on
//creating and using process state repositories.
{
//create the process state repository
DtString processSRName = DtString::nullString();
DtString processSRType = DtString::nullString();
{
}
//For backwards compatibility, when name/type aren't in descriptor
if (processSRName == DtString::nullString())
{
processSRName = "turn-and-move-psr";
}
if (processSRType == DtString::nullString())
{
}
processSRType, entity()));
{
return false;
}
return true;
}
//\copydoc DtSimComponent::type()
//\return DtTurnAndMoveControllerType.
{
}
//Overridden to register interest in user-task and task-completed
//radio messages.
{
//The top level task will be received as a DtUserTask.
//The addTaskGUI and addTaskSim examples show how to create a
//new task type for both the GUI and Sim Engine.
userTaskCallback, static_cast<void *>(this));
//Notifications of subtasks completing will be received as
//DtTaskCompletedReport messages.
taskCompleteReportCallback, static_cast<void*>(this));
}
{
static_cast<DtTurnAndMoveController*>(usr)->processUserTask(msg);
}
//This method starts off the top level task.
{
DtTaskMessage* taskMsg = static_cast<DtTaskMessage*>(msg);
if (taskMsg->task()->type() == DtUserTaskType)
{
//Only respond to user tasks specifically for this controller.
const DtUserTask* userTask = static_cast<const DtUserTask*>(taskMsg->task());
if (userTask->userTaskName() == "turn-and-move")
{
{
"Error starting turn-and-move task." << std::endl;
}
}
}
}
{
}
{
DtReportMessage * rm = static_cast<DtReportMessage*>(msg);
//We are only concerned with taskCompletedReports that come from ourself.
if ((rm->transmitterIsEchelonId() == true && rm->sender() == entity()->echelonIdString()) ||
(rm->transmitterIsEchelonId() == false && rm->sender() == entity()->objectName()))
{
DtTaskCompleteReport* report = static_cast<DtTaskCompleteReport*>(rm->report());
//No point in doing anything if we aren't currently tasked. Some other
//task could be completing.
if(tasked())
{
//Compare the subtask ID in the report with the one we started.
if (myProcessState->subtaskId() == report->subtaskId())
{
{
//Turning task has completed.
//We must manually remove the pendingSubtask ID from the list.
"Done turning." << std::endl;
//Issue the moveTo subtask to start the next phase.
}
{
//MoveTo task has completed.
//We must manually remove the pendingSubtask ID from the list.
"Done moving; Task complete." << std::endl;
//When this subtask completes, the overall task is complete,
//so call taskComplete().
}
}
}
}
}
//Main processing for component.
{
//This entire task is done by subtasks that are started inside
//callback functions in response to messaged. There is nothing
//that needs to be done inside the tick() method.
}
{
//Lookup the target object in the object manager.
DtVrfObject* destination = simManager()->vrfObjectManager()->
lookupVrfObjectByName(myProcessState->destinationName());
if (destination)
{
"Starting TURNING subtask." << std::endl;
//Calculate the heading to the destination object. This is the heading
//which we will turn to face before moving.
double desiredHeading =
headingAngleTo(entity()->vrfState()->vrfKinematicState()->localPosition(),
destination->vrfState()->vrfKinematicState()->localPosition(),
//Create a DtTurnToHeadingTask and fill in with appropriate data.
turnTask.setHeading(desiredHeading);
//sendSubTask() will issue this new task to the entity, as well as setting
//the subtask flag in the task to true. It will also create a unique
//(within this entity) ID for the subtask and add that to the pendingSubtasks
//list. The ID is returned.
int id = sendSubtask(turnTask);
//Save the ID so that we can match it up with taskCompleted reports that
//will be received later.
//Keep track internally what phase of the overall task we are currently
//executing.
return true;
}
else
{
"Could not find destination object "
<< myProcessState->destinationName() << "." << std::endl;
return false;
}
}
{
"Starting MOVING subtask." << std::endl;
DtMoveToTask moveToTask;
//Same as in startTurningPhase().
int id = sendSubtask(moveToTask);
return true;
}
{
//This is called as a result of taskComplete(), when another controller
//starts a task, or if the entity is issues a skipTask().
//If this task had any local resources that should be released
//when the task ends, that should be done here.
//Subtasks are automatically cleared by DtTaskControllerComponent::clearTask().
}
DtVrfObject* owner,
DtSimManager* simManager,
DtReaderWriterRegistry* parentRegistry)
{
return new DtTurnAndMoveController(name, owner, simManager, desc, parentRegistry);
}

Document ID: Generated on Mon Apr 8 19:24:01 EDT 2013 from SVN revision 125877
Copyright © 2005-2013 VT MÄK. All Rights Reserved (www.mak.com)