zoukankan      html  css  js  c++  java
  • 支架仿真系统的实现

    耗时一个多月,完成了放顶煤、薄煤层液压支架仿真程序的编写。

    主要思想:

    偶也是菜鸟,刚开始想用骨骼动画实现,但是没有人可给帮我做机械的骨骼动画,只好放弃。

    第二种思路,想用Max导出的关键帧动画来实现,每个支架有非常多的动作,十几种,每种动作与其他动作都有可能同时发生,用Max做好关键帧动画之后,导出时分段导出动画,对每个动作分别进行导出,导出后导入程序,当两个动作同时播放时发现模型裂了,如图:2011072200023481,纠结起原因,读OgreMax导入场景的代码,发现当播放两个动作时,此时模型的每个mesh都做了两次位移、旋转、等等,肯定会裂开,同时播放几个动画,此时模型就会位移几次~~,研究了将近一周的时间,美工没有用过OgreMax,加上我是个菜鸟~~最后多方求友,不得不放弃,(如果那位网友知道如何避免这个问题,请不吝赐教)。

    最后不得不采用控制节点,使用节点动画来实现,通过一个controller来实现,因为最终模型需要通过硬件来控制,控制器与PC是通过串口进行通讯的,所以本程序共分为三个部分:

    1、通讯部分

               通过串口,不同的支架传输不同字节长度的数据,根据数据的某一位控制支架做相应的动作。在数据传输过程中使用CRC校验。

    示例代码如下:

       1: unsigned short CRC16(unsigned char * puchMsg, unsigned short usDataLen)
       2: {
       3:     unsigned char uchCRCHi = 0xFF ; /* 高CRC 字节初始化 */
       4:     unsigned char uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */
       5:     unsigned uIndex ; /* CRC 循环中的索引 */
       6:     while (usDataLen--) /* 传输消息缓冲区 */
       7:     {
       8:         uIndex = uchCRCHi ^ *(puchMsg++) ; /* 计算CRC */
       9:         uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
      10:         uchCRCLo = auchCRCLo[uIndex] ;
      11:     }
      12:     return (uchCRCHi << 8 | uchCRCLo) ;
      13: }
      14:  
      15: //构造液压支架通信命令
      16: int make_support_command(const char * buf, int cnt, std::vector<char>& result)
      17: {
      18:     result.resize(cnt+3);
      19:     result[0] = 0xaf;
      20:  
      21:     memcpy(&result[1], buf, cnt);
      22:  
      23:     unsigned short crc = CRC16((unsigned char *)&result[0], cnt+1);
      24:     result[cnt + 1] = crc >> 8;
      25:     result[cnt + 2] = crc & 0xff;
      26:  
      27:     return cnt+3;
      28: }
      29:  
      30: //CRC校验
      31: int check_support_command(const char * buf, int cnt, std::vector<char>& result)
      32: {
      33:     //if(cnt != 9)
      34:     //{
      35:     //    TRACE(_T("数据长度错误!\n"));
      36:     //    //AfxMessageBox(_T("数据长度错误!"));
      37:     //}
      38:  
      39:     unsigned short recv_crc = CRC16((unsigned char *)(buf+0), cnt-2);
      40:     unsigned short send_crc = *((unsigned char *)(buf+1 + cnt-3));
      41:     send_crc <<= 8;
      42:     send_crc |= *((unsigned char *)(buf+2 + cnt-3));
      43:     if(send_crc != recv_crc)
      44:     {
      45:         TRACE(_T("校验码错误!\n"));
      46:         //AfxMessageBox(_T("校验码错误!"));
      47:         return -1;
      48:     }
      49:  
      50:     result.resize(cnt-3);
      51:     memcpy(&result[0], buf+1, cnt-3);
      52:  
      53:     return cnt-3;
      54: }

    2、支架组装,定义部分

       此部分将支架组装,使用了一种极其笨拙的方法,将支架的各个部分使用OgreMax导出后,然后根据OgreMax导出的scene文件的坐标值,然后在程序中组装支架。定义的变量相当繁琐,有很大缺陷,当换一个支架的时候,程序的数据需要重写。就是根据支架的结构创建支架,将支架的各个部分一一组装起来。代码如下:

       1: mSupportRoot = mSManager->getRootSceneNode()->createChildSceneNode(mName);
       2:     mFulcrum     = mSupportRoot->createChildSceneNode(mName + "supportFulrum", Vector3(0, 0, 0));
       3:  
       4:     //推溜节点
       5:     mMoveSupport = mSupportRoot->createChildSceneNode(mName + "moveSupport", Vector3(-1.18005, 0.115254, 0));
       6:     Entity *e = mSManager->createEntity(mName + "moveSupport", "TSmoveSupport.mesh");
       7:     mMoveSupport->attachObject(e);
       8:  
       9:     mScraper = mMoveSupport->createChildSceneNode(mName + "scraper", Vector3(-1.03653, -0.0424172, 0));
      10:     e = mSManager->createEntity(mName + "scraper", "TSscraper.mesh");
      11:     mScraper->attachObject(e);
      12:     mScraper->setVisible(mIsShowScraper);
      13:  
      14:     //底座节点
      15:     mBase = mFulcrum->createChildSceneNode(mName + "supportBase");
      16:     e = mSManager->createEntity(mName + "base", "TSbase.mesh");
      17:     mBase->attachObject(e);
      18:     mBasePillar = mBase->createChildSceneNode(mName + "basePillar", Vector3(-1.05936, 0.141, 0));
      19:  
      20:     //抬底节点
      21:     mLiftBase = mFulcrum->createChildSceneNode(mName + "liftBase", Vector3(-1.26348, 0.30187, 0));
      22:     e = mSManager->createEntity(mName + "liftBase", "TSliftBase.mesh");
      23:     mLiftBase->attachObject(e);
      24:  
      25:     //下立柱节点
      26:     mDownPillar = mBase->createChildSceneNode(mName + "downPillar", Vector3(-1.07193, 0.538018, 0));
      27:     e = mSManager->createEntity(mName + "downPillar", "TSdownPillar.mesh");
      28:     mDownPillar->attachObject(e);
      29:     mDownPillar->setOrientation(0.989742, 0, 0, 0.142869);
      30:  
      31:     //上立柱节点
      32:     //mUpPillar = mDownPillar->createChildSceneNode(mName + "upPillar", Vector3(-0.13854,0.961672, 0));
      33:     //mUpPillar = mDownPillar->createChildSceneNode(mName + "upPillar", Vector3(0, 0.961672, 0));
      34:     mUpPillar = mDownPillar->createChildSceneNode(mName + "upPillar", Vector3(0, 1.181672, 0));
      35:     e = mSManager->createEntity(mName + "upPillar", "TSupPillar.mesh");
      36:     mUpPillar->attachObject(e);
      37:     //mUpPillar->setOrientation(0.997184, 0, 0, 0.0749965);
      38:  
      39:     //顶梁节点
      40:     mTopBeamAxis  = mUpPillar->createChildSceneNode(mName + "topBeamAxis", Vector3(0.00674, -0.00362, 0));
      41:     mTopBeamAxis->roll(Radian(Math::DegreesToRadians(-17)));
      42:     mTopBeam      = mTopBeamAxis->createChildSceneNode(mName + "topBeam");
      43:     mTopPillar    = mUpPillar->createChildSceneNode(mName + "topPillar");
      44:     //mTopBeamTrack = mTopBeamAxis->createChildSceneNode(mName + "topBeamTrack", Vector3(0.915483, -0.10226, 0));
      45:     mTopBeamTrack = mTopBeamAxis->createChildSceneNode(mName + "topBeamTrack", Vector3(/*0.915483*/0.715483, -0.10226, 0));
      46:     //e = mSManager->createEntity("TStopTarget", "ninja.mesh");
      47:     //mTopBeamTrack->attachObject(e);
      48:     //mTopBeamTrack->setScale(0.001, 0.001, 0.001);
      49:     e = mSManager->createEntity(mName + "topBeam", "TStopBeam.mesh");
      50:     mTopBeam->attachObject(e);
      51:  
      52:     //恻护节点
      53:     mSideGuard = mTopBeam->createChildSceneNode(mName + "sideGurad", Vector3(-0.00456, -0.00654, 0));
      54:     e = mSManager->createEntity(mName +"sideGuard", "TSsideGuard.mesh");
      55:     mSideGuard->attachObject(e);
      56:  
      57:     //平衡千斤顶顶梁部分
      58:     mShieldJack2Axis = mTopBeam->createChildSceneNode(mName + "shiledJack2Axis", Vector3(0.435347, -0.00176, 0));
      59:     mShieldJack2Axis->setInheritOrientation(false);
      60:     mShieldJack2 = mShieldJack2Axis->createChildSceneNode(mName + "ShieldJack1");
      61:     mShieldJack2->setOrientation(0.907374, 0, 0, 0.420324);
      62:     e = mSManager->createEntity(mName + "shieldJack2", "TSshieldJack2.mesh");
      63:     mShieldJack2->attachObject(e);
      64:  
      65:     //掩护梁节点
      66:     mShieldBeamAxis = mTopBeam->createChildSceneNode(mName + "shieldBeamAxis", Vector3(0.715483, -0.01226, 0));
      67:     mShieldBeamAxis->setOrientation(0.909066, 0, 0, -0.416652);
      68:     //mShieldBeamAxis->roll(Radian(Degree(-50)));
      69:     mShieldBeam = mShieldBeamAxis->createChildSceneNode(mName + "shieldBeam");
      70:     mShieldBeam->translate(0.35, 0.05, 0, Node::TransformSpace::TS_LOCAL);
      71:     e = mSManager->createEntity(mName + "shieldBeam", "TSshieldBeam.mesh");
      72:     mShieldBeam->attachObject(e);
      73:     //mShieldBeam->setVisible(false);
      74:  
      75:     //掩护梁恻护节点
      76:     mShieldSideGuard = mShieldBeam->createChildSceneNode(mName + "shieldSideGuard", Vector3(0, 0, -0.503772));
      77:     e = mSManager->createEntity(mName + "shieldSideGuard", "TSshieldSideGuard.mesh");
      78:     mShieldSideGuard->attachObject(e);
      79:  
      80:     //平衡千斤顶掩护梁部分节点
      81:     //mShieldJack2Axis = mShieldBeam->createChildSceneNode(mName + "shieldJack2Axis", Vector3(-0.074592, -0.184284, 0));
      82:     mShieldJack1Axis = mShieldBeam->createChildSceneNode(mName + "shieldJack1Axis", Vector3(0.1 ,-0.104284, 0));
      83:     mShieldJack1Axis->setInheritOrientation(false);
      84:     mShieldJack1 = mShieldJack1Axis->createChildSceneNode(mName + "shieldJack1");
      85:     e = mSManager->createEntity(mName + "shieldJack1", "TSshieldJack1.mesh");
      86:     mShieldJack1->attachObject(e);
      87:  
      88:  
      89:     mShieldJack2->setAutoTracking(true, mShieldJack1Axis, Vector3::NEGATIVE_UNIT_Y);
      90:     mShieldJack1->setAutoTracking(true, mShieldJack2Axis, Vector3::UNIT_Y);
      91:  
      92:     //mFrontRodTarget = mShieldBeam->createChildSceneNode(mName + "frontRodTarget", Vector3(0.0817407, -0.278777, 0));
      93:     SceneNode *mFrontTargetTo = mShieldBeam->createChildSceneNode(mName + "frontRodTargetTo", Vector3(0.3517407, -0.098777, 0));
      94:     mFrontRodTarget = mShieldBeam->createChildSceneNode(mName + "frontRodTarget", Vector3(0.0517407, -0.178777, 0));
      95:     //e = mSManager->createEntity("frontRodTarget", "ninja.mesh");
      96:     //mFrontRodTarget->attachObject(e);
      97:     //mFrontRodTarget->setScale(0.0005, 0.0005, 0.0005);
      98:     mFrontRodAxis = mBase->createChildSceneNode(mName + "frontRodAxis", Vector3(-0.579555, 0.413417, 0));
      99:     mFrontRod = mFrontRodAxis->createChildSceneNode(mName + "frontRod");
     100:     e = mSManager->createEntity(mName + "frontRod", "TSfrontRod.mesh");
     101:     mFrontRod->attachObject(e);
     102:  
     103:  
     104:     //mBackRodTarget = mShieldBeam->createChildSceneNode(mName + "backRodTarget", Vector3(0.245769, -0.543867, 0));
     105:     SceneNode *mBackRodTo = mShieldBeam->createChildSceneNode(mName + "backRodTargetTo", Vector3(0.68769, -0.05, 0));
     106:     mBackRodTarget = mShieldBeam->createChildSceneNode(mName + "backRodTarget", Vector3(0.00769, -0.05, 0));
     107:     //e = mSManager->createEntity("backRodTarget", "ninja.mesh");
     108:     //mBackRodTarget->attachObject(e);
     109:     //mBackRodTarget->setScale(0.0005, 0.0005, 0.0005);
     110:     mBackRodAxis = mBase->createChildSceneNode(mName + "backRodAxis", Vector3(-0.201678, 0.140705, 0));
     111:     mBackRod = mBackRodAxis->createChildSceneNode(mName + "backRod");
     112:     e = mSManager->createEntity(mName + "backRod", "TSbackRod.mesh");
     113:     mBackRod->attachObject(e);
     114:  
     115:     mFrontRod->setAutoTracking(true, mFrontTargetTo, Vector3::UNIT_Y);
     116:     mBackRod->setAutoTracking(true, mBackRodTo, Vector3::UNIT_Y);

    3、动画控制部分

    对于每个动作创建一个动画控制器(controller),根据动作的速度与每一帧的时间控制支架做动作,创建的动画控制器为createFrameTimePassthroughController,这样就可以使用frame time传递给控制器函数(controller function)。

    为每个动作定义一个控制器,控制其中对每个支架的各个部分进行控制。在处理多个部分联动的时候可能要稍微注意一下,需要注意各部分的关系,本程序中在液压支架进行升柱、降柱的时候进对液压支架的顶梁、掩护梁、后连杆、底座、立柱进行了一系列余弦定理的处理,保证其动作的准确性。代码如下:

       1: public:
       2:     MonitorControllerValuePtr          mTopPillarDownController;          //上立柱降柱动画控制器
       3:     MonitorControllerValuePtr          mTopPillarUpController;            //上立柱升柱动画控制器
       4:     MonitorControllerValuePtr          mDownPillarDownController;         //下立柱降柱动画控制器
       5:     MonitorControllerValuePtr          mDownPillarUpController;           //下立柱升柱动画控制器
       6:  
       7:     MonitorControllerValuePtr          mBaseFrontController;              //移架动画控制器
       8:     MonitorControllerValuePtr          mScraperPushController;            //推溜动画控制器
       9:  
      10:     MonitorControllerValuePtr          mBalancePullController;            //伸平衡动画控制器
      11:     MonitorControllerValuePtr          mBalancePushController;            //收平衡动画控制器
      12:  
      13:     MonitorControllerValuePtr          mTopAngleCalController;            //顶梁角度控制器
       1: ControllerManager &contMgr = ControllerManager::getSingleton();
       2:  
       3:     //上立柱降柱动画控制器
       4:     mTopPillarDownController = MonitorControllerValuePtr(new MovePillarDown(mUpPillar,  1.03, mSpeedPillarDown, this));
       5:     contMgr.createFrameTimePassthroughController(mTopPillarDownController);
       6:     MonitorControlDest *pController = (MonitorControlDest *)mTopPillarDownController.get();
       7:  
       8:     //上立柱升柱动画控制器
       9:     //mTopPillarUpController = MonitorControllerValuePtr(new MovePillarUp(mUpPillar, 1.49607, mSpeedPillarUp, this));
      10:     mTopPillarUpController = MonitorControllerValuePtr(new MovePillarUp(mUpPillar, 1.181672, mSpeedPillarUp, this));
      11:     contMgr.createFrameTimePassthroughController(mTopPillarUpController);
      12:  
      13:     //下立柱降柱动画控制器
      14:     mDownPillarDownController = MonitorControllerValuePtr(new MovePillarDown(mDownPillar, 0.168, mSpeedPillarDown, this));
      15:     contMgr.createFrameTimePassthroughController(mDownPillarDownController);
      16:  
      17:     //下立柱升柱动画控制器
      18:     mDownPillarUpController = MonitorControllerValuePtr(new MovePillarUp(mDownPillar, 0.538018, mSpeedPillarUp, this));
      19:     contMgr.createFrameTimePassthroughController(mDownPillarUpController);
      20:  
      21:     //伸平衡动画控制器
      22:     mBalancePullController = MonitorControllerValuePtr(new PullBalance(mShieldBeamAxis, 3.0, mSpeedBalance, this));
      23:     contMgr.createFrameTimePassthroughController(mBalancePullController);
      24:  
      25:     //收平衡动画控制器
      26:     mBalancePushController = MonitorControllerValuePtr(new PushBalance(mShieldBeamAxis, 3.0, mSpeedBalance, this));
      27:     contMgr.createFrameTimePassthroughController(mBalancePushController);
      28:  
      29:     //推流动画控制器
      30:     mScraperPushController = MonitorControllerValuePtr(new MoveScraperFront(mMoveSupport, mFulcrum, 2.0, mSpeedPush));
      31:     contMgr.createFrameTimePassthroughController(mScraperPushController);
      32:  
      33:     //移架动画控制器
      34:     mBaseFrontController = MonitorControllerValuePtr(new MoveScraperFront(mFulcrum, mMoveSupport, -1.18005, mSpeedMove));
      35:     contMgr.createFrameTimePassthroughController(mBaseFrontController);
      36:  
      37:     mTopAngleCalController = MonitorControllerValuePtr(new CalAngle(this));
      38:     contMgr.createFrameTimePassthroughController(mTopAngleCalController);

    各个控制器,控制函数定义代码:

       1: class MonitorControlDest : public Ogre::ControllerValue<Ogre::Real>
       2: {
       3: public:
       4:     MonitorControlDest() : mControlValue(0), mControlFlow(0){}
       5:  
       6:     //设置控制值
       7:     void setControlValue(Ogre::Real controlValue)
       8:     {
       9:         mControlValue = controlValue;
      10:     }
      11:  
      12:     //得到控制值
      13:     Ogre::Real getControlValue()
      14:     {
      15:         return mControlValue;
      16:     }
      17:  
      18:     //设置动画控制器
      19:     void setControlFlow(ControlFlow *pFlow)
      20:     {
      21:         mControlFlow = pFlow;
      22:     }
      23:  
      24:     //得到动画控制器
      25:     ControlFlow* getControlFlow()
      26:     {
      27:         return mControlFlow;
      28:     }
      29: protected:
      30:     Ogre::Real    mControlValue;           //控制值
      31:     ControlFlow   *mControlFlow;           //流程动画控制器
      32: };
      33:  
      34:  //收平衡动画控制器
      35: class PushBalance : public MonitorControlDest
      36: {
      37: public:
      38:     PushBalance(Ogre::SceneNode *node, Ogre::Real stopPos, Ogre::Real speed, ThinSeamSupport *support)
      39:         : mNode(node), mStopPos(stopPos), mSpeed(speed), mSupport(support)
      40:     {
      41:  
      42:     }
      43:  
      44:     //得到当前的值
      45:     virtual Ogre::Real getValue(void) const
      46:     {
      47:         if(mNode)
      48:             return mNode->getOrientation().getPitch().valueDegrees();
      49:         return 0;
      50:     }
      51:  
      52:     //设置当前值
      53:     virtual void setValue(Ogre::Real value);
      54: protected:
      55:     Ogre::SceneNode         *mNode;           //被控制对象
      56:     Ogre::Radian             mStopPos;        //停止位置
      57:     Ogre::Real               mSpeed;          //速度
      58:     ThinSeamSupport         *mSupport;        //液压支架对象
      59: };

    程序运行如下:

    未命名

  • 相关阅读:
    UOJ Contest #50: Goodbye Jihai
    Codeforces 1278F: Cards
    RS-485总线和Modbus通信协议的关系
    基于Lwip协议栈中独立模式下回调函数的使用
    C语言之链表的使用
    LAN8720A网络模块的使用问题
    C语言的多行宏定义
    C# 解决ListView控件显示数据出现闪屏的问题
    解决使用SecureCRT不能连接Ubuntu的问题
    C++ 与C# 对应的变量互转
  • 原文地址:https://www.cnblogs.com/cg_ghost/p/2288799.html
Copyright © 2011-2022 走看看