vrforces中防空导弹类实体运行扰动组件方法

发表于2015-08-26
评论0 755浏览

vrforces是一个不错的计算机兵力生成平台,严格来讲,是个不错的开发框架,但是里面自带的组件的运行机制离我们想达到的要求还相差甚远,所以除了要在实体构建、opd文件配置、地形生成等方面研究以外,最重要的是要学会实体三大组件(传感器、控制器和执行器)的重新编写。
    本文以一个继承于DtMissileTrackEntityController的防空导弹运动控制组件编写方法为例,抛砖引玉,给大家稍作启发。
软件版本:
Visual Studio 2010
vrforces 4.1.1
vrlink4.0.5
makRti4.2
(当然也可以用vrforces3.X VC7 或者vc8的版本,把plugin.cxxmyMissileTrackEntityController.hmyMissileTrackEntityController.cxx插入到工程中,头文件的包含目录要改变一下,可参考具体版本的自带例子)
      背景:vrforces中地面实体发射防空导弹以后,地面实体在产生防空导弹时给导弹赋予一个打击的任务,防空导弹会直接飞向目标(可能是一个要打击的点、也可以是一个实体),这个我们实际的装备运行不一样,所以,需要重写其控制器,使得运行轨迹有一定的扰动误差,使得弹道不是平滑的直线(曲线)。本例不是真实的弹道扰动,只是软件编写方法的思路,大家可按此方法填写自己的真实算法。
废话少说,直接上代码,具体解释都在注释里面了:
1myMissileTrackEntityController.h
#pragma once
#include "vrfmodel/msslTrkEntCtl.h"
//
//模拟防空导弹的螺旋式飞行扰动,代替vrforces自带的直线飞向目标的模式
//

class MyMissileTrackEntityController : public DtMissileTrackEntityController
{
public:
   //构造函数
   MyMissileTrackEntityController(const DtString& name, DtVrfObject* object,
      DtSimManager* simManager, DtComponentDescriptor* compDescriptor,
      DtReaderWriterRegistry* parentRegistry = 0);
   //虚构函数
   virtual ~MyMissileTrackEntityController();
   //返回compTypes.h中的字符串,标示组件类型
   virtual DtString type() const;

   //调用父类函数,得到实际的打击目标位置,然后在其基础之上添加扰动的偏移量
   virtual bool setupControlPoint();
public:
   //创建函数
   static DtSimComponent* creator(const DtString& name, DtVrfObject* object,
      DtSimManager* simManager, DtComponentDescriptor* compDescriptor,
      DtReaderWriterRegistry* parentRegistry);
public:
//当前的偏移量(弹体自身坐标系),将会添加到 setupControlPoint()
   DtVector myNoiseOffset;
   //每个方向的扰动距离(单位:米)
   double myNoiseOffsetDistance;
   //偏移量的当前方向  0 = 向上, 1 =向右, 2 = 向下, 3 = 向左
   int myOffsetDirection;
   //上次改变偏移量的仿真时间
   double myNoiseOffsetLastUpdateTime;
};

#pragma once
#include "vrfmodel/msslTrkEntCtl.h"
//
//模拟防空导弹的螺旋式飞行扰动,代替vrforces自带的直线飞向目标的模式
//

class MyMissileTrackEntityController : public DtMissileTrackEntityController
{
public:
   //构造函数
   MyMissileTrackEntityController(const DtString& name, DtVrfObject* object,
      DtSimManager* simManager, DtComponentDescriptor* compDescriptor,
      DtReaderWriterRegistry* parentRegistry = 0);
   //虚构函数
   virtual ~MyMissileTrackEntityController();
   //返回compTypes.h中的字符串,标示组件类型
   virtual DtString type() const;

   //调用父类函数,得到实际的打击目标位置,然后在其基础之上添加扰动的偏移量
   virtual bool setupControlPoint();
public:
   //创建函数
   static DtSimComponent* creator(const DtString& name, DtVrfObject* object,
      DtSimManager* simManager, DtComponentDescriptor* compDescriptor,
      DtReaderWriterRegistry* parentRegistry);
public:
//当前的偏移量(弹体自身坐标系),将会添加到 setupControlPoint()
   DtVector myNoiseOffset;
   //每个方向的扰动距离(单位:米)
   double myNoiseOffsetDistance;
   //偏移量的当前方向  0 = 向上, 1 =向右, 2 = 向下, 3 = 向左
   int myOffsetDirection;
   //上次改变偏移量的仿真时间
   double myNoiseOffsetLastUpdateTime;
};
2myMissileTrackEntityController.cxx
//以下为要包含的头文件
#include "myMissileTrackEntityController.h"  
#include "vrfobjcore/compTypes.h"           //组件类型头文件
#include "vrfcore/simMgr.h"                 //仿真管理器
#include "vrfcore/exClock.h"               //时间头文件
#include "vrfobjcore/gndVehSR.h"           //地面车辆实体状态机
#include "vrfobjcore/vrfObject.h"          //实体对象
#include "vrfobjcore/inputPortGroup.h"    //端口输入组头文件
#include "vrfobjcore/conAnalogIOPort.h"  
#include "gdb/terrainDb.h"                 //地形头文件
//构造函数先初始化头文件中定义的变量
MyMissileTrackEntityController::MyMissileTrackEntityController(
   const DtString& name,
   DtVrfObject* object,
   DtSimManager* simManager,
   DtComponentDescriptor* compDescriptor,
   DtReaderWriterRegistry* const parentRegistry) :
   DtMissileTrackEntityController(name, object, simManager,
      compDescriptor, parentRegistry),
   myNoiseOffset(0,0,0.0),
   myNoiseOffsetDistance(200.0),
   myNoiseOffsetLastUpdateTime(0),
   myOffsetDirection(0)
{
}
MyMissileTrackEntityController::~MyMissileTrackEntityController()
{
}
//返回组件的类型为:追踪导弹实体类型
DtString MyMissileTrackEntityController::type() const
{
   return DtMissileTrackEntityType;
}
//重载父类的设置控制点函数(即要飞向的点),这是vrf自带导弹实体机制决定的,给实体一个飞向那个点的任务,导弹就会按照一定规律飞行
//(本函数会周期性自动调用)
bool MyMissileTrackEntityController::setupControlPoint()
{
//此函数主体思想:得到从父类中当前要飞向的点,过一段时间在此基础之上赋上扰动的偏移量,使得导弹弹道改变
//如果从父类中没有得到当前控制点,不能执行后面简单算法,返回。
   if (!DtMissileTrackEntityController::setupControlPoint())
   {
      return false;
   }
   //1/4秒切换到下一个方面的偏移量(当前仿真时钟-上次更新偏离量的仿真时间>0.25)
  
   if (mySimManager->exerciseClock()->simTime() - myNoiseOffsetLastUpdateTime > .25)
   {
      myNoiseOffset = DtVector::zero();
      if (myOffsetDirection == 0)
      {
    //向上设置偏移量
         myNoiseOffset.setZ(myNoiseOffsetDistance);
      }
      else if (myOffsetDirection == 1)
      {
   //向右设置偏移量
         myNoiseOffset.setX(myNoiseOffsetDistance);
      }
      else if (myOffsetDirection == 2)
      {
    //向下设置偏移量
         myNoiseOffset.setZ(-1.0 * myNoiseOffsetDistance);
      }
      else if (myOffsetDirection == 3)
      {
    //向左设置偏移量
         myNoiseOffset.setX(-1.0 * myNoiseOffsetDistance);
      }
//偏移方面标示累加,如果等于4就回到向上
      myOffsetDirection++;
      if (myOffsetDirection > 3)
      {
         myOffsetDirection = 0;
      }
      //记下当前改变偏离量的仿真时钟
   myNoiseOffsetLastUpdateTime = mySimManager->exerciseClock()->simTime();
   //打印扰动偏移量为多少,在仿真引擎vrfsim后端能看到
      DtInfo << "Noise offset" << myNoiseOffset.string() << std::endl;
   }

   //调用矩阵计算在导弹弹体坐标系下,扰动误差的矢量,然后加到当前要打击的位置上去,最后重新设置一下新的打击位置,导弹就会朝这个新位置飞去
   DtVector targetPoint(targetPoint());
   DtVector localTargetErrorOffset;
   DtDcm body2Ref = entity()->vrfState()->localOrientationMatrix();
   DtDcmVecMul(body2Ref, myNoiseOffset, localTargetErrorOffset);
   DtVecAdd(targetPoint, localTargetErrorOffset, targetPoint);
   setTargetPoint(targetPoint);
   return true;
}
//用组件工厂机制的创建函数
DtSimComponent* MyMissileTrackEntityController::creator(const DtString& name,
   DtVrfObject* vrfObject, DtSimManager* simManager,
   DtComponentDescriptor* compDescriptor,
   DtReaderWriterRegistry* parentRegistry)
{
   return new MyMissileTrackEntityController(name, vrfObject, simManager, compDescriptor,
      parentRegistry);
}
3plugin.cxx
//插件注册文件
#include "vrfcgf/vrfPluginExtension.h"
#include "myMissileTrackEntityController.h"
#include <vrfcgf/cgf.h>
#include <vrfcgf/factoryMgr.h>
#include <vrfobjcore/compTypes.h>
extern "C" {
   DT_VRF_DLL_PLUGIN void DtPluginInformation(DtVrfPluginInformation& info)
   {
      info.pluginName = "Missile Noise";
      info.pluginVersion = "1.00";
      info.pluginCreator = "娃娃鱼";
      info.pluginCreatorEmail = "99daodan@163.com";
      info.pluginContactWebPage = "www.mak.com";
      info.pluginContactMailingAddress = "china simulation";
      info.pluginContactPhone = "QQ515826628";
   }
   DT_VRF_DLL_PLUGIN bool DtInitializeVrfPlugin(DtCgf* cgf)
   {
//此插件函数重要:通过工厂管理器、组件管理器向工厂中添加新创建的组件
    //由于本组件没有使用新的组件类型,而是使用了DtMissileTrackEntityType,所以类似于防空导弹类型的实体控制组件就会被本组件的运行顶替。
      cgf->factoryManager()->componentFactory()->addCreatorFcn(
         DtMissileTrackEntityType, MyMissileTrackEntityController::creator);
      
      return true;
   }
}
运行效果如下:


文章转自:VR虚拟社区

原文链接

著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

游戏学院公众号二维码
腾讯游戏学院
微信公众号

提供更专业的游戏知识学习平台