| | |
| | | using HalconDotNet; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.Drawing; |
| | | using System.IO; |
| | | using System.Linq; |
| | |
| | | //} |
| | | |
| | | bind.AGVStatus = TaskStatus.Available; |
| | | |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(p => p.PositionCode == bind.AGVDest); |
| | | switch (position.Description) |
| | | { |
| | | case PathPositionDefinition.LoadEmptyTray: |
| | | Robot_LoadEmptyTray(bind.Id, position); |
| | | break; |
| | | case PathPositionDefinition.LoadFullTray: |
| | | break; |
| | | case PathPositionDefinition.UnloadEmptyTray: |
| | | Robot_UnloadEmptyTraySnap(bind.Id, position); |
| | | break; |
| | | case PathPositionDefinition.UnloadFullTray: |
| | | Robot_UnloadFullTraySnap(bind.Id, position); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | throw new ProcessException("未能根据机器人信息获取绑定设备信息", null); |
| | | } |
| | | |
| | | List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | //List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | |
| | | switch (msg.Action) |
| | | { |
| | |
| | | { |
| | | RobotMsg_UnloadEmptyTray.Para2 = msg.Para2; |
| | | robot.SendMsg(RobotMsg_UnloadEmptyTray, true); |
| | | } |
| | | else |
| | | { |
| | | bind.RobotStatus = TaskStatus.Available; |
| | | } |
| | | } |
| | | else |
| | |
| | | break; |
| | | } |
| | | |
| | | if (models.Count > 0) |
| | | { |
| | | models.ForEach(model => |
| | | { |
| | | if (!bind.TaskList.Any(t => t.MethodFunc.Method.Name == model.MethodFunc.Method.Name)) |
| | | { |
| | | model.OpConfig = new AGVBindOpConfig(bind.Id); |
| | | bind.TaskList.Add(model); |
| | | } |
| | | }); |
| | | } |
| | | //if (models.Count > 0) |
| | | //{ |
| | | // models.ForEach(model => |
| | | // { |
| | | // if (!bind.TaskList.Any(t => t.MethodName == model.MethodName)) |
| | | // { |
| | | // model.OpConfig = new AGVBindOpConfig(bind.Id); |
| | | // bind.AddTask(model); |
| | | // } |
| | | // }); |
| | | //} |
| | | } |
| | | |
| | | public void QueryRobotIO() |
| | |
| | | }); |
| | | } |
| | | |
| | | private void OnBindUnitTaskInvoke(AGVBindUnit bind) |
| | | { |
| | | var task = bind.TaskList[0]; |
| | | var response = task.MethodFunc.Invoke(task.OpConfig, task.Device); |
| | | } |
| | | //private void OnBindUnitTaskInvoke(AGVTaskModel task) |
| | | //{ |
| | | // InvokeMethodDict[task.MethodName].Invoke(this, new object[] { task.OpConfig, task.Device }); |
| | | |
| | | // //var response = task.MethodFunc.Invoke(task.OpConfig, task.Device); |
| | | //} |
| | | |
| | | #region Robot监听事件 |
| | | private void AddNewTaskToBind(string robotId, List<AGVTaskModel> models) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId); |
| | | //private void AddNewTaskToBind(string robotId, List<AGVTaskModel> models) |
| | | //{ |
| | | // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId); |
| | | |
| | | if (bind == null) |
| | | { |
| | | throw new ProcessException("未能根据机器人信息获取绑定设备信息", null); |
| | | } |
| | | // if (bind == null) |
| | | // { |
| | | // throw new ProcessException("未能根据机器人信息获取绑定设备信息", null); |
| | | // } |
| | | |
| | | AddNewTaskToBind(bind, models); |
| | | } |
| | | // AddNewTaskToBind(bind, models); |
| | | //} |
| | | |
| | | private void AddNewTaskToBind(AGVBindUnit bind, List<AGVTaskModel> models) |
| | | { |
| | | if (models.Count > 0) |
| | | { |
| | | models.ForEach(model => |
| | | { |
| | | if (!bind.TaskList.Any(t => t.MethodFunc.Method.Name == model.MethodFunc.Method.Name)) |
| | | { |
| | | model.OpConfig = new AGVBindOpConfig(bind.Id); |
| | | bind.TaskList.Add(model); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | //private void AddNewTaskToBind(AGVBindUnit bind, List<AGVTaskModel> models) |
| | | //{ |
| | | // if (models.Count > 0) |
| | | // { |
| | | // models.ForEach(model => |
| | | // { |
| | | // if (!bind.TaskList.Any(t => t.MethodName == model.MethodName)) |
| | | // { |
| | | // model.OpConfig = new AGVBindOpConfig(bind.Id); |
| | | // bind.AddTask(model); |
| | | // } |
| | | // }); |
| | | // } |
| | | //} |
| | | |
| | | [ProcessMethod("", "Robot_Monitor_Alarm", "机器人监听事件-报警", true)] |
| | | public ProcessResponse Robot_Monitor_Alarm(IOperationConfig config, IDevice device) |
| | |
| | | [ProcessMethod("", "Robot_Monitor_EmptyTrayEmpty", "机器人监听事件-空Tray区域清空", true)] |
| | | public ProcessResponse Robot_Monitor_EmptyTrayEmpty(IOperationConfig config, IDevice device) |
| | | { |
| | | bool isEmptyTrayEmpty = config.InputPara[0] == 1; |
| | | bool isEmptyTrayEmpty = config.InputPara[0] == 0; |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); |
| | | if (isEmptyTrayEmpty) |
| | | { |
| | |
| | | |
| | | Task.Run(() => |
| | | { |
| | | Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadEmptyTray; |
| | | while (bind.IsEmptyTrayEmpty && bind.TaskList.Count == 0 && !bind.TaskList.Any(u => u.MethodFunc.Method.Name == action.Method.Name)) |
| | | //Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadEmptyTray; |
| | | while (bind.IsEmptyTrayEmpty && !bind.IsEmptyTrayTaskAssigned) |
| | | { |
| | | if (bind.TaskList.Count == 0) |
| | | //if (bind.TaskList.Count == 0) |
| | | if (bind.AGVStatus == TaskStatus.Available && bind.RobotStatus == TaskStatus.Available) |
| | | { |
| | | List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | models.Add(new AGVTaskModel(TaskAvailableLevel.Both, AGV_LoadEmptyTray)); |
| | | models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, AfterEmptyTrayPositionArrived)); |
| | | //List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | //models.Add(new AGVTaskModel(TaskAvailableLevel.Both, "AGV_LoadEmptyTray")); |
| | | //models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, "AfterEmptyTrayPositionArrived")); |
| | | |
| | | AddNewTaskToBind(device.Id, models); |
| | | //AddNewTaskToBind(device.Id, models); |
| | | |
| | | AGV_LoadEmptyTray(bind.Id); |
| | | bind.IsEmptyTrayTaskAssigned = true; |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | } |
| | | }); |
| | | |
| | | } |
| | | else |
| | | { |
| | | bind.IsEmptyTrayEmpty = false; |
| | | bind.IsEmptyTrayTaskAssigned = false; |
| | | } |
| | | |
| | | return new ProcessResponse(true); |
| | |
| | | |
| | | Task.Run(() => |
| | | { |
| | | Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadFullTray; |
| | | while (bind.IsFullTrayFull && !bind.TaskList.Any(u => u.MethodFunc.Method.Name == action.Method.Name)) |
| | | //Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadFullTray; |
| | | while (bind.IsFullTrayFull && !bind.IsFullTrayTaskAssigned) |
| | | { |
| | | if (bind.TaskList.Count == 0) |
| | | //if (bind.TaskList.Count == 0) |
| | | if (bind.AGVStatus == TaskStatus.Available && bind.RobotStatus == TaskStatus.Available) |
| | | { |
| | | List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | models.Add(new AGVTaskModel(TaskAvailableLevel.Both, AGV_UnloadFullTray)); |
| | | models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, Robot_UnloadFullTray)); |
| | | //List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | //models.Add(new AGVTaskModel(TaskAvailableLevel.Both, "AGV_UnloadFullTray")); |
| | | //models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, "Robot_UnloadFullTray")); |
| | | |
| | | AddNewTaskToBind(device.Id, models); |
| | | //AddNewTaskToBind(device.Id, models); |
| | | |
| | | AGV_UnloadFullTray(bind.Id); |
| | | |
| | | bind.IsFullTrayTaskAssigned = true; |
| | | } |
| | | else |
| | | { |
| | |
| | | else |
| | | { |
| | | bind.IsFullTrayFull = false; |
| | | bind.IsFullTrayTaskAssigned = false; |
| | | } |
| | | |
| | | bind.RobotIOHandle.Set(); |
| | |
| | | [ProcessMethod("", "Robot_Monitor_FullTrayEmpty", "机器人监听事件-满Tray区域清空", true)] |
| | | public ProcessResponse Robot_Monitor_FullTrayEmpty(IOperationConfig config, IDevice device) |
| | | { |
| | | bool isFullTrayEmpty = config.InputPara[0] == 1; |
| | | bool isFullTrayEmpty = config.InputPara[0] == 0; |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); |
| | | bind.IsFullTrayEmpty = isFullTrayEmpty; |
| | | |
| | |
| | | |
| | | taskAssignedList.RemoveAll(u => u.AgvId == device.Id); |
| | | |
| | | bind.TaskList.Clear(); |
| | | //bind.ClearTask(); |
| | | bind.RobotStatus = bind.AGVStatus = TaskStatus.Available; |
| | | |
| | | return new ProcessResponse(true); |
| | |
| | | #endregion |
| | | |
| | | #region 空Tray上料 |
| | | [ProcessMethod("", "AGV_LoadEmptyTray", "AGV去往空Tray上料", true)] |
| | | public ProcessResponse AGV_LoadEmptyTray(IOperationConfig config, IDevice device) |
| | | //[ProcessMethod("", "AGV_LoadEmptyTray", "AGV去往空Tray上料", true)] |
| | | //public ProcessResponse AGV_LoadEmptyTray(IOperationConfig config, IDevice device) |
| | | //{ |
| | | // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); |
| | | |
| | | // if (position == null) |
| | | // { |
| | | // throw new ProcessException("路径配置未设置空Tray上料点"); |
| | | // } |
| | | |
| | | // bind.AGVDest = position.PositionCode; |
| | | // bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | // bind.AGVStatus = TaskStatus.Running; |
| | | |
| | | // return new ProcessResponse(true); |
| | | //} |
| | | |
| | | public void AGV_LoadEmptyTray(string bindId) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); |
| | | |
| | | if (position == null) |
| | |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | [ProcessMethod("", "AfterEmptyTrayPositionArrived", "到达空Tray上料点", true)] |
| | | public ProcessResponse AfterEmptyTrayPositionArrived(IOperationConfig config, IDevice device) |
| | | //[ProcessMethod("", "AfterEmptyTrayPositionArrived", "到达空Tray上料点", true)] |
| | | //public ProcessResponse AfterEmptyTrayPositionArrived(IOperationConfig config, IDevice device) |
| | | //{ |
| | | // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); |
| | | |
| | | // if (position == null) |
| | | // { |
| | | // throw new ProcessException("路径配置未设置空Tray上料点", null); |
| | | // } |
| | | |
| | | // if (bind.AGV.CurrentPosition != position.PositionCode) |
| | | // { |
| | | // throw new ProcessException("AGV尚未到达空Tray上料点", null); |
| | | // } |
| | | |
| | | // bind.Robot.SendMsg(RobotMsgAction.Load, RobotMsgParas.EmptyTray, 0); |
| | | // bind.RobotStatus = TaskStatus.Running; |
| | | |
| | | // return new ProcessResponse(true); |
| | | //} |
| | | |
| | | public void Robot_LoadEmptyTray(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | //PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); |
| | | |
| | | if (position == null) |
| | | { |
| | |
| | | |
| | | bind.Robot.SendMsg(RobotMsgAction.Load, RobotMsgParas.EmptyTray, 0); |
| | | bind.RobotStatus = TaskStatus.Running; |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | //[ProcessMethod("", "EmptyTrayReady", "空Tray上料完成", true)] |
| | |
| | | }); |
| | | } |
| | | |
| | | CheckEmptyTrayTask(position.PositionNo); |
| | | CheckUnloadEmptyTrayTask(position.PositionNo); |
| | | } |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | private async void CheckEmptyTrayTask(int positionNo) |
| | | private async void CheckUnloadEmptyTrayTask(int positionNo) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | |
| | | |
| | | while (taskStatus.IsTaskNeed && !taskStatus.IsTaskAssgined) |
| | | { |
| | | Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadEmptyTray; |
| | | //Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadEmptyTray; |
| | | |
| | | //if (!Config.AGVBindCollection.Any(b => b.TaskList.Any(t => t.MethodFunc.Method.Name == action.Method.Name))) |
| | | //if (!Config.AGVBindCollection.Any(b => b.TaskList.Any(t => t.MethodName == "AGV_UnloadEmptyTray"))) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.UnitStatus == TaskStatus.Available); |
| | | if (bind != null) |
| | | { |
| | | var position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNo); |
| | | AGVTaskModel model_AGV = new AGVTaskModel(TaskAvailableLevel.Both, action, new AGVBindOpConfig(bind.Id, position)); |
| | | AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, Robot_UnloadEmptyTray, new AGVBindOpConfig(bind.Id)); |
| | | //AGVTaskModel model_AGV = new AGVTaskModel(TaskAvailableLevel.Both, "AGV_UnloadEmptyTray", new AGVBindOpConfig(bind.Id, position)); |
| | | //AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, "Robot_UnloadEmptyTray", new AGVBindOpConfig(bind.Id)); |
| | | |
| | | bind.TaskList.Add(model_AGV); |
| | | bind.TaskList.Add(model_Robot); |
| | | //bind.AddTask(model_AGV); |
| | | //bind.AddTask(model_Robot); |
| | | |
| | | AGV_UnloadEmptyTray(bind.Id, position); |
| | | |
| | | taskStatus.IsTaskAssgined = true; |
| | | taskStatus.AgvId = bind.AGVId; |
| | |
| | | } |
| | | |
| | | //[ProcessMethod("", "AGV_UnloadEmptyTray", "AGV去往卸载空Tray料位置", true)] |
| | | public ProcessResponse AGV_UnloadEmptyTray(IOperationConfig config, IDevice device) |
| | | public void AGV_UnloadEmptyTray(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | |
| | | PathPosition position = (config as AGVBindOpConfig).Position; |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | |
| | | if (position == null) |
| | | { |
| | |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | //[ProcessMethod("", "Robot_UnloadEmptyTray", "机器人运动至空Tray拍照位置", true)] |
| | | public ProcessResponse Robot_UnloadEmptyTray(IOperationConfig config, IDevice device) |
| | | public void Robot_UnloadEmptyTraySnap(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadEmptyTray && u.PositionCode == bind.AGV.CurrentPosition); |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | //PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadEmptyTray && u.PositionCode == bind.AGV.CurrentPosition); |
| | | |
| | | if (position == null) |
| | | { |
| | |
| | | |
| | | bind.RobotStatus = TaskStatus.Running; |
| | | bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.UnloadEmptyTraySnap, position.PositionNo); |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | //[ProcessMethod("", "Camera_UnloadEmptyTray", "相机确认空Tray卸载机器人位置调整", true)] |
| | |
| | | throw new ProcessException("AGV当前未处于空Tray下料点"); |
| | | } |
| | | |
| | | PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); |
| | | float adjust_X = 0.0f; |
| | | float adjust_Y = 0.0f; |
| | | float adjust_Angle = 0.0f; |
| | | |
| | | if (visionConfig == null) |
| | | if (Config.IsEnableVisionGuide) |
| | | { |
| | | throw new ProcessException("未配置该相机的空Tray下料点的视觉操作配置"); |
| | | } |
| | | PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); |
| | | |
| | | float x = 0; |
| | | float y = 0; |
| | | float angle = 0; |
| | | |
| | | using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_UnloadEmptyTray")) |
| | | { |
| | | string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; |
| | | if (!_halconToolDict.ContainsKey(toolPath)) |
| | | if (visionConfig == null) |
| | | { |
| | | throw new ProcessException($"未配置Camera_UnloadEmptyTray的视觉算法路径"); |
| | | throw new ProcessException("未配置该相机的空Tray下料点的视觉操作配置"); |
| | | } |
| | | |
| | | var tool = _halconToolDict[toolPath]; |
| | | tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); |
| | | tool.RunProcedure(); |
| | | float x = 0; |
| | | float y = 0; |
| | | float angle = 0; |
| | | |
| | | x = (float)tool.GetResultTuple("OUTPUT_X").D; |
| | | y = (float)tool.GetResultTuple("OUTPUT_Y").D; |
| | | angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; |
| | | using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_UnloadEmptyTray")) |
| | | { |
| | | string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; |
| | | if (!_halconToolDict.ContainsKey(toolPath)) |
| | | { |
| | | throw new ProcessException($"未配置Camera_UnloadEmptyTray的视觉算法路径"); |
| | | } |
| | | |
| | | var tool = _halconToolDict[toolPath]; |
| | | tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); |
| | | tool.RunProcedure(); |
| | | |
| | | x = (float)tool.GetResultTuple("OUTPUT_X").D; |
| | | y = (float)tool.GetResultTuple("OUTPUT_Y").D; |
| | | angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; |
| | | } |
| | | |
| | | if (x <= 0 || y <= 0) |
| | | { |
| | | throw new ProcessException("Camera_UnloadEmptyTray视觉计算获取点位不可小于0"); |
| | | } |
| | | |
| | | float dx = visionConfig.StandardPoint.X - x; |
| | | float dy = visionConfig.StandardPoint.Y - y; |
| | | |
| | | HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); |
| | | |
| | | adjust_X = (float)dx_Robot.D; |
| | | adjust_Y = (float)dy_Robot.D; |
| | | adjust_Angle = angle; |
| | | } |
| | | |
| | | if (x <= 0 || y <= 0) |
| | | { |
| | | throw new ProcessException("Camera_UnloadEmptyTray视觉计算获取点位不可小于0"); |
| | | } |
| | | |
| | | float dx = visionConfig.StandardPoint.X - x; |
| | | float dy = visionConfig.StandardPoint.Y - y; |
| | | |
| | | HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); |
| | | |
| | | //bind.Robot.SendMsg(RobotMsgAction.Unload, RobotMsgParas.EmptyTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); |
| | | RobotMsg_UnloadEmptyTray.Action = RobotMsgAction.Unload; |
| | | RobotMsg_UnloadEmptyTray.Para1 = RobotMsgParas.EmptyTray; |
| | | RobotMsg_UnloadEmptyTray.Para2 = position.PositionNo; |
| | | RobotMsg_UnloadEmptyTray.Datas = new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }.ConvertAll(s => s.ToString()).ToList(); |
| | | RobotMsg_UnloadEmptyTray.Datas = new List<float>() { adjust_X, adjust_Y, 0, adjust_Angle }.ConvertAll(s => s.ToString()).ToList(); |
| | | bind.Robot.SendMsg(RobotMsg_UnloadEmptyTray, true); |
| | | |
| | | return new ProcessResponse(true); |
| | |
| | | |
| | | while (taskStatus.IsTaskNeed && !taskStatus.IsTaskAssgined) |
| | | { |
| | | Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadFullTray; |
| | | //Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadFullTray; |
| | | |
| | | //if (!Config.AGVBindCollection.Any(b => b.TaskList.Any(t => t.MethodFunc.Method.Name == action.Method.Name))) |
| | | { |
| | |
| | | if (bind != null) |
| | | { |
| | | var position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNo); |
| | | AGVTaskModel model_AGV = new AGVTaskModel(TaskAvailableLevel.Both, action, new AGVBindOpConfig(bind.Id, position)); |
| | | AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, Robot_LoadFullTray, new AGVBindOpConfig(bind.Id)); |
| | | //AGVTaskModel model_AGV = new AGVTaskModel(TaskAvailableLevel.Both, "AGV_LoadFullTray", new AGVBindOpConfig(bind.Id, position)); |
| | | //AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, "Robot_LoadFullTray", new AGVBindOpConfig(bind.Id)); |
| | | |
| | | bind.TaskList.Add(model_AGV); |
| | | bind.TaskList.Add(model_Robot); |
| | | //bind.AddTask(model_AGV); |
| | | //bind.AddTask(model_Robot); |
| | | |
| | | AGV_LoadFullTray(bind.Id, position); |
| | | |
| | | taskStatus.IsTaskAssgined = true; |
| | | taskStatus.AgvId = bind.AGVId; |
| | |
| | | }); |
| | | } |
| | | |
| | | [ProcessMethod("", "AGV_LoadFullTray", "AGV去往满Tray上料位置", true)] |
| | | public ProcessResponse AGV_LoadFullTray(IOperationConfig config, IDevice device) |
| | | //[ProcessMethod("", "AGV_LoadFullTray", "AGV去往满Tray上料位置", true)] |
| | | public void AGV_LoadFullTray(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | |
| | | PathPosition position = (config as AGVBindOpConfig).Position; |
| | | //PathPosition position = (config as AGVBindOpConfig).Position; |
| | | |
| | | if (position == null) |
| | | { |
| | |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | |
| | | return new ProcessResponse(true); |
| | | //return new ProcessResponse(true); |
| | | } |
| | | |
| | | [ProcessMethod("", "Robot_LoadFullTray", "机器人运动至满Tray拍照位置", true)] |
| | | public ProcessResponse Robot_LoadFullTray(IOperationConfig config, IDevice device) |
| | | //[ProcessMethod("", "Robot_LoadFullTray", "机器人运动至满Tray拍照位置", true)] |
| | | //public ProcessResponse Robot_LoadFullTray(IOperationConfig config, IDevice device) |
| | | //{ |
| | | // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadFullTray && u.PositionCode == bind.AGV.CurrentPosition); |
| | | |
| | | // if (position == null) |
| | | // { |
| | | // throw new ProcessException("路径配置未设置满Tray上料点"); |
| | | // } |
| | | |
| | | // //if (bind.AGV.CurrentPosition != position.PositionCode) |
| | | // //{ |
| | | // // throw new ProcessException("AGV当前未处于满Tray上料点"); |
| | | // //} |
| | | |
| | | // bind.RobotStatus = TaskStatus.Running; |
| | | // bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LoadFullTraySnap, position.PositionNo); |
| | | |
| | | // return new ProcessResponse(true); |
| | | //} |
| | | |
| | | public void Robot_LoadFullTraySnap(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadFullTray && u.PositionCode == bind.AGV.CurrentPosition); |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | //PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadFullTray && u.PositionCode == bind.AGV.CurrentPosition); |
| | | |
| | | if (position == null) |
| | | { |
| | |
| | | |
| | | bind.RobotStatus = TaskStatus.Running; |
| | | bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LoadFullTraySnap, position.PositionNo); |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | //[ProcessMethod("", "Camera_LoadFullTray", "相机确认满Tray上料机器人位置调整", true)] |
| | |
| | | throw new ProcessException("AGV当前未处于满Tray上料点"); |
| | | } |
| | | |
| | | PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); |
| | | float adjust_X = 0.0f; |
| | | float adjust_Y = 0.0f; |
| | | float adjust_Angle = 0.0f; |
| | | |
| | | if (visionConfig == null) |
| | | if (Config.IsEnableVisionGuide) |
| | | { |
| | | throw new ProcessException("未配置该相机的满Tray上料点的视觉操作配置"); |
| | | } |
| | | PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); |
| | | |
| | | float x = 0; |
| | | float y = 0; |
| | | float angle = 0; |
| | | |
| | | using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_LoadFullTray")) |
| | | { |
| | | string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; |
| | | if (!_halconToolDict.ContainsKey(toolPath)) |
| | | if (visionConfig == null) |
| | | { |
| | | throw new ProcessException($"未配置Camera_LoadFullTray的视觉算法路径"); |
| | | throw new ProcessException("未配置该相机的满Tray上料点的视觉操作配置"); |
| | | } |
| | | |
| | | var tool = _halconToolDict[toolPath]; |
| | | tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); |
| | | tool.RunProcedure(); |
| | | float x = 0; |
| | | float y = 0; |
| | | float angle = 0; |
| | | |
| | | x = (float)tool.GetResultTuple("OUTPUT_X").D; |
| | | y = (float)tool.GetResultTuple("OUTPUT_Y").D; |
| | | angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; |
| | | using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_LoadFullTray")) |
| | | { |
| | | string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; |
| | | if (!_halconToolDict.ContainsKey(toolPath)) |
| | | { |
| | | throw new ProcessException($"未配置Camera_LoadFullTray的视觉算法路径"); |
| | | } |
| | | |
| | | var tool = _halconToolDict[toolPath]; |
| | | tool.SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_X", new HTuple() }, { "OUTPUT_Y", new HTuple() }, { "OUTPUT_Angle", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); |
| | | tool.RunProcedure(); |
| | | |
| | | x = (float)tool.GetResultTuple("OUTPUT_X").D; |
| | | y = (float)tool.GetResultTuple("OUTPUT_Y").D; |
| | | angle = (float)tool.GetResultTuple("OUTPUT_Angle").D; |
| | | } |
| | | |
| | | if (x <= 0 || y <= 0) |
| | | { |
| | | throw new ProcessException("Camera_LoadFullTray视觉计算获取点位不可小于0"); |
| | | } |
| | | |
| | | float dx = visionConfig.StandardPoint.X - x; |
| | | float dy = visionConfig.StandardPoint.Y - y; |
| | | |
| | | HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); |
| | | |
| | | adjust_X = (float)dx_Robot.D; |
| | | adjust_Y = (float)dy_Robot.D; |
| | | adjust_Angle = angle; |
| | | } |
| | | |
| | | if (x <= 0 || y <= 0) |
| | | { |
| | | throw new ProcessException("Camera_LoadFullTray视觉计算获取点位不可小于0"); |
| | | } |
| | | |
| | | float dx = visionConfig.StandardPoint.X - x; |
| | | float dy = visionConfig.StandardPoint.Y - y; |
| | | |
| | | HOperatorSet.AffineTransPoint2d(new HTuple(visionConfig.Matrix[0], visionConfig.Matrix[1], 0, visionConfig.Matrix[3], visionConfig.Matrix[4], 0), dx, dy, out HTuple dx_Robot, out HTuple dy_Robot); |
| | | |
| | | //bind.Robot.SendMsg(RobotMsgAction.Load, RobotMsgParas.FullTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); |
| | | RobotMsg_LoadFullTray.Action = RobotMsgAction.Load; |
| | | RobotMsg_LoadFullTray.Para1 = RobotMsgParas.FullTray; |
| | | RobotMsg_LoadFullTray.Para2 = position.PositionNo; |
| | | RobotMsg_LoadFullTray.Datas = new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }.ConvertAll(s => s.ToString()).ToList(); |
| | | RobotMsg_LoadFullTray.Datas = new List<float>() { adjust_X, adjust_Y, 0, adjust_Angle }.ConvertAll(s => s.ToString()).ToList(); |
| | | bind.Robot.SendMsg(RobotMsg_LoadFullTray, true); |
| | | |
| | | return new ProcessResponse(true); |
| | |
| | | #endregion |
| | | |
| | | #region 满Tray产线下料 |
| | | [ProcessMethod("", "AGV_UnloadFullTray", "AGV去往卸载满Tray料", true)] |
| | | public ProcessResponse AGV_UnloadFullTray(IOperationConfig config, IDevice device) |
| | | //[ProcessMethod("", "AGV_UnloadFullTray", "AGV去往卸载满Tray料", true)] |
| | | //public ProcessResponse AGV_UnloadFullTray(IOperationConfig config, IDevice device) |
| | | //{ |
| | | // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); |
| | | |
| | | // if (position == null) |
| | | // { |
| | | // throw new ProcessException("路径配置未设置满Tray下料点"); |
| | | // } |
| | | |
| | | // bind.AGVDest = position.PositionCode; |
| | | // bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | // bind.AGVStatus = TaskStatus.Running; |
| | | |
| | | // return new ProcessResponse(true); |
| | | //} |
| | | |
| | | public void AGV_UnloadFullTray(string bindId) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); |
| | | |
| | | if (position == null) |
| | |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | [ProcessMethod("", "Robot_UnloadFullTray", "机器人卸载满Tray", true)] |
| | | public ProcessResponse Robot_UnloadFullTray(IOperationConfig config, IDevice device) |
| | | //[ProcessMethod("", "Robot_UnloadFullTray", "机器人卸载满Tray", true)] |
| | | //public ProcessResponse Robot_UnloadFullTray(IOperationConfig config, IDevice device) |
| | | //{ |
| | | // var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | // PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); |
| | | |
| | | // if (position == null) |
| | | // { |
| | | // throw new ProcessException("路径配置未设置满Tray下料点"); |
| | | // } |
| | | |
| | | // if (bind.AGV.CurrentPosition != position.PositionCode) |
| | | // { |
| | | // throw new ProcessException("AGV当前未处于满Tray下料点"); |
| | | // } |
| | | |
| | | // bind.RobotStatus = TaskStatus.Running; |
| | | // bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LineSnap, position.PositionNo); |
| | | |
| | | // return new ProcessResponse(true); |
| | | //} |
| | | |
| | | public void Robot_UnloadFullTraySnap(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | //PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); |
| | | |
| | | if (position == null) |
| | | { |
| | |
| | | |
| | | bind.RobotStatus = TaskStatus.Running; |
| | | bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LineSnap, position.PositionNo); |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | | |
| | | //[ProcessMethod("", "Camera_UnloadFullTray", "相机操作卸载满Tray", true)] |
| | |
| | | throw new ProcessException("AGV当前未处于满Tray下料点"); |
| | | } |
| | | |
| | | PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); |
| | | |
| | | if (visionConfig == null) |
| | | { |
| | | throw new ProcessException("未配置该相机的满Tray下料点的视觉操作配置"); |
| | | } |
| | | |
| | | //float adjust_X = 0.0f; |
| | | //float adjust_Y = 0.0f; |
| | | //float adjust_Angle = 0.0f; |
| | | bool isLineReady = false; |
| | | int reTryTime = Config.LineBusyRetryTimes; |
| | | |
| | | do |
| | | if (Config.IsEnableVisionGuide) |
| | | { |
| | | using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_UnloadFullTray")) |
| | | PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId); |
| | | |
| | | if (visionConfig == null) |
| | | { |
| | | string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; |
| | | if (!_halconToolDict.ContainsKey(toolPath)) |
| | | throw new ProcessException("未配置该相机的满Tray下料点的视觉操作配置"); |
| | | } |
| | | |
| | | |
| | | int reTryTime = Config.LineBusyRetryTimes; |
| | | |
| | | do |
| | | { |
| | | using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "Camera_UnloadFullTray")) |
| | | { |
| | | throw new ProcessException($"未配置Camera_UnloadFullTray的视觉算法路径"); |
| | | string toolPath = visionConfig.CameraOpConfig.AlgorithemPath; |
| | | if (!_halconToolDict.ContainsKey(toolPath)) |
| | | { |
| | | throw new ProcessException($"未配置Camera_UnloadFullTray的视觉算法路径"); |
| | | } |
| | | |
| | | _halconToolDict[toolPath].SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_Result", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); |
| | | _halconToolDict[toolPath].RunProcedure(); |
| | | |
| | | isLineReady = _halconToolDict[toolPath].GetResultTuple("OUTPUT_Result").I == 1; |
| | | } |
| | | |
| | | _halconToolDict[toolPath].SetDictionary(new Dictionary<string, HTuple>() { { "OUTPUT_Result", new HTuple() } }, new Dictionary<string, HObject>() { { "INPUT_Image", hImage } }); |
| | | _halconToolDict[toolPath].RunProcedure(); |
| | | if (!isLineReady) |
| | | { |
| | | Thread.Sleep(Config.LineBusyWaitInterval * 1000); |
| | | reTryTime--; |
| | | } |
| | | else |
| | | { |
| | | reTryTime = 0; |
| | | } |
| | | } while (reTryTime > 0); |
| | | |
| | | isLineReady = _halconToolDict[toolPath].GetResultTuple("OUTPUT_Result").I == 1; |
| | | } |
| | | |
| | | if (!isLineReady) |
| | | { |
| | | Thread.Sleep(Config.LineBusyWaitInterval * 1000); |
| | | reTryTime--; |
| | | } |
| | | else |
| | | { |
| | | reTryTime = 0; |
| | | } |
| | | } while (reTryTime > 0); |
| | | |
| | | //if (!isLineReady) |
| | | //{ |
| | | // bind.Robot.SendMsg(RobotMsgType.Send, -1, true, RobotMsgAction.State, RobotMsgParas.LineSnap, new List<string>() { "-1" }); |
| | | // throw new ProcessException("产线忙,等待超时"); |
| | | //} |
| | | //else |
| | | //{ |
| | | // bind.Robot.SendMsg(RobotMsgType.Send, -1, true, RobotMsgAction.State, RobotMsgParas.LineSnap, new List<string>() { "1" }); |
| | | //} |
| | | //if (!isLineReady) |
| | | //{ |
| | | // bind.Robot.SendMsg(RobotMsgType.Send, -1, true, RobotMsgAction.State, RobotMsgParas.LineSnap, new List<string>() { "-1" }); |
| | | // throw new ProcessException("产线忙,等待超时"); |
| | | //} |
| | | //else |
| | | //{ |
| | | // bind.Robot.SendMsg(RobotMsgType.Send, -1, true, RobotMsgAction.State, RobotMsgParas.LineSnap, new List<string>() { "1" }); |
| | | //} |
| | | } |
| | | else |
| | | { |
| | | isLineReady = true; |
| | | } |
| | | |
| | | if (isLineReady) |
| | | { |
| | |
| | | #endregion |
| | | } |
| | | |
| | | //[Device("AGVBind", "AGVBind", EnumHelper.DeviceAttributeType.OperationConfig)] |
| | | public class AGVBindOpConfig : OperationConfigBase |
| | | { |
| | | [Category("设备信息")] |
| | | [Description("操作相关的设备编号")] |
| | | public string BindId { get; set; } |
| | | |
| | | [Category("位置信息")] |
| | | [Description("操作相关的位置")] |
| | | public PathPosition Position { get; set; } |
| | | |
| | | public AGVBindOpConfig() { } |