Google VR开发-Cardboard VR SDK头部追踪实现(罗德里格旋转公式)
一、罗德里格旋转公式
这个图证明:
进而证明
二、罗德里格旋转矩阵
三、罗德里格旋转矩阵公式在VR中的应用
Matrix.multiplyMM(mRightEye.getTransform().getEyeView(), 0,mRightEyeTranslate, 0, mHeadTransform.getHeadView(), 0);
// 获取头部姿态矩阵mHeadTracker.getLastHeadView(mHeadTransform.getHeadView(), 0);
其实现为:
public void getLastHeadView(float[] headView, int offset){if (offset + 16 > headView.length) {throw new IllegalArgumentException("Not enough space to write the result");}//如果定义了卡尔曼滤波对象synchronized (mTracker) {//首先计算出当前时间距离上次预测时间的差值double secondsSinceLastGyroEvent = (System.nanoTime() - mLastGyroEventTimeNanos) * 1.E-09D;Log.d(TAG,"secondsSinceLastGyroEvent="+secondsSinceLastGyroEvent);//实际上有60帧每秒,30帧算的话,一帧33ms,所以这里是提前预测一帧//然后加上提前预测的时间33msdouble secondsToPredictForward = secondsSinceLastGyroEvent + 0.03333333333333333D;//这里返回的是一个double类型的数组,double[] mat = mTracker.getPredictedGLMatrix(secondsToPredictForward);for (int i = 0; i < headView.length; i++) {mTmpHeadView[i] = ((float)mat[i]);}}Matrix.multiplyMM(headView, offset, mTmpHeadView, 0, mEkfToHeadTracker, 0);}
可以看到这里计算了当前时间距离上次预测时间的差值,然后加了一个提前预测时间33ms,之后调用了getPredictedGLMatrix
public double[] getPredictedGLMatrix(double secondsAfterLastGyroEvent){//deltaT,时间差double dT = secondsAfterLastGyroEvent;Log.d(TAG,"dT="+dT);Vector3d pmu = getPredictedGLMatrixTempV1;//应该理解为向量乘以一个常量,这个常量就是提前预测的时间,但为什么乘以一个负的呢?Log.d(TAG,"lastGyro=("+Float.toString(lastGyro[0])+","+Float.toString(lastGyro[1])+","+Float.toString(lastGyro[2])+")");pmu.set(lastGyro[0] * -dT, lastGyro[1] * -dT, lastGyro[2] * -dT);Matrix3x3d so3PredictedMotion = getPredictedGLMatrixTempM1;//Log.d(TAG,"so3PredictedMotion="+so3PredictedMotion.toString());//这里返回的so3PredictedMotion就是一个Rodrigues矩阵So3Util.sO3FromMu(pmu, so3PredictedMotion);Matrix3x3d so3PredictedState = getPredictedGLMatrixTempM2;//Log.d(TAG,"getPredictedGLMatrix,so3SensorFromWorld="+so3SensorFromWorld.toString());Matrix3x3d.mult(so3PredictedMotion,so3SensorFromWorld,so3PredictedState);//so3PredictedState还是一个3x3的矩阵,这里把它放到一个4x4矩阵中return glMatrixFromSo3(so3PredictedState);}
//这个函数封装rodrigues算法,只不过这里根据角度的大小//来调节kA和kB的值。角度比较大的时候,和公式上比起来,KA多除了一个θ,kB多除了一个θ平方,不知道原因是什么根据。public static void sO3FromMu(Vector3d w, Matrix3x3d result){//向量点乘等于w向量模长的平方double thetaSq = Vector3d.dot(w, w);//如果这里是求theta,就要用点积再除以两者的模再求arccos//开平方,就是求得w向量的模长double theta = Math.sqrt(thetaSq);Log.d(TAG,"w=("+w.x+","+w.y+","+w.z+")"+",theta="+theta);double kA, kB;if (thetaSq < 1.0E-08D) {//Log.d(TAG,"thetaSq < 1.0E-08D");kA = 1.0D - 0.16666667163372D * thetaSq;kB = 0.5D;}else{if (thetaSq < 1.0E-06D) {//Log.d(TAG,"thetaSq < 1.0E-06D");kB = 0.5D - 0.0416666679084301D * thetaSq;kA = 1.0D - thetaSq * 0.16666667163372D * (1.0D - 0.16666667163372D * thetaSq);} else {//Log.d(TAG,"thetaSq > 1.0E-06D");double invTheta = 1.0D / theta;kA = Math.sin(theta) * invTheta;kB = (1.0D - Math.cos(theta)) * (invTheta * invTheta);}}//根据公式,w是一个单位向量,因为每一项都要除以一个模长,所以这里除以模长就放到了kA和kBrodriguesSo3Exp(w, kA, kB, result);}
函数sO3FromMu其实就是对罗德里格矩阵求法的一个封装,其中rodriguesSo3Exp函数就是罗德里格矩阵:
private static void rodriguesSo3Exp(Vector3d w, double kA, double kB, Matrix3x3d result){//求得向量的平方double wx2 = w.x * w.x;double wy2 = w.y * w.y;double wz2 = w.z * w.z;//result.set(0, 0, 1.0D - kB * (wy2 + wz2));result.set(1, 1, 1.0D - kB * (wx2 + wz2));result.set(2, 2, 1.0D - kB * (wx2 + wy2));double a, b;a = kA * w.z;b = kB * (w.x * w.y);result.set(0, 1, b - a);result.set(1, 0, b + a);a = kA * w.y;b = kB * (w.x * w.z);result.set(0, 2, b + a);result.set(2, 0, b - a);a = kA * w.x;b = kB * (w.y * w.z);result.set(1, 2, b - a);result.set(2, 1, b + a);}
public double[] getPredictedGLMatrix(double secondsAfterLastGyroEvent){//deltaT,时间差double dT = secondsAfterLastGyroEvent;Log.d(TAG,"dT="+dT);Vector3d pmu = getPredictedGLMatrixTempV1;//应该理解为向量乘以一个常量,这个常量就是提前预测的时间,但为什么乘以一个负的呢?Log.d(TAG,"lastGyro=("+Float.toString(lastGyro[0])+","+Float.toString(lastGyro[1])+","+Float.toString(lastGyro[2])+")");pmu.set(lastGyro[0] * -dT, lastGyro[1] * -dT, lastGyro[2] * -dT);Matrix3x3d so3PredictedMotion = getPredictedGLMatrixTempM1;//Log.d(TAG,"so3PredictedMotion="+so3PredictedMotion.toString());//这里返回的so3PredictedMotion就是一个Rodrigues矩阵So3Util.sO3FromMu(pmu, so3PredictedMotion);Matrix3x3d so3PredictedState = getPredictedGLMatrixTempM2;//Log.d(TAG,"getPredictedGLMatrix,so3SensorFromWorld="+so3SensorFromWorld.toString());Matrix3x3d.mult(so3PredictedMotion,so3SensorFromWorld,so3PredictedState);return glMatrixFromSo3(so3PredictedState);}
四、罗德里格矩阵与卡尔曼滤波的配合
Google VR开发-Cardboard VR SDK头部追踪实现(罗德里格旋转公式)相关推荐
- unity+Cardboard SDK VR开发Cardboard Unity SDK讲解
Cardboard Unity SDK Reference中文翻译版,水平有限请以英文版为准. Plugin Reference Package 内容 Unity插件包包含以下内容: 脚本 · ...
- Google VR开发-Cardboard VR SDK反畸变实现
上一篇文章分析了Cardboard SDK的生命周期设计. 这里我们看下畸变部分的实现. Cardboard中将畸变这部分封装成了一个Distortion类和DistortionRenderer类. ...
- VR开发基础—VR视频
1.导入谷歌官方提供的库: commonwidget.common.panowidget(全景图).videowidget(视频) 或者添加依赖: dependencies { compile pro ...
- 【获奖公布】走进VR开发世界——我们离开发一款VR大作还有多远?
此次征文比赛以分享VR开发经验为核心,在对所有参赛文章进行审核后,以"开发"为先,评选出一.二.三等奖,共9名. 获奖名单 奖项 文章 作者 评语 一等奖 <VR游戏交互开发 ...
- GOOGLE VR SDK开发VR游戏,VR播放器之一
最近一年来,VR虚拟现实和AR增强现实技术的宣传甚嚣尘上.其实VR,AR技术很早就有了,一直没有流行开来,不可否认价格是影响技术推广的最大壁垒.谷歌对VR最大的贡献是提供了廉价的谷歌眼镜,按照GOOG ...
- GOOGLE VR SDK开发VR游戏,VR播放器之中的一个
近期一年来,VR虚拟现实和AR增强现实技术的宣传甚嚣尘上.事实上VR,AR技术非常早就有了,一直没有流行开来.不可否认价格是影响技术推广的最大壁垒. 谷歌对VR最大的贡献是提供了便宜的谷歌眼镜,依照G ...
- 二、VR全景图显示器开发 ---- Android VR视频/Google VR for Android /VR Pano/VR Video
原文地址: http://blog.csdn.net/qq_24889075/article/details/52128463 http://www.jianshu.com/p/104251a3153 ...
- 谷歌 Daydream VR 开发工具
现在,谷歌的虚拟现实平台 Daydream 已经准备好迎接开发者的到来,这得益于新发布的 Googe VR SDK(开发者工具包),它在周四结束测试正式上线.谷歌表示,这套工具包将让开发者能够为支持 ...
- 走进VR开发世界(4)——走进VR游戏开发的世界
注: 原文2016年2月发表于公司内部社区, 最近才由同事转载出来, 删去了文中引用的一些内部文章和视频. 在这里我也只是把外网版本转过来, 留做备份. 背景介绍 我们组在2014年下半年尝试开发了一 ...
最新文章
- print、printf、println在Java中的使用
- 蓝牙的自适应跳频技术
- SQL Server R2 地图报表制作(四)
- pytorch实现L2和L1正则化regularization的方法
- .NET内存性能分析指南
- 接口测试之HTTP协议详解
- 发一个多CPU中进程与CPU绑定的例子
- 大数据_Flink_数据处理_案例WorldCount_批处理版---Flink工作笔记0008
- 计算机应用基础课改期望,《计算机应用基础》课改总结.doc
- springboot配置手动提交_kafka教程-springboot消费者-手动提交offset
- 飞机器减震器的matlab建模和仿真模拟
- 人在职场,身不由己?
- 计算机怎么格式化电脑吗,电脑怎么格式化
- Camera 图像处理原理分析- 色彩篇 二
- 关于鸿蒙开发系统组件的摘抄及运用1
- html阅读封面代码,HTML5/SVG 书本封面设计
- 295-光纤数据收发 隔离卡 加速计算卡 基于 Kintex-7 XC7K325T的半高PCIe x4双路万兆光纤收发卡
- 如何下载IEEE论文
- 全球互联网排名_全球互联网的梦想已死
- Your anti-virus program might be impacting 防火墙