Browse Source

新增了PSD谱平均计算功能

l2736 3 months ago
parent
commit
39642fbb6a

+ 12 - 0
Shaker.Model/Models/RandomDataModel.cs

@@ -8,9 +8,21 @@ namespace Shaker.Models
 {
     public class RandomDataModel : BaseModel, IResultDataModel
     {
+        public double CurrentIdentifyDisplacement = 0.05;
+        public double CurrentIdentifyRms = 0;
+        public int IdentifyIndex = 0;
+        public List<double[]> CurrentAccelerationPSD = new List<double[]>();
+        public double[] CurrentAccelerationSynthesisPSD = new double[0];
+        public double[] TransferFunction = new double[0];
+        public double[] DriverPSD = new double[0];
+
+        public RandomTestStep RandomTestStep = RandomTestStep.Start;
+        public double CurrentTestLevel = 0;
+        public double CurrentTestTime = 0;
         public override object Clone()
         {
             return this.CloneBase();
         }
+        public MainPageType MainPageType = MainPageType.RandomPage;
     }
 }

+ 16 - 0
Shaker.Model/Models/RandomTestStep.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Shaker.Models
+{
+    public enum RandomTestStep
+    {
+        Start,
+        Identify,
+        Stop,
+        Test,
+    }
+}

+ 0 - 1
Shaker/Service.cs

@@ -39,7 +39,6 @@ namespace ShakerService
         }
 
 
-        private FxpConvert.Common.ICalc Calc { get; } = new SIMDFxpConvert.SIMDCalc();
         /// <summary>
         /// 停止振动台主循环并重新开始等待
         /// </summary>

+ 1 - 0
Shaker/ViewModel/ServiceDataCacheViewModel.cs

@@ -9,6 +9,7 @@ namespace ShakerService.ViewModel
 {
     internal class ServiceDataCacheViewModel:BaseServiceViewModel<IModel>
     {
+        public FxpConvert.Common.ICalc Calc { get; } = new SIMDFxpConvert.SIMDCalc();
         public float[] ReadedDataCache = new float[0];
         public float[,] DataCache = new float[0, 0];
         public float[] SensitivityValues = new float[0];

+ 24 - 0
Shaker/ViewModel/ServiceRandomConfigViewModel.cs

@@ -10,20 +10,28 @@ namespace ShakerService.ViewModel
 {
     internal class ServiceRandomConfigViewModel:BaseServiceViewModel<RandomConfigModel>
     {
+        public double[] PSDWindow { get;private set;}
+        public double[] FixedWindow { get; private set; }
         public double HanningWindowCompensationCoefficient => Model.HanningWindowCompensationCoefficient;
         public uint LinearAverage => Model.LinearAverage;
         public uint ExponentialAverage => Model.ExponentialAverage;
+        public uint DOF { get; private set; }
+        public double FrequencyResolution { get; private set; }
         public uint RandomSampleRate => Model.RandomSampleRate;
         public int MaxFrequency => (int)Model.MaxFrequency;
         public AccelerationSynthesisType SynthesisType => Model.SynthesisType;
         public double MinFrequency => Model.MinFrequency;
         public uint SpectrumLines => (uint)Model.SpectrumLines;
+        public double[] StartWindow { get;private set; }
+        public double[] StopWindow { get; private set; }
         public double Sigma =>Model.Sigma;
         public ServiceRandomIdentifyViewModel Identify { get; } = new ServiceRandomIdentifyViewModel();
         public List<ServiceRandomSpectrumItemViewModel> SpectrumItems { get; } = new List<ServiceRandomSpectrumItemViewModel>();
         public List<ServiceRandomPlanItemViewModel> PlanItems { get; } = new List<ServiceRandomPlanItemViewModel>();
         public uint StopLins =>Model.StopLins;
         public uint WarnLines =>Model.WarnLines;
+        public int FFTFrameLength { get; private set; }
+        public int FFTHalfFrameLength { get; private set; }
         public double StopRMS =>Model.StopRMS;
         private ServiceRandomConfigViewModel()
         {
@@ -74,7 +82,23 @@ namespace ShakerService.ViewModel
             {
                 PlanItems.Add(new ServiceRandomPlanItemViewModel(item));
             }
+            DOF = (model.LinearAverage << 1) * ((model.ExponentialAverage << 1) - 1);
+            FrequencyResolution = MaxFrequency / (double)SpectrumLines;
+            FFTFrameLength = (int)((double)RandomSampleRate / MaxFrequency * SpectrumLines);
+            FFTHalfFrameLength = FFTFrameLength >> 1;
+            PSDWindow = Enumerable.Range(0, FFTHalfFrameLength).Select(x => (x * FrequencyResolution >= MinFrequency || x * FrequencyResolution <= MaxFrequency) ? 1d : 0d).ToArray();
+            FixedWindow = Enumerable.Repeat(1d, FFTFrameLength).ToArray();
+            StartWindow = new double[RandomSampleRate];
+            StopWindow = new double[RandomSampleRate];
+            for(int i=0;i<RandomSampleRate;i++)
+            {
+                double d = i * double.Pi / (RandomSampleRate << 1);
+                StartWindow[i] = Math.Pow(Math.Sin(d),3);
+                StopWindow[i] = Math.Pow(Math.Cos(d), 3);
+            }
         }
+
+        public ServiceRandomDataViewModel RandomData { get; } = new ServiceRandomDataViewModel();
         public static ServiceRandomConfigViewModel Instance { get; } = new ServiceRandomConfigViewModel();
     }
 }

+ 104 - 0
Shaker/ViewModel/ServiceRandomDataViewModel.cs

@@ -0,0 +1,104 @@
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService.ViewModel
+{
+    internal class PSDCache
+    {
+        private List<double[]> LinearAverageCache = new List<double[]>();
+        public List<double[]> ExponentialAverageCache= new List<double[]>();
+        public void Clear()
+        {
+            LinearAverageCache.Clear();
+            ExponentialAverageCache.Clear();
+        }
+        public double[] CalcPSD(double[] data)
+        {
+            if(data ==null || data.Length ==0)return new double[0];
+            if (ServiceRandomConfigViewModel.Instance.LinearAverage > 1)
+            {
+                if (LinearAverageCache.Count == ServiceRandomConfigViewModel.Instance.LinearAverage)
+                {
+                    for(int i=0;i<LinearAverageCache.Count-1;i++)
+                    {
+                        if (i == 0)
+                        {
+                            ServiceDataCacheViewModel.Instance.Calc.Add.Add(ref LinearAverageCache[i][0], ref LinearAverageCache[i + 1][0], (uint)data.Length, ref data[0]);
+                        }
+                        else
+                        {
+                            ServiceDataCacheViewModel.Instance.Calc.Add.Add(ref data[0], ref LinearAverageCache[i + 1][0], (uint)data.Length);
+                        }
+                    }
+                    ServiceDataCacheViewModel.Instance.Calc.Division.Division(ref data[0], LinearAverageCache.Count, (uint)data.Length);
+                    LinearAverageCache.Clear();
+                    
+                }
+                else
+                {
+                    LinearAverageCache.Add(data);
+                }
+            }
+            if (ServiceRandomConfigViewModel.Instance.ExponentialAverage > 1)
+            {
+                ExponentialAverageCache.Add(data);
+                if (ExponentialAverageCache.Count > ServiceRandomConfigViewModel.Instance.ExponentialAverage)
+                {
+                    ExponentialAverageCache.RemoveRange(0, (int)ServiceRandomConfigViewModel.Instance.ExponentialAverage - ExponentialAverageCache.Count);
+                }
+                if (ExponentialAverageCache.Count == 0 || ExponentialAverageCache.Count == 1) return data;
+                for(int i=0;i< ExponentialAverageCache.Count-2;i++)
+                {
+                    if(i==0)
+                    {
+                        ServiceDataCacheViewModel.Instance.Calc.Add.Add(ref ExponentialAverageCache[i][0], ref ExponentialAverageCache[i + 1][0], (uint)data.Length, ref ExponentialAverageCache[^1][0]);
+                    }
+                    else
+                    {
+                        ServiceDataCacheViewModel.Instance.Calc.Add.Add(ref ExponentialAverageCache[^1][0], ref ExponentialAverageCache[i + 1][0], (uint)data.Length);
+                    }
+                }
+                ServiceDataCacheViewModel.Instance.Calc.Division.Division(ref ExponentialAverageCache[^1][0], ExponentialAverageCache.Count, (uint)data.Length);
+                return ExponentialAverageCache[^1];
+            }
+            else return data;
+        }
+    }
+    internal class ServiceRandomDataViewModel : BaseServiceViewModel<RandomDataModel>,IData
+    {
+        private List<PSDCache> AccelerationPSDCache { get; }= new List<PSDCache>();
+        private PSDCache DriverCache { get; }= new PSDCache();
+        public double CurrentIdentifyDisplacement { get => Model.CurrentIdentifyDisplacement; set => Model.CurrentIdentifyDisplacement = value; }
+        public double CurrentIdentifyRms { get => Model.CurrentIdentifyRms; set => Model.CurrentIdentifyRms = value; }
+        public int IdentifyIndex { get => Model.IdentifyIndex; set => Model.IdentifyIndex = value; }
+        public List<double[]> CurrentAccelerationPSD { get => Model.CurrentAccelerationPSD; set => Model.CurrentAccelerationPSD = value; }
+        public RandomTestStep RandomTestStep{ get => Model.RandomTestStep; set => Model.RandomTestStep = value; }
+        public double[] CurrentAccelerationSynthesisPSD { get => Model.CurrentAccelerationSynthesisPSD; set => Model.CurrentAccelerationSynthesisPSD = value; }
+        public double[] TransferFunction { get => Model.TransferFunction; set => Model.TransferFunction = value; }
+        public double[] DriverPSD { get => Model.DriverPSD; set => Model.DriverPSD = value; }
+        public double CurrentTestLevel { get => Model.CurrentTestLevel; set => Model.CurrentTestLevel = value; }
+        public double CurrentTestTime { get => Model.CurrentTestTime; set => Model.CurrentTestTime = value; }
+        public MainPageType MainPageType => Model.MainPageType;
+        public void InitCache()
+        {
+            AccelerationPSDCache.Clear();
+            AccelerationPSDCache.AddRange(Enumerable.Range(0, ServiceShakerConfigViewModel.Instance.AccelerationSensorCount).Select(x => new PSDCache()));
+            DriverCache.Clear();
+        }
+        public void ClearCache()
+        {
+            AccelerationPSDCache.ForEach(x => x.Clear());
+            DriverCache.Clear();
+        }
+        public void ReadFpgaData()
+        {
+
+        }
+    }
+}