using Bro.Common.Base;
|
using Bro.Common.Helper;
|
using Bro.Common.Interface;
|
using Bro.Common.Model;
|
using Bro.Device.AuboRobot;
|
using Bro.Device.HikCamera;
|
using Bro.Device.SeerAGV;
|
using HalconDotNet;
|
using System;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Drawing;
|
using System.IO;
|
using System.Linq;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
|
namespace A032.Process
|
{
|
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 OnAGVBatterLvlChanged(SeerAGVDriver agv, float batterLvl)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.AGVId == agv.Id);
|
SeerAGVInitialConfig iConfig = agv.InitialConfig as SeerAGVInitialConfig;
|
if (batterLvl <= 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 (batterLvl >= iConfig.BatteryLvlChargeDone)
|
{
|
bind.SetAGVStatus(TaskStatus.Available);
|
return;
|
}
|
}
|
|
private void OnAGVTaskStatusChanged(SeerAGVDriver agv, AGVTaskStatus taskStatus)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.AGVId == agv.Id);
|
|
if (bind == null)
|
{
|
throw new ProcessException("未能根据AGV信息获取绑定设备信息", null);
|
}
|
|
if (bind.AGVDest == agv.CurrentPosition && taskStatus == AGVTaskStatus.Completed)
|
{
|
//PathPosition loadEmptyTrayPosition = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray);
|
|
//if (bind.AGVDest == loadEmptyTrayPosition.PositionCode)
|
//{
|
// bind.RobotStatus = TaskStatus.Running;
|
//}
|
|
bind.SetAGVStatus(TaskStatus.Available);
|
}
|
}
|
|
private void OnAGVPositionChanged(SeerAGVDriver agv, string positionCode)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.AGVId == agv.Id);
|
|
if (bind == null)
|
{
|
throw new ProcessException("未能根据AGV信息获取绑定设备信息", null);
|
}
|
|
if (bind.AGVDest == positionCode && agv.TaskStatus == AGVTaskStatus.Completed)
|
{
|
//PathPosition loadEmptyTrayPosition = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray);
|
|
//if (bind.AGVDest == loadEmptyTrayPosition.PositionCode)
|
//{
|
// bind.RobotStatus = TaskStatus.Running;
|
//}
|
|
bind.SetAGVStatus(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;
|
}
|
}
|
}
|
#endregion
|
|
private void OnRobotMsgReceived(DateTime dt, AuboRobotDriver robot, RobotMsg msg)
|
{
|
LogAsync(dt, robot.Name + "接收信息", msg.GetDisplayText());
|
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robot.Id);
|
|
if (bind == null)
|
{
|
throw new ProcessException("未能根据机器人信息获取绑定设备信息", null);
|
}
|
|
//List<AGVTaskModel> models = new List<AGVTaskModel>();
|
|
switch (msg.Action)
|
{
|
case RobotMsgAction.Load:
|
{
|
switch (msg.Para1)
|
{
|
case RobotMsgParas.EmptyTray:
|
{
|
bind.RobotStatus = bind.AGVStatus = TaskStatus.Available;
|
}
|
break;
|
case RobotMsgParas.FullTray:
|
{
|
machineFullTrayDict[msg.Para2]--;
|
bind.CurrentFullTray = int.Parse(msg.Datas[1]);
|
|
if (machineFullTrayDict[msg.Para2] > 0 && !bind.IsFullTrayFull)
|
{
|
RobotMsg_UnloadEmptyTray.Para2 = msg.Para2;
|
robot.SendMsg(RobotMsg_UnloadEmptyTray, true);
|
}
|
else
|
{
|
bind.RobotStatus = TaskStatus.Available;
|
}
|
}
|
break;
|
default:
|
break;
|
}
|
}
|
break;
|
case RobotMsgAction.Unload:
|
{
|
switch (msg.Para1)
|
{
|
case RobotMsgParas.EmptyTray:
|
{
|
machineEmptyTrayDict[msg.Para2]++;
|
bind.CurrentEmptyTray = int.Parse(msg.Datas[0]);
|
|
if (machineEmptyTrayDict[msg.Para2] < Config.Machine_EmptyTrayNum)
|
{
|
bind.RobotIOHandle.Reset();
|
bind.RobotIOHandle.WaitOne();
|
|
if (!bind.IsFullTrayFull)
|
{
|
RobotMsg_UnloadEmptyTray.Para2 = msg.Para2;
|
robot.SendMsg(RobotMsg_UnloadEmptyTray, true);
|
}
|
else
|
{
|
bind.RobotStatus = TaskStatus.Available;
|
}
|
}
|
else
|
{
|
bind.RobotStatus = TaskStatus.Available;
|
}
|
}
|
break;
|
case RobotMsgParas.FullTray:
|
{
|
bind.CurrentFullTray = int.Parse(msg.Datas[1]);
|
|
bind.RobotIOHandle.Reset();
|
bind.RobotIOHandle.WaitOne();
|
|
if (!bind.IsFullTrayEmpty)
|
{
|
Camera_UnloadFullTray(robot.Id, msg.Para2);
|
}
|
}
|
break;
|
default:
|
break;
|
}
|
}
|
break;
|
case RobotMsgAction.Move:
|
{
|
switch (msg.Para1)
|
{
|
case RobotMsgParas.LineSnap:
|
{
|
Camera_UnloadFullTray(robot.Id, msg.Para2);
|
}
|
break;
|
case RobotMsgParas.LoadFullTraySnap:
|
{
|
Camera_LoadFullTray(robot.Id, msg.Para2);
|
}
|
break;
|
case RobotMsgParas.UnloadEmptyTraySnap:
|
{
|
Camera_UnloadEmptyTray(robot.Id, msg.Para2);
|
}
|
break;
|
case RobotMsgParas.Home:
|
{
|
bind.RobotStatus = TaskStatus.Available;
|
}
|
break;
|
default:
|
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:
|
break;
|
}
|
|
//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()
|
{
|
RobotDict.Values.ToList().ForEach(r =>
|
{
|
r.SendMsg(RobotMsgAction.IO, RobotMsgParas.Query, 0);
|
});
|
}
|
|
//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);
|
|
// if (bind == null)
|
// {
|
// throw new ProcessException("未能根据机器人信息获取绑定设备信息", null);
|
// }
|
|
// AddNewTaskToBind(bind, models);
|
//}
|
|
//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)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id);
|
|
if (bind == null)
|
{
|
throw new ProcessException("未能根据机器人信息获取绑定设备信息", null);
|
}
|
|
bind.AGV.PauseTask();
|
bind.RobotStatus = TaskStatus.Warning;
|
|
return new ProcessResponse(true);
|
}
|
|
[ProcessMethod("", "Robot_Monitor_EmptyTrayEmpty", "机器人监听事件-空Tray区域清空", true)]
|
public ProcessResponse Robot_Monitor_EmptyTrayEmpty(IOperationConfig config, IDevice device)
|
{
|
bool isEmptyTrayEmpty = config.InputPara[0] == 0;
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id);
|
if (isEmptyTrayEmpty)
|
{
|
bind.IsEmptyTrayEmpty = true;
|
|
Task.Run(() =>
|
{
|
//Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadEmptyTray;
|
while (bind.IsEmptyTrayEmpty && !bind.IsEmptyTrayTaskAssigned)
|
{
|
//if (bind.TaskList.Count == 0)
|
if (bind.UnitStatus == TaskStatus.Available)
|
{
|
//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);
|
|
if (AGV_LoadEmptyTray(bind.Id))
|
{
|
bind.IsEmptyTrayTaskAssigned = true;
|
}
|
}
|
else
|
{
|
Thread.Sleep(WAITTIME);
|
}
|
}
|
});
|
}
|
else
|
{
|
bind.IsEmptyTrayEmpty = false;
|
bind.IsEmptyTrayTaskAssigned = false;
|
}
|
|
return new ProcessResponse(true);
|
}
|
|
[ProcessMethod("", "Robot_Monitor_FullTrayFull", "机器人监听事件-满Tray区域放满", true)]
|
public ProcessResponse Robot_Monitor_FullTrayFull(IOperationConfig config, IDevice device)
|
{
|
bool isFullTrayFull = config.InputPara[0] == 1;
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id);
|
if (isFullTrayFull)
|
{
|
bind.IsFullTrayFull = true;
|
|
Task.Run(() =>
|
{
|
//Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadFullTray;
|
while (bind.IsFullTrayFull && !bind.IsFullTrayTaskAssigned)
|
{
|
//if (bind.TaskList.Count == 0)
|
if (bind.UnitStatus == TaskStatus.Available)
|
{
|
//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);
|
|
if (AGV_UnloadFullTray(bind.Id))
|
{
|
bind.IsFullTrayTaskAssigned = true;
|
}
|
}
|
else
|
{
|
Thread.Sleep(WAITTIME);
|
}
|
}
|
});
|
}
|
else
|
{
|
bind.IsFullTrayFull = false;
|
bind.IsFullTrayTaskAssigned = false;
|
}
|
|
bind.RobotIOHandle.Set();
|
|
return new ProcessResponse(true);
|
}
|
|
[ProcessMethod("", "Robot_Monitor_FullTrayEmpty", "机器人监听事件-满Tray区域清空", true)]
|
public ProcessResponse Robot_Monitor_FullTrayEmpty(IOperationConfig config, IDevice device)
|
{
|
bool isFullTrayEmpty = config.InputPara[0] == 0;
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id);
|
bind.IsFullTrayEmpty = isFullTrayEmpty;
|
|
bind.RobotIOHandle.Set();
|
|
return new ProcessResponse(true);
|
}
|
|
//[ProcessMethod("", "Robot_Monitor_LoadEmptyTrayReady", "机器人监听事件-载入空Tray就绪", true)]
|
//public ProcessResponse Robot_Monitor_LoadEmptyTrayReady(IOperationConfig config, IDevice device)
|
//{
|
// var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id);
|
|
// if (bind == null)
|
// {
|
// throw new ProcessException("未能根据机器人信息获取绑定设备信息", null);
|
// }
|
|
// PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray);
|
// if (bind.AGV.CurrentPosition != position.PositionCode)
|
// {
|
// new ProcessException("上空Tray完成信号仅在上空Tray地点有效", null);
|
// return new ProcessResponse(true);
|
// }
|
|
// List<AGVTaskModel> models = new List<AGVTaskModel>();
|
// models.Add(new AGVTaskModel(TaskAvailableLevel.AGV, EmptyTrayReady));
|
// AddNewTaskToBind(bind, models);
|
|
// return new ProcessResponse(true);
|
//}
|
|
[ProcessMethod("", "Robot_Monitor_Reset", "机器人监听事件-Reset复位", true)]
|
public ProcessResponse Robot_Monitor_Reset(IOperationConfig config, IDevice device)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == device.Id);
|
|
if (bind == null)
|
{
|
throw new ProcessException("未能根据机器人信息获取绑定设备信息", null);
|
}
|
bind.AGV.CancelTask();
|
|
//isEmptyTrayTaskAssigned = false;
|
//isFullTrayTaskAssigned = false;
|
|
taskAssignedList.RemoveAll(u => u.AgvId == device.Id);
|
|
//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)
|
//{
|
// 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 bool AGV_LoadEmptyTray(string bindId)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId);
|
PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadEmptyTray);
|
|
if (position == null)
|
{
|
throw new ProcessException("路径配置未设置空Tray上料点");
|
}
|
|
if (bind.SetAGVStatus(TaskStatus.Running))
|
{
|
bind.AGVDest = position.PositionCode;
|
bind.AGV.TaskOrder(position.PositionCode);
|
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
|
//[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 == 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;
|
}
|
|
//[ProcessMethod("", "EmptyTrayReady", "空Tray上料完成", true)]
|
//public ProcessResponse EmptyTrayReady(IOperationConfig config, IDevice device)
|
//{
|
// var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == (config as AGVBindOpConfig).BindId);
|
// bind.RobotStatus = bind.AGVStatus = TaskStatus.Available;
|
|
// return new ProcessResponse(true);
|
//}
|
#endregion
|
|
#region 空Tray往机台下料
|
//bool isEmptyTrayNeed = false;
|
//bool isEmptyTrayTaskAssigned = false;
|
RobotMsg RobotMsg_UnloadEmptyTray = new RobotMsg();
|
|
[ProcessMethod("", "PLC_NoticeEmptyTray", "PLC通知需要上空Tray", true)]
|
public ProcessResponse PLC_NoticeEmptyTray(IOperationConfig config, IDevice device)
|
{
|
if (config.InputPara == null || config.InputPara.Count == 0)
|
{
|
throw new ProcessException("上空Tray方法未配置输入参数", null);
|
}
|
|
bool isEmptyTrayNeed = config.InputPara[0] == 1;
|
|
if (isEmptyTrayNeed)
|
{
|
var position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadEmptyTray && u.DeviceOwner == device.Id);
|
|
machineEmptyTrayDict[position.PositionNo] = 0;
|
|
if (!taskAssignedList.Any(u => u.PositionNo == position.PositionNo))
|
{
|
taskAssignedList.Add(new TaskAssignInfo()
|
{
|
IsTaskNeed = true,
|
IsTaskAssgined = false,
|
PositionNo = position.PositionNo,
|
});
|
}
|
|
CheckUnloadEmptyTrayTask(position.PositionNo);
|
}
|
|
return new ProcessResponse(true);
|
}
|
|
private async void CheckUnloadEmptyTrayTask(int positionNo)
|
{
|
await Task.Run(() =>
|
{
|
var taskStatus = taskAssignedList.FirstOrDefault(u => u.PositionNo == positionNo);
|
|
if (taskStatus == null)
|
return;
|
|
while (taskStatus.IsTaskNeed && !taskStatus.IsTaskAssgined)
|
{
|
//Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_UnloadEmptyTray;
|
|
//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, "AGV_UnloadEmptyTray", new AGVBindOpConfig(bind.Id, position));
|
//AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, "Robot_UnloadEmptyTray", new AGVBindOpConfig(bind.Id));
|
|
//bind.AddTask(model_AGV);
|
//bind.AddTask(model_Robot);
|
|
if (AGV_UnloadEmptyTray(bind.Id, position))
|
{
|
taskStatus.IsTaskAssgined = true;
|
taskStatus.AgvId = bind.AGVId;
|
}
|
}
|
}
|
|
Thread.Sleep(WAITTIME);
|
}
|
});
|
}
|
|
//[ProcessMethod("", "AGV_UnloadEmptyTray", "AGV去往卸载空Tray料位置", true)]
|
public bool AGV_UnloadEmptyTray(string bindId, PathPosition position)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId);
|
|
if (position == null)
|
{
|
throw new ProcessException("路径配置未设置空Tray下料点");
|
}
|
|
if (bind.SetAGVStatus(TaskStatus.Running))
|
{
|
bind.AGVDest = position.PositionCode;
|
bind.AGV.TaskOrder(position.PositionCode);
|
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
|
//[ProcessMethod("", "Robot_UnloadEmptyTray", "机器人运动至空Tray拍照位置", true)]
|
public void Robot_UnloadEmptyTraySnap(string bindId, PathPosition position)
|
{
|
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)
|
{
|
throw new ProcessException("路径配置未设置空Tray下料点");
|
}
|
|
taskAssignedList.RemoveAll(u => u.AgvId == bind.AGVId && u.PositionNo == position.PositionNo);
|
|
bind.RobotStatus = TaskStatus.Running;
|
bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.UnloadEmptyTraySnap, position.PositionNo);
|
}
|
|
//[ProcessMethod("", "Camera_UnloadEmptyTray", "相机确认空Tray卸载机器人位置调整", true)]
|
//public ProcessResponse Camera_UnloadEmptyTray(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.UnloadEmptyTray);
|
|
// if (position == null)
|
// {
|
// throw new ProcessException("路径配置未设置空Tray下料点");
|
// }
|
|
// if (bind.AGV.CurrentPosition != position.PositionCode)
|
// {
|
// 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 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))
|
// {
|
// 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);
|
|
// bind.Robot.SendMsg(RobotMsgAction.Unload, RobotMsgParas.EmptyTray, position.PositionNo, new List<float>() { (float)dx_Robot.D, (float)dy_Robot.D, angle });
|
|
// return new ProcessResponse(true);
|
//}
|
|
public ProcessResponse Camera_UnloadEmptyTray(string robotId, int positionNum)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId);
|
|
PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNum);
|
|
if (position == null)
|
{
|
throw new ProcessException("路径配置未设置空Tray下料点");
|
}
|
|
if (bind.AGV.CurrentPosition != position.PositionCode)
|
{
|
throw new ProcessException("AGV当前未处于空Tray下料点");
|
}
|
|
float adjust_X = 0.0f;
|
float adjust_Y = 0.0f;
|
float adjust_Angle = 0.0f;
|
|
if (Config.IsEnableVisionGuide)
|
{
|
PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId);
|
|
if (visionConfig == null)
|
{
|
throw new ProcessException("未配置该相机的空Tray下料点的视觉操作配置");
|
}
|
|
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))
|
{
|
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 = 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 });
|
RobotMsg_UnloadEmptyTray.Action = RobotMsgAction.Unload;
|
RobotMsg_UnloadEmptyTray.Para1 = RobotMsgParas.EmptyTray;
|
RobotMsg_UnloadEmptyTray.Para2 = position.PositionNo;
|
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);
|
}
|
#endregion
|
|
#region 从机台上满Tray
|
//bool isFullTrayNeed = false;
|
//bool isFullTrayTaskAssigned = false;
|
RobotMsg RobotMsg_LoadFullTray = new RobotMsg();
|
|
[ProcessMethod("", "PLC_NoticeFullTray", "PLC通知满Tray需要取走", true)]
|
public ProcessResponse PLC_NoticeFullTray(IOperationConfig config, IDevice device)
|
{
|
if (config.InputPara == null || config.InputPara.Count == 0)
|
{
|
throw new ProcessException("上空Tray方法未配置输入参数", null);
|
}
|
|
bool isFullTrayNeed = config.InputPara[0] == 1;
|
if (isFullTrayNeed)
|
{
|
var position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.LoadFullTray && u.DeviceOwner == device.Id);
|
|
machineFullTrayDict[position.PositionNo] = Config.Machine_FullTrayNum;
|
|
if (!taskAssignedList.Any(u => u.PositionNo == position.PositionNo))
|
{
|
taskAssignedList.Add(new TaskAssignInfo()
|
{
|
IsTaskNeed = true,
|
IsTaskAssgined = false,
|
PositionNo = position.PositionNo,
|
});
|
}
|
|
CheckFullTrayTask(position.PositionNo);
|
}
|
|
return new ProcessResponse(true);
|
}
|
|
private async void CheckFullTrayTask(int positionNo)
|
{
|
await Task.Run(() =>
|
{
|
var taskStatus = taskAssignedList.FirstOrDefault(u => u.PositionNo == positionNo);
|
|
if (taskStatus == null)
|
return;
|
|
while (taskStatus.IsTaskNeed && !taskStatus.IsTaskAssgined)
|
{
|
//Func<IOperationConfig, IDevice, ProcessResponse> action = AGV_LoadFullTray;
|
|
//if (!Config.AGVBindCollection.Any(b => b.TaskList.Any(t => t.MethodFunc.Method.Name == action.Method.Name)))
|
{
|
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, "AGV_LoadFullTray", new AGVBindOpConfig(bind.Id, position));
|
//AGVTaskModel model_Robot = new AGVTaskModel(TaskAvailableLevel.AGV, "Robot_LoadFullTray", new AGVBindOpConfig(bind.Id));
|
|
//bind.AddTask(model_AGV);
|
//bind.AddTask(model_Robot);
|
|
if (AGV_LoadFullTray(bind.Id, position))
|
{
|
taskStatus.IsTaskAssgined = true;
|
taskStatus.AgvId = bind.AGVId;
|
}
|
}
|
}
|
|
Thread.Sleep(300);
|
}
|
});
|
}
|
|
//[ProcessMethod("", "AGV_LoadFullTray", "AGV去往满Tray上料位置", true)]
|
public bool AGV_LoadFullTray(string bindId, PathPosition position)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId);
|
|
//PathPosition position = (config as AGVBindOpConfig).Position;
|
|
if (position == null)
|
{
|
throw new ProcessException("路径配置未设置满Tray上料点");
|
}
|
|
if (bind.SetAGVStatus(TaskStatus.Running))
|
{
|
bind.AGVDest = position.PositionCode;
|
bind.AGV.TaskOrder(position.PositionCode);
|
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
|
//return new ProcessResponse(true);
|
}
|
|
//[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 == 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);
|
}
|
|
//[ProcessMethod("", "Camera_LoadFullTray", "相机确认满Tray上料机器人位置调整", true)]
|
//public ProcessResponse Camera_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);
|
|
// if (position == null)
|
// {
|
// throw new ProcessException("路径配置未设置满Tray上料点");
|
// }
|
|
// if (bind.AGV.CurrentPosition != position.PositionCode)
|
// {
|
// 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 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))
|
// {
|
// 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);
|
|
// 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 ProcessResponse Camera_LoadFullTray(string robotId, int positionNum)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId);
|
|
PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == positionNum);
|
|
if (position == null)
|
{
|
throw new ProcessException("路径配置未设置满Tray上料点");
|
}
|
|
if (bind.AGV.CurrentPosition != position.PositionCode)
|
{
|
throw new ProcessException("AGV当前未处于满Tray上料点");
|
}
|
|
float adjust_X = 0.0f;
|
float adjust_Y = 0.0f;
|
float adjust_Angle = 0.0f;
|
|
if (Config.IsEnableVisionGuide)
|
{
|
PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId);
|
|
if (visionConfig == null)
|
{
|
throw new ProcessException("未配置该相机的满Tray上料点的视觉操作配置");
|
}
|
|
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))
|
{
|
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 = 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 });
|
RobotMsg_LoadFullTray.Action = RobotMsgAction.Load;
|
RobotMsg_LoadFullTray.Para1 = RobotMsgParas.FullTray;
|
RobotMsg_LoadFullTray.Para2 = position.PositionNo;
|
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)
|
//{
|
// 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 bool AGV_UnloadFullTray(string bindId)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.Id == bindId);
|
PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray);
|
|
if (position == null)
|
{
|
throw new ProcessException("路径配置未设置满Tray下料点");
|
}
|
|
if (bind.SetAGVStatus(TaskStatus.Running))
|
{
|
bind.AGVDest = position.PositionCode;
|
bind.AGV.TaskOrder(position.PositionCode);
|
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
|
//[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 == 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);
|
}
|
|
//[ProcessMethod("", "Camera_UnloadFullTray", "相机操作卸载满Tray", true)]
|
//public ProcessResponse Camera_UnloadFullTray(IOperationConfig config, IDevice device)
|
public ProcessResponse Camera_UnloadFullTray(string robotId, int positionNum)
|
{
|
var bind = Config.AGVBindCollection.FirstOrDefault(u => u.RobotId == robotId);
|
PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.Description == PathPositionDefinition.UnloadFullTray && u.PositionNo == positionNum);
|
|
if (position == null)
|
{
|
throw new ProcessException("路径配置未设置满Tray下料点");
|
}
|
|
if (bind.AGV.CurrentPosition != position.PositionCode)
|
{
|
throw new ProcessException("AGV当前未处于满Tray下料点");
|
}
|
|
//float adjust_X = 0.0f;
|
//float adjust_Y = 0.0f;
|
//float adjust_Angle = 0.0f;
|
bool isLineReady = false;
|
|
if (Config.IsEnableVisionGuide)
|
{
|
PositionVisionConfig visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.PositionCode == position.PositionCode && u.CameraId == bind.CameraId);
|
|
if (visionConfig == null)
|
{
|
throw new ProcessException("未配置该相机的满Tray下料点的视觉操作配置");
|
}
|
|
|
int reTryTime = Config.LineBusyRetryTimes;
|
|
do
|
{
|
using (HObject hImage = CollectHImage(bind.Camera, visionConfig.CameraOpConfig, "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;
|
}
|
|
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" });
|
//}
|
}
|
else
|
{
|
isLineReady = true;
|
}
|
|
if (isLineReady)
|
{
|
bind.Robot.SendMsg(RobotMsgAction.Unload, RobotMsgParas.FullTray, position.PositionNo);
|
}
|
else
|
{
|
bind.Robot.SendMsg(RobotMsgAction.Move, RobotMsgParas.Home, position.PositionNo);
|
}
|
|
return new ProcessResponse(true);
|
}
|
#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() { }
|
|
public AGVBindOpConfig(string bindId, PathPosition position = null)
|
{
|
BindId = bindId;
|
Position = position;
|
}
|
}
|
|
public class TaskAssignInfo
|
{
|
public int PositionNo { get; set; }
|
|
public bool IsTaskNeed { get; set; } = false;
|
|
public bool IsTaskAssgined { get; set; } = false;
|
|
public string AgvId { get; set; }
|
}
|
}
|