如需源码,请关注公众号后留言
潜水运动作为一种极限运动,充满危险、价格昂贵,即使是受过专业训练的潜水运动员,在没有氧气瓶和潜水衣的条件下也很难潜到 50m以下,对于普通人来说,想要体验深海的美丽更是难上加难。深海是一个尚未被开发过的领域,人们常常对未知的领域感到好奇,尤其是深海这样深邃而又壮阔、神秘的地方。真实的探索深海同样意味着危险、价格昂贵,普通人很难参与。
怀着对深海探索的向往,本组成员希望开发出一款能自由实现就地潜水的 VR 游戏,帮助人类探索深海,未来通过进一步优化可扩展,本应用可用于潜水爱好者的培训领域。
- 开发方案 -
/ 硬件平台选型 /
实现 VR 的硬件平台包括单目摄像机、双目摄像机、双目-深度摄像机,头盔显示器,VR 眼镜,数据手套等。由于时间和学习成本等问题,我们最终选用了 Kinect、数据手套和 VR 眼镜作为项目主要的输入和输出设备,以此构成交互式体验的闭环。
/ 软件开发平台的选择 /
虚拟现实的软件开发平台有 3DMAX,Unity,虚幻 4 引擎等。 而 Unity 的物理引擎十分优良,能够开发跨越移动、台式机、Web 游戏主机和其它平台的各种应用。而且国内用户较多,中文文献也多,大大降低了学习与开发成本。此外,Unity 对教育行业用户采取了开放的态度最新版本允许教师和学生免费使用,并且提供了大量的教程视频、示例项目和社区资源用来支持学习。所以我们最终决定用 Unity 以及 Visual Studio 作为我们项目的软件开发平台。
但由于微软已经停产 Kinect,Kinect 在 Unity上的库没人维护,因此在正式开发之前,我们还需先对 Kinect 库进行整合。
/ 开发流程和分工 /
综上对 项目实现的硬件和软件的选型分析,本项目开发流程和相关关键技术如下图所示。
组内成员分工如下:
- 人体骨骼流的建立与输出 -
/ Kinect 骨骼流原理介绍 /
Kinect是一款双目-深度摄像机,可以识别20个特征点来表征一个人体骨骼,其最多可以检测两幅骨骼,最多可以检测到六个人。如下图所示:
Kinect 骨骼流投影原理
Kinect skeleton flow projection principle
我们初始化并打开骨骼跟踪后,就可以从SkeletonStream中获得骨骼数据了。skeletonStream 产 生 的 每 一 帧 数 据skeletonFrame都是一个骨骼对象集合。包含了一个骨架数据结构的数组,其中每一个元素代表着一个被骨架追踪系统所识别的一个骨架信息。每一个骨架信息包含有描述骨骼位置以及骨骼关节的数据。每一个关节有一个唯一标示符如头(head)、肩(shoulder)、肘(dlbow)等信息和对应的三维坐标数据。
/ 利用骨骼流建模 /
在获取每个关节点的三维坐标之后,只需建立一个包含Kinect关节点的人体模型,并将Kinect对每个关节点的数据接收与运动写成脚本,挂载在模型上即可。
骨骼流绑定人物模型脚本
Bone Flow Binding Character Model Script
为了方便,我们从网上下载了包含人体 48个关节点的人物模型。
人物模型
Character model
Kinect 摄像效果如下:
Kinect 摄像效果
Kinect camera effect
但由于 Kinect 对于手腕识别不是很精准,而且没法对手势进行体感输入,于是我们这一模块所面临的下一个难题就是如何精细化输入。经过队友启发,我们打算做一款数据手套来辅助输入。
/ VR摄像机以及反畸变实现 /
在一开始用Kinect时我们就想到用手机不能处理如此庞大的数据流,必须要借助PC机的运
算,但这样就无法打包到手机上,利用SDK包进行VR的输出,于是如何显示就成了我们下一步面临的难题。
在查阅了大量文献后,我们突发奇想,为何不直接在PC上实现从虚拟环境到镜片上的映射,也就是实现VR摄像机的分屏与光线反畸变,然后将输出的视频投影到手机上,这样就可以用VR眼镜观看了。
于是我们对VR摄像机实现了分屏聚焦操作。而对于畸变,我们则从网上下载了畸变模型,将模型上的脚本挂载到Camera上。
PC 上实现的 VR 摄像机效果如下:
jy-901 实现效果
jy-901 to achieve the effect
Jy-901 成本价较高,但相对的效果也比较好,而且自带校准程序,但 z 轴还是会出现数据不稳定的情况,经常会出现无论怎么绕 z 轴旋转,z轴欧拉角都只会收敛到同一个值。经过程序校准后,情况好了许多。
jy-901 校准界面
jy-901 calibration interface
地磁校准过程:
MPU9250 实现效果(一)
MPU9250 to achieve the effect (1)
海底生物模型
Undersea creature model
/ 运动识别 /
由于采用的水资源只是水面上的渲染效果,并不能实现真正的物理水模型,也就不能给人物带来运动力,因此我们针对人物运动设计了一列碰撞小方块,该列方块是人体的子模型,人体运动时将伴随人体一起运动。该列方块以人体的胸腔为圆心,在手臂横向滑动平面,以手臂长为半径呈半圆分布:
人物运动识别模型
相关阅读 /虚拟现实/-应用-美国航母着舰信号指挥官训练基于VR技术虚拟现实将成为人工智能的下一代训练环境南加州大学CLVR实验室在虚拟环境中教机器人组装宜家家具快了!空客将用基于VR头显的飞行训练器进行改装训练-原理-视觉深度感知的基本原理 /飞行仿真/-历史-飞行员培训从基于真飞机到基于模拟机20世纪60年代Ames研究中心的飞行模拟器们飞行模拟机视景系统的史前时代-价值-NASA驾驶舱间隔管理(FIM)飞行试验试飞员真飞前的地面培训 /航空资料整理/3U8633那34分钟的惊心动魄,已经过去两年了 /可视化之禅/美国人收入差距有多大世界制造业产值地图

实现了基于VR的虚拟潜泳应用,通过交互的方式满足人们基于对深海探索的向往。运用 Unity、Kinect 和九轴传感器 9250,对人体骨骼流与关节节点姿态角进行了建模与研究,能够精准地实现包括手指在内的人体体感输入,延迟在 10ms 以内;以 VR 双屏反畸变的方式输出,使用 VR 眼镜即可体验。但由于 Kinect 所传输的数据流太过庞大,无法在 arm 移动端实现接收和运算,需要借助 PC 机解算并通过 unity 建模转换成视频流,再传给手机,这会导致手机有一定的卡顿,考虑在传输上再做一定的优化。 |

张子钰 | 李明 |
①Kinect 库整合 ②场景搭建以及绑定 Kinect 骨骼流 ③数据手套的调试 ④编写 VR 摄像机脚本、人物运动识别脚本 | ①电路设计 ②PCB 设计 ③硬件调试 ④编写数据处理程序 |





在PC上实现的VR摄像机
VR camera implemented on PC 但这个方法的缺点是,无法用unity自带的SDK包,那么实现的反畸变算法和实际的透镜并不能完全匹配,导致边缘部分可能会有色散或者图像扭曲。为此我们的解决方案是人为调参,将畸变的参数调整至观看最佳。 / 从PC到手机上的投影 / 由于大部分软件是将手机投影到电脑上,那么我们不妨换一个思路,PC 投影到手机上不妨看成是手机接管了电脑频幕,也就是微型计算机与远程计算机的通信。 查阅了相关文献后,我们利用了一款叫Teamviewer 的软件,该软件可以利用同一局域 网,实现远程计算机的相互接管:
TeamViewer用户界面
TeamViewer user interface 投影到手机上效果如下:
将PC屏幕投影到手机上
Project your PC screen onto your phone 由此即可用 VR 眼镜来体验虚拟现实沉浸式体验的输出。 - 数据手套设计 - / 数据手套原理介绍 / 数据手套是一种多模式的虚拟现实硬件,通过软件编程,可进行虚拟场景中物体的抓取、移动、旋转等动作,也可以利用它的多模式性,用作一种控制场景漫游的工具。从原理上可分为机械传动式和电磁通信式。机械传动主要是靠在手指关节处安装滑动变阻器,当手指弯曲或横向移动时,会带动滑杆改变滑动变阻器的值,从而改变电压值。每一个电压向量都可以映射为一个手势。但这种方法要求电阻的精密度很高,而且效果也与设备与人体的贴合性与人体手掌大小的差异性有很大关系。 于是我们采用了第二种方式,利用惯导定位,原理为在每一个关节点上都安装 IMU(6 轴/9 轴传感器)IMU(惯导单元)分为六轴和九轴惯导,六轴含有 3 轴加速度计、3 轴陀螺仪,这六个数据分别通过积分和数据融合可以算出惯导单元的三个方向上的欧拉角变化,但由于本身受重力影响,所以在 z 轴上存在固定的 9.8m/s2 的加速度初值,导致其 z 轴的欧拉角变化并不稳定。因此出现了九轴传感器,新添加了三轴磁力计,利用地磁数据来校准惯导单元的 z 轴欧拉角。常用的六轴传感器有 MPU6050、MPU6500,常用的九轴传感器有 MPU9250、jy-901 等。
九轴惯性导航单元原理图
Nine-axis inertial navigation unit schematic diagram 但首先摆在我们面前的难题就是通信问题: 一个单片机 NANO 只有一个 I2C 通道(两线),也就只能和一个设备或多个不同设备相连(因为相同设备的 I2C 地址都是一样的,如果将很多个相同设备并联到同一个 I2C 通道,那么访问从设备时会出现数据冲突的情况),如何区分不同设备就成了我们面临的下一个难题。 我们首先尝试了 jy-901,该传感器可以经过上位机程序修改 I2C 地址,那就可以将每个设备都改地址,那么在访问时就不会出现设备冲突的情况了。
jy-901 用户界面
jy-901 user interface 我们还找到了另一种解决方法,利用多串口通信设备 CJMCU-9548 模块: 该模块 I2C 地址为 0x70,定义了 8 个子通道,分别为 0x70~0x77,访问 9548 下挂的从设备时可以先访问 9548 的 I2 地址 0x70,接着再访问子通道 0x70~0x77,其内置的 I2C 转子通道 cpp 程序如下:uint8_t ClosedCube::Wired::TCA9548A::selectChannel(uint8_t channel) { uint8_t result = 0xff; if (channel >= 0 && channel < TCA9548A_MAX_CHANNELS) { Wire.beginTransmission(_address); Wire.write( ((uint8_t)1) << (channel+1)); _currentChannel = channel; result = Wire.endTransmission(); } return result; }
于是我们就此解决了通信难题。
然后针对于 MPU6050、jy-901、MPU9250 这几款惯导单元,我们都进行了尝试,并用 arduino NANO 进行与模型上的互传,并做总结:
Jy-901 效果:



jy-901 校准过程
image 13 jy-901 calibration process 但是准确度依然不能令人满意。 其原因在于校准过程中要让三个轴都逆时针转动两个完美的圆圈,在没有机器辅助的情况下难以做到。 我们之后又尝试了 MPU6050 的 DMP 读取,DMP 相当于对传感器烧录好了融合算法,每次读取的就是已经经过 dmp 处理好的欧拉角或者四元数。但是在调试过程中我们出现了卡帧的情况,推测是 MPU6050 回传速度不快,但单片机的扫描速度太快了,导致错开了时间窗。 后来我们又尝试了 9250,并对其库函数稍加了改动。因为其库函数自带卡尔曼滤波和与磁力计的融合算法,该方法名为 mpu.update():void update() { if (available()) { // On interrupt, check if data ready interrupt updateAccelGyro(); updateMag(); // TODO: set to 30fps? } qFilter.update(-a[0], a[1], a[2], g[0], -g[1], -g[2], m[1], -m[0], m[2], q); if (!b_ahrs) { tempCount = readTempData(); // Read the adc values temperature = ((float) tempCount) / 333.87 + 21.0; // Temperature in degrees Centigrade } else { updateRPY(); }}
该代码为已删减版本,由于原代码在上传数据后会往串口写入数据,PC 机接收数据就会接收一些不必要数据,但我们其实只是想要滤波之后的欧拉角或者四元数,于是删去了其串口写入的代码。
以及由于该库不自带四元数输出函数,于是需要对源文件中自己写入 getQuaternion()函数:并 在 头 文 件 声 明 以 及 往 关 键 字 文 件 中 声 明getQuaternion()。具体过程不加赘述。 同时在 unity 中编写接收数据驱动手指脚本。
实现效果如下:


MPU9250 实现效果(二)
MPU9250 to achieve the effect (2) 由于人体手本身是带有约束的,比如大部分人群无法单独操控手指第二指节的弯曲;在无名指、中指、食指伸直的情况下,只能操控小指进行第一指节的弯曲等等,于是我们最终对手进行了降阶处理,最终只采用了手腕、无名指、中指、食指 IMU 布局,而把小指和无名指看作一组辅助手指,共用无名指的数据。 与 Kinect 整体配合效果如下:整体实现效果(一)
Overall effect (1) 整体实现效果(二) Overall effect (2)整体实现效果(三)
Overall effect (3) - 场景搭建以及运动识别 - / 场景搭建 / 我们充分运用Unity国内开发者众多的优势,从网上下载了动态水、海底生物、海底气泡、海底植物资源,实现了一个美丽的大海的效果。对相关生物添加运动AI,使其看起来更加逼真。

Character motion recognition model
当人手臂模拟向前滑动时,会依次与这些小方块发生碰撞,当发生碰撞时,给予人体一个向前的加速度(考虑人体质量),即可实现向前的运动,同时由于人体的rigidbody脚本自带阻尼参数drag,调整参数为0.1,可实现较好的潜泳体验。 实现的脚本只提供了向前运动力,这是因为Kinect摄像机可以识别人体的转向,当人物转向时,这列碰撞块作为人体的子物体,也会随着人物一起转向,所以不必考虑横向移动无法实现的问题。 - 开发过程总结 - 1.经历了将近一个学期的开发,最终我们使用了 Kinect、自主研发的数据手套、VR 眼镜实现了一个可以在虚拟海洋中自由深潜的体感交互式 VR 项目。 2.我觉得我之前的任何一门专业课上的收获都没有我在这门课上所收获的多。从软件到硬件,由于是自主开发,所有的难题都是我们自己去寻找解决方案,主动吸取知识。也翻阅了很多博客、论文,有的可能恰好解决了我们的问题,有的也为我们另辟蹊径,还有的为我们拓宽了思路。为此我总结了一份技术文档 ,供学弟学妹们或者想要继续我们项目的同学做参考。 3.在开发的过程中,我很庆幸结识了李明同学作为队友,没有他在硬件上的支持,我绝对无法实现我开题时的目标,经过这次合作,我们培养了一起工作时的默契,相信以后也会有更多的合作。 4.本次开发我们遵循的是解决问题的思路,遇到问题后首先想的是以最快的速度去解决它,并形成自己的模块,写好接口、技术文档,固化整个实现流程,这也是我在此次开发过程中收获到的一个非常重要的知识点,这对我以后的工作学习有着莫大的帮助。【项目参考文献】
[1]Zhao Ca P. A survey on virtual reality. Sci China Ser-F: Inf Sci, 2009, 52: 348-400 [2]周忠,周颐,肖江剑.虚拟现实增强技术综述[J].中国科学:信息科学,2015,45(02):157-180. [3]王党校,焦健,张玉茹等.计算机触觉:虚拟现实环境的力触觉建模和生成[J].计算机辅助设计与图形学学报,2016,28(06):881-895. [4]吴景. 基于 Unity3D 的虚拟实验系统的设计[D].广东工业大学,2015. [5]周韬. 动作捕捉系统在虚拟现实中的应用[D].西安电子科技大学,2013. [6]周龙. 触觉手指传感器的设计与仿真研究[D].沈阳工业大学,2018. [7]陆熊,陈晓丽,孙浩浩等.面向自然人机交互的力触觉再现方法综述[J].仪器仪表学报,2017,38(10):2391-2399. [8]张凤军,戴国忠,彭晓兰.虚拟现实的人机交互综述[J].中国科学:信息科学,2016,46(12):1711-1736. [9]萧伟,孙富春,刘华平.机器人灵巧手的触觉分析与建模[J].机器人,2013,35(04):394-401. [10]沈冰. 虚拟现实头盔的延时感与立体感的研究[D].东华大学,2016. [11]王涌天,程德文,许晨.虚拟现实光学显示技术[J].中国科学:信息科学,2016,46(12):1694-1710. [12]王鲁建,李心瑶,柏树令.人手皮肤触觉小体分布的形态学[J].中国医科大学学报,2011,40(04):316-318. [13]张克敏. 基于虚拟现实的机器人仿真研究[D].重庆大学,2012. [14]李鉴,李源,冒东奎.基于虚拟现实的机器人仿真系统[J].宁夏工程技术,2008(02):127-129+132. [15] 尧 燕 . 基 于 虚 拟 现 实 的 平 行 四 边 形 机 器 人 仿 真 [J]. 机械,2013,40(07):39-41. 本文节选自 北航本科虚拟现实技术课程 开发实践作业 本文图片和部分文字来自公开文献 如有使用不当之处请私信告知 - END -相关阅读 /虚拟现实/-应用-美国航母着舰信号指挥官训练基于VR技术虚拟现实将成为人工智能的下一代训练环境南加州大学CLVR实验室在虚拟环境中教机器人组装宜家家具快了!空客将用基于VR头显的飞行训练器进行改装训练-原理-视觉深度感知的基本原理 /飞行仿真/-历史-飞行员培训从基于真飞机到基于模拟机20世纪60年代Ames研究中心的飞行模拟器们飞行模拟机视景系统的史前时代-价值-NASA驾驶舱间隔管理(FIM)飞行试验试飞员真飞前的地面培训 /航空资料整理/3U8633那34分钟的惊心动魄,已经过去两年了 /可视化之禅/美国人收入差距有多大世界制造业产值地图
