前言在工业互联网和物联网的影响下,人们对机械的管理、可视化和操作可视化提出了更高的要求。如何在一个系统中完整的展示机器的运行,机器的轨迹,或者机器的机械动作就显得尤为重要,因为这会帮助一个不懂机器的新手直观的了解机器的运行情况,可以更好的为三一重工或其他国内外重型机械企业展示或推广机械的所有可能动作。挖掘机又称挖掘机械,从近几年工程机械的发展来看,挖掘机的发展比较快,挖掘机已经成为工程建设中最重要的工程机械之一。因此,该系统实现了挖掘机的3D可视化。在传统行业中,二维视觉监控一般都是基于WebSCADA的前端技术,都是属于二维面板数据监控的一部分。数据是从后台和前端显示数据中获取的,但是对于挖掘机本身来说,挖掘机的模型,挖掘机的运动,挖掘机运行的可视化等更加醒目。因此,系统可视化了挖掘机3D模型的运动,一般包括以下几个方面:前进和后退——用户可以通过键盘wasd,或点击2D界面实现前进、后退、左右移动WASD实现挖掘机前进后退。机身旋转——用户可以使用键盘上的左右键实现机身旋转,或者点击二维界面<>实现机身旋转。BoomRotation--用户可以点击2D界面的第一个滑块部分来实现boom的旋转。ForearmRotation--用户可以点击2D界面的第二个滑块部分来实现小臂的旋转。铲斗挖掘——用户可以点击二维界面的第三个滑块部分,实现铲斗部分的旋转挖掘。挖掘机动画——用户可以点击二维界面上的铲子图标,点击后系统会依次显示挖掘机本身的几个动画。本文通过讲解挖掘机可视化场景的搭建和挖掘机机械动作代码的实现,讲解如何使用HT实现挖掘机的可视化。预览地址:HTML5基于WebGL的挖掘机3D可视化应用www.hightopo.com/demo/ht-exc...界面效果预览挖掘机机械运动效果通过上面的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],因为在计算位置的时候铲斗的,此时挖掘机可能已经移动到某个点或者旋转到某个轴,所以此时不??能使用相对于世界的坐标,必须是相对于挖掘机机体的相对坐标用过的。为了计算,代码中提供了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);返回位置.toA数组();该函数的返回值是相对坐标。挖掘机中需要转换的坐标是连接铲斗和小臂的两个部件。系统中使用armHinge和bucketHinge分别表示小臂铰链和铲斗。轮毂的两个部件可以从侧面看到铲斗的动作。从下图可以看出,重点是计算交点P的坐标,交点P的坐标是根据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,另一个小于0。二维向量的叉乘可以直接看成是3d向量,z轴为0的三维向量,但是二维向量的叉乘result结果不是一个向量而是一个值,如果结果>0,则a以<180°的角度旋转到b,如果k<0,则a以>180°的角度旋转到b,如果k=0则a,b向量平行,因此通过上面有了理论知识,我们可以知道结果一定是比0大1,比0小1。我们可以在程序中测试一下,知道我们需要获取的是P1大于0的点,所以我们可以选择两个通过以上方法每次交点下面是斗部分动画的执行流程图:经过上面的计算,我们就可以得到最终需要的点P坐标。P点坐标是铲斗与小臂连接的重要点。得到这个点后,我们就可以通过HT中提供的lookAtX函数来实现下一步的操作了。lookAtX函数的作用是让一个对象看向某个点。使用方法如下:node.lookAtX(position,'bottom');点的节点,position是要看的点的坐标,第二个参数有六个枚举值可以选择,分别是'bottom','back','front','top','right','left'',第二个参数的作用是当我们需要在某个点看物体的时候,还需要指定物体的哪一侧看这个点,所以需要提供第二个参数澄清一下,得到这个函数后,我们可以通过用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=项目Util.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时记录为true,keyup时记录为false,所以我们可以判断定时器中的bool值。当为真时,将执行相应的动作,否则不执行。下面是按键代码对应的部分:letkey_pressed={65:{status:false,action:turnLeft},87:{status:false,action:goAhead},68:{status:false,action:turnRight},83:{状态:假,动作:后退},37:{状态:假,动作:bodyTurnLeft},39:{状态:假,动作:bodyTurnRight}};setInterval(()=>{for(letkeyinkey_pressed){let{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时修改当前键状态的状态值,这样对应的action就可以了根据Interval中变量key_pressed的状态值执行。以下为执行流程图:HT轻量级,自适应目前的系统在移动端应该也能流畅运行。当然,移动端和电脑端的二维图纸加载的图纸是不一样的。在移动端的2D部分,只剩下操作挖掘机的操作部分,其他部分已经进行了相应的操作。放弃吧,不然不可能在移动端的小屏幕上显示这么多数据。3D场景部分共享同一个场景。场景构建部分的批量操作使得3D在移动端运行起来非常流畅。以下为移动端操作截图:总结物联网已经融入现代生活。通过嵌入在机械设备中的电子设备,我们可以完成对机械设备运行和性能的监控,以及及时预警机械设备出现的问题。在这个系统中,2D面板监控部分是将采集到的数据进行可视化展示,我们可以利用大数据和物联网技术,通过板载控制器、传感器、无线通讯模块,将每台机器连接到一个庞大的网络中。一铲一挥,一步行动,都形成了数据痕迹。大数据准确刻画了基础设施建设开工率等情况,成为观察固定资产投资等经济变化的风向标。因此,在实现上述挖掘机动作后,与挖掘机传感器连接后,可以将挖掘机此时的真实动作通过数据传递给系统,系统会根据动作进行相应的真实操作,真正做到实现挖掘机和挖掘机。网络互联。程序运行截图:
