Ver Fonte

修复移动单个相机拍两次

徐孝锋 há 8 meses atrás
pai
commit
c813494614

+ 146 - 96
TeamAAS-VM/Core/Management.cs

@@ -528,13 +528,13 @@ namespace TeamAAS_VP.Core
         {
             try
             {
-                
+
                 var screwDriverConfig = _configService.GetScrewDriverConfig();
                 ScrewDriver = new XYD_ScrewDriver(screwDriverConfig.IPAdress, screwDriverConfig.Port);
                 Status.Add(new StatusInfo(ScrewDriver.Id, "电批未连接", new SolidColorBrush(Colors.Red)));
                 ScrewDriver.ConnectStateChangedEvent += ScrewDriver_ConnectStateChangedEvent;
-                ScrewDriver.SendTimeout= screwDriverConfig.SendTimeout;
-                screwDriverConfig.ReceiveTimeout= screwDriverConfig.ReceiveTimeout;
+                ScrewDriver.SendTimeout = screwDriverConfig.SendTimeout;
+                screwDriverConfig.ReceiveTimeout = screwDriverConfig.ReceiveTimeout;
                 var isConnected = await ScrewDriver.ConnectAsync();
                 if (isConnected)
                 {
@@ -552,7 +552,7 @@ namespace TeamAAS_VP.Core
             }
         }
 
-        
+
 
         #endregion
 
@@ -1029,8 +1029,18 @@ namespace TeamAAS_VP.Core
             }
         }
 
-        PointF[] DowmCameraResults= new PointF[10];
-        PointF[] UpCameraPutResults = new PointF[10];
+        /// <summary>
+        /// 固定向上相机拍照结果
+        /// </summary>
+        OpenCvSharp.Point3f[] DowmCameraResults = new OpenCvSharp.Point3f[10];
+        /// <summary>
+        /// 移动向下相机拍照结果
+        /// </summary>
+        OpenCvSharp.Point3f[] UpCameraPutResults = new OpenCvSharp.Point3f[10];
+        
+        /// <summary>
+        /// 二次定位相机的工具坐标
+        /// </summary>
         PointF DownTool = new PointF();
         double _FixedUpCameraAngle = 0;
         double _MoveCameraAngle = 0;
@@ -1043,17 +1053,17 @@ namespace TeamAAS_VP.Core
         {
             try
             {
-                if (tuple.key!= "AutoSensor")
+                if (tuple.key != "AutoSensor")
                 {
                     return;
                 }
-
+                
                 var addressConfig = _configService.GetPlcAddresses();
                 var plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
                 if (plc == null || !plc.IsConnected) return;
                 // 获取当前产品
                 var currentProduct = _productService.GetCurrentProduct();
-                if (currentProduct==null)
+                if (currentProduct == null)
                 {
                     return;
                 }
@@ -1066,6 +1076,8 @@ namespace TeamAAS_VP.Core
                     _productService.CurrentProductCode = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                 }
 
+                bool isDryMode = plc.ReadNode<bool>(addressConfig.In_DryMode.Address);
+
                 // 触发下相机拍照
                 if (addressConfig.In_DowmCameraExe.Address.Contains(tuple.nodeId))
                 {
@@ -1077,7 +1089,7 @@ namespace TeamAAS_VP.Core
                             //相机的编号
                             Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_DowmCameraNum.Address);
                             SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
-                            
+
                             // 获取机器人当前坐标
                             var robot = _robotService.GetAllRobots().FirstOrDefault();
                             if (robot == null)
@@ -1091,10 +1103,10 @@ namespace TeamAAS_VP.Core
 
                             //如果下相机拍照的次数是1,则判断用时拍照的相机是几个
                             int downCameraNum = _configService.GetSystemConfiguration().DowmCameraNum;
-                            if (downCameraNum==1)
+                            if (downCameraNum == 1)
                             {
                                 //如果下相机2的流程id为空,则表示只有一个下相机
-                                if (currentProduct.FixedUpCamera2ProcedureId==Guid.Empty)
+                                if (currentProduct.FixedUpCamera2ProcedureId == Guid.Empty)
                                 {
                                     //获取固定向上相机1的流程
                                     var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
@@ -1106,22 +1118,25 @@ namespace TeamAAS_VP.Core
                                     }
                                     // 执行视觉任务
                                     var _cts = new CancellationTokenSource();
-                                    var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition .X, currentPosition .Y, currentPosition .U}, _cts.Token);
+                                    var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                    if (isDryMode)
+                                    {
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
+                                        return;
+                                    }
                                     if (visionResult.IsSucceed)
                                     {
                                         float toolX = (float)(visionResult.X - currentPosition.X);
                                         float toolY = (float)(visionResult.Y - currentPosition.Y);
-                                        
-                                        DowmCameraResults[cameraIndex] = new PointF(toolX, toolX);
-                                        DownTool= new PointF(toolX, toolX);
+
+                                        DowmCameraResults[cameraIndex] = new OpenCvSharp.Point3f(toolX, toolX, (float)visionResult.U);
+                                        DownTool = new PointF(toolX, toolX);
                                         await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
                                         return;
                                     }
                                     else
                                     {
-                                        //await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
-                                        //return;
-                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
                                         return;
                                     }
                                 }
@@ -1145,25 +1160,29 @@ namespace TeamAAS_VP.Core
                                     }
                                     // 执行视觉任务
                                     var _cts = new CancellationTokenSource();
-                                    var task1= _remoteCommandService.ExecutePhotoGetSinglePoint(process1, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
-                                    var task2= _remoteCommandService.ExecutePhotoGetSinglePoint(process2, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
-                                    var visionResults= await Task.WhenAll(task1, task2);
+                                    var task1 = _remoteCommandService.ExecutePhotoGetSinglePoint(process1, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                    var task2 = _remoteCommandService.ExecutePhotoGetSinglePoint(process2, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                    var visionResults = await Task.WhenAll(task1, task2);
+                                    if (isDryMode)
+                                    {
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
+                                        return;
+                                    }
                                     if (visionResults[0].IsSucceed && visionResults[1].IsSucceed)
                                     {
                                         float toolX = (float)(visionResults[0].X + visionResults[1].X) / 2;
                                         float toolY = (float)(visionResults[0].Y + visionResults[1].Y) / 2;
                                         _FixedUpCameraAngle = Common.CalculateAngleBetweenPointsDegrees(new PointF((float)visionResults[0].X, (float)visionResults[0].Y), new PointF((float)visionResults[1].X, (float)visionResults[1].Y));
-                                        DowmCameraResults[cameraIndex] = new PointF(toolX, toolX);
+                                        DowmCameraResults[cameraIndex] = new OpenCvSharp.Point3f(toolX, toolX, (float)_FixedUpCameraAngle);
                                         DownTool = new PointF(toolX, toolX);
                                         await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
                                         return;
                                     }
                                     else
                                     {
-                                        //await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
-                                        //return;
-                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
                                         return;
+                                        
                                     }
 
                                 }
@@ -1235,17 +1254,18 @@ namespace TeamAAS_VP.Core
                                     var task1 = _remoteCommandService.ExecutePhotoGetSinglePoint(process1, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
                                     var task2 = _remoteCommandService.ExecutePhotoGetSinglePoint(process2, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
                                     var visionResults = await Task.WhenAll(task1, task2);
+                                    if (isDryMode)
+                                    {
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
+                                        return;
+                                    }
                                     if (visionResults[0].IsSucceed && visionResults[1].IsSucceed)
                                     {
-                                        float tool1X = (float)(visionResults[0].X - visionResults[0].X);
-                                        float tool1Y = (float)(visionResults[0].Y - visionResults[0].Y);
-                                        float tool2X = (float)(visionResults[1].Y - visionResults[1].Y);
-                                        float tool2Y = (float)(visionResults[1].Y - visionResults[1].Y);
-                                        float toolX = (tool1X + tool2X) / 2;
-                                        float toolY = (tool1X + tool2X) / 2;
-
-                                        DowmCameraResults[cameraIndex] = new PointF(toolX, toolX);
-                                        DownTool = new PointF((DowmCameraResults[1].X + DowmCameraResults[2].X) / 2, (DowmCameraResults[1].Y + DowmCameraResults[2].Y) / 2);
+                                        float toolX = (float)(visionResults[0].X + visionResults[1].X) / 2;
+                                        float toolY = (float)(visionResults[0].Y + visionResults[1].Y) / 2;
+                                        _FixedUpCameraAngle = Common.CalculateAngleBetweenPointsDegrees(new PointF((float)visionResults[0].X, (float)visionResults[0].Y), new PointF((float)visionResults[1].X, (float)visionResults[1].Y));
+                                        DowmCameraResults[cameraIndex] = new OpenCvSharp.Point3f(toolX, toolX, (float)_FixedUpCameraAngle);
+                                        DownTool = new PointF(toolX, toolX);
                                         await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
                                         return;
                                     }
@@ -1447,7 +1467,7 @@ namespace TeamAAS_VP.Core
                             //相机的编号
                             Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPutNum.Address);
                             SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
-                            
+
 
                             // 获取机器人当前坐标
                             var robot = _robotService.GetAllRobots().FirstOrDefault();
@@ -1460,7 +1480,8 @@ namespace TeamAAS_VP.Core
                             }
                             var currentPosition = robot.GetRobotPos();
 
-                            //如果上相机2的流程id为空,则表示只有一个下相机
+                            
+                            //如果上相机2的流程id为空,则表示只有一个上相机
                             if (currentProduct.MoveDownCamera2LockPhotoProcedureId == Guid.Empty)
                             {
                                 //获取移动向下相机1的流程
@@ -1474,60 +1495,66 @@ namespace TeamAAS_VP.Core
                                 // 执行视觉任务
                                 var _cts = new CancellationTokenSource();
                                 var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                if (isDryMode)
+                                {
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
+                                    return;
+                                }
                                 if (visionResult.IsSucceed)
                                 {
-                                    UpCameraPutResults[cameraIndex] = new PointF((float)visionResult.X, (float)visionResult.Y);
+                                    UpCameraPutResults[cameraIndex] = new OpenCvSharp.Point3f((float)visionResult.X, (float)visionResult.Y, (float)visionResult.U);
                                     await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
                                     return;
                                 }
                                 else
                                 {
-                                    //await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
-                                    //return;
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                    return;
+                                }
+                            }
+                            else
+                            {
+                                //获取移动向下相机1的流程
+                                var process1 = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamera1LockPhotoProcedureId);
+                                if (process1 == null)
+                                {
+                                    SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.MoveDownCamera1LockPhotoProcedureId}", MessageLevel.Alarm);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                    return;
+                                }
+                                //获取移动向下相机2的流程
+                                var process2 = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamera2LockPhotoProcedureId);
+                                if (process2 == null)
+                                {
+                                    SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.MoveDownCamera2LockPhotoProcedureId}", MessageLevel.Alarm);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                    return;
+                                }
+                                // 执行视觉任务
+                                var _cts = new CancellationTokenSource();
+                                var task1 = _remoteCommandService.ExecutePhotoGetSinglePoint(process1, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                var task2 = _remoteCommandService.ExecutePhotoGetSinglePoint(process2, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                var visionResults = await Task.WhenAll(task1, task2);
+                                if (isDryMode)
+                                {
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
+                                    return;
+                                }
+                                if (visionResults[0].IsSucceed && visionResults[1].IsSucceed)
+                                {
+                                    float centerX = (float)(visionResults[0].X + visionResults[1].X) / 2;
+                                    float centerY = (float)(visionResults[0].Y + visionResults[1].Y) / 2;
+                                    _MoveCameraAngle = Common.CalculateAngleBetweenPointsDegrees(new PointF((float)visionResults[0].X, (float)visionResults[0].Y), new PointF((float)visionResults[1].X, (float)visionResults[1].Y));
+                                    UpCameraPutResults[cameraIndex] = new OpenCvSharp.Point3f(centerX, centerY,(float)_MoveCameraAngle);
                                     await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
                                     return;
                                 }
+                                else
+                                {
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                    return;
+                                }
                             }
-                            //else
-                            //{
-                            //    //获取固定向上相机1的流程
-                            //    var process1 = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamera1LockPhotoProcedureId);
-                            //    if (process1 == null)
-                            //    {
-                            //        SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.MoveDownCamera1LockPhotoProcedureId}", MessageLevel.Alarm);
-                            //        await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
-                            //        return;
-                            //    }
-                            //    //获取固定向上相机2的流程
-                            //    var process2 = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamera2LockPhotoProcedureId);
-                            //    if (process2 == null)
-                            //    {
-                            //        SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.MoveDownCamera2LockPhotoProcedureId}", MessageLevel.Alarm);
-                            //        await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
-                            //        return;
-                            //    }
-                            //    // 执行视觉任务
-                            //    var _cts = new CancellationTokenSource();
-                            //    var task1 = _remoteCommandService.ExecutePhotoGetSinglePoint(process1, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
-                            //    var task2 = _remoteCommandService.ExecutePhotoGetSinglePoint(process2, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
-                            //    var visionResults = await Task.WhenAll(task1, task2);
-                            //    if (visionResults[0].IsSucceed && visionResults[1].IsSucceed)
-                            //    {
-                            //        float centerX = (float)(visionResults[0].X + visionResults[1].X) / 2;
-                            //        float centerY = (float)(visionResults[0].Y + visionResults[1].Y) / 2;
-                            //        _MoveCameraAngle = Common.CalculateAngleBetweenPointsDegrees(new PointF((float)visionResults[0].X, (float)visionResults[0].Y), new PointF((float)visionResults[1].X, (float)visionResults[1].Y));
-                            //        UpCameraPutResults[cameraIndex] = new PointF(centerX, centerY);
-                            //        await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
-                            //        return;
-                            //    }
-                            //    else
-                            //    {
-                            //        //await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
-                            //        //return;
-                            //        await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
-                            //        return;
-                            //    }
-                            //}
                         }
                         else
                         {
@@ -1627,7 +1654,7 @@ namespace TeamAAS_VP.Core
                 {
                     if (tuple.value is Int16 state)
                     {
-                        if (state==1)
+                        if (state == 1)
                         {
                             SendTaskMessage($"收到开始锁付信号...", MessageLevel.Debug);
                             //位置编号
@@ -1646,7 +1673,7 @@ namespace TeamAAS_VP.Core
                 {
                     if (tuple.value is Int16 state)
                     {
-                        if (state==1 || state == 2)
+                        if (state == 1 || state == 2)
                         {
                             SendTaskMessage($"收到停止锁付信号...", MessageLevel.Debug);
                             //位置编号
@@ -1663,7 +1690,7 @@ namespace TeamAAS_VP.Core
 
                             await Task.Delay(60);
                             //获取电批结果
-                            bool isSucced= ScrewDriver.GetData();
+                            bool isSucced = ScrewDriver.GetData();
                             LockResult lockResult = new LockResult();
                             lockResult.ScrewdriverGetDataSucceed = isSucced;
                             lockResult.Number = positionIndex;
@@ -1710,18 +1737,41 @@ namespace TeamAAS_VP.Core
                         if (state == 1)
                         {
                             SendTaskMessage($"收到多相机坐标合并请求,开始合并...", MessageLevel.Debug);
+                            if (isDryMode)
+                            {
+                                var point1 = currentProduct.ScrewPoints[0].Clone();
+                                SendTaskMessage($"点:1,{point1.X_Position:F3},{point1.Y_Position:F4},{point1.U_Position:F4}", MessageLevel.Info);
+                                await point1.WriteToPlcAddress(addressConfig.Out_Screw, plc);
+                                await plc.WriteNodeAsync(addressConfig.Out_WorkNum.Address, (Int16)1);
+                                await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)1);
+                                return;
+                            }
+
+                            double upCameraX=0, upCameraY=0,upCameraU=0;
+                            upCameraX = UpCameraPutResults[1].X;
+                            upCameraY= UpCameraPutResults[1].Y;
+                            upCameraU= UpCameraPutResults[1].Z;
+                            //如果下相机拍照的次数是1,则判断用时拍照的相机是几个
+                            int upCameraNum = _configService.GetSystemConfiguration().UpCameraPutNum;
+                            if (upCameraNum == 2)
+                            {
+                                upCameraX = (UpCameraPutResults[1].X+ UpCameraPutResults[2].X) / 2;
+                                upCameraY= (UpCameraPutResults[1].Y + UpCameraPutResults[2].Y) / 2;
+                                upCameraU= Common.CalculateAngleBetweenPointsDegrees(new PointF((float)UpCameraPutResults[1].X, (float)UpCameraPutResults[1].Y), new PointF((float)UpCameraPutResults[2].X, (float)UpCameraPutResults[2].Y));
+                            }
+
                             var point = currentProduct.ScrewPoints[0].Clone();
-                            //var pn = Vector<double>.Build.Dense(new double[] { UpCameraPutResults[1].X, UpCameraPutResults[1].Y });
-                            ////目标角度:
-                            //double angle = point.U_Position + (_FixedUpCameraAngle - currentProduct.FixedUpCameraTempletAngle) + (_MoveCameraAngle - currentProduct.MoveDownCamerTempletAngle);
-
-                            //var toolCoord = new ToolCoord();
-                            //toolCoord.SetTool(DowmCameraResults[1].X, DowmCameraResults[1].Y);
-                            ////将_PutPoint转换为Tool0下要走的点
-                            //var p0 = toolCoord.GetTool0Coord(pn, angle);
-                            //point.X_Position = (float)p0[0];
-                            //point.Y_Position = (float)p0[1];
-                            //point.U_Position = (float)angle;
+                            var pn = Vector<double>.Build.Dense(new double[] { upCameraX, upCameraY });
+                            //目标角度:
+                            double angle = point.U_Position + (DowmCameraResults[1].Z - currentProduct.FixedUpCameraTempletAngle) + (upCameraU - currentProduct.MoveDownCamerTempletAngle);
+
+                            var toolCoord = new ToolCoord();
+                            toolCoord.SetTool(DowmCameraResults[1].X, DowmCameraResults[1].Y);
+                            //将_PutPoint转换为Tool0下要走的点
+                            var p0 = toolCoord.GetTool0Coord(pn, angle);
+                            point.X_Position = (float)p0[0];
+                            point.Y_Position = (float)p0[1];
+                            point.U_Position = (float)angle;
                             SendTaskMessage($"点:1,{point.X_Position:F3},{point.Y_Position:F4},{point.U_Position:F4}", MessageLevel.Info);
                             await point.WriteToPlcAddress(addressConfig.Out_Screw, plc);
                             await plc.WriteNodeAsync(addressConfig.Out_WorkNum.Address, (Int16)1);
@@ -1766,12 +1816,12 @@ namespace TeamAAS_VP.Core
                 {
                     if (tuple.value is Int16 state)
                     {
-                        if (state!=0)
+                        if (state != 0)
                         {
                             SendTaskMessage($"螺丝供料器...", MessageLevel.Info);
                             await plc.WriteNodeAsync(addressConfig.In_PickINC.Address, (Int16)0);
                         }
-                        
+
                     }
                 }
             }

+ 14 - 1
TeamAAS-VM/Models/PLC/PlcAddressConfig.cs

@@ -530,7 +530,15 @@ namespace TeamAAS_VP.Models.PLC
             set { SetProperty(ref _In_PickINC, value); }
         }
 
-
+        private PlcAddress _In_DryMode;
+        /// <summary>
+        /// 空跑模式
+        /// </summary>
+        public PlcAddress In_DryMode
+        {
+            get { return _In_DryMode; }
+            set { SetProperty(ref _In_DryMode, value); }
+        }
         #endregion
 
         public PlcAddressConfig()
@@ -906,6 +914,11 @@ namespace TeamAAS_VP.Models.PLC
             In_PickINC.DataType = "int16";
             In_PickINC.Description = "取一颗螺丝触发信号";
 
+            In_DryMode = Ensure(In_DryMode);
+            In_DryMode.Address = "ns=4;s=DB_Control|Mode.Status.DryMode";
+            In_DryMode.DataType = "bool";
+            In_DryMode.Description = "空跑模式";
+
             // 说明:若项目中 PlcAddress 的实际属性名或类型与此不同(例如使用枚举、不同字段名),
             // 请根据实际类型调整赋值。本方法主要提供合理的默认字符串地址、数据类型及描述,便于后续从配置覆盖。
         }

+ 58 - 14
TeamAAS-VM/ViewModels/Product/PlcPointParamsViewModel.cs

@@ -651,6 +651,7 @@ namespace TeamAAS_VP.ViewModels.Product
                     {
                         return;
                     }
+                    double upCameraU = Common.CalculateAngleBetweenPointsDegrees(new PointF((float)_PutPoints[0].X, (float)_PutPoints[0].Y), new PointF((float)_PutPoints[1].X, (float)_PutPoints[1].Y));
 
                     var curpos1 = await Robot.GetRobotPosAsync();
                     //将当前点位转换为产品Local坐标系下的点位
@@ -660,7 +661,7 @@ namespace TeamAAS_VP.ViewModels.Product
                     SelectedPoint.U_Position = curpos1.U;
                     SelectedPoint.R_Position = curpos1.V;
                     SelectProduct.FixedUpCameraTempletAngle = _FixedUpCameraTempletAngle;
-                    SelectProduct.MoveDownCamerTempletAngle = _MoveCameraTempletAngle;
+                    SelectProduct.MoveDownCamerTempletAngle = upCameraU;
                     _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"{Lang.完成}!", Duration = 0.4 });
                     return;
                 }
@@ -1149,8 +1150,7 @@ namespace TeamAAS_VP.ViewModels.Product
 
         ToolCoord toolCoord = null;
         double _FixedUpCameraTempletAngle = 0;
-        double _MoveCameraTempletAngle = 0;
-        PointF _PutPoint = new PointF();
+        OpenCvSharp.Point3f[] _PutPoints = new OpenCvSharp.Point3f[2];
         /// <summary>
         /// 去二次定位
         /// </summary>
@@ -1289,11 +1289,11 @@ namespace TeamAAS_VP.ViewModels.Product
                 // 1. 控制机器人移动至拍照点位
                 var rpoint = new RPoint()
                 {
-                    X = SelectedPoint.X_Position,
-                    Y = SelectedPoint.Y_Position,
-                    Z = SelectedPoint.Z_Position_Start,
-                    U = SelectedPoint.U_Position,
-                    V = SelectedPoint.R_Position,
+                    X = Points[0].X_Position,
+                    Y = Points[0].Y_Position,
+                    Z = Points[0].Z_Position_Start,
+                    U = Points[0].U_Position,
+                    V = Points[0].R_Position,
                 };
                 await Robot.CalibMotionAsync(rpoint, 0);
                 await Task.Delay(200);
@@ -1315,8 +1315,49 @@ namespace TeamAAS_VP.ViewModels.Product
                 var visionResult =await _remoteCommandService.ExecutePhotoGetSinglePoint(process1, null, new double[] { rpoint.X, rpoint.Y, rpoint.U }, _cts.Token);
                 if (visionResult.IsSucceed)
                 {
-                    _MoveCameraTempletAngle = visionResult.U;
-                    _PutPoint = new PointF((float)visionResult.X, (float)visionResult.Y);
+                    _PutPoints[0] = new OpenCvSharp.Point3f((float)visionResult.X, (float)visionResult.Y, (float)visionResult.U);
+                }
+                else
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "视觉定位失败,无法进行产品拍照!", Duration = 1 });
+                    if (DialogHost.IsDialogOpen("RootDialog"))
+                    {
+                        DialogHost.Close("RootDialog");
+                    }
+                    await task;
+                    return;
+                }
+
+                // 2. 控制机器人移动至拍照点位
+                rpoint = new RPoint()
+                {
+                    X = Points[1].X_Position,
+                    Y = Points[1].Y_Position,
+                    Z = Points[1].Z_Position_Start,
+                    U = Points[1].U_Position,
+                    V = Points[1].R_Position,
+                };
+                await Robot.CalibMotionAsync(rpoint, 0);
+                await Task.Delay(200);
+
+                //获取移动向下相机1的流程
+                var process2= _productService.GetCurrentProductProcedureModelById(SelectProduct.MoveDownCamera2LockPhotoProcedureId);
+                if (process2 == null)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"移动向下相机2视觉流程,流程ID:{SelectProduct.MoveDownCamera2LockPhotoProcedureId} 未找到!", Duration = 1 });
+                    if (DialogHost.IsDialogOpen("RootDialog"))
+                    {
+                        DialogHost.Close("RootDialog");
+                    }
+                    await task;
+                    return;
+                }
+                // 执行视觉任务
+                _cts = new CancellationTokenSource();
+                visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process2, null, new double[] { rpoint.X, rpoint.Y, rpoint.U }, _cts.Token);
+                if (visionResult.IsSucceed)
+                {
+                    _PutPoints[1] = new OpenCvSharp.Point3f((float)visionResult.X, (float)visionResult.Y, (float)visionResult.U);
 
                     if (DialogHost.IsDialogOpen("RootDialog"))
                     {
@@ -1376,7 +1417,7 @@ namespace TeamAAS_VP.ViewModels.Product
                     return;
                 }
 
-                if (_PutPoint.X == 0 && _PutPoint.Y == 0)
+                if (_PutPoints[0].X == 0 && _PutPoints[0].Y == 0 && _PutPoints[1].X == 0 && _PutPoints[1].Y == 0)
                 {
                     _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "检测到未定位产品", Duration = 1 });
                     return;
@@ -1386,9 +1427,13 @@ namespace TeamAAS_VP.ViewModels.Product
                 //show the dialog
                 var task = DialogHost.Show(waiting, "RootDialog", null, null, null);
 
-                var pn = Vector<double>.Build.Dense(new double[] { _PutPoint.X, _PutPoint.Y });
+                double upCameraX = (_PutPoints[0].X + _PutPoints[1].X) / 2;
+                double upCameraY = (_PutPoints[0].Y + _PutPoints[1].Y) / 2;
+                double upCameraU = Common.CalculateAngleBetweenPointsDegrees(new PointF((float)_PutPoints[0].X, (float)_PutPoints[0].Y), new PointF((float)_PutPoints[1].X, (float)_PutPoints[1].Y));
+
+                var pn = Vector<double>.Build.Dense(new double[] { upCameraX, upCameraY });
                 //目标角度:
-                double angle = SelectedPoint.U_Position + (_FixedUpCameraTempletAngle - SelectProduct.FixedUpCameraTempletAngle) + (_MoveCameraTempletAngle - SelectProduct.MoveDownCamerTempletAngle);
+                double angle = SelectedPoint.U_Position + (_FixedUpCameraTempletAngle - SelectProduct.FixedUpCameraTempletAngle) + (upCameraU - SelectProduct.MoveDownCamerTempletAngle);
                 //将_PutPoint转换为Tool0下要走的点
                 var p0 = toolCoord.GetTool0Coord(pn, angle);
 
@@ -1704,7 +1749,6 @@ namespace TeamAAS_VP.ViewModels.Product
             try
             {
                 toolCoord = null;
-                _PutPoint = new PointF();
                 SelectProduct = navigationContext.Parameters.GetValue<ProductModel>("SelectProduct");
 
                 SelectedIndex = 0;