前言
在飞机航行的过程中,客舱里座位上方的荧屏上,除了播放电视剧和广告之外,还会时不时的切换到一个飞机航行的监控系统。这个监控系统的主要目的是,让乘客可以了解到飞机在航行过程中的整体状况、距离目的地的航线进程以及一些有可能出现的突发事件。飞机航行的监控系统在一定程度上,可以使乘客在旅途过程中得到准确的信息源,最重要的是可以使乘客在旅途中得到安心。在保障乘客获取到实际信息源的同时,飞机航行的监控系统也能将采集到的数据及时的反馈给航务人员,而且将数据记录保存下来,在飞机过站或航后供航务和机务人员使用和监测维护。介于 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 系统采集到的数据,对接到显示终端去展示,通过实时监测的数据准确地显示出来,起到对飞机状态的监控功能并即时反馈信息数据的变化。
 
实现过程
云中穿行效果
为了达到飞机云中穿行的效果,最开始我遇到的问题是飞机飞行的层次感,也就通常所说的透视效果,这里我采用的是云通道和云背景以不同的速度流动,制造一种飞行的透视效果。
 
云我采用的是贴图的方式呈现的,但是仅仅是贴图会遮挡天空和飞机,非常影响飞机飞行的观感,所以我开启了相应图元的 transparent 和 opacity,云背景和云通道设置不同的透明度,不仅增加了层次感,还会让人产生云朵从眼前飘过的错觉。
 
云通道采用的是 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.js HT 动画扩展插件去实现飞机颠簸效果,代码如下:
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 的 eye 和 center,不太了解的朋友可以去看 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 的限制空间,也就是球扇形,不太理解的朋友可以参考这个图:

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

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 可视化系统
2019 我们也更新了数百个工业互联网 2D/3D 可视化案例集,在这里你能发现许多新奇的实例,也能发掘出不一样的工业互联网:https://mp.weixin.qq.com/s/ZbhB6LO2kBRPrRIfHlKGQA
同时,你也可以查看更多案例及效果:https://www.hightopo.com/demos/index.html

Web 三维组态的仿真运用案例:民航飞机的数据监控的更多相关文章

  1. WEB 三维引擎在高精地图数据生产的探索和实践

    1. 前言 高精地图(High Definition Map)作为自动驾驶安全性不可或缺的一部分,能有效强化自动驾驶的感知能力和决策能力,提升自动驾驶的等级.对于自动驾驶来说,高精地图主要是给机器用的 ...

  2. threejs构建web三维视图入门教程

    本文是一篇简单的webGL+threejs构建web三维视图的入门教程,你可以了解到利用threejs创建简单的三维图形,并且控制图形运动.若有不足,欢迎指出. 本文使用的框架是three.js gi ...

  3. 基于MVC4+EasyUI的Web开发框架经验总结(12)--利用Jquery处理数据交互的几种方式

    在基于MVC4+EasyUI的Web开发框架里面,大量采用了Jquery的方法,对数据进行请求或者提交,方便页面和服务器后端进行数据的交互处理.本文主要介绍利用Jquery处理数据交互的几种方式,包括 ...

  4. 项目案例之GitLab的数据迁移

    项目案例之GitLab的数据迁移 链接:https://pan.baidu.com/s/1CgaEv12cwfbs5RxcNpxdAg 提取码:fytm 复制这段内容后打开百度网盘手机App,操作更方 ...

  5. Smart3D系列教程6之 《案例实战演练3——倾斜数据正射影像及DSM的生产》

    一.前言 Wish3D出品的系列教程中,前面两讲分别讲述说明了小物件的照片三维重建.大区域地形的三维重建,从照片的直接导入至软件到通过Excel表格将区块导入处理,从不同的模型类别.不同的导入方式演示 ...

  6. 【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME

    原文:[ASP.NET Web API教程]5.3 发送HTML表单数据:文件上传与多部分MIME 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面 ...

  7. 【ASP.NET Web API教程】5.2 发送HTML表单数据:URL编码的表单数据

    原文:[ASP.NET Web API教程]5.2 发送HTML表单数据:URL编码的表单数据 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...

  8. 利用RTL2832u电视棒芯片追踪民航飞机轨迹

    我国民航飞机通讯的频率为1090Mhz,而rtl2832u电视棒芯片可以接受的频率范围为24 – 1766 MHz(通过改制Q通道可以接收0-30Mhz的短波)下面开始介绍利用rtl2832u电视棒芯 ...

  9. ArcGIS案例学习笔记_3_2_CAD数据导入建库

    ArcGIS案例学习笔记_3_2_CAD数据导入建库 计划时间:第3天下午 内容:CAD数据导入,建库和管理 目的:生成地块多边形,连接属性,管理 问题:CAD存在拓扑错误,标注位置偏移 教程:pdf ...

随机推荐

  1. .Net Core微服务化ABP之六——处理Authentication

    上篇中我们已经可以实现sso,并且为各个服务集成sso认证.本篇处理权限系统的角色问题,权限系统分两层,第一层为整体系统角色权限,区分app用户.后台用户.网站用户的接口权限,第二层为业务系统权限,对 ...

  2. JS理论--正则表达式RegExp的创建、元字符、优先度、方法(test(),exec(),match(),replace())

    实战,参数可以对照上面的,代码一定要敲 var str = 'abc123cba456aaa789'; var reg = /\d+/g; console.log(reg.test(str)) //s ...

  3. void 型指针的高阶用法,你掌握了吗?

    [导读] 要比较灵活的使用C语言实现一些高层级的框架时,需要掌握一些进阶编程技巧,这篇来谈谈void指针的一些妙用.测试环境采用 IAR for ARM 8.40.1 什么是void指针 void指针 ...

  4. 最短路径——floyd算法代码(c语言)

    最短路径问题 昨天自己试了试写一下dijkstra的算法博客 dijkstra链接在这← 今天来更floyd算法,感觉非常简单果然暴力才是解决一切的王道 一.总体思想 floyd算法就是每一次从邻接矩 ...

  5. Django之ORM配置与单表操作

    ORM数据库操作流程: 1.    配置数据库(项目同名包中settings.py和__init__.py) 2.    定义类(app包中models.py),执行建表命令(Tools---> ...

  6. 重学 Java 设计模式:实战工厂方法模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  7. (数据科学学习手札84)基于geopandas的空间数据分析——空间计算篇(上)

    本文示例代码.数据及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在本系列之前的文章中我们主要讨论了g ...

  8. JAVA反射整理总结

    //1.通过对象获取            Person p=new Person();            Class c=p.getClass();                //2.通过类 ...

  9. html常用字体

    例1(小米米官网):font-family: "Arial","Microsoft YaHei","黑体","宋体",s ...

  10. Python的大小整数池跟深浅copy

    一.小整数池 可变的数据类型:list dict set 可变: 就是里面的数据类型变了,但是指向的内存地址没变. 不可变的数据类型:str 数值类型 tuple 不可变:如果改变了里面的值,相应的只 ...