我有一个应用程序可以记录用户在物体周围走动时的角度,同时将设备(最好)指向物体的中心。 角度根据用户命令重置 - 因此引用姿态被重置。
使用欧拉角会产生万向节锁,所以我目前正在使用四元数并以这种方式计算角度:
double angleFromLastPosition = acos(fromLastPositionAttitude.quaternion.w) * 2.0f;
这提供了良好的精度,如果设备的俯仰和偏航不改变,它可以完美地工作。换句话说,当角度显示为 360 度时,我最终到达的位置与圆的起点相同。
问题 1:如果设备的偏航和俯仰略有变化(用户没有直接指向对象的中心),angleFromLastPosition 也会发生变化。 我理解这部分,因为我的角度公式只是显示了 3D 空间中两个设备姿态之间的角度。
场景:
问题 1 是,如何使用四元数只计算设备的滚动,而忽略其他两个轴的变化(至少在一些合理的度数内)。
问题 2:如果我旋转一点然后完全卡住设备(在三脚架上,所以根本没有晃动),angleFromLastPosition 以每 10-20 秒 1 度的速度漂移,而且看起来没有是线性的。换句话说,它开始漂移得很快,然后就大大减慢了。有时我根本没有漂移 - 如果设备静止,角度是坚如磐石的。这让我无法理解正在发生的事情。
问题 2,这是怎么回事,我该如何处理漂移?
我浏览了很多文章和教程,目前四元数数学超出了我的范围,希望有人能够提供提示、链接或几行代码的帮助。
最佳答案
我已经对此进行了测试,它似乎可以满足您在问题 1 中寻找的内容,Andrei。
我将 homeangle 初始设置为 0,并在第一次通过后立即将 walkaroundAngleFromAttitude:fromHomeAngle: 返回的角度存储在 homeangle 中,以备将来使用。
我的测试包括使用引用框架启动设备更新:
[_motionManager
startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryZVertical
toQueue:operationQueue
withHandler:handler];
并使用以下在处理程序中调用的方法:
- (CMQuaternion) multiplyQuanternion:(CMQuaternion)left withRight:(CMQuaternion)right {
CMQuaternion newQ;
newQ.w = left.w*right.w - left.x*right.x - left.y*right.y - left.z*right.z;
newQ.x = left.w*right.x + left.x*right.w + left.y*right.z - left.z*right.y;
newQ.y = left.w*right.y + left.y*right.w + left.z*right.x - left.x*right.z;
newQ.z = left.w*right.z + left.z*right.w + left.x*right.y - left.y*right.x;
return newQ;
}
-(float)walkaroundRawAngleFromAttitude:(CMAttitude*)attitude {
CMQuaternion e = (CMQuaternion){0,0,1,1};
CMQuaternion quatConj = attitude.quaternion;
quatConj.x *= -1; quatConj.y *= -1; quatConj.z *= -1;
CMQuaternion quat1 = attitude.quaternion;
CMQuaternion quat2 = [self multiplyQuanternion:quat1 withRight:e];
CMQuaternion quat3 = [self multiplyQuanternion:quat2 withRight:quatConj];
return atan2f(quat3.y, quat3.x);
}
-(float)walkaroundAngleFromAttitude:(CMAttitude*)attitude fromHomeAngle:(float)homeangle {
float rawangle = [self walkaroundRawAngleFromAttitude:attitude];
if (rawangle <0) rawangle += M_PI *2;
if (homeangle < 0) homeangle += M_PI *2;
float finalangle = rawangle - homeangle;
if (finalangle < 0) finalangle += M_PI *2;
return finalangle;
}
这是使用来自 Finding normal vector to iOS device 的一些修改和扩展代码
编辑以处理问题 2 和问题 2:
这可能无法解决。我在其他应用程序(例如 360 全景)中看到过它,并阅读过陀螺仪等的错误读数。如果您尝试对其进行补偿,那么当某些真实的旋转运动被补偿代码抛出时,您当然会得到一种紧张的体验。就我过去几年的解释而言,这是一个基于硬件的问题。
关于ios - 态度改变 - 角度和轴问题 - 四元数数学,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16531281/
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我有以下内容:text.gsub(/(lower)(upper)/,'\1\2')我可以将\2替换为大写吗?类似于:sed-e's/\(abc\)/\U\1/'这在Ruby中可行吗? 最佳答案 查看gsub文档:str.gsub(模式){|匹配|block}→new_str在block形式中,当前匹配字符串作为参数传入,$1、$2、$`、$&、$'等变量将被适当设置。block返回的值将替换为每次调用的匹配项。"alowerupperb".gsub(/(lower)(upper)/){|s|$1+""+$2.upcase}
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
ruby中有这样的东西吗?send(+,1,2)我想让这段代码看起来不那么冗余ifop=="+"returnarg1+arg2elsifop=="-"returnarg1-arg2elsifop=="*"returnarg1*arg2elsifop=="/"returnarg1/arg2 最佳答案 是的,只需像这样使用send(或者更好的是public_send):arg1.public_send(op,arg2)这是可行的,因为Ruby中的大多数运算符(包括+、-、*、/、andmore)只需调用方法。所以1+2与1.+(2)相同
当我将IO::popen与不存在的命令一起使用时,我在屏幕上打印了一条错误消息:irb>IO.popen"fakefake"#=>#irb>(irb):1:commandnotfound:fakefake有什么方法可以捕获此错误,以便我可以在脚本中进行检查? 最佳答案 是:升级到ruby1.9。如果您在1.9中运行它,则会引发Errno::ENOENT,您将能够拯救它。(编辑)这是在1.8中的一种hackish方式:error=IO.pipe$stderr.reopenerror[1]pipe=IO.popen'qwe'#
当我尝试使用“套接字”库中的方法“read_nonblock”时出现以下错误IO::EAGAINWaitReadable:Resourcetemporarilyunavailable-readwouldblock但是当我通过终端上的IRB尝试时它工作正常如何让它读取缓冲区? 最佳答案 IgetthefollowingerrorwhenItrytousethemethod"read_nonblock"fromthe"socket"library当缓冲区中的数据未准备好时,这是预期的行为。由于异常IO::EAGAINWaitReadab
情况:我正在编写一个程序来求解素数。我需要解决4x^2+y^2=n的问题,其中n是一个已知变量。是的,必须是Ruby。我愿意在这个项目上花费大量时间。我最好自己编写方程式的求解算法,并将其作为该项目的一部分。我真正喜欢的是:如果任何人都可以向我提供指南、网站的链接,或者关于与求解代数方程特别相关的形式算法的构造的歧义消除,或者向我提供似乎你是读者它会帮助我完成任务。请不要建议我使用其他语言。如果您在回答之前接受我真的非常想这样做,我将不胜感激。该项目没有范围或时间限制,也不以营利为目的。这是为了我自己的教育。注意:我并不直接反对为Ruby实现和使用现存的数学库/模块/其他东西,但我更喜
我发现许多Rails应用程序主要针对企业、社交网络类型的Web应用程序。我看到有人将Ruby与一些出色的OOPS语言(如Java和C#)进行了比较,但我确实发现很难获得一些数学密集型应用程序。非常感谢任何知识渊博的输入(指向示例程序的链接等),其中轻松显示了语言的用法,就像快速启动或显示该语言如何用于各种数学问题一样。 最佳答案 不幸的是,Ruby并没有在数学和科学计算领域涉足太多。目前,有一个名为SciRuby的pre-alpha库它试图为Ruby带来更多面向数学的功能。他们正试图构建一个NumPy/SciPy等价物。SciRub