HTC 重力感应传感器编程资料总结

HTC 重力感应传感器编程资料总结

         与硬件结合的软件编程总是比纯软件多出很多乐趣,比如给智能车单片机编程,比如能利用到重力传感器(gsensor)的手机编程。不过能做到更多事情的同时,也会面对更多麻烦,比如智能车要考虑到千奇百怪的外界环境,而重力传感器也要考虑到硬件误差的问题。好在只要你不拿手机编写比如精确测量重力加速度之类的程序(这一点后面还要讨论),一般的软件、游戏可以完全不考虑误差。现在智能设备上重力感应程序满天飞,即使一个普通的软件也希望能做一些比如晃一晃屏幕就更换界面之类的效果。我有幸在实习的过程中碰到一个这样的题目,从零开始对HTC(dopod)上的gsensor编程进行了一番探索,现在把自己学到的东西总结一下。事先声明,本人大三,经验甚少,甚至连windows api都是新学的,因此文字中可能会出现不准确的论断或不高效的写法,还请大家指正。

    本文的废话可能比较多,主要是对一些细节问题进行了探讨,以及提出了一些可能是新点子的想法,大家可以先看代码,文字酌情浏览:)

         先晒一下本人的测试环境:

l  visual studio 2008:参考程序1的运行需要vs2008

l  Windows Mobile 6 Professional SDK Refresh下载地址

当然里面的模拟器不能模拟gsensor,只能看看界面对不对。

l  HTC s900c:这是拜公司所赐的测试机。没错,就是右上角有一坨不明物标志的这个。

 

HTC 重力感应传感器编程资料总结_第1张图片

 

参考网页及程序:

1.         http://www.cnblogs.com/procoder/archive/2009/07/28/1532592.html

这个网页介绍了一些关于gsensor的背景知识,值得一看。另外,还提供了一个测试程序。这个程序比较长,不过所提供的功能仅仅是显示三个文本框而已。用到了一些比较高级的c++知识,我并没有完全看懂。这个程序试图将SamsungHTCgsensor调用整合到一个类里,不过他的GSensorFactory::CreateGSensor() 函数似乎存在一些问题:假如SamsungMobileSDK_1.lib不存在的话,程序不能编译通过;如果存在的话,不管是什么手机,程序都会去调用Samsung的库。改正方法是,如果只管HTC的话,把上面提到的函数中第一个try块注释掉就可以了。我觉得这个程序编的有些过于复杂了,只实现取加速度值没必要这么多语句。

 

2.         http://download.csdn.net/source/901809#acomment

这个程序就简单许多,也给了我不少帮助。我的SensorInit.cpp中几个函数就是得自于这个程序(话又说回来,这几个函数最初出自于哪位大神也不得而知)。这个程序不仅仅演示了HTC的重力传感器调用,还演示了一些触摸键的传感器用法(并非所有手机都有这些触摸键)。

 

3.         http://download.csdn.net/source/1565406

这就是我下面要详细说的,我自己编的程序。这个工程包含了两个项目,第一个项目中封装了一个被我取名为CHTCGSensor的类(是不是被一排不知所云的大写字母弄晕了?我只不过是在模仿vc的命名风格…)。这个类提供了对HTC手机重力感应传感器进行读取和处理的基本操作,不过如果将初始化语句修改一下,放到其他windows mobile手机中(如Samsung)也能用。使用时应先调用InitSensor,然后根据需要调用RegisterStateEventRegisterChangeEventRegisterShakeEvent并进行相应的消息处理,不过一般来说只需要调用GetGVector就足够了。这个项目被设定为生成.lib文件。如果想详细了解每个方法可参阅源代码和这个简单的文档(要真想利用这个类最好还是看一下)。第二个项目是这个类的一个Tester。某些更详细的东西将在下面讨论。

 

关于HTCSensorSDK.dll的问题:

         浏览了上面源代码的同志可能已经发现,这几个程序都离不开一个动态链接库HTCSensorSDK.dll。我承认,在网上找这个库就花了我一天的时间,而编写程序只不过花了两天多而已。这个库,网上的版本不少,不过在我的s900c上却没有一个能用的。我的程序压缩包里提供的是从HTC diamond2手机的windows目录下复制的,也不知道适用范围有多广,反正我自己是能用。另外这里还有一位老兄将这个库反汇编成c++了,大家可以参考一下库里面还有什么自己用的上的函数。顺便总结一下,可能是废话,那就是中文搜不到的去英文网站搜;自己要实现什么功能,先找找已经实现了类似功能的软件,会帮你避免不少麻烦;低版本的平台运行不了的软件或找不到的库,就去找高版本的平台试试看。

 

下面是传说中的正文:

一、对重力传感器的一点深入探讨

         手机中加装各种传感器,是一个天才的主意,也是一种必然。你说传感器现在做的越来越小越来越便宜,不就是为了嵌入各种设备、走进千家万户么?从话筒(这也算一种传感器吧…)、光照传感器到触摸传感器、GSensor,听说iPhone还装了陀螺仪,听说而已,我没有亲见。总之我们国家的山寨手机要想创新倒不妨在这方面打打主意(这都扯到哪去了)。

         言归正传。重力传感器,在我看来叫做加速度传感器更确切一点,因为它并不单是为了检测重力而生的。我把它想象成这样一种模型,一个小正方体重物,六面都贴着压力传感器,当重物想要向右移动时,左面的传感器就会感受到压力从而传出信号。同理,因为重物一直受着重力,这个重力会按照平行四边形法则分摊到某几个传感器上,因此靠几个传感器传回来的值就可以判断手机现在的姿态,是横放还是竖放。这是一个简单的三维加速度传感器的模型。至于具体这个传感器的构造是怎样的,我并不十分了解。我猜测应当是用到了微机电MEMS技术,莫非是利用了电子的惯性?呼唤学微电子的同学来扫盲。

HTC 重力感应传感器编程资料总结_第2张图片 

         说到加速度传感器就不能不提陀螺仪。看到网上有些文章说,某某设备(比如数码相机)因为用到了陀螺仪,因此当设备转动时就能够检测出来云云,这些设备或许确实用到了陀螺仪,并且陀螺仪确实是用来检测设备姿态的,不过从上一段的叙述也可以看出,检测设备姿态并不是陀螺仪的专利,一个加速度传感器就可以做到这一点。关于加速度传感器的更多应用技巧可以参看这里。不过加速度传感器的限制在于,它测量出的设备姿态只有在设备静止时才是准确的。一旦设备本身有了加速度或角加速度,那么加速度传感器测出的加速度值就是重力加速度和设备加速度的矢量和,单靠软件并不能把它们分开。简要的说,设备的运动状态和姿态是一个6维的量,而加速度传感器只有3维。有了陀螺仪,才能够做到对设备的全部运动情况了如指掌。加速度传感器与陀螺仪的配合应用现在已经十分普及,而最为人熟知的应用要数GPS导航,当卫星信号暂时掉线时,GPS利用这两个传感器进行惯性导航,不过时间一长会有漂移,还需要磁场传感器等来进行校正。我是从这里的最后一段了解到这些的。

 

HTC 重力感应传感器编程资料总结_第3张图片

 

二、Tester中几个界面的简介

 

         下面就让我来讲讲这个我两天半工作成果,界面做的比较简单,大家主要看看功能吧!

 HTC 重力感应传感器编程资料总结_第4张图片

1.    首先想到的当然是文字界面。最上面的三个值直接显示的是传感器返回的值,没有进行单位转换,如果非要用m/s2作为单位的话,不妨把这个值除以100

         接下来三行显示的是手机的姿态,正如上面所说,这三个角度只有在手机没有加速度时才有效。角度的范围是0~359°。关于这些角度的更多解释请参看源代码注释。我以前没有想到这些角度的应用,写出这三个值纯粹是为了检验我对GSensor值理解的对不对。不过昨天上网浏览时一个网页启发我想出了一个点子,或许可以这样应用:一个读文本软件,当屏幕向下倾斜时就像下滚屏,倾斜的角度越大滚屏速度就越快之类。

         下面一行同样是屏幕姿态,不过它没有详细的数值,只有六种文字表示的姿态,详细的参见CHTCGSensor类文档。

         最下面是摇动事件记录,也就是说你摇一下就会蹦出一行,有时候也会蹦出好几行或不蹦,详细的内容参见类文档。

         在文字界面比较容易看出传感器的误差问题。照片中的手机本来是平放在桌面上的,理应只有-z方向的加速度,可是x,y方向的值却是一个非0且不断变化的值,相当于有±3%的误差。并且±x,±y,±z六个方向的最大值也并不相等,虽然都在1000左右5%。这两者共同导致了手机姿态角判断的不准确。

 

2.      小球界面。点击“小球”按钮后,会出现一个在文字、图形间跳动的蓝色小球,当然它的运动是根据重力感应来控制的。编写这个小球的原因可以说是为了进一步理解传感器返回值的意义,但最主要是为了好玩。试一试就会发现它的效果还是不错的,在代码中我加入了摩擦力和碰撞衰减以使其看上去足够真实。事实上只要有漂亮的界面编写一个Teeter(各种重力感应手机中都有的一个控制小球绕过陷阱到达目的地的游戏)并非难事。控制小球的运动并不需要陀螺仪,因为不管是手机姿态产生的加速度还是手机位移产生的加速度,对于小球本身都是一样的。

 

 HTC 重力感应传感器编程资料总结_第5张图片

3.      图形界面。就是上图这个类似心电图的界面。一接触这个课题,我就知道,一个类似这样的界面是肯定得编的。比如要想检测手机摇动,必须先得了解摇动从开始、加速、减速到停止的过程中,三个加速度的变化趋势,才能制定出一个准确而易行的检测方案。再比如,你想把手机当成一个计步器,晨跑的时候装到兜里,这种软件能编吗?也需要先画出跑步时加速度的动态变化曲线,看看是否能总结出一个模式来进行检测。这个界面实现的细节我就不在这里罗嗦了,看源代码最清楚。

 

三、摇动检测的一点深入讨论

         上面提到通过观察“心电图”来确定摇动检测方案,下面不妨先看看这些“心电图”的样子。(横轴为时间,向右为正方向;纵轴为加速度,向上为正方向;三条细线为0值)

 

HTC 重力感应传感器编程资料总结_第6张图片

         从第一幅图里我们能够得到什么信息呢?首先,手机一开始时是向后倾斜的正立姿势。其次,手机进行了一次向+y方向(也就是向下)的晃动,这次晃动还稍稍偏左后。为什么是向右呢?看看下面这幅图的第一列就明白了。提示一下,速度是加速度的积分,位移是速度的积分。明白了第一幅,那么后两幅“心电图”也就很好懂了:第二幅是先向下再向上的摇晃,第三幅则纯粹是在把手机当汽水瓶子摇。

 

HTC 重力感应传感器编程资料总结_第7张图片

         知道了摇动时加速度的变化趋势,摇动检测的算法又应该如何写呢?可能有些人的第一想法,是要首先保存一个加速度数组,一串“时间序列”。那么,保存了以后又应当怎么做呢?匹配先上升、再下降、再上升的模式么?其实要做到这一点并没有那么复杂,只需要保存前一个极值点的值就可以了,如上图绿点所示。观察上面的三幅“心电图”就会发现,每发生一次摇动(向单一方向算一次),就会有一条比较长的竖线,这条竖线代表短时间内加速度发生了很大的变化。那么只要检测两次极值之差有没有超过一个阈值Threshold,就可以判断有没有发生有意识的晃动了。这个方法简单易行,只需要保存一个历史值,和进行一些简单的判断。

         有一点我们可以肯定,那就是超过阈值的一定得是差值,而不能是某方向上加速度的绝对值,原因是手机的姿势不能确定,因此不能排除重力加速度的影响。上面某一个参考网页上提出了一个修正办法,那就是将传感器的返回值先通过一个高通滤波器,滤除直流偏置和变化相对缓慢的分量,这样就能够直接比较绝对值了。如果某滤波后的加速度分量先在正方向超过了阈值又马上在负方向超过了阈值,那么可以判断手机发生了向该正方向的晃动。这个方法肯定是可行的,但有些麻烦,需要配置滤波器的通阻带和两次事件的时间差,而且效果不一定比上面的方法更好。不过有兴趣的同志不妨尝试一下,假如把原始的传感器值减去滤波后的值,得到的缓慢变化的分量是否就是手机姿态的变化情况了呢?

         还有一些细节需要注意,那就是误判断的问题。从上面的心电图看出,在进行y方向的摇动时,不可避免在xz方向也会有一些加速度分量。上图还是小心翼翼的摇动的结果,而大部分用户在摇动时肯定不会注意那么多,向一个方向摇动的时候另外两个分量很可能也会超过阈值。再比如,如果向右晃动停止时的加速度过大,还会导致向左晃的错误消息被发出。这两个问题,只要是用加速度来判断摇晃的算法,都必须要面对。我在这里针对本检测方法提出三个解决方案:第一,可以利用摇动时附带的力度和时间信息(请参见CHTCGSensor类文档)。如果在很短的时间内检测出了向两个方向的摇动,那么就忽略掉摇动力度较小的那个,说白了就是进行后期处理。后两种解决方案其实是折衷办法,其一是不要用过于精确的摇动信息,比如只判断发生了左右摇动,而不判断向左摇动一次或向右摇动一次;其二是重新编写检测函数,手机可以进行的动作很多嘛,不一定非要摇才行,比如扭动手机,有兴趣的同志可以试一下,检测起来会不会更容易一些?

 

HTC 重力感应传感器编程资料总结_第8张图片

 

         或许有些同志已经想到了第四种解决方案:如果用加速度来检测不确定性较大,那么如果用速度呢?如果出现一个向某方向的比较大的速度就判断出现了摇动。或者干脆用位移,出现了向某一方向的位移当然就是出现了摇动,这种方法看起来再直观不过了。至于速度和位移的取得么,就像上面的图示一样,用加速度的数值积分求得。

         这种方法的主要问题在于,没有陀螺仪帮助判断手机姿态,而且即使有了陀螺仪,也会因为传感器误差累积造成积分得到的速度和位移严重失真。还记得上面提到的3%的误差吗?如果这个误差均值为0还好办一点,不过在我的试验中,情况没有这么乐观,把手机平放在桌子上,累加加速度来算速度,再用速度算时间,结果没过几秒钟,根据计算,手机已经在几百米之外了。本来我的算盘打得挺好,如果这种方法能成功,那么手机如果保证姿态不变不就可以相当于一个GPS了么?为此我还编写了一个工程G-Meter来试图针对传感器的误差进行各种软件校正。后来上网一查,即使有类似功能的GPS还需要地磁传感器来校正漂移哪,更不用说安了如此廉价传感器的手机了。我们只有把希望寄托给技术进步吧!

         本文行至这里就拟结束,如果读者能够从中得到哪怕一点的知识或灵感我就满足,当然更欢迎留言来探讨技术。

viggin

09/08/13

你可能感兴趣的:(编程,windows,HTC,mobile,文档,手机)