compass-react-native
compass-react-native copied to clipboard
Compass fluctuation and unstable values.
Thank you for the compass I was looking for the same. But on the real device, it is getting fluctuated and the values also are unstable. Please help me out. Also tried Low Pass Filter as per the stack solution https://stackoverflow.com/questions/57308560/smooth-orientation-compass-using-react-native-sensorss-magnetometer.
The following added screen is of stable device.
Please, check the latest commit and test it out to see if the issue still exists. It's been a while I got the chance to look into this project. Also I've posted an answer on Stackoverflow. Please check and accept the answer if it helps.
The problem is with LPF in the _angle method. When magnetometer's "y" goes from positive values to negative rapidly, the LPF.next() recieves greatly different values. Some close to 0 degrees, some close to 360. So the input to LPF might look somthing like this: 0, 357, 2, 350 etc. It can't keep up. And that's why the image starts to oscillate.
Any solution for this? how to solve?
I have introduced hysteresis like behavior into the response. Added the _hysteresis method for that. But I have also changed a few other things, like inside the _angle method I simply return the atan with an angle between -180 to 180. I don't rotate it to be between 0-360. And the subscription is expo based. I have also edited the compass image, so that North is pointing to the right side on it, this way I don't have to rotate it with another 90 degrees inside the code. So don't just copy that one method, cause it won't work like that with original code. :D
import React, { Component } from "react";
import { View, StyleSheet, Dimensions, Image } from "react-native";
import { Magnetometer } from "expo-sensors";
import LPF from "lpf";
let ScreenHeight = Dimensions.get("window").height;
class CompassPointer extends Component\<{}, { degree: number }\> {
_magnetometerSubscription;
constructor(props) {
super(props);
this.state = {
degree: 0
};
LPF.init([]);
LPF.smoothing = 0.2;
};
componentDidMount() {
this._subscribe();
}
componentWillUnmount() {
this._unsubscribe();
};
_subscribe = async () => {
if (Magnetometer.isAvailableAsync()) {
Magnetometer.setUpdateInterval(16);
this._magnetometerSubscription = Magnetometer.addListener(sensorData => {
this.setState({ degree: this._angle(sensorData) });
});
} else {
console.log("Magnetometer not available!");
}
};
_unsubscribe = () => {
this._magnetometerSubscription.remove();
this._magnetometerSubscription = null;
};
_angle = magnetometer => {
let angle = 0;
if (magnetometer) {
let { x, y } = magnetometer;
angle = Math.atan2(y, x) * (180 / Math.PI);
}
return Math.round(LPF.next(this._hysteresis(angle)));
};
_hysteresis = angle => {
if (Math.abs(this.state.degree - angle) >= 180) {
if (angle >= 0) {
return angle - 360;
}
if (angle < 0) {
return 360 + angle;
}
} else {
return angle;
}
}
render() {
return (
<View>
<Image style={[this.styles.compassImage,
{ transform: [{ rotate: 360 - this.state.degree + "deg" }] }]}
source={require("../../../assets/compass.jpg")} />
</View>
)
}
styles = StyleSheet.create({
compassImage: {
width: ScreenHeight / 4,
height: ScreenHeight / 4,
borderRadius: ScreenHeight / 8
}
});
}
export default CompassPointer;
This can still become unstable for a second if you turn it around too much.
Please, check the latest commit and test it out to see if the issue still exists. It's been a while I got the chance to look into this project. Also I've posted an answer on Stackoverflow. Please check and accept the answer if it helps.
it is still the same. even my App hangs after i nevigate to compass
The problem is with LPF in the _angle method. When magnetometer's "y" goes from positive values to negative rapidly, the LPF.next() recieves greatly different values. Some close to 0 degrees, some close to 360. So the input to LPF might look somthing like this: 0, 357, 2, 350 etc. It can't keep up. And that's why the image starts to oscillate.
Is there any method to flush the LPF and start a new when it approaches 0 ?