Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#

Integration: Mechanics + Hydraulics + Navigation

Rate me:
Please Sign up or sign in to vote.
5.00/5 (46 votes)
3 Feb 2011CPOL21 min read 61.5K   6.1K   88  
Sample of integration of branches of engineering.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;


using CategoryTheory;
using DiagramUI;

using SerializationInterface;


using DataPerformer;
using DataPerformer.Interfaces;

using Motion6D;
using Motion6D.Intrefaces;

namespace AggregateLibrary
{
    /// <summary>
    /// Rigid body aggregate
    /// </summary>
    [Serializable()]
    internal class RigidBody : AggregableMechanicalObjectDataConsumer, 
        IPropertiesEditor, IStarted, INormalizable, IOrientation, ISerializable
    {
        #region Fields

        /// <summary>
        /// Connections ccordinates
        /// </summary>
        protected double[][] connections;

        /// <summary>
        /// Inverted mass
        /// </summary>
        protected double invertedMass = 1;

        /// <summary>
        /// Mass
        /// </summary>
        protected double mass = 1;

        /// <summary>
        /// Moment of inertia
        /// </summary>
        protected double[,] momemtOfInertia = new double[,]
            {{1, 0, 0},
            {0, 1, 0},
            {0, 0, 1}};

        /// <summary>
        /// Inverted moment of inertia
        /// </summary>
        protected double[,] invertedMomentOfInertia = new double[,]
            {{1, 0, 0},
            {0, 1, 0},
            {0, 0, 1}};

        /// <summary>
        /// Measurements of external accelations
        /// </summary>
        private IMeasure[] inertialAccelationMea = new IMeasure[3];

        /// <summary>
        /// String representation of measures
        /// </summary>
        protected string[] inerialAccelerationStr = new string[3];

        /// <summary>
        /// Measures of forces
        /// </summary>
        private IMeasure[] forces = new IMeasure[6];

        /// <summary>
        /// String of forces
        /// </summary>
        protected string[] forcesStr = new string[6];

        /// <summary>
        /// States of connections
        /// </summary>
        private double[][] connectionStates;

        /// <summary>
        /// Matrixes of acceleration
        /// </summary>
        protected double[][,] accelreationMatrixes;

        /// <summary>
        /// Matrixes of forces
        /// </summary>
        protected double[][,] forcesMatrixes;

        /// <summary>
        /// Internal acceleration
        /// </summary>
        protected double[] internalAcceleration = new double[6];


        /// <summary>
        /// Array of transformation matrixes
        /// </summary>
        private double[][,] transformationMatrixes;

        /// <summary>
        /// Internal accelerations
        /// </summary>
        protected double[][] internalAccelerations;

        /// <summary>
        /// auxiliary vector
        /// </summary>
        protected double[] v3d = new double[3];

        /// <summary>
        /// auxiliary vector
        /// </summary>
        protected double[] v3d1 = new double[3];

        /// <summary>
        /// auxiliary vector
        /// </summary>
        protected double[] v3d2 = new double[3];

        /// <summary>
        /// omega
        /// </summary>
        private double[] omega = new double[3];

        /// <summary>
        /// Additional omega
        /// </summary>
        private double[] omegaAdd = new double[3];

        /// <summary>
        /// Additional omega
        /// </summary>
        private double[] omegaAddP = new double[3];

        /// <summary>
        /// Auxiliary matrix
        /// </summary>
        private double[,] auxiliaryMatrix = new double[3, 3];

        /// <summary>
        /// Auxiliary matrix add
        /// </summary>
        private double[,] auxiliaryMatrixAdd = new double[3, 3];

        /// <summary>
        /// Auxiliary matrix add
        /// </summary>
        private double[,] auxiliaryMatrixAddP = new double[3, 3];

        /// <summary>
        /// Auxiliary quaternion
        /// </summary>
        private double[] quater = new double[4];

        /// <summary>
        /// Auxiliary quaternion
        /// </summary>
        private double[] quaterAdd = new double[4];

        /// <summary>
        /// Auxiliary quaternion
        /// </summary>
        private double[] quaterAddP = new double[4];

        /// <summary>
        /// Auxiliary transformation matrix
        /// </summary>
        private double[,] transformMatrix = new double[3, 3];


        /// <summary>
        /// Matrix for quaternion transformation
        /// </summary>
        private double[,] qq = new double[4, 4];
        
        /// <summary>
        /// Editor of properties
        /// </summary>
        private FormRigidBody f;

        /// <summary>
        /// Square of angular velocity
        /// </summary>
        private double omega2;

        /// <summary>
        /// Orientation matrix
        /// </summary>
        protected double[,] orientation = new double[3, 3];

        /// <summary>
        /// Transposed ori
        /// </summary>
        protected double[,] transposedOrientation = new double[3, 3];

        /// <summary>
        /// Auxiliary matrix
        /// </summary>
        protected double[,] auxMatrix = new double[3, 3];

        protected Action AddForce = delegate()
        {
        };

        protected Action AddMomentum = delegate()
        {
        };

        #endregion

        #region Ctor

        internal RigidBody()
            : this(true)
        {
        }

        /// <summary>
        /// Default constructor
        /// </summary>
        protected RigidBody(bool setForce)
            : this(13, setForce)
        {
            Post();
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="n">Number of variables</param>
        protected RigidBody(int n, bool setForce)
        {
            initialState = new double[n];
            for (int i = 0; i < n; i++)
            {
                initialState[i] = 0;
            }
            initialState[6] = 1;
            state = new double[n];
            Array.Copy(initialState, state, n);
            if (setForce)
            {
                AddForce += AddForceFunc;
                AddMomentum += AddMomentumFunc;
            }
        }

        protected RigidBody(SerializationInfo info, StreamingContext context)
        {
           Properties = Serialization.Deserialize<object>("Properties", info);
           if (state == null)
           {
               state = new double[initialState.Length];
           }
        }

        #endregion

 
        #region IPropertiesEditor Members

        public virtual object Editor
        {
            get 
            {
                return new object[] { Form, ResourceImage.RigidBody };
            }
        }

        public virtual object Properties
        {
            get
            {
                object[] o = new object[] { momemtOfInertia, connections, aliasNames, inerialAccelerationStr, forcesStr, mass, initialState };
                return LibraryObjectWrapper.TransformToBytes(o);
            }
            set
            {
                object[] ob = value as object[];
                object[] o = LibraryObjectWrapper.TransformFromBytes(ob);
                SetProperties(o);
             }
        }
 
        #endregion

        #region IStarted Members

        void IStarted.Start(double time)
        {
            Array.Copy(InitialState, state, state.Length);
            PostStart(time);
        }

        #endregion

        #region INormalizable Members



        public virtual void Normalize()
        {
            RealMatrixProcessor.RealMatrix.Normalize(state, 6, 4);
            SetConnectionStates();
        }

        #endregion

        #region IOrientation Members

        double[] IOrientation.Quaternion
        {
            get { return quater; }
        }

        double[,] IOrientation.Matrix
        {
            get { return orientation; }
        }

        #endregion


        #region Overriden Members

        public override int Dimension
        {
            get { return 13; }
        }

        public override double[] InternalAcceleration
        {
            get { return internalAcceleration; }
        }

        public override int NumberOfConnections
        {
            get
            {
                if (connections == null)
                {
                    return 0;
                }
                return connections.GetLength(0);
            }
        }

        public override double[] this[int numOfConnection]
        {
            get
            {
                if (connections == null)
                {
                    return null;
                }
                return connectionStates[numOfConnection];
            }
            set
            {
                if ((connections == null) | (value == null))
                {
                    return;
                }
                SetStateByConnection(value, numOfConnection);
            }
        }

        public override double[,] GetAccelerationMatrix(int numOfConnection)
        {
            return accelreationMatrixes[numOfConnection];
        }

        public override double[,] GetForcesMatrix(int numOfConnection)
        {
            return forcesMatrixes[numOfConnection];
        }

        public override double[] GetInternalAcceleration(int numOfConnection)
        {
            return internalAccelerations[numOfConnection];
        }

        public override bool IsConstant
        {
            get { return true; }
        }


        protected override void Post()
        {
            base.Post();
            CreateConnections();
            CreateMesurements();
            InvertMoment();
            CreateArrays();
        }

        protected override void Update()
        {
            base.Update();
            CalculateInternalAccelerations();
        }

        protected virtual void SetProperties(object[] o)
        {
            momemtOfInertia = o[0] as double[,];
            RealMatrixProcessor.RealMatrix.Invert(momemtOfInertia, invertedMomentOfInertia);
            if (o[1] != null)
            {
                connections = o[1] as double[][];
                if (connections != null)
                {
                    connectionStates = CreateArray(connections.Length, 13);
                }
            }
            aliasNames = o[2] as Dictionary<int, string>;
            inerialAccelerationStr = o[3] as string[];
            forcesStr = o[4] as string[];
            mass = (double)o[5];
            invertedMass = 1 / mass;
            InitialState = o[6] as double[];
            CreateArrays();
        }


        #endregion

        #region Specific Members

        protected virtual void PostStart(double time)
        {
        }


        internal void Set(Dictionary<int, string> aliasNames, string[] forcesStr, string[] inerialAccelerationStr,
            double[][] connections, double[,] momemtOfInertia, double mass, double[] initialState)
        {
            this.aliasNames = aliasNames;
            this.forcesStr = forcesStr;
            this.inerialAccelerationStr = inerialAccelerationStr;
            this.connections = connections;
            this.momemtOfInertia = momemtOfInertia;
            RealMatrixProcessor.RealMatrix.Invert(momemtOfInertia, invertedMomentOfInertia);
            this.mass = mass;
            invertedMass = 1 / mass;
            this.initialState = initialState;
            if (GetType().Name.Equals("RigidBody"))
            {
                Post();
            }
        }

        /// <summary>
        /// Gets connection coordinates
        /// </summary>
        /// <param name="num">Number of connection</param>
        /// <returns>Connection coordinates</returns>
        public double[] GenConnection(int num)
        {
            double[] x = new double[7];
            double[] c = connections[num];
            Array.Copy(c, x, 7);
            return x;
        }
 
        /// <summary>
        /// Mass
        /// </summary>
        public double Mass
        {
            get
            {
                return mass;
            }
        }

        /// <summary>
        /// Moment of inertia
        /// </summary>
        public double[,] MomentOfInertia
        {
            get
            {
                return momemtOfInertia;
            }
        }

        public string[] Forces
        {
            get
            {
                return forcesStr;
            }
        }

        public string[] Inretial
        {
            get
            {
                return inerialAccelerationStr;
            }
        }

 
        private void SetOrientation()
        {
            Array.Copy(state, 6, quater, 0, 4);
            Vector3D.V3DOperations.CalculateMatrix(quater, orientation, qq);
            RealMatrixProcessor.RealMatrix.Transpose(orientation, transposedOrientation);
        }
 

        /// <summary>
        /// Creates connections
        /// </summary>
        private void CreateConnections()
        {
            if (connections == null)
            {
                return;
            }
            CreateArrays();
        }

        private void CreateMesurements()
        {
            if (forcesStr != null)
            {
                forces = this.FindMeasures(forcesStr, true);
            }
            if (inerialAccelerationStr != null)
            {
                inertialAccelationMea = this.FindMeasures(inerialAccelerationStr, true);
            }
        }

        private void InvertMoment()
        {
            RealMatrixProcessor.RealMatrix.Invert(momemtOfInertia, invertedMomentOfInertia);
        }

        private static double[][] CreateArray(int n, int m)
        {
            double[][] arr = new double[n][];
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i] = new double[m];
            }
            return arr;
        }

        protected virtual object Form
        {
            get
            {
                if (f == null)
                {
                    f = new FormRigidBody(this);
                }
                else
                {
                    if (f.IsDisposed)
                    {
                        f = new FormRigidBody(this);
                    }
                }
                return f;
            }
        }
        
        private static double[][,] CreateArray(int n, int m, int k)
        {
            double[][,] arr = new double[n][,];
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i] = new double[m, k];
            }
            return arr;
        }

        private void CreateArrays()
        {
            if (connections == null)
            {
                return;
            }
            IAggregableMechanicalObject agg = this;
            int dim = agg.Dimension;
            int n = connections.GetLength(0);
            internalAccelerations = CreateArray(n, 6);
            forcesMatrixes = CreateArray(n, (dim - 1) / 2, 6);
            accelreationMatrixes = CreateArray(n, 6, (dim - 1) / 2);
            connectionStates = CreateArray(n, 13);
            transformationMatrixes = new double[n][,];
            SetForcesMatrix();
        }

        protected virtual void SetForcesMatrix()
        {
            int n = connections.GetLength(0);
            for (int i = 0; i < n; i++)
            {
                SetForcesMatrix(i);
            }
        }

        protected void NormalizeInitialQuaternion()
        {
            double a = 0;
            for (int i = 3; i < 7; i++)
            {
                double x = InitialState[i];
                a += x * x;
            }
            a = 1 / Math.Sqrt(a);
            for (int i = 3; i < 7; i++)
            {
                InitialState[i] *= a;
            }
        }

        protected virtual void SetConnectionStates()
        {
            Array.Copy(state, 6, quater, 0, 4);
            Array.Copy(state, 10, omega, 0, 3);
            SetOrientation();
            if (connections == null)
            {
                return;
            }
            for (int i = 0; i < connections.Length; i++)
            {
                SetConnectionState(connectionStates[i], i);
            }
        }

        /// <summary>
        /// Sets connection state
        /// </summary>
        /// <param name="connectionState">Connection state</param>
        /// <param name="numberOfConnection">Number of connection</param>
        protected void SetConnectionState(double[] connectionState, int numberOfConnection)
        {
            double[] connection = connections[numberOfConnection];
            Array.Copy(state, connectionState, 13);

            // Position
            Array.Copy(connection, v3d, 3);
            RealMatrixProcessor.RealMatrix.Multiply(orientation, v3d, v3d1);
            for (int i = 0; i < 3; i++)
            {
                connectionState[i] += v3d1[i];
            }

            // Orientation
            Array.Copy(connection, 3, quaterAdd, 0, 4);
            Vector3D.V3DOperations.QuaternionMultiply(quater, quaterAdd, quaterAddP);
            Array.Copy(quaterAddP, 0, connectionState, 6, 4);

            // Velocity
            Array.Copy(state, v3d, 3);
            Array.Copy(state, 10, v3d1, 0, 3);
            Vector3D.V3DOperations.VectorPoduct(v3d, v3d1, v3d2);
            RealMatrixProcessor.RealMatrix.Multiply(orientation, v3d2, v3d);
            for (int i = 0; i < 3; i++)
            {
                connectionState[i + 3] += v3d[i];
            }

            // Angular velocity
            Array.Copy(state, 10, v3d, 0, 3);
            RealMatrixProcessor.RealMatrix.Multiply(orientation, v3d, v3d1);
            Array.Copy(v3d1, 0, connectionState, 10, 3);

        }


        private void Transform(double[,] trans, double[] vector, double[] result, int offset)
        {
            Array.Copy(vector, offset, v3d, 0, 3);
            RealMatrixProcessor.RealMatrix.Multiply(trans, v3d, result);
        }


        private void Transform(double[,] trans, double[] vector, double[] result, int source, int target)
        {
            Array.Copy(vector, source, v3d, 0, 3);
            RealMatrixProcessor.RealMatrix.Multiply(trans, v3d, v3d1);
            Array.Copy(v3d, 0, result, target, 3);
        }

        /// <summary>
        /// Sets state by connection state
        /// </summary>
        /// <param name="conn">Connetion state</param>
        /// <param name="number">Connection number</param>
        protected void SetStateByConnection(double[] connectionExternal, int number)
        {
            double[] connectionInrernal = connections[number];

            //  Orientation
            Array.Copy(connectionExternal, 6, quaterAdd, 0, 4);
            Array.Copy(connectionInrernal, 3, quaterAddP, 0, 4);
            Vector3D.V3DOperations.QuaternionInvertMultiply(quaterAddP, quaterAdd, quater);
            Array.Copy(quater, 0, state, 6, 4);
            SetOrientation();

            // Position
            Array.Copy(connectionInrernal, v3d, 3);
            RealMatrixProcessor.RealMatrix.Multiply(orientation, v3d, v3d1);
            for (int i = 0; i < 3; i++)
            {
                state[i] = connectionExternal[i] - v3d1[i];
            }

            // Angular velocity
            Array.Copy(connectionExternal, 10, v3d1, 0, 3);
            RealMatrixProcessor.RealMatrix.Multiply(v3d1, orientation, omega);
            Array.Copy(omega, 0, state, 10, 3);

            // Velocity
            Array.Copy(connectionExternal, 3, state, 3, 3);
            Array.Copy(connectionInrernal, v3d, 3);
            Vector3D.V3DOperations.VectorPoduct(omega, v3d, v3d1);
            RealMatrixProcessor.RealMatrix.Multiply(orientation, v3d, v3d2);
            for (int i = 0; i < 3; i++)
            {
                state[i + 3] -= v3d2[i];
            }
        }



        protected void SetForcesMatrix(int n)
        {
            double[] internalConnection = connections[n];
            Array.Copy(internalConnection, 3, quater, 0, 4);
            double[,] tm = new double[3, 3];
            Vector3D.V3DOperations.CalculateMatrix(quater, tm, qq);
            transformationMatrixes[n] = tm;

            double[,] fm = forcesMatrixes[n];

            // Zero
            for (int i = 0; i < fm.GetLength(0); i++)
            {
                for (int j = 0; j < fm.GetLength(1); j++)
                {
                    fm[i, j] = 0;
                }
            }

            // Force to linear acceleration
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    fm[i, j] = tm[i, j] * invertedMass;
                }
            }

            // Momentum to angular acceleration
            RealMatrixProcessor.RealMatrix.Multiply(invertedMomentOfInertia, tm, auxiliaryMatrix);
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    fm[i + 3, j + 3] = auxiliaryMatrix[i, j];
                }
            }

            // Force to angular acceleration
            Array.Copy(internalConnection, v3d, 3);
            Vector3D.V3DOperations.SO3VectorToSO3Matrix(v3d, auxiliaryMatrix); 
            RealMatrixProcessor.RealMatrix.Multiply(auxiliaryMatrix, tm, auxiliaryMatrixAdd);
            RealMatrixProcessor.RealMatrix.Multiply(invertedMomentOfInertia, auxiliaryMatrixAdd, auxiliaryMatrix);
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    fm[i + 3, j] = auxiliaryMatrix[i, j];
                }
            }

            SetAccelerationMatrix(n);
        }

        protected virtual void SetAccelerationMatrix(int n)
        {
            double[,] am = accelreationMatrixes[n];
            double[,] t = transformationMatrixes[n];
            
            // Angular
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    double a = t[j, i];
                    am[i + 3, j + 3] = a;
                    am[i, j] = a;
                }
            }

            double[] conn = connections[n];
            Array.Copy(conn, v3d, 3);
            Vector3D.V3DOperations.SO3VectorToSO3Matrix(v3d, auxiliaryMatrix);
            RealMatrixProcessor.RealMatrix.Multiply(auxiliaryMatrix, t, auxiliaryMatrixAdd);
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    am[i, j + 3] = auxiliaryMatrixAdd[i, j];
                }
            }
        }

        private void AddForceFunc()
        {
            for (int i = 0; i < 3; i++)
            {
                double a = 0;
                IMeasure m = inertialAccelationMea[i];
                if (m != null)
                {
                    a += (double)m.Parameter();
                }
                m = forces[i];
                if (m != null)
                {
                    a += invertedMass * (double)m.Parameter();
                }
                internalAcceleration[i] += a;
            }
        }

        private void AddMomentumFunc()
        {
            for (int i = 0; i < 3; i++)
            {
                IMeasure m = forces[i + 3];
                if (m != null)
                {
                    v3d[i] += (double)m.Parameter();
                }
            }
        }

        protected virtual void CalculateInternalAccelerations()
        {
            for (int i = 0; i < internalAcceleration.Length; i++)
            {
                internalAcceleration[i] = 0;
            }
            AddForce();
            Array.Copy(state, 10, omega, 0, 3);
            RealMatrixProcessor.RealMatrix.Multiply(momemtOfInertia, omega, omegaAdd);
            Vector3D.V3DOperations.VectorPoduct(omega, omegaAdd, omegaAddP);
            for (int i = 0; i < 3; i++)
            {
                internalAcceleration[i + 3] += omegaAddP[i];
            }
            for (int i = 0; i < 3; i++)
            {
                v3d[i] = 0;
            }
            AddMomentum();
            RealMatrixProcessor.RealMatrix.Multiply(invertedMomentOfInertia, v3d, omegaAdd);
            for (int i = 0; i < 3; i++)
            {
                internalAcceleration[i + 3] += omegaAdd[i];
            }
            omega2 = 0;
            for (int i = 0; i < 3; i++)
            {
                omega2 += omega[i] * omega[i];
            }
            if (connections == null)
            {
                return;
            }
            int n = connections.Length;
            for (int i = 0; i < n; i++)
            {
                CalculateInternalAccelerations(i);
            }
        }

        protected virtual void CalculateInternalAccelerations(int n)
        {
            double[] acc = internalAccelerations[n];
            double[] x = connections[n];

            // Angular acceleration
            Array.Copy(internalAcceleration, 3, v3d, 0, 3);
            RealMatrixProcessor.RealMatrix.Multiply(v3d, orientation, v3d1);
            Array.Copy(v3d1, 0, acc, 3, 3);

            // Linear acceleration
            Array.Copy(internalAcceleration, 3, v3d, 0, 3);
            Array.Copy(x, v3d1, 3);
            Vector3D.V3DOperations.VectorPoduct(v3d, v3d1, v3d2);
            RealMatrixProcessor.RealMatrix.Multiply(v3d2, orientation, v3d1);
            for (int i = 0; i < 3; i++)
            {
                acc[i] = internalAcceleration[i] + v3d1[i];
            }
            Array.Copy(x, v3d1, 3);
            Vector3D.V3DOperations.VectorPoduct(omega, v3d1, v3d2);
            Vector3D.V3DOperations.VectorPoduct(omega, v3d2, v3d1);
            RealMatrixProcessor.RealMatrix.Multiply(v3d1, orientation, v3d);
            for (int i = 0; i < 3; i++)
            {
                acc[i] += v3d[i];
            }
        }

 
        #endregion



        #region ISerializable Members

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            Serialization.Serialize<object>("Properties", info, Properties);
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Russian Federation Russian Federation
Ph. D. Petr Ivankov worked as scientific researcher at Russian Mission Control Centre since 1978 up to 2000. Now he is engaged by Aviation training simulators http://dinamika-avia.com/ . His additional interests are:

1) Noncommutative geometry

http://front.math.ucdavis.edu/author/P.Ivankov

2) Literary work (Russian only)

http://zhurnal.lib.ru/editors/3/3d_m/

3) Scientific articles
http://arxiv.org/find/all/1/au:+Ivankov_Petr/0/1/0/all/0/1

Comments and Discussions