package com.o3dr.services.android.lib.drone.companion.solo.tlv.mpcc;
import android.os.Parcel;
import com.o3dr.services.android.lib.coordinate.LatLongAlt;
import com.o3dr.services.android.lib.drone.companion.solo.tlv.TLVMessageTypes;
import com.o3dr.services.android.lib.drone.companion.solo.tlv.TLVPacket;
import java.nio.ByteBuffer;
/**
* Bidirectional
* <p/>
* Used to transmit proposed or actual Keypoints on the current camera Path.
* <p/>
* Shotmanager uses this message for two things:
* To transmit Keypoints it creates in response to Artoo button presses or SOLO_MESSAGE_RECORD_POSITION messages.
* To confirm the validity of Keypoints it receives from the app; to ACK those Keypoints.
* <p/>
* When shotmanager creates a Keypoint, it assigns an index. When the app receives this message and a Keypoint with the index already exists, it updates the Keypoint to the values in this message; it replaces the existing Keypoint.
* <p/>
* The app uses this message to load Keypoints from previously recorded, known valid Paths into shotmanager.
* <p/>
* In every case, shotmanager sends a SOLO_SPLINE_POINT message back to the app to confirm it was able to create the Keypoint. If it can't create the Keypoint, it sends a failure status.
* <p/>
* <p/>
* Created by Fredia Huya-Kouadio on 12/8/15.
*
* @since 2.8.0
*/
public class SoloSplinePoint extends TLVPacket {
public static final int MESSAGE_LENGTH = 44;
public static final short STATUS_SUCCESS = 0;
public static final short STATUS_MODE_ERROR = -1; //tried setting a spline point when we were already in PLAY mode
public static final short STATUS_KEYPOINTS_TOO_CLOSE_ERROR = -2; //Keypoint too close to a previous keypoint
public static final short STATUS_DUPLICATE_INDEX_ERROR = -3; //Received multiple keypoints for a single index.
private short version;
/**
* Absolute altitude of home location when cable was recorded, in meters.
*/
private float absAltReference;
/**
* starting at 0
*/
private int index;
/**
* Latitude (decimal degrees). Longitude (decimal degrees). Relative altitude in meters.
*/
private LatLongAlt coordinate;
/**
* Pitch (degrees).
*/
private float pitch;
/**
* Yaw (degrees)
*/
private float yaw;
/**
* Parametric offset of the Keypoint along the Path.
* In Record mode, these values have no meaning since they can't be assigned until the Path is complete.
* In Play mode, shotmanager assigns these values and sends messages to the app.
* The app never creates these values.
*/
private float uPosition;
/**
* Shotmanager sends this value to indicate success or failure when creating a Keypoint.
* Negative values are failure;
* 0 or positive is success.
*
* -1 : mode error (tried setting a spline point when we were already in PLAY mode).
* -2 : keypoint too close to a previous keypoint
* -3 : duplicate index error (received multiple Keypoints for a single index)
* -4..-MAXINT16 : unspecified failure
*/
private short status;
public SoloSplinePoint(short version, float absAltReference, int index, LatLongAlt coordinate,
float pitch, float yaw, float uPosition, short status) {
super(TLVMessageTypes.TYPE_SOLO_SPLINE_POINT, MESSAGE_LENGTH);
this.version = version;
this.absAltReference = absAltReference;
this.coordinate = coordinate;
this.index = index;
this.pitch = pitch;
this.status = status;
this.uPosition = uPosition;
this.yaw = yaw;
}
public SoloSplinePoint(ByteBuffer dataBuffer){
this(dataBuffer.getShort(),
dataBuffer.getFloat(),
dataBuffer.getInt(),
new LatLongAlt(dataBuffer.getDouble(), dataBuffer.getDouble(), dataBuffer.getFloat()),
dataBuffer.getFloat(),
dataBuffer.getFloat(),
dataBuffer.getFloat(),
dataBuffer.getShort());
}
@Override
protected void getMessageValue(ByteBuffer valueCarrier){
valueCarrier.putShort(version);
valueCarrier.putFloat(absAltReference);
valueCarrier.putInt(index);
valueCarrier.putDouble(coordinate.getLatitude());
valueCarrier.putDouble(coordinate.getLongitude());
valueCarrier.putFloat((float) coordinate.getAltitude());
valueCarrier.putFloat(pitch);
valueCarrier.putFloat(yaw);
valueCarrier.putFloat(uPosition);
valueCarrier.putShort(status);
}
public short getVersion() {
return version;
}
public float getAbsAltReference() {
return absAltReference;
}
public LatLongAlt getCoordinate() {
return coordinate;
}
public int getIndex() {
return index;
}
public float getPitch() {
return pitch;
}
public short getStatus() {
return status;
}
public float getUPosition() {
return uPosition;
}
public float getYaw() {
return yaw;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(version);
dest.writeFloat(absAltReference);
dest.writeInt(this.index);
dest.writeParcelable(this.coordinate, 0);
dest.writeFloat(this.pitch);
dest.writeFloat(this.yaw);
dest.writeFloat(this.uPosition);
dest.writeInt(this.status);
}
protected SoloSplinePoint(Parcel in) {
super(in);
this.version = (short) in.readInt();
this.absAltReference = in.readFloat();
this.index = in.readInt();
this.coordinate = in.readParcelable(LatLongAlt.class.getClassLoader());
this.pitch = in.readFloat();
this.yaw = in.readFloat();
this.uPosition = in.readFloat();
this.status = (short) in.readInt();
}
public static final Creator<SoloSplinePoint> CREATOR = new Creator<SoloSplinePoint>() {
public SoloSplinePoint createFromParcel(Parcel source) {
return new SoloSplinePoint(source);
}
public SoloSplinePoint[] newArray(int size) {
return new SoloSplinePoint[size];
}
};
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
SoloSplinePoint that = (SoloSplinePoint) o;
if (version != that.version) {
return false;
}
if (Float.compare(that.absAltReference, absAltReference) != 0) {
return false;
}
if (index != that.index) {
return false;
}
if (Float.compare(that.pitch, pitch) != 0) {
return false;
}
if (Float.compare(that.yaw, yaw) != 0) {
return false;
}
if (Float.compare(that.uPosition, uPosition) != 0) {
return false;
}
if (status != that.status) {
return false;
}
return coordinate.equals(that.coordinate);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (int) version;
result = 31 * result + (absAltReference != +0.0f ? Float.floatToIntBits(absAltReference) : 0);
result = 31 * result + index;
result = 31 * result + coordinate.hashCode();
result = 31 * result + (pitch != +0.0f ? Float.floatToIntBits(pitch) : 0);
result = 31 * result + (yaw != +0.0f ? Float.floatToIntBits(yaw) : 0);
result = 31 * result + (uPosition != +0.0f ? Float.floatToIntBits(uPosition) : 0);
result = 31 * result + (int) status;
return result;
}
@Override
public String toString() {
return "SoloSplinePoint{" +
"version=" + version +
", absAltReference=" + absAltReference +
", index=" + index +
", coordinate=" + coordinate +
", pitch=" + pitch +
", yaw=" + yaw +
", uPosition=" + uPosition +
", status=" + status +
'}';
}
}