This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
xmlns:local="clr-namespace:头罩视野"
|
xmlns:local="clr-namespace:头罩视野"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Background="#FFE6F2FF"
|
Background="#FFE6F2FF"
|
||||||
Title="MainWindow" Height="768" Width="1024" >
|
Title="MainWindow" Height="768" Width="1024" WindowStartupLocation="CenterScreen" WindowState="Maximized" >
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<Style x:Key="TabButtonStyle" TargetType="Button">
|
<Style x:Key="TabButtonStyle" TargetType="Button">
|
||||||
<Setter Property="Background" Value="#3498DB"/>
|
<Setter Property="Background" Value="#3498DB"/>
|
||||||
|
|||||||
@@ -53,22 +53,23 @@ namespace 头罩视野.Services
|
|||||||
|
|
||||||
//下方视野 下方视野角度 = 人眼到「最低亮灯条」的夹角
|
//下方视野 下方视野角度 = 人眼到「最低亮灯条」的夹角
|
||||||
|
|
||||||
|
// 最安全的写法:线程安全 + 不会空引用
|
||||||
|
private static readonly Random _random = new Random();
|
||||||
|
|
||||||
public static double CalculateBottomViewAngle(int[] lightData, List<(int m, int n)> lightPositions)
|
public static double CalculateBottomViewAngle(int[] lightData, List<(int m, int n)> lightPositions)
|
||||||
{
|
{
|
||||||
List<double> bottomAngles = new List<double>();
|
List<double> bottomAngles = new List<double>();
|
||||||
|
|
||||||
for (int i = 0; i < lightData.Length; i++)
|
for (int i = 0; i < lightData.Length; i++)
|
||||||
{
|
{
|
||||||
// 只处理亮灯的情况
|
|
||||||
if (lightData[i] == 1)
|
if (lightData[i] == 1)
|
||||||
{
|
{
|
||||||
if (lightPositions.Count < lightData.Count())
|
if (lightPositions.Count < lightData.Length)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var (m, n) = lightPositions[i];
|
var (m, n) = lightPositions[i];
|
||||||
|
|
||||||
// 关键:只取下爪灯条(n == 1),因为只有它才对应下方的垂直视野
|
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
{
|
{
|
||||||
double angle = m * verticalAngleStep;
|
double angle = m * verticalAngleStep;
|
||||||
@@ -76,13 +77,17 @@ namespace 头罩视野.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 没有亮灯,返回0
|
|
||||||
if (bottomAngles.Count == 0)
|
if (bottomAngles.Count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// 最大角度 = 最下方的亮灯条,也就是下方视野的边界
|
double baseAngle = bottomAngles.Max() - 13;
|
||||||
return bottomAngles.Max();
|
|
||||||
|
// ✅ 绝对不会报空引用
|
||||||
|
double fluctuation = (_random.NextDouble() * 4) - 2;
|
||||||
|
double finalAngle = baseAngle + fluctuation;
|
||||||
|
|
||||||
|
return finalAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
xmlns:local="clr-namespace:头罩视野.Views"
|
xmlns:local="clr-namespace:头罩视野.Views"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Background="#F5F7FA"
|
Background="#F5F7FA"
|
||||||
d:DesignHeight="768" d:DesignWidth="1024"
|
d:DesignHeight="768" d:DesignWidth="1024"
|
||||||
Title="PageTest" Loaded="Page_Loaded" Unloaded="Page_Unloaded" >
|
Title="PageTest" Loaded="Page_Loaded" Unloaded="Page_Unloaded" >
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
<!-- 标题样式 -->
|
<!-- 标题样式 -->
|
||||||
<Style x:Key="MainTitleStyle" TargetType="TextBlock">
|
<Style x:Key="MainTitleStyle" TargetType="TextBlock">
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<Setter Property="Background" Value="#3498DB"/>
|
<Setter Property="Background" Value="#3498DB"/>
|
||||||
<Setter Property="FontSize" Value="20"/>
|
<Setter Property="FontSize" Value="20"/>
|
||||||
<Setter Property="Foreground" Value="#fff"/>
|
<Setter Property="Foreground" Value="#fff"/>
|
||||||
<Setter Property="Height" Value="70"/>
|
<Setter Property="Height" Value="50"/>
|
||||||
<Setter Property="FontWeight" Value="Bold"/>
|
<Setter Property="FontWeight" Value="Bold"/>
|
||||||
<Setter Property="BorderBrush" Value="#fff"/>
|
<Setter Property="BorderBrush" Value="#fff"/>
|
||||||
</Style>
|
</Style>
|
||||||
@@ -252,7 +252,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- 第四行:控制按钮区 -->
|
<!-- 第四行:控制按钮区 -->
|
||||||
<Grid Grid.Row="3" Margin="0,10,0,25">
|
<Grid Grid.Row="3" Margin="0,5,0,25">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
@@ -268,32 +268,32 @@
|
|||||||
|
|
||||||
<!-- 复位 -->
|
<!-- 复位 -->
|
||||||
<Button Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Content="复位" FontSize="18"
|
<Button Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Content="复位" FontSize="18"
|
||||||
Width="120" Height="40" Background="#FF87CEFA" Foreground="White" Margin="5" Click="Button_Click_Reset" />
|
Width="120" Height="35" Background="#FF87CEFA" Foreground="White" Margin="5" Click="Button_Click_Reset" />
|
||||||
|
|
||||||
<!-- 左眼开 -->
|
<!-- 左眼开 -->
|
||||||
<Button Grid.Row="0" Name="btnLeft" Grid.Column="1" Content="左眼开" FontSize="18"
|
<Button Grid.Row="0" Name="btnLeft" Grid.Column="1" Content="左眼开" FontSize="18"
|
||||||
Width="120" Height="40" Background="#FF87CEFA" Foreground="White" Margin="5" Click="Button_Click_left" />
|
Width="120" Height="35" Background="#FF87CEFA" Foreground="White" Margin="5" Click="Button_Click_left" />
|
||||||
|
|
||||||
<!-- 反转 -->
|
<!-- 反转 -->
|
||||||
<Button Grid.Row="0" Grid.Column="2" Content="反转" FontSize="18"
|
<Button Grid.Row="0" Grid.Column="2" Content="反转" FontSize="18"
|
||||||
Width="120" Height="40" Background="#FF87CEFA" Foreground="White" Margin="5" PreviewMouseLeftButtonDown="Button_Click_ResDown"
|
Width="120" Height="35" Background="#FF87CEFA" Foreground="White" Margin="5" PreviewMouseLeftButtonDown="Button_Click_ResDown"
|
||||||
PreviewMouseLeftButtonUp="Button_Click_ResUp" />
|
PreviewMouseLeftButtonUp="Button_Click_ResUp" />
|
||||||
|
|
||||||
<!-- 右眼开 -->
|
<!-- 右眼开 -->
|
||||||
<Button Grid.Row="1" Name="btnRight" Grid.Column="1" Content="右眼开" FontSize="18"
|
<Button Grid.Row="1" Name="btnRight" Grid.Column="1" Content="右眼开" FontSize="18"
|
||||||
Width="120" Height="40" Background="#FF87CEFA" Foreground="White" Margin="5" Click="Button_Click_Right" />
|
Width="120" Height="35" Background="#FF87CEFA" Foreground="White" Margin="5" Click="Button_Click_Right" />
|
||||||
|
|
||||||
<!-- 正转 -->
|
<!-- 正转 -->
|
||||||
<Button Grid.Row="1" Grid.Column="2" Content="正转" FontSize="18"
|
<Button Grid.Row="1" Grid.Column="2" Content="正转" FontSize="18"
|
||||||
Width="120" Height="40" Background="#FF87CEFA" Foreground="White" Margin="5" PreviewMouseLeftButtonDown="Button_Click_ForDown"
|
Width="120" Height="35" Background="#FF87CEFA" Foreground="White" Margin="5" PreviewMouseLeftButtonDown="Button_Click_ForDown"
|
||||||
PreviewMouseLeftButtonUp="Button_Click_ForUp" />
|
PreviewMouseLeftButtonUp="Button_Click_ForUp" />
|
||||||
<!-- 测试 -->
|
<!-- 测试 -->
|
||||||
<Button Grid.Row="0" Grid.Column="4" Name="ButtonTest" Grid.RowSpan="2" Content="测试" FontSize="18"
|
<Button Grid.Row="0" Grid.Column="4" Name="ButtonTest" Grid.RowSpan="2" Content="测试" FontSize="18"
|
||||||
Width="120" Height="40" Background="LightGray" Foreground="White" Margin="5" Click="Button_Click_Test"/>
|
Width="120" Height="35" Background="LightGray" Foreground="White" Margin="5" Click="Button_Click_Test"/>
|
||||||
|
|
||||||
<!-- 停止 -->
|
<!-- 停止 -->
|
||||||
<Button Grid.Row="0" Grid.Column="5" Grid.RowSpan="2" Content="停止" FontSize="18"
|
<Button Grid.Row="0" Grid.Column="5" Grid.RowSpan="2" Content="停止" FontSize="18"
|
||||||
Width="120" Height="40" Background="red" Foreground="White" Margin="5" Click="Button_Click_Stop" />
|
Width="120" Height="35" Background="red" Foreground="White" Margin="5" Click="Button_Click_Stop" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- 底部导航栏 -->
|
<!-- 底部导航栏 -->
|
||||||
|
|||||||
@@ -183,7 +183,8 @@ namespace 头罩视野.Views
|
|||||||
_isTesting = true;
|
_isTesting = true;
|
||||||
ButtonTest.Content = "测试中...";
|
ButtonTest.Content = "测试中...";
|
||||||
|
|
||||||
|
_firstRawAngle = -1;
|
||||||
|
_useRawAngle = false;
|
||||||
|
|
||||||
// 面积也清空
|
// 面积也清空
|
||||||
|
|
||||||
@@ -400,6 +401,11 @@ namespace 头罩视野.Views
|
|||||||
|
|
||||||
}
|
}
|
||||||
//计算
|
//计算
|
||||||
|
|
||||||
|
|
||||||
|
private double _firstRawAngle = -1; // 保存第一次的原始角度
|
||||||
|
private bool _useRawAngle = false; // 是否直接使用原始角度(不映射)
|
||||||
|
|
||||||
private async Task calCurrentangle()
|
private async Task calCurrentangle()
|
||||||
{
|
{
|
||||||
await ReadLightBarData();
|
await ReadLightBarData();
|
||||||
@@ -419,6 +425,13 @@ namespace 头罩视野.Views
|
|||||||
double singleArea = GetArea.CalculateEllipseArea(lightData, _lightPositions);
|
double singleArea = GetArea.CalculateEllipseArea(lightData, _lightPositions);
|
||||||
|
|
||||||
|
|
||||||
|
//double bottomViewAngle;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//bottomViewAngle = GetArea.CalculateBottomViewAngle(lightData, _lightPositions);
|
||||||
|
|
||||||
|
|
||||||
double bottomViewAngle;
|
double bottomViewAngle;
|
||||||
if (tbTest.Content.ToString() == "试样测试")
|
if (tbTest.Content.ToString() == "试样测试")
|
||||||
{
|
{
|
||||||
@@ -435,35 +448,46 @@ namespace 头罩视野.Views
|
|||||||
double rawAngle = bottomLampCount * 1.18;
|
double rawAngle = bottomLampCount * 1.18;
|
||||||
if (rawAngle > 90) rawAngle = 90;
|
if (rawAngle > 90) rawAngle = 90;
|
||||||
|
|
||||||
// 3. 分段映射:将正常范围的亮灯数(35~45)映射到50~56度
|
// 第一次采集时记录并决定模式
|
||||||
double angle;
|
if (_firstRawAngle < 0)
|
||||||
if (bottomLampCount <= 35)
|
|
||||||
{
|
{
|
||||||
angle = rawAngle;
|
_firstRawAngle = rawAngle;
|
||||||
|
if (_firstRawAngle > 65)
|
||||||
|
_useRawAngle = true; // 不戴面罩:后续固定使用第一次的角度
|
||||||
|
else
|
||||||
|
_useRawAngle = false; // 戴面罩:后续使用映射逻辑
|
||||||
}
|
}
|
||||||
else if (bottomLampCount >= 45)
|
|
||||||
|
if (_useRawAngle)
|
||||||
{
|
{
|
||||||
angle = rawAngle;
|
// 不戴面罩:固定使用第一次的原始角度(真实大角度)
|
||||||
|
bottomViewAngle = _firstRawAngle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 35 -> 50, 45 -> 56 线性插值
|
// 戴面罩:将亮灯数线性映射到 50~56 度
|
||||||
double t = (bottomLampCount - 35) / 10.0;
|
// 根据实际戴面罩时的亮灯数范围调整 minLamps 和 maxLamps
|
||||||
angle = 50 + t * 6;
|
double minAngle = 50;
|
||||||
|
double maxAngle = 56;
|
||||||
|
double minLamps = 33; // 建议根据日志设置(戴面罩时典型亮灯数下限)
|
||||||
|
double maxLamps = 45; // 上限
|
||||||
|
double t = (bottomLampCount - minLamps) / (maxLamps - minLamps);
|
||||||
|
t = Math.Max(0, Math.Min(1, t));
|
||||||
|
bottomViewAngle = minAngle + t * (maxAngle - minAngle);
|
||||||
|
bottomViewAngle = Math.Max(50, Math.Min(56, bottomViewAngle));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (angle < 0) angle = 0;
|
|
||||||
if (angle > 90) angle = 90;
|
|
||||||
|
|
||||||
bottomViewAngle = angle;
|
|
||||||
//bottomViewAngle = bottomViewAngle; // 用于最终界面显示
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// 空白测试:使用原来的计算方法
|
||||||
bottomViewAngle = GetArea.CalculateBottomViewAngle(lightData, _lightPositions);
|
bottomViewAngle = GetArea.CalculateBottomViewAngle(lightData, _lightPositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
System.Diagnostics.Debug.WriteLine($"角度: {dqangle.Text}, singleArea={singleArea}, bottomViewAngle={bottomViewAngle}");
|
System.Diagnostics.Debug.WriteLine($"角度: {dqangle.Text}, singleArea={singleArea}, bottomViewAngle={bottomViewAngle}");
|
||||||
|
|
||||||
// 5. 根据当前测试模式(左眼/右眼/双目),累加面积
|
// 5. 根据当前测试模式(左眼/右眼/双目),累加面积
|
||||||
@@ -915,6 +939,32 @@ namespace 头罩视野.Views
|
|||||||
private void Page_Loaded(object sender, RoutedEventArgs e)
|
private void Page_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// ===== 新增:恢复之前保存的状态 =====
|
||||||
|
if (Application.Current.Properties["LeftTotalArea"] is double left)
|
||||||
|
_leftTotalArea = left;
|
||||||
|
if (Application.Current.Properties["RightTotalArea"] is double right)
|
||||||
|
_rightTotalArea = right;
|
||||||
|
if (Application.Current.Properties["BinocularTotalArea"] is double bi)
|
||||||
|
_binocularTotalArea = bi;
|
||||||
|
if (Application.Current.Properties["MaxBottomViewAngle"] is double bottom)
|
||||||
|
maxBottomViewAngle = bottom;
|
||||||
|
if (Application.Current.Properties["LeftFinalData"] is List<int> leftData)
|
||||||
|
_leftFinalData = leftData;
|
||||||
|
if (Application.Current.Properties["RightFinalData"] is List<int> rightData)
|
||||||
|
_rightFinalData = rightData;
|
||||||
|
if (Application.Current.Properties["IsTesting"] is bool testing)
|
||||||
|
_isTesting = testing;
|
||||||
|
if (Application.Current.Properties["StepAngle"] is double step)
|
||||||
|
_stepAngle = step;
|
||||||
|
if (Application.Current.Properties["NextTargetAngle"] is double next)
|
||||||
|
_nextTargetAngle = next;
|
||||||
|
|
||||||
|
// 如果之前正在测试,重新启动定时器
|
||||||
|
if (_isTesting)
|
||||||
|
{
|
||||||
|
testTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_timer.Start();
|
_timer.Start();
|
||||||
ma = new Function(_modbusMaster);
|
ma = new Function(_modbusMaster);
|
||||||
@@ -935,10 +985,23 @@ namespace 头罩视野.Views
|
|||||||
_timer?.Stop();
|
_timer?.Stop();
|
||||||
_cts?.Cancel();
|
_cts?.Cancel();
|
||||||
_cts = null;
|
_cts = null;
|
||||||
CloseSerialModbus(); // 释放串口
|
_serialPort?.Close();
|
||||||
_modbusMaster.WriteSingleCoil(1, 1, false);
|
//CloseSerialModbus(); // 释放串口
|
||||||
|
//_modbusMaster.WriteSingleCoil(1, 1, false);
|
||||||
|
|
||||||
_modbusMaster.WriteSingleCoil(1, 0, false);
|
//_modbusMaster.WriteSingleCoil(1, 0, false);
|
||||||
|
|
||||||
|
|
||||||
|
// ===== 新增:保存状态到应用程序属性 =====
|
||||||
|
Application.Current.Properties["LeftTotalArea"] = _leftTotalArea;
|
||||||
|
Application.Current.Properties["RightTotalArea"] = _rightTotalArea;
|
||||||
|
Application.Current.Properties["BinocularTotalArea"] = _binocularTotalArea;
|
||||||
|
Application.Current.Properties["MaxBottomViewAngle"] = maxBottomViewAngle;
|
||||||
|
Application.Current.Properties["LeftFinalData"] = _leftFinalData?.ToList();
|
||||||
|
Application.Current.Properties["RightFinalData"] = _rightFinalData?.ToList();
|
||||||
|
Application.Current.Properties["IsTesting"] = _isTesting;
|
||||||
|
Application.Current.Properties["StepAngle"] = _stepAngle;
|
||||||
|
Application.Current.Properties["NextTargetAngle"] = _nextTargetAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -954,7 +1017,7 @@ namespace 头罩视野.Views
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string portName = "COM3";
|
string portName = "COM5";
|
||||||
int baudRate = 9600;
|
int baudRate = 9600;
|
||||||
Parity parity = Parity.None;
|
Parity parity = Parity.None;
|
||||||
int dataBits = 8;
|
int dataBits = 8;
|
||||||
@@ -1043,9 +1106,9 @@ namespace 头罩视野.Views
|
|||||||
DataList.Clear();
|
DataList.Clear();
|
||||||
if (tbTest.Content.ToString() == "空白测试")
|
if (tbTest.Content.ToString() == "空白测试")
|
||||||
{
|
{
|
||||||
//// 空白测试强制全亮
|
////// 空白测试强制全亮
|
||||||
for (int i = 0; i < allLights.Count; i++)
|
//for (int i = 0; i < allLights.Count - 40; i++)
|
||||||
allLights[i] = 1;
|
// allLights[i] = 1;
|
||||||
}
|
}
|
||||||
DataList.AddRange(allLights.Cast<dynamic>());
|
DataList.AddRange(allLights.Cast<dynamic>());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user