using A032.Process.Calibration; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using Bro.Device.AuboRobot; using HalconDotNet; using System; using System.Collections.Generic; using System.Linq; using static Bro.Common.Helper.EnumHelper; namespace A032.Process { public partial class ProcessControl { [ProcessMethod("CalibrationCollection", "RobotCalibration", "机器人9点标定", true)] public ProcessResponse RobotCalibration(IOperationConfig config, IDevice device) { CalibrationConfigCollection calibConfig = config as CalibrationConfigCollection; var bind = Config.AGVBindCollection.FirstOrDefault(u => u.CameraId == calibConfig.CameraId); if (bind == null) { throw new ProcessException("未能获取绑定设备信息"); } PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.PositionCode == calibConfig.PositionCode); if (position == null) { throw new ProcessException("未能获取正确位置信息"); } if (calibConfig.Configs.Count < 9) { throw new ProcessException("请至少配置9个标定点位"); } if (calibConfig.IsStartedFromUI) { FrmCalib9PDynamic frm = new FrmCalib9PDynamic(this, calibConfig, bind, position, CalculateMatrix); frm.ShowDialog(); } else { MultipleStepsProcess(calibConfig, bind); CalculateMatrix(calibConfig, bind, position); } return new ProcessResponse(true); } [ProcessMethod("CalibrationCollection", "StandardPointCalibration", "标准点位标定", true)] public ProcessResponse StandardPointCalibration(IOperationConfig config, IDevice device) { CalibrationConfigCollection calibConfig = config as CalibrationConfigCollection; var bind = Config.AGVBindCollection.FirstOrDefault(u => u.CameraId == calibConfig.CameraId); if (bind == null) { throw new ProcessException("未能获取绑定设备信息"); } PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.PositionCode == calibConfig.PositionCode); if (position == null) { throw new ProcessException("未能获取正确位置信息"); } if (calibConfig.Configs.Count < 1) { throw new ProcessException("请至少配置1个标定点位"); } if (calibConfig.IsStartedFromUI) { FrmCalib9PDynamic frm = new FrmCalib9PDynamic(this, calibConfig, bind, position, CalculateStandardPoint); frm.ShowDialog(); } else { MultipleStepsProcess(calibConfig, bind); CalculateStandardPoint(calibConfig, bind, position); } return new ProcessResponse(true); } public void CalculateMatrix(CalibrationConfigCollection calibConfig, AGVBindUnit bind, PathPosition position) { List matrix = GetMovementMatrix(calibConfig.Configs.Select(u => u.ImageMarkPoint as CustomizedPoint).ToList(), calibConfig.Configs.Select(u => new CustomizedPoint(u.PlatPoint.X, u.PlatPoint.Y)).ToList(), out string msg); var visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.CameraId == bind.CameraId && u.PositionCode == position.PositionCode); if (visionConfig != null) { visionConfig.Matrix = new List() { matrix[0], matrix[1], 0, matrix[3], matrix[4], 0 }; } else { Config.VisionConfigCollection.Add(new PositionVisionConfig() { CameraId = bind.CameraId, PositionCode = position.PositionCode, Matrix = new List() { matrix[0], matrix[1], 0, matrix[3], matrix[4], 0 }, }); } PubSubCenter.Publish(PubTag.CalibAllDone.ToString(), "", msg, true); } /// /// 获取标定点的转换矩阵 /// /// /// protected List GetMovementMatrix(List imagePoints, List platPoints, out string msg) { HTuple uList, vList, xList, yList, matrix; ConvertPointToHTuple(imagePoints, out uList, out vList); ConvertPointToHTuple(platPoints, out xList, out yList); HOperatorSet.VectorToHomMat2d(uList, vList, xList, yList, out matrix); double sum = 0; for (int i = 0; i < imagePoints.Count; i++) { HOperatorSet.AffineTransPoint2d(matrix, imagePoints[i].X, imagePoints[i].Y, out HTuple m, out HTuple n); sum += Math.Sqrt((Math.Pow((m.D - platPoints[i].X), 2) + Math.Pow((n.D - platPoints[i].Y), 2))); } sum = sum / (double)imagePoints.Count; msg = $"标定点数量:{imagePoints.Count};单点误差:{sum.ToString()}脉冲"; return matrix.DArr.ToList(); } private void ConvertPointToHTuple(List point, out HTuple x, out HTuple y) { x = new HTuple(point.Select(p => p.X).ToArray()); y = new HTuple(point.Select(p => p.Y).ToArray()); } public void CalculateStandardPoint(CalibrationConfigCollection calibConfig, AGVBindUnit bind, PathPosition position) { CustomizedPointWithAngle markPoint = calibConfig.Configs[0].ImageMarkPoint; var visionConfig = Config.VisionConfigCollection.FirstOrDefault(u => u.CameraId == bind.CameraId && u.PositionCode == position.PositionCode); if (visionConfig != null) { visionConfig.StandardPoint = new CustomizedPointWithAngle(markPoint.X, markPoint.Y, markPoint.Angle); } else { Config.VisionConfigCollection.Add(new PositionVisionConfig() { CameraId = bind.CameraId, PositionCode = position.PositionCode, StandardPoint = new CustomizedPointWithAngle(markPoint.X, markPoint.Y, markPoint.Angle), }); } PubSubCenter.Publish(PubTag.CalibAllDone.ToString(), "", $"标定完成,标准点:{markPoint.GetDisplayText()}", true); } public void MultipleStepsProcess(CalibrationConfigCollection calibConfig, AGVBindUnit bind) { for (int i = 0; i < calibConfig.Configs.Count; i++) { SingleStepProcess(calibConfig.Configs[i], bind, i); } } public void SingleStepProcess(CalibrationConfig config, AGVBindUnit bind, int index) { bind.Robot.Move(config.PlatPoint, MoveType.AbsoluteMove, true); using (HObject hImage = CollectHImage(bind.Camera, config.CameraOpConfig, "RobotCalibration")) { var tool = _halconToolDict[config.CameraOpConfig.AlgorithemPath]; tool.InputImageDic.Clear(); tool.InputImageDic["INPUT_Image"] = hImage; tool.RunProcedure(); float x = (float)tool.GetResultTuple("OUTPUT_X").D; float y = (float)tool.GetResultTuple("OUTPUT_Y").D; float angel = (float)tool.GetResultTuple("OUTPUT_Angle").D; if (x < 0 || y < 0) { throw new ProcessException("获取点位信息不正确"); } config.ImageMarkPoint = new CustomizedPointWithAngle(x, y, angel); } PubSubCenter.Publish(PubTag.CalibStepDone.ToString(), index, "", true); } } }