- Home /
Unable to recalibrate accelerometer to the initial angle of device, so that it doesn't need to be flat.
I have an object being controlled by the accelerometer. However, my device needs to be really flat and hence it is uncomfortable to play. The following is the code I have but it has issues I'm unable to fix.
Vector3 dir = new Vector3 (Input.acceleration.x, Input.acceleration.y, 0.0f);
if (dir.sqrMagnitude > 1)
dir.Normalize();
dir *= Time.deltaTime;
transform.Translate(dir * speed);
float inputX = Input.acceleration.x;
float inputY = Input.acceleration.y;
anim.SetFloat ("SpeedX", inputX);
anim.SetFloat ("SpeedY", inputY);
Vector3 recalDir = new Vector3 (Input.acceleration.x - inputX; Input.acceleration.y - inputY; 0.0f);
if (recalDir.sqrMagnitude > 1)
recalDir.Normalize();
Answer by coolbird22 · May 11, 2014 at 03:54 PM
Managed to get it to work with a different code from the Unity forums. Here it is:
Matrix4x4 calibrationMatrix;
void calibrateAccelerometer(){
Vector3 wantedDeadZone = Input.acceleration;;
Quaternion rotateQuaternion = Quaternion.FromToRotation(new Vector3(0f, 0f, -1f), wantedDeadZone);
//create identity matrix ... rotate our matrix to match up with down vec
Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, rotateQuaternion, new Vector3(1f, 1f, 1f));
//get the inverse of the matrix
this.calibrationMatrix = matrix.inverse;
}
Vector3 getAccelerometer(Vector3 accelerator){
Vector3 accel = this.calibrationMatrix.MultiplyVector(accelerator);
return accel;
}
void Start(){
calibrateAccelerometer();
}
void Update(){
Vector3 dir = getAccelerometer(Input.acceleration);
if (dir.sqrMagnitude > 1)
dir.Normalize();
dir *= Time.deltaTime;
transform.Translate(dir * speed);
}
hi.. i used your code(which is quite cool!!) but the accelerometer stopped working just jitters.. can you tell me why did you use (0, 0, -1) for rotateQuaternion? I guess, i need to change siomething in that part for my game (landscape left). Thanx in advance.
my code is:
...
***void calliberateAccel(){
wantedDeadZone = Input.acceleration;
Quaternion rotateQuaternion = Quaternion.FromToRotation (new Vector3(0f, 0f, -1f), wantedDeadZone);
$$anonymous$$atrix4x4 mat = $$anonymous$$atrix4x4.TRS (Vector3.zero, rotateQuaternion, new Vector3(1f, 1f, 1f));
caliberation$$anonymous$$atrix = mat.inverse;
}
Vector3 getAccel(Vector3 accel){
Vector3 accel2 = caliberation$$anonymous$$atrix.$$anonymous$$ultiplyVector (accel);
return accel2;
}
void Start(){
calliberateAccel();
}
void Fixedupdate(){
Vector3 inputAccel = getAccel (Input.acceleration);
float moveHorizontal = inputAccel.x * xSensitivity;
float moveVertical = inputAccel.y * zSensitivity;
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
movement.Normalize ();
movement *= Time.fixedDeltaTime *15f;
GetComponent <Rigidbody> ().velocity = movement*speed;
GetComponent<Rigidbody>().position = new Vector3
(
$$anonymous$$athf.Clamp (GetComponent<Rigidbody>().position.x, boundary.x$$anonymous$$in, boundary.x$$anonymous$$ax),
0.0f,
$$anonymous$$athf.Clamp (GetComponent<Rigidbody>().position.z, boundary.z$$anonymous$$in, boundary.z$$anonymous$$ax)
);
GetComponent<Rigidbody>().rotation = Quaternion.Euler ( -90.0f + GetComponent<Rigidbody>().velocity.x * -tilt, -90.0f, 90.0f);
}***
Answer by DMGregory · May 10, 2014 at 03:14 PM
It sounds like you want to counter-rotate your accelerometer values to adjust for what the player finds to be a comfortable "neutral" pose:
// Play with the "neutralPitch" value until you find one that feels right.
// Or you can adjust it over time to adapt to the player's (changing) pose.
Quaternion accelerometerAdjustment = Quaternion.Euler(neutralPitch, 0f, 0f);
// Each time you want to read the acceleration:
Vector3 adjustedAcceleration = accelerometerAdjustment * Input.acceleration;
float inputX = adjustedAcceleration.x;
float inputY = adjustedAcceleration.y;
// Now you can proceed as before.
Note that raw accelerometer values can be noisy - small linear accelerations like flinches/shivers or device vibration can show up as spikes, polluting the tilt information you get from gravity. You might find that Input.gyro.attitude or Input.gyro.gravity give you a more stable steering input, since they use the device's other sensors in addition to the accelerometer.
I'm not sure what you're doing with the recalDir at the bottom. It looks like it will always be a zero vector, since you're subtracting Input.acceleration.x from itself, and similarly for y.
$$anonymous$$assive thanks for replying to this. I was having a hard time figuring this out. You were right in stating that I wanted the accelerometer adjust according to what the player finds as a comfortable angle. I will look into stabilizing the noisy values, though the code you provided didn't help or maybe I'm using it wrong ? The device still needs to be flat for the object to move. Here is the code now:
Vector3 dir = new Vector3 (Input.acceleration.x, Input.acceleration.y, 0.0f);
if (dir.sqr$$anonymous$$agnitude > 1)
dir.Normalize();
dir *= Time.deltaTime;
transform.Translate(dir * speed);
Quaternion accelerometerAdjustment = Quaternion.Euler(500, 0f, 0f);
Vector3 adjustedAcceleration = accelerometerAdjustment * Input.acceleration;
float inputX = adjustedAcceleration.x;
float inputY = adjustedAcceleration.y;
anim.SetFloat ("SpeedX", inputX);
anim.SetFloat ("SpeedY", inputY);
neutral$$anonymous$$ch is an angle in degrees, so 500 really isn't a sensible value for it. You would probably want something in the +-60 range, depending on which way the coordinate system of the device works.