| | |
| | | { |
| | | public partial class ProcessControl |
| | | { |
| | | const int WAITTIME = 5000; |
| | | |
| | | Dictionary<int, int> machineFullTrayDict = new Dictionary<int, int>(); |
| | | Dictionary<int, int> machineEmptyTrayDict = new Dictionary<int, int>(); |
| | | List<TaskAssignInfo> taskAssignedList = new List<TaskAssignInfo>(); |
| | | |
| | | #region AGV事件 |
| | | private void OnAGVBatteryLvlChanged(SeerAGVDriver agv, float preBatteryLvl, float batteryLvl) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.AGVId == agv.Id); |
| | | SeerAGVInitialConfig iConfig = agv.InitialConfig as SeerAGVInitialConfig; |
| | | if (batteryLvl <= iConfig.BatteryLvlToCharge && preBatteryLvl > iConfig.BatteryLvlToCharge) |
| | | { |
| | | Task.Run(() => |
| | | { |
| | | var position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.Charge); |
| | | |
| | | if (position == null) |
| | | { |
| | | throw new ProcessException("未找到充电地点"); |
| | | } |
| | | |
| | | while (bind.UnitStatus != TaskStatus.Available) |
| | | { |
| | | if (bind.SetAGVStatus(TaskStatus.Running)) |
| | | { |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | break; |
| | | } |
| | | |
| | | Thread.Sleep(WAITTIME); |
| | | } |
| | | }); |
| | | |
| | | return; |
| | | } |
| | | |
| | | if (batteryLvl >= iConfig.BatteryLvlChargeDone && preBatteryLvl < iConfig.BatteryLvlChargeDone) |
| | | { |
| | | var position = Config.PositionCollection.FirstOrDefault(u => u.PositionCode == agv.CurrentPosition); |
| | | |
| | | if (position != null && position.Description == PathPositionDefinition.Charge) |
| | | { |
| | | bind.SetAGVStatus(TaskStatus.Available); |
| | | } |
| | | return; |
| | | } |
| | | } |
| | | |
| | | private void OnAGVTaskStatusChanged(SeerAGVDriver agv, AGVTaskStatus taskStatus) |
| | | { |
| | |
| | | // bind.RobotStatus = TaskStatus.Running; |
| | | //} |
| | | |
| | | bind.AGVStatus = TaskStatus.Available; |
| | | bind.SetAGVStatus(TaskStatus.Available); |
| | | } |
| | | } |
| | | |
| | |
| | | // bind.RobotStatus = TaskStatus.Running; |
| | | //} |
| | | |
| | | bind.AGVStatus = TaskStatus.Available; |
| | | bind.SetAGVStatus(TaskStatus.Available); |
| | | LogAsync(DateTime.Now, $"AGV到位{positionCode}", ""); |
| | | |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(p => p.PositionCode == bind.AGVDest); |
| | | switch (position.Description) |
| | | { |
| | | case PathPositionDefinition.LoadEmptyTray: |
| | | LogAsync(DateTime.Now, $"AGV完成,准备上空Tray", ""); |
| | | Robot_LoadEmptyTray(bind.Id, position); |
| | | break; |
| | | case PathPositionDefinition.LoadFullTray: |
| | | LogAsync(DateTime.Now, $"AGV完成,准备上满Tray", ""); |
| | | Robot_LoadFullTraySnap(bind.Id, position); |
| | | break; |
| | | case PathPositionDefinition.UnloadEmptyTray: |
| | | LogAsync(DateTime.Now, $"AGV完成,准备下空Tray", ""); |
| | | Robot_UnloadEmptyTraySnap(bind.Id, position); |
| | | break; |
| | | case PathPositionDefinition.UnloadFullTray: |
| | | LogAsync(DateTime.Now, $"AGV完成,准备下满Tray", ""); |
| | | Robot_UnloadFullTraySnap(bind.Id, position); |
| | | break; |
| | | default: |
| | |
| | | } |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | private void OnRobotMsgReceived(DateTime dt, AuboRobotDriver robot, RobotMsg msg) |
| | | { |
| | |
| | | |
| | | if (machineEmptyTrayDict[msg.Para2] < Config.Machine_EmptyTrayNum) |
| | | { |
| | | bind.RobotIOHandle.Reset(); |
| | | bind.RobotIOHandle.WaitOne(); |
| | | //bind.RobotIOHandle.Reset(); |
| | | //bind.RobotIOHandle.WaitOne(); |
| | | bind.Robot.MonitorHandle.WaitOne(); |
| | | //bind.Robot.IOChangedHandle.WaitOne(); |
| | | Thread.Sleep((bind.Robot.InitialConfig as AuboRobotInitialConfig).ScanInterval); |
| | | |
| | | if (!bind.IsFullTrayFull) |
| | | { |
| | |
| | | { |
| | | bind.CurrentFullTray = int.Parse(msg.Datas[1]); |
| | | |
| | | bind.RobotIOHandle.Reset(); |
| | | bind.RobotIOHandle.WaitOne(); |
| | | //bind.RobotIOHandle.Reset(); |
| | | //bind.RobotIOHandle.WaitOne(); |
| | | bind.Robot.MonitorHandle.WaitOne(); |
| | | //bind.Robot.IOChangedHandle.WaitOne(); |
| | | Thread.Sleep((bind.Robot.InitialConfig as AuboRobotInitialConfig).ScanInterval); |
| | | |
| | | if (!bind.IsFullTrayEmpty) |
| | | { |
| | | Camera_UnloadFullTray(robot.Id, msg.Para2); |
| | | } |
| | | else |
| | | { |
| | | bind.RobotStatus = TaskStatus.Available; |
| | | } |
| | | } |
| | | break; |
| | |
| | | break; |
| | | case RobotMsgAction.Calibration: |
| | | { |
| | | _calibReply.CalibIndex = int.Parse(msg.Datas[4]); |
| | | _calibReply.CalibPositionNo = msg.Para2; |
| | | _calibReply.RobotPosition = new CustomizedPoint(float.Parse(msg.Datas[0]), float.Parse(msg.Datas[1])); |
| | | |
| | | _calibReply.CalibHandle.Set(); |
| | | } |
| | | break; |
| | | case RobotMsgAction.StandardPoint: |
| | | { |
| | | |
| | | _calibReply.CalibPositionNo = msg.Para2; |
| | | _calibReply.CalibHandle.Set(); |
| | | } |
| | | break; |
| | | default: |
| | |
| | | while (bind.IsEmptyTrayEmpty && !bind.IsEmptyTrayTaskAssigned) |
| | | { |
| | | //if (bind.TaskList.Count == 0) |
| | | if (bind.AGVStatus == TaskStatus.Available && bind.RobotStatus == TaskStatus.Available) |
| | | if (bind.UnitStatus == TaskStatus.Available) |
| | | { |
| | | //List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | //models.Add(new AGVTaskModel(TaskAvailableLevel.Both, "AGV_LoadEmptyTray")); |
| | |
| | | |
| | | //AddNewTaskToBind(device.Id, models); |
| | | |
| | | AGV_LoadEmptyTray(bind.Id); |
| | | bind.IsEmptyTrayTaskAssigned = true; |
| | | if (AGV_LoadEmptyTray(bind.Id)) |
| | | { |
| | | bind.IsEmptyTrayTaskAssigned = true; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | Thread.Sleep(500); |
| | | Thread.Sleep(WAITTIME); |
| | | } |
| | | } |
| | | }); |
| | |
| | | [ProcessMethod("", "Robot_Monitor_FullTrayFull", "机器人监听事件-满Tray区域放满", true)] |
| | | public ProcessResponse Robot_Monitor_FullTrayFull(IOperationConfig config, IDevice device) |
| | | { |
| | | //(device as AuboRobotDriver).IOChangedHandle.Reset(); |
| | | bool isFullTrayFull = config.InputPara[0] == 1; |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); |
| | | if (isFullTrayFull) |
| | |
| | | while (bind.IsFullTrayFull && !bind.IsFullTrayTaskAssigned) |
| | | { |
| | | //if (bind.TaskList.Count == 0) |
| | | if (bind.AGVStatus == TaskStatus.Available && bind.RobotStatus == TaskStatus.Available) |
| | | if (bind.UnitStatus == TaskStatus.Available) |
| | | { |
| | | //List<AGVTaskModel> models = new List<AGVTaskModel>(); |
| | | //models.Add(new AGVTaskModel(TaskAvailableLevel.Both, "AGV_UnloadFullTray")); |
| | |
| | | |
| | | //AddNewTaskToBind(device.Id, models); |
| | | |
| | | AGV_UnloadFullTray(bind.Id); |
| | | |
| | | bind.IsFullTrayTaskAssigned = true; |
| | | if (AGV_UnloadFullTray(bind.Id)) |
| | | { |
| | | bind.IsFullTrayTaskAssigned = true; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | Thread.Sleep(500); |
| | | Thread.Sleep(WAITTIME); |
| | | } |
| | | } |
| | | }); |
| | |
| | | bind.IsFullTrayTaskAssigned = false; |
| | | } |
| | | |
| | | bind.RobotIOHandle.Set(); |
| | | //(device as AuboRobotDriver).IOChangedHandle.Set(); |
| | | |
| | | //bind.RobotIOHandle.Set(); |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | |
| | | [ProcessMethod("", "Robot_Monitor_FullTrayEmpty", "机器人监听事件-满Tray区域清空", true)] |
| | | public ProcessResponse Robot_Monitor_FullTrayEmpty(IOperationConfig config, IDevice device) |
| | | { |
| | | //(device as AuboRobotDriver).IOChangedHandle.Reset(); |
| | | bool isFullTrayEmpty = config.InputPara[0] == 0; |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id); |
| | | bind.IsFullTrayEmpty = isFullTrayEmpty; |
| | | |
| | | bind.RobotIOHandle.Set(); |
| | | //(device as AuboRobotDriver).IOChangedHandle.Set(); |
| | | //bind.RobotIOHandle.Set(); |
| | | |
| | | return new ProcessResponse(true); |
| | | } |
| | |
| | | // return new ProcessResponse(true); |
| | | //} |
| | | |
| | | public void AGV_LoadEmptyTray(string bindId) |
| | | public bool AGV_LoadEmptyTray(string bindId) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray); |
| | |
| | | throw new ProcessException("路径配置未设置空Tray上料点"); |
| | | } |
| | | |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | if (bind.SetAGVStatus(TaskStatus.Running)) |
| | | { |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | //[ProcessMethod("", "AfterEmptyTrayPositionArrived", "到达空Tray上料点", true)] |
| | |
| | | //bind.AddTask(model_AGV); |
| | | //bind.AddTask(model_Robot); |
| | | |
| | | AGV_UnloadEmptyTray(bind.Id, position); |
| | | |
| | | taskStatus.IsTaskAssgined = true; |
| | | taskStatus.AgvId = bind.AGVId; |
| | | if (AGV_UnloadEmptyTray(bind.Id, position)) |
| | | { |
| | | taskStatus.IsTaskAssgined = true; |
| | | taskStatus.AgvId = bind.AGVId; |
| | | } |
| | | } |
| | | } |
| | | |
| | | Thread.Sleep(300); |
| | | Thread.Sleep(WAITTIME); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | //[ProcessMethod("", "AGV_UnloadEmptyTray", "AGV去往卸载空Tray料位置", true)] |
| | | public void AGV_UnloadEmptyTray(string bindId, PathPosition position) |
| | | public bool AGV_UnloadEmptyTray(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | |
| | |
| | | throw new ProcessException("路径配置未设置空Tray下料点"); |
| | | } |
| | | |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | if (bind.SetAGVStatus(TaskStatus.Running)) |
| | | { |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | //[ProcessMethod("", "Robot_UnloadEmptyTray", "机器人运动至空Tray拍照位置", true)] |
| | |
| | | |
| | | adjust_X = (float)dx_Robot.D; |
| | | adjust_Y = (float)dy_Robot.D; |
| | | adjust_Angle = angle; |
| | | adjust_Angle = visionConfig.StandardPoint.Angle - angle; |
| | | } |
| | | |
| | | //bind.Robot.SendMsg(RobotMsgAction.Unload, RobotMsgParas.EmptyTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); |
| | |
| | | //bind.AddTask(model_AGV); |
| | | //bind.AddTask(model_Robot); |
| | | |
| | | AGV_LoadFullTray(bind.Id, position); |
| | | |
| | | taskStatus.IsTaskAssgined = true; |
| | | taskStatus.AgvId = bind.AGVId; |
| | | if (AGV_LoadFullTray(bind.Id, position)) |
| | | { |
| | | taskStatus.IsTaskAssgined = true; |
| | | taskStatus.AgvId = bind.AGVId; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | //[ProcessMethod("", "AGV_LoadFullTray", "AGV去往满Tray上料位置", true)] |
| | | public void AGV_LoadFullTray(string bindId, PathPosition position) |
| | | public bool AGV_LoadFullTray(string bindId, PathPosition position) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | |
| | |
| | | throw new ProcessException("路径配置未设置满Tray上料点"); |
| | | } |
| | | |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | if (bind.SetAGVStatus(TaskStatus.Running)) |
| | | { |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | //return new ProcessResponse(true); |
| | | } |
| | |
| | | |
| | | adjust_X = (float)dx_Robot.D; |
| | | adjust_Y = (float)dy_Robot.D; |
| | | adjust_Angle = angle; |
| | | adjust_Angle = visionConfig.StandardPoint.Angle - angle; |
| | | } |
| | | |
| | | //bind.Robot.SendMsg(RobotMsgAction.Load, RobotMsgParas.FullTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle }); |
| | |
| | | // return new ProcessResponse(true); |
| | | //} |
| | | |
| | | public void AGV_UnloadFullTray(string bindId) |
| | | public bool AGV_UnloadFullTray(string bindId) |
| | | { |
| | | var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId); |
| | | PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray); |
| | |
| | | throw new ProcessException("路径配置未设置满Tray下料点"); |
| | | } |
| | | |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | if (bind.SetAGVStatus(TaskStatus.Running)) |
| | | { |
| | | bind.AGVDest = position.PositionCode; |
| | | bind.AGV.TaskOrder(position.PositionCode); |
| | | |
| | | bind.AGVStatus = TaskStatus.Running; |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | //[ProcessMethod("", "Robot_UnloadFullTray", "机器人卸载满Tray", true)] |
| | |
| | | |
| | | bind.RobotStatus = TaskStatus.Running; |
| | | bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.LineSnap, position.PositionNo); |
| | | //LogAsync(DateTime.Now, "Robot运动至下满Tray拍照", ""); |
| | | } |
| | | |
| | | //[ProcessMethod("", "Camera_UnloadFullTray", "相机操作卸载满Tray", true)] |