Browse Source

新增锁附点位相机自动矫正功能

新增AutoCorrectLockPoint弹窗及ViewModel,实现锁附点位通过相机自动批量校正。PlcPointParams界面增加“通过相机自动矫正锁附点位”按钮,支持一键校准所有锁附点XY坐标,提升校准自动化与准确性。完善异常处理与用户提示。
孝锋 徐 8 months ago
parent
commit
e5e0b7bb39

+ 8 - 0
TeamAAS-VM/TeamAAS-VP.csproj

@@ -784,6 +784,7 @@
     <Compile Include="ValueConverter\RobotIdToVisibiltyConverter.cs" />
     <Compile Include="ValueConverter\RoiToTextConverter.cs" />
     <Compile Include="ValueConverter\StringFormatConverter.cs" />
+    <Compile Include="ViewModels\Product\AutoCorrectLockPointViewModel.cs" />
     <Compile Include="ViewModels\DebugMod\LightManualViewModel.cs" />
     <Compile Include="ViewModels\Calibration\FixedUpCameraFindP0ViewModel.cs" />
     <Compile Include="ViewModels\Product\LightChannelListViewModel.cs" />
@@ -927,6 +928,9 @@
     <Compile Include="Views\Product\AfagFeederParams.xaml.cs">
       <DependentUpon>AfagFeederParams.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Views\Product\AutoCorrectLockPoint.xaml.cs">
+      <DependentUpon>AutoCorrectLockPoint.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Views\Product\CalculateOffsetU.xaml.cs">
       <DependentUpon>CalculateOffsetU.xaml</DependentUpon>
     </Compile>
@@ -1249,6 +1253,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Views\Product\AutoCorrectLockPoint.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Views\Product\CalculateOffsetU.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 373 - 0
TeamAAS-VM/ViewModels/Product/AutoCorrectLockPointViewModel.cs

@@ -0,0 +1,373 @@
+using Cognex.VisionPro;
+using MaterialDesignThemes.Wpf;
+using Prism.Commands;
+using Prism.Events;
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Drawing;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using TeamAAS_VP.Core;
+using TeamAAS_VP.Core.PLCs;
+using TeamAAS_VP.Events;
+using TeamAAS_VP.Interfaces;
+using TeamAAS_VP.Models;
+using TeamAAS_VP.Models.PLC;
+
+namespace TeamAAS_VP.ViewModels.Product
+{
+    public class AutoCorrectLockPointViewModel : BindableBase
+    {
+        private readonly IRobotService _robotService;
+        private readonly IProductService _productService;
+        private readonly IRemoteCommandService _remoteCommandService;
+        private readonly IPlcService _plcService;
+        private readonly IEventAggregator _eventAggregator;
+        private readonly ICalibrationService _calibrationService;
+
+        private CancellationTokenSource _cts;
+        #region 属性
+        private ICogImage _Image;
+
+        public ICogImage Image
+        {
+            get { return _Image; }
+            set { SetProperty(ref _Image, value); }
+        }
+
+        private Cognex.VisionPro.CogGraphicCollection _Graphic;
+
+        public Cognex.VisionPro.CogGraphicCollection Graphic
+        {
+            get { return _Graphic; }
+            set { SetProperty(ref _Graphic, value); }
+        }
+
+        private List<PlcPoint> _AllScrewPoint;
+        /// <summary>
+        /// 所有的锁付点
+        /// </summary>
+        public List<PlcPoint> AllScrewPoint
+        {
+            get { return _AllScrewPoint; }
+            set { SetProperty(ref _AllScrewPoint, value);
+                if (value!=null)
+                {
+                    CorrectPoints = new ObservableCollection<PointEx>();
+                    foreach (var item in value)
+                    {
+                        CorrectPoints.Add(new PointEx(item));
+                    }
+                }
+            }
+        }
+
+        private ObservableCollection<PointEx> _CorrectPoints;
+        /// <summary>
+        /// 所有校准的点集合
+        /// </summary>
+        public ObservableCollection<PointEx> CorrectPoints
+        {
+            get { return _CorrectPoints; }
+            set { SetProperty(ref _CorrectPoints, value); }
+        }
+
+        //执行中
+        private bool _IsExecuting;
+        public bool IsExecuting
+        {
+            get { return _IsExecuting; }
+            set { SetProperty(ref _IsExecuting, value); }
+        }
+
+        private IRobot _Robot;
+        public IRobot Robot
+        {
+            get { return _Robot; }
+            set { SetProperty(ref _Robot, value); }
+        }
+
+        #endregion
+
+        #region 命令
+        private DelegateCommand _StartAutoCorrectCommand;
+        public DelegateCommand StartAutoCorrectCommand =>
+            _StartAutoCorrectCommand ?? (_StartAutoCorrectCommand = new DelegateCommand(ExecuteStartAutoCorrectCommand, CanExecuteStartAutoCorrectCommand).ObservesProperty(()=> IsExecuting));
+
+        private DelegateCommand _CancelAutoCorrectCommand;
+        public DelegateCommand CancelAutoCorrectCommand =>
+            _CancelAutoCorrectCommand ?? (_CancelAutoCorrectCommand = new DelegateCommand(ExecuteCancelAutoCorrectCommand, CanExecuteCancelAutoCorrectCommand).ObservesProperty(() => IsExecuting));
+
+        
+        #endregion
+
+
+        public AutoCorrectLockPointViewModel(IRobotService robotService, IProductService productService, IRemoteCommandService remoteCommandService, IPlcService plcService,
+            IEventAggregator eventAggregator, ICalibrationService calibrationService)
+        {
+            _robotService = robotService;
+            _productService = productService;
+            _remoteCommandService = remoteCommandService;
+            _plcService = plcService;
+            _eventAggregator = eventAggregator;
+            _calibrationService = calibrationService;
+        }
+
+        #region 方法
+
+
+        /// <summary>
+        /// 开始校准
+        /// </summary>
+        async void ExecuteStartAutoCorrectCommand()
+        {
+            IsExecuting= true;
+            try
+            {
+                if (Robot == null || !Robot.IsConnected)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "机器人未连接,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                //获取当前产品
+                var product = _productService.GetCurrentProduct();
+                if (product == null)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未选择产品,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                //获取锁付相机拍照点位
+                var screwCameraPoint = product.ScrewCameraPoints;
+                if (screwCameraPoint == null || screwCameraPoint.Count == 0)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                //获取相机拍照点位对应的锁付点
+                var screwCameraLocalPoint1 = product.ScrewCameraLocalPos1;
+                if (screwCameraLocalPoint1 == null)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位对应的锁付点,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                var screwCameraLocalPoint2= product.ScrewCameraLocalPos2;
+                if (screwCameraLocalPoint2 == null)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照点位对应的锁付点,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                var ProcedureModels = new ObservableCollection<ProcedureModel>();
+                foreach (var item in product.CameraProcedures)
+                {
+                    foreach (var item1 in item.ProcedureModels)
+                    {
+                        ProcedureModels.Add(item1);
+                    }
+                }
+                //获取拍照流程
+                if (product.MoveDownCameraLockPhotoProcedureId == Guid.Empty)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照流程,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                var procedure = ProcedureModels.FirstOrDefault(p => p.Id == product.MoveDownCameraLockPhotoProcedureId);
+                if (procedure == null)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "未获取到锁付相机拍照流程,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+
+
+                //移动机器人至拍照点位,拍照
+                var rpoint = new RPoint()
+                {
+                    X = screwCameraPoint[0].X_Position,
+                    Y = screwCameraPoint[0].Y_Position,
+                    Z = screwCameraPoint[0].Z_Position_Start,
+                    U = screwCameraPoint[0].U_Position,
+                    V = screwCameraPoint[0].R_Position,
+                };
+                await Robot.CalibMotionAsync(rpoint, 0);
+                await Task.Delay(200);
+                // 执行拍照并获取识别结果
+                var recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                if (!recognitionResult.IsSucceed)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                //第一个点位的校正结果
+                PointF worldP1 = new PointF((float)recognitionResult.X, (float)recognitionResult.Y);
+                //移动机器人至拍照点位,拍照
+                rpoint = new RPoint()
+                {
+                    X = screwCameraPoint[0].X_Position,
+                    Y = screwCameraPoint[0].Y_Position,
+                    Z = screwCameraPoint[0].Z_Position_Start,
+                    U = screwCameraPoint[0].U_Position,
+                    V = screwCameraPoint[0].R_Position,
+                };
+                await Robot.CalibMotionAsync(rpoint, 0);
+                if (_cts.IsCancellationRequested)
+                    return;
+                await Task.Delay(200);
+                // 执行拍照并获取识别结果
+                recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                if (!recognitionResult.IsSucceed)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
+                    return;
+                }
+                //第一个点位的校正结果
+                PointF worldP2 = new PointF((float)recognitionResult.X, (float)recognitionResult.Y);
+
+                //计算移动相机与拍照点之间的偏差
+                //获取校准
+                var calibration = _calibrationService.GetCalibration(procedure.CalibrationId);
+
+                //获取mark点
+                var mark = calibration.MarkPoint;
+                //获取中心点
+                var center = calibration.CenterPoint;
+                //计算相机中心与披头之间的坐标偏差
+                var cameraOffsetX = mark.X - center.X;
+                var cameraOffsetY = mark.Y - center.Y;
+
+
+                //根据UpCameraPutResults[]中的索引1、2,和拍照点对应的Local下的坐标,从创建Local坐标系
+                PointF localP1 = new PointF(screwCameraLocalPoint1.X_Position, screwCameraLocalPoint1.Y_Position);
+                PointF localP2 = new PointF(screwCameraLocalPoint2.X_Position, screwCameraLocalPoint2.Y_Position);
+                CoordinateTransformer local = new CoordinateTransformer(worldP1, worldP2, localP1, localP2);
+
+                for (int i = 0; i < product.ScrewPoints.Count; i++)
+                {
+                    var localPoint = new PointF(product.ScrewCameraPoints[i].X_Position, product.ScrewCameraPoints[i].Y_Position);
+                    var worldPoint = local.ToOldCoord(localPoint.X, localPoint.Y);
+                    var point = product.ScrewCameraPoints[i].Clone();
+                    point.X_Position = (float)worldPoint[0];
+                    point.Y_Position = (float)worldPoint[1];
+                    //计算当前点的高度与screwCameraLocalPoint1的Z轴之间的偏差
+                    var deltaZ = product.ScrewPoints[i].Z_Position_Start - screwCameraPoint[0].Z_Position_Start;
+
+                    //计算相机去拍照点位
+                    point.X_Position+= cameraOffsetX;
+                    point.Y_Position+= cameraOffsetY;
+                    point.Z_Position_Start= screwCameraPoint[0].Z_Position_Start + deltaZ;
+
+                    //移动机器人至拍照点位,拍照
+                    rpoint = new RPoint()
+                    {
+                        X = point.X_Position,
+                        Y = point.Y_Position,
+                        Z = point.Z_Position_Start,
+                        U = screwCameraPoint[0].U_Position,
+                        V = screwCameraPoint[0].R_Position,
+                    };
+                    await Robot.CalibMotionAsync(rpoint, 0);
+                    if (_cts.IsCancellationRequested)
+                        return;
+                    await Task.Delay(200);
+                    // 执行拍照并获取识别结果
+                    recognitionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(procedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
+                    if (!recognitionResult.IsSucceed)
+                    {
+                        _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "拍照获取识别结果失败,无法执行取料拍照点位矫正!", Duration = 1 });
+                        return;
+                    }
+                    //将获取到的点位转换至Local坐标系下
+                    var correctedPoint = local.ToNewCoord((float)recognitionResult.X, (float)recognitionResult.Y);
+                    CorrectPoints[i].PostX = (float)correctedPoint[0];
+                    CorrectPoints[i].PostY = (float)correctedPoint[1];
+                    if (_cts.IsCancellationRequested)
+                        return;
+                }
+
+            }
+            catch (Exception)
+            {
+
+                throw;
+            }
+            finally
+            {
+                IsExecuting= false;
+            }   
+        }
+
+        bool CanExecuteStartAutoCorrectCommand()
+        {
+            return !IsExecuting;
+        }
+
+        void ExecuteCancelAutoCorrectCommand()
+        {
+            _cts?.Cancel();
+        }
+
+        bool CanExecuteCancelAutoCorrectCommand()
+        {
+            return IsExecuting;
+        }
+        #endregion
+
+        public class PointEx : BindableBase
+        {
+            private int _Number;
+            public int Number
+            {
+                get { return _Number; }
+                set { SetProperty(ref _Number, value); }
+            }
+
+            private string _Label;
+            public string Label
+            {
+                get { return _Label; }
+                set { SetProperty(ref _Label, value); }
+            }
+
+            private float _PreX;
+            public float PreX
+            {
+                get { return _PreX; }
+                set { SetProperty(ref _PreX, value); }
+            }
+
+            private float _PreY;
+            public float PreY
+            {
+                get { return _PreY; }
+                set { SetProperty(ref _PreY, value); }
+            }
+
+            private float _PostX;
+            public float PostX
+            {
+                get { return _PostX; }
+                set { SetProperty(ref _PostX, value); }
+            }
+
+            private float _PostY;
+            public float PostY
+            {
+                get { return _PostY; }
+                set { SetProperty(ref _PostY, value); }
+            }
+
+            public PointEx()
+            {
+            }
+
+            public PointEx(PlcPoint point)
+            {
+                Number = point.Number;
+                Label = point.Label;
+                PreX = point.X_Position;
+                PreY = point.Y_Position;
+            }
+        }
+    }
+}

+ 44 - 1
TeamAAS-VM/ViewModels/Product/PlcPointParamsViewModel.cs

@@ -12,6 +12,7 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows;
+using TeamAAS_VP.Controls;
 using TeamAAS_VP.Core;
 using TeamAAS_VP.Core.PLCs;
 using TeamAAS_VP.DxfModule;
@@ -351,7 +352,9 @@ namespace TeamAAS_VP.ViewModels.Product
         public DelegateCommand ApplyLockPointFeederAndScrewProgramCommand =>
             _ApplyLockPointFeederAndScrewProgramCommand ?? (_ApplyLockPointFeederAndScrewProgramCommand = new DelegateCommand(ExecuteApplyLockPointFeederAndScrewProgramCommand));
 
-        
+        private DelegateCommand _AutoCorrectLockPoint;
+        public DelegateCommand AutoCorrectLockPoint =>
+            _AutoCorrectLockPoint ?? (_AutoCorrectLockPoint = new DelegateCommand(ExecuteAutoCorrectLockPoint));
 
         #endregion
 
@@ -967,6 +970,31 @@ namespace TeamAAS_VP.ViewModels.Product
                 point.Z_Position_Start = LockPointStartZ;
             }
         }
+
+        /// <summary>
+        /// 通过相机自动矫正锁附点位
+        /// </summary>
+        async void ExecuteAutoCorrectLockPoint()
+        {
+            try
+            {
+                var view = new AutoCorrectLockPoint();
+                var vm = view.DataContext as AutoCorrectLockPointViewModel;
+                vm.Robot = Robot;
+                vm.AllScrewPoint = new List<PlcPoint>(Points.ToArray());
+                //show the dialog
+                var result = await DialogHost.Show(view, "RootDialog", null, null, null);
+                if (result != null)
+                {
+                    
+                }
+            }
+            catch (Exception ex)
+            {
+                LogHelper.WriteLogError("通过相机自动矫正锁附点位时出错!", ex);
+                _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = ex.Message, Duration = 1 });
+            }
+        }
         #endregion
 
         #region 继承
@@ -1122,6 +1150,10 @@ namespace TeamAAS_VP.ViewModels.Product
                     return;
                 }
 
+                var waiting = new WaitingControl();
+                //show the dialog
+                var task = DialogHost.Show(waiting, "RootDialog", null, null, null);
+
                 // 1. 控制机器人移动至拍照点位
                 var rpoint = new RPoint()
                 {
@@ -1138,6 +1170,11 @@ namespace TeamAAS_VP.ViewModels.Product
                 var recognitionResult =await _remoteCommandService.ExecutePhotoGetSinglePoint(SelectProcedure, null, new double[] { rpoint.X, rpoint.Y, 0 }, _cts.Token);
                 if (!recognitionResult.IsSucceed)
                 {
+                    if (DialogHost.IsDialogOpen("RootDialog"))
+                    {
+                        DialogHost.Close("RootDialog");
+                    }
+                    await task;
                     _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "取料拍照点位矫正失败,识别未成功!", Duration = 1 });
                     return;
                 }
@@ -1146,6 +1183,12 @@ namespace TeamAAS_VP.ViewModels.Product
                 SelectedPickPoint.X_Position = (float)recognitionResult.X;
                 SelectedPickPoint.Y_Position = (float)recognitionResult.Y;
 
+                if (DialogHost.IsDialogOpen("RootDialog"))
+                {
+                    DialogHost.Close("RootDialog");
+                }
+                await task;
+
                 _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "取料拍照点位矫正完成!", Duration = 0.4 });
             }
             catch (Exception ex)

+ 114 - 0
TeamAAS-VM/Views/Product/AutoCorrectLockPoint.xaml

@@ -0,0 +1,114 @@
+<UserControl x:Class="TeamAAS_VP.Views.Product.AutoCorrectLockPoint"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:prism="http://prismlibrary.com/"
+             xmlns:wf="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
+             xmlns:vp="clr-namespace:Cognex.VisionPro;assembly=Cognex.VisionPro.Controls"
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:vm="clr-namespace:TeamAAS_VP.ViewModels.Product"
+             xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
+             xmlns:sys="clr-namespace:System;assembly=mscorlib"
+             xmlns:uControl="clr-namespace:TeamAAS_VP.Controls"
+             xmlns:localbehaviors="clr-namespace:TeamAAS_VP.Behaviors"
+             xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
+             xmlns:lex="http://wpflocalizeextension.codeplex.com"
+             lex:LocalizeDictionary.DesignCulture="zh-CN"
+             lex:ResxLocalizationProvider.DefaultAssembly="TeamAAS-VP"
+             lex:ResxLocalizationProvider.DefaultDictionary="Lang"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             mc:Ignorable="d"
+             d:DataContext="{d:DesignInstance Type=vm:AutoCorrectLockPointViewModel}"
+             Height="768"
+             Width="1024"
+             d:Background="White"
+             FontFamily="{DynamicResource DefaultFont}">
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="*" />
+            <RowDefinition Height="Auto" />
+            <RowDefinition Height="Auto" />
+        </Grid.RowDefinitions>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="*" />
+            <ColumnDefinition Width="Auto" />
+        </Grid.ColumnDefinitions>
+
+        <wf:WindowsFormsHost Grid.Column="0"
+                             Margin="5">
+            <vp:CogRecordDisplay x:Name="display" />
+        </wf:WindowsFormsHost>
+
+        <!-- 新增:右侧表格,显示校准前/校准后 XY 坐标 -->
+        <DataGrid Grid.Row="0"
+                  Grid.Column="1"
+                  Margin="5"
+                  Width="360"
+                  ItemsSource="{Binding CorrectPoints}"
+                  AutoGenerateColumns="False"
+                  IsReadOnly="True"
+                  CanUserAddRows="False"
+                  CanUserDeleteRows="False"
+                  HeadersVisibility="Column"
+                  SelectionMode="Single"
+                  SelectionUnit="FullRow">
+            <DataGrid.Columns>
+                <DataGridTextColumn Header="编号"
+                                    Binding="{Binding Number}"
+                                    MinWidth="60" />
+                <DataGridTextColumn Header="标签"
+                                    Binding="{Binding Label}"
+                                    MinWidth="60" />
+                <DataGridTextColumn Header="校准前X"
+                                    Binding="{Binding PreX, StringFormat=F3}"
+                                    MinWidth="80" />
+                <DataGridTextColumn Header="校准前Y"
+                                    Binding="{Binding PreY, StringFormat=F3}"
+                                    MinWidth="80" />
+                <DataGridTextColumn Header="校准后X"
+                                    Binding="{Binding PostX, StringFormat=F3}"
+                                    MinWidth="80" />
+                <DataGridTextColumn Header="校准后Y"
+                                    Binding="{Binding PostY, StringFormat=F3}"
+                                    MinWidth="80" />
+            </DataGrid.Columns>
+        </DataGrid>
+
+        <StackPanel Grid.Row="1"
+                    Grid.ColumnSpan="2"
+                    Orientation="Horizontal"
+                    HorizontalAlignment="Center"
+                    Margin="5">
+            <!--开始按钮-->
+            <Button Content="{lex:Loc 开始校准}"
+                    Command="{Binding StartAutoCorrectCommand}"
+                    Margin="0,0,12,0" />
+            <!--取消按钮-->
+            <Button Content="取消校准"
+                    Command="{Binding CancelAutoCorrectCommand}" />
+        </StackPanel>
+
+        <StackPanel Grid.Row="2"
+                    Grid.ColumnSpan="2"
+                    Orientation="Horizontal"
+                    HorizontalAlignment="Right"
+                    Margin="5"
+                    IsEnabled="{Binding IsExecuting,Converter={StaticResource InvertBooleanConverter}}">
+            <Button Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
+                    CommandParameter="{Binding}"
+                    IsDefault="True"
+                    Content="{lex:Loc 确定}"
+                    Margin="0,0,12,0" />
+
+            <Button Margin="0"
+                    Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
+                    IsCancel="True"
+                    Content="{lex:Loc 取消}">
+                <Button.CommandParameter>
+                    <x:Null />
+                </Button.CommandParameter>
+            </Button>
+        </StackPanel>
+    </Grid>
+</UserControl>

+ 48 - 0
TeamAAS-VM/Views/Product/AutoCorrectLockPoint.xaml.cs

@@ -0,0 +1,48 @@
+using System.Windows.Controls;
+using TeamAAS_VP.ViewModels.Calibration;
+using TeamAAS_VP.ViewModels.Product;
+
+namespace TeamAAS_VP.Views.Product
+{
+    /// <summary>
+    /// Interaction logic for AutoCorrectLockPoint
+    /// </summary>
+    public partial class AutoCorrectLockPoint : UserControl
+    {
+        AutoCorrectLockPointViewModel VM;
+        public AutoCorrectLockPoint()
+        {
+            InitializeComponent();
+            VM = DataContext as AutoCorrectLockPointViewModel;
+            VM.PropertyChanged += VM_PropertyChanged;
+            this.display.VerticalScrollBar = false;
+            this.display.HorizontalScrollBar = false;
+            this.display.AutoFit = true;
+            this.display.BackColor = System.Drawing.SystemColors.ActiveCaption;
+        }
+
+        private void VM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+        {
+            try
+            {
+                if (e.PropertyName == "Image")
+                {
+                    this.display.Image = VM.Image;
+                }
+                else if (e.PropertyName == "Graphic")
+                {
+                    this.display.StaticGraphics.Clear();
+                    if (VM.Graphic != null)
+                    {
+                        this.display.StaticGraphics.AddList(VM.Graphic, "");
+                    }
+
+                }
+            }
+            catch (System.Exception)
+            {
+
+            }
+        }
+    }
+}

+ 12 - 0
TeamAAS-VM/Views/Product/PlcPointParams.xaml

@@ -411,6 +411,7 @@
                                                     <ColumnDefinition Width="Auto" />
                                                     <ColumnDefinition Width="Auto" />
                                                     <ColumnDefinition Width="Auto" />
+                                                    <ColumnDefinition Width="Auto" />
                                                 </Grid.ColumnDefinitions>
                                                 <Grid.RowDefinitions>
                                                     <RowDefinition Height="Auto" />
@@ -540,6 +541,17 @@
                                                         HorizontalAlignment="Left"
                                                         materialDesign:ButtonAssist.CornerRadius="5"
                                                         Command="{Binding ImportCadLockCameraPointCommand}" />
+                                                <!--通过相机自动矫正锁附点位-->
+                                                <Button Content="通过相机自动矫正锁附点位"
+                                                        Grid.Row="0"
+                                                        Grid.Column="8"
+                                                        Grid.RowSpan="2"
+                                                        Margin="10,0"
+                                                        MinWidth="150"
+                                                        HorizontalAlignment="Left"
+                                                        materialDesign:ButtonAssist.CornerRadius="5"
+                                                        Command="{Binding AutoCorrectLockCameraPointCommand}" />
+
                                             </Grid>
                                         </StackPanel>
                                     </ScrollViewer>