patrick
2019-12-10 1c4426810c71eead57084be8a18ade8d314dd8c4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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<double> 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<double>() { 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<double>() { matrix[0], matrix[1], 0, matrix[3], matrix[4], 0 },
                });
            }
 
            PubSubCenter.Publish(PubTag.CalibAllDone.ToString(), "", msg, true);
        }
 
        /// <summary>
        /// 获取标定点的转换矩阵
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        protected List<double> GetMovementMatrix(List<CustomizedPoint> imagePoints, List<CustomizedPoint> 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<CustomizedPoint> 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);
        }
    }
}