HeatBuf.cs 21.9 KB
Newer Older
1 2
using AutoMapper;
using FLY.FeedbackRenZiJia.Common;
潘栩锋's avatar
潘栩锋 committed
3
using FLY.FeedbackRenZiJia.IService;
4
using FLY.FeedbackRenZiJia.Server.Model;
5
using FLY.OBJComponents.Server.Model;
潘栩锋's avatar
潘栩锋 committed
6
using FObjBase;
7
using Misc;
8
using Newtonsoft.Json;
9
using PropertyChanged;
10 11 12
using System;
using System.Collections.Generic;
using System.ComponentModel;
13
using System.IO;
14
using System.Linq;
潘栩锋's avatar
潘栩锋 committed
15 16 17 18 19 20 21 22 23

namespace FLY.FeedbackRenZiJia.Server
{
    /// <summary>
    /// 存放一堆厚度与加热数据。
    /// 1.用于判断加热是否稳定了;
    /// 2.加热偏移;
    /// 3.加热/厚度
    /// </summary>
24
    public class HeatBuf : IHeatBufService
潘栩锋's avatar
潘栩锋 committed
25 26 27 28 29
    {

        #region 参数


30
        [DoNotCheckEquality]
潘栩锋's avatar
潘栩锋 committed
31 32 33
        /// <summary>
        /// 加热生效曲线,允许为空,则不生效
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
34
        public int[] HeatEffectCurve { get; set; } = new int[] { 3, 4, 7, 4, 3 };
潘栩锋's avatar
潘栩锋 committed
35

36

潘栩锋's avatar
潘栩锋 committed
37 38 39
        /// <summary>
        /// 厚度稳定范围 %, 偏差在范围内,都是稳定的 
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
40
        public int StableRange { get; set; } = 4;
41 42


43

44 45


潘栩锋's avatar
潘栩锋 committed
46 47 48
        /// <summary>
        /// 对位模式, 加热与厚度相关性阀值, 相关性 >=0.7
        /// </summary>
49
        public double ThresholdR { get; set; } = 0.75;
50 51


潘栩锋's avatar
潘栩锋 committed
52
        /// <summary>
53
        /// 对位模式 加热%差 的极差 >= 20% 才能触发  单位%
潘栩锋's avatar
潘栩锋 committed
54
        /// </summary>
55
        public int ThresholdMaxMin { get; set; } = 40;
56 57


潘栩锋's avatar
潘栩锋 committed
58 59 60 61
        /// <summary>
        /// %
        /// 最大sigma, 只有当前的sigma  在 最大sigma 与 最小 sigma 内,才能控制
        /// </summary>
62
        public int ThresholdSigmaMax { get; set; } = 25;
潘栩锋's avatar
潘栩锋 committed
63 64 65 66 67 68 69 70

        #endregion

        #region 状态

        /// <summary>
        /// 总延时 =Delay+mRenZiJiaService.FilmLength/mRenZiJiaService.Velocity
        /// </summary>
71 72
        public TimeSpan Delay { get; set; } = TimeSpan.FromSeconds(100);

潘栩锋's avatar
潘栩锋 committed
73 74 75


        #region 对位
76

77

潘栩锋's avatar
潘栩锋 committed
78
        /// <summary>
79
        /// 对位查找范围 默认 ±30°, 最大值 90°,最小值 10°
潘栩锋's avatar
潘栩锋 committed
80
        /// </summary>
81
        public int SearchRange { get; set; } = 10;
82

潘栩锋's avatar
潘栩锋 committed
83 84 85
        /// <summary>
        /// 计算的最佳复位区号
        /// </summary>
86
        public int BestOrgBoltNo { get; set; } = -1;
87 88


潘栩锋's avatar
潘栩锋 committed
89 90 91
        /// <summary>
        /// 计算的最佳复位区号 对应的 加热/厚度 
        /// </summary>
92
        public double BestKp { get; set; } = -1;
93 94


潘栩锋's avatar
潘栩锋 committed
95 96 97
        /// <summary>
        /// 计算的最佳复位区号 对应的 加热与厚度相关性
        /// </summary>
98
        public double MaxR { get; set; } = -1;
99 100


潘栩锋's avatar
潘栩锋 committed
101
        /// <summary>
102 103 104 105 106 107 108 109 110 111 112 113
        /// 计算的最佳复位区号 对应的 加热%变化极差 单位%
        /// </summary>
        public int MaxMin { get; set; } = -1;


        /// <summary>
        /// MaxR 对应的 数据幅 Id0
        /// </summary>
        public long MaxR_Id0 { get; private set; } = -1;

        /// <summary>
        /// MaxR 对应的 数据幅 Id1
潘栩锋's avatar
潘栩锋 committed
114
        /// </summary>
115
        public long MaxR_Id1 { get; private set; } = -1;
116

117 118 119
        /// <summary>
        /// MaxR 对应的 时间
        /// </summary>
120
        public DateTime MaxR_Time { get; private set; }
潘栩锋's avatar
潘栩锋 committed
121 122 123 124 125 126
        #endregion

        #region 稳定性
        /// <summary>
        /// 当前检测出来的厚度数据 稳定状态
        /// </summary>
127
        public STABILITY Stability { get; protected set; } = STABILITY.IDLE;
潘栩锋's avatar
潘栩锋 committed
128 129 130 131

        /// <summary>
        /// 当前检测出来的厚度数据 的稳定性 
        /// </summary>
132
        public double CurrR { get; set; } = -1;
133 134


潘栩锋's avatar
潘栩锋 committed
135 136 137
        /// <summary>
        /// 当前检测出来的厚度数据 2Sigma
        /// </summary>
138
        public double Curr2Sigma { get; set; } = -1;
139 140


潘栩锋's avatar
潘栩锋 committed
141 142 143
        /// <summary>
        /// 当前检测出来的厚度数据,时间
        /// </summary>
144
        public DateTime CurrTime { get; set; } = DateTime.MinValue;
145

潘栩锋's avatar
潘栩锋 committed
146 147

        #region 每个分区状态
148 149

        [DoNotCheckEquality]
150
        public bool[] BoltIsStable { get; private set; }
151

潘栩锋's avatar
潘栩锋 committed
152 153 154 155 156 157 158 159 160 161
        #endregion

        #endregion

        #endregion


        /// <summary>
        /// HeatCell 的 Kp
        /// </summary>
162 163
        public double Kp { get; set; } = 3;

164

潘栩锋's avatar
潘栩锋 committed
165 166 167
        /// <summary>
        /// 厚度数量
        /// </summary>
168
        int BoltCnt = 88;
潘栩锋's avatar
潘栩锋 committed
169 170 171 172

        /// <summary>
        /// 加热数量
        /// </summary>
173
        int ChannelCnt = 88;
174

潘栩锋's avatar
潘栩锋 committed
175 176 177 178
        /// <summary>
        /// 缓存区大小
        /// </summary>
        int BufSize = 60;
179

180
        public List<ThickHeat2> mData;
181

潘栩锋's avatar
潘栩锋 committed
182
        /// <summary>
183
        /// 最后一幅数据,单位 channelcnt, 可以有double.NaN
潘栩锋's avatar
潘栩锋 committed
184
        /// </summary>
185
        public double[] ThickPercents=null;
潘栩锋's avatar
潘栩锋 committed
186
        /// <summary>
187 188 189 190
        /// 最后一幅数据的混合次数
        /// </summary>
        public int MixCnt = 1;
        /// <summary>
191
        /// 最后一幅数据的复位区号
潘栩锋's avatar
潘栩锋 committed
192
        /// </summary>
193
        public int OrgBoltNo = 1;
潘栩锋's avatar
潘栩锋 committed
194 195

        /// <summary>
196
        /// 最后一幅加热偏差变化量
潘栩锋's avatar
潘栩锋 committed
197
        /// </summary>
198 199
        public int LastHeatDiffMaxMin = 0;

200
        public bool HasMaxR = false;
潘栩锋's avatar
潘栩锋 committed
201 202 203 204 205 206
        static HeatBuf()
        {

        }
        public HeatBuf()
        {
207
            mData = new List<ThickHeat2>();
208 209 210
            
            if (!Load())
                Save();
潘栩锋's avatar
潘栩锋 committed
211 212 213

            checkParamErr();
        }
潘栩锋's avatar
潘栩锋 committed
214

潘栩锋's avatar
潘栩锋 committed
215 216 217 218
        void checkParamErr()
        {
            if (StableRange < 1 || StableRange > 10)
            {
219
                StableRange = 4;
潘栩锋's avatar
潘栩锋 committed
220 221 222 223
            }

            if (ThresholdR < 0.1 || ThresholdR > 0.9)
            {
224
                ThresholdR = 0.6;
潘栩锋's avatar
潘栩锋 committed
225 226
            }

227
            if (ThresholdMaxMin < 10 || ThresholdMaxMin > 90)
潘栩锋's avatar
潘栩锋 committed
228
            {
229
                ThresholdMaxMin = 40;
潘栩锋's avatar
潘栩锋 committed
230 231
            }
        }
232

233
        public void SetToBestThickPercents()
潘栩锋's avatar
潘栩锋 committed
234
        {
235 236 237
            MoveThickPercents(BestOrgBoltNo);
            //ThickPercents = Common.MyMath.Move(ThickPercents, (BestOrgBoltNo - OrgBoltNo)* ChannelCnt/BoltCnt);
            //OrgBoltNo = BestOrgBoltNo;
238 239 240 241 242 243 244
            Stability = STABILITY.OK_CORREL;
            bool[] isStables = new bool[ChannelCnt];
            for (int i = 0; i < isStables.Count(); i++)
                isStables[i] = true;

            CurrR = MaxR;
            BoltIsStable = isStables;
潘栩锋's avatar
潘栩锋 committed
245
        }
246 247 248 249 250 251 252 253 254 255 256
        public bool MoveThickPercents(int orgBoltNo)
        {
            if (ThickPercents != null && OrgBoltNo!=orgBoltNo)
            {
                ThickPercents = Common.MyMath.Move(ThickPercents, (orgBoltNo - OrgBoltNo) * ChannelCnt / BoltCnt);
                OrgBoltNo = orgBoltNo;
                return true;
            }
            return false;
        }

257
        public void Init(int boltCnt, int channelCnt)
潘栩锋's avatar
潘栩锋 committed
258 259 260
        {
            BoltCnt = boltCnt;
            ChannelCnt = channelCnt;
261

潘栩锋's avatar
潘栩锋 committed
262 263
            mData.Clear();
        }
264

潘栩锋's avatar
潘栩锋 committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286


        public bool IsStable()
        {
            if ((int)Stability > 0)
                return true;
            else
                return false;
        }
        public bool IsUnstable()
        {
            if ((int)Stability < 0)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 1.添加数据到缓冲;
        /// 2.判断是否稳定
        /// 3.根据稳定变化,加热变化,计算偏移
        /// </summary>
287
        public bool Add(Lc_ThickHeat thickHeat)
潘栩锋's avatar
潘栩锋 committed
288
        {
289
            HasMaxR = false;
潘栩锋's avatar
潘栩锋 committed
290 291 292
            //thicks 的数据量一定要是 BoltCnt
            //heats 的数据量一定要是 ChannelCnt
            //不是返回 false
293

294
            if (thickHeat.Thicks.Count() != BoltCnt)//异常
潘栩锋's avatar
潘栩锋 committed
295 296
                return false;

297
            if (thickHeat.Heats.Count() != ChannelCnt)//异常
潘栩锋's avatar
潘栩锋 committed
298 299
                return false;

300 301 302 303
            
            //转为 加热棒数量
            var thks = Common.MyMath.ZoomOut(thickHeat.Thicks, BoltCnt / ChannelCnt);
            var thkpercents = Common.MyMath.GetPercent(thks);
潘栩锋's avatar
潘栩锋 committed
304

305 306 307 308
            //加热%偏差
            var heatPercents = Common.MyMath.OffsetAvgBe0(thickHeat.Heats.Select(da=>(double)da).ToArray());//平移到平均值为0
            var heatEffectCurve = HeatEffectCurve == null ? null : HeatEffectCurve.Select(da => (double)da);
            heatPercents = Common.MyMath.Filter(heatPercents, heatEffectCurve);
潘栩锋's avatar
潘栩锋 committed
309

310
            var thkavg = thickHeat.Thicks.AverageNoNull();
潘栩锋's avatar
潘栩锋 committed
311 312


313

314
            CurrTime = thickHeat.Time;
315 316
            ThickPercents = thkpercents;
            MixCnt = 1;
317
            OrgBoltNo = thickHeat.OrgBoltNo;
318
            Curr2Sigma = thkpercents.Sigma() * 2;
319

潘栩锋's avatar
潘栩锋 committed
320 321


322
            if (!thickHeat.IsStable)
潘栩锋's avatar
潘栩锋 committed
323
            {
324 325 326
                //这幅图还没生效,没有用,不放进mData
                //需要更新状态
                Stability = STABILITY.ERROR_NO_ARRIVE;
潘栩锋's avatar
潘栩锋 committed
327
                CurrR = -1;
328 329
                BoltIsStable = new bool[ChannelCnt];
                return true;
潘栩锋's avatar
潘栩锋 committed
330
            }
331 332

            if (Curr2Sigma > ThresholdSigmaMax)
潘栩锋's avatar
潘栩锋 committed
333
            {
334 335 336 337 338 339
                //这幅图太差,无效,不放进mData
                //需要更新状态
                Stability = STABILITY.ERROR_SIGMA_OVERSIZE;
                CurrR = -1;
                BoltIsStable = new bool[ChannelCnt];
                return true;
潘栩锋's avatar
潘栩锋 committed
340 341
            }

342
            ThickHeat2 d = new ThickHeat2()
343
            {
344
                thickHeat = Lc_ThickHeat_Clone(thickHeat),
345 346 347 348
                ThickAvg = thkavg,//肯定有数据
                ThickPercents = thkpercents,
                HeatPercents = heatPercents
            };
349

350 351
            //更新每个分区的稳定状态
            UpdateStable3(d);
潘栩锋's avatar
潘栩锋 committed
352 353
            return true;
        }
354 355 356 357 358
        Lc_ThickHeat Lc_ThickHeat_Clone(Lc_ThickHeat thickHeat) 
        {
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(thickHeat);
            return Newtonsoft.Json.JsonConvert.DeserializeObject<Lc_ThickHeat>(json);
        }
359

360
        void DataAdd(ThickHeat2 d)
潘栩锋's avatar
潘栩锋 committed
361
        {
362
            if (mData.Count == BufSize)
潘栩锋's avatar
潘栩锋 committed
363
            {
364
                mData.RemoveAt(0);
潘栩锋's avatar
潘栩锋 committed
365
            }
366
            mData.Add(d);
潘栩锋's avatar
潘栩锋 committed
367

368
            return;
潘栩锋's avatar
潘栩锋 committed
369 370 371
        }

        /// <summary>
372 373
        /// 更新稳定状态,需要2幅数据才能比较的;
        /// 返回 true:添加进 mData
潘栩锋's avatar
潘栩锋 committed
374 375
        /// </summary>
        /// <param name="d"></param>
376
        /// <returns></returns>
377
        void UpdateStable3(ThickHeat2 d)
潘栩锋's avatar
潘栩锋 committed
378
        {
379
            if (mData.Count() == 0)//没有以前的数据
潘栩锋's avatar
潘栩锋 committed
380
            {
381
                Stability = STABILITY.IDLE;
382
                goto _error;
潘栩锋's avatar
潘栩锋 committed
383 384
            }

385
            var d_last = mData.Last();
386
            {
387 388 389 390 391 392 393
                double sec_delta = Math.Abs(d.thickHeat.RPeriod.TotalSeconds - d_last.thickHeat.RPeriod.TotalSeconds);
                if (sec_delta / d_last.thickHeat.RPeriod.TotalSeconds > 0.1)
                {
                    //旋转时间不同,无法比较
                    Stability = STABILITY.ERROR_ROTATE_CHANGED;
                    goto _error;
                }
394 395
            }

396 397 398 399 400 401 402 403 404 405 406 407 408 409
            if (d.thickHeat.RAngle != d_last.thickHeat.RAngle)
            {
                //旋转角度不同,无法比较
                Stability = STABILITY.ERROR_PARAM_CHANGED;
                goto _error;
            }

            if (d.thickHeat.FilmLength != d_last.thickHeat.FilmLength)
            {
                //膜距离不用,无法比较
                Stability = STABILITY.ERROR_PARAM_CHANGED;
                goto _error;
            }

潘栩锋's avatar
潘栩锋 committed
410
            if (d.ThickAvg <= 0)
潘栩锋's avatar
潘栩锋 committed
411
            {
潘栩锋's avatar
潘栩锋 committed
412
                //厚度为负数异常
413
                Stability = STABILITY.ERROR_THICK_CHANGED;
414
                goto _error;
潘栩锋's avatar
潘栩锋 committed
415
            }
潘栩锋's avatar
潘栩锋 committed
416 417 418 419 420 421 422 423 424 425
            double thk_diff = Math.Abs((double)(d_last.ThickAvg - d.ThickAvg));
            if (thk_diff > 10)
            {
                if (thk_diff / d.ThickAvg > 0.15) {
                    //厚度变化15%, 不能比较
                    Stability = STABILITY.ERROR_THICK_CHANGED;
                    goto _error;
                }
            }
            //获取 厚度%偏差,与 加热%偏差,大小都为 ChannelCnt
426 427 428 429
            //thickpercents_diff = d.ThickPercents - d_last.ThickPercents
            //heatpercents_diff = d_last.ThickPercents - d.ThickPercents
            GetPercentDatas3(d, d_last,
                out double[] thickpercents_diff, out double[] heatpercents_diff);
潘栩锋's avatar
潘栩锋 committed
430

431 432


潘栩锋's avatar
潘栩锋 committed
433 434
            //通过简单的范围比较计算稳定性
            //当Kp, 错位,就会另 稳定性的值很低
潘栩锋's avatar
潘栩锋 committed
435
            bool[] isStables = CalStable(thickpercents_diff, heatpercents_diff);
436 437
            double currR = 1.0 * isStables.Count(b => b) / isStables.Count();
            BoltIsStable = isStables;
438
            if (heatpercents_diff.All(h => h == 0))
潘栩锋's avatar
潘栩锋 committed
439
            {
440 441 442 443 444 445 446 447 448
                //加热没有变化, 
                CurrR = currR;
                if (CurrR >= ThresholdR)
                {
                    Stability = STABILITY.OK_CORREL;

                    //把 d 合并到 d_last
                    mData.RemoveAt(mData.Count() - 1);
                    d.Mix(d_last);
潘栩锋's avatar
潘栩锋 committed
449

450 451 452 453 454 455 456 457 458
                    //更新图
                    ThickPercents = d.ThickPercents;
                    MixCnt = d.MixCnt;
                    Curr2Sigma = ThickPercents.Sigma() * 2;
                }
                else
                {
                    Stability = STABILITY.ERROR_CORREL;
                }
潘栩锋's avatar
潘栩锋 committed
459
            }
460
            else
潘栩锋's avatar
潘栩锋 committed
461
            {
462 463 464
                double currR2 = Misc.MyMath.Correl(thickpercents_diff, heatpercents_diff);
                if (double.IsNaN(currR2))
                    currR2 = -1;
潘栩锋's avatar
潘栩锋 committed
465

466
                CurrR = Math.Max(currR, currR2);
潘栩锋's avatar
潘栩锋 committed
467

468 469 470 471 472 473 474 475 476 477 478
                if (CurrR >= ThresholdR)
                {
                    Stability = STABILITY.OK_CORREL;
                }
                else
                {
                    Stability = STABILITY.ERROR_CORREL;
                }
            }

            LastHeatDiffMaxMin = (int)Common.MyMath.CalMaxMin(heatpercents_diff);
潘栩锋's avatar
潘栩锋 committed
479 480


481 482 483 484 485 486 487 488 489
            //通过平移 达到最大 加热厚度相关性
            double maxOffsetHeatThickR = -1;
            long maxOffsetHeatThickR_id = -1;
            double maxOffsetHeatThickR_maxMin = -1;
            int maxOffsetHeatThickR_orgBoltNo = -1;
            double maxOffsetHeatThickR_kp = -1;
            DateTime last_h_t = DateTime.MinValue;
            //从尾向前找
            for (int i = 0; i < mData.Count(); i++)
潘栩锋's avatar
潘栩锋 committed
490
            {
491 492
                int index = mData.Count() - 1 - i;
                d_last = mData[index];
潘栩锋's avatar
潘栩锋 committed
493

494 495 496 497
                //超过2个小时的数据删除
                if (d.thickHeat.Time - d_last.thickHeat.Time > TimeSpan.FromMinutes(120))
                {
                    mData.RemoveRange(0, index);
潘栩锋's avatar
潘栩锋 committed
498
                    //因为是从尾到前找, 所以这个超时的,已经是最前一个,可以结束了
499 500
                    break;
                }
潘栩锋's avatar
潘栩锋 committed
501

502 503 504 505 506
                if (last_h_t != DateTime.MinValue)
                {
                    if (d_last.thickHeat.HTime == last_h_t)
                    {
                        //认为加热一样的,厚度也是一样,不比较了
潘栩锋's avatar
潘栩锋 committed
507
                        //加热一样,只用最新的那幅数据
508 509 510 511
                        continue;
                    }
                }
                last_h_t = d_last.thickHeat.HTime;
潘栩锋's avatar
潘栩锋 committed
512

513 514
                GetPercentDatas3(d, d_last,
                    out thickpercents_diff, out heatpercents_diff);
潘栩锋's avatar
潘栩锋 committed
515 516


517 518 519 520 521 522
                //加热极差 判断可信度用
                double maxMin = Common.MyMath.CalMaxMin(heatpercents_diff);
                if (maxMin >= ThresholdMaxMin)
                {
                    //通过平移找最大相关性
                    //计算平移
523
                    Common.MyMath.CalBestMove(heatpercents_diff, thickpercents_diff, SearchRange, out int offset, out double heatThickR);
潘栩锋's avatar
潘栩锋 committed
524 525


526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
                    if (heatThickR > maxOffsetHeatThickR)
                    {
                        maxOffsetHeatThickR = heatThickR;
                        maxOffsetHeatThickR_orgBoltNo = OrgBoltNoOffset(d.thickHeat.OrgBoltNo, offset * BoltCnt / ChannelCnt);
                        maxOffsetHeatThickR_maxMin = maxMin;
                        maxOffsetHeatThickR_id = d_last.thickHeat.ID;

                        var thickpercents_diff2 = Common.MyMath.Move(thickpercents_diff, offset);

                        //当前数据的加热与厚度 比例
                        double b;
                        double a;
                        Misc.MyMath.Linest(heatpercents_diff, thickpercents_diff2, out a, out b);
                        maxOffsetHeatThickR_kp = a;
                    }
                }
潘栩锋's avatar
潘栩锋 committed
542

543
            }
544

545
            if (maxOffsetHeatThickR != -1)
潘栩锋's avatar
潘栩锋 committed
546
            {
547
                if (maxOffsetHeatThickR >= ThresholdR)
潘栩锋's avatar
潘栩锋 committed
548
                {
549 550 551 552 553 554 555
                    BestOrgBoltNo = maxOffsetHeatThickR_orgBoltNo;
                    BestKp = Math.Round(maxOffsetHeatThickR_kp, 1);
                    MaxR = Math.Round(maxOffsetHeatThickR, 2);
                    MaxMin = (int)Math.Round(maxOffsetHeatThickR_maxMin, 0);
                    MaxR_Id0 = maxOffsetHeatThickR_id;
                    MaxR_Id1 = d.thickHeat.ID;
                    MaxR_Time = DateTime.Now;
556
                    HasMaxR = true;
潘栩锋's avatar
潘栩锋 committed
557 558 559
                }
            }

560
            DataAdd(d);
561 562 563 564 565 566 567 568
            return;
            _error:
            CurrR = -1;
            BoltIsStable = new bool[ChannelCnt];
            //删除前面的
            mData.Clear();
            DataAdd(d);

569
        }
潘栩锋's avatar
潘栩锋 committed
570

571 572
        int OrgBoltNoOffset(int orgBoltNo, int offset)
        {
潘栩锋's avatar
潘栩锋 committed
573

574 575 576 577 578 579
            orgBoltNo += offset;
            if (orgBoltNo > BoltCnt)
                orgBoltNo -= BoltCnt;
            else if (orgBoltNo < 1)
                orgBoltNo += BoltCnt;
            return orgBoltNo;
潘栩锋's avatar
潘栩锋 committed
580
        }
581
        void GetPercentDatas3(
582
            ThickHeat2 d, ThickHeat2 d_last,
583
            out double[] thickpercents_diff, out double[] heatpercents_diff)
潘栩锋's avatar
潘栩锋 committed
584
        {
585 586 587 588
            //厚度%偏差
            double[] thickpercents_last;
            //当两幅图复位区号不一致时,移动以前的数据,使之一致
            if (d.thickHeat.OrgBoltNo != d_last.thickHeat.OrgBoltNo)
潘栩锋's avatar
潘栩锋 committed
589
            {
590 591 592
                int z = d.thickHeat.Thicks.Count() / d.ThickPercents.Count();
                int move = (d.thickHeat.OrgBoltNo - d_last.thickHeat.OrgBoltNo) / z;
                thickpercents_last = Common.MyMath.Move(d_last.ThickPercents, move);
潘栩锋's avatar
潘栩锋 committed
593
            }
594 595
            else {
                thickpercents_last = d_last.ThickPercents;
潘栩锋's avatar
潘栩锋 committed
596 597
            }

598
            thickpercents_diff = Common.MyMath.GetDiff(d.ThickPercents, thickpercents_last);
潘栩锋's avatar
潘栩锋 committed
599

600 601 602
            //加热%偏差
            heatpercents_diff = Common.MyMath.GetDiff(d_last.HeatPercents, d.HeatPercents);//-加热增量, 它是反转的!!!!
        }
潘栩锋's avatar
潘栩锋 committed
603 604


潘栩锋's avatar
潘栩锋 committed
605
        bool[] CalStable(double[] thickpercents_diff, double[] heatpercents_diff)
606 607 608 609
        {
            //降低要求
            //thickpercents_diff = Common.MyMath.Filter(thickpercents_diff, 3);
            //heatpercents_diff = Common.MyMath.Filter(heatpercents_diff, 3);
潘栩锋's avatar
潘栩锋 committed
610

611 612 613
            double kp = Kp;
            if (kp < 1)
                kp = 1;
潘栩锋's avatar
潘栩锋 committed
614 615


616
            int stableRange = StableRange;
潘栩锋's avatar
潘栩锋 committed
617

618 619
            if (stableRange < 1)
                stableRange = 1;
潘栩锋's avatar
潘栩锋 committed
620

潘栩锋's avatar
潘栩锋 committed
621
            bool[] isStable = new bool[heatpercents_diff.Count()];
622
            for (int i = 0; i < heatpercents_diff.Count(); i++)
潘栩锋's avatar
潘栩锋 committed
623
            {
624 625
                if ((!double.IsNaN(thickpercents_diff[i])) &&
                    (Math.Abs(thickpercents_diff[i] - heatpercents_diff[i] / kp) <= stableRange))
潘栩锋's avatar
潘栩锋 committed
626
                {
627 628
                    //稳定!!!!!
                    isStable[i] = true;
潘栩锋's avatar
潘栩锋 committed
629 630
                }
            }
潘栩锋's avatar
潘栩锋 committed
631
            return isStable;
潘栩锋's avatar
潘栩锋 committed
632 633 634 635 636 637 638 639
        }



        public void Apply()
        {
            Save();
        }
640 641

        string file_path = "heatbuf.json";
潘栩锋's avatar
潘栩锋 committed
642 643
        bool Load()
        {
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
            if (File.Exists(file_path))
            {
                try
                {
                    string json = File.ReadAllText(file_path);
                    var jsonDb = JsonConvert.DeserializeObject<HeatBufJsonDb>(json);
                    HeatBufJsonDb.Mapper.Map(jsonDb, this);
                    return true;
                }
                catch
                {
                    //异常,没有json 解码失败

                }
                return false;
            }
            return false;
潘栩锋's avatar
潘栩锋 committed
661 662 663
        }
        void Save()
        {
664 665 666 667 668 669 670 671 672 673 674
            try
            {
                var jsonDb = HeatBufJsonDb.Mapper.Map<HeatBufJsonDb>(this);
                string json = JsonConvert.SerializeObject(jsonDb, Formatting.Indented);
                File.WriteAllText(file_path, json);
            }
            catch
            {
                //异常,没有json 编码失败

            }
潘栩锋's avatar
潘栩锋 committed
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
        }

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }
        #endregion

    }
690 691 692 693 694 695 696 697
    public class HeatBufJsonDb {

        public static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c => {
            c.CreateMap<HeatBuf, HeatBufJsonDb>().ReverseMap();
        }));

        #region 参数

698
        /// <summary>
699
        /// 对位查找范围 默认 ±10区
700
        /// </summary>
701
        public int SearchRange = 10;
702 703 704 705

        /// <summary>
        /// 加热生效曲线,允许为空,则不生效
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
706
        public int[] HeatEffectCurve = new int[] { 3, 4, 7, 4, 3 };
707 708 709 710 711


        /// <summary>
        /// 厚度稳定范围 %, 偏差在范围内,都是稳定的 
        /// </summary>
712
        public int StableRange= 4;
713 714 715 716

        /// <summary>
        /// 对位模式, 加热与厚度相关性阀值, 相关性 >=0.7
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
717
        public double ThresholdR = 0.75;
718 719 720 721 722


        /// <summary>
        /// 对位模式 厚度%差 的极差 >= +4%-4%=8%, 单位%
        /// </summary>
潘栩锋's avatar
潘栩锋 committed
723
        public int ThresholdMaxMin = 30;
724 725 726 727 728 729


        /// <summary>
        /// %
        /// 最大sigma, 只有当前的sigma  在 最大sigma 与 最小 sigma 内,才能控制
        /// </summary>
730
        public int ThresholdSigmaMax = 20;
731 732 733 734


        #endregion
    }
潘栩锋's avatar
潘栩锋 committed
735 736 737


}