# Accelerometer

Watch the screencast!

The Accelerometer service uses acceleration events to provide information to applications:

- Orientation events—useful for rotating your application between portrait and landscape mode to match the orientation of the device.

- Shake events—can be applied in creative ways as an alternative for user input such as a start/stop indicator.

- Raw accelerometer data—useful for games or other applications that can integrate device movement directly into the application's interaction with the user.

Unlike the other system services, the Accelerometer service communicates via events; the application uses framework controller functions or event listeners to receive the events. For information about listening to events (and stopping listening) see the Events page.

## Orientation events

It's extremely simple to enable your application to respond to changes in screen orientation. Within your stage assistant or main scene assistant, set your application's card stage window to a free orientation through the stage controller's setWindowOrientation() method. Example:

>     if (this.controller.stageController.setWindowOrientation) {
>       this.controller.stageController.setWindowOrientation("free");
>     }

The system automatically rotates the stage window, following the orientation of the device between up (portrait), right (clockwise rotation from up), down (portrait but the reverse of up) or left (counter-clockwise from up). You can use the same method to force an orientation with any of up, down, left or right passed as a string as the argument.

There is a corresponding getWindowOrientation() method to retrieve the current stage window orientation.

If you want to something more than simply rotate the stage's window, you can add a listener to the stage window for the orientationchange event, and then respond to the change. Example:

>     this.controller.listen(document, 'orientationchange',
>       this.handleOrientation.bindAsEventListener(this));
>     ...
>     MyAssistant.prototype.handleOrientation(event) {
>       Mojo.Log.info("Orientation change position: ", event.position, " pitch: ", event.pitch,
>           " roll: ", event.roll);
>     };

The new orientation data are passed as properties to the event object described in Table 1.

Property | Value | Description
--- | --- | ---
position | Integer | Numeric value from 0 to 5: 0 = face up 1 = face down 2 = up, or normal portrait 3 = down, or reverse portrait 4 = left, or landscape, left side down 5 = right, or landscape, right side down
roll | Float | Right-handed rotation about the x-axis (in degrees)
pitch | Float | Right-handed rotation about the y-axis (in degrees)

## Pitch and Roll

Pitch and roll are values that describe the orientation of the device:

- Pitch refers to the angle of forward/back rotation—from -90 (power button edge is highest) to 90 (power button edge is lowest).

- Roll refers to the angle of side-to-side rotation—from -90 (rotated 90 degrees to the left) to 90 (rotated 90 degrees to the right).

Pitch and roll both range from -90 to 90 degrees. When the device is lying flat, both pitch and roll are zero. For any combination of pitch and roll, there are two orientations that return the same values. You can use the position property to distinguish the two cases.

## Shake

There are three events:

- shakestart
- shaking
- shakeend

As you would expect, the start and end events are sent as soon as a shaking motion starts or stops. Shaking events are sent regularly while shaking continues, at the same rate as raw events, or 4Hz. The events include a magnitude property (in units of gravitational acceleration or g's) where a large value indicates more vigorous shaking.

>     this.controller.listen(document, 'shaking', this.handleShaking.bindAsEventListener(this));
>     ...
>     MyAssistant.prototype.shaking(event) {
>       Mojo.Log.info("Shaking with magnitude: ", event.magnitude);
>     );

In practice, you may not need to listen to the shake start and end events unless you have some specific actions for those events. The shaking events begin as soon as the shaking motion starts and cease when the shaking stops.

## Raw Accelerometer Data

Detailed acceleration data is provided with each acceleration event, which is sent at 4Hz whenever the device is in motion. While it is accurate enough for games and similar dynamic applications, it won't be sufficient to allow inertial position tracking applications. Acceleration events are targeted at the window and do not bubble.

>     this.controller.listen(document, 'acceleration',
>       this.handleAcceleration.bindAsEventListener(this));
>     ...
>     MyAssistant.prototype.acceleration(event) {
>       Mojo.Log.info("X: ", event.accelX, "; Y:", event.accelY, "; Z:",
>           event.accelZ, "; time: ", event.time);

If a more frequent acceleration data update is required, pass the "fastAccelerometer" parameter to the StageController.setWindowProperties method to increase the update rate to 30Hz.

>     this.controller.stageController.setWindowProperties({fastAccelerometer:true});

Acceleration events contain additional properties as described in the following table.

Property | Value | Description
--- | --- | ---
accelX | Float | Acceleration along the X axis (in g's)
accelY | Float | Acceleration along the Y axis (in g's)
accelZ | Float | Acceleration along the Z axis (in g's)

## See a demo

This screencast takes you through a simple example of using raw accelerometer X, Y, and Z data, as well as roll, pitch, and screen orientation.

## Sample code from the screencast

This is a pretty straightforward application. After pushing the main scene from the stage assistant, the only code involved is main-assistant.js and main-scene.html.

### main-assistant.js

>     function MainAssistant() {
>     }

>     MainAssistant.prototype.handleAcceleration = function(event){
>       this.controller.get("accx").update("X = " + event.accelX);
>       this.controller.get("accy").update("Y = " + event.accelY);
>       this.controller.get("accz").update("Z = " + event.accelZ);
>     }

>     MainAssistant.prototype.handleOrientation = function(event){
>       var position = [
>           "Flat, face up",
>           "Flat, face down",
>           "Upright",
>           "Upside Down",
>           "Pointed left",
>           "Pointed right"];

>       this.controller.get("position").update("Orientation: " + position[event.position]);
>       this.controller.get("roll").update("Roll: " + event.roll + " degrees");
>       this.controller.get("pitch").update("Pitch: " + event.pitch + " degrees");
>     }

>     MainAssistant.prototype.setup = function() {
>       if (this.controller.stageController.setWindowOrientation) {
>           this.controller.stageController.setWindowOrientation("free");
>           this.controller.stageController.setWindowProperties({ fastAccelerometer: true });
>       }

>       this.handleOrientation = this.handleOrientation.bindAsEventListener(this);
>       Mojo.Event.listen(document, 'orientationchange', this.handleOrientation);
>       this.handleAcceleration = this.handleAcceleration.bindAsEventListener(this);
>       Mojo.Event.listen(document, 'acceleration', this.handleAcceleration);
>     };

>     MainAssistant.prototype.cleanup = function(event) {
>       Mojo.Event.stopListening(document, 'orientationchange',this.handleOrientation);
>       Mojo.Event.stopListening(document, 'acceleration',this.handleAcceleration);
>     };

### main-scene.html

>     <div id="main" class = "palm-hasheader">
>       <div class="palm-header">Accelerometer test</div>
>       <div id="accx" name="accx" class="palm-body-text">0</div>
>       <div id="accy" name="accy" class="palm-body-text">0</div>
>       <div id="accz" name="accz" class="palm-body-text">0</div>

>       <div id="position" class="palm-body-text">Position</div>
>       <div id="roll" class="palm-body-text">0</div>
>       <div id="pitch" class="palm-body-text">0</div>
>     </div>