HTC Vive Pro eye 眼动数据简单获取

news/2024/11/28 6:35:19/

文章目录

  • 前言
  • 一、unity软件的安装
  • 二、OpenXR与SteamVR插件的安装
  • 三、SRanipaRuntime SDK的安装与使用
    • 读取数据
  • 总结


前言

本文旨在介绍如何使用HTC Vive Pro eye,结合Unity,读取到眼动的数据。假设文章内容面向的是此前从未接触过unity以及刚上手HTC Vive Pro eye的同学(这也是我对自己的个人定位),文章会尽量写的详尽一些,如果阅读内容已经掌握,可以选择跳过。
另外,本文仅对一些不方便搜索得知的内容进行说明,如有疑问可以自行Google或者百度。
最终成果为一个简单的Demo,可以在unity的Log栏中看到输出的信息。如下图所示,右下角的信息栏中可看到读取到的眼动数据。
右下角的信息栏中可看到读取到的眼动数据
另外,本文支持转载,转载时请注明作者与出处。希望大家在研究的过程中可以收获到分享与交流的快乐。
如发现错误,请通过评论或是私信的方式批评指正。

感谢b站的大佬邓布利多军,在个人空间中分享过几例测试demo,本文也是在其耐心的指导下完成的。由衷的表示感谢。


一、unity软件的安装

unity的官方网址
选择红框中的“Get Started”
在这里插入图片描述

在进入的页面中,以学生身份或是个人身份,进行unity账户的注册(此处略过)。之后运行unity客户端时,需要个人身份验证才可以正常使用。
在这里插入图片描述
unity 下载界面
在这里插入图片描述
推荐使用unity hub,即unity官方提供的管理平台进行不同版本的客户端的安装。

选择想要下载的unity版本进行下载安装即可(至于安装过程中工具包的具体选择,视个人需要,笔者是在windows平台,所以选择了与windows相关的工具包)。

以下为几点个人在过程中遇到的问题:
1、通常在安装unity各版本的客户端时,由于网络问题,“Document”经常下载失败或是下载进度为零,可以直接选择不进行下载。
2、如要使用其他人的unity项目,请注意版本的问题。通常若两个项目的unity版本不一致,会发生错误。

新建项目时,选择3D项目即可。
在这里插入图片描述



二、OpenXR与SteamVR插件的安装

在新建的项目中,选择“window”,在子菜单栏中选择Package Manager
在这里插入图片描述
在Unity Registry中选择OpenVR Plugin,点击右下方的install即可。
在这里插入图片描述
有两种方式安装SteamVR。一是通过网页
unity store 搜索 steam vr 后的结果,选择红框对应的插件,选择在unity中打开即可。
在这里插入图片描述
在这里插入图片描述
第二种方法近似,即在菜单栏的windows中选择Assert Store,步骤与一近似。

下载好steamVR插件后, 需要在package manager中的My Asserts中选择进行import。
在这里插入图片描述
到这里,基本的工作就已经做好了。
可以在steam VR官方提供的场景中进行交互测试。
在这里插入图片描述
在这里插入图片描述

三、SRanipaRuntime SDK的安装与使用

HTC Vive 官方提供了SDK
安装网址
两个SDK都需要安装,根据步骤一步一步来即可。
在这里插入图片描述
安装好两个SDK后,可以在安装目录中,看到如此的两个文件夹。
在这里插入图片描述
在SDK文件夹下存放着说明文档,C、Unity、虚幻环境的demo。
在这里插入图片描述

此处提供一个方便查阅SDK 中 各API的网址,也是官方提供的,在下图所示路径下。
在这里插入图片描述
在这里插入图片描述
而在SRainipal文件夹中,则存放着本次实验的关键应用。具体使用方法请阅读SDK中提供的Eye_SRanipal_SDK_Guide。
在这里插入图片描述

在如图所示的路径下,可以找到HTC官方提供的demo package。在unity中选择该package file,进行import。
在这里插入图片描述

导入后,可以在Project中看到如图所示红框对应的文件夹ViceSR,选择Scenes中的Eye,双击EyeSample_v2。
在这里插入图片描述
之后则可以在Hierarchy中看到如此的结构。
在这里插入图片描述
笔者此处在Gaze Ray Sample_v2和Avatar_Fairy_V2组件的Inspector进行了勾选。unity通过红框中的对勾即可以实现各组件的随意添加与移除。
在这里插入图片描述

读取数据

在Gaze Ray Sample v2组件中,挂载了当前脚本。在这里插入图片描述

在该脚本中,修改代码,结果为下面所示。
修改后,需要启动SRanipalRuntime,同时启动SteamVR,使得HMD正常运行。点击unity中的play,即可看到最终结果。

//========= Copyright 2018, HTC Corporation. All rights reserved. ===========
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Assertions;namespace ViveSR
{namespace anipal{namespace Eye{public class SRanipal_GazeRaySample_v2 : MonoBehaviour{public int LengthOfRay = 25;[SerializeField] private LineRenderer GazeRayRenderer;private static EyeData_v2 eyeData = new EyeData_v2();private bool eye_callback_registered = false;//此处为增加的变量private float pupilDiameterLeft, pupilDiameterRight;private Vector2 pupilPositionLeft, pupilPositionRight;private float eyeOpenLeft, eyeOpenRight;private void Start(){if (!SRanipal_Eye_Framework.Instance.EnableEye){enabled = false;return;}Assert.IsNotNull(GazeRayRenderer);}private void Update(){if (SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.WORKING &&SRanipal_Eye_Framework.Status != SRanipal_Eye_Framework.FrameworkStatus.NOT_SUPPORT) return;if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == true && eye_callback_registered == false){SRanipal_Eye_v2.WrapperRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye_v2.CallbackBasic)EyeCallback));eye_callback_registered = true;}else if (SRanipal_Eye_Framework.Instance.EnableEyeDataCallback == false && eye_callback_registered == true){SRanipal_Eye_v2.WrapperUnRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye_v2.CallbackBasic)EyeCallback));eye_callback_registered = false;}Vector3 GazeOriginCombinedLocal, GazeDirectionCombinedLocal;if (eye_callback_registered){if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.COMBINE, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { }else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.LEFT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { }else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.RIGHT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal, eyeData)) { }else return;}else{if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.COMBINE, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { }else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.LEFT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { }else if (SRanipal_Eye_v2.GetGazeRay(GazeIndex.RIGHT, out GazeOriginCombinedLocal, out GazeDirectionCombinedLocal)) { }else return;}Vector3 GazeDirectionCombined = Camera.main.transform.TransformDirection(GazeDirectionCombinedLocal);GazeRayRenderer.SetPosition(0, Camera.main.transform.position - Camera.main.transform.up * 0.05f);GazeRayRenderer.SetPosition(1, Camera.main.transform.position + GazeDirectionCombined * LengthOfRay);//以下为新增的部分//pupil diameter 瞳孔的直径pupilDiameterLeft = eyeData.verbose_data.left.pupil_diameter_mm;pupilDiameterRight = eyeData.verbose_data.right.pupil_diameter_mm;//pupil positions 瞳孔位置//pupil_position_in_sensor_area手册里写的是The normalized position of a pupil in [0,1],给坐标归一化了pupilPositionLeft = eyeData.verbose_data.left.pupil_position_in_sensor_area;pupilPositionRight = eyeData.verbose_data.right.pupil_position_in_sensor_area;//eye open 睁眼//eye_openness手册里写的是A value representing how open the eye is,也就是睁眼程度,从输出来看是在0-1之间,也归一化了eyeOpenLeft = eyeData.verbose_data.left.eye_openness;eyeOpenRight = eyeData.verbose_data.right.eye_openness;Debug.Log("左眼瞳孔直径:" + pupilDiameterLeft + " 左眼位置坐标:" + pupilPositionLeft + "左眼睁眼程度" + eyeOpenLeft);Debug.Log("右眼瞳孔直径:" + pupilDiameterRight + " 右眼位置坐标:" + pupilPositionRight + " 左眼睁眼程度" + eyeOpenRight);}private void Release(){if (eye_callback_registered == true){SRanipal_Eye_v2.WrapperUnRegisterEyeDataCallback(Marshal.GetFunctionPointerForDelegate((SRanipal_Eye_v2.CallbackBasic)EyeCallback));eye_callback_registered = false;}}private static void EyeCallback(ref EyeData_v2 eye_data){eyeData = eye_data;}}}}
}

该方法有些取巧,前文提到的“邓布利多军”是通过新建脚本实现的该功能。笔者也在进一步的尝试中。

总结

笔者从一头雾水,到如今简单的实现了该功能,要感谢官方论坛中许多位前辈,以及官方技术人员的技术支持。同时也要感谢众多曾在网络上分享技术,发表见解的前辈们。

最后,再次感谢“邓布利多军”。希望有更多未来的开发者们,加入技术分享的大家庭中。


http://www.ppmy.cn/news/249817.html

相关文章

HTC G12官方解锁步骤

终于找到了,http://htc.zol.com.cn/115/33080_1149673.html

唯美云海高清动态壁纸分享

唯美云海高清动态壁纸分享,景色十分壮观,壁纸整体的颜色渲染炫丽。更多Mac高清动态壁纸尽在Macw.com,欢迎下载体验! https://www.macw.com/desk/1031.html

5K高清流浪星球唯美Mac动态壁纸

the wander 是一款5K高清流浪星球唯美动态壁纸,画风细腻唯美,展现了宇宙的浩瀚与神秘。

唯美动态壁纸

唯美动态壁纸 动态壁纸让您轻松自己来设计图片(通过选择相册或者拍照来完成),实现:“我的桌面我做主”,本身提供漂亮,性感,可爱的超美女照片,给你视觉的冲击和精神的享受。具体使用&…

唯美图片下载

唯美图片下载 0)项目自述 ​ 本项目的高级项目是在中级项目的基础上完成的,相较而言,代码更加工整,功能更加强大,因此,本次只介绍高级项目的完成过程。 Ⅰ.初级项目 ​ 下载不完全,且容易出现…

img在单反号拼接中被解析为字符串

今天有同学问我他的代码为啥图片显示不出来(没想到本菜鸟也有被问的一天hhhhhhhh) 只能说是细节引发的惨案(划掉)o(╥﹏╥)o 以下是该小迷糊的代码 数据: 他是直接单反号拼接 ,但这里推荐使用模板引擎哦&am…

单反照片误删找回办法

前段时间是我们结婚5周年纪念,5年的时光说啊长不长,说短也不短,我们日子过得很平静,但也很温暖。说实话,一旦有了孩子,生活有的时候就由不得你了。好不容易等孩子上了幼儿园,我能喘口气了。老公…