Bladeren bron

下/上相机多流程支持及点位配置优化

本次提交实现了下相机/上相机多流程、多相机的灵活配置,扩展了产品模型和参数ViewModel,支持固定/移动下相机1/2的取料与锁附拍照流程。管理核心逻辑根据流程ID动态选择并并发执行视觉任务,提升了定位精度。界面同步增加了相关流程配置项和点位类型,优化了操作体验。为后续复杂场景的扩展和维护打下基础。
孝锋 徐 8 maanden geleden
bovenliggende
commit
a1376dedc8

+ 355 - 76
TeamAAS-VM/Core/Management.cs

@@ -1031,6 +1031,7 @@ namespace TeamAAS_VP.Core
 
         PointF[] DowmCameraResults= new PointF[10];
         PointF[] UpCameraPutResults = new PointF[10];
+        PointF DownTool = new PointF();
         
 
         /// <summary>
@@ -1076,15 +1077,6 @@ namespace TeamAAS_VP.Core
                             Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_DowmCameraNum.Address);
                             SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
 
-                            // 获取流程
-                            var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
-                            if (process == null)
-                            {
-                                SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera1ProcedureId}", MessageLevel.Alarm);
-                                await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
-                                return;
-                            }
-
                             // 获取机器人当前坐标
                             var robot = _robotService.GetAllRobots().FirstOrDefault();
                             if (robot == null)
@@ -1096,21 +1088,177 @@ namespace TeamAAS_VP.Core
                             }
                             var currentPosition = robot.GetRobotPos();
 
-                            // 执行视觉任务
-                            var _cts = new CancellationTokenSource();
-                            var visionResult =await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null,null, _cts.Token);
-                            if (visionResult.IsSucceed)
+                            //如果下相机拍照的次数是1,则判断用时拍照的相机是几个
+                            int downCameraNum = _configService.GetSystemConfiguration().DowmCameraNum;
+                            if (downCameraNum==1)
                             {
-                                //披头偏差
-                                float offsetX = (float)(visionResult.X - currentPosition.X);
-                                float offsetY = (float)(visionResult.Y - currentPosition.Y);
+                                //如果下相机2的流程id为空,则表示只有一个下相机
+                                if (currentProduct.FixedUpCamera2ProcedureId==Guid.Empty)
+                                {
+                                    //获取固定向上相机1的流程
+                                    var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
+                                    if (process == null)
+                                    {
+                                        SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera1ProcedureId}", MessageLevel.Alarm);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
+                                        return;
+                                    }
+                                    // 执行视觉任务
+                                    var _cts = new CancellationTokenSource();
+                                    var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition .X, currentPosition .Y, currentPosition .U}, _cts.Token);
+                                    if (visionResult.IsSucceed)
+                                    {
+                                        float toolX = (float)(visionResult.X - currentPosition.X);
+                                        float toolY = (float)(visionResult.Y - currentPosition.Y);
 
-                                DowmCameraResults[cameraIndex] = new PointF(offsetX, offsetY);
-                                await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
-                                return;
+                                        DowmCameraResults[cameraIndex] = new PointF(toolX, toolX);
+                                        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;
+                                    }
+                                }
+                                else
+                                {
+                                    //获取固定向上相机1的流程
+                                    var process1 = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
+                                    if (process1 == null)
+                                    {
+                                        SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera1ProcedureId}", MessageLevel.Alarm);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
+                                        return;
+                                    }
+                                    //获取固定向上相机2的流程
+                                    var process2 = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera2ProcedureId);
+                                    if (process2 == null)
+                                    {
+                                        SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera2ProcedureId}", MessageLevel.Alarm);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.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 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 = (tool1Y + tool2Y) / 2;
+
+                                        DowmCameraResults[cameraIndex] = new PointF(toolX, toolX);
+                                        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;
+                                    }
+
+                                }
+                            }
+                            else if (downCameraNum == 2)
+                            {
+                                //如果下相机2的流程id为空,则表示只有一个下相机
+                                if (currentProduct.FixedUpCamera2ProcedureId == Guid.Empty)
+                                {
+                                    //获取固定向上相机1的流程
+                                    //var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
+                                    //if (process == null)
+                                    //{
+                                    //    SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera1ProcedureId}", MessageLevel.Alarm);
+                                    //    await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
+                                    //    return;
+                                    //}
+                                    //// 执行视觉任务
+                                    //var _cts = new CancellationTokenSource();
+                                    //var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                    //if (visionResult.IsSucceed)
+                                    //{
+                                    //    float toolX = (float)(visionResult.X - currentPosition.X);
+                                    //    float toolY = (float)(visionResult.Y - currentPosition.Y);
+
+                                    //    DowmCameraResults[cameraIndex] = new PointF(toolX, toolX);
+
+                                    //    if (cameraIndex == downCameraNum)
+                                    //    {
+                                    //        //求取多个DowmCameraResults的中心点
+
+
+                                    //        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)2);
+                                    return;
+                                }
+                                else
+                                {
+                                    //获取固定向上相机1的流程
+                                    var process1 = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
+                                    if (process1 == null)
+                                    {
+                                        SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera1ProcedureId}", MessageLevel.Alarm);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
+                                        return;
+                                    }
+                                    //获取固定向上相机2的流程
+                                    var process2 = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera2ProcedureId);
+                                    if (process2 == null)
+                                    {
+                                        SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera2ProcedureId}", MessageLevel.Alarm);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.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 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);
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)1);
+                                        return;
+                                    }
+                                    else
+                                    {
+                                        await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
+                                        return;
+                                    }
+
+                                }
                             }
                             else
                             {
+                                //暂时没有应用场景,不支持
                                 await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
                                 return;
                             }
@@ -1135,43 +1283,43 @@ namespace TeamAAS_VP.Core
                             SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
 
                             // 获取流程
-                            var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
-                            if (process == null)
-                            {
-                                SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera1ProcedureId}", MessageLevel.Alarm);
-                                await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
-                                return;
-                            }
-
-                            // 获取机器人当前坐标
-                            var robot = _robotService.GetAllRobots().FirstOrDefault();
-                            if (robot == null)
-                            {
-                                SendTaskMessage($"未找到机器人,无法执行上相机锁附/组装拍照视觉任务", MessageLevel.Alarm);
-                                await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
-                                return;
-
-                            }
-                            var currentPosition = robot.GetRobotPos();
-
-                            // 执行视觉任务
-                            var _cts = new CancellationTokenSource();
-                            var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, null, _cts.Token);
-                            if (visionResult.IsSucceed)
-                            {
-                                //披头偏差
-                                float offsetX = (float)(visionResult.X - currentPosition.X);
-                                float offsetY = (float)(visionResult.Y - currentPosition.Y);
-
-                                DowmCameraResults[cameraIndex] = new PointF(offsetX, offsetY);
-                                await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)1);
-                                return;
-                            }
-                            else
-                            {
-                                await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
-                                return;
-                            }
+                            //var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
+                            //if (process == null)
+                            //{
+                            //    SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.FixedUpCamera1ProcedureId}", MessageLevel.Alarm);
+                            //    await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
+                            //    return;
+                            //}
+
+                            //// 获取机器人当前坐标
+                            //var robot = _robotService.GetAllRobots().FirstOrDefault();
+                            //if (robot == null)
+                            //{
+                            //    SendTaskMessage($"未找到机器人,无法执行上相机锁附/组装拍照视觉任务", MessageLevel.Alarm);
+                            //    await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
+                            //    return;
+
+                            //}
+                            //var currentPosition = robot.GetRobotPos();
+
+                            //// 执行视觉任务
+                            //var _cts = new CancellationTokenSource();
+                            //var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, null, _cts.Token);
+                            //if (visionResult.IsSucceed)
+                            //{
+                            //    //披头偏差
+                            //    float offsetX = (float)(visionResult.X - currentPosition.X);
+                            //    float offsetY = (float)(visionResult.Y - currentPosition.Y);
+
+                            //    DowmCameraResults[cameraIndex] = new PointF(offsetX, offsetY);
+                            //    await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)1);
+                            //    return;
+                            //}
+                            //else
+                            //{
+                            //    await plc.WriteNodeAsync(addressConfig.Out_ScrewTeachOk.Address, (Int16)2);
+                            //    return;
+                            //}
                         }
                         else
                         {
@@ -1189,10 +1337,96 @@ namespace TeamAAS_VP.Core
                         {
                             SendTaskMessage($"触发上相机取料拍照...", MessageLevel.Debug);
                             //相机的编号
-                            //Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPickNum.Address);
+                            Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPickNum.Address);
+                            SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
 
+                            // 获取机器人当前坐标
+                            var robot = _robotService.GetAllRobots().FirstOrDefault();
+                            if (robot == null)
+                            {
+                                SendTaskMessage($"未找到机器人,无法执行上相机锁附/组装拍照视觉任务", MessageLevel.Alarm);
+                                await plc.WriteNodeAsync(addressConfig.Out_DownCameraStatus.Address, (Int16)2);
+                                return;
 
-                            await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)1);
+                            }
+                            var currentPosition = robot.GetRobotPos();
+
+                            //如果上相机2的流程id为空,则表示只有一个下相机
+                            if (currentProduct.MoveDownCamer2PickPhotoProcedureId == Guid.Empty)
+                            {
+                                //获取移动向下相机1的流程
+                                var process = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamer1PickPhotoProcedureId);
+                                if (process == null)
+                                {
+                                    SendTaskMessage($"移动向下相机1视觉流程,流程ID:{currentProduct.MoveDownCamer1PickPhotoProcedureId}", MessageLevel.Alarm);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)2);
+                                    return;
+                                }
+                                // 执行视觉任务
+                                var _cts = new CancellationTokenSource();
+                                var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                if (visionResult.IsSucceed)
+                                {
+                                    currentProduct.PickPoints[0].X_Position = (float)visionResult.X;
+                                    currentProduct.PickPoints[0].Y_Position = (float)visionResult.Y;
+                                    //currentProduct.PickPoints[0].U_Position += (float)visionResult.U;
+                                    await currentProduct.ScrewPoints[0].WriteToPlcAddress(addressConfig.Out_Pick, plc);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)1);
+                                    return;
+                                }
+                                else
+                                {
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)2);
+                                    return;
+                                }
+                            }
+                            else
+                            {
+                                //获取固定向上相机1的流程
+                                var process1 = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamer1PickPhotoProcedureId);
+                                if (process1 == null)
+                                {
+                                    SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.MoveDownCamer1PickPhotoProcedureId}", MessageLevel.Alarm);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)2);
+                                    return;
+                                }
+                                //获取固定向上相机2的流程
+                                var process2 = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamer2PickPhotoProcedureId);
+                                if (process2 == null)
+                                {
+                                    SendTaskMessage($"固定向上相机1视觉流程,流程ID:{currentProduct.MoveDownCamer2PickPhotoProcedureId}", MessageLevel.Alarm);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.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 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 = (tool1Y + tool2Y) / 2;
+
+                                    //计算两个点的线角度
+
+                                    currentProduct.PickPoints[0].X_Position = (float)toolX;
+                                    currentProduct.PickPoints[0].Y_Position = (float)toolY;
+                                    //currentProduct.PickPoints[0].U_Position += (float)visionResult.U;
+                                    await currentProduct.ScrewPoints[0].WriteToPlcAddress(addressConfig.Out_Pick, plc);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)1);
+                                    return;
+                                }
+                                else
+                                {
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPickStatus.Address, (Int16)2);
+                                    return;
+                                }
+                            }
                         }
                         else
                         {
@@ -1213,15 +1447,6 @@ namespace TeamAAS_VP.Core
                             Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPutNum.Address);
                             SendTaskMessage($"编号:{cameraIndex}", MessageLevel.Info);
 
-                            // 获取流程
-                            var process = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCameraLockPhotoProcedureId);
-                            if (process == null)
-                            {
-                                SendTaskMessage($"未找到上相机锁附/组装拍照对应的视觉流程,流程ID:{currentProduct.MoveDownCameraLockPhotoProcedureId}", MessageLevel.Alarm);
-                                await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
-                                return;
-                            }
-
                             // 获取机器人当前坐标
                             var robot = _robotService.GetAllRobots().FirstOrDefault();
                             if (robot == null)
@@ -1233,19 +1458,73 @@ namespace TeamAAS_VP.Core
                             }
                             var currentPosition = robot.GetRobotPos();
 
-                            // 执行视觉任务
-                            var _cts = new CancellationTokenSource();
-                            var visionResult =await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X , currentPosition.Y, currentPosition.U}, _cts.Token);
-                            if (visionResult.IsSucceed)
+                            //如果上相机2的流程id为空,则表示只有一个下相机
+                            if (currentProduct.MoveDownCamera2LockPhotoProcedureId == Guid.Empty)
                             {
-                                UpCameraPutResults[cameraIndex]=new PointF((float)visionResult.X, (float)visionResult.Y);
-
-                                
-                                await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
+                                //获取移动向下相机1的流程
+                                var process = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCamera1LockPhotoProcedureId);
+                                if (process == null)
+                                {
+                                    SendTaskMessage($"移动向下相机1视觉流程,流程ID:{currentProduct.MoveDownCamera1LockPhotoProcedureId}", MessageLevel.Alarm);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                    return;
+                                }
+                                // 执行视觉任务
+                                var _cts = new CancellationTokenSource();
+                                var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token);
+                                if (visionResult.IsSucceed)
+                                {
+                                    UpCameraPutResults[cameraIndex] = new PointF((float)visionResult.X, (float)visionResult.Y);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
+                                    return;
+                                }
+                                else
+                                {
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                    return;
+                                }
                             }
                             else
                             {
-                                await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                //获取固定向上相机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 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 = (tool1Y + tool2Y) / 2;
+
+                                    UpCameraPutResults[cameraIndex] = new PointF(toolX, toolY);
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)1);
+                                    return;
+                                }
+                                else
+                                {
+                                    await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
+                                    return;
+                                }
                             }
                         }
                         else

+ 49 - 9
TeamAAS-VM/Models/Product/ProductModel.cs

@@ -166,24 +166,64 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref _FixedUpCamera2ProcedureId, value); }
         }
 
-        private Guid _FixedDownCameraProcedureId;
+        private Guid _FixedDownCamera1ProcedureId;
         /// <summary>
         /// 固定向下相机取料流程ID
         /// </summary>
-        public Guid FixedDownCameraProcedureId
+        public Guid FixedDownCamera1ProcedureId
         {
-            get { return _FixedDownCameraProcedureId; }
-            set { SetProperty(ref _FixedDownCameraProcedureId, value); }
+            get { return _FixedDownCamera1ProcedureId; }
+            set { SetProperty(ref _FixedDownCamera1ProcedureId, value); }
         }
 
-        private Guid _MoveDownCameraLockPhotoProcedureId;
+        private Guid _FixedDownCamera2ProcedureId;
         /// <summary>
-        /// 移动向下相机锁付拍照流程ID
+        /// 固定向下相机取料流程ID
+        /// </summary>
+        public Guid FixedDownCamera2ProcedureId
+        {
+            get { return _FixedDownCamera2ProcedureId; }
+            set { SetProperty(ref _FixedDownCamera2ProcedureId, value); }
+        }
+
+        private Guid _MoveDownCamera1LockPhotoProcedureId;
+        /// <summary>
+        /// 移动向下相机1锁付拍照流程ID
+        /// </summary>
+        public Guid MoveDownCamera1LockPhotoProcedureId
+        {
+            get { return _MoveDownCamera1LockPhotoProcedureId; }
+            set { SetProperty(ref _MoveDownCamera1LockPhotoProcedureId, value); }
+        }
+
+        private Guid _MoveDownCamera2LockPhotoProcedureId;
+        /// <summary>
+        /// 移动向下相机2锁付拍照流程ID
+        /// </summary>
+        public Guid MoveDownCamera2LockPhotoProcedureId
+        {
+            get { return _MoveDownCamera2LockPhotoProcedureId; }
+            set { SetProperty(ref _MoveDownCamera2LockPhotoProcedureId, value); }
+        }
+
+        private Guid _MoveDownCamer1PickPhotoProcedureId;
+        /// <summary>
+        /// 移动向下相机1取料拍照流程ID
+        /// </summary>
+        public Guid MoveDownCamer1PickPhotoProcedureId
+        {
+            get { return _MoveDownCamer1PickPhotoProcedureId; }
+            set { SetProperty(ref _MoveDownCamer1PickPhotoProcedureId, value); }
+        }
+
+        private Guid _MoveDownCamer2PickPhotoProcedureId;
+        /// <summary>
+        /// 移动向下相机2取料拍照流程ID
         /// </summary>
-        public Guid MoveDownCameraLockPhotoProcedureId
+        public Guid MoveDownCamer2PickPhotoProcedureId
         {
-            get { return _MoveDownCameraLockPhotoProcedureId; }
-            set { SetProperty(ref _MoveDownCameraLockPhotoProcedureId, value); }
+            get { return _MoveDownCamer2PickPhotoProcedureId; }
+            set { SetProperty(ref _MoveDownCamer2PickPhotoProcedureId, value); }
         }
 
         private ObservableCollection<ProductGlobalParam> _GlobalParamListCollection;

+ 92 - 16
TeamAAS-VM/ViewModels/Product/ProductParamsViewModel.cs

@@ -102,32 +102,100 @@ namespace TeamAAS_VP.ViewModels.Product
             }
         }
 
-        private ProcedureModel _FixedDownCameraProcedure;
+        private ProcedureModel _FixedDownCamera1Procedure;
         /// <summary>
-        /// 固定向下相机取料流程ID
+        /// 固定向下相机1取料流程ID
         /// </summary>
-        public ProcedureModel FixedDownCameraProcedure
+        public ProcedureModel FixedDownCamera1Procedure
         {
-            get { return _FixedDownCameraProcedure; }
-            set { SetProperty(ref _FixedDownCameraProcedure, value);
+            get { return _FixedDownCamera1Procedure; }
+            set { SetProperty(ref _FixedDownCamera1Procedure, value);
                 if (value != null)
                 {
-                    SelectProduct.FixedDownCameraProcedureId = value.Id;
+                    SelectProduct.FixedDownCamera1ProcedureId = value.Id;
                 }
             }
         }
 
-        private ProcedureModel _MoveDownCameraLockPhotoProcedure;
+        private ProcedureModel _FixedDownCamera2Procedure;
         /// <summary>
-        /// 移动向下相机锁付拍照流程ID
+        /// 固定向下相机2取料流程ID
         /// </summary>
-        public ProcedureModel MoveDownCameraLockPhotoProcedure
+        public ProcedureModel FixedDownCamera2Procedure
         {
-            get { return _MoveDownCameraLockPhotoProcedure; }
-            set { SetProperty(ref _MoveDownCameraLockPhotoProcedure, value);
+            get { return _FixedDownCamera2Procedure; }
+            set
+            {
+                SetProperty(ref _FixedDownCamera2Procedure, value);
+                if (value != null)
+                {
+                    SelectProduct.FixedDownCamera2ProcedureId = value.Id;
+                }
+            }
+        }
+
+        private ProcedureModel _MoveDownCamera1LockPhotoProcedure;
+        /// <summary>
+        /// 移动向下相机1锁付拍照流程ID
+        /// </summary>
+        public ProcedureModel MoveDownCamera1LockPhotoProcedure
+        {
+            get { return _MoveDownCamera1LockPhotoProcedure; }
+            set { SetProperty(ref _MoveDownCamera1LockPhotoProcedure, value);
+                if (value != null)
+                {
+                    SelectProduct.MoveDownCamera1LockPhotoProcedureId = value.Id;
+                }
+            }
+        }
+
+        private ProcedureModel _MoveDownCamera2LockPhotoProcedure;
+        /// <summary>
+        /// 移动向下相机2锁付拍照流程ID
+        /// </summary>
+        public ProcedureModel MoveDownCamera2LockPhotoProcedure
+        {
+            get { return _MoveDownCamera2LockPhotoProcedure; }
+            set
+            {
+                SetProperty(ref _MoveDownCamera2LockPhotoProcedure, value);
+                if (value != null)
+                {
+                    SelectProduct.MoveDownCamera2LockPhotoProcedureId = value.Id;
+                }
+            }
+        }
+
+        private ProcedureModel _MoveDownCamer1PickPhotoProcedureId;
+        /// <summary>
+        /// 移动向下相机1取料拍照流程ID
+        /// </summary>
+        public ProcedureModel MoveDownCamer1PickPhotoProcedureId
+        {
+            get { return _MoveDownCamer1PickPhotoProcedureId; }
+            set
+            {
+                SetProperty(ref _MoveDownCamer1PickPhotoProcedureId, value);
+                if (value != null)
+                {
+                    SelectProduct.MoveDownCamer1PickPhotoProcedureId = value.Id;
+                }
+            }
+        }
+
+        private ProcedureModel _MoveDownCamer2PickPhotoProcedureId;
+        /// <summary>
+        /// 移动向下相机2取料拍照流程ID
+        /// </summary>
+        public ProcedureModel MoveDownCamer2PickPhotoProcedureId
+        {
+            get { return _MoveDownCamer2PickPhotoProcedureId; }
+            set
+            {
+                SetProperty(ref _MoveDownCamer2PickPhotoProcedureId, value);
                 if (value != null)
                 {
-                    SelectProduct.MoveDownCameraLockPhotoProcedureId = value.Id;
+                    SelectProduct.MoveDownCamer2PickPhotoProcedureId = value.Id;
                 }
             }
         }
@@ -265,13 +333,21 @@ namespace TeamAAS_VP.ViewModels.Product
                 {
                     FixedUpCamera2Procedure = ProcedureModels.FirstOrDefault(p => p.Id == SelectProduct.FixedUpCamera2ProcedureId);
                 }
-                if (SelectProduct.FixedDownCameraProcedureId != Guid.Empty)
+                if (SelectProduct.FixedDownCamera1ProcedureId != Guid.Empty)
+                {
+                    FixedDownCamera1Procedure = ProcedureModels.FirstOrDefault(p => p.Id == SelectProduct.FixedDownCamera1ProcedureId);
+                }
+                if (SelectProduct.FixedDownCamera2ProcedureId != Guid.Empty)
+                {
+                    FixedDownCamera2Procedure = ProcedureModels.FirstOrDefault(p => p.Id == SelectProduct.FixedDownCamera2ProcedureId);
+                }
+                if (SelectProduct.MoveDownCamera1LockPhotoProcedureId != Guid.Empty)
                 {
-                    FixedDownCameraProcedure = ProcedureModels.FirstOrDefault(p => p.Id == SelectProduct.FixedDownCameraProcedureId);
+                    MoveDownCamera1LockPhotoProcedure = ProcedureModels.FirstOrDefault(p => p.Id == SelectProduct.MoveDownCamera1LockPhotoProcedureId);
                 }
-                if (SelectProduct.MoveDownCameraLockPhotoProcedureId != Guid.Empty)
+                if (SelectProduct.MoveDownCamera2LockPhotoProcedureId != Guid.Empty)
                 {
-                    MoveDownCameraLockPhotoProcedure = ProcedureModels.FirstOrDefault(p => p.Id == SelectProduct.MoveDownCameraLockPhotoProcedureId);
+                    MoveDownCamera2LockPhotoProcedure = ProcedureModels.FirstOrDefault(p => p.Id == SelectProduct.MoveDownCamera2LockPhotoProcedureId);
                 }
             }
             catch (Exception ex)

+ 16 - 9
TeamAAS-VM/Views/Product/PlcPointParams.xaml

@@ -198,6 +198,7 @@
                         <!--选项列表-->
                         <ListBox Height="80"
                                  DockPanel.Dock="Top"
+                                 d:SelectedIndex="0"
                                  SelectedIndex="{Binding SelectedIndex}"
                                  Style="{StaticResource MaterialDesign3.NavigationBarPrimaryListBox}">
                             <b:Interaction.Triggers>
@@ -205,6 +206,7 @@
                                     <b:InvokeCommandAction Command="{Binding SelectionChangedCommand}" />
                                 </b:EventTrigger>
                             </b:Interaction.Triggers>
+                            <!--取料拍照点位-->
                             <ListBoxItem>
                                 <ListBoxItem.Style>
                                     <Style TargetType="ListBoxItem"
@@ -217,6 +219,7 @@
                                 </ListBoxItem.Style>
                                 <TextBlock Text="取料拍照点位" />
                             </ListBoxItem>
+                            <!--取料点位-->
                             <ListBoxItem>
                                 <ListBoxItem.Style>
                                     <Style TargetType="ListBoxItem"
@@ -229,6 +232,7 @@
                                 </ListBoxItem.Style>
                                 <TextBlock Text="取料点位" />
                             </ListBoxItem>
+                            <!--下相机二次定位点位-->
                             <ListBoxItem>
                                 <ListBoxItem.Style>
                                     <Style TargetType="ListBoxItem"
@@ -241,6 +245,7 @@
                                 </ListBoxItem.Style>
                                 <TextBlock Text="下相机二次定位点位" />
                             </ListBoxItem>
+                            <!--锁附拍照点位-->
                             <ListBoxItem>
                                 <ListBoxItem.Style>
                                     <Style TargetType="ListBoxItem"
@@ -251,8 +256,9 @@
                                                 Value="CircleOutline" />
                                     </Style>
                                 </ListBoxItem.Style>
-                                <TextBlock Text="锁附拍照点位" />
+                                <TextBlock Text="产品拍照点位" />
                             </ListBoxItem>
+                            <!--锁附点位-->
                             <ListBoxItem>
                                 <ListBoxItem.Style>
                                     <Style TargetType="ListBoxItem"
@@ -263,8 +269,9 @@
                                                 Value="CircleOutline" />
                                     </Style>
                                 </ListBoxItem.Style>
-                                <TextBlock Text="附点位" />
+                                <TextBlock Text="产品贴附点位" />
                             </ListBoxItem>
+                            <!--复检点位-->
                             <ListBoxItem>
                                 <ListBoxItem.Style>
                                     <Style TargetType="ListBoxItem"
@@ -301,7 +308,7 @@
                                     MinWidth="80"
                                     materialDesign:ButtonAssist.CornerRadius="5"
                                     Command="{Binding MovePointDownCommand}" />
-                            <Button Content="CAD导入点位"
+                            <!--<Button Content="CAD导入点位"
                                     Margin="5,2"
                                     MinWidth="80"
                                     d:Visibility="Visible"
@@ -313,7 +320,7 @@
                                         <Setter Property="Visibility"
                                                 Value="Collapsed" />
                                         <Style.Triggers>
-                                            <!-- 当 SelectedIndex == 0 时显示此面板 -->
+                                            --><!-- 当 SelectedIndex == 0 时显示此面板 --><!--
                                             <DataTrigger Binding="{Binding SelectedIndex}"
                                                          Value="4">
                                                 <Setter Property="Visibility"
@@ -322,7 +329,7 @@
                                         </Style.Triggers>
                                     </Style>
                                 </Button.Style>
-                            </Button>
+                            </Button>-->
                         </StackPanel>
                         <Border BorderBrush="LightGray"
                                 BorderThickness="1"
@@ -334,7 +341,7 @@
                             <StackPanel DockPanel.Dock="Bottom"
                                         Orientation="Vertical">
                                 <!--取料拍照点位面板-->
-                                <StackPanel x:Name="AutoCorrectPickPointPanel"
+                                <!--<StackPanel x:Name="AutoCorrectPickPointPanel"
                                             Orientation="Vertical"
                                             d:Visibility="Visible">
                                     <StackPanel.Style>
@@ -342,7 +349,7 @@
                                             <Setter Property="Visibility"
                                                     Value="Collapsed" />
                                             <Style.Triggers>
-                                                <!-- 当 SelectedIndex == 0 时显示此面板 -->
+                                                --><!-- 当 SelectedIndex == 0 时显示此面板 --><!--
                                                 <DataTrigger Binding="{Binding SelectedIndex}"
                                                              Value="0">
                                                     <Setter Property="Visibility"
@@ -427,13 +434,13 @@
                                                     </DataTemplate>
                                                 </ComboBox.ItemTemplate>
                                             </ComboBox>
-                                            <Button Content="执行校准"
+                                            <Button Content="执行位置"
                                                     Margin="10,0,0,0"
                                                     materialDesign:ButtonAssist.CornerRadius="5"
                                                     Command="{Binding AutoCorrectPickPointCommand}" />
                                         </StackPanel>
                                     </ScrollViewer>
-                                </StackPanel>
+                                </StackPanel>-->
 
                                 <!--锁付拍照面板-->
                                 <StackPanel x:Name="LockCameraPanel"

+ 101 - 6
TeamAAS-VM/Views/Product/ProductParams.xaml

@@ -120,6 +120,9 @@
                         <RowDefinition Height="auto" />
                         <RowDefinition Height="auto" />
                         <RowDefinition Height="auto" />
+                        <RowDefinition Height="auto" />
+                        <RowDefinition Height="auto" />
+                        <RowDefinition Height="auto" />
                     </Grid.RowDefinitions>
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="auto" />
@@ -278,14 +281,14 @@
                             </DataTemplate>
                         </ComboBox.ItemTemplate>
                     </ComboBox>
-                    <!--固定向下相机取料流程-->
+                    <!--固定向下相机1取料流程-->
                     <TextBlock Grid.Row="3"
                                Grid.Column="0"
-                               Text="固定向下相机取料流程ID: " />
+                               Text="固定向下相机1取料流程ID: " />
                     <ComboBox Grid.Row="3"
                               Grid.Column="1"
                               ItemsSource="{Binding ProcedureModels}"
-                              SelectedItem="{Binding FixedDownCameraProcedure}"
+                              SelectedItem="{Binding FixedDownCamera1Procedure}"
                               materialDesign:TextFieldAssist.HasClearButton="True"
                               materialDesign:HintAssist.Hint="{lex:Loc 选择需要配置的流程}">
                         <ComboBox.ItemTemplate>
@@ -301,14 +304,106 @@
                             </DataTemplate>
                         </ComboBox.ItemTemplate>
                     </ComboBox>
-                    <!--移动向下相机锁付拍照流程-->
+                    <!--固定向下相机2取料流程-->
                     <TextBlock Grid.Row="4"
                                Grid.Column="0"
-                               Text="移动向下相机锁付拍照流程ID: " />
+                               Text="固定向下相机2取料流程ID: " />
                     <ComboBox Grid.Row="4"
                               Grid.Column="1"
                               ItemsSource="{Binding ProcedureModels}"
-                              SelectedItem="{Binding MoveDownCameraLockPhotoProcedure}"
+                              SelectedItem="{Binding FixedDownCamera2Procedure}"
+                              materialDesign:TextFieldAssist.HasClearButton="True"
+                              materialDesign:HintAssist.Hint="{lex:Loc 选择需要配置的流程}">
+                        <ComboBox.ItemTemplate>
+                            <DataTemplate>
+                                <StackPanel Orientation="Horizontal">
+                                    <materialDesign:PackIcon Kind="VideoOutline" />
+                                    <TextBlock Text="{Binding CameraName}"
+                                               Margin="6,0" />
+                                    <materialDesign:PackIcon Kind="ProgressWrench" />
+                                    <TextBlock Text="{Binding Name}"
+                                               Margin="6,0" />
+                                </StackPanel>
+                            </DataTemplate>
+                        </ComboBox.ItemTemplate>
+                    </ComboBox>
+                    <!--移动向下相机1锁付拍照流程-->
+                    <TextBlock Grid.Row="5"
+                               Grid.Column="0"
+                               Text="移动向下相机1锁付拍照流程ID: " />
+                    <ComboBox Grid.Row="5"
+                              Grid.Column="1"
+                              ItemsSource="{Binding ProcedureModels}"
+                              SelectedItem="{Binding MoveDownCamera1LockPhotoProcedure}"
+                              materialDesign:TextFieldAssist.HasClearButton="True"
+                              materialDesign:HintAssist.Hint="{lex:Loc 选择需要配置的流程}">
+                        <ComboBox.ItemTemplate>
+                            <DataTemplate>
+                                <StackPanel Orientation="Horizontal">
+                                    <materialDesign:PackIcon Kind="VideoOutline" />
+                                    <TextBlock Text="{Binding CameraName}"
+                                               Margin="6,0" />
+                                    <materialDesign:PackIcon Kind="ProgressWrench" />
+                                    <TextBlock Text="{Binding Name}"
+                                               Margin="6,0" />
+                                </StackPanel>
+                            </DataTemplate>
+                        </ComboBox.ItemTemplate>
+                    </ComboBox>
+                    <!--移动向下相机2锁付拍照流程-->
+                    <TextBlock Grid.Row="6"
+                               Grid.Column="0"
+                               Text="移动向下相机2锁付拍照流程ID: " />
+                    <ComboBox Grid.Row="6"
+                              Grid.Column="1"
+                              ItemsSource="{Binding ProcedureModels}"
+                              SelectedItem="{Binding MoveDownCamera2LockPhotoProcedure}"
+                              materialDesign:TextFieldAssist.HasClearButton="True"
+                              materialDesign:HintAssist.Hint="{lex:Loc 选择需要配置的流程}">
+                        <ComboBox.ItemTemplate>
+                            <DataTemplate>
+                                <StackPanel Orientation="Horizontal">
+                                    <materialDesign:PackIcon Kind="VideoOutline" />
+                                    <TextBlock Text="{Binding CameraName}"
+                                               Margin="6,0" />
+                                    <materialDesign:PackIcon Kind="ProgressWrench" />
+                                    <TextBlock Text="{Binding Name}"
+                                               Margin="6,0" />
+                                </StackPanel>
+                            </DataTemplate>
+                        </ComboBox.ItemTemplate>
+                    </ComboBox>
+                    <!--移动向下相机1取料拍照流程-->
+                    <TextBlock Grid.Row="7"
+                               Grid.Column="0"
+                               Text="移动向下相机1取料拍照流程ID: " />
+                    <ComboBox Grid.Row="7"
+                              Grid.Column="1"
+                              ItemsSource="{Binding ProcedureModels}"
+                              SelectedItem="{Binding MoveDownCamer1PickPhotoProcedureId}"
+                              materialDesign:TextFieldAssist.HasClearButton="True"
+                              materialDesign:HintAssist.Hint="{lex:Loc 选择需要配置的流程}">
+                        <ComboBox.ItemTemplate>
+                            <DataTemplate>
+                                <StackPanel Orientation="Horizontal">
+                                    <materialDesign:PackIcon Kind="VideoOutline" />
+                                    <TextBlock Text="{Binding CameraName}"
+                                               Margin="6,0" />
+                                    <materialDesign:PackIcon Kind="ProgressWrench" />
+                                    <TextBlock Text="{Binding Name}"
+                                               Margin="6,0" />
+                                </StackPanel>
+                            </DataTemplate>
+                        </ComboBox.ItemTemplate>
+                    </ComboBox>
+                    <!--移动向下相机2取料拍照流程-->
+                    <TextBlock Grid.Row="8"
+                               Grid.Column="0"
+                               Text="移动向下相机2取料拍照流程ID: " />
+                    <ComboBox Grid.Row="8"
+                              Grid.Column="1"
+                              ItemsSource="{Binding ProcedureModels}"
+                              SelectedItem="{Binding MoveDownCamer2PickPhotoProcedureId}"
                               materialDesign:TextFieldAssist.HasClearButton="True"
                               materialDesign:HintAssist.Hint="{lex:Loc 选择需要配置的流程}">
                         <ComboBox.ItemTemplate>