I am making an AR experience where I would like to use a phone's compass to direct a player toward true north, but I am having problems with smoothing the compass readings on Android devices. The code I have experimented with so far logs a certain number of readings into a queue, copies the queue into a list and then once the list is full it takes the average of all the readings. From here I would like to scale the reading between -1 & 1, where 0 represents South. Then I want this data to be used to rotate a compass image on the GUI layer.
The data is nowhere near as smooth as I'd like it to be, but here is the code I have so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CompassSlider : MonoBehaviour
{
public float reading;
public Queue<float> data;
private float[] dataList;
public int maxData = 100;
public int count;
public float sum, average;
public float dampening = 0.1f;
public float rotationToNorth;
// Use this for initialization
void Start()
{
data = new Queue<float>();
dataList = new float[maxData];
}
// Update is called once per frame
void Update()
{
Input.location.Start();
Input.compass.enabled = true;
count = data.Count;
if (data.Count > 0)
{
data.CopyTo(dataList, 0);
}
if (data.Count == maxData)
{
for (int i = 0; i < data.Count; i++)
{
sum += dataList[i];
}
if (Mathf.Abs(dataList[maxData - 1]) > 0)
{
average = sum / maxData;
sum = 0;
data.Clear();
dataList = new float[maxData];
}
}
if (data.Count >= maxData)
{
data.Dequeue();
}
reading = Mathf.Round(Input.compass.trueHeading);
data.Enqueue(reading);
if (count == maxData) {
rotationToNorth = average / 180;
rotationToNorth = (Mathf.Round(rotationToNorth * 10)) / 10;
rotationToNorth = rotationToNorth - 1;
}
}
}