ardupilot/Tools/ArdupilotMegaPlanner/HIL/Quaternion.cs

151 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
namespace YLScsDrawing.Drawing3d
{
public struct Quaternion
{
public double X, Y, Z, W;
public Quaternion(double w, double x, double y, double z)
{
W = w; X = x; Y = y; Z = z;
}
public Quaternion(double w, Vector3d v)
{
W = w; X = v.X; Y = v.Y; Z = v.Z;
}
public Vector3d V
{
set { X = value.X; Y = value.Y; Z = value.Z; }
get { return new Vector3d(X, Y, Z); }
}
public void Normalise()
{
double m = W * W + X * X + Y * Y + Z * Z;
if (m > 0.001)
{
m = Math.Sqrt(m);
W /= m;
X /= m;
Y /= m;
Z /= m;
}
else
{
W = 1; X = 0; Y = 0; Z = 0;
}
}
public void Conjugate()
{
X = -X; Y = -Y; Z = -Z;
}
public void FromAxisAngle(Vector3d axis, double angleRadian)
{
double m = axis.Magnitude;
if (m > 0.0001)
{
double ca = Math.Cos(angleRadian / 2);
double sa = Math.Sin(angleRadian / 2);
X = axis.X / m * sa;
Y = axis.Y / m * sa;
Z = axis.Z / m * sa;
W = ca;
}
else
{
W = 1; X = 0; Y = 0; Z = 0;
}
}
public Quaternion Copy()
{
return new Quaternion(W, X, Y, Z);
}
public void Multiply(Quaternion q)
{
this *= q;
}
// -1
// V'=q*V*q ,
public void Rotate(Point3d pt)
{
this.Normalise();
Quaternion q1 = this.Copy();
q1.Conjugate();
Quaternion qNode = new Quaternion(0, pt.X, pt.Y, pt.Z);
qNode = this * qNode * q1;
pt.X = qNode.X;
pt.Y = qNode.Y;
pt.Z = qNode.Z;
}
public void Rotate(Point3d[] nodes)
{
this.Normalise();
Quaternion q1 = this.Copy();
q1.Conjugate();
for (int i = 0; i < nodes.Length; i++)
{
Quaternion qNode = new Quaternion(0, nodes[i].X, nodes[i].Y, nodes[i].Z);
qNode = this * qNode * q1;
nodes[i].X = qNode.X;
nodes[i].Y = qNode.Y;
nodes[i].Z = qNode.Z;
}
}
// Multiplying q1 with q2 is meaning of doing q2 firstly then q1
public static Quaternion operator *(Quaternion q1, Quaternion q2)
{
double nw = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
double nx = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
double ny = q1.W * q2.Y + q1.Y * q2.W + q1.Z * q2.X - q1.X * q2.Z;
double nz = q1.W * q2.Z + q1.Z * q2.W + q1.X * q2.Y - q1.Y * q2.X;
return new Quaternion(nw, nx, ny, nz);
}
public static Vector3d operator *(Quaternion self, Vector3d other)
{
double w = self.W;
double x = self.X;
double y = self.Y;
double z = self.Z;
double Vx = other.X;
double Vy = other.Y;
double Vz = other.Z;
double ww = w * w;
double w2 = w * 2;
double wx2 = w2 * x;
double wy2 = w2 * y;
double wz2 = w2 * z;
double xx = x * x;
double x2 = x * 2;
double xy2 = x2 * y;
double xz2 = x2 * z;
double yy = y * y;
double yz2 = 2 * y * z;
double zz = z * z;
return new Vector3d(
ww * Vx + wy2 * Vz - wz2 * Vy +
xx * Vx + xy2 * Vy + xz2 * Vz -
zz * Vx - yy * Vx,
xy2 * Vx + yy * Vy + yz2 * Vz +
wz2 * Vx - zz * Vy + ww * Vy -
wx2 * Vz - xx * Vy,
xz2 * Vx + yz2 * Vy +
zz * Vz - wy2 * Vx - yy * Vz +
wx2 * Vy - xx * Vz + ww * Vz);
}
}
}