using ArduinoBluetoothAPI;
using System;
using UnityEngine;
public class o06DOF
{
/////////////////////g degree/ms
//void Update(Vector3 Acc, Vector3 Gyr, Vector3 Mag, long TimeGap)
//{
// if (TimeGap <= 0)
// return;
//}
public class SixAxisFusion
{
Vector3 acceleratorOffset;
Vector3 gyroscopeOffset;
float gForce;
float gyroscopeToDegree;
//float acceleratorRateAsOffset;
float overallGVectorCredibility = 0;
Vector3 previousAccelerator;
public Vector3 acceleratorGlobal;
public Quaternion quaternion = new Quaternion(0, 0, 0, 1);
public Vector3 accelerationNG//with No G force
{
get
{
var newQuat = new Quaternion(quaternion.x, quaternion.y, quaternion.z, -quaternion.w);
return previousAccelerator - newQuat * new Vector3(0, -gForce, 0);
}
}
public Vector3 speed = Vector3.zero;
public Vector3 locus = Vector3.zero;
public Vector3 rotation = Vector3.zero;
public SixAxisFusion(Vector3 acceleratorOffset, Vector3 gyroscopeOffset, float gForce, float gyroscopeToDegree)
{
this.acceleratorOffset = acceleratorOffset;// 反向校正
this.gyroscopeOffset = gyroscopeOffset;// 反向校正
this.gForce = gForce;
this.gyroscopeToDegree = gyroscopeToDegree;
//this.acceleratorRateAsOffset = acceleratorRateAsOffset;
previousAccelerator = new Vector3(0, -gForce, 0);
acceleratorGlobal = new Vector3(0, -gForce, 0);
}
Quaternion update(Vector3 accelerator, Vector3 gyroscope)
{
accelerator += acceleratorOffset;
gyroscope += gyroscopeOffset;
gyroscope *= gyroscopeToDegree;
var newQua = new Quaternion();
newQua.eulerAngles = gyroscope;
// 根据陀螺仪计算新的四元数旋转
//var newQua = Quaternion.Euler(gyroscope); // 使用 Euler 角度来生成四元数
quaternion = quaternion * newQua;//一定要这样乘
float gForceCredibility = 1 / (1 + Mathf.Pow((Mathf.Abs(Mathf.Sqrt(accelerator.sqrMagnitude) - gForce) / gForce * 16), 1.0f));
float gDegreeCredibility = 1 / (1 + Mathf.Pow(Vector3.Angle(accelerator, newQua * previousAccelerator), 1.0f));
overallGVectorCredibility = overallGVectorCredibility * 0.3f + gForceCredibility * gDegreeCredibility * 0.7f;
//Debug.Log(Mathf.Pow(overallGVectorCredibility, 0.1f));
float rotationUnCredibility = Mathf.Pow(1 - 1 / (1 + gyroscope.magnitude), 5);
//Debug.Log(rotationUnCredibility);
acceleratorGlobal = quaternion * accelerator;
Vector3 downVector = new Vector3(0, -1, 0);
float angle = Vector3.Angle(acceleratorGlobal, downVector);
//Vector3 gVector = Vector3.RotateTowards(acceleratorGlobal, downVector, angle / 180 * Mathf.PI * Mathf.Pow(overallGVectorCredibility, 1f) * rotationUnCredibility, 1);//偏移量,从陀螺仪数据往加速计数据的偏移量
Vector3 gVector = Vector3.RotateTowards(acceleratorGlobal, downVector, angle / 180 * Mathf.PI * Mathf.Pow(overallGVectorCredibility, 1f) * 0.1f, 1);//偏移量,从陀螺仪数据往加速计数据的偏移量
//Vector3 gVector = Vector3.RotateTowards(acceleratorGlobal, downVector, angle / 180 * Mathf.PI * 1, 1);//偏移量,从陀螺仪数据往加速计数据的偏移量
newQua = new Quaternion();
newQua.SetFromToRotation(quaternion * accelerator, gVector);
// 使用 SetFromToRotation 进行四元数校正
// newQua = Quaternion.FromToRotation(quaternion * accelerator, gVector);
quaternion = newQua * quaternion;//一定要反过来乘
previousAccelerator = accelerator;
rotation = gyroscope;
speed = speed * 0.95f + accelerationNG;
locus = locus * 0.95f + speed;
return quaternion;
}
public void ResetToInitialRotation()
{
quaternion = Quaternion.identity;
speed = Vector3.zero;
locus = Vector3.zero;
rotation = Vector3.zero;
previousAccelerator = new Vector3(0, -gForce, 0);
acceleratorGlobal = new Vector3(0, -gForce, 0);
Debug.Log("重置到初始状态");
}
///
/// 转换成四元数
///
///
///
///
public Quaternion tranUpdateData(SixData sixData) {
return update(sixData.Acc, sixData.Gryo);
}
protected double LastMS;
///
/// 解析处理一个6轴数据
///
///
///
public SixData getSixAxisByBytes(byte[] bytes)
{
// 获取时间信息
int min = bytes[16];
int sec = bytes[17];
float millis = SNum(bytes[1], bytes[2]);
var CurrentMS = (((double)min) * 60 + sec) * 1000 + millis;
if (LastMS == default)
{
LastMS = CurrentMS;
}
// 计算时间差,以秒为单位
var GapMS = CurrentMS - LastMS;
LastMS = CurrentMS;
double deltaTime = GapMS / 1000.0; // 转换为秒
string handle = bytes[3].ToString();
float ax = (SNum(bytes[4], bytes[5]) / 32768 * 16);
float ay = (SNum(bytes[6], bytes[7]) / 32768 * 16);
float az = (SNum(bytes[8], bytes[9]) / 32768 * 16);
float gx = (SNum(bytes[10], bytes[11]) / 32768 * 2000); // 度/秒
float gy = (SNum(bytes[12], bytes[13]) / 32768 * 2000); // 度/秒
float gz = (SNum(bytes[14], bytes[15]) / 32768 * 2000); // 度/秒
string[] parseDataAcc = { ax.ToString("#0.000"), ay.ToString("#0.000"), az.ToString("#0.000") };
string[] parseDataGro = { gx.ToString("#0.000"), gy.ToString("#0.000"), gz.ToString("#0.000") };
string[] parseDataTime = { min.ToString(), sec.ToString(), millis.ToString() };
// 计算每帧旋转的角度(角速度 * 时间)
float rotationX = gx * (float)deltaTime; // X轴转动的度数
float rotationY = gy * (float)deltaTime; // Y轴转动的度数
float rotationZ = gz * (float)deltaTime; // Z轴转动的度数
//Quaternion quaternion = update(new Vector3(ax, ay, az), new Vector3(rotationX, rotationY, rotationZ));
//+ ":Quat:" + quaternion
// Debug.Log("数据:Acc[" + string.Join(", ", parseDataAcc) + "] Gryo:" + string.Join(", ", parseDataGro) + "]. Time:" + string.Join(", ", parseDataTime) + ",Euler:" + quaternion.eulerAngles);
return new SixData(new Vector3(ax, ay, az), new Vector3(rotationX, rotationY, rotationZ), min, sec, millis);
}
float SNum(byte b1, byte b2)
{
ushort twoByte = (ushort)(b1 * 256 + b2);
short shortNum = (short)twoByte;
return (float)shortNum;
}
}
///
/// 解析转换的6轴格式
///
public class SixData
{
public Vector3 Acc;
public Vector3 Gryo;
public int Min;
public int Sec;
public float Millis;
public SixData(Vector3 acc, Vector3 gyro, int min, int sec, float millis)
{
Acc = acc;
Gryo = gyro;
Min = min;
Sec = sec;
Millis = millis;
}
}
}