|
|
@@ -1,9 +1,10 @@
|
|
|
-using ArduinoBluetoothAPI;
|
|
|
-using System;
|
|
|
+using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using UnityEngine;
|
|
|
-using UnityEngine.UI;
|
|
|
+using Newtonsoft.Json;
|
|
|
+using MathNet;
|
|
|
+using MathNet.Numerics.LinearAlgebra;
|
|
|
|
|
|
public class o0Vector3Filter
|
|
|
{
|
|
|
@@ -23,6 +24,310 @@ public class o0Vector3Filter
|
|
|
return state;
|
|
|
}
|
|
|
}
|
|
|
+public class o0MagneticCalibraterEllipsoidFitting//默认在无磁干扰环境下,有磁干扰则无法保证效果
|
|
|
+{
|
|
|
+ [JsonIgnore]
|
|
|
+ public Vector3 _Center = Vector3.zero;
|
|
|
+ [JsonIgnore]
|
|
|
+ Matrix<double> _CorrectMatrix = null;
|
|
|
+
|
|
|
+ public o0Project.Vector3f Center
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return new o0Project.Vector3f(_Center.x, _Center.y, _Center.z);
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ _Center = new Vector3(value.x, value.y, value.z);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public double[] CorrectMatrix
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ if (_CorrectMatrix == null)
|
|
|
+ return default;
|
|
|
+ var m = new double[9];
|
|
|
+ for (var i = 0; i < 3; ++i)
|
|
|
+ for (var j = 0; j < 3; ++j)
|
|
|
+ m[j + i * 3] = _CorrectMatrix[i,j];
|
|
|
+ return m;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ _CorrectMatrix = CreateMatrix.Dense<double>(3,3);
|
|
|
+ for (var i = 0; i < 3; ++i)
|
|
|
+ for (var j = 0; j < 3; ++j)
|
|
|
+ _CorrectMatrix[i, j] = value[j + i * 3];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public o0MagneticCalibraterEllipsoidFitting()
|
|
|
+ {
|
|
|
+ //Calibration = true;
|
|
|
+ }
|
|
|
+ public o0MagneticCalibraterEllipsoidFitting(o0Project.Vector3f Center, double[] CorrectMatrix)
|
|
|
+ {
|
|
|
+ this.Center = Center;
|
|
|
+ this.CorrectMatrix = CorrectMatrix;
|
|
|
+ }
|
|
|
+ [JsonIgnore]
|
|
|
+ List<Vector3> records = null;
|
|
|
+ [JsonIgnore]
|
|
|
+ public Vector3 _Radius = default;
|
|
|
+ [JsonIgnore]
|
|
|
+ public bool Calibration
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return records != null;
|
|
|
+ }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ if (value == true)
|
|
|
+ {
|
|
|
+ records = new List<Vector3>();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ int mag_data_counter = records.Count; //mag数据数量
|
|
|
+
|
|
|
+ double mag_x, mag_y, mag_z;
|
|
|
+
|
|
|
+ var mat_D = CreateMatrix.Dense<double>(mag_data_counter, 9);
|
|
|
+
|
|
|
+ //读取mag
|
|
|
+ for (int i = 0; i < mag_data_counter; i++)
|
|
|
+ {
|
|
|
+
|
|
|
+ //mag_x_y_z赋值
|
|
|
+ mag_x = records[i].x;
|
|
|
+ mag_y = records[i].y;
|
|
|
+ mag_z = records[i].z;
|
|
|
+
|
|
|
+ mat_D[i, 0] = mag_x * mag_x;
|
|
|
+ mat_D[i, 1] = mag_y * mag_y;
|
|
|
+ mat_D[i, 2] = mag_z * mag_z;
|
|
|
+ mat_D[i, 3] = 2 * mag_x * mag_y;
|
|
|
+ mat_D[i, 4] = 2 * mag_x * mag_z;
|
|
|
+ mat_D[i, 5] = 2 * mag_y * mag_z;
|
|
|
+ mat_D[i, 6] = 2 * mag_x;
|
|
|
+ mat_D[i, 7] = 2 * mag_y;
|
|
|
+ mat_D[i, 8] = 2 * mag_z;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ var mat_DT = mat_D.Transpose();
|
|
|
+
|
|
|
+ var mat_Ones = CreateMatrix.Dense<double>(mag_data_counter, 1, 1.0);
|
|
|
+
|
|
|
+ var mat_Result = (mat_DT * mat_D).Inverse() * (mat_DT * mat_Ones);
|
|
|
+
|
|
|
+ var mat_A_4x4 = CreateMatrix.Dense<double>(4, 4);
|
|
|
+
|
|
|
+ mat_A_4x4[0, 0] = mat_Result[0, 0];
|
|
|
+ mat_A_4x4[0, 1] = mat_Result[3, 0];
|
|
|
+ mat_A_4x4[0, 2] = mat_Result[4, 0];
|
|
|
+ mat_A_4x4[0, 3] = mat_Result[6, 0];
|
|
|
+
|
|
|
+ mat_A_4x4[1, 0] = mat_Result[3, 0];
|
|
|
+ mat_A_4x4[1, 1] = mat_Result[1, 0];
|
|
|
+ mat_A_4x4[1, 2] = mat_Result[5, 0];
|
|
|
+ mat_A_4x4[1, 3] = mat_Result[7, 0];
|
|
|
+
|
|
|
+ mat_A_4x4[2, 0] = mat_Result[4, 0];
|
|
|
+ mat_A_4x4[2, 1] = mat_Result[5, 0];
|
|
|
+ mat_A_4x4[2, 2] = mat_Result[2, 0];
|
|
|
+ mat_A_4x4[2, 3] = mat_Result[8, 0];
|
|
|
+
|
|
|
+ mat_A_4x4[3, 0] = mat_Result[6, 0];
|
|
|
+ mat_A_4x4[3, 1] = mat_Result[7, 0];
|
|
|
+ mat_A_4x4[3, 2] = mat_Result[8, 0];
|
|
|
+ mat_A_4x4[3, 3] = -1.0;
|
|
|
+
|
|
|
+
|
|
|
+ var mat_Center = -((mat_A_4x4.SubMatrix(0, 3, 0, 3)).Inverse() * mat_Result.SubMatrix(6, 3, 0, 1));
|
|
|
+ //椭球圆心 //分块,从0,0开始的3*3的矩阵
|
|
|
+
|
|
|
+ var mat_T_4x4 = CreateMatrix.DenseIdentity<double>(4, 4);
|
|
|
+ mat_T_4x4.SetSubMatrix(3, 1, 0, 3, mat_Center.Transpose());
|
|
|
+
|
|
|
+ var mat_R = mat_T_4x4 * mat_A_4x4 * mat_T_4x4.Transpose();
|
|
|
+
|
|
|
+ var evd = mat_R.SubMatrix(0, 3, 0, 3) / -mat_R[3, 3];
|
|
|
+ var eig = evd.Evd();
|
|
|
+
|
|
|
+ var mat_Eigval = CreateVector.Dense<double>(3);
|
|
|
+ var mat_Evecs = eig.EigenVectors;
|
|
|
+
|
|
|
+
|
|
|
+ mat_Eigval[0] = eig.EigenValues[0].Real; //特征值的实部
|
|
|
+ mat_Eigval[1] = eig.EigenValues[1].Real;
|
|
|
+ mat_Eigval[2] = eig.EigenValues[2].Real;
|
|
|
+
|
|
|
+
|
|
|
+ var mat_Radii = mat_Eigval.Map(delegate (double x)
|
|
|
+ {
|
|
|
+ return 1.0 / Math.Sqrt(Math.Abs(x));
|
|
|
+ }); //椭球半径,特征值倒数后开方
|
|
|
+
|
|
|
+ var mat_Scale = CreateMatrix.DenseIdentity<double>(3, 3);
|
|
|
+ mat_Scale[0, 0] = mat_Radii[0];
|
|
|
+ mat_Scale[1, 1] = mat_Radii[1];
|
|
|
+ mat_Scale[2, 2] = mat_Radii[2];
|
|
|
+
|
|
|
+ //double min_Radii = mat_Radii.Minimum(); //返回最小的元素
|
|
|
+
|
|
|
+ mat_Scale = mat_Scale.Inverse();// * min_Radii;
|
|
|
+ var mat_Correct = mat_Evecs * mat_Scale * mat_Evecs.Transpose();
|
|
|
+
|
|
|
+ //_Center = new Vector3((float)mat_Center[0], (float)mat_Center[1], (float)mat_Center[2]);
|
|
|
+
|
|
|
+ Debug.Log("The Ellipsoid center is:" + mat_Center.ToString());
|
|
|
+ Debug.Log("The Ellipsoid radii is:" + mat_Radii.ToString());
|
|
|
+ Debug.Log("The scale matrix is:" + mat_Scale.ToString());
|
|
|
+ Debug.Log("The correct matrix is:" + mat_Correct.ToString());
|
|
|
+
|
|
|
+ _Center = new Vector3((float)mat_Center[0, 0], (float)mat_Center[1, 0], (float)mat_Center[2, 0]);
|
|
|
+ _Radius = new Vector3((float)mat_Radii[0], (float)mat_Radii[1], (float)mat_Radii[2]);
|
|
|
+ this._CorrectMatrix = mat_Correct;
|
|
|
+
|
|
|
+ /*
|
|
|
+ {
|
|
|
+ var textV = new o0Project.Variance(records.Count);
|
|
|
+ foreach (var i in records)
|
|
|
+ {
|
|
|
+ var v = i - new Vector3((float)mat_Center[0, 0], (float)mat_Center[1, 0], (float)mat_Center[2, 0]);
|
|
|
+ var MathNetV = CreateVector.Dense<double>(3);
|
|
|
+ MathNetV[0] = v.x;
|
|
|
+ MathNetV[1] = v.y;
|
|
|
+ MathNetV[2] = v.z;
|
|
|
+ //MathNetV = (MathNetV * mat_Scale) * mat_Correct;
|
|
|
+ MathNetV = (MathNetV) * mat_Correct;
|
|
|
+ v = new Vector3((float)MathNetV[0], (float)MathNetV[1], (float)MathNetV[2]);
|
|
|
+ textV.Update(v.magnitude);
|
|
|
+ }
|
|
|
+ Debug.Log(textV.Value);
|
|
|
+ }
|
|
|
+ {
|
|
|
+ var textV = new o0Project.Variance(records.Count);
|
|
|
+ foreach (var i in records)
|
|
|
+ {
|
|
|
+ var v = i;
|
|
|
+ var MathNetV = CreateVector.Dense<double>(3);
|
|
|
+ MathNetV[0] = v.x;
|
|
|
+ MathNetV[1] = v.y;
|
|
|
+ MathNetV[2] = v.z;
|
|
|
+ //MathNetV = (MathNetV * mat_Scale) * mat_Correct;
|
|
|
+ MathNetV = (MathNetV) * mat_Correct;
|
|
|
+ v = new Vector3((float)MathNetV[0], (float)MathNetV[1], (float)MathNetV[2]) - new Vector3((float)mat_Center[0, 0], (float)mat_Center[1, 0], (float)mat_Center[2, 0]);
|
|
|
+ textV.Update(v.magnitude);
|
|
|
+ }
|
|
|
+ Debug.Log(textV.Value);
|
|
|
+ }
|
|
|
+ {
|
|
|
+ var textV = new o0Project.Variance(records.Count);
|
|
|
+ foreach (var i in records)
|
|
|
+ {
|
|
|
+ var v = i - new Vector3((float)mat_Center[0, 0], (float)mat_Center[1, 0], (float)mat_Center[2, 0]);
|
|
|
+ var MathNetV = CreateVector.Dense<double>(3);
|
|
|
+ MathNetV[0] = v.x;
|
|
|
+ MathNetV[1] = v.y;
|
|
|
+ MathNetV[2] = v.z;
|
|
|
+ MathNetV = (MathNetV * mat_Scale) * mat_Correct;
|
|
|
+ v = new Vector3((float)MathNetV[0], (float)MathNetV[1], (float)MathNetV[2]);
|
|
|
+ textV.Update(v.magnitude);
|
|
|
+ }
|
|
|
+ Debug.Log(textV.Value);
|
|
|
+ }
|
|
|
+ {
|
|
|
+ var textV = new o0Project.Variance(records.Count);
|
|
|
+ foreach (var i in records)
|
|
|
+ {
|
|
|
+ var v = i - new Vector3((float)mat_Center[0, 0], (float)mat_Center[1, 0], (float)mat_Center[2, 0]);
|
|
|
+ var MathNetV = CreateVector.Dense<double>(3);
|
|
|
+ MathNetV[0] = v.x;
|
|
|
+ MathNetV[1] = v.y;
|
|
|
+ MathNetV[2] = v.z;
|
|
|
+ MathNetV = (MathNetV * mat_Correct) * mat_Scale;
|
|
|
+ v = new Vector3((float)MathNetV[0], (float)MathNetV[1], (float)MathNetV[2]);
|
|
|
+ textV.Update(v.magnitude);
|
|
|
+ }
|
|
|
+ Debug.Log(textV.Value);
|
|
|
+ }
|
|
|
+ {
|
|
|
+ var textV = new o0Project.Variance(records.Count);
|
|
|
+ foreach (var i in records)
|
|
|
+ {
|
|
|
+ var v = i - new Vector3((float)mat_Center[0, 0], (float)mat_Center[1, 0], (float)mat_Center[2, 0]);
|
|
|
+ var MathNetV = CreateVector.Dense<double>(3);
|
|
|
+ MathNetV[0] = v.x;
|
|
|
+ MathNetV[1] = v.y;
|
|
|
+ MathNetV[2] = v.z;
|
|
|
+ MathNetV = MathNetV * mat_Scale;
|
|
|
+ v = new Vector3((float)MathNetV[0], (float)MathNetV[1], (float)MathNetV[2]);
|
|
|
+ textV.Update(v.magnitude);
|
|
|
+ }
|
|
|
+ Debug.Log(textV.Value);
|
|
|
+ }
|
|
|
+ {
|
|
|
+ var textV = new o0Project.Variance(records.Count);
|
|
|
+ foreach (var i in records)
|
|
|
+ {
|
|
|
+ var v = i - new Vector3((float)mat_Center[0, 0]/ (float)mat_Radii[0], (float)mat_Center[1, 0]/(float)mat_Radii[1], (float)mat_Center[2, 0]/(float)mat_Radii[2]);
|
|
|
+ textV.Update(v.magnitude);
|
|
|
+ }
|
|
|
+ Debug.Log(textV.Value);
|
|
|
+ }
|
|
|
+ {
|
|
|
+ var textV = new o0Project.Variance(records.Count);
|
|
|
+ foreach (var i in records)
|
|
|
+ {
|
|
|
+ var v = i -new Vector3((float)mat_Center[0, 0], (float)mat_Center[1, 0], (float)mat_Center[2, 0]);
|
|
|
+ textV.Update(v.magnitude);
|
|
|
+ }
|
|
|
+ Debug.Log(textV.Value);
|
|
|
+ }/**/
|
|
|
+
|
|
|
+ records = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public Vector3 Update(Vector3 v)
|
|
|
+ {
|
|
|
+ if (v.magnitude > 30)
|
|
|
+ Debug.Log(v);
|
|
|
+ if (Calibration)
|
|
|
+ {
|
|
|
+ records.Add(v);
|
|
|
+ return v;
|
|
|
+ }
|
|
|
+ if(_CorrectMatrix != null)
|
|
|
+ {
|
|
|
+ v -= _Center;
|
|
|
+
|
|
|
+ var MathNetV = CreateVector.Dense<double>(3);
|
|
|
+ MathNetV[0] = v.x;
|
|
|
+ MathNetV[1] = v.y;
|
|
|
+ MathNetV[2] = v.z;
|
|
|
+ //MathNetV = (MathNetV * mat_Scale) * mat_Correct;
|
|
|
+ MathNetV = (MathNetV) * _CorrectMatrix;
|
|
|
+
|
|
|
+ v = new Vector3((float)MathNetV[0], (float)MathNetV[1], (float)MathNetV[2]);
|
|
|
+ //Debug.Log(v.magnitude);
|
|
|
+ return v;
|
|
|
+ }
|
|
|
+ return v;
|
|
|
+ }
|
|
|
+ public float CalibratCompletionPercentage()
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+}
|
|
|
public class o0MagneticCalibraterSimple//默认在无磁干扰环境下,有磁干扰则无法保证效果
|
|
|
{
|
|
|
|
|
|
@@ -85,7 +390,6 @@ public class o0MagneticCalibraterSimple//默认在无磁干扰环境下,有磁
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- public System.Random r = new System.Random();
|
|
|
public Vector3 Update(Vector3 v)
|
|
|
{
|
|
|
if (v.magnitude > 30)
|