1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using FLY.Thick.Base.Common;
using FLY.Thick.Base.Server;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FLY.Simulation.Battery.RayLaser
{
public class GageAd_Ray : ISimulationGageAD
{
CurveCollection curve;
/// 编码器2 mm/p 胶轮周长200mm,编码器 转1圈800脉冲 正确应该0.25
/// </summary>
const double Mmpp2 = 0.24925;
/// <summary>
/// 编码器1 mm/p
/// </summary>
public double Mmpp { get; set; } = 0.2;
public double VSignOffset { get; set; }
public double SensorWidth { get; set; } = 25;
/// <summary>
/// 长度为 SensorWidth 的卷积核
/// </summary>
public List<double> Conv { get; private set; }
public int TotalLength { get; private set; }
GageAd gageAd;
public GageAd_Ray()
{
}
public void Init(GageAd gageAd) {
this.gageAd = gageAd;
curve = gageAd.curve_ray;
VSignOffset = gageAd.VSignOffsetRay;
TotalLength = gageAd.TotalLength;
updateConv();
}
void updateConv() {
List<double> conv = new List<double>();
//用圆形代替
double sensorRadius = SensorWidth / 2.0;
for (int i = 0; i < SensorWidth; i++) {
double r = Math.Abs(-sensorRadius + i);
double h = Math.Sqrt(Math.Pow(sensorRadius, 2) - Math.Pow(r, 2));
conv.Add(h * 2);
}
double sum = conv.Sum();
conv = conv.Select(v => v / sum).ToList();
Conv = conv;
}
int GetAdMm(int mm, int mm_v_offset) {
int posLength = (int)(gageAd.FilmPosition*1000 - VSignOffset+ mm_v_offset);
double value = gageAd.GetValue(true, mm, posLength, out GageAd.PosType posType);
if (posType == GageAd.PosType.Hold)
{
return 0;
}
int ad = curve.Value2Ad(value, AD2ValueFlag.NoRevised);
if (ad > 65535)
ad = 65535;
else if (ad < 0)
ad = 0;
return ad;
}
Random random = new Random();
public int GetAD(int mm)
{
//需要对探头直径范围的数据求均值
double hValue = 0;
for (int i = 0; i < Conv.Count(); i++)
{
int mm2 = (int)(mm - Conv.Count()/2.0 + i);
hValue += GetAdMm(mm2, 0) * Conv[i];
}
double vValue = 0;
for (int i = 0; i < Conv.Count(); i++)
{
int mm_v_offset = (int)(-Conv.Count() / 2.0 + i);
vValue += GetAdMm(mm, mm_v_offset) * Conv[i];
}
int ad = (int)((hValue + vValue) / 2);
return ad;
}
public void OnPoll(DateTime now)
{
//不实现
gageAd.OnPoll(now);
}
public UInt16 GetInput()
{
UInt16 istatus = 0x0fff;
if (gageAd.IsVSignLight)
Misc.MyBase.CLEARBIT(ref istatus, IODefinition.IN_VSENSOR);
if(gageAd.IsSyncLight)
Misc.MyBase.CLEARBIT(ref istatus, IODefinition.IN_SYNC);
return istatus;
}
public void SetOutput(UInt16 output) {
if (!Misc.MyBase.CHECKBIT(output, IODefinition.OUT_SYNC))
gageAd.IsSyncLight = true;
else
gageAd.IsSyncLight = false;
}
public int GetPosition2()
{
return (int)(gageAd.FilmPosition * 1000 / Mmpp2);
}
public int GetSpeed2()
{
return (int)(gageAd.FilmVelocity * 1000 / 60 / Mmpp2);
}
}
}