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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
using A032.Process.Calibration;
using Bro.Common.Base;
using Bro.Common.Helper;
using Bro.Common.Interface;
using Bro.Common.Model;
using HalconDotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static Bro.Common.Helper.EnumHelper;
 
namespace A032.Process
{
    public partial class ProcessControl
    {
        CalibReplyMsg _calibReply = new CalibReplyMsg();
 
        [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.PositionNo == calibConfig.PositionNo);
            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, SendMessageToRobot_Calibration, CalculateMatrix);
                frm.ShowDialog();
            }
            else
            {
                MultipleStepsProcess(calibConfig, bind, SendMessageToRobot_Calibration);
 
                CalculateMatrix(calibConfig, bind, position);
            }
 
            //for (int i = 0; i < calibConfig.Configs.Count; i++)
            //{
            //    bind.Robot.SendMsg(Bro.Device.AuboRobot.RobotMsgAction.Calibration, Bro.Device.AuboRobot.RobotMsgParas.None, calibConfig.PositionNo, new List<float>() { i + 1 });
 
            //    _calibReply.CalibHandle.WaitOne();
 
            //    if (_calibReply.CalibIndex != (i + 1) || _calibReply.CalibPositionNo != calibConfig.PositionNo)
            //    {
            //        throw new ProcessException("标定反馈的索引或位置信息不一致");
            //    }
 
            //    calibConfig.Configs[i].CurrentPlatPoint = new CustomizedPoint(_calibReply.RobotPosition.X, _calibReply.RobotPosition.Y);
 
            //    using (HObject hImage = CollectHImage(bind.Camera, calibConfig.Configs[i].CameraOpConfig, "RobotCalibration"))
            //    {
            //        var tool = _halconToolDict[calibConfig.Configs[i].CameraOpConfig.AlgorithemPath];
 
            //        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 = (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("获取点位信息不正确");
            //        }
 
            //        calibConfig.Configs[i].ImageMarkPoint = new CustomizedPointWithAngle(x, y, angel);
            //    }
            //}
 
            //HOperatorSet.VectorToHomMat2d(new HTuple(calibConfig.Configs.Select(u => u.ImageMarkPoint.X).ToArray()), new HTuple(calibConfig.Configs.Select(u => u.ImageMarkPoint.Y).ToArray()), new HTuple(calibConfig.Configs.Select(u => u.CurrentPlatPoint.X).ToArray()), new HTuple(calibConfig.Configs.Select(u => u.CurrentPlatPoint.Y).ToArray()), out HTuple matrix);
 
            //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 },
            //    });
            //}
 
            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.PositionNo == calibConfig.PositionNo);
            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, SendMessageToRobot_Standard, CalculateStandardPoint);
                frm.ShowDialog();
            }
            else
            {
                MultipleStepsProcess(calibConfig, bind, SendMessageToRobot_Standard);
 
                CalculateStandardPoint(calibConfig, bind, position);
            }
 
            //for (int i = 0; i < calibConfig.Configs.Count; i++)
            //{
            //    bind.Robot.SendMsg(Bro.Device.AuboRobot.RobotMsgAction.Calibration, Bro.Device.AuboRobot.RobotMsgParas.None, calibConfig.PositionNo, new List<float>() { i + 1 });
 
            //    _calibReply.CalibHandle.WaitOne();
 
            //    if (_calibReply.CalibPositionNo != calibConfig.PositionNo)
            //    {
            //        throw new ProcessException("标定反馈的位置信息不一致");
            //    }
 
            //    calibConfig.Configs[i].CurrentPlatPoint = new CustomizedPoint(_calibReply.RobotPosition.X, _calibReply.RobotPosition.Y);
 
            //    using (HObject hImage = CollectHImage(bind.Camera, calibConfig.Configs[i].CameraOpConfig, "RobotCalibration"))
            //    {
            //        var tool = _halconToolDict[calibConfig.Configs[i].CameraOpConfig.AlgorithemPath];
 
            //        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 = (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("获取点位信息不正确");
            //        }
 
            //        calibConfig.Configs[i].ImageMarkPoint = new CustomizedPointWithAngle(x, y, angel);
            //    }
            //}
 
            //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),
            //    });
            //}
 
            return new ProcessResponse(true);
        }
 
        public void CalculateMatrix(CalibrationConfigCollection calibConfig, AGVBindUnit bind, PathPosition position)
        {
            //HOperatorSet.VectorToHomMat2d(new HTuple(calibConfig.Configs.Select(u => u.ImageMarkPoint.X).ToArray()), new HTuple(calibConfig.Configs.Select(u => u.ImageMarkPoint.Y).ToArray()), new HTuple(calibConfig.Configs.Select(u => u.CurrentPlatPoint.X).ToArray()), new HTuple(calibConfig.Configs.Select(u => u.CurrentPlatPoint.Y).ToArray()), out HTuple matrix);
 
            List<double> matrix = GetMovementMatrix(calibConfig.Configs.Select(u => u.ImageMarkPoint as CustomizedPoint).ToList(), calibConfig.Configs.Select(u => u.CurrentPlatPoint).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)Config.LengthPulseRatio) * 100.0) / ((double)imagePoints.Count);
            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)
        {
            //var bind = Config.AGVBindCollection.FirstOrDefault(u => u.CameraId == calibConfig.CameraId);
            //if (bind == null)
            //{
            //    throw new ProcessException("未能获取绑定设备信息");
            //}
 
            //PathPosition position = Config.PositionCollection.FirstOrDefault(u => u.PositionNo == calibConfig.PositionNo);
            //if (position == null)
            //{
            //    throw new ProcessException("未能获取正确位置信息");
            //}
 
            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, Action<AGVBindUnit, int, int> sendMessageToRobot)
        {
            for (int i = 0; i < calibConfig.Configs.Count; i++)
            {
                SingleStepProcess(calibConfig.Configs[i], sendMessageToRobot, bind, calibConfig.PositionNo, i);
            }
        }
 
        public void SendMessageToRobot_Calibration(AGVBindUnit bind, int positionNo, int index)
        {
            bind.Robot.SendMsg(Bro.Device.AuboRobot.RobotMsgAction.Calibration, Bro.Device.AuboRobot.RobotMsgParas.None, positionNo, new List<float>() { index + 1 });
 
            _calibReply.CalibHandle.WaitOne();
 
            if (_calibReply.CalibIndex != (index + 1) || _calibReply.CalibPositionNo != positionNo)
            {
                throw new ProcessException("标定反馈的索引或位置信息不一致");
            }
        }
 
        public void SendMessageToRobot_Standard(AGVBindUnit bind, int positionNo, int index)
        {
            bind.Robot.SendMsg(Bro.Device.AuboRobot.RobotMsgAction.StandardPoint, Bro.Device.AuboRobot.RobotMsgParas.None, positionNo);
 
            _calibReply.CalibHandle.WaitOne();
 
            if (_calibReply.CalibPositionNo != positionNo)
            {
                throw new ProcessException("标定反馈的位置信息不一致");
            }
        }
 
        //PubSubCenter.Subscribe(PubTag.CalibStepDone.ToString(), CalibStepDone);
        //PubSubCenter.Subscribe(PubTag.CalibAllDone.ToString(), CalibAllDone);
        public void SingleStepProcess(CalibrationConfig config, Action<AGVBindUnit, int, int> sendMessageToRobot, AGVBindUnit bind, int positionNo, int index)
        {
            sendMessageToRobot.Invoke(bind, positionNo, index);
 
            config.CurrentPlatPoint = new CustomizedPoint(_calibReply.RobotPosition.X, _calibReply.RobotPosition.Y);
 
            using (HObject hImage = CollectHImage(bind.Camera, config.CameraOpConfig, "RobotCalibration"))
            {
                var tool = _halconToolDict[config.CameraOpConfig.AlgorithemPath];
 
                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 = (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);
        }
    }
 
    public class CalibReplyMsg
    {
        public AutoResetEvent CalibHandle { get; set; } = new AutoResetEvent(false);
 
        public int CalibIndex { get; set; } = 0;
 
        public int CalibPositionNo { get; set; }
 
        public CustomizedPoint RobotPosition { get; set; } = new CustomizedPoint();
    }
}