iPhoneの加速度センサーをPCから見たい!-2
やっとMacなしで加速度センサーの値をPCから見ることに成功。
と言うわけでiPhoneの加速度センサーの状態をPCで見れると色々楽しいんだと思うんですよ
の続き。
The Big5 application for Apple iPhone and iPod touch is a simplified gateway to your web apps.
↑を使って、PCのアプリに加速度センサの値を送信するサンプル。
使い方
概要/ソースコード
- Big5アプリからJavaScriptでローカルのHTTPサーバにXMLHttpRequestする。
- cgiMotionSensor.py
#!/usr/bin/python # -*- coding: utf-8 -*- import BaseHTTPServer import SimpleHTTPServer import CGIHTTPServer import threading import wireFrame from SimpleXMLRPCServer import * from math import * PORT = 8000 frame = wireFrame.wireFrame() class motionHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): def do_GET(self): path = self.path strReceiver = "motionreceiver.py" l = len(strReceiver) i = path.find(strReceiver) if( i==-1 ): SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) return self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write("<html></html>") rest = path[l+2:] flag = 0 keyword = "" value = "" argList = {} for ii in range(len(rest)): c = rest[ii] if c=="&" or ii==len(rest)-1: argList[keyword] = value flag = 0 value = "" keyword = "" continue if c=="=": flag = 1 continue if flag==0: keyword += c else: value += c if 'x' in argList and 'y' in argList and 'z' in argList: x = float(argList['x']) y = float(argList['y']) z = float(argList['z']) degy = degrees(atan2(z,y))+180 degx = -1*degrees(atan2(y,x))+180 frame.xAxisRollAngle.set(degy) frame.zAxisRollAngle.set(degx) frame.angleChangedEventCall() Handler = motionHandler httpDaemon = threading.Thread(target=SimpleHTTPServer.test,args=(Handler,BaseHTTPServer.HTTPServer)) httpDaemon.setDaemon(True) httpDaemon.start() frame.mainloop() print "end of file"
- allowcube.txt
- ワイヤーフレームオブジェクトのサンプル。適当に四角と丸が書いてある
line,-100,0,0,100,0,0 line,0,-100,0,0,100,0 line,0,0,-100,0,0,100 sphere,100,0,0,10 sphere,0,100,0,10 sphere,0,0,100,10 line,-100,100,-100,100,100,-100 line,100,100,-100,100,-100,-100 line,100,-100,-100,-100,-100,-100 line,-100,-100,-100,-100,100,-100 line,-100,100,-100,-100,100,100, line,100,100,-100,100,100,100, line,100,-100,-100,100,-100,100, line,-100,-100,-100,-100,-100,100, line,-100,100,100,100,100,100 line,100,100,100,100,-100,100 line,100,-100,100,-100,-100,100 line,-100,-100,100,-100,100,100 text,130,0,0,x text,0,130,0,y text,0,0,130,z
- motiontest.html
- Big5アプリで開くhtmlファイル。
- cgiMotionSensor.pyがたとえば192.168.0.6で起動していれば、192.168.0.6:8000/motiontest.htmlをBig5で開く。
<html> <head> <meta name="viewport" content="width = device-width"></meta> <script type="text/javascript" src="http://www.big5apps.com/api/bigfive.js"></script> <script src="./motiontest.js" type="text/javascript"></script> </head> <body> <form name="f"> <input type="button" onclick="logtest()" value="deviceInfo"/> <input type="button" onclick="accelerationTest()" value="motion"/><br/> x:<input type="text" name="x" value=0/> <br/> y:<input type="text" name="y" value=0/> <br/> z:<input type="text" name="z" value=0/> <br/> </form> </body> </html>
- motiontest.js
- Big5アプリで取得できるようになったiPhoneの加速度センサーの値をHTTPサーバにXMLHttpRequestするJavaScript。
function handleDeviceInfo() { alert(Device.model+":"+Device.id); } function logtest() { Device.start(handleDeviceInfo); } var isBusy = false; var req = new XMLHttpRequest(); req.onreadystatechange = function(){ isBusy = false; if(req.readyState==4){ if(req.status==200){ }else{ alert("XMLHttpRequest error"); } } } function sendAcceleration(x,y,z) { if( isBusy ){ return; } val = "x="+x+"&"+"y="+y+"&"+"z="+z; req.open("GET","http://192.168.0.6:8000/motionreceiver.py?"+val,true); req.send(""); isBusy = true; } function handleAcceleration(x,y,z) { document.f.x.value = x; document.f.y.value = y; document.f.z.value = z; sendAcceleration(x,y,z); } var flag = 0; function accelerationTest() { flag = !flag; if( flag ){ Device.Acceleration.start(handleAcceleration); }else{ Device.Acceleration.stop(); } }
- wireFrame.py
- むかし作ったワイヤーフレームのサンプル。少し修正した。
#!/usr/bin/env python import Tkinter import tkFileDialog import math class wireFrame: def clickOpenFile(self): fileName = tkFileDialog.askopenfilename() self.openFile(fileName) def cnvMap(self,x,y): # return (x-self.width/2,y*-1+self.height/2) return (x-self.width/2,(y-self.height/2)*-1,0) def cnvCanvas(self,x,y,z): interval = self.viewPoint.get()*10 / (self.viewPoint.get()*10 + float(z)) x = x*interval y = y*interval return (x+self.width/2,(y-self.height/2)*-1) def roll(self,x,y,degree): (orgX,orgY) = (x,y) orgR = math.sqrt(math.pow(orgX,2)+math.pow(orgY,2)) if orgR==0: return (x,y) orgTheta = math.atan2(orgY/orgR,orgX/orgR) theta = math.radians(degree)+orgTheta x = math.cos(theta)*orgR y = math.sin(theta)*orgR return (x,y) def roll3DbySetting(self,x,y,z): x,y = self.roll(x,y,self.zAxisRollAngle.get()) y,z = self.roll(y,z,self.xAxisRollAngle.get()) x,z = self.roll(x,z,self.yAxisRollAngle.get()) return (x,y,z) def roll3DbySettingReverse(self,x,y,z): x,z = self.roll(x,z,-self.yAxisRollAngle.get()) y,z = self.roll(y,z,-self.xAxisRollAngle.get()) x,y = self.roll(x,y,-self.zAxisRollAngle.get()) return (x,y,z) def createObject(self,item): ''' item => ('line',startX,startY,startZ,endX,endY,endZ) => ('sphere',centerX,centerY,centerZ,radius) => ('text',startX,startY,startX,text) ''' if item[0]=='line': (itemType,sx,sy,sz,ex,ey,ez) = (item[0], int(item[1]),int(item[2]),int(item[3]), int(item[4]),int(item[5]),int(item[6])) (rsx,rsy,rsz) = self.roll3DbySetting(sx,sy,sz) (rex,rey,rez) = self.roll3DbySetting(ex,ey,ez) (lineSx,lineSy) = self.cnvCanvas(rsx,rsy,rsz) (lineEx,lineEy) = self.cnvCanvas(rex,rey,rez) line = self.canvas.create_line(lineSx,lineSy, lineEx,lineEy, fill=self.penColor,width=self.penWidth) obj = dict(id=line,itemType=itemType,coords=[sx,sy,sz,ex,ey,ez]) # self.objects.append(obj) self.objects[line] = obj return obj elif item[0]=='sphere': (itemType,x,y,z,r) = (item[0], int(item[1]),int(item[2]),int(item[3]),int(item[4])) (rx,ry,rz) = self.roll3DbySetting(x,y,z) (cx,cy) = self.cnvCanvas(rx,ry,rz) sphere = self.canvas.create_oval(cx-r,cy-r,cx+r,cy+r, fill=self.penColor,outline=self.penColor) obj = dict(id=sphere,itemType=itemType,coords=[x,y,z,r]) # self.objects.append(obj) self.objects[sphere] = obj # print sphere,itemType,x,y,z,r return obj elif item[0]=='text': (itemType,x,y,z,txt) = (item[0], int(item[1]),int(item[2]),int(item[3]), item[4]) (sx,sy,sz) = self.roll3DbySetting(x,y,z) (cx,cy) = self.cnvCanvas(sx,sy,sz) txtObj = self.canvas.create_text(cx,cy,text=txt) obj = dict(id=txtObj,itemType=itemType,coords=[x,y,z],txt=txt) self.objects[txtObj] = obj else: pass pass def clearCanvas(self): # for obj in self.objects: # item,itemType,sx,sy,sz,ex,ey,ez = obj # self.canvas.delete(item) for id in self.objects.keys(): self.canvas.delete(id) self.objects = {} def openFile(self,fileName): f = open(fileName) for row in f: row = row.replace('\n','') if row=='':continue item = row.split(',') obj = self.createObject(item) f.close() def angleChanged(self,event): self.angleChangedEventCall() def angleChangedEventCall(self): # for obj in self.objects: for id,obj in self.objects.iteritems(): itemType = obj['itemType'] if itemType=='line': item,itemType,(sx,sy,sz,ex,ey,ez) = obj['id'],obj['itemType'],obj['coords'] (rsx,rsy,rsz) = self.roll3DbySetting(sx,sy,sz) (rex,rey,rez) = self.roll3DbySetting(ex,ey,ez) (lineSx,lineSy) = self.cnvCanvas(rsx,rsy,rsz) (lineEx,lineEy) = self.cnvCanvas(rex,rey,rez) self.canvas.coords(item,lineSx,lineSy,lineEx,lineEy) elif itemType=='sphere': item,itemType,(x,y,z,r) = obj['id'],obj['itemType'],obj['coords'] (rx,ry,rz) = self.roll3DbySetting(x,y,z) (cx,cy) = self.cnvCanvas(rx,ry,rz) self.canvas.coords(item,cx-r,cy-r,cx+r,cy+r) elif itemType=='text': item,itemType,(x,y,z),txt = obj['id'],obj['itemType'],obj['coords'],obj['txt'] (rx,ry,rz) = self.roll3DbySetting(x,y,z) (cx,cy) = self.cnvCanvas(rx,ry,rz) self.canvas.coords(item,cx,cy) def __init__(self): self.window = Tkinter.Tk() self.width = 800 self.height = 600 self.penColor = 'red' self.penWidth = 3 self.canvas = Tkinter.Canvas(self.window,bg="white", width=self.width,height=self.height) self.canvas.pack() self.xAxisRollAngle = Tkinter.Scale(self.window, from_=0, to=360, orient=Tkinter.HORIZONTAL) self.xAxisRollAngle.bind("<ButtonPress-1>",self.angleChanged) self.xAxisRollAngle.bind("<ButtonRelease-1>",self.angleChanged) self.xAxisRollAngle.bind("<B1-Motion>",self.angleChanged) self.xAxisRollAngle.pack(side=Tkinter.LEFT); self.yAxisRollAngle = Tkinter.Scale(self.window, from_=0, to=360, orient=Tkinter.HORIZONTAL) self.yAxisRollAngle.bind("<ButtonPress-1>",self.angleChanged) self.yAxisRollAngle.bind("<ButtonRelease-1>",self.angleChanged) self.yAxisRollAngle.bind("<B1-Motion>",self.angleChanged) self.yAxisRollAngle.pack(side=Tkinter.LEFT); self.zAxisRollAngle = Tkinter.Scale(self.window, from_=0, to=360, orient=Tkinter.HORIZONTAL) self.zAxisRollAngle.bind("<ButtonRelease-1>",self.angleChanged) self.zAxisRollAngle.bind("<ButtonPress-1>",self.angleChanged) self.zAxisRollAngle.bind("<B1-Motion>",self.angleChanged) self.zAxisRollAngle.pack(side=Tkinter.LEFT); self.viewPoint = Tkinter.Scale(self.window, from_=1, to=100, orient=Tkinter.HORIZONTAL) self.viewPoint.bind("<ButtonRelease-1>",self.angleChanged) self.viewPoint.bind("<ButtonPress-1>",self.angleChanged) self.viewPoint.bind("<B1-Motion>",self.angleChanged) self.viewPoint.set(100) self.viewPoint.pack(side=Tkinter.LEFT); self.btnOpenFile = Tkinter.Button(self.window,text="open",command=self.clickOpenFile) self.btnOpenFile.pack(side=Tkinter.RIGHT) self.objects = {} # self.window.mainloop() def mainloop(self): self.window.mainloop() if __name__=='__main__': wireFrame()
ファイルのリンク
http://dl.dropbox.com/u/228440/veleno-samples/python-samples/motiontest/cgiMotionSensor.py
http://dl.dropbox.com/u/228440/veleno-samples/python-samples/motiontest/allowcube.txt
http://dl.dropbox.com/u/228440/veleno-samples/python-samples/motiontest/motiontest.html
http://dl.dropbox.com/u/228440/veleno-samples/python-samples/motiontest/motiontest.js
http://dl.dropbox.com/u/228440/veleno-samples/python-samples/motiontest/wireFrame.py
加速度センサーの返す値。
- x:平面におき、左側に傾けたときに-1。右側に傾けたときに1。
- y:垂直に置いて上側を天に向けたときに-1。下側を天に向けたときに1。
- z:画面を上にして平面に置いたとき、-1。裏にしたときに1。
動作環境
Ubuntu10.04とiPhone3Gでしか確認していません。
他の環境とかだとどうなのかなー。
*1:触らないことw