在 HoloLens 上还是在 Daydream 之外使用 Daydream 控制器?

     2023-03-30     167

关键词:

【中文标题】在 HoloLens 上还是在 Daydream 之外使用 Daydream 控制器?【英文标题】:Use Daydream Controller on HoloLens or outside Daydream? 【发布时间】:2016-11-21 22:48:11 【问题描述】:

Daydream 控制器非常棒,我们希望能够在我的 AR 应用中使用它。它通过蓝牙与 HoloLens 配对很好,但不确定我是否可以在 Unity 中查看它。

HoloLens 和 daydream 都需要各自的 Unity 技术预览。 gvr Controller code 在线,但似乎直接与 GVR C api 对话。

是否有可能在 Daydream 技术预览之外访问 Unity 中的 Daydream 控制器?

【问题讨论】:

顺便说一句,Doob 先生构建了一个 JS 版本的 @Dotphracker 的惊人代码答案,如下所示。 github.com/mrdoob/daydream-controller.js 【参考方案1】:

很可能在没有 GVR 服务的情况下访问 Daydream 控制器。事实上,我自己也在努力,可以分享我所知道的。

获取数据

使用蓝牙 gatt,您可以查看所有可用数据并订阅您想要的 ID。我不知道您将如何在 Hololens/Unity 中专门执行此操作。基本上你想:

    连接到设备 选择服务 (0000fe55-0000-1000-8000-00805f9b34fb) 选择特征 (00000001-1000-1000-8000-00805f9b34fb) 为其请求通知 (00002902-0000-1000-8000-00805f9b34fb)

Android 示例:

static final UUID DAYDREAM_CUSTOM_SERVICE = UUID.fromString("0000fe55-0000-1000-8000-00805f9b34fb");
static final UUID DAYDREAM_CHARACTERISTIC = UUID.fromString("00000001-1000-1000-8000-00805f9b34fb");
static final UUID CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
...
BluetoothGattService service = gatt.getService(DAYDREAM_CUSTOM_SERVICE);
BluetoothGattCharacteristic characteristic = service.getCharacteristic(DAYDREAM_CHARACTERISTIC);
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID);
descriptor.setValue( BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);

我建议查找蓝牙 Gatt 以了解有关服务和特性的更多信息。在开始编写代码之前,我还使用了 playstore 上的 BLE Scanner 应用来查看大量此类信息。

解析数据

设备提供 20 字节的数据来处理。它由时间、方向、加速度、原始陀螺仪、触摸位置和按钮标志组成。

示例(平放在桌子上):

5BEBFFB825FDB000041000B00000000000000000
63EFFFB825FDB000041000B00000000000000008
6C73FFB825FDB000041000B00000000000000038

示例(使用触摸板):

480BFE87EB00E801841000B00000000191FBA008
4F8FFE47EB00E800441000B0000003FEB1FBA038
5893FE27EB00EFFF041000B0000003FF51FBA000

字节定义如下:

Bytes:

  - 1: TTTT TTTT * T for time, loops
  - 2: TNNN NNKK * N is sequence number
  - 3: KKKK KKKK * IJK is orientation
  - 4: KKKI IIII
  - 5: IIII IIII
  - 6: JJJJ JJJJ
  - 7: JJJJ JOOO * MNO is acceleration
  - 8: OOOO OOOO
  - 9: OONN NNNN
  -10: NNNN NNNM
  -11: MMMM MMMM
  -12: MMMM CCCC * CDE for raw gyro
  -13: CCCC CCCC
  -14: CDDD DDDD
  -15: DDDD DDEE
  -16: EEEE EEEE
  -17: EEEX XXXX * All the X is the X touch position (8 bits)
  -18: XXXY YYYY * Y the Y touch position (8 bits)
  -19: YYYB BBBB * B the buttons (5 bits | [+][-][App][Home][Click])
  -20: Values vary

有了这个,我的触摸板和按钮可以与任何我可以为其构建应用程序的蓝牙设备配合使用。此外,您需要添加回功能以重置设备位置、控制音频等。

在 Android 上使用这个定义:

static final int CLICK_BTN = 0x1;
static final int HOME_BTN = 0x2;
static final int APP_BTN = 0x4;
static final int VOL_DOWN_BTN = 0x8;
static final int VOL_UP_BTN = 0x10;
float xTouch=0, yTouch=0;
...
final boolean isClickDown = (data[18] & CLICK_BTN) > 0;
final boolean isHomeDown = (data[18] & HOME_BTN) > 0;
final boolean isAppDown = (data[18] & APP_BTN) > 0;
final boolean isVolMinusDown = (data[18] & VOL_DOWN_BTN) > 0;
final boolean isVolPlusDown = (data[18] & VOL_UP_BTN) > 0;

final int time = ((data[0] & 0xFF) << 1 | (data[1] & 0x80) >> 7 );

final int seq = (data[1] & 0x7C) >> 2;

int xOri = (data[1] & 0x03) << 11 | (data[2] & 0xFF) << 3 | (data[3] & 0xE0) >> 5;
xOri = (xOri << 19) >> 19;

int yOri = (data[3] & 0x1F) << 8 | (data[4] & 0xFF);
yOri = (yOri << 19) >> 19;

int zOri = (data[5] & 0xFF) << 5 | (data[6] & 0xF8) >> 3;
zOri = (zOri << 19) >> 19;

int xAcc = (data[6] & 0x07) << 10 | (data[7] & 0xFF) << 2 | (data[8] & 0xC0) >> 6;
xAcc = (xAcc << 19) >> 19;

int yAcc = (data[8] & 0x3F) << 7 | (data[9] & 0xFE) >>> 1;
yAcc = (yAcc << 19) >> 19;

int zAcc = (data[9] & 0x01) << 12 | (data[10] & 0xFF) << 4 | (data[11] & 0xF0) >> 4;
zAcc = (zAcc << 19) >> 19;

int xGyro = ((data[11] & 0x0F) << 9 | (data[12] & 0xFF) << 1 | (data[13] & 0x80) >> 7);
xGyro = (xGyro << 19) >> 19;

int yGyro = ((data[13] & 0x7F) << 6 | (data[14] & 0xFC) >> 2 );
yGyro = (yGyro << 19) >> 19;

int zGyro = ((data[14] & 0x03) << 11 | (data[15] & 0xFF) << 3 | (data[16] & 0xE0) >> 5);
zGyro = (zGyro << 19) >> 19;

xTouch = ((data[16] & 0x1F) << 3 | (data[17] & 0xE0) >> 5) / 255.0f;
yTouch = ((data[17] & 0x1F) << 3 | (data[18] & 0xE0) >> 5) / 255.0f;

这可以进行优化,但它会分配除最后一个字节之外的所有位。代码value = (value &lt;&lt; 19) &gt;&gt; 19 也可以是value = (value &gt;&gt; 12) == 0 ? value : ~0x1FFF | value。只是将有符号位扩展为 32 位有符号整数。

我希望这会有所帮助,并期待其他答案。

-- 更新 2--

查看 gvr 代码后,我发现我之前的假设存在一些问题。它实际上是方向/加速度/陀螺仪。序列也多 1 位,时间少 1 位。我已经更新了字节定义和 android 示例。

此外,X、Y、Z 值需要缩放为浮点数。对于 Unity,您可以将整数放入 Vector3s,然后使用以下内容。对于 Unity,我还否定了 oriVector 中的 x 和 y。

Vector3 oriVector = new Vector3 (-xOri, -yOri, zOri);
...
oriVector *= (2 * Mathf.PI / 4095.0);
accVector *= (8 * 9.8 / 4095.0);
gyroVector *= (2048 / 180 * Mathf.PI / 4095.0);

然后要获得旋转,您只需要 oriVector。这实际上是一个轴角,存储为:单位向量*角度。

public Quaternion orientation = Quaternion.identity;
private Quaternion controllerPoseInSensorSpace = Quaternion.identity;
private Quaternion startFromSensorTransformation = Quaternion.identity;
...
// do this bit after getting the data and scaling it
float sqrMagnitude = oriVector.sqrMagnitude;
if (sqrMagnitude > 0) 
    // extract radian angle
    float w = Mathf.Sqrt (sqrMagnitude);
    // normalize vector
    oriVector /= w;
    // set orientation space
    setOrientationInSensorSpace (w,oriVector);

...
// then assign to a Transform
controller.localRotation = this.orientation;
...
// sets orientation with rotation offset
void setOrientationInSensorSpace(float angle, Vector3 axis) 
    // set orientation space
    this.controllerPoseInSensorSpace = Quaternion.AngleAxis(angle*Mathf.Rad2Deg,axis);
    // rotate based on centered offset
    this.orientation = this.startFromSensorTransformation * this.controllerPoseInSensorSpace;

...
// after holding home for 600 milliseconds
private void setStartFromSensorTransformation() 
    Vector3 angles = this.controllerPoseInSensorSpace.eulerAngles;
    // reset rotation on Y
    this.startFromSensorTransformation.Set(0,Mathf.Sin(-angles.y * Mathf.Deg2Rad / 2f), 0, Mathf.Cos(angles.y * Mathf.Deg2Rad / 2f));
    // could also reset all, easier to work with
    //this.startFromSensorTransformation = Quaternion.Inverse (this.controllerPoseInSensorSpace);

这就是让白日梦与常规蓝牙设备一起工作的所有内容。我还在 Unity3D 中使用了上述 C# 代码。

-- 更新 1--

添加了更完整的字节定义。之前缺少的值是陀螺仪、磁力计和加速度数据。它们每个都有三个 13 位有符号整数。时间位中似乎还有一个序列号。

继续前进

为了在其他平台上使用设备数据,您需要通过用于 9DoF/IMU 设备的类似公式来处理数据。我不知道如何解决这个问题。

最后一个字节

这可能是为标志保留的,我不确定其含义,但我有一些发现要列出。版本号是控制器的固件版本。

1.0.10 (out of the box): 0xF0/0xF8
1.0.10 (previously used with gvr): 0x00/0x08/0x38/0x51
1.0.15: 0x00/0x70

【讨论】:

感谢您分享您的发现!如果您取得更多进展,如果您可以分享您的代码,那就太好了。 ?? 谢谢!您在字节定义方面取得了进展吗? 是的,我已经更新了数据并相信除了最后一个字节之外它是完整的。要让它在 GVR 之外完全工作需要做一些工作,但我在 Google 上搜索的一些视频似乎显示了 9DoF/IMU 设备(至少是 arduino)的使用,甚至在 Unity 中也被使用。 顺便说一句,@Dotphracker 我们现在开始将您的代码移植到 HoloLens,因为内置输入法不是很可靠。自上次发布以来,您是否有任何可能有用的更新?甚至您可以分享一些代码/github链接?我们会非常感激的。 @Dotphracker 感谢您更新代码!都非常有帮助。我们正在使用 JS 传感器融合代码 here 并且仍然遇到一些问题。好奇是否可以在 github 上分享整个项目的代码?

在 HoloLens 2 中用手在平面上绘制

】在HoloLens2中用手在平面上绘制【英文标题】:DrawoverplaneusinghandinHoloLens2【发布时间】:2021-02-1316:34:33【问题描述】:我想在HoloLens2应用程序上实现一项功能,该功能允许用户在用户触摸的每个部分的特定表面上绘制/绘画。所... 查看详情

在 Hololens 上评估 OpenFilePicker 时调用 System.Exception

】在Hololens上评估OpenFilePicker时调用System.Exception【英文标题】:System.ExceptiongettingcalledwhenassessingOpenFilePickeronHololens【发布时间】:2021-05-2216:53:19【问题描述】:我将MRTK用于hololens应用程序,我需要选择用户放入其文档文件夹中的... 查看详情

在 Hololens (Unity3D) 上使用本机 C++ 库

】在Hololens(Unity3D)上使用本机C++库【英文标题】:UsingnativeC++librariesonHololens(Unity3D)【发布时间】:2021-07-2612:52:52【问题描述】:对于另一个项目,我正在尝试在Unity项目中的MicrosoftHololens上运行本机C++库(libsvm.dll)。为了尝试了解使... 查看详情

如果部署在 HoloLens2 上,Unity 中的蒙面精灵和模板缓冲区是不是仅在一只眼睛上可见?

】如果部署在HoloLens2上,Unity中的蒙面精灵和模板缓冲区是不是仅在一只眼睛上可见?【英文标题】:AremaskedspritesandStencilBuffersinUnityonlyvisibleononeeyeifdeployedonHoloLens2?如果部署在HoloLens2上,Unity中的蒙面精灵和模板缓冲区是否仅在... 查看详情

hololens开发手记-实现3d应用启动器(代码片段)

一直有人问我,第三方应用在HoloLens上可以实现3D启动图标吗?就像微软官方出的应用那样。在不久之前,这个问题的答案还是No。但是随着最新的Windowsbuild1803版本的发布,现在我们可以创建3D启动图标了。 实现方法 要实... 查看详情

电脑桌面画面实时传输到手机端或者hololens上显示(基于fmetpstream)(代码片段)

电脑桌面画面实时传输到手机端或者HoloLens上显示(基于FMETPSTREAM)最近在研究HoloLens,突发奇想在HoloLens上显示电脑画面,便做了各种尝试,使用过微软的Mirage,功能强大,相当于扩展屏幕,但是UWP... 查看详情

DataReader Hololens

】DataReaderHololens【英文标题】:【发布时间】:2018-01-2208:03:53【问题描述】:我正在尝试在Hololens上创建一个udp客户端/服务器。我在这个项目背后的想法是在iOS应用程序和Hololens之间进行通信。这是我的代码:usingSystem;usingSystem.C... 查看详情

hololens开发手记-构建2d应用building2dapps

HoloLens可以让我们在真实世界中看到全息图像内容。但是它本质上还是一台Windows10设备,这意味着HoloLens可以以2D应用形式运行WindowsStore里的大部分UWP应用。 目标平台设为Windows.Universal TargetingWindows.Universal 微软过去几... 查看详情

FilePicker 通过沉浸式 Unity 应用程序挂在 HoloLens 上

】FilePicker通过沉浸式Unity应用程序挂在HoloLens上【英文标题】:FilePickerhangsonHoloLenswithimmersiveUnityapp【发布时间】:2021-10-2904:42:23【问题描述】:我正在尝试找出是否可以在沉浸式Unity应用程序中使用本机HoloLens文件选择器。到目... 查看详情

无法从 HoloLens 连接到本地服务器 (XAMPP)

】无法从HoloLens连接到本地服务器(XAMPP)【英文标题】:CAn\'tconnecttoalocalserver(XAMPP)fromHoloLens【发布时间】:2019-08-0817:45:21【问题描述】:我正在尝试在HoloLens和XAMMP服务器之间建立连接。当我在unity上测试应用程序时,它运行良好... 查看详情

hololens微软hololens虚拟现实视频集

 混合虚拟现实(Hololens眼镜) 微软还是混合虚拟现实的行业领导者,Hololens眼镜在很多行业有了令人印象深刻的应用和演示。譬如:Hololens中文宣传片:https://pan.baidu.com/s/1jHRcD0MHololens展现无限可能(中文)https://pan.baidu.co... 查看详情

Unity 和 HoloLens 中的 Prefab 低于空间映射

】Unity和HoloLens中的Prefab低于空间映射【英文标题】:PrefabinUnityandHoloLensfallingbelowthespatialmapping【发布时间】:2019-12-0223:10:11【问题描述】:我正在使用HoloLens在Unity应用程序中工作,我在房间中放置不同的预制件,然后使用TapToPla... 查看详情

MRTK (V2) 需要更新 Hololens?

】MRTK(V2)需要更新Hololens?【英文标题】:MRTK(V2)NeedtoupdateHololens?【发布时间】:2019-04-1016:04:44【问题描述】:我正在尝试检查新的MRTK(V2),但我在构建时遇到了麻烦,首先在Unity上下载了WindowsSDK18362,现在我正在尝试在VisualStudio... 查看详情

hololens开发与性能优化实践

HoloLens中国版终于于5月底在中国上市,同时国内的技术社区经过一年的成长也有了很大的扩张,越来越多的开发者开始进入了HoloLens开发领域,尝试着使用混合现实(MixedReality)技术来构建属于未来的创新应用。 HoloLens开发... 查看详情

三星galaxys8得到daydream支持

...想的情况; 三星新的GalaxyS8智能手机将很快支持Google的Daydream移动VR生态系统的支持。     ?    ?该消息在今天GoogleI/O开发者大会舞台上公布。今年夏天 查看详情

无法在 Hololens 中读取文件

】无法在Hololens中读取文件【英文标题】:UnabletoreadfileinHololens【发布时间】:2020-04-0608:39:22【问题描述】:我正在开发一个需要在运行时读取hololens中的.obj格式文件的应用程序。确切地说,我要做的是将.obj文件保存在hololens中... 查看详情

吊打magicleap,微软hololens2不只为炫技

参考技术A2015年1月,微软HoloLens横空出世。四年后,在2月25日的MWC2019上,“HoloLens之父”Kipman登台宣布HoloLens2问世。受邀出席的雷锋网(公众号:雷锋网)现场第一时间发回报道《时隔四年,HoloLens2终于来了》。雷锋网也整理了HoloL... 查看详情

daydream队伍壮大:谷歌宣布华为mate9支持daydream

...17展会谷歌宣布在Pixel和MotoZ之后,增加移动虚拟现实平台Daydream的支持机型。华为Mate9保时捷版、Mate9Pro、中兴Axon7和华硕ZenfoneAR都支持Daydream平台。不过华为的这一代旗舰手机将不会支持Tango,谷歌表示他们正致力于把AR平台兼容... 查看详情