/// <summary> /// 单目相机偏差计算 /// </summary> /// <param name="index">基准值的索引,计算结果与该基准值进行计算,需要与标定时的index一致</param> /// <param name="baseParComprehensive">拍照相机的算子参数,用于索引旋转中心的算子</param> /// <param name="result"></param> /// <returns></returns> public bool MonoCalc(int index, BaseParComprehensive baseParComprehensive, out double[] result) { result = new double[3] { 0, 0, 0 }; try { //TODO 根据产品两角,以及旋转中心和基准值计算偏差 if (!Calc(pt2MarkArray[(int)PtType_Mono.AutoMark1], pt2MarkArray[(int)PtType_Mono.AutoMark2], index, baseParComprehensive, out result)) { ShowState(string.Format("相机{0}偏差计算出错", g_NoCamera)); return(false); } FinishPhotoPLC(CameraResult.OK); ShowState(string.Format("单目相机偏差:X:{0},Y:{1},R{2}", result[0], result[1], result[2])); return(true); } catch (Exception ex) { FinishPhotoPLC(CameraResult.NG); Log.L_I.WriteError(NameClass, ex); return(false); } }
/// <summary> /// 保存多目校准的系数 /// </summary> /// <param name="noCamera_e">相机序号</param> /// <param name="index">算子序号,不是拍照位置</param> /// <param name="calib"></param> /// <returns></returns> public static bool SaveCalibMultCo(NoCamera_enum noCamera_e, int index, double[] calib) { try { BaseParComprehensive par = GetParComphensive(noCamera_e); //index 获取对应算子的所有单元格名称 List <string> nameCell_L = par.GetAllNameCellByType("多目校准"); if (nameCell_L.Count < index) { return(false); } string nameCell = nameCell_L[index - 1]; ParCalibMult parCalibMult = par.GetCellParCalibrate(nameCell) as ParCalibMult; for (int i = 0; i < calib.Length; i++) { parCalibMult.CoCalib[i] = calib[i]; } bool blSave = par.WriteXmlDoc(nameCell); if (blSave) { ShowState(string.Format("将多目校准{0}参数保存到本地成功", nameCell)); } else { ShowAlarm(string.Format("将多目校准{0}参数保存到本地失败", nameCell)); return(false); } return(true); } catch (Exception ex) { Log.L_I.WriteError("BaseDealComprehensiveResult", ex); return(false); } }
public bool CalibRotateCenter(string cellName, Point2D pt2Mark1, Point2D pt2Mark2, double rotateAngle, BaseParComprehensive parComprehensive) { try { //获取旋转中心cell BaseParCalibrate baseParComprehensive = parComprehensive.GetCellParCalibrate(cellName); //获取旋转中心算子 ParCalibRotate parCalibRotate = (ParCalibRotate)baseParComprehensive; //根据参数求旋转中心 Point2D rc = new FunCalibRotate().GetOriginPoint(rotateAngle, pt2Mark1, pt2Mark2); //把旋转中心存入算子 parCalibRotate.XRC = rc.DblValue1; parCalibRotate.YRC = rc.DblValue2; //讲计算结果写入xml parComprehensive.WriteXmlDoc(cellName); //将参数保存到结果类 new FunCalibRotate().SaveParToResult(HtResult_Cam1, parCalibRotate); //输出计算结果 string info = string.Format("相机{0}旋转中心标定完成,X:{1},Y:{2}", g_NoCamera, parCalibRotate.XRC.ToString(), parCalibRotate.YRC.ToString()); ShowState(info); return(true); } catch (Exception ex) { Log.L_I.WriteError(NameClass, ex); return(false); } }
/// <summary> /// 偏差计算,取deltaX进行角度计算 /// </summary> /// <param name="mark1">旋转起始点</param> /// <param name="mark2">旋转终止点</param> /// <param name="ratio">相机系数</param> /// <param name="disMark">mark间距</param> /// <param name="cellName">算子序号</param> /// <param name="index">对应的基准值索引</param> /// <param name="baseParComprehensive">相机综合设置算子序列</param> /// <param name="pt3Result">计算结果</param> /// <returns></returns> public static bool CalcDeviationY(Point2D mark1, Point2D mark2, double ratio, double disMark, string cellName, int index, BaseParComprehensive baseParComprehensive, out double[] pt3Result) { pt3Result = new double[3]; try { //用于计算结果的工具类 FunCalibRotate funCalibRotate = new FunCalibRotate(); //计算当前位置与标定位的角度 double deltar = GetCurAngleByY(disMark, ratio, mark1, mark2); //算上基准值的角度,本机只用到pos0/1 Point4D calibPos = CalibDataMngr.instance.CalibPos_L[index]; deltar -= calibPos.DblValue4; //计算旋转之后的mark位置,此处用第二点计算 if (!GetPtAfterRotate(mark2, -deltar, cellName, baseParComprehensive, out Point2D result)) { return(false); } pt3Result = new double[] { Math.Round((calibPos.DblValue1 - result.DblValue1) * ratio, 4), Math.Round((calibPos.DblValue2 - result.DblValue2) * ratio, 4), Math.Round(deltar, 4) }; } catch (Exception ex) { Log.L_I.WriteError(ClassName, ex); return(false); } return(true); }
//获取错误单元 string GetErrorCell(Hashtable hashtable) { try { if (hashtable == null) { return(""); } if (hashtable.Keys == null) { return(""); } foreach (string key in hashtable.Keys) { if (hashtable[key] == null) { string str = "相机" + g_NoCamera.ToString() + "处理异常:"; BaseParComprehensive baseParComprehensive = g_BaseParComprehensive.GetCellClass(key); string annotation = baseParComprehensive.Annotation; g_UCAlarm.AddInfo(str + key + ":" + annotation); g_UCStateWork.AddInfo(str + key + ":" + annotation); } } return(""); } catch (Exception ex) { Log.L_I.WriteError(NameClass, ex); return(""); } }
/// <summary> /// 计算相机的映射系数 /// </summary> /// <param name="par1">基准相机参数</param> /// <param name="index1">算子索引号</param> /// <param name="par2"></param> /// <param name="index2">算子索引号</param> /// <returns></returns> bool CalibMult_Co(BaseParComprehensive par1, int index1, BaseParComprehensive par2, int index2) { try { //第一个相机 List <string> name1_L = par1.GetAllNameCellByType("多目校准"); if (name1_L.Count < index1) { WinMsgBox.ShowMsgBox("算子个数小于序号!"); return(false); } string name1 = name1_L[index1 - 1]; ParCalibMult parCalibMult1 = par1.GetCellParCalibrate(name1) as ParCalibMult; //第二个相机 List <string> name2_L = par2.GetAllNameCellByType("多目校准"); if (name2_L.Count < index1) { WinMsgBox.ShowMsgBox("算子个数小于序号!"); return(false); } string name2 = name2_L[index1 - 1]; ParCalibMult parCalibMult2 = par2.GetCellParCalibrate(name2) as ParCalibMult; //计算系数 FunCalibMult fun = new FunCalibMult(); fun.CalCalibMult(parCalibMult1, parCalibMult2); //保存此单元格 bool blSave = par1.WriteXmlDoc(par1.NameCell); if (blSave) { ShowState(string.Format("将相机{0}参数{1}保存到本地成功", par1.NoCamera.ToString(), par1.NameCell)); } else { ShowAlarm(string.Format("将相机{0}参数{1}保存到本地失败", par1.NoCamera.ToString(), par1.NameCell)); return(false); } blSave = par2.WriteXmlDoc(par2.NameCell); if (blSave) { ShowState(string.Format("将相机{0}参数{1}保存到本地成功", par2.NoCamera.ToString(), par2.NameCell)); } else { ShowAlarm(string.Format("将相机{0}参数{1}保存到本地失败", par2.NoCamera.ToString(), par2.NameCell)); return(false); } return(true); } catch (Exception ex) { Log.L_I.WriteError(NameClass, ex); return(false); } }
/// <summary> /// 判断指定单元格结果 /// </summary> /// <param name="htResult">哈希表结果</param> /// <param name="cell_L">单元格名称</param> /// <param name="name">错误单元格名称</param> /// <returns></returns> protected bool GetErrorCell(Hashtable htResult, List <string> cell_L, out string name) { int numError = 0; name = ""; try { if (htResult == null) { return(false); } if (htResult.Keys == null) { return(false); } foreach (string key in cell_L) { if (htResult[key] == null) { string str = "相机" + g_NoCamera.ToString() + "处理异常:"; BaseParComprehensive baseParComprehensive = g_BaseParComprehensive.GetCellClass(key); string annotation = baseParComprehensive.Annotation; ShowAlarm(str + key + ":" + annotation); numError++; name += key + ","; } else { if (htResult[key] is BaseResult) { BaseResult result = htResult[key] as BaseResult; if (result.LevelError_e == LevelError_enum.Error &&//单元格错误,并且位置相同 !result.Type.Contains("模板")) { numError++; string str = string.Format("相机{0}{1}处理异常:{2}", g_NoCamera.ToString(), result.NameCell + result.Type, result.Annotation); ShowAlarm(str); } } name += key + ","; } } if (numError > 0) { return(false); } return(true); } catch (Exception ex) { Log.L_I.WriteError(NameClass, ex); return(false); } }
/// <summary> /// 获取相机综合设置参数顶层类 /// </summary> /// <param name="noCamera_e"></param> /// <returns></returns> public static BaseParComprehensive GetParComphensive(NoCamera_enum noCamera_e) { try { BaseParComprehensive par = ParComprehensive1.P_I; switch (noCamera_e) { case NoCamera_enum.Camera1: par = ParComprehensive1.P_I; break; case NoCamera_enum.Camera2: par = ParComprehensive2.P_I; break; case NoCamera_enum.Camera3: par = ParComprehensive3.P_I; break; case NoCamera_enum.Camera4: par = ParComprehensive4.P_I; break; case NoCamera_enum.Camera5: par = ParComprehensive5.P_I; break; case NoCamera_enum.Camera6: par = ParComprehensive6.P_I; break; case NoCamera_enum.Camera7: par = ParComprehensive7.P_I; break; case NoCamera_enum.Camera8: par = ParComprehensive8.P_I; break; } return(par); } catch (Exception ex) { return(null); } }
/// <summary> /// 计算偏差 /// </summary> /// <param name="mark1">单目定位中的角1</param> /// <param name="mark2">单目定位中的角2,即用于标定以及计算偏差的角</param> /// <param name="index">基准值索引</param> /// <param name="baseParComprehensive"></param> /// <param name="pt3Result"></param> /// <returns></returns> public bool Calc(Point2D mark1, Point2D mark2, int index, BaseParComprehensive baseParComprehensive, out double[] pt3Result) { //return MonocularLation.CalcDeviationY(mark1, mark2, AMP, // ModelParams.MonoGlassX, strCamera5RC, index, baseParComprehensive, out pt3Result); double r; if (!ModelParams.IfMirrior) { r = ModuleBase.GetCurAngleByY(ModelParams.MonoGlassX, AMP, mark1, mark2); } else { r = ModuleBase.GetCurAngleByY(ModelParams.MonoGlassX, AMP, mark2, mark1); } return(MonocularLation.CalcDeviationY(mark2, r, AMP, strCamera5RC, index, baseParComprehensive, out pt3Result)); }
public static bool GetPtAfterRotate(Point2D pt, double r, string cellName, BaseParComprehensive parComprehensive, out Point2D result) { result = new Point2D(); try { if (!GetRcFromPar(cellName, parComprehensive, out Point2D rc)) { return(false); } result = new FunCalibRotate().GetPoint_AfterRotation(-r / 180 * Math.PI, rc, pt); } catch (Exception ex) { Log.L_I.WriteError(ClassName, ex); return(false); } return(true); }
/// <summary> /// 判断是否存在额料 /// </summary> /// <param name="pos1"></param> /// <param name="pos2"></param> /// <param name="parComprehensive"></param> /// <returns></returns> public bool Judge(Point2D pos1, Point2D pos2, BaseParComprehensive parComprehensive) { Point2D dblMark1After = new Point2D(); Point2D dblMark2After = new Point2D(); Point2D result; try { //计算当前位置与标定位置的角度差, //此处有一个问题,当存在额料的时候,相当于mark实际距离边长,这导致计算出的角度其实有偏差,理论上额料越大,导致偏差越大 double deltar = GetCurAngle(ModelParams.confGlassY, ParCalibWorld.V_I[g_NoCamera], pos1, pos2); //计算旋转之后的mark1位置 if (!ModuleBase.GetPtAfterRotate(pos1, deltar, strRotateCalibCell1, parComprehensive, out result)) { return(false); } dblMark1After = result; //计算旋转之后的mark2位置 if (!ModuleBase.GetPtAfterRotate(pos2, deltar, strRotateCalibCell1, parComprehensive, out result)) { return(false); } dblMark2After = result; //求出旋转后两个点的实际偏差 double deltaX = (dblMark1After.DblValue1 - dblMark2After.DblValue1) * AMP; double deltaY = (dblMark1After.DblValue2 - dblMark2After.DblValue2) * AMP; //把判断标准和一次拍照统一,共用阈值 double ratioX = (Math.Abs(deltaX) + ModelParams.GlassXInPrecise) / ModelParams.GlassXInPrecise; double ratioY = (Math.Abs(deltaY) + ModelParams.GlassYInPrecise) / ModelParams.GlassYInPrecise; //判断是否有额料,是否要做额料位置的区分? if (ratioX > ModelParams.AreaMax || ratioY > ModelParams.AreaMax) { ShowState("有额料"); return(false); } return(true); } catch (Exception ex) { Log.L_I.WriteError(NameClass, ex); return(false); } }
public static bool GetRcFromPar(string cellName, BaseParComprehensive parComprehensive, out Point2D rc) { rc = new Point2D(); try { //获取单元格 BaseParCalibrate baseParComprehensive = parComprehensive.GetCellParCalibrate(cellName); //获取旋转中心算子 ParCalibRotate parCalibRotate = (ParCalibRotate)baseParComprehensive; //计算旋转之后的mark位置 rc = parCalibRotate.PointRC; } catch (Exception ex) { Log.L_I.WriteError(ClassName, ex); return(false); } return(true); }
/// <summary> /// 标定旋转中心 /// </summary> /// <param name="cellName"></param> /// <param name="baseParComprehensive"></param> /// <returns></returns> public bool CalibRC(string cellName, BaseParComprehensive baseParComprehensive) { ShowState(string.Format("开始计算旋转中心")); if (ModelParams.IfUseRealRC && !CalibRotateCenter(cellName, pt2MarkArray[(int)PtType_Mono.R180Mark2], pt2MarkArray[(int)PtType_Mono.RcMark2], -ModelParams.RCCalibAngle, baseParComprehensive)) { ShowState("旋转中心计算失败"); return(false); } //验证计算旋转中心时PLC控制玻璃旋转的角度是否与设定的计算角度一致 if (!VerifyRotateCenter(pt2MarkArray[(int)PtType_Mono.R180Mark1], pt2MarkArray[(int)PtType_Mono.R180Mark2], pt2MarkArray[(int)PtType_Mono.RcMark1], pt2MarkArray[(int)PtType_Mono.RcMark2], -ModelParams.RCCalibAngle, 0.2)) { ShowAlarm("旋转中心角度校验失败,标定结果可能存在偏差,请人工确认"); } ShowState(string.Format("相机{0}标定结束", g_NoCamera)); return(true); }
public bool SetRotateCenter(string cellName, Point2D rc, BaseParComprehensive parComprehensive) { //获取旋转中心cell BaseParCalibrate baseParComprehensive = parComprehensive.GetCellParCalibrate(cellName); //获取旋转中心算子 ParCalibRotate parCalibRotate = (ParCalibRotate)baseParComprehensive; //把旋转中心存入算子 parCalibRotate.XRC = rc.DblValue1; parCalibRotate.YRC = rc.DblValue2; //讲计算结果写入xml parComprehensive.WriteXmlDoc(cellName); //将参数保存到结果类 new FunCalibRotate().SaveParToResult(HtResult_Cam1, parCalibRotate); //输出计算结果 string info = string.Format("相机{0}旋转中心标定完成,X:{1},Y:{2}", g_NoCamera, parCalibRotate.XRC.ToString(), parCalibRotate.YRC.ToString()); ShowState(info); return(true); }
/// <summary> /// 获取指定相机中校准算子的引用值列表, /// </summary> /// <param name="noCamera_e">相机序号</param> /// <param name="pos">算子序号</param> /// <param name="nameType">算子名称</param> /// <returns></returns> public static List <Point2D> GetCalibCellRefValue2(NoCamera_enum noCamera_e, int pos, string nameType) { List <Point2D> p_L = new List <Point2D>(); try { BaseParComprehensive par = GetParComphensive(noCamera_e); //获取对应算子的所有单元格名称 List <string> nameCell_L = par.GetAllNameCellByType(nameType); if (nameCell_L.Count < pos) { return(null); } string nameCell = nameCell_L[pos - 1]; //校准基类 BaseParCalibrate baseParCalibrate = par.GetCellParCalibrate(nameCell); List <ResultforCalib> resultforCalib_L = baseParCalibrate.g_ParGetResultFromCell.ResultforCalib_L; if (nameType == "旋转中心变换") { resultforCalib_L = ((ParCalibRotate)baseParCalibrate).g_ParGetResultFromCellForRC.ResultforCalib_L; } for (int i = 0; i < resultforCalib_L.Count; i++) { if (resultforCalib_L[i].XResult * resultforCalib_L[i].YResult != 0) { p_L.Add(new Point2D(resultforCalib_L[i].XResult, resultforCalib_L[i].YResult)); } } return(p_L); } catch (Exception ex) { Log.L_I.WriteError("Main_EX", ex); return(null); } }