using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using FObjBase; using FlyADBase; using FLY.Thick.Base.IService; using System.IO; using AutoMapper; using Newtonsoft.Json; using FObjBase.Reflect; namespace FLY.Thick.Base.Server { public class GM_ScanCorr : GM_Base, IScanCorrService { /// <summary> /// 速度 /// </summary> public UInt32 Velocity { get; set; } = 1000; #region IScanCorrService 接口 /// <summary> /// 使能!! /// </summary> public bool Enable { get; set; } /// <summary> /// 数据更新时间 /// </summary> public DateTime[] UpdateTimes { get; private set; } = new DateTime[2]; /// <summary> /// 当前操作的组 /// </summary> public int CurrGroupIndex { get; private set; } /// <summary> /// 0~100 /// </summary> public int Progress { get; private set; } /// <summary> /// 来回次数 /// </summary> public int ScanCnt { get; set; } = 2; public int SmoothFactor { get; set; } = 30; #endregion string file_path; ScanMotion2 scanMotion; InitParam initParam; public ScanCorrGroup[] Groups; public GM_ScanCorr():this("scancorr.json") { } public GM_ScanCorr(string param_path) { GMState = Common.CTRL_STATE.CORR; this.file_path = param_path; Load(); //参数检测 checkParam(); this.PropertyChanged += GM_ScanCorr_PropertyChanged; } private void GM_ScanCorr_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(Enable)) { Save(); } } void checkParam() { if (Groups == null || Groups.Count()!=2 || Groups[0]==null || Groups[1] == null) { Groups = new ScanCorrGroup[2] { new ScanCorrGroup(), new ScanCorrGroup() }; } } public void Init(FlyAD7 flyad, InitParam initParam) { base.Init(flyad); this.initParam = initParam; Misc.BindingOperations.SetBinding(initParam, nameof(initParam.VAccuracy), this, nameof(Velocity)); scanMotion = new ScanMotion2(); scanMotion.Init(flyad); scanMotion.EndEvent += GM_GageInfo_EndEvent; scanMotion.PropertyChanged += GM_GageInfo_PropertyChanged; } bool IsDataOK(ScanCorrGroup group) { if (group.OrgDatas == null || group.OrgDatas.Count()!=2 || group.OrgDatas[0]==null || group.OrgDatas[1]==null) { return false; } if ((group.PosLen != initParam.PosLength) || (group.PosOfGrid != initParam.PosOfGrid)) { return false; } return true; } public void Start(int groupIndex, int scanCnt, int smoothFactor) { if (Groups == null || groupIndex < 0 || groupIndex >= Groups.Count()) { return; } Enable = false;//关闭校正,让flyad7 输出的是原始数据 SmoothFactor = smoothFactor; ScanCnt = scanCnt; CurrGroupIndex = groupIndex; Start(); } public override void Start() { base.Start(); if (!IsRunning) return; Progress = 0; var group = Groups[CurrGroupIndex]; group.PosOfGrid = initParam.PosOfGrid; group.PosLen = initParam.PosLength; group.OrgDatas = null; group.CorrDatas = null; group.Avg = Misc.MyBase.NULL_VALUE; UpdateTimes[CurrGroupIndex] = DateTime.Now; NotifyPropertyChanged(nameof(UpdateTimes)); scanMotion.Start(ScanCnt, Velocity); } public override void Stop() { var group = Groups[CurrGroupIndex]; base.Stop(); if (IsDataOK(Groups[CurrGroupIndex])){ //顺便把CorrDatas也算出来 //默认以10个数据,平均滤波 group.CorrDatas = new int[2][]; group.CorrDatas[0] = Smooth(group.OrgDatas[0], SmoothFactor); group.CorrDatas[1] = Smooth(group.OrgDatas[1], SmoothFactor); int avg0 = Misc.MyMath.Avg(group.CorrDatas[0]); int avg1 = Misc.MyMath.Avg(group.CorrDatas[1]); if (!Misc.MyBase.ISVALIDATA(avg0) || !Misc.MyBase.ISVALIDATA(avg1)) { group.CorrDatas = null; group.Avg = Misc.MyBase.NULL_VALUE; //失败 } else { group.Avg = (avg0 + avg1) / 2; } UpdateTimes[CurrGroupIndex] = DateTime.Now; NotifyPropertyChanged(nameof(UpdateTimes)); Progress = 100; } else { //失败了 group.PosOfGrid = initParam.PosOfGrid; group.PosLen = initParam.PosLength; group.OrgDatas = null; group.CorrDatas = null; group.Avg = Misc.MyBase.NULL_VALUE; UpdateTimes[CurrGroupIndex] = DateTime.Now; NotifyPropertyChanged(nameof(UpdateTimes)); } Save(); } int[] Smooth(int[] orgDatas, int smoothFactor = 20) { var filters = new int[orgDatas.Count()]; for (int i = 0; i < orgDatas.Count(); i++) { int sum = 0; int cnt = 0; for (int j = 0; j < smoothFactor; j++) { int index = i - smoothFactor / 2+j; if (index < 0) continue; else if (index >= orgDatas.Count()) break; if (Misc.MyBase.ISVALIDATA(orgDatas[index])) { sum += orgDatas[index]; cnt++; } } if (cnt > 0) filters[i] = sum / cnt; else filters[i] = Misc.MyBase.NULL_VALUE; } return filters; } protected override void OnPoll() { if (scanMotion.OnPoll()) { Stop(); } } private void GM_GageInfo_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(ScanMotion2.Progress)) { Progress = scanMotion.Progress; } } /// <summary> /// 清空组数据 /// </summary> /// <param name="groupIndex"></param> public void Clear(int groupIndex) { if (groupIndex < 0 || groupIndex >= Groups.Count()) return; Groups[groupIndex].Clear(); UpdateTimes[groupIndex] = DateTime.Now; NotifyPropertyChanged(nameof(UpdateTimes)); Save(); } private void GM_GageInfo_EndEvent(object obj, MiniGridEventArgs e) { DataEnd(e.direction, e.posOfGrid, e.grid_start, e.buf); } void DataEnd(Misc.DIRECTION direction, int posOfGrid, int start_grid, int[] dat) { //posOfGrid 肯定为 initParam.PosOfGrid //start_grid 肯定为 0 var group = Groups[CurrGroupIndex]; if (group.OrgDatas == null) group.OrgDatas = new int[2][]; int orgDatas_index = (direction == Misc.DIRECTION.FORWARD) ? 0 : 1; if (group.OrgDatas[orgDatas_index] == null) { group.OrgDatas[orgDatas_index] = dat.ToArray(); } else { var orgDatas = group.OrgDatas[orgDatas_index]; for (int i = 0; i < orgDatas.Count(); i++) { var org_ad = orgDatas[i]; var ad = dat[i]; if (Misc.MyBase.ISVALIDATA(org_ad) && Misc.MyBase.ISVALIDATA(ad)) { org_ad = (org_ad * scanMotion.CurrCnt + ad) / (scanMotion.CurrCnt + 1); } else { org_ad = ad; } orgDatas[i] = org_ad; } } UpdateTimes[CurrGroupIndex] = DateTime.Now; NotifyPropertyChanged(nameof(UpdateTimes)); } bool Load() { return ScanCorrJsonDb.Load(file_path, this); } bool Save() { return ScanCorrJsonDb.Save(file_path, this); } /// <summary> /// 设置修正曲线 /// </summary> /// <param name="groupIndex">组序号</param> /// <param name="corrDatas">修正数据</param> /// <param name="avg">均值</param> public void SetCorrData(int groupIndex, int[][] corrDatas, int avg) { if (Groups == null || groupIndex < 0 || groupIndex >= Groups.Count()) { return; } var group = Groups[groupIndex]; group.CorrDatas = corrDatas; group.Avg = avg; Save(); } [Call(typeof(GetScanCorrGroupResponse))] public void GetScanCorrGroup(int groupIndex, AsyncCBHandler asyncDelegate, object asyncContext) { if (Groups == null || groupIndex < 0 || groupIndex >= Groups.Count()) { asyncDelegate(asyncContext, new GetScanCorrGroupResponse() { GroupIndex = groupIndex }); return; } var group = Groups[groupIndex]; var reponse = new GetScanCorrGroupResponse() { GroupIndex = groupIndex, IsDataOK = IsDataOK(group), Avg = group.Avg, OrgDatas = group.OrgDatas, CorrDatas = group.CorrDatas, UpdateTime = UpdateTimes[groupIndex] }; asyncDelegate(asyncContext, reponse); } public void CorrectADs(Misc.DIRECTION direction, int start_grid, int[] dat) { if (Enable && initParam.HasScanCorr) { for (int i = 0; i < dat.Length; i++) { int grid = start_grid + i; dat[i] = CorrectAD(direction, grid, dat[i]); } } } public int CorrectAD(Misc.DIRECTION direction, int grid, int ad) { if ((Misc.MyBase.ISVALIDATA(ad) == false) || (Misc.MyBase.ISVALIDATA(grid) == false) || (Enable == false) || (initParam.HasScanCorr == false)) return ad; //没有修正数据 if (Groups[0].CorrDatas == null && Groups[1].CorrDatas == null) return ad; int datasize; if (Groups[0].CorrDatas != null) datasize = Groups[0].CorrDatas[0].Count(); else datasize = Groups[1].CorrDatas[0].Count(); if (grid < 0) grid = 0; else if (grid >= datasize) grid = datasize - 1; int ad0 = Misc.MyBase.NULL_VALUE;//group 0 int ad1 = Misc.MyBase.NULL_VALUE;//group 1 int ad0_avg = Groups[0].Avg;//group 0 int ad1_avg = Groups[1].Avg;//group 1 if (direction == Misc.DIRECTION.FORWARD) { if (Groups[0].CorrDatas != null) ad0 = Groups[0].CorrDatas[0][grid]; if (Groups[1].CorrDatas != null) ad1 = Groups[1].CorrDatas[0][grid]; } else if (direction == Misc.DIRECTION.BACKWARD) { if (Groups[0].CorrDatas != null) ad0 = Groups[0].CorrDatas[1][grid]; if (Groups[1].CorrDatas != null) ad1 = Groups[1].CorrDatas[1][grid]; } else { int ad2 = Misc.MyBase.NULL_VALUE; int ad3 = Misc.MyBase.NULL_VALUE; if (Groups[0].CorrDatas!=null) { ad0 = Groups[0].CorrDatas[0][grid]; ad2 = Groups[0].CorrDatas[1][grid]; } if (Groups[1].CorrDatas != null) { ad1 = Groups[1].CorrDatas[0][grid]; ad3 = Groups[1].CorrDatas[1][grid]; } if (Misc.MyBase.ISVALIDATA(ad0) && Misc.MyBase.ISVALIDATA(ad2)) ad0 = (ad0 + ad2) / 2; else if (Misc.MyBase.ISVALIDATA(ad2)) ad0 = ad2; if (Misc.MyBase.ISVALIDATA(ad1) && Misc.MyBase.ISVALIDATA(ad3)) ad1 = (ad1 + ad3) / 2; else if (Misc.MyBase.ISVALIDATA(ad3)) ad1 = ad3; } //TODO double x, p0, p1; if (Misc.MyBase.ISVALIDATA(ad0) && Misc.MyBase.ISVALIDATA(ad1)) { // ad0_avg 与 ad1_avg 偏差必须 40%以上 double d = (double)Math.Abs(ad0_avg - ad1_avg) / (ad0_avg + ad1_avg); if (d < 0.2) { //异常 x = (double)ad0_avg / ad0; ad = (int)(x * ad); } else { p0 = (double)ad0_avg / ad0; p1 = (double)ad1_avg / ad1; x = (p0 - p1) * (ad - ad1_avg) / (ad0_avg - ad1_avg) + p1; ad = (int)(x * ad); } } else if (Misc.MyBase.ISVALIDATA(ad0)) { x = (double)ad0_avg / ad0; ad = (int)(x * ad); } else if (Misc.MyBase.ISVALIDATA(ad1)) { x = (double)ad1_avg / ad1; ad = (int)(x * ad); } return ad; } } public class ScanCorrGroup { /// <summary> /// 机架总长,脉冲 /// </summary> public int PosLen; /// <summary> /// 1个grid = N个pos /// </summary> public int PosOfGrid; /// <summary> /// 原始 正方向机架AD值数据, grid数据, 0:正方向 ; 1:反方向 /// </summary> public int[][] OrgDatas; /// <summary> /// 修正用数据 0:正方向机架AD值数据 ; 1:反方向 /// </summary> public int[][] CorrDatas; /// <summary> /// CorrDatas 的均值 /// </summary> public int Avg; public ScanCorrGroup() { } public bool IsDataOK() { if (OrgDatas == null || OrgDatas.Count() != 2 || OrgDatas[0] == null || OrgDatas[1] == null) { return false; } return true; } public void Clear() { Avg = Misc.MyBase.NULL_VALUE; CorrDatas = null; OrgDatas = null; } } public class ScanCorrJsonDb { static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c => { c.CreateMap<GM_ScanCorr, ScanCorrJsonDb>().ReverseMap(); })); public static bool Save(string filePath, GM_ScanCorr src) { try { var p = Mapper.Map<ScanCorrJsonDb>(src); File.WriteAllText(filePath, JsonConvert.SerializeObject(p, Formatting.Indented)); return true; } catch { //异常,没有json 编码失败 } return false; } public static bool Load(string filePath, GM_ScanCorr src) { try { if (File.Exists(filePath)) { string json = File.ReadAllText(filePath); var p = JsonConvert.DeserializeObject<ScanCorrJsonDb>(json); Mapper.Map(p, src); } } catch { //异常,没有json 解码失败 } return false; } public bool Enable; public int ScanCnt = 2; public int SmoothFactor = 30; public ScanCorrGroup[] Groups; } }