package com.o3dr.services.android.lib.drone.property;
import android.os.Parcel;
import android.os.Parcelable;
import com.MAVLink.enums.EKF_STATUS_FLAGS;
import java.util.BitSet;
/**
* Abstraction for vehicle EFK status. See http://copter.ardupilot.com/wiki/common-apm-navigation-extended-kalman-filter-overview/
*/
public class EkfStatus implements DroneAttribute {
private static final int FLAGS_BIT_COUNT = 16;
public enum EkfFlags {
EKF_ATTITUDE(EKF_STATUS_FLAGS.EKF_ATTITUDE),
EKF_VELOCITY_HORIZ(EKF_STATUS_FLAGS.EKF_VELOCITY_HORIZ),
EKF_VELOCITY_VERT(EKF_STATUS_FLAGS.EKF_VELOCITY_VERT),
EKF_POS_HORIZ_REL(EKF_STATUS_FLAGS.EKF_POS_HORIZ_REL),
EKF_POS_HORIZ_ABS(EKF_STATUS_FLAGS.EKF_POS_HORIZ_ABS),
EKF_POS_VERT_ABS(EKF_STATUS_FLAGS.EKF_POS_VERT_ABS),
EKF_POS_VERT_AGL(EKF_STATUS_FLAGS.EKF_POS_VERT_AGL),
EKF_CONST_POS_MODE(EKF_STATUS_FLAGS.EKF_CONST_POS_MODE),
EKF_PRED_POS_HORIZ_REL(EKF_STATUS_FLAGS.EKF_PRED_POS_HORIZ_REL),
EKF_PRED_POS_HORIZ_ABS(EKF_STATUS_FLAGS.EKF_PRED_POS_HORIZ_ABS);
final int value;
EkfFlags(int value) {
this.value = value;
}
}
private float velocityVariance;
private float horizontalPositionVariance;
private float verticalPositionVariance;
private float compassVariance;
private float terrainAltitudeVariance;
private final BitSet flags;
public EkfStatus() {
this.flags = new BitSet(FLAGS_BIT_COUNT);
}
public EkfStatus(int flags, float compassVariance, float horizontalPositionVariance, float
terrainAltitudeVariance, float velocityVariance, float verticalPositionVariance) {
this();
this.compassVariance = compassVariance;
this.horizontalPositionVariance = horizontalPositionVariance;
this.terrainAltitudeVariance = terrainAltitudeVariance;
this.velocityVariance = velocityVariance;
this.verticalPositionVariance = verticalPositionVariance;
fromShortToBitSet(flags);
}
private void fromShortToBitSet(int flags) {
final EkfFlags[] ekfFlags = EkfFlags.values();
final int ekfFlagsCount = ekfFlags.length;
for (int i = 0; i < ekfFlagsCount; i++) {
this.flags.set(i, (flags & ekfFlags[i].value) != 0);
}
}
public float getTerrainAltitudeVariance() {
return terrainAltitudeVariance;
}
public void setTerrainAltitudeVariance(float terrainAltitudeVariance) {
this.terrainAltitudeVariance = terrainAltitudeVariance;
}
public float getVelocityVariance() {
return velocityVariance;
}
public void setVelocityVariance(float velocityVariance) {
this.velocityVariance = velocityVariance;
}
public float getVerticalPositionVariance() {
return verticalPositionVariance;
}
public void setVerticalPositionVariance(float verticalPositionVariance) {
this.verticalPositionVariance = verticalPositionVariance;
}
public float getHorizontalPositionVariance() {
return horizontalPositionVariance;
}
public void setHorizontalPositionVariance(float horizontalPositionVariance) {
this.horizontalPositionVariance = horizontalPositionVariance;
}
public float getCompassVariance() {
return compassVariance;
}
public void setCompassVariance(float compassVariance) {
this.compassVariance = compassVariance;
}
public boolean isEkfFlagSet(EkfFlags flag){
return flags.get(flag.ordinal());
}
/**
* Returns true if the horizontal absolute position is ok, and home position is set.
*
* @param armed
* @return
*/
public boolean isPositionOk(boolean armed) {
if (armed) {
return this.flags.get(EkfFlags.EKF_POS_HORIZ_ABS.ordinal())
&& !this.flags.get(EkfFlags.EKF_CONST_POS_MODE.ordinal());
} else {
return this.flags.get(EkfFlags.EKF_POS_HORIZ_ABS.ordinal())
|| this.flags.get(EkfFlags.EKF_PRED_POS_HORIZ_ABS.ordinal());
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeFloat(this.velocityVariance);
dest.writeFloat(this.horizontalPositionVariance);
dest.writeFloat(this.verticalPositionVariance);
dest.writeFloat(this.compassVariance);
dest.writeFloat(this.terrainAltitudeVariance);
dest.writeSerializable(this.flags);
}
private EkfStatus(Parcel in) {
this.velocityVariance = in.readFloat();
this.horizontalPositionVariance = in.readFloat();
this.verticalPositionVariance = in.readFloat();
this.compassVariance = in.readFloat();
this.terrainAltitudeVariance = in.readFloat();
this.flags = (BitSet) in.readSerializable();
}
public static final Parcelable.Creator<EkfStatus> CREATOR = new Parcelable.Creator<EkfStatus>() {
public EkfStatus createFromParcel(Parcel source) {
return new EkfStatus(source);
}
public EkfStatus[] newArray(int size) {
return new EkfStatus[size];
}
};
}