HTML5 Device Orientation - reliable compass implementation? - javascript

I am working on a mobile web project that needs to know the compass direction the user's device is pointing. It's incredibly simple right now, but here's what I have:
var updateDirection = function (evt) {
$("#direction").val(evt.alpha);
};
window.addEventListener("deviceorientation", updateDirection);
Based on what I've researched so far, the alpha channel of the event should be the compass position. However, I've observed (and read) that there are a wide variety of implementations based on OS and browser.
On my HTC smartphone, in Chrome or the default Android browser, I only get a reasonable reading (0 degrees = North, 90 = East, so on) when I hold the phone perfectly vertical in a "selfie" position. Any angle to the phone throws readings quite far off.
On my Surface Pro using Chrome, I can't get a reading greater than about 50.
On my Surface Pro using Edge, I get very reasonable readings, but only when I hold the device horizontal, as if it was laying on a table.
It seems likely that people have achieved getting the compass direction in a mobile browser regardless of device. Is there some library I can use to do this? Or is it necessary to simply code for many different specific scenarios, like this example, which also didn't work for all the devices listed:
Device Orientation Events

Is that really necessary for you to use javascript to find out orientation?
You could possibly achieve the same result with CSS media queries

Related

SpaceMouse Compact not working with js Gamepad api in Chrome on Ubuntu

As the title suggests I have a problem with using SpaceMouse in Chrome on Ubuntu. On Windows 10 it works fine. I've tried installing 3DxWare 10 and spacenavd but it still does not work.
It is worth mentioning that the mouse works with Gazebo perfectly fine so it must be a problem with Chrome. Is there some flag in Chrome or additional software to make the SpaceMouse compatible with Gamepad api in javascript?
Short answer: If your SpaceMouse isn't working with Gamepad API on Chrome for Linux, try relabsd.
Long answer: SpaceMouse is close enough to a gamepad that it sometimes works but sometimes doesn't. It would be nice if it worked, but getting it to work reliably in Gamepad API across all platforms is non-trivial and that kind of effort is better spent supporting real gamepads.
For this specific issue, the problem is how the device describes its inputs. Each input has a flag indicating whether the input is absolute (with a defined minimum and maximum value) or relative (meaning each input must be compared with the previous value). Absolute inputs are used for things like joysticks and touchscreen touch points while relative inputs are used for things like optical mice and trackpad movements.
Some SpaceMouse devices describe their axis inputs as relative, some as absolute. When it's an absolute axis, Chrome can fetch the bounds information and use it to normalize the axis to the range [-1,+1] as required by the Gamepad API. When it's a relative axis, bounds information is not available and the axis can't be normalized reliably.
SpaceMouse axes always behave like absolute axes, it's a bug when they're defined as relative. There's a third-party tool for mapping SpaceMouse relative axes to absolute axes, I haven't tested it but from the description it sounds like it does what you need:
https://github.com/nsensfel/relabsd
Some SpaceMouse devices (like SpaceMouse Wireless) report absolute axes and work with Gamepad API.

How do I detect if a device has a gyroscope in a web browser?

I am using THREE.js and creating a web-app where the user can rotate the device and the scene will move accordingly. Something similar to this.
I am having a problem differentiating between devices that have a gyroscope and those that don't.
Detecting devices that don't have orientation sensors at all is easy. All the alpha, beta, gamma values of DeviceOrientationEvent are null. But, if a mobile device doesn't have a gyro, it still gives alpha, beta, gamma values in DeviceOrientationEvent. The problem is these values are very noisy, and cause a lot of shaking in the scene. So, I want to disable the device orientation for these devices. But, so far I haven't been able to find how to make out if the data is coming from a gyro or accelerometer (that's my guess on where the data is coming from).
I don't know if it helps, but a good example of how this is handled can be seen here. (Press the axis like icon at the bottom; you'll have to see it on a device that doesn't have a gyroscope and a gyroscope to see the difference). What they are doing for devices without a gyroscope is only updating the pitch and the roll. The yaw isn't updated when you rotate with the phone.
So, it is definitely possible, but I haven't yet found out how even after searching a lot. It would be great if anyone could help.
Thanks a lot.
EDIT:
On devices that just have an accelerometer, like MOTO E, all values are null - DeviceOrientationEvent and rotationRate - with the only exception of accelerationIncludingGravity. But, the device I was testing earlier, that didn't have a gyro but still gave alpha, beta, gamma values for DeviceOrientationEvent, seems to have 2 accelerometers according to the "sensors" details on GSM Arena. That is how I suspect it was able to give DeviceOrientationEvent data, albeit noisy. Looks like 2 accelerometers aren't enough to give rotation rate ;)
If you want to check if gyroscope is present or not, check the parameters that only gyroscope can measure. For example rotation rate is something only gyroscope measures.
Have a look at an example code which says whether gyroscope is present or not:
var gyroPresent = false;
window.addEventListener("devicemotion", function(event){
if(event.rotationRate.alpha || event.rotationRate.beta || event.rotationRate.gamma)
gyroPresent = true;
});
Hope this helps!
EDIT:
Just a small note: Here, the DeviceMotionEvent is used because the rotationRate (and acceleration etc.) can be accessed from this event only. The OP had tried only the DeviceOrientationEvent, so this is worth a mention.
Modern solution:
if (window.DeviceOrientationEvent) {
// gyro exist
}
source

Three.js Camera Orientation in Firefox for Android

Encountering an issue where the phone behaves as though the camera is crossing the environment zenith when it should simply be looking straight ahead. Everything flips upside down the way it would when the phone was oriented so that the camera is looking straight up, but this change happens when looking forward.
I'm on the latest version of Firefox (and the Firefox beta browser) on a Samsung Galaxy S6 running Android version 5.0.2. I can reproduce the issue on this video.
The issue appears to be that the rotation around the x-axis crosses from 0 to 180 (degrees) at that point. Is there a way to normalize this? I'm not encountering it in Chrome for Android on the same device.
The simplest solution is to use the experimental WebVR API features in Firefox to get the PositionSensorVRDevice and use its getState() method to derive orientation. The camera may still be slightly off from what you expect, but you can rotate it to be correct without the world flipping the way it does with the device orientation.

How does htmlcompass work?

I have a Wifi iPad and this compass actually knows the direction of north. Now I know it's quite possible to use the gyroscope data to fairly accurately track device rotations once north has already been established, but how on earth does it know the actual direction?
Now I'm pretty sure the ipad does not have a magnetometer... or does it? It's got a bunch of magnets all along its sides!
My reasoning is that if it didn't come with the Compass app, the device doesn't have a magnetometer.
Update: Okay I'm able to affect the result by moving a magnet around a stationary iPad. So it does have the magnetometer after all.
iPad and iPhone (3GS and later) have a digital compass (magnetometer) chip onboard, such as the AK8975 3-axis Magnetic field sensor.
By the way, it can be calibrated, see here: http://support.apple.com/kb/TS2767
In addition iPad also has gyroscope and accelerometer chips.
If you want to peek inside the iPad, check out the ifixit site and the teardown at chipworx.
Turns out iPad Wifi has a magnetometer.

window.pixelRatio not working in Opera. Any alternative?

I have been working on making our CMS export valid content for mobile devices. One of the problems we encountered was that newer devices, like the iphone4 have a higher resolution display so we needed to find a way to render the same page correctly on older devices and newer that use a 300dpi display. So far we used javascript and window.devicePixelRatio in order to get the dpi resolution, but it turns out this is not working in opera(?) and opera mobile.
Any suggestetions or maybe a defferent approach? I researched a bit but was unable to find somethig.
Thanks
I think you might misunderstand what devicePixelRatio is really telling you — surprise, a pixel is not a pixel!
When you specify a pixel size in CSS, you're not necessarily specifying a size in physical pixels. Instead the CSS px unit is actually a "device-independent pixel" (DIP), which is relative to the device's DPI:
Pixel units are relative to the resolution of the viewing device, i.e., most often a computer display. If the pixel density of the output device is very different from that of a typical computer display, the user agent should rescale pixel values.
The reference pixel is defined as 96dpi (Windows' default DPI setting), so on your computer, it is true that 1 DIP (CSS px) = 1 physical screen pixel. Additionally, even though older iOS devices have a physical DPI of 163, they still use 1 DIP = 1 pixel. However, on iPhone 4's doubled resolution of 326 DPI, 1 DIP = 2 screen pixels, which is what devicePixelRatio = 2 is telling you.
Thus, speaking strictly of the difference between the iPhone 3 and iPhone 4, a HTML element with the style { width:100px; height:100px; } should render at roughly the same size on older devices and on the higher-DPI iPhone 4 since it rescales the pixel values.
So there is no reason you sould have to use script to account for high-DPI devices; it should just work.
Opera Mobile doesn't have devicePixelRatio yet as it is pretty much a none-standard extension added by Apple. We are considering adding this however, and may be in the next release of Opera Mobile if we do. You don't need to use JS for this however. It should work in a Media Query too with device-pixel-ratio (with vendor prefixes).
HI all,
josh3736 gave a very nice and concise answer to the css vs device pixel issue. Just wanted to add that it does seem to be an issue with large, high definition images which may need to be served more specifically for individual dpi or ppi device spec's. Searching google, I found that others are (attempting to?) using the device-pixel-ratio as a base to resize images smaller for high ppi displays, while keeping the original high def. image available for these devices and providing low def. images for mobiles without high dpi displays. That way the image is of higher quality for these devices, yet looks sized the same relative to the rest of the page across the spectrum of user devices.
The ability to zoom seems to make this more useful I gather, since a user can zoom in on high def. images and get increased detail. Of coarse this does add another layer of complexity to deal with, but it may be important to address as we have more and more new high end devices entering the markets. Still looking into this, so post back if anyone has good examples.

Categories