Expo Gyrocope API returning false readings

#1

Hi, i am using the test code provided by expo: https://docs.expo.io/versions/v19.0.0/sdk/gyroscope.html. In order to rerun gyroscopic data.

This does seem to return something (it’s unclear - but it looks like it returns RotatationRate in radians?) in (x,y,z) of the phone - (can someone please confirm?)

However, what I need is absolute angle of the (yaw,pitch,roll) phone - not angular velocity - as such just keeping a running count of radians(x,y,z) and each incoming subscription value adding to it - should in theory do the trick.

The issue is that (even when the phone) is on a flat surface - the API is returning data. Data seems to be small (0.01 approx) - however - keeping a running count is causing drift - since it is updating (when it shouldn’t be!).

Please help - I need (as said above) - absolute (yaw,pitch,roll) of phone at any one point. Similar to any off the shelf gyro app out there…

thanks.

0 Likes

#2

I believe you want to use the magnetometer https://docs.expo.io/versions/latest/sdk/magnetometer.html instead of the microscope. Integrating the gyroscope readings should work in theory if you know the initial orientation, but there is inevitably going to be noise in the raw sensor readings.

0 Likes

#3

thank you for responding. However unfortunately the magnetometer won’t work for me. Since I believe it gives compass readings. (I tried it and it indeed only gives compass readings - though they seem a bit weird as well)

I actually need to know the (pitch,yaw,roll) of the device - hence the gyro.

I did realize a couple of things - since the subscription is in radians per sec - I have to divide the result by my subscription frequency - i.e. if my frequency is 20 millisecs - then the returned angular velocity should be divided by 50 (1000/20 = 50).

Doing this indeed gives me almost accurate results (I do have to clean up the data a bit - since there seems to be jitter in the result). As such I do a (unscientific) abs(x,…) < some threshold I throw away data - else I add it to my initial angle.

… here is the (modified) code from expo - again this almost works - but in the end - I think this is a dead end - since the data is too dirty to use - I guess i’m going to have to detach from expo to use native modules directly…that sucks…

import React from ‘react’;
import {
Gyroscope,
} from ‘expo’;
import {
StyleSheet,
Text,
TouchableOpacity,
View,
FlatList
} from ‘react-native’;

export default class GyroscopeSensor extends React.Component {
state = {
radData: {x:0,y:0,z:0},
}

componentDidMount() {
this._toggle();
}

componentWillUnmount() {
this._unsubscribe();
}

_toggle = () => {
if (this._subscription) {
this._unsubscribe();
} else {
this._subscribe();
}
}

_toDegress = (radData) => {
let { x, y, z } = radData;
x = radiansToDegrees(x);
y = radiansToDegrees(y);
z = radiansToDegrees(z);
return {x:round(x), y:round(y), z:round(z)};
}

_slow = () => {
Gyroscope.setUpdateInterval(1000);
}

_fast = () => {
Gyroscope.setUpdateInterval(20);
}

_cleanData = (result) => {
let x = result.x / 50;
let y = result.y / 50;
let z = result.z / 50;
if (Math.abs(x) < 0.0005)
x = 0;
if (Math.abs(y) < 0.0005)
y = 0;
if (Math.abs(z) < 0.0005)
z = 0;
return {x: x, y:y, z:z};
}

_subscribe = () => {
this._subscription = Gyroscope.addListener((result) => {
let cleanData = this._cleanData(result);
let radData = this.state.radData;

  radData.x += cleanData.x;
  radData.y += cleanData.y;
  radData.z += cleanData.z;
  this.setState({radData: radData});
});
this._fast();

}

_unsubscribe = () => {
this._subscription && this._subscription.remove();
this._subscription = null;
this.setState({radData: {x:0,y:0,z:0}});
}

render() {
let rad = this.state.radData;
let deg = this._toDegress(rad);

return (
  <View style={styles.sensor}>
    <Text>Gyroscope:</Text>
    <Text>rad.x: {rad.x} rad.y: {rad.y} rad.z: {rad.z}</Text>
    <Text>deg.x: {deg.x} deg.y: {deg.y} deg.z: {deg.z}</Text>
    
    <View style={styles.buttonContainer}>
      <TouchableOpacity onPress={this._toDegress} style={styles.button}>
        <Text>To Degrees</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={this._toggle} style={styles.button}>
        <Text>Toggle</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={this._slow} style={[styles.button, styles.middleButton]}>
        <Text>Slow</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={this._fast} style={styles.button}>
        <Text>Fast</Text>
      </TouchableOpacity>
    </View>       
  </View>
);

}
}

function radiansToDegrees(radians) {
return radians * 180 / Math.PI;
};

function round(n) {
if (!n) {
return 0;
}

return Math.floor(n * 100) / 100;
}

const styles = StyleSheet.create({
container: {
flex: 1
},
buttonContainer: {
flexDirection: ‘row’,
alignItems: ‘stretch’,
marginTop: 15,
},
button: {
flex: 1,
justifyContent: ‘center’,
alignItems: ‘center’,
backgroundColor: ‘#eee’,
padding: 10,
},
middleButton: {
borderLeftWidth: 1,
borderRightWidth: 1,
borderColor: ‘#ccc’,
},
sensor: {
marginTop: 15,
paddingHorizontal: 10,
},
});

0 Likes