MathNet.Numerics - peace098beat/windows_applicaciton GitHub Wiki

Numeric

https://numerics.mathdotnet.com/Matrix.html

線形代数基礎 (回転, 並進)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MathNet.Numerics.LinearAlgebra; // https://numerics.mathdotnet.com/Matrix.html

/*
 * 
 * 多軸マニュピュレータの数値計算
 * 
 * [仕様]
 *  1. 回転行列は、右ねじ方向が正
 *  2. 回転行列と並進行列は4x4
 * 
 */
namespace _WpfApplicationOpenTKTemplate1
{
    public class IK
    {
        int ITERATION_NUMBER = 500;

        // ゼロベクトル
        public Vector<double> V0 = Vector<double>.Build.DenseOfArray(new double[4] { 0, 0, 0, 1 });

        public IK() { }

        // Util Vec4to3
        public Vector<double> Vec4To3(Vector<double> V4)
        {
            var r = Vector<double>.Build.DenseOfArray(new double[3] { V4[0], V4[1], V4[2] });
            return r;
        }

        // S
        public Matrix<double> S(double sx, double sy, double xz)
        {
            Matrix<double> Li = Matrix<double>.Build.Dense(4, 4, 0);
            return Li;
        }

        // T
        public Matrix<double> T(double tx, double ty, double tz)
        {
            Matrix<double> r = Matrix<double>.Build.DenseOfArray(new double[4, 4]
                    {
                        {  1,  0,  0,  0},
                        {  0,  1,  0,  0},
                        {  0,  0,  1,  0},
                        { tx, ty, tz,  1}});
            return r;
        }
        // T オーバーライド
        public Matrix<double> T(Vector<double> Vt)
        {
            double tx = Vt[0];
            double ty = Vt[1];
            double tz = Vt[2];
            return T(tx, ty, tz);
        }
        // Rx
        // v' = v*Rx
        public Matrix<double> Rx(double rad)
        {
            Matrix<double> r = Matrix<double>.Build.DenseOfArray(new double[4, 4]
                    {
                        { 1,               0,              0,      0},
                        { 0,   Math.Cos(rad),   Math.Sin(rad),     0},
                        { 0, - Math.Sin(rad),   Math.Cos(rad),     0},
                        { 0,               0,              0,      1}});
            return r;
        }
        // Ry
        public Matrix<double> Ry(double rad)
        {
            Matrix<double> r = Matrix<double>.Build.DenseOfArray(new double[4, 4]
                    {
                        { Math.Cos(rad), 0, -Math.Sin(rad),     0},
                        { 0,             1,              0,     0},
                        { Math.Sin(rad), 0,  Math.Cos(rad),     0},
                        { 0,             0,              0,     1}});
            return r;
        }
        // Rz
        public Matrix<double> Rz(double rad)
        {
            Matrix<double> r = Matrix<double>.Build.DenseOfArray(new double [4, 4]
                    {
                    {  Math.Cos(rad),  Math.Sin(rad), 0,     0},
                    { -Math.Sin(rad),  Math.Cos(rad), 0,     0},
                    { 0,               0,             1,     0},
                    { 0,               0,             0,     1} });
            return r;
        }
        // R
        public Matrix<double> Rxyz(double radx, double rady, double radz)
        {
            Matrix<double> r = Matrix<double>.Build.Dense(4, 4, 0);
            return r;
        }

    }

}

線形代数テスト(MSTEST)

/*
 * IKのユニットテスト
 * 
 * http://qiita.com/mima_ita/items/55394bcc851eb8b6dc24
 */

using _WpfApplicationOpenTKTemplate1;
using MathNet.Numerics.LinearAlgebra;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]

        public void IK生成テスト()
        {
            var ik = new IK();
        }

        [TestMethod]
        public void MathNetテスト()
        {
            // Vec(4) = Vec(4) * Matrix(4x4) 
            var M4 = Matrix<double>.Build.DenseIdentity(4); // 4x4
            var V3 = Vector<double>.Build.Dense(3);
            var V4 = Vector<double>.Build.Dense(4);
            // テスト
            var _V = V4 * M4; // (1,4)x(4,4) = (1,4)
            Assert.AreEqual(_V.Count, 4);
        }

        // 次元チェック
        [TestMethod]
        public void ディメンジョンテスト()
        {
            var ik = new IK();

            // TRUE : Rz = (4x4)
            var Rz = ik.Rz(Math.PI);
            Assert.AreEqual(Rz.RowCount, 4);
            Assert.AreEqual(Rz.ColumnCount, 4);

            // TRUE : Rz = (4x4)
            var Rx = ik.Rx(Math.PI);
            Assert.AreEqual(Rx.RowCount, 4);
            Assert.AreEqual(Rx.ColumnCount, 4);

            // TRUE : Ry = (4x4)
            var Ry = ik.Ry(Math.PI);
            Assert.AreEqual(Ry.RowCount, 4);
            Assert.AreEqual(Ry.ColumnCount, 4);

            // TRUE : R = (4x4)
            var Rxyz = ik.Rxyz(Math.PI, Math.PI, Math.PI);
            Assert.AreEqual(Rxyz.RowCount, 4);
            Assert.AreEqual(Rxyz.ColumnCount, 4);

            // TRUE : T = (4x4)
            var ez = Vector<double>.Build.DenseOfArray(new double[] { 1, 0, 0, 1 });
            var T = ik.T(ez);
            Assert.AreEqual(T.RowCount, 4);
            Assert.AreEqual(T.ColumnCount, 4);
        }
        # region TEST_RotationMatrix

        [TestMethod]
        public void 回転行列の正則テスト()
        {
            var ik = new IK();
            var I_ = Matrix<double>.Build.DenseIdentity(4);

            var Rx = ik.Rx(Math.PI);
            Assert.AreEqual(Rx * Rx.Transpose(), I_);

            var Ry = ik.Ry(Math.PI);
            Assert.AreEqual(Ry * Ry.Transpose(), I_);

            var Rz = ik.Rz(Math.PI);
            Assert.AreEqual(Rz * Rz.Transpose(), I_);

        }
        [TestMethod]
        public void TestRx()
        {
            // 単位座標exを-90度回転させて,eyとなるかテスト
            var ik = new IK();

            // TRUE : (0,1,0)*Rx(-PI/4) = (0,0,1)
            var ez_ = Vector<double>.Build.DenseOfArray(new double[] { 0, 0, 1 }); // 真値

            var _ey = Vector<double>.Build.DenseOfArray(new double[] { 0, 1, 0, 1 }); // ez z方向単位ベクトル
            Vector<double> _ey4 = _ey * ik.Rx(Math.PI / 2);// -90度回転
            var _ez = ik.Vec4To3(_ey4); //4=>3

            Assert.AreEqual((_ez - ez_).L2Norm(), 0, 1e-15); // 2つが重なっているかテスト
        }
        [TestMethod]
        public void TestRy()
        {
            // 単位座標exを-90度回転させて,eyとなるかテスト
            var ik = new IK();

            // TRUE : (0,1,0)*Rx(-PI/4) = (0,0,1)
            var ex_ = Vector<double>.Build.DenseOfArray(new double[] { 1, 0, 0 }); // 真値

            var _ez = Vector<double>.Build.DenseOfArray(new double[] { 0, 0, 1, 1 }); // ez z方向単位ベクトル
            Vector<double> _ey4 = _ez * ik.Ry(Math.PI / 2);// -90度回転
            var _ex = ik.Vec4To3(_ey4); //4=>3

            Assert.AreEqual((ex_ - _ex).L2Norm(), 0, 1e-15); // 2つが重なっているかテスト
        }

        [TestMethod]
        public void TestRy2() { 
            var ik = new IK();

            // ベクトル TestVector = (1,1,1)
            var TestVector = Vector<double>.Build.DenseOfArray(new double[] { 1, 1, 1, 1 }); // 真値

            // 回転 Ry(Math.PI/2)
            Vector<double> _RotatedVector4 = TestVector * ik.Ry(-Math.PI / 2);// -90度回転
            Vector<double> _RotatedVector = ik.Vec4To3(_RotatedVector4);

            // 回転後 TrueVector = (-1, 1, 1)
            var TrueVector = Vector<double>.Build.DenseOfArray(new double[] { -1, 1, 1 }); // 真値

            Assert.AreEqual((TrueVector - _RotatedVector).L2Norm(), 0, 1e-15); // 2つが重なっているかテスト


        }
        [TestMethod]
        public void TestRz()
        {
            // 単位座標exを-90度回転させて,eyとなるかテスト
            var ik = new IK();

            // TRUE : (1,0,0)*Rz(-PI/4) = (0,1,0)
            var ey_ = Vector<double>.Build.DenseOfArray(new double[] { 0, 1, 0 }); // 真値

            var _ez = Vector<double>.Build.DenseOfArray(new double[] { 1, 0, 0, 1 }); // ez z方向単位ベクトル
            Vector<double> _ey4 = _ez * ik.Rz(Math.PI / 2);// -90度回転
            var _ey = ik.Vec4To3(_ey4); //4=>3

            Assert.AreEqual((_ey - ey_).L2Norm(), 0, 1e-15); // 2つが重なっているかテスト
        }
        #endregion
        [TestMethod]
        public void TestT_double()
        {
            // 単位座標exを-90度回転させて,eyとなるかテスト
            var ik = new IK();

            // TRUE : (1,0,0)*Rz(-PI/4) = (0,1,0)
            var TrueVector = Vector<double>.Build.DenseOfArray(new double[3] { 5, 1, 0 }); // 真値

            var _OriginVector = Vector<double>.Build.DenseOfArray(new double[4] { 1, 1, 0, 1 }); // ez z方向単位ベクトル

            var Transform = Vector<double>.Build.DenseOfArray(new double[3] { 4, 0, 0 });
            double tx = Transform[0];
            double ty = Transform[1];
            double tz = Transform[2];
            // テスト
            Matrix<double> MatrixT = ik.T(tx, ty, tz);// 並進行列 4x4

            var _TransformedVector4 =  _OriginVector * MatrixT;
            var _TransformedVector = ik.Vec4To3(_TransformedVector4);

            Assert.AreEqual((TrueVector - _TransformedVector).L2Norm(), 0, 1e-15); // 2つが重なっているかテスト
        }
        [TestMethod]
        public void TestT_Vector()
        {
            // 単位座標exを-90度回転させて,eyとなるかテスト
            var ik = new IK();

            // TRUE : (1,0,0)*Rz(-PI/4) = (0,1,0)
            var TrueVector = Vector<double>.Build.DenseOfArray(new double[3] { 5, 1, 0 }); // 真値

            var _OriginVector = Vector<double>.Build.DenseOfArray(new double[4] { 1, 1, 0, 1 }); // ez z方向単位ベクトル

            var Transform = Vector<double>.Build.DenseOfArray(new double[3] { 4, 0, 0 });
            // テスト
            Matrix<double> MatrixT = ik.T(Transform);// 並進行列 4x4

            var _TransformedVector4 = _OriginVector * MatrixT;
            var _TransformedVector = ik.Vec4To3(_TransformedVector4);

            Assert.AreEqual((TrueVector - _TransformedVector).L2Norm(), 0, 1e-15); // 2つが重なっているかテスト
        }
        //Utility Vec4To3のテスト
        [TestMethod]
        public void TestVec4To3()
        {
            var ik = new IK();
            var _P4 = Vector<double>.Build.DenseOfArray(new double[] { 1, 2, 3, 4 });
            var P3_ = Vector<double>.Build.DenseOfArray(new double[] { 1, 2, 3 });
            // TEST
            var _P3 = ik.Vec4To3(_P4);
            Assert.AreEqual(_P3, P3_);

        }
    }
}
⚠️ **GitHub.com Fallback** ⚠️