- Home /
This post has been wikified, any user with enough reputation can edit it.
Question by
looMeenin · Dec 31, 2014 at 08:27 AM ·
c#javascriptfilteraccelometer
How to implement a low pass filter for accelerometer?
Here is the code I am using to move my character with accelerometer(no low pass filter):
public float speed = 30.0f;
private float accel;
Vector2 dir;
void Start ()
{
accel = Input.acceleration.x;
}
// Update is called once per frame
void Update ()
{
accel = Mathf.MoveTowards (accel, Input.acceleration.x, speed * Time.deltaTime);
// map accel -Y and X to game X and Y directions:
dir = new Vector3(accel, 0);
// move the object at the velocity defined in speed:
transform.Translate(lowPassValue * speed * Time.deltaTime, 0);
}
I want to implement a low pass filter that I found in the Unity manuals here:http://docs.unity3d.com/Manual/MobileInput.html
Here it is(in UnityScript):
var AccelerometerUpdateInterval : float = 1.0 / 60.0;
var LowPassKernelWidthInSeconds : float = 1.0;
private var LowPassFilterFactor : float = AccelerometerUpdateInterval / LowPassKernelWidthInSeconds; // tweakable
private var lowPassValue : Vector3 = Vector3.zero;
function Start () {
lowPassValue = Input.acceleration;
}
function LowPassFilterAccelerometer() : Vector3 {
lowPassValue = Mathf.Lerp(lowPassValue, Input.acceleration, LowPassFilterFactor);
return lowPassValue;
}
Can someone help me implement this low pass filter into my original c# code?
Comment
Best Answer
Answer by hav_ngs_ru · Dec 31, 2014 at 10:11 AM
using System.Collections.Generic;
...
protected Queue<Vector3> filterDataQueue = new Queue<Vector3>();
public int filterLength = 3; //you could change it in inspector
void Start() {
...
for(int i=0; i<filterLength; i++)
filterDataQueue.Enqueue(Input.acceleration); //filling the queue to requered length
...
}
public Vector3 LowPassAccelerometer() {
if(filterLength <= 0)
return Input.acceleration;
filterDataQueue.Enqueue(Input.acceleration);
filterDataQueue.Dequeue();
Vector3 vFiltered= Vector3.zero;
foreach(Vector3 v in filterDataQueue)
vFiltered += v;
vFiltered /= filterLength;
return vFiltered;
}
didnt test it for typos, but idea is like this
Answer by michaelstv · Mar 14, 2016 at 02:04 PM
Hi
Here is another implementation, simpler IMHO as it doesn't use an array of past values: using UnityEngine; using System.Collections;
public class LowPassTransformFilter : MonoBehaviour
{
Quaternion currentRotation, targetRotation;
Vector3 currentPosition, targetPosition;
// with these fields you can select whether to apply low pass on rotation or position only
public bool applyOnRotation = true;
public bool applyOnPosition = true;
// This field controls the low pass value
// Use 1 for no filtering, and a value closer to zero for more sluggish filtering
// (Note that zero would be invalid and freeze the transform)
//
[Range(0.1f, 1.0f)]
public float lowPassFilter = 0.5f;
public float LowPassFilter { set { lowPassFilter = value; } }
// Use this for initialization
void Start ()
{
currentRotation = targetRotation = transform.rotation;
currentPosition = targetPosition = transform.position;
}
// Use LateUpdate in case other scripts also use LateUpdate to change the transform
void LateUpdate ()
{
if (transform.rotation != currentRotation) {
targetRotation = transform.rotation;
}
if (transform.position != currentPosition) {
targetPosition = transform.position;
}
if (lowPassFilter < 1) {
if (applyOnRotation) {
transform.rotation = Quaternion.Slerp (currentRotation, targetRotation, lowPassFilter);
}
if (applyOnPosition) {
transform.position = Vector3.Lerp (currentPosition, targetPosition, lowPassFilter);
}
}
currentRotation = transform.rotation;
currentPosition = transform.position;
}
}
Thank you, Thank you, Thank you. I'd award 100 points if I could :)