1

I am creating a tool using Box2D and wanted to see if there was a way to match the direction of the real force of gravity acting on a mobile device.

I've got this completely working on iPad by binding to the devicemotion event. I check to see if the window's width is greater than its height in order to determine if the user is holding the device in landscape or portrait mode and I translate the data that the accelerometer provides based on that fact. For instance, if the iPad is being held with the home button to the bottom of the device, y is negative and corresponds to the force of gravity, as you might expect. If the device is rotated 90 degrees left or right, y moves toward 0 and x either increases to 9.8 or decreases to -9.8.

The problem is that when I move to an Android device whose orientation is landscape by default (i.e. the device's hardware is arranged in such a way that it is clear it is intended to be used mainly in landscape orientation) the x and y coordinates are reversed and the fact that the window's height is greater than its width can't be used to determine whether the user is holding the device with it's top "up" and its bottom "down".

Is there a more universal way for me to determine the direction that a device is being held and as a result know how I should interpret the accelerometer data so that my gravity is always relative to the Earth?

Here is a quick snippet of the method I'm using to determine the property values.

window.addEventListener('devicemotion', function(e) { console.log(e.accelerationIncludingGravity.x); console.log(e.accelerationIncludingGravity.y); })

itsmequinn
  • 1,054
  • 1
  • 8
  • 21
  • You assertions about how Android devices work do not correspond with my experience at all. – Pointy Apr 10 '14 at 16:40
  • I'm seeing this on Android 4.4.2 running on a Nexus 10. In landscape, with the device's front-facing camera at the top of the device, y is close to 9.8 and x is close to 0. If you hold it "upside-down", y is close to -9.8 and x is close to 0. In either of the other two orientations, x is close to +/-9.8 and y is close to 0. Contrast that with the iPad where y is close to +/-9.8 in portrait with the camera at the top of the device. – itsmequinn Apr 10 '14 at 16:44
  • ok so where are those coordinates coming from? Is if an element on a page or something? Or are they event properties? *edit* ah they're the acceleration "coordinates" right? I'll make a fiddle. – Pointy Apr 10 '14 at 16:48
  • event properties. let me add a code snippet to the question. – itsmequinn Apr 10 '14 at 16:51
  • OK I see - Android (both Firefox and Chrome) give values relative to the physical device geometry, and the y axis is determined by the position of the camera. – Pointy Apr 10 '14 at 17:27
  • Yes, excatly. I only use the camera because it's a convenient way to describe it but all of the labeling etc. on the device are arranged in such a way that it seems that it was meant to be used primarily in a landscape orientation. – itsmequinn Apr 10 '14 at 17:51
  • Well I wonder if you could figure it out by also tracking "deviceorientation" events. – Pointy Apr 10 '14 at 18:07

1 Answers1

0

After working on this for the rest of the day, it looks like the answer is that you need to add a listener to the window for the orientationchange event (and also the resize event since some Android devices don't fire orientationchange) and then checking window.orientation, which is either 0, 180 or +/-90 based on orientation.

var orientation = window.orientation;

//Optionally add an evenr listener on resize here
window.addEventListener('devicemotion', function() {
    if(Math.abs(orientation) == 90) {
        //device is sideways
    } else {
        //device is vertical
    }
});

window.addEventListener('orientationchange', function(e) {
    if(PanScaleTool.scaleToolData.accelerometer == true) {

        if(Math.abs(e.beta) > 45) {
            orientation = window.orientation;
        } else {
            orientation = window.orientation;
        }
    }
});

In my limited testing with an iOS device and two android devices, 0 and 180 seem to always correspond to device is vertical (front facing camera at top of screen for example) or upside down. +/- 90 correspond to the other two orientations.

Here's another question on SO that I referenced for this answer

Community
  • 1
  • 1
itsmequinn
  • 1,054
  • 1
  • 8
  • 21