public Vector Mul( Vector v1 ) { Vector r = new Vector(); for (int i = 0; i < 3; i++) { r.v[i] = 0.0f; for (int j = 0; j < 3; j++) { r.v[i] += m[i, j] * v1.v[j]; } } return r; }
void ComputeAngularVelocities() { Vector Axis; Quaternion qrot = follow.Conjugate() * quat; float angle = qrot.ToAngleAxis( out Axis ); Vector angularDisplacement = Axis * angle; // * Mathf.Deg2Rad; //Vector angularSpeed = angularDisplacement / Time.deltaTime; Velocities = angularDisplacement; // It's possible for this to accumulate extra spins, apparently - will need to be clamped -PI to +PI follow = follow.Slerp( quat, 0.05f ); matFollow.From( follow ); }
void BuildCube() { CubePt[0] = new Vector( -cubeWidth, -cubeHeight, -cubeDepth ); CubePt[1] = new Vector( -cubeWidth, cubeHeight, -cubeDepth ); CubePt[2] = new Vector( cubeWidth, -cubeHeight, -cubeDepth ); CubePt[3] = new Vector( cubeWidth, cubeHeight, -cubeDepth ); CubePt[4] = new Vector( -cubeWidth, -cubeHeight, cubeDepth ); CubePt[5] = new Vector( -cubeWidth, cubeHeight, cubeDepth ); CubePt[6] = new Vector( cubeWidth, -cubeHeight, cubeDepth ); CubePt[7] = new Vector( cubeWidth, cubeHeight, cubeDepth ); CubePt[8] = new Vector( 0, 0, cubeDepth - 0.1f ); CubePt[9] = new Vector( 0, 0, cubeDepth + 0.1f ); Invalidate(); }
void BuildCube() { CubePt[0] = new Vector( -cubeWidth, -cubeHeight, -cubeDepth ); CubePt[1] = new Vector( -cubeWidth, cubeHeight, -cubeDepth ); CubePt[2] = new Vector( cubeWidth, -cubeHeight, -cubeDepth ); CubePt[3] = new Vector( cubeWidth, cubeHeight, -cubeDepth ); CubePt[4] = new Vector( -cubeWidth, -cubeHeight, cubeDepth ); CubePt[5] = new Vector( -cubeWidth, cubeHeight, cubeDepth ); CubePt[6] = new Vector( cubeWidth, -cubeHeight, cubeDepth ); CubePt[7] = new Vector( cubeWidth, cubeHeight, cubeDepth ); CubePt[8] = new Vector( 0, 0, cubeDepth - 0.1f ); CubePt[9] = new Vector( 0, 0, cubeDepth + 0.1f ); for(int i = 0; i < 16; i++) { QuadPt[i] = new Vector( Quad2d[i].X * cubeWidth, -cubeHeight * 0.1f, Quad2d[i].Y * cubeDepth ); QuadPt[i+16] = new Vector( Quad2d[i].X * cubeWidth, +cubeHeight * 0.1f, Quad2d[i].Y * cubeDepth ); } QuadPt[32] = new Vector( 0.0f, 0.0f, 0.3f * cubeDepth ); QuadPt[33] = new Vector( 0.0f, 0.0f, 0.5f * cubeDepth ); Invalidate(); }
void DrawShape( Graphics g, Matrix m, Color col, Vector[] points, int[] lines ) { for(int i = 0; i < points.Length; i++) { pt[i] = m.Mul( points[i] ); } for(int i = 0; i < points.Length; i++) { pt[i].v[2] += ViewDist; if(pt[i].v[2] == 0) { pt[i].v[2] = 0.0001f; } pt[i].v[0] /= pt[i].v[2]; pt[i].v[1] /= pt[i].v[2]; } Pen penCol = new Pen( col ); PointF[] cb = new PointF[2]; for(int i = 0; i < lines.Length; i += 2) { cb[0].X = pt[lines[i]].v[0]; cb[0].Y = pt[lines[i]].v[1]; cb[1].X = pt[lines[i + 1]].v[0]; cb[1].Y = pt[lines[i + 1]].v[1]; cb[0].X = cb[0].X * DrawScale + CenterX; cb[0].Y = cb[0].Y * -DrawScale + CenterY; cb[1].X = cb[1].X * DrawScale + CenterX; cb[1].Y = cb[1].Y * -DrawScale + CenterY; g.DrawLine( penCol, cb[0], cb[1] ); } }
// Returns an angle and an axis that represents the rotation of the quaternion public float ToAngleAxis( out Vector Axis ) { float tw = Math.Min( w, 1.0f ); float angle = 2.0f * (float)Math.Acos( tw ); Axis = new Vector(); float s = (float)Math.Sqrt( 1.0f - tw*tw ); // assuming quaternion normalised then w is less than 1, so term always positive. s = Math.Max( s, 0.001f ); // prevent divide by zero Axis.x = x / s; // normalise axis Axis.y = y / s; Axis.z = z / s; return angle; }
private float ComputeTiltCompensatedHeading() { // Compute pitch and roll from the current accelerometer vector - only accurate if stationary Vector v = new Vector( AccelX, AccelY, AccelZ ); v = v.Normalize(); float accPitch = (float)Math.Asin( -v.x ); float accRoll = (float)Math.Asin( v.y / Math.Cos(accPitch) ); // Technically we should also calibrate the min/max readings from the mag first - this may not be accurate otherwise float Mxh = (float)(MagX * Math.Cos( accPitch ) + MagZ * Math.Sin( accPitch )); float Myh = (float)(MagX * Math.Sin( accRoll ) * Math.Sin( accPitch ) + MagY * Math.Cos( accRoll ) - MagZ * Math.Sin( accRoll ) * Math.Cos( accPitch )); float Heading = (float)(Math.Atan2( Mxh, Myh ) * 1800.0 / Math.PI); return Heading; }
private void ComputeAltitudeEstimate() { acc = new Vector( -AccelX, AccelZ, AccelY ); acc *= 1.0f * AccScale; // Get gravity vector from orentation matrix Vector gravity = new Vector( m.m[1,0], m.m[1,1], m.m[1,2] ); // Subtract from accelerometer vector to get directional forces acc -= gravity; // acc is now m/s^2 acc *= 9.8f; // Orient accelerometer vector (or at least just Z component) Vector forceW = m.Transpose().Mul( acc ); // Compute the vertical velocity from the altimeter altVelocity = ((float)(Alt - prevAlt) / 1000.0f) * UpdateRate; // Now in M/s // Integrate accelerometer vector to get velocity (m/sec) velocityEstimate += forceW * (1.0f / UpdateRate); // Use the altimeter velocity estimate to drift correct the computed velocity velocityEstimate.y = velocityEstimate.y * 0.998f + altVelocity * 0.002f; // Integrate Z velocity to get approximate height (in meters) positionEstimate += velocityEstimate * (1.0f / UpdateRate); // Slowly un-drift the Y position estimate with the altimeter over time positionEstimate.y = (positionEstimate.y * 0.998f) + (((float)Alt / 1000.0f) * 0.002f); lblStatOutput.Text = string.Format( "{0:0.00} {1:0.000}", positionEstimate.y, velocityEstimate.y ); }
void ComputeQuatAlternateMethod() { // Trapezoidal integration of gyro readings float rx = (float)((GyroX+lastGx)*0.5f - GZeroX) * GyroScale + errCorrX2; float ry = (float)((GyroZ+lastGz)*0.5f - GZeroZ) * -GyroScale + errCorrY2; float rz = (float)((GyroY+lastGy)*0.5f - GZeroY) * -GyroScale + errCorrZ2; lastGx = GyroX; lastGy = GyroY; lastGz = GyroZ; float rMag = (float)(Math.Sqrt(rx * rx + ry * ry + rz * rz + 0.0000000001) * 0.5); float cosr = (float)Math.Cos(rMag); float sinr = (float)Math.Sin(rMag) / rMag; qdot.w = -(rx * Q2.x + ry * Q2.y + rz * Q2.z) * 0.5f; qdot.x = (rx * Q2.w + rz * Q2.y - ry * Q2.z) * 0.5f; qdot.y = (ry * Q2.w - rz * Q2.x + rx * Q2.z) * 0.5f; qdot.z = (rz * Q2.w + ry * Q2.x - rx * Q2.y) * 0.5f; Q2.w = cosr * Q2.w + sinr * qdot.w; Q2.x = cosr * Q2.x + sinr * qdot.x; Q2.y = cosr * Q2.y + sinr * qdot.y; Q2.z = cosr * Q2.z + sinr * qdot.z; Q2 = Q2.Normalize(); // Convert to matrix form m2.From(Q2); // Compute the difference between the accelerometer vector and the matrix Y (up) vector acc = new Vector( -AccelX, AccelZ, AccelY ); rMag = acc.Length * AccScale; acc = acc.Normalize(); float accWeight = 1.0f - Math.Min( Math.Abs( 2.0f - rMag * 2.0f ), 1.0f ); // accWeight *= accWeight * 4.0f; float errDiffX = acc.y * m2.m[1,2] - acc.z * m2.m[1,1]; float errDiffY = acc.z * m2.m[1,0] - acc.x * m2.m[1,2]; float errDiffZ = acc.x * m2.m[1,1] - acc.y * m2.m[1,0]; accWeight *= 1.0f / 512.0f; errCorrX2 = errDiffX * accWeight; errCorrY2 = errDiffY * accWeight; errCorrZ2 = errDiffZ * accWeight; // At this point, errCorr represents a very small correction rotation vector, but in the WORLD frame // Rotate it into the current BODY frame //Vector errVect = new Vector( errCorrX2, errCorrY2, errCorrZ2 ); //errVect = m.Transpose().Mul( errVect ); //errCorrX2 = errVect.x; //errCorrY2 = errVect.y; //errCorrZ2 = errVect.z; }
void ComputeQuatOriginalMethod() { float rx = (float)(GyroX - GZeroX) * GyroScale + errCorrX1; float ry = (float)(GyroZ - GZeroZ) * -GyroScale + errCorrY1; float rz = (float)(GyroY - GZeroY) * -GyroScale + errCorrZ1; float rMag = (float)(Math.Sqrt(rx * rx + ry * ry + rz * rz + 0.0000000001) * 0.5); float cosr = (float)Math.Cos(rMag); float sinr = (float)Math.Sin(rMag) / rMag; qdot.w = -(rx * Q1.x + ry * Q1.y + rz * Q1.z) * 0.5f; qdot.x = (rx * Q1.w + rz * Q1.y - ry * Q1.z) * 0.5f; qdot.y = (ry * Q1.w - rz * Q1.x + rx * Q1.z) * 0.5f; qdot.z = (rz * Q1.w + ry * Q1.x - rx * Q1.y) * 0.5f; Q1.w = cosr * Q1.w + sinr * qdot.w; Q1.x = cosr * Q1.x + sinr * qdot.x; Q1.y = cosr * Q1.y + sinr * qdot.y; Q1.z = cosr * Q1.z + sinr * qdot.z; Q1 = Q1.Normalize(); // Convert to matrix form m.From(Q1); // Compute the difference between the accelerometer vector and the matrix Y (up) vector acc = new Vector( -AccelX, AccelZ, AccelY ); rMag = acc.Length * AccScale; acc = acc.Normalize(); float accWeight = 1.0f - Math.Min( Math.Abs( 2.0f - rMag * 2.0f ), 1.0f ); float errDiffX = acc.y * m.m[1,2] - acc.z * m.m[1,1]; float errDiffY = acc.z * m.m[1,0] - acc.x * m.m[1,2]; float errDiffZ = acc.x * m.m[1,1] - acc.y * m.m[1,0]; accWeight *= 1.0f / 512.0f; errCorrX1 = errDiffX * accWeight; errCorrY1 = errDiffY * accWeight; errCorrZ1 = errDiffZ * accWeight; }