前言在工业互联网和物联网的影响下,人们对机械的管理、可视化和操作可视化提出了更高的要求。如何在一个系统中完整的展示机器的运行,机器的轨迹,或者机器的机械动作就显得尤为重要,因为这会帮助一个不懂机器的新手直观的了解机器的运行情况,可以更好的为三一重工或其他国内外重型机械企业展示或推广机械的所有可能动作。挖掘机又称挖掘机械,从近几年工程机械的发展来看,挖掘机的发展比较快,挖掘机已经成为工程建设中最重要的工程机械之一。因此,该系统实现了挖掘机的3D可视化。在传统行业中,二维视觉监控一般都是基于WebSCADA的前端技术,都是属于二维面板数据监控的一部分。数据是从后台和前端显示数据中获取的,但是对于挖掘机本身来说,挖掘机的模型,挖掘机的运动,挖掘机运行的可视化等更加醒目。因此,系统可视化了挖掘机3D模型的运动,一般包括以下几个方面:前进和后退——用户可以通过键盘wasd,或点击2D界面实现前进、后退、左右移动WASD实现挖掘机前进后退。机身旋转——用户可以使用键盘上的左右键实现机身旋转,或者点击二维界面<>实现机身旋转。BoomRotation--用户可以点击2D界面的第一个滑块部分来实现boom的旋转。ForearmRotation--用户可以点击2D界面的第二个滑块部分来实现小臂的旋转。铲斗挖掘——用户可以点击二维界面的第三个滑块部分,实现铲斗部分的旋转挖掘。挖掘机动画——用户可以点击二维界面上的铲子图标,点击后系统会依次显示挖掘机本身的几个动画。本文通过讲解挖掘机可视化场景的搭建和挖掘机机械动作代码的实现,讲解如何使用HT实现挖掘机的可视化。预览地址:基于HTML5WebGL的挖掘机3D可视化应用http://www.hightopo.com/demo/...界面效果预览挖掘机机械运动效果通过上面的gif图片,可以看到挖掘机的几个主要动作。挖掘机铲斗运动效果滑动页面上的第三个滑块控制铲斗的转动。挖掘机机身运动通过上面的gif图,我们可以看到挖掘机的前后运动和机身旋转的几个动作。场景构建这个3D场景中的所有形状都是用HT里面的walltool构建的,通过设置wall的透明属性shape3d.transparent为true并映射构建好的墙来构建类似建筑展示的效果,具体样式可以参考HT的样式手册,场景效果:从上图可以看出场景中有很多墙体建筑,所以它们有很多相似之处,比如样式和贴图都是一样的,所以在HT中,这些墙体可以通过批量操作。批量是指当前未处理情况下的墙体元素都是独立绘制的模型,所以性能会比较差,而当一批图元聚合成一个大模型进行一次性绘制时,WebGL的刷新性能会是大大改善。这是分批完成的。具体请参考HT的批处理手册。系统的二维面板部分也是通过HT向量绘制的。面板部分主要包括当前挖掘机的运行状况、工作时间、保修信息、故障信息等,并以二维的方式展示这些数据信息。面板截图:机械运动代码分析本系统中挖掘机的动作非常重要和关键。大、小臂移动时液压杆应该如何移动,铲斗移动时液压杆、转点部件、与铲斗连接的部件如何联动是重点。大部分数学知识用于机械动画中计算点和面的位置。以下是几个关键的数学知识点作为基础:在数学中,向量(也称几何向量、矢量)是指a和量的方向。它可以可视化为带有箭头的线段。系统会通过向量的叉积计算垂直于某个表面的向量,即法向量。在计算铲斗的旋转时,需要计算垂直于铲斗表面的法向量来计算点。ht.Math封装在HTMathematicalfunction中,其中的ht.Math.Vector2指的是二维向量,ht.Math.Vector3是三维向量,可以传入三个值来初始化向量,并且向量的原型有一个cross的方法来计算两个向量的法向量,比如下面的伪代码:varVector3=ht.Math.Vector3;vara=newVector3([10,10,0]);varb=newVector3([10,0,0]);varab=a.clone().cross(b);上面代码中,ab是计算法向量,a.clone是为了避免交叉操作修改a原来的内容,所以clone一个新的向量进行叉乘,下面是示意图:桶会将桶的位置和桶的所有连接点的设备转换成相对于某个节点的相对位置,比如节点A在世界上节点A的坐标是[100,100,100],有是世界上的另一个节点B,节点B的坐标是[10,10,10],那么节点A相对于节点B的相对位置就是[90,90,90],因为在计算节点的位置时bucket,此时挖掘机可能已经移动到某个点或者旋转到某个轴,所以此时不??能使用相对于世界的坐标,必须使用相对于挖掘机机体的相对坐标。为了计算,代码中提供了toLocalPostion(node,worldPosition),将世界坐标worldPosition转换为相对于node的相对坐标。代码实现如下:varMatrix4=ht.Math.Matrix4,Vector3=ht.Math.Vector3;varmat=newMatrix4().fromArray(this.getNodeMat(g3d,node)),matInverse=newMatrix4().getInverse(mat),position=newVector3(worldPosition).applyMatrix4(matInverse);返回position.toArray();该函数的返回值是相对坐标。挖掘机中需要转换的坐标是连接铲斗和小臂的两个部分。系统中使用armHinge和bucketHinge分别表示臂铰链和斗铰链。一个组件,你可以从侧面看水桶的动作。从下图可以看出,重点是计算交点P的坐标,交点P的坐标以armHinge和bucketHinge的位置为中心。armHinge和bucketHinge的长度是两个半径为圆的交点,而这两个圆的圆心在铲斗转动的过程中不断变化,因此需要通过数学计算不断计算交点的位置。下面是示意图:交点的位置从上图可以知道有两个p1和p2,程序计算由圆心1和圆心2形成的向量c2ToC1,下面是伪代码:varVector2=ht.Math.Vector2;varc2ToC1=newVector2({x:c1.x,y:c1.y}).sub(newVector2({x:c2.x,y:c2.y}));c1和c2分别是armHinge和bucketHinge的中心坐标,接下来就是计算中心2和点p1、p2组成的向量c2ToP1和c2ToP2,下面是伪代码:varVector2=ht.Math.Vector2;varc2ToP1=newVector2({x:p1.x,y:p1.y}).sub(newVector2({x:c2.x,y:c2.y}));varc2ToP2=newVector2({x:p2.x,y:p2.y}).sub(newVector2({x:c2.x,y:c2.y}));通过以上操作,我们可以得到三个向量c2ToC1,c2ToP1,c2ToP2,所以我们可以利用我上面提到的向量叉积的概念来选择p1和p2点,通过向量c2ToC1和c2ToP1,向量c2ToC1和c2ToP2叉乘的结果肯定是一个大于0另一个小于0than0.二维向量的叉乘可以直接看成是3d向量,z轴是三维向量补0,但是二维向量叉乘的结果不是向量是一个值,如果result>0,则那么a旋转到b的角度<180°,如果k<0,那么a旋转到b的角度>180°,如果k=0那么a,b向量是平行的,所以通过上面的理论知识我们可以知道结果一定是比0大1,比0小1,我们可以在程序中测一下,知道需要获取的是P1大于0的点,所以每次都可以用上面的方法来选择两个交点。下面是部分动画的bucket执行流程图:经过以上操作,我们就可以得到最终需要的点P坐标。P点坐标是铲斗与小臂连接的重要点。得到这个点之后,我们就可以使用HT提供的lookAtX函数来实现下一步的操作了。lookAtX函数的作用是让一个对象看向某个点。使用方法如下:node.lookAtX(position,'bottom');node是需要查看某个点的节点。position是要看的点的坐标,第二个参数有六个枚举值可以选择,分别是'bottom','back','front','top','right','left',thesecond第一个参数的作用是当我们需要在某个点看一个物体时,我们还需要指定该点看物体的哪一侧,所以我们需要提供第二个参数来明确。得到这个函数后,我们用bucketHinge看P点,用armHinge看P点,就可以让连接的两个设备永远面向这个点。以下是部分伪代码:bucketHinge.lookAtX(P,'front');armHinge.lookAtX(P,'底部');那么经过上面的操作,我们已经正确放置了铲斗的两个关键部件,接下来就是将液压部件正确放置在与铲斗相连的小臂上,接下来介绍如何放置节点。液压联动分析在场景中我们可以看到液压主要分为两部分,一部分是较细的白色液压杆,另一部分是较粗的黑色液压杆,白色液压杆插入黑色液压杆中杆。因此,在小臂或水桶转动过程中,我们需要保持两个节点的相对位置。通过上一步我们可以知道lookAtX的功能,所以我们在液压杆部分也使用这个功能来实现。在上一步中,我们得到了铲斗旋转过程中的关键点P,因此在铲斗旋转过程中,小臂上的液压杆也应随之变化。具体操作是改变小臂白色液压杆的位置,将其设置为上一步计算出的P点位置。当然,你需要相应地设置白色液压杆的锚点,然后让白色液压杆看着黑色液压杆,让黑色液压杆看着白色液压杆。两根液压杆相互对视,所以呈现的效果是白色液压杆在黑色液压杆内伸缩。伪代码如下:bucketWhite.p3(P);bucketWhite.lookAtX(bucketBlack.p3(),'top');bucketBlack.lookAtX(P,'底部');代码中bucketWhite节点是小臂上的白色液压杆,bucketBlack节点是小臂上的黑色液压杆。通过以上设置就可以实现拉伸动画效果,下面是液压操作示意图:同理,吊臂对机身的液压动作,以及机身与吊臂连接处的液压动作,都是采用上述方法实现的.这两部分的代码如下:rotateBoom:(rotateVal)=>{excavatorBoomNode.setRotationX(dr*rotateVal);让archorVector=[0.5-0.5,0.56-0.5,0.22-0.5];让pos=projectUtil.toWorldPosition(g3d,excavatorBoomNode,archorVector);boomWhite.lookAtX(boomBlack.p3(),'底部');boomBlack.lookAtX(pos,'top');},rotateArm:(rotateVal)=>{projectUtil.applyRelativeRotation(excavatorArmNode,excavatorBoomNode,-rotateVal);让archorVector=[0.585-0.5,0.985-0.5,0.17-0.5];让pos=projectUtil.toWorldPosition(g3d,excavatorArmNode,archorVector);armWhite.lookAtX(armBlack.p3(),'底部');armBlack.lookAtX(pos,'top');}我把两部分的运动封装成两个函数rotateBoom和rotateArm分别是动臂与机身连接处的液压运动和动臂上的液压运动。在这部分,为了准确获取视角,我使用toWorldPosition方法将相对坐标转换为世界坐标。相对坐标为黑白液压。杆的锚点坐标转换成相对于吊杆或机身的世界坐标基本运动分析挖掘机的基本运动包括前进后退和车身回转。这部分比上面的动作简单多了。在HT三维坐标系中,不断修改挖掘机本体的x、y、z坐标,即可实现挖掘机的前进后退运动。通过修改机身的y轴旋转角度,可以控制机身的旋转。当然,挖掘机车身上的其他所有部件都需要吸附在机身上。当机身旋转时,其他部件也会随之旋转,而挖掘机在前进时,挖掘机底部的履带也会相应地滚动。当然我们这里在爬虫上使用了一个爬虫贴图,修改了挖掘机前进时贴图的偏移量。轨道的滚动可以通过移动值来实现。修改偏移值的伪代码如下:node.s('shape3d.uv.offset',[x,y]);上面的x,y分别是x轴和y轴的方向可以在挖掘机前进和后退的过程中不断调整挖掘机的偏移值,以达到履带滚动的效果。具体文档请参考3D手册。在挖掘机前进和后退的过程中,我们可以同时按下wasd的四个键,并且可以一直响应按键,js中可以通过document.addEventListener('keydown',(e))来监听=>{})和document.addEventListener('keyup',(e)=>{}),但是这样每次只能执行一次需要执行的动作,所以我们可以在外部设置一个定时器来执行在按键期间需要连续执行的操作。我们可以使用一个keyMap来记录当前点击的按钮。当keydown时record为true,keyup时record为false,所以我们可以判断timer中的bool值,为true时执行相应的action,否则不执行。下面是按键代码对应的部分:letkey_pressed={65:{status:false,action:turnLeft},87:{status:false,action:goAhead},68:{status:false,action:turnRight},83:{状态:错误,行动ion:back},37:{status:false,action:bodyTurnLeft},39:{status:false,action:bodyTurnRight}};setInterval(()=>{for(letkeyinkey_pressed){让{status,action}=key_pressed[key];if(status){action();}}},50);document.addEventListener('keydown',(event)=>{letkeyCode=event.keyCode;key_pressed[keyCode]&&(key_pressed[keyCode].status=true);event.stopPropagation();},true);document.addEventListener('keyup',(event)=>{letkeyCode=event.keyCode;key_pressed[keyCode]&&(key_pressed[keyCode].status=false);event.stopPropagation();},true);从上面的代码可以看出,我在key_pressed变量中记录了对应的键和该键对应的action,在keydown和keyup时对应修改当前键状态的state值,这样就可以执行对应的action根据Interval中key_pressed变量的状态值。下面是执行流程图:HT的轻量级、自适应使得当前系统在手机端可以流畅运行,当然目前手机端和电脑端的二维图纸加载不同的图纸。2D部分只留下操作挖掘机的操作部分,其他部分相应舍弃。否则,移动端的小屏幕无法显示这么多数据。在3D场景部分,共享同一个场景,通过场景构建的部分进行批量操作,使得3D在移动端运行起来非常流畅。以下是手机端操作截图:总结物联网已经融入现代生活。通过嵌入在机械设备中的电子设备,我们可以完成机械设备的运行和性能。在系统的二维面板监控部分,将采集到的数据进行可视化展示,我们可以利用大数据和物联网技术,让每台机器通过机器。它配备有控制器、传感器和无线通信模块,并连接到一个庞大的网络。每挥动一把铲子,迈出每一步,都会形成数据痕迹。大数据准确刻画了基础设施建设开工率等情况,成为观察固定资产投资等经济变化的风向标。因此,在实现上述挖掘机动作后,与挖掘机传感器连接后,可以将挖掘机此时的真实动作通过数据传递给系统,系统会根据动作进行相应的真实操作,真正做到实现挖掘机和挖掘机。网络互联。程序运行截图:
