Web 三维组态的仿真运用案例:民航飞机的数据监控

2024-08-30 10:58

本文主要是介绍Web 三维组态的仿真运用案例:民航飞机的数据监控,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在飞机航行的过程中,客舱里座位上方的荧屏上,除了播放电视剧和广告之外,还会时不时的切换到一个飞机航行的监控系统。这个监控系统的主要目的是,让乘客可以了解到飞机在航行过程中的整体状况、距离目的地的航线进程以及一些有可能出现的突发事件。飞机航行的监控系统在一定程度上,可以使乘客在旅途过程中得到准确的信息源,最重要的是可以使乘客在旅途中得到安心。在保障乘客获取到实际信息源的同时,飞机航行的监控系统也能将采集到的数据及时的反馈给航务人员,而且将数据记录保存下来,在飞机过站或航后供航务和机务人员使用和监测维护。介于 2D 组态和 3D 组态上,Hightopo(以下简称 HT )的 HT for Web 产品上的有着丰富的组态化可供选择,本文将介绍如何运用 HT 丰富的 2/3D 组态搭建出一个飞机航行的监控系统的解决方案。

预览地址:flight-monitor

系统分析

飞机航行监控是一种测量、跟踪飞机性能变化趋势的简单而实用方法。在日常航班飞行中,用机载仪表记录飞机巡航时的有关参数,并将其与原有性能进行比较。监控的主要参数有:飞行单位时间消耗的燃油量、飞机的巡航飞行速度和消耗单位燃油量飞机飞过的水平距离。它们分别表示发动机、飞机及飞机发动机的综合性能。它们分别表示发动机、飞机及飞机发动机的综合性能。性能监控的结果,既可为飞机维修提供可能的故障信息,又为制定飞行计划提供可靠的性能依据。

目前,先进的喷气运输机都已安装飞行状态监控系统,它记录下有关参数值,并存储在数据管理装置中,这些数据可以发送到或在飞机着陆后送到地面站,用专用计算机程序进行计算和修正,使性能监控数据采集、发送、计箅分析工作自动化,节省了人力,提高了精确度。

1、飞行数据记录器:自从飞行数据记录器 FDR(Flight Data Recorder)“俗称黑匣子”诞生以来,其提供的详实准确的飞行数据为事故调查、机务维护保障、安全运营监控提供了重要依据,成为航空安全运营的重要管理手段。

2、ACMS(Aireraft Condition Monitoring System)的系统概述:ACMS 系统是飞机上安装的先进机载数据采集和处理系统,它能以实时方式收集数据,对发动机状态和飞行性能进行监控以及进行特殊的工程调查。由飞机通信寻址与报告系统(ACARS)通过地空数据链发送到地面接收站,最后传送到航空公司的终端,也可通过快速存取记录器(QAR)将数据记录保存下来,在飞机过站或航后供航务和机务人员使用。

而 HT 实现的业务功能可以通过ACMS 系统采集到的数据,对接到显示终端去展示,通过实时监测的数据准确地显示出来,起到对飞机状态的监控功能并即时反馈信息数据的变化。

实现过程

云中穿行效果

为了达到飞机云中穿行的效果,最开始我遇到的问题是飞机飞行的层次感,也就通常所说的透视效果,这里我采用的是云通道和云背景以不同的速度流动,制造一种飞行的透视效果。

云我采用的是贴图的方式呈现的,但是仅仅是贴图会遮挡天空和飞机,非常影响飞机飞行的观感,所以我开启了相应图元的transparentopacity,云背景和云通道设置不同的透明度,不仅增加了层次感,还会让人产生云朵从眼前飘过的错觉。

云通道采用的是ht.Polyline类型,通道缩放拉大了 Y 轴的比例,使云通道有更大的纵向空间,设置reverse.flip背拷贝使云通道内部也显示出贴图,仿佛让飞机置身于云海中穿梭;云背景采用ht.Node类型,只设置一个面显示充当云背景。

整体的云流动效果采用offset偏移实现,改变相应图元或相应图元面的贴图偏移量来达到飞机云中穿行的效果, 代码如下:

var i = 1,p = 0;
setInterval(() => {i -= 0.1; p += 0.005;clouds.s('shape3d.uv.offset', [i, 0]);cloudBackground.s('all.uv.offset', [p, 0]);
}, 100);
升降颠簸效果

虽然达到了飞机云中穿行的效果,但是如果飞机只是直直的飞行,那也会降低飞行的实感,相信坐过飞机的朋友肯定都遇到过因气流产生的颠簸,也经常感受到飞机飞行途中的爬升和下降,这其实是因为飞机的航线并不是一直固定在一个高度上,有时会爬升有时会下降,所以我就用ht-animation.jsHT 动画扩展插件去实现飞机颠簸效果,代码如下:

dm.enableAnimation(20);
plane.setAnimation({back1: {from: 0,to: 160,easing: 'Cubic.easeInOut',duration: 8000,next: "up1",onUpdate: function (value) {value = parseInt(value);var p3 = this.p3();this.p3(value, p3[1], p3[2]);}},//...省略相似start: ["back1"]
});
球扇形视角限制

飞行效果完善之后,这时我就遇到了一个比较棘手的问题,因为实际上虽然看着飞机是在云海中穿梭,但是仅仅是在通道中飞行,背景其实也只是平面贴图,所以当视角到达某种程度的时候就会有强烈的违和感和不真实感,就需要一个视角限制,使视角的调整刚刚好在一个范围内。

视角限制的话一般是限制 g3d 的 eyecenter ,不太了解的朋友可以去看 hightopo 官网中的 3d 手册,里面有详细的说明,这里我就不再赘述了;因为视角范围的关系,所以我决定固定center的位置,代码如下:

g3d.addPropertyChangeListener(e => {// 固定中心点if (e.property === 'center') {e.newValue[0] = center[0];e.newValue[1] = center[1];e.newValue[2] = center[2];}
}

然后再把eye限制在某一个范围内就大功告成了,然而这里却并不是那么简单,最开始我把eye限制在一个立方体的空间内,但交互效果很不理想,考虑到 g3d 默认交互中,鼠标拖拽平移视角变换时,实际上eye是在一个以center为球心的球面上运动的,所以我决定从这个球中挖出来一块作为eye的限制空间,也就是球扇形,不太理解的朋友可以参考这个图:

球扇形视角限制,一共需要三个参数,分别是中心参考轴、中心轴和外边所成角度、所在球限制半径,其中中心参考轴可根据初始eyecenter的连接延长线确定,所在球限制半径又分最大限制和最小限制,代码如下:

function limitEye(g3d, eye, center, options) {var limitMaxL   = options.limitMaxL,limitMinL   = options.limitMinL,limitA      = options.limitA;g3d.addPropertyChangeListener(e => {// 固定中心点if (e.property === 'center') {e.newValue[0] = center[0];e.newValue[1] = center[1];e.newValue[2] = center[2];}// 限制视角if (e.property === 'eye') {var newEyeV = new ht.Math.Vector3(e.newValue),centerV = new ht.Math.Vector3(center),refEyeV = new ht.Math.Vector3(eye),refVector = refEyeV.clone().sub(centerV),newVector = newEyeV.clone().sub(centerV);if (centerV.distanceTo(newEyeV) > limitMaxL) {newVector.setLength(limitMaxL);e.newValue[0] = newVector.x;e.newValue[1] = newVector.y;e.newValue[2] = newVector.z;}if (centerV.distanceTo(newEyeV) < limitMinL) {newVector.setLength(limitMinL);e.newValue[0] = newVector.x;e.newValue[1] = newVector.y;e.newValue[2] = newVector.z;}if (newVector.angleTo(refVector) > limitA) {var oldLength = newVector.length(),oldAngle  = newVector.angleTo(refVector),refLength = oldLength * Math.cos(oldAngle),vertVector,realVector,realEye;refVector.setLength(refLength);newEyeV = newVector.clone().add(centerV);refEyeV = refVector.clone().add(centerV);vertVector = newEyeV.clone().sub(refEyeV);vertLength = refLength * Math.tan(limitA);vertVector.setLength(vertLength);realVector = vertVector.clone().add(refEyeV).sub(centerV);realVector.setLength(oldLength);realEye = realVector.clone().add(centerV);// 防止移动角度大于 180 度,视角反转if (oldAngle > Math.PI / 2) {realEye.negate();}e.newValue[0] = realEye.x;e.newValue[1] = realEye.y;e.newValue[2] = realEye.z;}  }})
}

飞机监控系统

当然作为监控系统,自然要有监控了,增加右下角的小地图,并提供三种模式,分别是聚焦飞机,聚焦飞行轨迹和聚焦地图,并根据飞机的飞行方向控制飞行轨迹的流动效果,其中聚焦飞机会跟随飞机移动进行fitData,使飞机一直处于小地图的中心,代码如下:

var fitFlowP = function (e) {if (e.property === 'position' && e.data === plane) {mapGV.fitData(plane, false);}
};
buttonP.s({'interactive': true,'onClick': function (event, data, view, point, width, height) {map.a('fitDataTag', 'plane2D');mapGV.fitData(plane, false);mapDM.md(fitFlowP);}
});
buttonL.s({'interactive': true,'onClick': function (event, data, view, point, width, height) {mapDM.umd(fitFlowP);map.a('fitDataTag', 'flyLine');mapGV.fitData(flyLine, false);}
});
// ...省略

在这里插入图片描述

增加鼠标移到飞机相应位置进行名称的提示、双击后显示飞机相应位置的信息面板并将视角聚焦到面板上、点击飞机任意地方切换回飞机飞行模式等效果。

左侧增加监控面板替代上面提到的双击相应位置这步操作直接聚焦到相应位置的信息面板上,这里按钮开启了交互并添加了相应的交互逻辑,代码如下:

button_JC.s({'interactive': true,'onClick': function (event, data, view, point, width, height) {event.preventDefault();let g3d = G.g3d,g3dDM = G.g3d.dm();g3d.fireInteractorEvent({kind: 'doubleClickData',data: g3dDM.getDataByTag(data.getTag())})}
});
//...省略

天空渲染效果

既然是监控系统肯定是 24 小时无差别的监控,这就涉及到一个问题,我总不可能半夜的时候飞机也从瓦蓝瓦蓝的天空上飞过,这就很欠缺真实性了,所以要有一个天空从亮到暗再从暗到亮的过程,这个过程我暂定到 06:00-06:30 和19:00-19:30 这两个时间段。

天空采用的是shape3d : 'sphere’球形,包裹整个场景,然后使用reverse.flip背拷贝 和blend染色,之后天空就可以渲染成我想要的颜色,如果按照时间改变天空明暗只要改变染色值就可以了。

但是由于白天和晚上光照情况的不同,云反射光的强度也不同,就导致了白天和晚上云的差异,所以也要调整云道和云背景的贴图的opacity透明度,晚间更为透明度,代码如下:

if ((hour > 6 && hour < 19) || (hour == 6 && minutes >= 30)) {timePane && timePane.a({'morning.visible': false,'day.visible': true,'dusk.visible': false,'night.visible': false,'day.opacity': 1})skyBox.s({"shape3d.blend": 'rgb(127, 200, 240)',})cloudBackground.s({"back.opacity": 0.7,})clouds.s({"shape3d.opacity": 0.7,})
} else if ((hour < 6 || hour > 19) || (hour == 19 && minutes >= 30)) {
//...省略
} else if (hour == 6 && minutes < 15 ) {
//...省略
} else if (hour == 6 && minutes >= 15 && minutes < 30) {
//...省略
} else if (hour == 19 && minutes < 15) {
//...省略
} else if (hour == 19 && minutes >= 15 && minutes < 30) {
//...省略
}


这里我还增加了对右上角时间面板时间状态图标的支持,并增加了图标切换时的渐隐渐显效果,同时给时间面板状态图标位置增加了点击切换到下一时间状态的功能。

为了演示效果我增加了时间倍速按钮,下图是 500 倍时间流速下的变化情况:

总结

身处大数据时代的我们,在网络科技发展越来越快的环境下,迎来了 5G 的新征程和工业4.0的新变革,在信息数据采集传输和数据可视化系统的融合下,可以发掘出许多行业管控可视化系统的解决方案。而 HT 长久以来一直致力于多样化行业系统可视化的搭建,涉猎的技术行业所累积的经验,通过自主创新研发的技术产品,已经打造出许多行业上具有代表性意义的可视化管控系统,例如同样有关于飞机的监控可视化系统:无人机 3D 可视化系统

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hvYQGzq8-1591092123840)(https://img2020.cnblogs.com/blog/1496396/202006/1496396-20200601185137243-2111613258.gif)]

2019 我们也更新了数百个工业互联网 2D/3D 可视化案例集,在这里你能发现许多新奇的实例,也能发掘出不一样的工业互联网:https://mp.weixin.qq.com/s/ZbhB6LO2kBRPrRIfHlKGQA

同时,你也可以查看更多案例及效果:https://www.hightopo.com/demos/index.html

这篇关于Web 三维组态的仿真运用案例:民航飞机的数据监控的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120624

相关文章

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Java中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例解析

《Java中的分布式系统开发基于Zookeeper与Dubbo的应用案例解析》本文将通过实际案例,带你走进基于Zookeeper与Dubbo的分布式系统开发,本文通过实例代码给大家介绍的非常详... 目录Java 中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例一、分布式系统中的挑战二

C#使用iText获取PDF的trailer数据的代码示例

《C#使用iText获取PDF的trailer数据的代码示例》开发程序debug的时候,看到了PDF有个trailer数据,挺有意思,于是考虑用代码把它读出来,那么就用到我们常用的iText框架了,所... 目录引言iText 核心概念C# 代码示例步骤 1: 确保已安装 iText步骤 2: C# 代码程

Pandas处理缺失数据的方式汇总

《Pandas处理缺失数据的方式汇总》许多教程中的数据与现实世界中的数据有很大不同,现实世界中的数据很少是干净且同质的,本文我们将讨论处理缺失数据的一些常规注意事项,了解Pandas如何表示缺失数据,... 目录缺失数据约定的权衡Pandas 中的缺失数据None 作为哨兵值NaN:缺失的数值数据Panda

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

Java 中的 equals 和 hashCode 方法关系与正确重写实践案例

《Java中的equals和hashCode方法关系与正确重写实践案例》在Java中,equals和hashCode方法是Object类的核心方法,广泛用于对象比较和哈希集合(如HashMa... 目录一、背景与需求分析1.1 equals 和 hashCode 的背景1.2 需求分析1.3 技术挑战1.4

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

python库pydantic数据验证和设置管理库的用途

《python库pydantic数据验证和设置管理库的用途》pydantic是一个用于数据验证和设置管理的Python库,它主要利用Python类型注解来定义数据模型的结构和验证规则,本文给大家介绍p... 目录主要特点和用途:Field数值验证参数总结pydantic 是一个让你能够 confidentl

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

JAVA实现亿级千万级数据顺序导出的示例代码

《JAVA实现亿级千万级数据顺序导出的示例代码》本文主要介绍了JAVA实现亿级千万级数据顺序导出的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 前提:主要考虑控制内存占用空间,避免出现同时导出,导致主程序OOM问题。实现思路:A.启用线程池