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: };

    程序运行如下:

    未命名

  • 相关阅读:
    PHP实现无限极分类
    html2canvas生成并下载图片
    一次线上问题引发的过程回顾和思考,以更换两台服务器结束
    Intellij IDEA启动项目报Command line is too long. Shorten command line for XXXApplication or also for
    mq 消费消息 与发送消息传参问题
    idea 创建不了 java 文件
    Java switch 中如何使用枚举?
    Collections排序
    在idea 设置 git 的用户名
    mongodb添加字段和创建自增主键
  • 原文地址:https://www.cnblogs.com/cg_ghost/p/2288799.html
Copyright © 2011-2022 走看看