Shannon Appelcline

Subscribe to Shannon Appelcline: eMailAlertsEmail Alerts
Get Shannon Appelcline: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


Related Topics: iPhone Developer

iPhone Developer: Article

Book Excerpt: iPhone in Action

Using the iPhone's accelerometers

The Accelerometer and Movement
When you're using the iPhone's orientation notification, the frameworks are doing your work for you: they're taking low-level acceleration reports and turning them into more meaningful events. It's similar to the concept of iPhone actions, which turn low-level touch events into high-level control events.

Warning
Accelerometer programs cannot be demoed on the iPhone Simulator. Instead you'll need to have a fully provisioned iPhone in order to test out your code on a live device.

However, that's not going to be sufficient for many of you, who would prefer to program an entire interface that effectively uses the iPhone's movement in three-dimensional space as a new user input device. For that, you'll need to access two iPhone classes: UIAccelerometer and the UIAcceleration.

Accessing the UIAccelerometer
The UIAccelerometer is a shared device (like the UIApplication and UIDevice) that you can use to register to receive acceleration-related data. The simple process is shown in Listing 2.

The first step is to access the accelerometer (#1), which is achieved by yet another call to a shared-object method. Having this step as a standalone is probably strictly unnecessary, since you could do the other two steps as nested calls, but we find it a lot more readable.

Next, select your update interval, which is how often you'll receive information on acceleration. This is hardware limited, with a current default of 100 updates per second. That's probably just right if you're creating a game using the accelerometer, but excessive for other purposes. We've opted for 10 updates per second, and thus an updateInterval of .1. You should always go for the lowest acceptable input because doing so preserves power on the iPhone.

Finally, you must set a delegate for the accelerometer. The delegate will need to respond to only one method: accelerometer:didAccelerate:, which sends a message containing a UIAcceleration object whenever acceleration occurs (to the limit of the updateInterval).

Parsing the UIAcceleration
The UIAcceleration information can be used to accurately and easily measure two things: the device's relationship to gravity and the device's movement through three-dimensional space. These are both done through a set of three properties: x, y, and z, which refer to a three-space axis, as shown in Figure 1.

The x-axis measures along the short side of the iPhone, the y-axis measures along the long side of the iPhone, and the z-axis measures through the iPhone. All values are measured in units of "g"s, which is to say g-force. A value of 1g represents the force of gravity on earth.

The thing to watch for when accessing your accelerometer is that it measures two types of force applied to the device: both "g"s of movement in any direction and the actual force of gravity. That means that an iPhone at rest will always show an acceleration of 1g toward the earth's core, something that may require filtering if you're doing more sophisticated iPhone work.

Filtering and the Accelerometer
Though it might seem like the iPhone acceleration data is all mushed together, it's actually easy to isolate exactly the data that you need using basic electronics techniques.

A low-pass filter passes low-frequency signals and attenuates high-frequency signals. That's what you'll use to reduce the effects of sudden changes in your data, such as an abrupt motion.

A high-pass filter passes high-frequency signals and attenuates low-frequency signals. That's what you'll use to reduce the effects of ongoing effects, such as gravity.

We'll see examples of the two main filtering methods in the upcoming sections.

Checking for Gravity
When the accelerometers are at rest, they naturally detect gravity. This may be used to detect the precise orientation that an iPhone is currently held in, going far beyond the four or six states supported by the orientation variables. Listing 3 shows how this could be used.

Any accelerometer program begins with the accelerometer:didAccelerate: method (#1) that's accessed by setting the current program as a delegate of the Accelerometer shared action.

This particular example takes advantage of a red ball (#2), a UIImageView object that you can create in Interface Builder. You're going to move that red ball based on the accelerometer.

In order to access the accelerometer, look at the x and y coordinates of the UIAcceleration object (#3). There's also a z property for the third axis and a timestamp property showing when the UIAcceleration object was created, none of which you'll be using in this example.

Note that we're not yet talking about filtering; we'll hit that topic next after finishing this example. For the moment movement is going to have a pretty limited effect on our example anyway, since an abrupt movement won't really change the ball's slow roll.

After acquiring your gravitic information, make sure that the 50x50 red ball stays within the bounds of the iPhone screen (#4). If you wanted to be really fancy, you could introduce vectors and bounce the ball when it hits the edge, but that's beyond the scope of this example. After that check, you can actually move your ball (#5).

With a very minimal amount of work you've created a program that's truly acted upon by gravity. This program could easily be modified to act as a leveler tool for pictures (by having it only move in one of the three axes) or into a game where a player tries to move a ball from one side of the screen to the other, avoiding pits on the way.

Now, what would it take to do this example totally right by filtering out all movement? The answer, it turns out, is quite easy.

Filtering Out Movement
To create a low-pass filter that will let through gravitic force but not movement, average out the acceleration information that you're receiving so that at any time the vast majority of your input is coming from the steady force of gravity. This is shown in Listing 4, which modifies our previous example.

This example depends on three pre-defined elements. First, there's kFilteringFactor, a constant that's set to .1, which means that only 10% of the active moment will be used at any time. Second, there are two instance variables: gravX and gravY. These each maintain an average for their axis of movement as the program runs. After that, the filter is easy to use.

More Stories By Christopher Allen

Christopher Allen is one of the leaders of the iPhone developer community. He is the host of iPhoneWebDev.com, which is the largest independent community of iPhone-based web developers, and manages its mailing list. He is also one of the founders of iPhoneDevCamp and oversees its Hackathon, and is co-author of iPhone in Action:Introduction to Web and SDK Development. Christopher is a longtime technologist, and is also a leader in social software and was one of the authors of TLS, the next-generation SSL protocol.

More Stories By Shannon Appelcline

Shannon Appelcline is a writer and technologist. He was a participant in Charles River Media's Massively Multiplayer Game Development 2. He has also been published by Chaosium Inc., Issaries Inc., Jones Publishing, Partizan Press, White Wolf Publishing, and Wizards of the Coast. In 2007 he wrote over 350,000 words for professional publication, including books for Mongoose Publishing and Moon Design Publications. He has also written fiction published by Green Knight Publishing and comic books published by Skotos Tech.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.