Skip to content

Commit

Permalink
Merge pull request #31 from KalebKE/v1.2.2
Browse files Browse the repository at this point in the history
v1.2.2
  • Loading branch information
KalebKE authored Mar 29, 2020
2 parents 2b96280 + ffd7d0f commit 438ed0f
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package com.kircherelectronics.fsensor.filter.gyroscope;

import android.util.Log;

import com.kircherelectronics.fsensor.BaseFilter;
import com.kircherelectronics.fsensor.util.angle.AngleUtils;
import com.kircherelectronics.fsensor.util.rotation.RotationUtil;

import org.apache.commons.math3.complex.Quaternion;
import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.RotationConvention;
import org.apache.commons.math3.geometry.euclidean.threed.RotationOrder;

import java.util.Arrays;

/*
* Copyright 2018, Kircher Electronics, LLC
Expand Down Expand Up @@ -105,6 +99,18 @@ public float[] getOutput() {

/**
* Calculate the fused orientation of the device.
*
* Rotation is positive in the counterclockwise direction (right-hand rule). That is, an observer looking from some positive location on the x, y, or z axis at
* a device positioned on the origin would report positive rotation if the device appeared to be rotating counter clockwise. Note that this is the
* standard mathematical definition of positive rotation and does not agree with the aerospace definition of roll.
*
* See: https://source.android.com/devices/sensors/sensor-types#rotation_vector
*
* Returns a vector of size 3 ordered as:
* [0]X points east and is tangential to the ground.
* [1]Y points north and is tangential to the ground.
* [2]Z points towards the sky and is perpendicular to the ground.
*
* @param gyroscope the gyroscope measurements.
* @param timestamp the gyroscope timestamp
* @return An orientation vector -> @link SensorManager#getOrientation(float[], float[])}
Expand All @@ -115,15 +121,7 @@ public float[] calculateOrientation(float[] gyroscope, long timestamp) {
if (this.timestamp != 0) {
final float dT = (timestamp - this.timestamp) * NS2S;
rotationVectorGyroscope = RotationUtil.integrateGyroscopeRotation(rotationVectorGyroscope, gyroscope, dT, EPSILON);

Rotation rotation = new Rotation(rotationVectorGyroscope.getQ0(), rotationVectorGyroscope.getQ1(), rotationVectorGyroscope.getQ2(),
rotationVectorGyroscope.getQ3(), true);

try {
output = doubleToFloat(rotation.getAngles(RotationOrder.XYZ, RotationConvention.VECTOR_OPERATOR));
} catch(Exception e) {
Log.d(TAG, "", e);
}
output = AngleUtils.getAngles(rotationVectorGyroscope.getQ0(), rotationVectorGyroscope.getQ1(), rotationVectorGyroscope.getQ2(), rotationVectorGyroscope.getQ3());
}

this.timestamp = timestamp;
Expand Down Expand Up @@ -156,14 +154,4 @@ public void reset() {
public boolean isBaseOrientationSet() {
return rotationVectorGyroscope != null;
}

private static float[] doubleToFloat(double[] values) {
float[] f = new float[values.length];

for(int i = 0; i < f.length; i++){
f[i] = (float) values[i];
}

return f;
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package com.kircherelectronics.fsensor.filter.gyroscope.fusion.complementary;

import android.util.Log;

import com.kircherelectronics.fsensor.filter.gyroscope.fusion.OrientationFused;
import com.kircherelectronics.fsensor.util.angle.AngleUtils;
import com.kircherelectronics.fsensor.util.rotation.RotationUtil;

import org.apache.commons.math3.complex.Quaternion;
import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.RotationConvention;
import org.apache.commons.math3.geometry.euclidean.threed.RotationOrder;

/*
* Copyright 2018, Kircher Electronics, LLC
Expand Down Expand Up @@ -97,11 +93,21 @@ public OrientationFusedComplementary(float timeConstant) {

/**
* Calculate the fused orientation of the device.
*
* Rotation is positive in the counterclockwise direction (right-hand rule). That is, an observer looking from some positive location on the x, y, or z axis at
* a device positioned on the origin would report positive rotation if the device appeared to be rotating counter clockwise. Note that this is the
* standard mathematical definition of positive rotation and does not agree with the aerospace definition of roll.
*
* See: https://source.android.com/devices/sensors/sensor-types#rotation_vector
*
* Returns a vector of size 3 ordered as:
* [0]X points east and is tangential to the ground.
* [1]Y points north and is tangential to the ground.
* [2]Z points towards the sky and is perpendicular to the ground.
*
* @param gyroscope the gyroscope measurements.
* @param timestamp the gyroscope timestamp
* @param acceleration the acceleration measurements
* @param magnetic the magnetic measurements
* @return the fused orientation estimation.
* @return An orientation vector -> @link SensorManager#getOrientation(float[], float[])}
*/
public float[] calculateFusedOrientation(float[] gyroscope, long timestamp, float[] acceleration, float[] magnetic) {
if (isBaseOrientationSet()) {
Expand Down Expand Up @@ -130,14 +136,7 @@ public float[] calculateFusedOrientation(float[] gyroscope, long timestamp, floa
(scaledRotationVectorAccelerationMagnetic);
}

Rotation rotation = new Rotation(rotationVectorGyroscope.getQ0(), rotationVectorGyroscope.getQ1(), rotationVectorGyroscope.getQ2(),
rotationVectorGyroscope.getQ3(), true);

try {
output = doubleToFloat(rotation.getAngles(RotationOrder.XYZ, RotationConvention.VECTOR_OPERATOR));
} catch(Exception e) {
Log.d(TAG, "", e);
}
output = AngleUtils.getAngles(rotationVectorGyroscope.getQ0(), rotationVectorGyroscope.getQ1(), rotationVectorGyroscope.getQ2(), rotationVectorGyroscope.getQ3());
}

this.timestamp = timestamp;
Expand All @@ -147,14 +146,4 @@ public float[] calculateFusedOrientation(float[] gyroscope, long timestamp, floa
throw new IllegalStateException("You must call setBaseOrientation() before calling calculateFusedOrientation()!");
}
}

private static float[] doubleToFloat(double[] values) {
float[] f = new float[values.length];

for(int i = 0; i < f.length; i++){
f[i] = (float) values[i];
}

return f;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
import com.kircherelectronics.fsensor.filter.gyroscope.fusion.kalman.filter.RotationKalmanFilter;
import com.kircherelectronics.fsensor.filter.gyroscope.fusion.kalman.filter.RotationMeasurementModel;
import com.kircherelectronics.fsensor.filter.gyroscope.fusion.kalman.filter.RotationProcessModel;
import com.kircherelectronics.fsensor.util.angle.AngleUtils;
import com.kircherelectronics.fsensor.util.rotation.RotationUtil;

import org.apache.commons.math3.complex.Quaternion;
import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.RotationConvention;
import org.apache.commons.math3.geometry.euclidean.threed.RotationOrder;

import java.util.Arrays;

Expand Down Expand Up @@ -63,8 +61,6 @@ public class OrientationFusedKalman extends OrientationFused {
private static final String TAG = OrientationFusedComplementary.class.getSimpleName();

private RotationKalmanFilter kalmanFilter;
private RotationProcessModel pm;
private RotationMeasurementModel mm;
private volatile boolean run;
private volatile float dT;
private volatile float[] output = new float[3];
Expand All @@ -78,11 +74,7 @@ public OrientationFusedKalman() {

public OrientationFusedKalman(float timeConstant) {
super(timeConstant);

pm = new RotationProcessModel();
mm = new RotationMeasurementModel();

kalmanFilter = new RotationKalmanFilter(pm, mm);
kalmanFilter = new RotationKalmanFilter(new RotationProcessModel(), new RotationMeasurementModel());
}

public void startFusion() {
Expand Down Expand Up @@ -124,6 +116,22 @@ public float[] getOutput() {
return output;
}

/**
* Calculate the fused orientation of the device.
*
* Rotation is positive in the counterclockwise direction (right-hand rule). That is, an observer looking from some positive location on the x, y, or z axis at
* a device positioned on the origin would report positive rotation if the device appeared to be rotating counter clockwise. Note that this is the
* standard mathematical definition of positive rotation and does not agree with the aerospace definition of roll.
*
* See: https://source.android.com/devices/sensors/sensor-types#rotation_vector
*
* Returns a vector of size 3 ordered as:
* [0]X points east and is tangential to the ground.
* [1]Y points north and is tangential to the ground.
* [2]Z points towards the sky and is perpendicular to the ground.
*
* @return An orientation vector -> @link SensorManager#getOrientation(float[], float[])}
*/
private float[] calculate() {
if (rotationVectorGyroscope != null && rotationOrientation != null && dT != 0) {

Expand Down Expand Up @@ -151,14 +159,7 @@ private float[] calculate() {
rotationVectorGyroscope = new Quaternion(kalmanFilter.getStateEstimation()[3],
Arrays.copyOfRange(kalmanFilter.getStateEstimation(), 0, 3));

Rotation rotation = new Rotation(rotationVectorGyroscope.getQ0(), rotationVectorGyroscope.getQ1(), rotationVectorGyroscope.getQ2(),
rotationVectorGyroscope.getQ3(), true);

try {
output = doubleToFloat(rotation.getAngles(RotationOrder.XYZ, RotationConvention.VECTOR_OPERATOR));
} catch(Exception e) {
Log.d(TAG, "", e);
}
output = AngleUtils.getAngles(rotationVectorGyroscope.getQ0(), rotationVectorGyroscope.getQ1(), rotationVectorGyroscope.getQ2(), rotationVectorGyroscope.getQ3());

return output;
}
Expand Down Expand Up @@ -191,14 +192,4 @@ public float[] calculateFusedOrientation(float[] gyroscope, long timestamp, floa
throw new IllegalStateException("You must call setBaseOrientation() before calling calculateFusedOrientation()!");
}
}

private static float[] doubleToFloat(double[] values) {
float[] f = new float[values.length];

for(int i = 0; i < f.length; i++){
f[i] = (float) values[i];
}

return f;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.kircherelectronics.fsensor.util.angle;

import android.util.Log;

public class AngleUtils {
private static final String TAG = AngleUtils.class.getSimpleName();

/**
* https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm
*
* +X to the right
* +Y straight up
* +Z axis toward viewer
*
* Heading = rotation about y axis
* Attitude = rotation about z axis
* Bank = rotation about x axis
*
* Heading applied first
* Attitude applied second
* Bank applied last
*
* @param w
* @param z
* @param x
* @param y
* @return
*/
public static float[] getAngles(double w, double z, double x, double y) {
double heading;
double pitch;
double roll;

double test = x*y + z*w;
if (test > 0.499) { // singularity at north pole
heading = 2 * Math.atan2(x,w);
pitch = -Math.PI/2;
roll = 0;
Log.e(TAG, "singularity at north pole");
return new float[]{(float)heading, (float)pitch, (float)roll};
}
if (test < -0.499) { // singularity at south pole
heading = -2 * Math.atan2(x,w);
pitch = Math.PI/2;
roll = 0;
Log.e(TAG, "singularity at south pole");
return new float[]{(float)heading, (float)pitch, (float)roll};
}
double sqx = x*x;
double sqy = y*y;
double sqz = z*z;
heading = Math.atan2(2*y*w-2*x*z , 1 - 2*sqy - 2*sqz);
pitch = -Math.asin(2*test);
roll = -Math.atan2(2*x*w-2*y*z , 1 - 2*sqx - 2*sqz);

return new float[]{(float)pitch,(float)roll, (float)heading};
}
}

0 comments on commit 438ed0f

Please sign in to comment.