lvjincheng 3 سال پیش
والد
کامیت
cfae775ae1

+ 147 - 0
代码备份/2022-6-11/o09AxisCS.cs

@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+public class o09AxisCS
+{
+    static public Vector3 AccIdentity = new Vector3(0, -1, 0);
+    static public Vector3 MagIdentity = new Vector3(-1, 2, 0).normalized;
+    public class State
+    {
+        public long TimeGap;
+        public Vector3 Acc = AccIdentity;
+        public Vector3 AccSmooth = AccIdentity;
+        public double AccVariance = 1;
+
+        public Vector3 Gyr;
+        public Vector3 Mag = MagIdentity;
+        public Vector3 MagSmooth = MagIdentity;
+        public Quaternion Qua = Quaternion.identity;
+        public Quaternion QuaSmooth = Quaternion.identity;
+        public double Variance = 1;
+    }
+
+    o0Project.Variance HardwareVarianceGyr = new o0Project.Variance(1000);
+    o0Project.Variance HardwareVarianceAcc = new o0Project.Variance(1000);
+    o0Project.Variance HardwareVarianceMag = new o0Project.Variance(1000);
+
+    public List<State> States = new List<State>();
+
+    public Vector3 AccOld;
+    public Vector3 GyrOld;
+    public Vector3 MagOld;
+
+    public float x;
+    public float y;
+    public float z;
+
+    long TimeGapOld;
+    o0Aien.o0WeightedAverageFilterVector3 AccFilter = new o0Aien.o0WeightedAverageFilterVector3(5);
+    o0Aien.o0WeightedAverageFilterVector3 MagFilter = new o0Aien.o0WeightedAverageFilterVector3(10);
+         
+    public Quaternion update(Vector3 AccOld, Vector3 GyrOld, Vector3 MagOld, long TimeGapOld)
+    {
+        o0UIRawImageTester.UpdateAllOffset();
+
+        var Acc = this.AccOld;
+        var Gyr = (this.GyrOld + GyrOld)/2;
+        var Mag = this.MagOld;
+        float TimeGap = this.TimeGapOld;
+        this.AccOld = AccOld;
+        this.GyrOld = GyrOld;
+        this.MagOld = MagOld;
+        this.TimeGapOld = TimeGapOld;
+        var Last = States.LastOrDefault() ?? new State();
+        if (this.TimeGapOld <= 0)
+            return Last.Qua;
+        States.Add(new State());
+        if (States.Count > 200)
+            States.RemoveAt(0);
+        var state = States.Last();
+        state.Acc = Acc;
+
+        state.AccSmooth = AccFilter.Update(Acc);
+        
+        state.Gyr = Gyr;
+        state.Mag = Mag;/**/
+        state.MagSmooth = MagFilter.Update(Mag);
+        if (States.Count <=1)
+            return Quaternion.identity;
+
+        HardwareVarianceGyr.Update((Gyr).magnitude);//每毫秒方差2.331017E-09 度左右   0.00000002331017
+        HardwareVarianceAcc.Update(Vector3.Angle(state.Acc, Last.Acc));//方差0.0012度左右
+        HardwareVarianceMag.Update(Vector3.Angle(state.Mag, Last.Mag));//方差3.5度左右
+
+        var LastQuaternion = Last.Qua;
+
+        var newQua = new Quaternion();
+        newQua.eulerAngles = Gyr * TimeGap;
+        var quaGyr = LastQuaternion * newQua;
+
+        double AccLengthToAngle = 5;//1倍引力差相当于多少度方差
+        double MagLengthToAngle = 5;//1倍磁力差相当于多少度方差
+
+        double GyrVariance = Last.Variance + Math.Pow((Gyr * TimeGap).magnitude * 0.3,3);// 指数4 = 方差2 * 欧拉角旋转误差2     移动导致累计误差
+        double AccVariance = Math.Max((Gyr * TimeGap).magnitude, Vector3.Angle(state.AccSmooth, Last.AccSmooth)) * 1 + Math.Pow(Math.Abs(state.AccSmooth.magnitude - 9.8) / 9.8 * AccLengthToAngle,4);
+        double MagVariance = Math.Max((Gyr * TimeGap).magnitude, Vector3.Angle(state.MagSmooth, Last.MagSmooth)) * 1 + Math.Pow(Math.Abs(state.MagSmooth.magnitude - 1) / 1 * MagLengthToAngle,4);/**/
+
+        state.Variance = GyrVariance;
+        state.Variance = state.Variance * (AccVariance+ MagVariance) / (state.Variance + (AccVariance + MagVariance));
+
+        if (double.IsNaN(GyrVariance))
+            GyrVariance = double.MinValue;
+        if (double.IsNaN(AccVariance))
+            AccVariance = double.MinValue;
+        if (double.IsNaN(MagVariance))
+            MagVariance = double.MinValue;
+        if (double.IsNaN(state.Variance))
+            state.Variance = double.MinValue;
+
+        var quaAccMag = o0Project.o0.FormQuaternion(AccIdentity, MagIdentity, state.AccSmooth, state.MagSmooth, (float)(AccVariance / (AccVariance + MagVariance)));
+
+        var quaMinRate = GyrVariance / (GyrVariance + Math.Max(AccVariance, MagVariance));
+        var quaMaxRate = GyrVariance / (GyrVariance + Math.Min(AccVariance, MagVariance));
+        Quaternion quaFirst = Quaternion.Slerp(quaGyr, quaAccMag, (float)quaMinRate).normalized;
+        if (float.IsNaN(quaFirst.w))
+            quaFirst = Last.Qua;
+
+        var quaSecondRate = (quaMaxRate - quaMinRate) / (1 - quaMinRate);
+
+        state.Qua = AccVariance < MagVariance ? o0Project.o0.FormQuaternion(quaFirst, AccIdentity, state.AccSmooth, (float)quaSecondRate) : o0Project.o0.FormQuaternion(quaFirst, MagIdentity, state.MagSmooth, (float)quaSecondRate);
+        
+        if (float.IsNaN(state.Qua.w))
+            state.Qua = Last.Qua;/**/
+        state.QuaSmooth = Quaternion.Slerp(Last.QuaSmooth, state.Qua, 0.3f);
+
+        var frontV = Last.Qua * Vector3.forward;
+        var upV = Last.Qua * Vector3.up;
+
+        x = (Mathf.Atan(upV.y / upV.z) / Mathf.PI * 180 + (upV.z < 0 ? 90:270));
+        y = (Mathf.Atan(frontV.z / frontV.x) / Mathf.PI * 180+(frontV.x < 0 ? 90:270));
+        z = (Mathf.Atan(upV.y / upV.x) / Mathf.PI * 180 + (upV.x < 0 ? 90:270));
+
+        return state.Qua;
+    }
+
+    public void SetIdentity()
+    {
+        Quaternion qua = default;
+        AccIdentity = AccOld;
+        MagIdentity = MagOld;
+        qua = o0Project.o0.FormQuaternion(Quaternion.identity, Vector3.down,AccIdentity, 1);
+        AccIdentity=qua*AccIdentity;
+        MagIdentity = qua*MagIdentity;
+        States.Last().Qua = Quaternion.identity;
+        States.Last().Qua = qua*States.Last().Qua;//Quaternion.identity;
+        States.Last().Variance = 0.0000001;
+    }
+
+    public State getLastState() {
+        return this.States.Last();
+    }
+
+    public Vector3 getGyrOld() {
+        return GyrOld;
+    }
+}

+ 1 - 0
代码备份/2022-6-11/备份原因.txt

@@ -0,0 +1 @@
+九轴算法修改待测试

BIN
代码备份/2022-6-24/hit.mp3


BIN
代码备份/2022-6-24/hit.wav


+ 1 - 0
代码备份/2022-6-24/备份原因.txt

@@ -0,0 +1 @@
+射箭击中音频更换

+ 589 - 0
代码备份/2022-6-4/BluetoothAim.cs

@@ -0,0 +1,589 @@
+using ArduinoBluetoothAPI;
+using System;
+using UnityEngine;
+using System.Collections.Generic;
+using UnityEngine.UI;
+using DG.Tweening;
+using UnityEngine.SceneManagement;
+/* 蓝牙瞄准模块 */
+public class BluetoothAim : MonoBehaviour
+{
+    BluetoothHelper bluetoothHelper;
+    BluetoothHelperCharacteristic characteristicWrite;
+    BluetoothHelperService bluetoothService;
+    string targetDeviceName = "Bbow_20210501";
+    string deviceName = "";
+    bool canConnect = true;
+    [SerializeField] Text textUI;
+    public BluetoothStatusEnum status = BluetoothStatusEnum.Connect;
+    public bool hasData = false;
+    public long hasDataTime;
+    public static bool scanLock = false; //防止同时扫描冲突
+    public static BluetoothAim ins;
+
+    void Start() {
+        ins = this;
+        InitAutoDormancy();
+    }
+
+    void OnDestroy()
+    {
+        if (bluetoothHelper != null)
+        {
+            bluetoothHelper.Disconnect();
+        }
+    }
+
+    private bool userDoConnect = false;
+    private bool doConnect = false;
+    public void DoConnect() {
+        if (status == BluetoothStatusEnum.Connect) {
+            userDoConnect = true;
+            doConnect = true;
+            SetStatus(BluetoothStatusEnum.Connecting);
+        } else if (status == BluetoothStatusEnum.ConnectSuccess) {
+            userDoConnect = false;
+            doConnect = false;
+            OnDisconnect();
+            bluetoothHelper.Disconnect();
+        }
+    }
+
+    void OnDisconnect() {
+        hasData = false;
+        canConnect = true;
+        SetStatus(BluetoothStatusEnum.ConnectFail);
+        BowCamera.isTouchMode = true;
+        DestroyWhenDisconenct();
+    }
+
+    void Update()
+    {
+        if (userDoConnect && status == BluetoothStatusEnum.Connect) {
+            DoConnect();
+        }
+        if (doConnect) Connect();
+    }
+
+    void SetStatus(BluetoothStatusEnum statusValue) 
+    {
+        status = statusValue;
+        if (status == BluetoothStatusEnum.ConnectFail) {
+            Sequence sequence = DOTween.Sequence();
+            sequence.AppendInterval(2f);
+            sequence.AppendCallback(delegate() {
+                if (status == BluetoothStatusEnum.ConnectFail) {
+                    status = BluetoothStatusEnum.Connect;        
+                }
+            });
+            sequence.SetUpdate(true);
+            DeviceReconnectView.Show();
+        }
+    }
+
+    void Connect()
+    {
+        if (BluetoothShoot.scanLock)
+        {
+            return;
+        }
+        if (!canConnect)
+        {
+            return;
+        }
+        doConnect = false;
+        scanLock = true;
+        canConnect = false;
+        SetStatus(BluetoothStatusEnum.Connecting);
+        try
+        {
+            BluetoothHelper.BLE = true;
+            bluetoothHelper = BluetoothHelper.GetNewInstance();
+
+            bluetoothHelper.OnConnected += (BluetoothHelper helper) =>
+            {
+                Log("连接成功\n" + helper.getDeviceName());
+                SetStatus(BluetoothStatusEnum.ConnectSuccess);
+                BowCamera.isTouchMode = false;
+                foreach (BluetoothHelperService service in helper.getGattServices())
+                {
+                
+                    if (service.getName().ToLower().StartsWith("0000fff0"))
+                    {
+                        bluetoothService = service;
+
+                        foreach (BluetoothHelperCharacteristic characteristic in service.getCharacteristics())
+                        {
+                            if (characteristic.getName().ToLower().StartsWith("0000fff2"))
+                            {
+                                characteristicWrite = characteristic;
+                            }
+                            else if (characteristic.getName().ToLower().StartsWith("0000fff1"))
+                            {
+
+                                BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristic.getName());
+                                ch.setService(bluetoothService.getName());
+                                bluetoothHelper.Subscribe(ch);
+                            }
+                        }
+                    }
+                }
+                // CallDelay(1, OpenInfrared);
+                // CallDelay(2, OpenReceiveData);
+                // CallDelay(3, RequestBattery);
+                CallDelay(2, () => {
+                    if (status != BluetoothStatusEnum.ConnectSuccess) return;
+                    InitWhenConenct();
+                });
+            };
+            bluetoothHelper.OnConnectionFailed += (BluetoothHelper helper) =>
+            {
+                Log("连接失败\n" + helper.getDeviceName());
+                OnDisconnect();
+            };
+            bluetoothHelper.OnCharacteristicChanged += (helper, value, characteristic) =>
+            {
+                if (!hasData) hasDataTime = JC.CS.Utility.GetTimestamp();
+                hasData = true;
+                byte[] bytes = value;
+                // Log(String.Join(",", bytes));
+                BluetoothClient.UploadData(0, bytes);
+                if (AimHandler.ins)
+                {
+                    AimHandler.ins.OnDataReceived(bytes);
+                }
+            };
+            int scanCount = 0;
+            bluetoothHelper.OnScanEnded += (BluetoothHelper helper, LinkedList<BluetoothDevice> nearbyDevices) =>
+            {
+                scanLock = false;
+                foreach (BluetoothDevice device in nearbyDevices)
+                {
+                    if (device.DeviceName == targetDeviceName)
+                    {
+                        deviceName = device.DeviceName;
+                        bluetoothHelper.setDeviceName(deviceName);
+                        bluetoothHelper.Connect();
+                        Log("发现设备\n" + device.DeviceName);
+                        return;
+                    }
+                }
+                if (scanCount < 3) { //如果没扫描到,则重新扫描,达到延迟提示失败的效果
+                    scanCount++;
+                    scanLock = true;
+                    bluetoothHelper.ScanNearbyDevices();
+                } else {
+                    canConnect = true;
+                    Log("没有发现设备");
+                    SetStatus(BluetoothStatusEnum.ConnectFail);
+                }
+            };
+
+            bluetoothHelper.ScanNearbyDevices();
+            Log("正在扫描设备");
+        }
+        catch (Exception e)
+        {
+            Debug.Log(e.Message);
+            canConnect = true;
+            Log("请打开蓝牙");
+        }
+    }
+
+    #region 自动进入/退出休眠状态, 这里做程指令发送队列,为了控制连续发送指令的间隔,避免硬件收不到或处理不过来
+        class CmdToSend {
+            public string[] cmds;
+            public Action onComplete;
+            public Func<bool> canDo; 
+            public CmdToSend(string[] cmds, Action onComplete, Func<bool> canDo) {
+                this.cmds = cmds; 
+                this.onComplete = onComplete;
+                this.canDo = canDo;
+            }
+        }
+        Queue<CmdToSend> cmdWaitingList = new Queue<CmdToSend>();
+        bool isSendCmdLocked = false;
+        bool canAutoDormancy = false;
+        bool isStartUp = false;
+        JC.CS.CountLocker needModularAwake = new JC.CS.CountLocker();
+        void CheckAndStartUp() {
+            if (needModularAwake.IsLocked()) {
+                StartUp();
+            } else {
+                Dormancy();
+            }
+        }
+        void InitAutoDormancy() {
+            // GlobalEventCenter.ins.onGameSceneLoad += () => { 
+            //     needModularAwake.Lock(); 
+            //     CheckAndStartUp();
+            // };
+            // GlobalEventCenter.ins.onGameSceneDestroy += () => { 
+            //     needModularAwake.Unlock(); 
+            //     CheckAndStartUp();
+            // };
+            // GlobalEventCenter.ins.onSimulateMouseAwakeChanged += (waked) => {
+            //     if (waked) needModularAwake.Lock();
+            //     else needModularAwake.Unlock();;
+            //     CheckAndStartUp();
+            // };
+            // GlobalEventCenter.ins.onDeviceCalibrateViewAwakeChanged += (waked) => {
+            //     if (waked) needModularAwake.Lock();
+            //     else needModularAwake.Unlock();;
+            //     CheckAndStartUp();
+            // };
+            //暂时关闭自动休眠,默认是需要模块保持激活
+            needModularAwake.Lock(); 
+        }
+        void InitWhenConenct() { 
+            canAutoDormancy = true;
+            List<string> cmds = new List<string>();
+            cmds.Add("b"); //确保开启stm32
+            cmds.Add("b"); //获取初始电量
+            cmds.Add("1"); //开启发送逻辑
+            Action onComplete = null;
+            if (needModularAwake.IsLocked()) {
+                cmds.Add("w"); //红外灯开启
+                cmds.Add("3"); //九轴开启
+                onComplete = () => {
+                    isStartUp = true;
+                };
+            } else {
+                cmds.Add("s"); //红外灯关闭
+                cmds.Add("S"); //Stm32关闭
+                cmds.Add("4"); //九轴关闭
+                onComplete = () => {
+                    isStartUp = false;
+                };
+            }
+            SendCDM(null, onComplete, cmds.ToArray());
+        }
+        void DestroyWhenDisconenct() {
+            canAutoDormancy = false;
+            sendCMD_CheckAndDoStop(null);
+
+        }
+        //启动
+        void StartUp() {
+            SendCDM(() => {
+                return !isStartUp;
+            }, () => {
+                isStartUp = true;
+            }, "b", "w", "3");
+        }
+        //休眠
+        void Dormancy() {
+            SendCDM(() => {
+                return isStartUp;
+            }, () => {
+                isStartUp = false;
+            }, "4", "s", "S");
+        }
+        void SendCDM(Func<bool> canDo, Action onComplete, params string[] cmds) {
+            CmdToSend cmdToSend = new CmdToSend(cmds, onComplete, canDo);
+            if (isSendCmdLocked) {
+                cmdWaitingList.Enqueue(cmdToSend);
+                return;
+            }
+            sendCMD_NotCheck(cmdToSend);
+        }   
+        void sendCMD_NotCheck(CmdToSend cmdToSend) {
+            if (cmdToSend.canDo != null && !cmdToSend.canDo.Invoke()) {
+                sendCMD_CheckNext();
+                return;
+            }
+            isSendCmdLocked = true;
+            Sequence sequence = DOTween.Sequence();
+            sequence.PrependInterval(0.3f);
+            foreach (var cmd in cmdToSend.cmds) {
+                sequence.AppendCallback(() => {
+                    bool stopped = sendCMD_CheckAndDoStop(sequence);
+                    if (!stopped) WriteData(cmd);
+                });
+                sequence.AppendInterval(0.5f);
+            }
+            sequence.AppendCallback(() => {
+                bool stopped = sendCMD_CheckAndDoStop(sequence);
+                if (!stopped) {
+                    isSendCmdLocked = false;
+                    cmdToSend.onComplete?.Invoke();
+                    sendCMD_CheckNext();
+                }
+            });
+            sequence.SetUpdate(true);
+        }
+        void sendCMD_CheckNext() {
+            if (cmdWaitingList.Count <= 0) return;
+            CmdToSend cmdToSend = cmdWaitingList.Dequeue();
+            sendCMD_NotCheck(cmdToSend);
+        }
+        bool sendCMD_CheckAndDoStop(Sequence sequence) {
+            if (canAutoDormancy) return false;
+            isStartUp = false;
+            isSendCmdLocked = false;
+            cmdWaitingList.Clear();
+            if (sequence != null) sequence.Kill();
+            return true;
+        }
+    #endregion
+
+
+    void OpenInfrared()
+    {
+        WriteData("1");
+        Log("红外线准备完成\n" + deviceName);
+    }
+
+    void OpenReceiveData()
+    {
+        WriteData("3");
+        Log("瞄准模块准备完成\n" + deviceName);
+    }
+
+    public void RequestBattery() {
+        if (!isStartUp) return;
+        if (isSendCmdLocked) return;
+        WriteData("b");
+    }
+
+    public void ReplyInfraredShoot() {
+        if (isSendCmdLocked) return;
+        WriteData("I");
+    }
+
+    void CallDelay(float delayTime, TweenCallback callback)
+    {
+        Sequence sequence = DOTween.Sequence();
+        sequence.PrependInterval(delayTime).AppendCallback(callback);
+        sequence.SetUpdate(true);
+    }
+
+    public void WriteData(string data)
+    {
+        if (DebugDeviceCMD.ins) DebugDeviceCMD.ins.ShowCMD(data);
+        BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristicWrite.getName());
+        ch.setService(bluetoothService.getName());
+        bluetoothHelper.WriteCharacteristic(ch, data);
+    }
+
+    void Log(string text)
+    {
+        if (textUI) 
+        {
+            textUI.text = text;
+        }
+    }
+}
+// public class BluetoothAim : MonoBehaviour
+// {
+//     BluetoothHelper bluetoothHelper;
+//     BluetoothHelperCharacteristic characteristicWrite;
+//     BluetoothHelperService bluetoothService;
+//     string targetDeviceName = "Bbow_20210501";
+//     string deviceName = "";
+//     bool canConnect = true;
+//     [SerializeField] Text textUI;
+//     public BluetoothStatusEnum status = BluetoothStatusEnum.Connect;
+//     public bool hasData = false;
+//     public long hasDataTime;
+//     public static bool scanLock = false; //防止同时扫描冲突
+//     public static BluetoothAim ins;
+
+//     void Start() {
+//         ins = this;
+//     }
+
+//     void OnDestroy()
+//     {
+//         if (bluetoothHelper != null)
+//         {
+//             bluetoothHelper.Disconnect();
+//         }
+//     }
+
+//     private bool userDoConnect = false;
+//     private bool doConnect = false;
+//     public void DoConnect() {
+//         if (status == BluetoothStatusEnum.Connect) {
+//             userDoConnect = true;
+//             doConnect = true;
+//             SetStatus(BluetoothStatusEnum.Connecting);
+//         } else if (status == BluetoothStatusEnum.ConnectSuccess) {
+//             userDoConnect = false;
+//             doConnect = false;
+//             OnDisconnect();
+//             bluetoothHelper.Disconnect();
+//         }
+//     }
+
+//     void OnDisconnect() {
+//         hasData = false;
+//         canConnect = true;
+//         SetStatus(BluetoothStatusEnum.ConnectFail);
+//         BowCamera.isTouchMode = true;
+//     }
+
+//     void Update()
+//     {
+//         if (userDoConnect && status == BluetoothStatusEnum.Connect) {
+//             DoConnect();
+//         }
+//         if (doConnect) Connect();
+//     }
+
+//     void SetStatus(BluetoothStatusEnum statusValue) 
+//     {
+//         status = statusValue;
+//         if (status == BluetoothStatusEnum.ConnectFail) {
+//             Sequence sequence = DOTween.Sequence();
+//             sequence.AppendInterval(2f);
+//             sequence.AppendCallback(delegate() {
+//                 if (status == BluetoothStatusEnum.ConnectFail) {
+//                     status = BluetoothStatusEnum.Connect;        
+//                 }
+//             });
+//             sequence.SetUpdate(true);
+//             DeviceReconnectView.Show();
+//         }
+//     }
+
+//     void Connect()
+//     {
+//         if (BluetoothShoot.scanLock)
+//         {
+//             return;
+//         }
+//         if (!canConnect)
+//         {
+//             return;
+//         }
+//         doConnect = false;
+//         scanLock = true;
+//         canConnect = false;
+//         SetStatus(BluetoothStatusEnum.Connecting);
+//         try
+//         {
+//             BluetoothHelper.BLE = true;
+//             bluetoothHelper = BluetoothHelper.GetNewInstance();
+
+//             bluetoothHelper.OnConnected += (BluetoothHelper helper) =>
+//             {
+//                 Log("连接成功\n" + helper.getDeviceName());
+//                 SetStatus(BluetoothStatusEnum.ConnectSuccess);
+//                 BowCamera.isTouchMode = false;
+//                 foreach (BluetoothHelperService service in helper.getGattServices())
+//                 {
+                
+//                     if (service.getName().ToLower().StartsWith("0000fff0"))
+//                     {
+//                         bluetoothService = service;
+
+//                         foreach (BluetoothHelperCharacteristic characteristic in service.getCharacteristics())
+//                         {
+//                             if (characteristic.getName().ToLower().StartsWith("0000fff2"))
+//                             {
+//                                 characteristicWrite = characteristic;
+//                             }
+//                             else if (characteristic.getName().ToLower().StartsWith("0000fff1"))
+//                             {
+
+//                                 BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristic.getName());
+//                                 ch.setService(bluetoothService.getName());
+//                                 bluetoothHelper.Subscribe(ch);
+//                             }
+//                         }
+//                     }
+//                 }
+//                 CallDelay(1, OpenInfrared);
+//                 CallDelay(2, OpenReceiveData);
+//                 CallDelay(3, RequestBattery);
+//             };
+//             bluetoothHelper.OnConnectionFailed += (BluetoothHelper helper) =>
+//             {
+//                 Log("连接失败\n" + helper.getDeviceName());
+//                 OnDisconnect();
+//             };
+//             bluetoothHelper.OnCharacteristicChanged += (helper, value, characteristic) =>
+//             {
+//                 if (!hasData) hasDataTime = JC.CS.Utility.GetTimestamp();
+//                 hasData = true;
+//                 byte[] bytes = value;
+//                 // Log(String.Join(",", bytes));
+//                 BluetoothClient.UploadData(0, bytes);
+//                 if (AimHandler.ins)
+//                 {
+//                     AimHandler.ins.OnDataReceived(bytes);
+//                 }
+//             };
+//             bluetoothHelper.OnScanEnded += (BluetoothHelper helper, LinkedList<BluetoothDevice> nearbyDevices) =>
+//             {
+//                 scanLock = false;
+//                 foreach (BluetoothDevice device in nearbyDevices)
+//                 {
+//                     if (device.DeviceName == targetDeviceName)
+//                     {
+//                         deviceName = device.DeviceName;
+//                         bluetoothHelper.setDeviceName(deviceName);
+//                         bluetoothHelper.Connect();
+//                         Log("发现设备\n" + device.DeviceName);
+//                         return;
+//                     }
+//                 }
+//                 canConnect = true;
+//                 Log("没有发现设备");
+//                 SetStatus(BluetoothStatusEnum.ConnectFail);
+//             };
+
+//             bluetoothHelper.ScanNearbyDevices();
+//             Log("正在扫描设备");
+//         }
+//         catch (Exception e)
+//         {
+//             Debug.Log(e.Message);
+//             canConnect = true;
+//             Log("请打开蓝牙");
+//         }
+//     }
+
+//     void OpenInfrared()
+//     {
+//         WriteData("1");
+//         Log("红外线准备完成\n" + deviceName);
+//     }
+
+//     void OpenReceiveData()
+//     {
+//         WriteData("3");
+//         Log("瞄准模块准备完成\n" + deviceName);
+//     }
+
+//     public void RequestBattery() {
+//         WriteData("b");
+//     }
+
+//     public void ReplyInfraredShoot() {
+//         WriteData("I");
+//     }
+
+//     void CallDelay(float delayTime, TweenCallback callback)
+//     {
+//         Sequence sequence = DOTween.Sequence();
+//         sequence.PrependInterval(delayTime).AppendCallback(callback);
+//         sequence.SetUpdate(true);
+//     }
+
+//     public void WriteData(string data)
+//     {
+//         BluetoothHelperCharacteristic ch = new BluetoothHelperCharacteristic(characteristicWrite.getName());
+//         ch.setService(bluetoothService.getName());
+//         bluetoothHelper.WriteCharacteristic(ch, data);
+//     }
+
+//     void Log(string text)
+//     {
+//         if (textUI) 
+//         {
+//             textUI.text = text;
+//         }
+//     }
+// }

+ 1 - 0
代码备份/2022-6-4/备份原因.txt

@@ -0,0 +1 @@
+因为需要接入PC端蓝牙

+ 377 - 0
代码备份/2022-7-15/AimHandler.cs

@@ -0,0 +1,377 @@
+using System;
+using UnityEngine;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine.UI;
+using Newtonsoft.Json;
+/* 瞄准处理器 */
+public class AimHandler : MonoBehaviour
+{
+    Transform controlObj {
+        get {
+            if (CameraToLook.ins) {
+                return CameraToLook.ins.transform;
+            }
+            return null;
+        }
+    }
+    [SerializeField] Button SetIdentityButton;
+    [SerializeField] Button MagCalibrationButton;
+    [SerializeField] Button GyrCalibrationButton;
+    [SerializeField] Text MagScaleText;
+    [SerializeField] Text GyrScaleText;
+
+    //椭圆对象
+    [SerializeField] Ellipse ellipseScript;
+    [SerializeField] GameObject AccObj;
+    [SerializeField] GameObject MagObj;
+
+    [SerializeField] GameObject AccMesh;
+    [SerializeField] GameObject GryMesh;
+    [SerializeField] GameObject MagMesh;
+    [SerializeField] GameObject AMesh;
+    [SerializeField] Transform DebugTexts;
+    [SerializeField] Transform DrawImage;
+    
+    long TimeGap = default;
+    Vector3 Acc = default;
+    Vector3 Gyr = default;
+    Vector3 Mag = default;
+    o09Axis _9Axis = new o09Axis();
+
+    Vector3 cMaxVector = new Vector3(0,0,0);
+    Vector3 cMinVector = new Vector3(0, 0, 0);
+
+    public o0MagneticCalibraterEllipsoidFitting MagCalibrater;
+    o0GyrCalibrater GyrCalibrater;
+
+    //陀螺仪校准进度记录
+    public int gyrCalibrateCompleteCount = 0;
+    public int gyrCalibrateTotalCount = 300;
+
+    long msOld = 0;
+
+    public static AimHandler ins; 
+
+    void Start()
+    {
+        ins = this;
+        BluetoothDispatcher.aim = OnDataReceived;
+
+        //初始化
+        _9Axis.LoadIdentity();
+
+        _9Axis.AccMesh = AccMesh;
+        _9Axis.GryMesh = GryMesh;
+        _9Axis.MagMesh = MagMesh;
+
+        for (var i = 0; i < 9; ++i)
+        {
+            _9Axis.Tester.Add(DrawImage.Find(i.ToString()).gameObject.AddComponent<o0UIRawImageTester>());
+        }
+
+        for (var i = 0; i < 15; ++i)
+        {
+            _9Axis.TextTester.Add(DebugTexts.transform.Find("Text" + i.ToString()).gameObject.GetComponent<Text>());
+        }
+
+        if (SetIdentityButton) 
+        {
+            SetIdentityButton.onClick.AddListener(DoIdentity);
+        }
+        
+        try 
+        {  
+            string magDataStr = PlayerPrefs.GetString("o0MagneticCalibrater");
+            MagCalibrater = JsonConvert.DeserializeObject<o0MagneticCalibraterEllipsoidFitting>(magDataStr);
+        } 
+        catch(Exception) 
+        {
+            MagCalibrater = null;
+        }
+
+        if (MagCalibrater == null) 
+        {
+            MagCalibrater = new o0MagneticCalibraterEllipsoidFitting();
+        }
+        if (MagCalibrationButton)
+        {
+            MagCalibrationButton.onClick.AddListener(delegate {
+                CalibrateMag(!MagCalibrater.Calibration);
+            });
+        }
+
+        try {
+            string gyrDataStr = PlayerPrefs.GetString("o0GyrCalibrater");
+            GyrCalibrater = JsonConvert.DeserializeObject<o0GyrCalibrater>(gyrDataStr);
+            if (GyrCalibrater._Average != Vector3.zero) GyrScaleText.text = "已校准";
+        } catch(Exception) {
+            GyrCalibrater = null;
+        }
+        if (GyrCalibrater == null) 
+        {
+            GyrCalibrater = new o0GyrCalibrater();
+        }
+        if (GyrCalibrationButton)
+        {
+            GyrCalibrationButton.onClick.AddListener(delegate() {
+                CalibrateGyr(!GyrCalibrater.Calibration);
+            });
+        }
+    }
+
+    public void CalibrateGyr(bool calibration) {
+        try {
+            GyrCalibrater.Calibration = calibration;
+            if (calibration)
+            {
+                GyrCalibrationButton.GetComponentInChildren<Text>().text = "停止陀螺仪校准";
+            }
+            else
+            {
+                GyrCalibrationButton.GetComponentInChildren<Text>().text = "开始陀螺仪校准";
+                PlayerPrefs.SetString("o0GyrCalibrater", JsonConvert.SerializeObject(GyrCalibrater));            
+            }
+        } catch (Exception e) { Debug.LogError(e.Message); }
+    }
+
+     public void CalibrateMag(bool calibration) {
+        try {
+            if (calibration)
+            {
+                MagCalibrater.Calibration = calibration;
+                MagCalibrationButton.GetComponentInChildren<Text>().text = "停止地磁计校准";
+                this.cMaxVector = new Vector3(0, 0, 0);
+                this.cMinVector = new Vector3(0, 0, 0);
+                this.ellipseScript.ellipseTran.gameObject.SetActive(false);
+            }
+            else
+            {
+                List<Vector3> list = MagCalibrater.getRecords();
+                //停止校准时候,看看数组值
+                float maxDistance = 0f,ratio = 1f;
+                Vector3 maxVector3 = new Vector3(0,0,0);
+                List<Vector3> endRecords = new List<Vector3>();
+                foreach (Vector3 i in list)
+                {
+                    Vector3 v = i - MagCalibrater._Center;
+                    if (Math.Abs(v.magnitude) > maxDistance)
+                    {
+                        maxVector3 = v;
+                        maxDistance = Math.Abs(v.magnitude);
+                        if(Math.Abs(v.magnitude) < Math.Abs(MagCalibrater._Radius.magnitude))
+                            ratio = Math.Abs(v.magnitude) / Math.Abs(MagCalibrater._Radius.magnitude);
+                        else
+                            ratio = Math.Abs(MagCalibrater._Radius.magnitude) / Math.Abs(v.magnitude);
+                    }
+                }
+                Debug.LogWarning(maxDistance + " == " + Math.Abs(MagCalibrater._Radius.magnitude) + " == " + MagCalibrater._Radius + " = " + maxVector3);
+                //如果比例效果不理想。可以设置为ratio=0.5f 
+                foreach (Vector3 i in list)
+                {
+                    //- MagCalibrater._Center
+                    Vector3 v = i ;
+                    v *= ratio;
+                    if(endRecords.Count>3000)
+                    {
+                        endRecords.RemoveAt(0);
+                    }
+                    endRecords.Add(v);
+                }
+                this.ellipseScript.ClearAndUpdatePointArray();
+                this.ellipseScript.DrawPointCloud(endRecords);
+
+                MagCalibrater.Calibration = calibration;
+
+                this.ellipseScript.ellipseTran.gameObject.SetActive(true);
+                //绘制椭圆形
+                if (MagCalibrater._Radius != this.ellipseScript.ellipseTran.localScale)
+                {
+                    this.ellipseScript.setEllipseLocalScaleAndCenter(MagCalibrater._Radius, MagCalibrater._Center* ratio);
+                    //设置绘制图像相机的对应位置
+                    this.ellipseScript.setCameraPos(MagCalibrater._Center * 0.5f);
+                }
+
+                MagCalibrationButton.GetComponentInChildren<Text>().text = "开始地磁计校准";
+                PlayerPrefs.SetString("o0MagneticCalibrater", JsonConvert.SerializeObject(MagCalibrater));
+            }
+        } catch (Exception e) { Debug.LogError(e.Message); }
+    }
+
+    //转换读取的数据,无符号->有符号
+    float TwoByteToFloat(byte b1, byte b2) 
+    {
+        ushort twoByte = (ushort) (b1 * 256 + b2);
+        short shortNum = (short) twoByte;
+        return (float) shortNum; 
+    }
+
+    public void OnDataReceived(byte[] bytes)
+    {
+        // Debug.Log("瞄准模块数据长度" + bytes.Length);
+        if (bytes.Length != 27)
+        {
+            if (bytes.Length == 2) {
+                if (bytes[0] == 0x66 && bytes[1] == 0x31) {
+                    if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked) {
+                        //鼠标居中
+                        SB_EventSystem.ins.MakeMouseToScreenCenter(); 
+                    }
+                    //视角回正
+                    DoIdentity();
+                } else if (bytes[0] == 0x66 && bytes[1] == 0x32) {
+                    if (SB_EventSystem.ins) {
+                        //唤起/隐藏虚拟鼠标
+                        SB_EventSystem.ins.AwakenSimulateMouse(); 
+                    }
+                } else if (bytes[1] == 10) {
+                    //显示电量
+                    DeviceBatteryView.ins.RenderBattery(1, bytes[0]); 
+                }
+            } else if (bytes[0] == 0x5b) {
+                if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked) {
+                    //点击鼠标
+                    SB_EventSystem.ins.ClickMouse(); 
+                } else {
+                    //红外射击检测
+                    ShootCheck.ins.ShootByInfrared(bytes); 
+                }
+            }
+            return;
+        }
+        if (bytes[7] == 0 && bytes[8] == 0 && bytes[9] == 0 && bytes[10] == 0 && bytes[11] == 0 && bytes[12] == 0)
+            return;
+        if (bytes[19] == 0 && bytes[20] == 0 && bytes[21] == 0 && bytes[22] == 0 && bytes[23] == 0 && bytes[24] == 0)
+            return;
+        
+        float ax = -TwoByteToFloat(bytes[7], bytes[8]);
+        float ay = -TwoByteToFloat(bytes[9], bytes[10]);
+        float az = -TwoByteToFloat(bytes[11], bytes[12]);
+        ax = ax / 32768 * 16;
+        ay = ay / 32768 * 16;
+        az = az / 32768 * 16;
+        Acc = new Vector3(ay, ax, az);
+        AccObj.transform.GetChild(0).localPosition = Acc;
+
+
+        float roll = TwoByteToFloat(bytes[13], bytes[14]);
+        float pitch = TwoByteToFloat(bytes[15], bytes[16]);
+        float yaw = TwoByteToFloat(bytes[17], bytes[18]);
+        roll = -roll / 32768 * 2000;
+        pitch = -pitch / 32768 * 2000;
+        yaw = -yaw / 32768 * 2000;
+        Gyr = new Vector3(pitch, roll, yaw) / 1000;
+        Gyr = GyrCalibrater.Update(Gyr);
+        if (GyrCalibrater.Calibration) 
+        {
+            if (gyrCalibrateCompleteCount < gyrCalibrateTotalCount) {
+                gyrCalibrateCompleteCount++;
+            }
+        }
+        if (GyrScaleText && GyrCalibrater.Calibration) 
+        {    
+            // GyrScaleText.text = GyrCalibrater._Average.x + "\n" + GyrCalibrater._Average.y + "\n" + GyrCalibrater._Average.z;
+            // GyrScaleText.text = "Gyr*1000,000:" + (_9Axis.GyrOld * 1000000).ToString();
+            GyrScaleText.text = "" + (_9Axis.getGyrOld() * 1000000).ToString();
+        }
+
+        float x = TwoByteToFloat(bytes[19], bytes[20]);
+        float y = TwoByteToFloat(bytes[21], bytes[22]);
+        float z = TwoByteToFloat(bytes[23], bytes[24]);
+        var mag = new Vector3(-y, x, -z);
+        Mag = mag / 32768 * 256;
+    
+
+        if(Mag.x > -128 && Mag.y > -128 && Mag.z > -128 && Mag.x < 128 && Mag.y < 128 && Mag.z < 128)
+        {   
+            //绘制地磁计点
+            if (MagCalibrater.Calibration)
+            {
+                this.ellipseScript.AddAndUpdatePointArray(Mag);
+
+                if (Mag.magnitude > this.cMaxVector.magnitude)
+                {
+                    this.cMaxVector = Mag;
+                }
+                else if (Mag.magnitude < this.cMinVector.magnitude) {
+                    this.cMinVector = Mag;
+                }
+
+                Vector3 _center = this.cMaxVector - this.cMinVector;
+                Debug.LogWarning(_center + " == "+ _center.magnitude);
+                //设置绘制图像相机的对应位置
+                this.ellipseScript.setCameraPos(_center/2);
+            }
+            Mag = MagCalibrater.Update(Mag);
+
+            if (MagScaleText)
+            {
+                MagScaleText.text = MagCalibrater._Radius.ToString();
+            }
+           
+        }
+        MagObj.transform.GetChild(0).localPosition = Mag;
+
+        var ms = (((long)bytes[1]) *60 + bytes[2])*1000 + (long)TwoByteToFloat(bytes[3], bytes[4]);
+        if(msOld == default)
+        {
+            msOld = ms;
+            return;
+        }
+        TimeGap = ms - msOld;
+        msOld = ms;
+
+        AMesh.transform.localRotation = newRotation = _9Axis.update(Acc * 10, Gyr, Mag, TimeGap);
+
+        if (BowQuatDebug.ins) BowQuatDebug.ins.ShowModuleQuat(newRotation.eulerAngles);
+
+        if (SB_EventSystem.ins && SB_EventSystem.ins.simulateMouseIsAwaked) {
+            SB_EventSystem.ins.MoveSimulateMouse(newRotation);
+        }
+        // 记录一些旋转角---start
+        // if (ArmBow.ins) {
+        //     for (int i = ArmBow.ins.recordRotations.Length - 1; i > 0 ; i--)
+        //     {
+        //         ArmBow.ins.recordRotations[i] = ArmBow.ins.recordRotations[i - 1];
+        //     }
+        //     ArmBow.ins.recordRotations[0] = newRotation;
+        //     ArmBow.ins.recordCount++;
+        // }
+        // 记录一些旋转角---end
+    }   
+
+    [NonSerialized] public bool lerpForRotation = true;
+    [NonSerialized] public float lerpTimeRate = 7;
+    public void Update()
+    {
+        if (controlObj && !banControlObjRotate)
+        {
+            if (lerpForRotation)
+            {
+                controlObj.localRotation = Quaternion.Lerp(controlObj.localRotation, newRotation, Time.deltaTime * lerpTimeRate);   
+            } 
+            else 
+            {
+                controlObj.localRotation = newRotation;
+            }
+        }
+    }
+
+    private bool banControlObjRotate = false;
+    public void BanControlObjRotate(bool ban) {
+        banControlObjRotate = ban;
+        if (!ban) {
+            if (controlObj) controlObj.localRotation = newRotation;
+        }
+    }
+
+    Quaternion newRotation = Quaternion.identity;
+
+    public void DoIdentity()
+    {
+        _9Axis.SetIdentityAndSave();
+        Quaternion qua = _9Axis.getLastState().Qua;
+        newRotation = qua;
+        if (controlObj) controlObj.localRotation = qua;
+    }
+}