diff --git a/Assets/Resources/Animation/Nod.anim b/Assets/Resources/Animation/Nod.anim index a924e1c..60eaee6 100644 --- a/Assets/Resources/Animation/Nod.anim +++ b/Assets/Resources/Animation/Nod.anim @@ -214208,7 +214208,7 @@ AnimationClip: intParameter: 3 messageOptions: 0 - time: 66.333336 - functionName: FinishCurrentActionCheck + functionName: FinishCurrentLevel data: objectReferenceParameter: {fileID: 0} floatParameter: 0 diff --git a/Assets/Resources/Animation/ShakeHead.anim b/Assets/Resources/Animation/ShakeHead.anim index 4c14194..57ce4c5 100644 --- a/Assets/Resources/Animation/ShakeHead.anim +++ b/Assets/Resources/Animation/ShakeHead.anim @@ -195595,3 +195595,10 @@ AnimationClip: floatParameter: 0 intParameter: 1 messageOptions: 0 + - time: 66.53333 + functionName: FinishCurrentLevel + data: + objectReferenceParameter: {fileID: 0} + floatParameter: 0 + intParameter: 0 + messageOptions: 0 diff --git a/Assets/Resources/UI/GuideUI.prefab b/Assets/Resources/UI/GuideUI.prefab index 32e83ee..6304b69 100644 --- a/Assets/Resources/UI/GuideUI.prefab +++ b/Assets/Resources/UI/GuideUI.prefab @@ -581,7 +581,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!224 &406787417813524232 RectTransform: m_ObjectHideFlags: 0 @@ -2051,7 +2051,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &3096906925272982799 RectTransform: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/PoseCheck/EstimateModel/CVEstimator.cs b/Assets/Scripts/PoseCheck/EstimateModel/CVEstimator.cs index 8efde88..4c07222 100644 --- a/Assets/Scripts/PoseCheck/EstimateModel/CVEstimator.cs +++ b/Assets/Scripts/PoseCheck/EstimateModel/CVEstimator.cs @@ -43,9 +43,9 @@ public class CVEstimator : Singleton } YogaManager.Instance.CurrentEstimator.Init(); + IsRunning = false; _mainThread = new Thread(new ThreadStart(MainThread)); _mainThread.Start(); - IsRunning = false; IsInited = true; } @@ -96,35 +96,45 @@ public class CVEstimator : Singleton { DateTime startTime = DateTime.Now; Mat bgrMat = new Mat(); + LogPrint.Log("IsRunning: " + IsRunning); while (IsRunning) { - Mat rgbaMat = YogaManager.Instance.RgbaMat; - if (rgbaMat == null) + try { - LogPrint.Log("WebCamTexture is null. "); - LogPrint.Log("Re-Estimation."); - continue; //重新检测 - } - Imgproc.cvtColor(rgbaMat, bgrMat, Imgproc.COLOR_RGBA2BGR); + LogPrint.Log("Estimation Thread Running!IsRunning: " + IsRunning); + Mat rgbaMat = YogaManager.Instance.RgbaMat; + if (rgbaMat == null) + { + LogPrint.Log("WebCamTexture is null. "); + LogPrint.Log("Re-Estimation."); + continue; //重新检测 + } + Imgproc.cvtColor(rgbaMat, bgrMat, Imgproc.COLOR_RGBA2BGR); - if (!YogaManager.Instance.CurrentEstimator.Esitmate(bgrMat, rgbaMat, out List points)) - { - LogPrint.Log("Pose estimation failed. Re-Estimating."); - continue; //重新检测 - } + if (!YogaManager.Instance.CurrentEstimator.Esitmate(bgrMat, rgbaMat, out List points)) + { + LogPrint.Log("Pose estimation failed. Re-Estimating."); + continue; //重新检测 + } - //更新关键点位检测结果 - YogaManager.Instance.AddCurrEstimateKeyPoints(points); + //更新关键点位检测结果 + YogaManager.Instance.AddCurrEstimateKeyPoints(points); - //等待到下一个更新周期 - if (DateTime.Now - startTime > _refreshRate) - { - startTime = DateTime.Now; + //等待到下一个更新周期 + if (DateTime.Now - startTime > _refreshRate) + { + startTime = DateTime.Now; + } + else + { + Thread.Sleep(_refreshRate - (DateTime.Now - startTime)); + } } - else + catch (Exception e) { - Thread.Sleep(_refreshRate - (DateTime.Now - startTime)); + LogPrint.Exception(e); } + } bgrMat.Dispose(); } diff --git a/Assets/Scripts/PoseCheck/HandsHold.cs b/Assets/Scripts/PoseCheck/HandsHold.cs index 6949ce6..4a8ae48 100644 --- a/Assets/Scripts/PoseCheck/HandsHold.cs +++ b/Assets/Scripts/PoseCheck/HandsHold.cs @@ -31,18 +31,26 @@ public class HandsHold : PoseBase public override void ValidationMovement(Vector2 distance, TimeSpan totalTimeSpan, int level) { + if (totalTimeSpan.TotalMilliseconds / 1000 < 0.05f) + { + LogPrint.Error("TimeSpan too short"); + return; + } var angle = Vector2.SignedAngle(Vector2.down, distance); LogPrint.Log($"Angle:{angle}", PrintLevel.Normal); if (MathF.Abs(angle) < 10) EventManager.Instance.Dispatch(YogaEventType.Action_Success); //方向不能偏移超过10° else + { EventManager.Instance.Dispatch(YogaEventType.Action_Fail); + return; + } if (level < 1) return; - LogPrint.Log($"distance x:{distance.x}, y:{distance.y}, magnitude:{distance.magnitude}", PrintLevel.Normal); - if (distance.magnitude > 5f || distance.magnitude < 0.1f) + LogPrint.Log($"distance x:{distance.x}, y:{distance.y}, magnitude:{distance.magnitude}"); + if (distance.magnitude > 80f || distance.magnitude < 20f) EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceNotAccurate); else EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceExactly); diff --git a/Assets/Scripts/PoseCheck/HandsUp.cs b/Assets/Scripts/PoseCheck/HandsUp.cs index 764f8c7..fe3e91a 100644 --- a/Assets/Scripts/PoseCheck/HandsUp.cs +++ b/Assets/Scripts/PoseCheck/HandsUp.cs @@ -32,18 +32,26 @@ public class HandsUp : PoseBase public override void ValidationMovement(Vector2 distance, TimeSpan totalTimeSpan, int level) { + if (totalTimeSpan.TotalMilliseconds / 1000 < 0.05f) + { + LogPrint.Error("TimeSpan too short"); + return; + } var angle = Vector2.SignedAngle(Vector2.up, distance); LogPrint.Log($"Angle:{angle}", PrintLevel.Normal); if (MathF.Abs(angle) < 10) EventManager.Instance.Dispatch(YogaEventType.Action_Success); //方向不能偏移超过10° else + { EventManager.Instance.Dispatch(YogaEventType.Action_Fail); + return; + } if (level < 1) return; LogPrint.Log($"distance x:{distance.x}, y:{distance.y}, magnitude:{distance.magnitude}", PrintLevel.Normal); - if (distance.magnitude > 5f || distance.magnitude < 0.1f) + if (distance.magnitude > 80f || distance.magnitude < 20f) EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceNotAccurate); else EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceExactly); diff --git a/Assets/Scripts/PoseCheck/HeadTurnDown.cs b/Assets/Scripts/PoseCheck/HeadTurnDown.cs index 767c8fb..d2f79f2 100644 --- a/Assets/Scripts/PoseCheck/HeadTurnDown.cs +++ b/Assets/Scripts/PoseCheck/HeadTurnDown.cs @@ -20,18 +20,27 @@ public class HeadTurnDown : PoseBase public override void ValidationMovement(Vector2 distance, TimeSpan totalTimeSpan, int level) { + if (totalTimeSpan.TotalMilliseconds / 1000 < 0.05f) + { + LogPrint.Error("TimeSpan too short"); + return; + } var angle = Vector2.SignedAngle(Vector2.down, distance); LogPrint.Log($"Angle:{angle}", PrintLevel.Normal); if (MathF.Abs(angle) < 10) EventManager.Instance.Dispatch(YogaEventType.Action_Success); //方向不能偏移超过10° else + { EventManager.Instance.Dispatch(YogaEventType.Action_Fail); + return; + } + if (level < 1) return; LogPrint.Log($"distance x:{distance.x}, y:{distance.y}, magnitude:{distance.magnitude}", PrintLevel.Normal); - if (distance.magnitude > 5f || distance.magnitude < 0.1f) + if (distance.magnitude > 80f || distance.magnitude < 20f) EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceNotAccurate); else EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceExactly); @@ -41,9 +50,9 @@ public class HeadTurnDown : PoseBase var speed = distance.magnitude / totalTimeSpan.TotalSeconds; LogPrint.Log($"speed:{speed}", PrintLevel.Normal); - if (speed > 0.5f) + if (speed > 20f) EventManager.Instance.Dispatch(YogaEventType.Action_SpeedTooFast); //速度语音提示 - else if (speed < 0.1f) + else if (speed < 8f) EventManager.Instance.Dispatch(YogaEventType.Action_SpeedTooSlow); //速度语音提示 } diff --git a/Assets/Scripts/PoseCheck/HeadTurnLeft.cs b/Assets/Scripts/PoseCheck/HeadTurnLeft.cs index d045f5f..2e58a68 100644 --- a/Assets/Scripts/PoseCheck/HeadTurnLeft.cs +++ b/Assets/Scripts/PoseCheck/HeadTurnLeft.cs @@ -21,18 +21,27 @@ public class HeadTurnLeft : PoseBase public override void ValidationMovement(Vector2 distance, TimeSpan totalTimeSpan, int level) { + if (totalTimeSpan.TotalMilliseconds / 1000 < 0.05f) + { + LogPrint.Error("TimeSpan too short"); + return; + } + var angle = Vector2.SignedAngle(Vector2.left, distance); LogPrint.Log($"Angle:{angle}", PrintLevel.Normal); if (MathF.Abs(angle) < 10) EventManager.Instance.Dispatch(YogaEventType.Action_Success); //方向不能偏移超过10° else + { EventManager.Instance.Dispatch(YogaEventType.Action_Fail); + return; + } if (level < 1) return; LogPrint.Log($"distance x:{distance.x}, y:{distance.y}, magnitude:{distance.magnitude}", PrintLevel.Normal); - if (distance.magnitude > 5f || distance.magnitude < 0.1f) + if (distance.magnitude > 80f || distance.magnitude < 20f) EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceNotAccurate); else EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceExactly); diff --git a/Assets/Scripts/PoseCheck/HeadTurnRight.cs b/Assets/Scripts/PoseCheck/HeadTurnRight.cs index a669b25..1760b34 100644 --- a/Assets/Scripts/PoseCheck/HeadTurnRight.cs +++ b/Assets/Scripts/PoseCheck/HeadTurnRight.cs @@ -21,18 +21,27 @@ public class HeadTurnRight : PoseBase public override void ValidationMovement(Vector2 distance, TimeSpan totalTimeSpan, int level) { + if (totalTimeSpan.TotalMilliseconds / 1000 < 0.05f) + { + LogPrint.Error("TimeSpan too short"); + return; + } + var angle = Vector2.SignedAngle(Vector2.right, distance); LogPrint.Log($"Angle:{angle}", PrintLevel.Normal); if (MathF.Abs(angle) < 10) EventManager.Instance.Dispatch(YogaEventType.Action_Success); //方向不能偏移超过10° else + { EventManager.Instance.Dispatch(YogaEventType.Action_Fail); + return; + } if (level < 1) return; LogPrint.Log($"distance x:{distance.x}, y:{distance.y}, magnitude:{distance.magnitude}", PrintLevel.Normal); - if (distance.magnitude > 5f || distance.magnitude < 0.1f) + if (distance.magnitude > 80f || distance.magnitude < 20f) EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceNotAccurate); else EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceExactly); diff --git a/Assets/Scripts/PoseCheck/HeadTurnUp.cs b/Assets/Scripts/PoseCheck/HeadTurnUp.cs index 3740809..b194a49 100644 --- a/Assets/Scripts/PoseCheck/HeadTurnUp.cs +++ b/Assets/Scripts/PoseCheck/HeadTurnUp.cs @@ -20,18 +20,26 @@ public class HeadTurnUp : PoseBase public override void ValidationMovement(Vector2 distance, TimeSpan totalTimeSpan, int level) { + if (totalTimeSpan.TotalMilliseconds / 1000 < 0.05f) + { + LogPrint.Error("TimeSpan too short"); + return; + } var angle = Vector2.SignedAngle(Vector2.up, distance); LogPrint.Log($"Angle:{angle}", PrintLevel.Normal); if (MathF.Abs(angle) < 10) EventManager.Instance.Dispatch(YogaEventType.Action_Success); //方向不能偏移超过10° else + { EventManager.Instance.Dispatch(YogaEventType.Action_Fail); + return; + } if (level < 1) return; LogPrint.Log($"distance x:{distance.x}, y:{distance.y}, magnitude:{distance.magnitude}", PrintLevel.Normal); - if (distance.magnitude > 5f || distance.magnitude < 0.1f) + if (distance.magnitude > 80f || distance.magnitude < 20f) EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceNotAccurate); else EventManager.Instance.Dispatch(YogaEventType.Action_MoveDistanceExactly); diff --git a/Assets/Scripts/PoseCheck/PoseBase.cs b/Assets/Scripts/PoseCheck/PoseBase.cs index 1e574a1..4aabc87 100644 --- a/Assets/Scripts/PoseCheck/PoseBase.cs +++ b/Assets/Scripts/PoseCheck/PoseBase.cs @@ -1,6 +1,7 @@ using OpenCVForUnity.CoreModule; using System; using System.Collections.Generic; +using System.Linq; using UnityEngine; public abstract class PoseBase @@ -74,15 +75,23 @@ public abstract class PoseBase return; var distance = Vector2.zero; - var totalTimeSpan = TimeSpan.Zero; + TimeSpan totalTimeSpan = TimeSpan.MinValue; for (int i = 0; i < points.Count - 1; i++) { var p1 = points[i].Item2; var p2 = points[i + 1].Item2; - TimeSpan timeSpan = points[i + 1].Item1 - points[i].Item1; + var vector = GetAverageVector(p1, p2, "Nose"); //关键点Nose distance += vector; - totalTimeSpan += timeSpan; + if (vector.magnitude > 0.1f) //如果矢量长度大于0.1f,说明有运动 + { + TimeSpan timeSpan = points[i + 1].Item1 - points[i].Item1; + + if (totalTimeSpan == TimeSpan.MinValue) + totalTimeSpan = timeSpan; + else + totalTimeSpan += timeSpan; + } } LogPrint.Log($"distance: {distance}, totalTimeSpan: {totalTimeSpan}", PrintLevel.Normal); diff --git a/Assets/Scripts/Service/YogaManager.cs b/Assets/Scripts/Service/YogaManager.cs index 7f6ef42..d140dd9 100644 --- a/Assets/Scripts/Service/YogaManager.cs +++ b/Assets/Scripts/Service/YogaManager.cs @@ -362,7 +362,7 @@ public class YogaManager : MonoSingleton { if (!p.IsValid(points)) //有一个点不符合 返回false { - LogPrint.Error($"ActionCheckPoints failed, {p} is not valid"); + //LogPrint.Log($"ActionCheckPoints failed, {p} is not valid"); return false; } } diff --git a/Assets/Scripts/UI/Component/MotionUSBCameraCaptureManager.cs b/Assets/Scripts/UI/Component/MotionUSBCameraCaptureManager.cs index bdb8c89..fd0471a 100644 --- a/Assets/Scripts/UI/Component/MotionUSBCameraCaptureManager.cs +++ b/Assets/Scripts/UI/Component/MotionUSBCameraCaptureManager.cs @@ -27,14 +27,8 @@ namespace Yoga var index = PlayerPrefs.GetInt("USBCameraIndex"); if (index >= devices.Count) //数量超出时候改为默认第一个 index = 0; - for (int i = 0; i < devices.Count; i++) - { - UVCManager.CameraInfo device = devices[i]; - picCaptured = device.previewTexture; - if (i == index) //后续可改为IR和RGB条件 - break; - } + picCaptured = devices[index].previewTexture; if (picCaptured == null) throw new Exception("No preview Texture found!");