webgl(three.js)实现室内定位,楼宇bim、实时定位三维可视化解决方案

简介: 3D定位、三维室内定位、3d建筑,3d消防,消防演习模拟,3d库房,3d档案室,3d密集架,webGL,threejs,3d机房,bim管理系统

(写在前面,谈谈物联网展会)上次深圳会展中心举行物联网展会,到了展会一看,80%以上的物联网应用都是在搞RFID,室内定位,我一度怀疑物联网落地方案的方向局限性与市场导向,后来多方面了解才明白,展会上看到的不能体现目前物联网最前沿最广泛的应用,很多大的企业与技术前沿企业没有参与这样的展会,一是不屑于参加,二是展会带来的市场价值实在太少太少,展会最大的价值就是让同行之间再抄一抄(国内大部分企业基本这样,互相山寨),看看各家都做了啥,所以,展会上我们所看到的往往不是企业最核心最好的东西,不能体现当前国内物联网最前沿的技术与发展状况。

前言:GPS、北斗系统将全球地图导航定位发展到了极致的程度,但精确精度还不能达到两米以内, 如何解决解决室内这最后几米的定位问题,国内外各大厂家各出奇招。因为有市场需求所以有资本驱动,室内精确定位在仓库,档案馆,监狱,医院,办公,人员,以及各种高价值重要资产等定位场景中都要这样的需求。室内定位设想应用于人员的管理、机器人仿生、被标签物的定位追踪等等。如果室内定位能够解决精度,延迟,容量三方面瓶颈,其市场应用价值不可限量

技术目标:将非可视内容的可视化呈现,更直观的掌控数据情况。

一、市场背景与领域:

  1、信息采集定位:打卡、签注、活动范围圈定、电子围栏、工作中日常监控等等。

  2、安防监控定位:安防领域比较广泛,包括了消防、监控、维保安保等等,这些具体行业划分方面对精准定位可视化需求都比较强烈。保护人民生命财产、监控消防英雄实时位置这些都是有待解决的问题。

  3、工业4.0:这是最新的工业诉求,真正落地的,目前还没有几家,其主要目标就是通过室内定位技术让整个生产流程实现可视化,可追踪化。

  4、监狱、医院、机场领域、商场。定位可视化需求也比较强烈

    监狱:防止越狱,防止自杀等。每个犯人手上上一个不可拆卸的手环,只要系统检查到有人某处停留时间过长,系统就会报警。

    医院:为患者提供快捷的寻址巡诊服务。

    机场、商场:为客人,旅客提供方便快捷的定位导航服务,为机场提供可疑物品贴标签定位方案。

  5、仓库资产定位

  6、无人机、物流、快递派送定位

  7、APP应用服务,适当位置推送适当服务。

  8、游戏场景,VR应用

 等等,随便想想就这么多,看来市场还是比较有前景的。

二、技术方案分析:

  当前市面上室内定位技术主要分为下列几种:

  1、wifi探针+摄像机智能分析技术:这种技术利用wifi探针撤出大体位置在用摄像机智能分析,分析出精确位置,优点是精确度高,缺点是成本高,摄像机死角多。

    

  2、无源RFID+读卡器技术:这种技术是目前市面上用的比较多的技术,比如超市,仓储,优点是成本低,缺点是没什么精度要求 ,精度范围 是房间内

  3、低功耗有源RFID+读卡器基地器+智能分析:这种利用有源发射信号的方式定位,精确多虽然高 但是读卡器多的情况下会出现误报,乱报情况,这就需要智能分析,数据清洗。目前比较看好的方案,成本低,精确度一米以内。

  4、蓝牙信号强度探测分析:精確的高,但是藍牙信號受阻擋,受干扰比较严重。这也是展会中看到的方案。

  5、定位地毯+有源信号卡(手环):这是精确度非常高的方案,但是成本也很高。要在室内铺上一层定位弱电地毯。

  6、红外探测技术、超宽带技术、超声波技术:和蓝牙的方案差不多。

技术交流邮箱: 1203193731@qq.com

三、三维可视化显示

我们还是和前面的课程一样选择webgl无插件解决方案,直观体现定位可视化。

3.1、首先是场景搭建,搭建需要定位的三维场景。这里我们随便做了一栋大楼,作为需要定位的场景。

d1

下图是gif图效果,(为了上传到文章里,特意做了帧数删减)

d1

模型代码:

3.2、显示单个楼层实时定位效果。这里我们动态添加定位标签。标注标签。在右下角显示标签信息,规避场景内凌乱。

d2

楼层切换效果
d3

逻辑代码: 

if (_this.build1CurrentShowFlow == 8&&_this.currentShowLocationState == 1) {

         _this.closeLocation(doshowAnimiation);
} else {
         doshowAnimiation();
  }
 function doshowAnimiation(){
WT3DObj.commonFunc.changeCameraPosition(
    { x: -3160 + (8 - floornub) * 300, y: 5645 - (8 - floornub) * 300, z: -3292 + (8 - floornub) * 300 },
    { x: 80, y: 23, z: 155 },
    500,
   function () {
            if (_this.build1CurrentShowFlow > floornub)
            {
                var start = _this.build1CurrentShowFlow;
                _this.build1CurrentShowFlow = floornub;
                for (var i = start; i >= floornub + 1; i--) {
                    (function (floorindex) {
                        setTimeout(function () {
                            var movemodesname = "cM_dingweifloor_" + floorindex;
                            var movemodel = _this.outFloorModels[movemodesname];
                            if (!movemodel.oldposition) {
                                movemodel.oldposition = {
                                    x: movemodel.position.x,
                                    y: movemodel.position.y,
                                    z: movemodel.position.z
                                };
                            }
                            var moveToPositon = movemodel.position.y + 5000;
                            new TWEEN.Tween(movemodel.position).to({
                                y: moveToPositon
                            }, 1000).onComplete(function () {
                                movemodel.visible = false;
                                if (floorindex == floornub + 1) {
                                    if (_this.currentShowLocationState == 1) {
                                        if (floornub < 8) {
                                            var showTxt = "";
                                            showTxt += _this.addFloorMarks(floornub);
                                            $("#showText").html(showTxt);
                                        } else {
                                            _this.showLocation();
                                        }
                                    }
                                }
                            }).start();
                        }, 500 * (start+1 - floorindex));
                    })(i);
                }

            }
            else if (_this.build1CurrentShowFlow < floornub)
            {
                var start = _this.build1CurrentShowFlow+1;
                _this.build1CurrentShowFlow = floornub;
                for (var i = start; i <= floornub ; i++) {
                    (function (floorindex) {
                        setTimeout(function () {
                            var movemodesname = "cM_dingweifloor_" + floorindex;
                            var movemodel = _this.outFloorModels[movemodesname];
                            var moveToPositon = movemodel.oldposition.y;
                            movemodel.visible = true;
                            new TWEEN.Tween(movemodel.position).to({
                                y: moveToPositon
                            }, 1000).onComplete(function () {
                                if (floorindex == floornub) {
                                setTimeout(function () {
                                    if (_this.currentShowLocationState == 1) {
                                        if (floornub < 8) {
                                            var showTxt = "";
                                            showTxt += _this.addFloorMarks(floornub);
                                            $("#showText").html(showTxt);
                                        } else {
                                            _this.showLocation();
                                        }
                                    }
                                }, 150 * floornub - start);
                                }
                            }).start();
                        }, 500 * (floorindex-start + 1));
                    })(i);
                }

            }
            
   });
 }

  

单楼层显示定位效果
d3

‘’

动态标签模型代码:

[{ "show": true, "uuid": "", "name": "dmark_" + name, "objType": "GroupObj", "scale": { "x": 1, "y": 1, "z": 1 }, "position": position, "rotation": [{ "direction": "x", "degree": 0 }], "childrens": [{ "name": "dmark_" + name + "OBJCREN0", "objType": "picIdentification", "size": { "x": size.width, "y": size.height }, "position": { "x": 0, "y": 0, "z": 0 }, "imgurl": picurl, "showSortNub": 3480, "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }, { "name": "dmark_" + name + "OBJCREN1", "objType": "makeTextSprite", "textColor": { "r": Txtcolor.r, "g": Txtcolor.g, "b": Txtcolor.b, "a": 1 }, "message": "" + showNub, "fontsize": 300, "canvasWidth": 400, "canvasHeight": 350, "position": { "x": 0, "y": 64.901, "z": 0 }, "showSortNub": 3481, "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }], "showSortNub": 3480 }];
单楼层显示定位代码:

ModelBusiness.prototype.marks = [];
ModelBusiness.prototype.addMark = function (name, position, size, picurl,showNub,Txtcolor) {

if (this.marks.indexOf("dmark_" + name) >= 0) {
    modelBusiness.moveMark("dmark_" + name, position, 1000);
    return;
}
this.marks.push("dmark_" + name);
var timestrik = new Date().getTime();

var showHtml = "hello";
var local = [{ "show": true, "uuid": "", "name": "dmark_" + name, "objType": "GroupObj", "scale": { "x": 1, "y": 1, "z": 1 }, "position": position, "rotation": [{ "direction": "x", "degree": 0 }], "childrens": [{ "name": "dmark_" + name + "OBJCREN0", "objType": "picIdentification", "size": { "x": size.width, "y": size.height }, "position": { "x": 0, "y": 0, "z": 0 }, "imgurl": picurl, "showSortNub": 3480, "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }, { "name": "dmark_" + name + "OBJCREN1", "objType": "makeTextSprite", "textColor": { "r": Txtcolor.r, "g": Txtcolor.g, "b": Txtcolor.b, "a": 1 }, "message": "" + showNub, "fontsize": 300, "canvasWidth": 400, "canvasHeight": 350, "position": { "x": 0, "y": 64.901, "z": 0 }, "showSortNub": 3481, "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }], "showSortNub": 3480 }];
//[{ "name": "dmark_" + name, "objType": "picIdentification", "size": { "x": size.width, "y": size.height }, "position": position, "imgurl": picurl, "showSortNub": 3480, "show": true, "customType1": "", "customType2": "", "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null },
//    { "name": "dmark_TxtNub_" + name, "objType": "makeTextSprite", "textColor": { "r": 255, "g": 255, "b": 0, "a": 1 }, "message": "001", "fontsize": 100, "canvasWidth": 100, "canvasHeight": 120, "position": { "x": position.x, "y": position.y + 53.904, "z": position.z}, "showSortNub": 5, "animation": null, "dbclickEvents": null, "BindDevId": null, "BindDevName": null, "devInfo": null, "BindMeteId": null, "BindMeteName": null }];
WT3DObj.commonFunc.loadModelsByJsons(local, { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 }, true);

}
ModelBusiness.prototype.addMarkTxt = function (showHtml, _obj, buildNub, position, closeFunc) {

var timestrik = new Date().getTime();
var _obj = {
    uuid: 'daf4',
    name: "showMark",
    showSortNub: 1,
    objType: "DivTagging",
    tagType: 'sprite',//plane/sprite
    elementParam: {
        cssid: "style_divtest",
        css: "",
        marginValue: {
            x: 0,
            y: 0,
            z: 0
        },
        divid: 'divtest',
        html: "<div id='divtest'><div  style='width:300px;height:200px;background-color:rgba(0,0,0,1);padding:10px;border:1px solid #00ffff;'>" + showHtml + "</div > </div >",
    },
    position: { x: position.x, y: position.y + 500, z: position.z },
    scale: { x: 8, y: 8, z: 1 },
    rotation: [],
}
var ccd = WT3DObj.addDivTagging(WT3DObj, _obj);
ccd.renderOrder = 1;
WT3DObj.addObject(ccd);

}
3.3、显示整体楼层实时定位效果。
d4

gif录屏图
d4

d5
 实现代码:
if (_this.build1CurrentShowFlow == 8&&_this.currentShowLocationState == 1) {

         _this.closeLocation(doshowAnimiation);
} else {
         doshowAnimiation();
  }
 function doshowAnimiation(){
WT3DObj.commonFunc.changeCameraPosition(
    { x: -3160 + (8 - floornub) * 300, y: 5645 - (8 - floornub) * 300, z: -3292 + (8 - floornub) * 300 },
    { x: 80, y: 23, z: 155 },
    500,
   function () {
            if (_this.build1CurrentShowFlow > floornub)
            {
                var start = _this.build1CurrentShowFlow;
                _this.build1CurrentShowFlow = floornub;
                for (var i = start; i >= floornub + 1; i--) {
                    (function (floorindex) {
                        setTimeout(function () {
                            var movemodesname = "cM_dingweifloor_" + floorindex;
                            var movemodel = _this.outFloorModels[movemodesname];
                            if (!movemodel.oldposition) {
                                movemodel.oldposition = {
                                    x: movemodel.position.x,
                                    y: movemodel.position.y,
                                    z: movemodel.position.z
                                };
                            }
                            var moveToPositon = movemodel.position.y + 5000;
                            new TWEEN.Tween(movemodel.position).to({
                                y: moveToPositon
                            }, 1000).onComplete(function () {
                                movemodel.visible = false;
                                if (floorindex == floornub + 1) {
                                    if (_this.currentShowLocationState == 1) {
                                        if (floornub < 8) {
                                            var showTxt = "";
                                            showTxt += _this.addFloorMarks(floornub);
                                            $("#showText").html(showTxt);
                                        } else {
                                            _this.showLocation();
                                        }
                                    }
                                }
                            }).start();
                        }, 500 * (start+1 - floorindex));
                    })(i);
                }

            }
            else if (_this.build1CurrentShowFlow < floornub)
            {
                var start = _this.build1CurrentShowFlow+1;
                _this.build1CurrentShowFlow = floornub;
                for (var i = start; i <= floornub ; i++) {
                    (function (floorindex) {
                        setTimeout(function () {
                            var movemodesname = "cM_dingweifloor_" + floorindex;
                            var movemodel = _this.outFloorModels[movemodesname];
                            var moveToPositon = movemodel.oldposition.y;
                            movemodel.visible = true;
                            new TWEEN.Tween(movemodel.position).to({
                                y: moveToPositon
                            }, 1000).onComplete(function () {
                                if (floorindex == floornub) {
                                setTimeout(function () {
                                    if (_this.currentShowLocationState == 1) {
                                        if (floornub < 8) {
                                            var showTxt = "";
                                            showTxt += _this.addFloorMarks(floornub);
                                            $("#showText").html(showTxt);
                                        } else {
                                            _this.showLocation();
                                        }
                                    }
                                }, 150 * floornub - start);
                                }
                            }).start();
                        }, 500 * (floorindex-start + 1));
                    })(i);
                }

            }
            
   });
 }

由于篇幅原因,这一课先介绍到这里

后面我将继续讲解用webgl 建立 3D园区 3D智慧小区 、室内定位、桥梁隧道三维应用炫酷效果等等

技术交流 1203193731@qq.com

交流微信:

    
800616_20190306111130020_1677299606

如果你有什么要交流的心得 可邮件我

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
4月前
|
开发框架 前端开发 JavaScript
C# 6.0+JavaScript云LIS系统源码  云LIS实验室信息管理新型解决方案
云LIS是为区域医疗提供临床实验室信息服务的计算机应用程序,可协助区域内所有临床实验室相互协调并完成日常检验工作,对区域内的检验数据进行集中管理和共享,通过对质量控制的管理,最终实现区域内检验结果互认。其目标是以医疗服务机构为主体,以医疗资源和检验信息共享为目标,集成共性技术及医疗服务关键技术,建立区域协同检验,最大化利用有限的医疗卫生资源。
146 1
|
1天前
|
JavaScript 前端开发
js怎么定位不同的页面元素
在JavaScript中,有多种方法定位和选择页面元素。
|
4月前
|
前端开发 JavaScript API
Howler.js:音频处理的轻量级解决方案
Howler.js:音频处理的轻量级解决方案
312 0
|
1月前
|
JavaScript 调度
Three.js开发秘籍:FlyControls的拖拽视角问题解决方案
Three.js开发秘籍:FlyControls的拖拽视角问题解决方案
39 0
|
2月前
|
JavaScript 前端开发
vue常见报错解决方案 | javascript heap out of memory
vue常见报错解决方案 | javascript heap out of memory
168 0
|
4月前
|
JavaScript 前端开发 数据可视化
Vue.js 与 ViewDesign:为企业级 Web 应用提供高效可靠的解决方案
Vue.js 是一款开源的渐进式 JavaScript 框架,擅长构建用户界面,适用于各种规模的应用。其特点包括渐进式设计、虚拟 DOM、响应式数据绑定和组件化。ViewDesign(前身为 iView)是基于 Vue.js 的企业级 UI 组件库,提供丰富的组件、遵循企业设计规范,并支持高度定制。两者结合,能提升开发效率、保证界面一致性、简化维护,且两者生态均得到良好支持。Vue.js 3 的支持使得开发更加现代和高效。
|
4月前
|
移动开发 JavaScript 前端开发
Web Worker:JavaScript的后台任务解决方案
Web Worker:JavaScript的后台任务解决方案
|
4月前
|
JavaScript 前端开发 网络协议
利用Node.js和cpolar实现远程访问,无需公网IP和路由器设置的完美解决方案
利用Node.js和cpolar实现远程访问,无需公网IP和路由器设置的完美解决方案
48 0
|
4月前
|
JavaScript 前端开发 安全
JavaScript中跨域资源共享(CORS):原理和解决方案
【4月更文挑战第22天】本文介绍了JavaScript中跨域资源共享(CORS)的原理和解决方案。CORS借助HTTP头部字段允许跨域请求,核心是Access-Control-Allow-Origin响应头。解决方案包括:服务器端设置响应头(如使用Express.js的cors中间件)、使用代理服务器或JSONP。现代Web开发推荐使用CORS,因为它更安全、灵活,而JSONP已逐渐被淘汰。理解并正确实施CORS能提升Web应用性能和安全性。
|
4月前
|
移动开发 定位技术 API
编程笔记 html5&css&js 035 HTML 地理定位
编程笔记 html5&css&js 035 HTML 地理定位