NETMF_Autopilot/Rotation.cs

267 lines
7.9 KiB
C#

using System;
using Microsoft.SPOT;
using GHIElectronics.NETMF.System;
namespace PlaneOnBoardSoftware
{
public class Vector3D
{
public float X;
public float Y;
public float Z;
private static float degPerPi = 57.29577951308f;
public static Vector3D xAxis = new Vector3D(1, 0, 0);
public static Vector3D yAxis = new Vector3D(0, 1, 0);
public static Vector3D zAxis = new Vector3D(0, 0, 1);
public Vector3D()
{
this.X = 0;
this.Y = 0;
this.Z = 0;
}
public Vector3D(float x, float y, float z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
public float Length
{
get { return (float)MathEx.Sqrt(X * X + Y * Y + Z * Z); }
}
public Vector3D Normated()
{
return new Vector3D(X / Length, Y / Length, Z / Length);
}
public static float VectorAngle(Vector3D Vector1, Vector3D Vector2)
{
return (float)MathEx.Acos(DotProduct(Vector1, Vector2) / Vector1.Length / Vector2.Length) * degPerPi;
}
public static float DotProduct(Vector3D Vector1, Vector3D Vector2)
{
return Vector1.X * Vector2.X + Vector1.Y * Vector2.Y + Vector1.Z * Vector2.Z;
}
public static Vector3D CrossProduct(Vector3D Vector1, Vector3D Vector2)
{
Vector3D result = new Vector3D();
result.X = Vector1.Y * Vector2.Z - Vector1.Z * Vector2.Y;
result.Y = Vector1.Z * Vector2.X - Vector1.X * Vector2.Z;
result.Z = Vector1.X * Vector2.Y - Vector1.Y * Vector2.X;
return result;
}
public static Vector3D operator *(Vector3D c1, Vector3D c2)
{
return CrossProduct(c1, c2);
}
}
public class Quaternion
{
public float X;
public float Y;
public float Z;
public float W;
private static float degPerPi = 57.29577951308f;
public Quaternion()
{
this.X = 0;
this.Y = 0;
this.Z = 0;
this.W = 1;
}
public Quaternion(float x, float y, float z, float w)
{
this.X = x;
this.Y = y;
this.Z = z;
this.W = w;
}
public Quaternion(Vector3D RotationAxis, float Angle)
{
Angle = Angle / degPerPi / 2;
float c = (float)MathEx.Cos(Angle);
float s = (float)MathEx.Sin(Angle);
if (RotationAxis.Length > float.Epsilon)
{
RotationAxis = RotationAxis.Normated();
X = RotationAxis.X * s;
Y = RotationAxis.Y * s;
Z = RotationAxis.Z * s;
W = c;
}
else
{
X = 0; Y = 0; Z = 0;
W = 1;
}
}
public static Quaternion GetFastQuaternion(Vector3D NormatedRotationAxis, float Angle)
{
Angle = Angle / degPerPi / 2f;
float s = (float)MathEx.Sin(Angle);
return new Quaternion(NormatedRotationAxis.X * s, NormatedRotationAxis.Y * s, NormatedRotationAxis.Z * s, (float)MathEx.Cos(Angle));
}
public void XAxisTurn(float Angle)
{
Angle = Angle / degPerPi / 2f;
float s = (float)MathEx.Sin(Angle);
float c = (float)MathEx.Cos(Angle);
float tx = X; //s
float ty = Y; //0
float tz = Z; //0
float tw = W; //c
W = tw * c - tx * s;
X = tw * s + tx * c;
Y = ty * c + tz * s;
Z = -ty * s + tz * c;
}
public void YAxisTurn(float Angle)
{
Angle = Angle / degPerPi / 2f;
float s = (float)MathEx.Sin(Angle);
float c = (float)MathEx.Cos(Angle);
float tx = X; //0
float ty = Y; //s
float tz = Z; //0
float tw = W; //c
W = tw * c - ty * s;
X = tx * c - tz * s;
Y = tw * s + ty * c;
Z = tx * s + tz * c;
}
public void ZAxisTurn(float Angle)
{
Angle = Angle / degPerPi / 2f;
float s = (float)MathEx.Sin(Angle);
float c = (float)MathEx.Cos(Angle);
float tx = X; //0
float ty = Y; //0
float tz = Z; //s
float tw = W; //c
W = tw * c - tz * s;
X = tx * c + ty * s;
Y = -tx * s + ty * c;
Z = tw * s + tz * c;
}
public float Angle
{
get { return (float)MathEx.Acos(W) * 2.0f * degPerPi; }
}
public static Quaternion operator *(Quaternion c1, Quaternion c2)
{
return hamiltonProduct(c1, c2);
}
private static Quaternion hamiltonProduct(Quaternion q1, Quaternion q2)
{
var result = new Quaternion();
result.W = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
result.X = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
result.Y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X;
result.Z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W;
return result;
}
public void Normate()
{
float length = (float)MathEx.Sqrt(X * X + Y * Y + Z * Z);
X = X / length;
Y = Y / length;
Z = Z / length;
}
public Quaternion Conjugate()
{
return new Quaternion(W, -X, -Y, -Z);
}
public Vector3D RotateVector(Vector3D Vector)
{
return QuaternionRotation(this, Vector);
}
private static Vector3D QuaternionRotation(Quaternion q, Vector3D v)
{
Vector3D result = new Vector3D();
float a00 = q.W * q.W;
float a01 = q.W * q.X;
float a02 = q.W * q.Y;
float a03 = q.W * q.Z;
float a11 = q.X * q.X;
float a12 = q.X * q.Y;
float a13 = q.X * q.Z;
float a22 = q.Y * q.Y;
float a23 = q.Y * q.Z;
float a33 = q.Z * q.Z;
result.X = v.X * (a00 + a11 - a22 - a33) + 2 * (a12 * v.Y + a13 * v.Z + a02 * v.Z - a03 * v.Y);
result.Y = v.Y * (a00 - a11 + a22 - a33) + 2 * (a12 * v.X + a23 * v.Z + a03 * v.X - a01 * v.Z);
result.Z = v.Z * (a00 - a11 - a22 + a33) + 2 * (a13 * v.X + a23 * v.Y - a02 * v.X + a01 * v.Y);
return result;
}
public Vector3D GetEulerAngles()
{
return GetEulerAnglesFromQuaternion(this);
}
private static Vector3D GetEulerAnglesFromQuaternion(Quaternion q)
{
Vector3D result = new Vector3D();
float a01 = 2 * q.W * q.X;
float a02 = 2 * q.W * q.Y;
float a03 = 2 * q.W * q.Z;
float a11 = 2 * q.X * q.X;
float a12 = 2 * q.X * q.Y;
float a13 = 2 * q.X * q.Z;
float a22 = 2 * q.Y * q.Y;
float a23 = 2 * q.Y * q.Z;
float a33 = 2 * q.Z * q.Z;
//result.Y = (float)MathEx.Atan2(a01 + a23, 1 - (a11 + a22)) * degPerPi;
//result.X = (float)MathEx.Asin(a02 - a13) * degPerPi;
//result.Z = (float)MathEx.Atan2(a03 + a12, 1 - (a22 + a33)) * degPerPi;
result.Y = (float)MathEx.Atan2(a02 - a13, 1 - (a22 + a11)) * degPerPi;
result.X = (float)MathEx.Asin(a01 + a23) * degPerPi;
result.Z = (float)MathEx.Atan2(a03 - a12, 1 - (a11 + a33)) * degPerPi;
return result;
}
}
}