o06DOF.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using ArduinoBluetoothAPI;
  2. using System;
  3. using UnityEngine;
  4. public class o06DOF
  5. {
  6. /////////////////////g degree/ms
  7. //void Update(Vector3 Acc, Vector3 Gyr, Vector3 Mag, long TimeGap)
  8. //{
  9. // if (TimeGap <= 0)
  10. // return;
  11. //}
  12. public class SixAxisFusion
  13. {
  14. Vector3 acceleratorOffset;
  15. Vector3 gyroscopeOffset;
  16. float gForce;
  17. float gyroscopeToDegree;
  18. //float acceleratorRateAsOffset;
  19. float overallGVectorCredibility = 0;
  20. Vector3 previousAccelerator;
  21. public Vector3 acceleratorGlobal;
  22. public Quaternion quaternion = new Quaternion(0, 0, 0, 1);
  23. public Vector3 accelerationNG//with No G force
  24. {
  25. get
  26. {
  27. var newQuat = new Quaternion(quaternion.x, quaternion.y, quaternion.z, -quaternion.w);
  28. return previousAccelerator - newQuat * new Vector3(0, -gForce, 0);
  29. }
  30. }
  31. public Vector3 speed = Vector3.zero;
  32. public Vector3 locus = Vector3.zero;
  33. public Vector3 rotation = Vector3.zero;
  34. public SixAxisFusion(Vector3 acceleratorOffset, Vector3 gyroscopeOffset, float gForce, float gyroscopeToDegree)
  35. {
  36. this.acceleratorOffset = acceleratorOffset;// 反向校正
  37. this.gyroscopeOffset = gyroscopeOffset;// 反向校正
  38. this.gForce = gForce;
  39. this.gyroscopeToDegree = gyroscopeToDegree;
  40. //this.acceleratorRateAsOffset = acceleratorRateAsOffset;
  41. previousAccelerator = new Vector3(0, -gForce, 0);
  42. acceleratorGlobal = new Vector3(0, -gForce, 0);
  43. }
  44. Quaternion update(Vector3 accelerator, Vector3 gyroscope)
  45. {
  46. accelerator += acceleratorOffset;
  47. gyroscope += gyroscopeOffset;
  48. gyroscope *= gyroscopeToDegree;
  49. var newQua = new Quaternion();
  50. newQua.eulerAngles = gyroscope;
  51. // 根据陀螺仪计算新的四元数旋转
  52. //var newQua = Quaternion.Euler(gyroscope); // 使用 Euler 角度来生成四元数
  53. quaternion = quaternion * newQua;//一定要这样乘
  54. float gForceCredibility = 1 / (1 + Mathf.Pow((Mathf.Abs(Mathf.Sqrt(accelerator.sqrMagnitude) - gForce) / gForce * 16), 1.0f));
  55. float gDegreeCredibility = 1 / (1 + Mathf.Pow(Vector3.Angle(accelerator, newQua * previousAccelerator), 1.0f));
  56. overallGVectorCredibility = overallGVectorCredibility * 0.3f + gForceCredibility * gDegreeCredibility * 0.7f;
  57. //Debug.Log(Mathf.Pow(overallGVectorCredibility, 0.1f));
  58. float rotationUnCredibility = Mathf.Pow(1 - 1 / (1 + gyroscope.magnitude), 5);
  59. //Debug.Log(rotationUnCredibility);
  60. acceleratorGlobal = quaternion * accelerator;
  61. Vector3 downVector = new Vector3(0, -1, 0);
  62. float angle = Vector3.Angle(acceleratorGlobal, downVector);
  63. //Vector3 gVector = Vector3.RotateTowards(acceleratorGlobal, downVector, angle / 180 * Mathf.PI * Mathf.Pow(overallGVectorCredibility, 1f) * rotationUnCredibility, 1);//偏移量,从陀螺仪数据往加速计数据的偏移量
  64. Vector3 gVector = Vector3.RotateTowards(acceleratorGlobal, downVector, angle / 180 * Mathf.PI * Mathf.Pow(overallGVectorCredibility, 1f) * 0.1f, 1);//偏移量,从陀螺仪数据往加速计数据的偏移量
  65. //Vector3 gVector = Vector3.RotateTowards(acceleratorGlobal, downVector, angle / 180 * Mathf.PI * 1, 1);//偏移量,从陀螺仪数据往加速计数据的偏移量
  66. newQua = new Quaternion();
  67. newQua.SetFromToRotation(quaternion * accelerator, gVector);
  68. // 使用 SetFromToRotation 进行四元数校正
  69. // newQua = Quaternion.FromToRotation(quaternion * accelerator, gVector);
  70. quaternion = newQua * quaternion;//一定要反过来乘
  71. previousAccelerator = accelerator;
  72. rotation = gyroscope;
  73. speed = speed * 0.95f + accelerationNG;
  74. locus = locus * 0.95f + speed;
  75. return quaternion;
  76. }
  77. public void ResetToInitialRotation()
  78. {
  79. quaternion = Quaternion.identity;
  80. speed = Vector3.zero;
  81. locus = Vector3.zero;
  82. rotation = Vector3.zero;
  83. previousAccelerator = new Vector3(0, -gForce, 0);
  84. acceleratorGlobal = new Vector3(0, -gForce, 0);
  85. Debug.Log("重置到初始状态");
  86. }
  87. /// <summary>
  88. /// 转换成四元数
  89. /// </summary>
  90. /// <param name="accelerator"></param>
  91. /// <param name="gyroscope"></param>
  92. /// <returns></returns>
  93. public Quaternion tranUpdateData(SixData sixData) {
  94. return update(sixData.Acc, sixData.Gryo);
  95. }
  96. protected double LastMS;
  97. /// <summary>
  98. /// 解析处理一个6轴数据
  99. /// </summary>
  100. /// <param name="bytes"></param>
  101. /// <returns></returns>
  102. public SixData getSixAxisByBytes(byte[] bytes)
  103. {
  104. // 获取时间信息
  105. int min = bytes[16];
  106. int sec = bytes[17];
  107. float millis = SNum(bytes[1], bytes[2]);
  108. var CurrentMS = (((double)min) * 60 + sec) * 1000 + millis;
  109. if (LastMS == default)
  110. {
  111. LastMS = CurrentMS;
  112. }
  113. // 计算时间差,以秒为单位
  114. var GapMS = CurrentMS - LastMS;
  115. LastMS = CurrentMS;
  116. double deltaTime = GapMS / 1000.0; // 转换为秒
  117. string handle = bytes[3].ToString();
  118. float ax = (SNum(bytes[4], bytes[5]) / 32768 * 16);
  119. float ay = (SNum(bytes[6], bytes[7]) / 32768 * 16);
  120. float az = (SNum(bytes[8], bytes[9]) / 32768 * 16);
  121. float gx = (SNum(bytes[10], bytes[11]) / 32768 * 2000); // 度/秒
  122. float gy = (SNum(bytes[12], bytes[13]) / 32768 * 2000); // 度/秒
  123. float gz = (SNum(bytes[14], bytes[15]) / 32768 * 2000); // 度/秒
  124. string[] parseDataAcc = { ax.ToString("#0.000"), ay.ToString("#0.000"), az.ToString("#0.000") };
  125. string[] parseDataGro = { gx.ToString("#0.000"), gy.ToString("#0.000"), gz.ToString("#0.000") };
  126. string[] parseDataTime = { min.ToString(), sec.ToString(), millis.ToString() };
  127. // 计算每帧旋转的角度(角速度 * 时间)
  128. float rotationX = gx * (float)deltaTime; // X轴转动的度数
  129. float rotationY = gy * (float)deltaTime; // Y轴转动的度数
  130. float rotationZ = gz * (float)deltaTime; // Z轴转动的度数
  131. //Quaternion quaternion = update(new Vector3(ax, ay, az), new Vector3(rotationX, rotationY, rotationZ));
  132. //+ ":Quat:" + quaternion
  133. // Debug.Log("数据:Acc[" + string.Join(", ", parseDataAcc) + "] Gryo:" + string.Join(", ", parseDataGro) + "]. Time:" + string.Join(", ", parseDataTime) + ",Euler:" + quaternion.eulerAngles);
  134. return new SixData(new Vector3(ax, ay, az), new Vector3(rotationX, rotationY, rotationZ), min, sec, millis);
  135. }
  136. float SNum(byte b1, byte b2)
  137. {
  138. ushort twoByte = (ushort)(b1 * 256 + b2);
  139. short shortNum = (short)twoByte;
  140. return (float)shortNum;
  141. }
  142. }
  143. /// <summary>
  144. /// 解析转换的6轴格式
  145. /// </summary>
  146. public class SixData
  147. {
  148. public Vector3 Acc;
  149. public Vector3 Gryo;
  150. public int Min;
  151. public int Sec;
  152. public float Millis;
  153. public SixData(Vector3 acc, Vector3 gyro, int min, int sec, float millis)
  154. {
  155. Acc = acc;
  156. Gryo = gyro;
  157. Min = min;
  158. Sec = sec;
  159. Millis = millis;
  160. }
  161. }
  162. }