绘制手机重力仪数据的实时动态图像

最近跟着老师做了一些人机交互的小玩意儿,倍感无聊。其实说无聊也有些过头了,不过确实思路还没有打开,很局限,思考来思考去就是那几套方案。我想可能是因为自己在这方面的积累还太少吧,视野不够开阔,总是想不到什么好的点子,或许也可能因为一直习惯于解决问题的思路,而没有领悟到创新的方法吧。革命和创新往往都是从一个新颖的想法出发,而后有着这个想法作支撑,问题一般也就迎刃而解。记得马克吐温曾经说过:使我们陷入麻烦的不是那些我们不知道的东西,而是那些我们认为理所当然的东西。当然提出这些想法不但需要勇气,也需要相当的知识积累。

不过虽是这么说,安卓的编程倒是学到了不少,重力仪和陀螺仪的控制也熟悉了一些,想起前几天刚刚看到的 Python 包 Matplotlib,就想是不是可以用 matplotib 来绘制手机重力仪和陀螺仪数据实时的动态图像呢?因为之前都是画的静态图像,而像心电图、示波器这一类的动态图像的显示却没试过,所以就自然而然地有了这样的想法。

好了,话不多说。对 matplotlib 不熟悉的同学可以先参考一下用matplotlib绘制数学图像

我的这个重力仪的数据是通过无线网传输过来的,所以思路很简单:用 Socket 绑定和监听端口,然后将收到的数据传给 matplotlib 就好了。由于我们是要绘制动态图像,所以似乎是要调用 ion(),意思是打开互动模式。参考代码如下:

import socket
from pylab import *
import numpy

def update(newdata):
	global x
	global h1
	x = np.delete(x, 0)
	x = np.append(x, newdata[0])
	h1.set_ydata(x)
	draw()

def processing(data):
	try:
		coor = data.split("\n")[0].split(",")
		update(coor)
	except:
		print "Error. Comma-separated data expected."

TCP_IP = '192.168.0.104'
TCP_PORT = 8099
BUFFER_SIZE = 1024

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)

ion()
x = zeros(100)
h1, = plot(x)
ylim(-10,10)
xlabel('Time')
ylabel('Accelerometer data on $X$ axis')
title('Dynamic Plotting')

conn, addr = s.accept()
print 'Connection address:', addr
while 1:
	data = conn.recv(BUFFER_SIZE)
	if not data: break
	print "received data:", data
	conn.send(data)  # echo
	processing(data)
conn.close()

最终的显示还是很流畅的,下面是摇晃手机时候的波形,从线条看出来 matplotlib 的反锯齿处理得还是很不错的(我就不吐槽某些商业软件了):
shaking the phone

敲桌子的加速度波动则要小得多,可以看出手机内置的传感器还是相当灵敏的:
knock_on_the_table

据说通过探测加速度的值还能计算出位移的大小(是不是可以用这个坐在电梯里就能算出层高呢?),但是实测发现误差太大,根本没有实际的应用价值。个人认为是因为通过加速度计算位移需要二重积分,而手机只能每隔一小段时间返回一次加速度值,这时候噪音累积的误差已经无法忽略了。欢迎大家参与这个话题进一步的讨论。

Leave a Reply

Your email address will not be published. Required fields are marked *