佟昭 张志利 梁丰 李向阳
摘要:虚拟手仿真是虚拟现实和人机交互领域的一个重要研究内容。分析并建立了包含16个自由度的虚拟手运动学模型。对5DT数据手套的标定和使用方法进行了分析。推导了基于线性对应关系的骨骼旋转控制基本方程。阐述了每个手指骨骼对象的控制方法,采用一种新的方法以解决拇指掌骨的运动控制问题,并编写了虚拟手控制脚本。在Unity中开发虚拟手控制场景,运行场景进行仿真验证,取得良好效果。
关键词:虚拟手;Unity;数据手套;控制脚本
中图分类号:TP391 文献标识码:A 文章编号:1009-3044(2015)21-0186-04
Research of Virtual Hand Simulation Based on Unity and 5DT Data Glove
TONG Zhao, ZHANG Zhi-li, LIANG Feng, LI Xiang-yang
(The Second Artillery Engineering University, Xian 710025, China)
Abstract: Virtual hand simulation is an important research topic in the field of virtual reality and human-computer interaction. A kinematic model of the virtual hand that contains 16 freedom degrees was obtained. Calibration and use of the 5DT data glove were analyzed. The linear relationship based fundamental equation of skeleton rotation was derived. The control method of finger skeleton objects were expounded. A new method was adopted to solve the problem of thumb metacarpal bone motion control. The virtual hand control script was written. The scene was built in Unity, which got a good result.
Key words: virtual hand; Unity; data glove; control script
虚拟手作为用户的手的替身,在众多虚拟现实应用中扮演了重要角色,它与虚拟世界进行交互,使其发生符合用户期望的变化,让用户沉浸在虚拟环境中完成预想的一系列操作,而虚拟手仿真技术的进步能够让用户可以在虚拟现实应用中获得更加优质的体验。
对于数据手套驱动的虚拟手仿真研究,已有不少相关研究:有的使用了旋转矩阵[1],有的每次都要通过代码寻找父物体[2],有的使用C++在Creator平台中进行开发,其编程的难度较大[3],有的还要二次开发程序集[4]。
Unity是一款跨平台3D游戏引擎,它使用C#或JavaScript语言,代码编写相对简单,且无需过问图形渲染过程,使得开发人员可以更专心于功能的设计。而且Unity编辑器提供了对场景的直接测试,场景正在运行的过程中还可以对其进行修改以查看更多的细节。
本文使用Unity开发了一个使用5DT数据手套对虚拟手进行运动控制的仿真程序。首先分析了手部结构和运动规律,建立了16自由度的手部运动学模型;推导了控制骨骼旋转的基本方程,对不同的骨骼控制方法进行分类讨论,提出了拇指掌骨旋转控制的新方法;在Visual Studio中编辑控制器脚本,在Unity中编辑项目并生成了可执行程序,取得了良好的仿真效果。
1 虚拟手运动学建模
手部共包含27块骨骼,其中,主要的骨骼和关节名称如图1所示(原始图片来源于http://sucai.redocn. com/tupian/570815.html)。
正常情况下,骨骼靠近人体的一端一直和关节连接,其约束模型可简化为铰链约束[6],骨骼绕靠近人体一端关节的旋转运动可以描述其局部运动,为此规定骨骼局部坐标系如下:以骨骼靠近手掌一端(近掌端)作为原点;从原点指向骨骼另一端的方向作为X轴正方向;在手进行抓握时,手指做屈伸运动的平面内,与X轴垂直指向外侧的方向作为Y轴正方向;以“右手定则”确定Z轴正方向;如图2所示。
为了建立虚拟手模型,考虑尽量简化骨骼运动,又要保留其运动特征,应合理限制各个手指骨骼旋转的自由度和角度范围。通过观察手指运动,骨骼绕关节做局部旋转的自由度和角度大致范围如表1所示。
2 使用5DT数据手套
2.1 5DT数据手套
本文采用的是5DT Data Glove Ultra 14数据手套,内置14个传感器,其外观及官方定义的传感器编号如图3所示。
2.2 标定方法
数据手套标定的出发点,是结合人手关节弯曲的角度范围,使用归一化的数据控制虚拟手骨骼旋转。数据手套驱动可将传感器的弯曲角度线性地转换为0到4095之间的整数(伸直为最小值,弯曲180度为最大值),这些原始数值可以通过SDK中FDTGloveUltraCSharpWrapper程序集的GetSensorRawAll方法记录到数组中[7]。之前已经讨论过,手指运动具有一定范围,而手指的极限位置会形成传感器的最小弯曲和最大弯曲,从而得到传感器的最小数值[rLow]和最大数值[rUp]。SDK中的标定方法SetCalibration,通过式(1)将当前的原始数值[rVal]线性映射为[0,1]区间内的数值[scaled],从而实现归一化。
[scaled=0,rVal 当手动标定出现错误,使[rUp≤rLow]时,[scaled]的计算如式(2)。 [scaled=01,rVal≤rLow,rVal>rLow] (2) 3 Unity场景开发 3.1 Unity项目开发流程 1)导入资源:项目开发所需要的一切资源都要放在Assets文件夹中才能被Unity编辑器使用,比如三维模型、贴图、SDK程序集和脚本文件等。为了更有效地管理资源,通常在Assets文件夹中创建几个子文件夹,将各种资源分门别类存放进去,例如Scripts(脚本)、Plugins(插件)、Models(模型)、Texture(贴图)等。由于使用的是64位版本的Unity,因此需要将64位的数据手套驱动文件fglove.dll也放入Assets文件夹。 2)编辑脚本:Unity支持用JavaScript和C#两种语言编写脚本。JavaScript语句比较精简,易于上手,并且Unity对它的执行效率进行了优化。而C#语言通用性比较强,可以使用面向C#的SDK进行开发。支持使用内置的MonoDevelop和其他编辑器(比如Microsoft Visual Studio)进行开发。本文基于C#语言编写了虚拟手控制脚本,将在3.2节中详细介绍。 3)编辑和测试场景:将导入的各种资源放置到场景中,在场景中添加声光,设置模型材质,为游戏对象添加组件等,搭建虚拟现实环境。 将控制脚本拖拽至虚拟手对象的查看器空白处,即可为虚拟手添加脚本。点击运行按钮测试场景运行情况。 4)构建和执行:Unity支持多达20种软硬件平台的游戏开发,在其“File->Build Settings”下可以设置其输出平台。本文选择x86_x64构架的Windows平台。 3.2 虚拟手控制脚本 3.3.1 引用命名空间 在脚本开头用using关键字声明所引用的程序集FDTGloveUltraCSharpWrapper,之后便可以使用程序集内的各种方法。在类的开头,定义和初始化脚本需要的字段,设定骨骼编号分组(下面“虚拟手控制”中会提到)和骨骼旋转角度范围。 3.3.2 开始 在Start()方法中实现脚本的初始化,有以下内容。 1)初始化手套实例: 用glove = new CfdGlove()和glove.Open ("USB0")两个语句新建并初始化手套实例。 2)映射骨骼: 本文使用Transform类型的数组lHandBones[]引用虚拟手手指的15个骨骼。为了使数据手套传感器控制所对应的虚拟手骨骼旋转的这种映射关系在代码中更加直观,使场景中的骨骼对象在lHandBones[]中的编号尽量与数据手套对应位置上的传感器编号一致,对照图1设定游戏场景骨骼到lHandBones[]元素的映射关系如表2所示。 3)标定手套 用caliFileLoaded = glove.LoadCalibration (“文件完整路径”)语句加载在GloveManager中保存的标定文件,并用bool类型的caliFileLoaded字段记录标定文件是否成功加载。 3.3.3 虚拟手控制 通过Update()方法,实现了在每一个游戏帧里读取数据手套传感器数值、并映射为场景中骨骼旋转的角度。本小节首先推导了控制虚拟手骨骼旋转的基本方程,而后讨论了各种类型骨骼的控制方案,最后介绍了如何通过代码实现。 1)虚拟手骨骼旋转控制基本方程 设传感器的最小弯曲角度为[angleLow],最大弯曲角度为[angleUp],传感器的当前弯曲角度为[angle],若数据手套传感器的数值和其弯曲角度成线性关系,则存在实数[k]使得 [angle-angleLow=k(rVal-rLow)] (3) 可以推出 [angle=(angleUp-angleLow)?scaled+angleLow] (4) 设骨骼旋转的最小弯曲角度为[handLow],最大弯曲角度为[handUp],当前骨骼旋转角度为[hand],若骨骼旋转角度与传感器弯曲角度成线性关系,即存在实数[q]使得: [hand-handLow=q(angle-angleLow)] (5) 则同理可推出 [hand=(handUp-handLow)?scaled+handLow] (6) 由式(6)即得到了基于线性对应关系的虚拟手骨骼旋转控制基本方程。 2)虚拟手骨骼旋转控制方案 控制虚拟手骨骼旋转的总体方案是,将骨骼对象的编号进行分组:0、1、4、6、7、10、13号为第一组,5、8、11、14号为第二组,3、9、12号为第三组,2号为第四组,每个组内的骨骼控制方法是相近的。第一组和第二组骨骼情形简单,编号分别用一个数组存放,便于使用foreach语句遍历组内编号进行控制,其他两组逐个骨骼进行控制,取表1中的角度范围作为虚拟手骨骼的旋转范围,具体方法如下。 ① 0、1、4、6、7、10、13号骨骼只有Z一个自由度,且其靠近手掌一端的关节处有一个同样编号的传感器,则根据式(6),由此传感器数据控制其Z轴旋转。 ② 5、8、11、14号骨骼只有Z一个自由度,但没有对应的传感器,根据手部运动规律[8],其旋转角度分别规定为4、7、10、13号骨骼旋转角的2/3。
③ 3、9、12号骨骼有Y、Z两个自由度,且其靠近手掌一端的关节处有一个同样编号的传感器,由此传感器数据按式(6)控制其Z轴旋转,此关节靠近中指一侧、与相邻关节之间有一个传感器,由此传感器数据控制骨骼的Y轴旋转。由于规定6号骨骼无Y向旋转,可作为参考,因此3号和9号的Y轴旋转由数据手套的5号和8号传感器按式(6)控制,而12号的Y向旋转是它相对于9号的Y向旋转和9号自身Y向旋转的叠加,12号相对于9号的Y向旋转可由11号传感器数值经式(6)计算得到。
④ 2号骨骼有X、Y、Z三个自由度,而只有2号传感器与其直接对应。与2号传感器相邻的是0号传感器,如果找到0号传感器数值与2号骨骼的旋转角度之间的关系,就可以用0号和2号传感器共同控制2号骨骼的旋转。基于此,借助GloveManager做如下分析。
首先使用将传感器进行适当标定,而后单独观测0、2号传感器数值,通过两种手部运动研究拇指指骨的控制方法:(a)保持拇指近节指骨和末节指骨不转动,沿Y轴转动拇指掌骨,使拇指指甲近似在同一平面内移动,得到图4中a段曲线;(b)保持拇指末节指骨不转动,沿Z轴转动拇指掌骨,使拇指在XOY平面内进行自然的屈伸运动,得到图4中b段曲线。
观察a段曲线发现,拇指掌骨的Y向旋转对2号传感器数值有明显影响,而对0号的影响并不明显,因此可以用2号传感器的数值控制拇指掌骨的Y向旋转。观察b段曲线发现,拇指掌骨单纯沿Z轴旋转时,0、2号传感器数值都有明显变化。若单纯用2号传感器的数值控制拇指掌骨的Z向旋转,会导致拇指掌骨沿Y轴旋转时传感器数值会同时带动虚拟手拇指掌骨沿Z向旋转。
解决办法是,用2号传感器的归一化数值和比例因子[f2]的乘积,减去0号传感器数值归一化和比例因子[f0]的乘积,将差值限定在[0,1]区间内,若比0小则为0,比1大则取1。这个差值作为[scaled]值代入式(6)计算2号骨骼对象Z向旋转角,本文设置[f2]取1.3,[f0]取0.3。另外,通过观察发现,2号骨骼的X向旋转与Y向旋转成线性关系,因此可以用1减去2号传感器归一化数值的差值控制其X向旋转。
3)代码实现
① 令字段获取手套传感器数值。用GetSensorScaledAll (ref values)语句得到的长度为20的数组values中,前14个元素中的values[i]即为图3中编号为i的传感器的归一化数据。
② 传感器数值换算为角度。根据式(6),计算各传感器所相应自由度上的旋转角度。
③ 根据计算结果旋转骨骼对象。设游戏对象名为obj,则obj.transform.localRotation是一个四元数(Quaternion)类型变量,描述了obj的局部坐标系相对于其父级对象的局部坐标系的旋转。Quaternion.Euler()方法将绕三个轴分别转动一定角度(单位为度)的一个旋转转换为一个四元数。通过lHandPalm.localRotation = Quaternion. Euler (x,y,z)语句,就实现了让LeftHand对象绕父级对象局部坐标的z轴旋转z度、x轴旋转x度、绕y轴旋转y度(以这样的顺序[9])。根据控制方案,将②中计算的角度值作为上述语句中的相应的y或z,则可实现骨骼对象在场景中的旋转。
3.3.4 界面显示
在OnGUI()方法中使用GUI.Label方法显示标定文件是否成功加载,若caliFileLoaded字段为真则显示“Calibration File Loaded”,否则显示“Calibration File Loading Failed”。
4 仿真验证
用GloveManager对数据手套进行标定后保存标定文件,并在虚拟手控制脚本的检视器中输入其完整路径,点击运行按钮,各种手势下的仿真效果如图5所示。总体上运动跟踪的效果较好,但是对于大拇指掌骨在某些方位下旋转的控制仍然令用户困惑,说明在数据手套传感器数量不足的情况下,大拇指掌骨的运动重定向仍需要进一步优化。
5 结论
本文在Unity中开发了一个用5DT数据手套控制虚拟手活动的场景,并对其关键技术和实现进行了阐述,对开发过程中遇到的一些问题提出了解决办法,最后运行场景取得了较好效果。今后将研究利用Unity实现虚拟手抓取物体,以提高对数据手套的利用效果。
参考文献:
[1] 安明, 陈善广, 刘玉庆. 基于数据手套的虚拟手精确建模的研究与实现[J]. 计算机仿真, 2010(1): 241-244.
[2] 张志纯, 杨晓文, 况立群, 等. 基于Virtools和5DT数据手套的手势仿真研究[J]. 科学技术与工程, 2015(4): 140-144.
[3] 陈冠宇, 李雯文, 佘建国. 船舶机舱虚拟环境中虚拟手的介入操控[J]. 上海海事大学学报, 2014(04): 50-54, 84.
[4] 罗迎. Quest3D虚拟人机交互系统中5DT数据手套的应用[J]. 科学技术与工程, 2011(4): 855-859.
[5] 宣雨松. Unity3D游戏开发[M]. 北京: 人民邮电出版社, 2012.
[6] 李澍, 刘毅,王念东. 虚拟环境中的多手指抓取操作技术[J]. 计算机辅助设计与图形学学报, 2010,22(10): 1728-1733.
[7] 5DT. 5DT Data Glove Ultra Manual [EB/OL]. 2011/2015-04-19. http://www.5dt.com/?page_id=34.
[8] 殷磊, 韩静, 王烨, 等. 虚拟现实环境下虚拟手控制技术研究[J]. 系统仿真学报,2009(2): 488-451.
[9] 游戏蛮牛. Unity脚本手册[EB/OL]. 2014/2015-04-28. http://www.unitymanual.com/m/Script/index.htm