
The accelerometer is not simulated in the current iPhone SDK (for iPhone OS 2.2).
Otto Chrons has posted a neat package that sends accelerometer data from an iPhone or iPod Touch to an application running in the iPhone simulator. This package is in two parts: a ‘server’ that runs on your iPhone hardware and a ‘client’ in the form of source code that you can drop into your project (adding just an #import statement).
This works really well, except when:
1) you don’t have an iPhone or iPod Touch, or
2) you’re not registered in the Standard or Enterprise iPhone Development programme; I wasn’t registered at the time, and so I had no way to push Otto’s server application to my iPod Touch.
But then it occurred to me that my MacBook did have an accelerometer. If only that could serve data to the fake accelerometer in the simulator... So I looked, and providentially enough, UniMotion hove into view.
So I browsed the source for the two packages for a bit, with a view to nefarious smash-and-grab, but by more happy chance it turned out that the relevant pieces in both were modular enough to fit as they were, with a little python for glue.
Otto’s client expects a string with timestamp and x,y,z readings over UDP, and UniMotion’s motion is kind enough to spew x, y and z readings to standard output, though they’re not oriented in the same directions as those in the iPhone SDK’s UIAcceleration.
On my late 2006 MacBook, motion emits x,y,z with a positive magnitude to the left, towards me and downwards, respectively. UIAcceleration expects readings to be positive to the right, away from me and upwards, respectively.
So all I needed to do was to grab motion’s output (with the -f flag for acceleration in units of G), multipy each value by -1, add a timestamp and broadcast over UDP on the given port in the format that Otto’s client expects. I did need to run calibrate in the UniMotion suite first.
Here’s my python glue:
import sys, socket, time, traceback
kCFAbsoluteTimeIntervalSince1970 = 978307200.0 # from CFDate.c
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('',0))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
while 1:
try:
line = sys.stdin.readline()[:-1] # read line and strip EOL
fields = line.split() # split around space character
floatfields = map(float, fields) # convert to floats
# transform co-ordinate system, from SMS- to UIAcceleration-format,
# for my macbook (late 2006)
x, y, z = map(lambda x: -1 * x, floatfields)
# change epoch to be compatible with CFAbsoluteTimeGetCurrent()
currentTime = time.time() - kCFAbsoluteTimeIntervalSince1970
accdata = ','.join(map(str,('ACC: 0',currentTime,x,y,z)))
sock.sendto(accdata, ('<broadcast>', 10552))
# print '% .2f % .2f % .2f' % (x, y, z)
except (ValueError, KeyboardInterrupt):
sock.close()
sys.exit(-1)
except:
traceback.print_exc()
I call this sendaccsim.py and run it as:
$ ./motion -f 17 | python sendaccsim.py
It’s just a bit awkward swinging the Mac around like a tea tray.
14 comments:
I thought you would fiddle with it, when did u decide to poke and peek ;)
haha.. I don't know how you serve your guests tea, but hopefully it's not on them :)
Nice post... look forward to reading more.
When you say you needed to run calibrate, what exactly did you do with it? I can't understand what to do with it, and I'm not able to get it running on my machine
Thanks for posting this up.
'calibrate' will run in a loop, printing out current orientation values to stdout and expecting scale and offset calibration values on stdin in every iteration.
For the Mac lying on a surface as horizontal as you can arrange, you should expect the three values in the f: field to be as close as possible to 0.00, 0.00 and -1.00 respectively, as you tweak calibration values.
When you exit, these values are saved to ~/Library/Preferences/com.ramsayl.UniMotion.plist (I think) and subsequently are picked up by 'motion'.
Fantastic - this was just what I needed to start development before getting a developer license. Thanks!
I am also facing the problem of shift of choti-I matra one position right than its normal position on an linux based ebmedded board with Firefox 3.0.1. Any suggestions will be greatly appreciated.
We mentioned this method in our IAQ (Infrequently Answered Questions) on our website: http://www.appalbum.com/developers/iaq.html#q5
This is a very cool trick thanks. But a note, this only works if the simulated orientation of the phone is portrait. For example, if you're in landscape then X & Y on the accelerometer are swapped.
The other thing that's a little strange is how much network activity this creates. It reminds me of the Doom 1.0 days, lots of broadcasting all over the network!
:) I guess you could reduce the accelerometer sampling rate.
It seems unnecessary that this script be sending anything at all on the network let alone broadcasting.
If you make these changes the "traffic" won't leave the local machine.
#sock.bind(('',0))
sock.bind(('',10522))
#sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# sock.sendto(accdata, ('{broadcast}', 10552))
sock.sendto(accdata, ('localhost', 10552))
Yes, I agree that that would make more sense!
Will it be possible to use macbook's multi-touch pad to send multi-touch event to iphone simulator?
I guess so. You could try the code here:
http://www.steike.com/code/multitouch/
I haven't been able to run it myself because my MacBook doesn't have a multitouch trackpad. I tried!
Post a Comment