支架仿真系统的实现

mac2022-06-30  26

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

主要思想:

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

第二种思路,想用Max导出的关键帧动画来实现,每个支架有非常多的动作,十几种,每种动作与其他动作都有可能同时发生,用Max做好关键帧动画之后,导出时分段导出动画,对每个动作分别进行导出,导出后导入程序,当两个动作同时播放时发现模型裂了,如图:,纠结起原因,读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: };

 

程序运行如下:

转载于:https://www.cnblogs.com/cg_ghost/archive/2011/12/15/2288799.html

相关资源:液压支架参数化变型设计系统研究与应用
最新回复(0)