589 lines
26 KiB
C#
589 lines
26 KiB
C#
using Aurora.Api;
|
|
using AuroraLaserScanner;
|
|
using Hermes;
|
|
using MilUI;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Reactive.Disposables;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using VisionCommon;
|
|
using WeldingCommon.Alarm;
|
|
using WeldingCommon.Data;
|
|
using WeldingCommon.Settings;
|
|
|
|
namespace WeldingCommon.Sequences
|
|
{
|
|
class SeqScannerCalibration
|
|
{
|
|
static readonly Logger Log = new Logger("SeqScannerCalibration");
|
|
|
|
const string SEQ_ENTER = "[SeqScannerCalibration] SEQ_ENTER"; // inputParam 으로 받자.
|
|
const string SEQ_CHECK_INIT_CONDITION = "[SeqScannerCalibration] Check Init Condition"; // Check Init Condition
|
|
|
|
const string SEQ_CAPTURE_NEXT_POSITION = "[SeqScannerCalibration] Capture Next Position";
|
|
const string SEQ_FIND_PATTERN = "[SeqScannerCalibration] Find Pattern";
|
|
const string SEQ_DECISION_FIND_RESULT = "[SeqScannerCalibration] Decision Find Result";
|
|
const string SEQ_DECISION_CHECK_OFFSET = "[SeqScannerCalibration] Decision Check Offset";
|
|
const string SEQ_SET_VISION_POSITION = "[SeqScannerCalibration] Set Vision Position";
|
|
const string SEQ_SET_VISION_POSITION_FAILED = "[SeqScannerCalibration] Set Vision Position Failed";
|
|
const string SEQ_DECISION_CHECK_NEXT_POSITION_EXISTS = "[SeqScannerCalibration] Decision Check Next Postion Exists";
|
|
|
|
const string SEQ_SAVE_RESULT_DATA = "[SeqScannerCalibration] Save Result Data";
|
|
|
|
const string SEQ_WRITE_COMPLETION_PLC_BIT = "[SeqScannerCalibration] Write Completion PLC Bit";
|
|
const string SEQ_COMPLETE = "[SeqScannerCalibration] SEQ_COMPLETE"; // 완료
|
|
|
|
static class ContextKey
|
|
{
|
|
public const string KEY_SEQUENCE_RESULT = "KEY_SEQUENCE_RESULT_SeqScannerCalibration";
|
|
public const string KEY_SEQUENCE_START_TIME = "KEY_SEQUENCE_START_TIME_SeqScannerCalibration";
|
|
}
|
|
|
|
|
|
private SeqScannerCalibration_InitParam _InitParam;
|
|
|
|
private Scanner _Scanner;
|
|
private SystemParameter _SystemParameter;
|
|
private FieldScanParams _FieldScanParams;
|
|
|
|
private PatternResult _PatternResult;
|
|
private PatternAgentBase _PatternAgent;
|
|
private ProcPatternInfo _ProcPatternInfo;
|
|
private PatternInfo _PatternInfo;
|
|
private ICameraDisplay _CameraDisplay;
|
|
private CameraAgentBase _CameraAgent;
|
|
|
|
//private eListNo _MarkingGridScannerListNo;
|
|
//private double _JumpSpeed;
|
|
|
|
private List<PointF> _MarkingPositionList_MM; // MM 은 밀리미터 단위 인듯
|
|
|
|
private int _PositionIndex = 0;
|
|
private double _CurrentPositionX = 0;
|
|
private double _CurrentPositionY = 0;
|
|
|
|
private double _PatternOffsetX = 0;
|
|
private double _PatternOffsetY = 0;
|
|
private int _CheckOffsetCount = 0;
|
|
private int _FindPatternCount = 0;
|
|
private double _Score = 0;
|
|
private object _GrabImage;
|
|
private int _JumpSleepTime = 0;
|
|
private int _Is1stepCount;
|
|
private int _NotFoundCount;
|
|
|
|
public SequenceBuilder Builder()
|
|
{
|
|
var sb = new SequenceBuilder(1000, true);
|
|
////var sb = new SequenceBuilder(1000, false); // With log
|
|
|
|
sb.AddAction(SEQ_ENTER, Sequence_Enter);
|
|
sb.AddDecision(SEQ_CHECK_INIT_CONDITION, CheckInitCondition); //분기
|
|
|
|
sb.AddAction(SEQ_CAPTURE_NEXT_POSITION, CaptureNextPosition);
|
|
sb.AddAction(SEQ_FIND_PATTERN, FindPattern);
|
|
sb.AddDecision(SEQ_DECISION_FIND_RESULT, DecisionFindResult);
|
|
sb.AddDecision(SEQ_DECISION_CHECK_OFFSET, DecisionCheckOffset);
|
|
sb.AddAction(SEQ_SET_VISION_POSITION_FAILED, SetVisionPositionFailed);
|
|
sb.AddAction(SEQ_SET_VISION_POSITION, SetVisionPosition);
|
|
sb.AddDecision(SEQ_DECISION_CHECK_NEXT_POSITION_EXISTS, DecisionCheckNextPostionExists);
|
|
|
|
sb.AddAction(SEQ_SAVE_RESULT_DATA, SaveResultData); // 해당 공정의 정보를 기록 함.
|
|
sb.AddAction(SEQ_WRITE_COMPLETION_PLC_BIT, WriteCompletionPLCBit); // 정상적으로 종료 되면, complete bit write
|
|
sb.AddAction(SEQ_COMPLETE, Complete);
|
|
|
|
|
|
sb.Flows(sb.Init > sb[SEQ_ENTER] > sb[SEQ_CHECK_INIT_CONDITION]
|
|
> sb[SEQ_CAPTURE_NEXT_POSITION] > sb[SEQ_FIND_PATTERN]
|
|
> sb[SEQ_DECISION_FIND_RESULT] > sb[SEQ_DECISION_CHECK_OFFSET]
|
|
> sb[SEQ_SET_VISION_POSITION] > sb[SEQ_DECISION_CHECK_NEXT_POSITION_EXISTS]
|
|
> sb[SEQ_SAVE_RESULT_DATA] > sb[SEQ_WRITE_COMPLETION_PLC_BIT] > sb[SEQ_COMPLETE]);
|
|
|
|
sb.Flows(sb[SEQ_DECISION_FIND_RESULT] > sb[SEQ_SET_VISION_POSITION_FAILED] > sb[SEQ_DECISION_CHECK_NEXT_POSITION_EXISTS]);
|
|
sb.Flows(sb[SEQ_DECISION_FIND_RESULT] > sb[SEQ_FIND_PATTERN]);
|
|
|
|
sb.Flows(sb[SEQ_DECISION_CHECK_OFFSET] > sb[SEQ_SET_VISION_POSITION_FAILED] > sb[SEQ_DECISION_CHECK_NEXT_POSITION_EXISTS]);
|
|
sb.Flows(sb[SEQ_DECISION_CHECK_OFFSET] > sb[SEQ_FIND_PATTERN]);
|
|
|
|
sb.Flows(sb[SEQ_DECISION_CHECK_NEXT_POSITION_EXISTS] > sb[SEQ_CAPTURE_NEXT_POSITION]);
|
|
|
|
sb.Flows(sb[SEQ_CHECK_INIT_CONDITION] > sb[SEQ_COMPLETE] > sb.Final);
|
|
|
|
sb.OnStopped(OnStopped);
|
|
sb.OnForceError(OnForceError);
|
|
|
|
|
|
//sb.Draw("SeqScannerCalibration.pdf");
|
|
|
|
return sb;
|
|
}
|
|
|
|
private SequenceActionResult Sequence_Enter(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
Log.I("ScannerCalibration Start");
|
|
|
|
_InitParam = param.Param as SeqScannerCalibration_InitParam;
|
|
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
|
|
|
|
InitDev(context);
|
|
if (!CheckDeviceReady(context)) { //Check Device
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_ScannerCalibration_DeviceNotReady);
|
|
Log.E("The devices are not active.");
|
|
return null;
|
|
}
|
|
|
|
if (InitSequenceVariable(context) == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_ScannerCalibration_InitVariableError);
|
|
return null;
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private bool InitSequenceVariable(SequenceContext context)
|
|
{
|
|
_FieldScanParams = FieldScanParams.GetInstance();
|
|
|
|
if (_InitParam.Is1StepCalibration) {
|
|
_PositionIndex = _InitParam.SelectedRowIndex;
|
|
} else {
|
|
_PositionIndex = 0;
|
|
}
|
|
_FindPatternCount = 0;
|
|
_JumpSleepTime = 1000;
|
|
_Is1stepCount = 0;
|
|
_NotFoundCount = 0;
|
|
// Initialize MasterPos
|
|
_MarkingPositionList_MM = new List<PointF>();
|
|
float tempX = 0, tempY = 0;
|
|
float posX = 0;
|
|
float posY = 0;
|
|
|
|
for (int column = 0; column < _InitParam.ColumnCount; column++) {
|
|
tempX = _InitParam.UnitLength * ((column % _InitParam.ColumnCount) - (_InitParam.ColumnCount - 1) / 2f);
|
|
|
|
for (int row = 0; row < _InitParam.RowCount; row++) {
|
|
tempY = _InitParam.UnitLength * ((row % _InitParam.RowCount) - (_InitParam.RowCount - 1) / 2f);
|
|
|
|
posX = tempX * (float)Math.Cos(_InitParam.TiltingDegree * Math.PI / 180) - tempY * (float)Math.Sin(_InitParam.TiltingDegree * Math.PI / 180);
|
|
posY = tempX * (float)Math.Sin(_InitParam.TiltingDegree * Math.PI / 180) + tempY * (float)Math.Cos(_InitParam.TiltingDegree * Math.PI / 180);
|
|
_MarkingPositionList_MM.Add(new PointF(posX, posY));
|
|
}
|
|
}
|
|
|
|
// InitializeCameraDevice
|
|
//FovInfo는 UI 생성자를 통해 전달된 Params의 FovInfo를 사용한다.
|
|
_PatternAgent = PatternAgentManager.GetAgent(_InitParam.FovInfo);
|
|
//VisionRecipe - FovRecipes - PatternRecipe에 ProcPatternInfos를 수동으로 추가줘야 Pattern Apply시 ProcPatternInfo가 생성됨
|
|
//ProcPatternInfos는 Recipe에 1개만 등록해두고 필요 시 패턴의 apply를 변경하도록 하자
|
|
_ProcPatternInfo = VisionRecipeManager.GetProcPatternInfo(_InitParam.FovInfo, "Align1", eProcPatternId.ProcPattern1);
|
|
//ProcPatternInfo로 등록한 PatternInfo(패턴 정보)를 받아오자
|
|
_PatternInfo = _PatternAgent.GetPatternInfo(_InitParam.FovInfo, _ProcPatternInfo.PatternId);
|
|
// 패턴을 찾는 공정이 있으므로 eDisplayType을 반드시 Pattern으로 해야 한다.
|
|
_CameraDisplay = CameraDisplayManager.GetDisplay(_InitParam.FovInfo, eDisplayType.Pattern);
|
|
//카메라 에이전트 가져오기
|
|
_CameraAgent = CameraAgentManager.GetCameraAgent(_InitParam.FovInfo);
|
|
|
|
// InitGrabImageBuffer
|
|
try {
|
|
//GrabImageBuffer를 Update할 필요가 있으면 아래 코드 사용
|
|
//IpAdapter.Instance.IpEnvironment.FreeImage(_GrabImage);
|
|
_GrabImage = _CameraAgent.CloneImageBuffer();
|
|
} catch (Exception e) {
|
|
Log.E(e.Message);
|
|
}
|
|
|
|
// ClearCameraDisplay
|
|
ClearCameraDisplay();
|
|
|
|
return true;
|
|
}
|
|
|
|
public void ClearCameraDisplay()
|
|
{
|
|
if (_CameraAgent != null) {
|
|
_CameraDisplay.ClearAllGraphics();
|
|
}
|
|
}
|
|
|
|
|
|
private void InitDev(SequenceContext context)
|
|
{
|
|
//Device Init
|
|
_Scanner = context.GetLaserScanner();
|
|
}
|
|
|
|
private bool CheckDeviceReady(SequenceContext context)
|
|
{
|
|
List<string> deviceListToCheck = new List<string>() { CommonDeviceIds.Scanner };
|
|
bool isAllDeviceActivated = true;
|
|
foreach (string item in deviceListToCheck) {
|
|
if (!context.Devices[item].IsActivated) {
|
|
isAllDeviceActivated = isAllDeviceActivated && false;
|
|
}
|
|
}
|
|
|
|
return isAllDeviceActivated;
|
|
}
|
|
|
|
private bool CheckCondition()
|
|
{
|
|
if (CheckCondition_Interlock()) {
|
|
if (InitializeDeviceStatus()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool CheckCondition_Interlock()
|
|
{
|
|
// PLC, Data, IO 등 Interlock checking
|
|
return true;
|
|
}
|
|
|
|
private bool InitializeDeviceStatus()
|
|
{
|
|
// Device 의 status 를 맞추자. ScannerCalibration 는 Scanner 를 설정 한다. 초기 설정 해야 하는 값으로
|
|
_Scanner.SetJumpSpeed(_SystemParameter.FieldScanJumpSpeed);
|
|
|
|
return true;
|
|
}
|
|
|
|
private string CheckInitCondition(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (!CheckCondition()) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_ScannerCalibration_CheckInitCondition);
|
|
Log.E("Condition is not in state to start sequence.");
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, false);
|
|
return SEQ_COMPLETE;
|
|
}
|
|
|
|
var startTime = DateTime.Now;
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_START_TIME, startTime);
|
|
|
|
Log.D("DoCrossLaserShot Sequence CheckInitCondition");
|
|
return SEQ_CAPTURE_NEXT_POSITION;
|
|
}
|
|
|
|
|
|
private SequenceActionResult CaptureNextPosition(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
_CurrentPositionX = _MarkingPositionList_MM[_PositionIndex].X + _InitParam.MasterPosOffsetX;
|
|
_CurrentPositionY = _MarkingPositionList_MM[_PositionIndex].Y + _InitParam.MasterPosOffsetY;
|
|
|
|
//1.스캐너 필드 위치 이동(Jump이동)
|
|
_Scanner.JumpAbs(_CurrentPositionX, _CurrentPositionY);
|
|
Thread.Sleep(_JumpSleepTime); // 스캐너 점프 이동 후 안정화 시간 추가
|
|
|
|
Log.I(string.Format($"Move Next Position [{_CurrentPositionX},{_CurrentPositionY}]"));
|
|
|
|
_CheckOffsetCount = 0;
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult FindPattern(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
try {
|
|
if(_Is1stepCount > 5)
|
|
{
|
|
Log.I(string.Format($"Pattern Not Found. 1StepCount OverFlow"));
|
|
return null;
|
|
}
|
|
_GrabImage = DoGrab();
|
|
_PatternResult = _PatternAgent.Find(_PatternInfo, _GrabImage, _CameraDisplay);
|
|
} catch (Exception e) {
|
|
Log.E(e.Message);
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
public object DoGrab()
|
|
{
|
|
var image = _GrabImage;
|
|
_CameraAgent.GrabSync(_CameraDisplay, ref image);
|
|
_GrabImage = image;
|
|
|
|
return _GrabImage;
|
|
}
|
|
|
|
private string DecisionFindResult(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
double offsetX = 0;
|
|
double offsetY = 0;
|
|
|
|
if (_PatternResult.Status == eFoundStatus.FoundOK) {
|
|
Log.I($"PatternResult : {_PatternResult}");
|
|
_PatternAgent.Draw(_PatternInfo, _PatternResult, _CameraDisplay);
|
|
|
|
//patternResult의 X,Y 좌표값을 받아서 Image의 센터와의 차이만큼 계산하여 스캐너 구동 후 다시 매칭
|
|
var patternRsultInfo = _PatternResult.MoreInfo as FixtureResult;
|
|
offsetX = patternRsultInfo.Origin.X;
|
|
offsetY = patternRsultInfo.Origin.Y;
|
|
|
|
TranslateImageToField(offsetX, offsetY, out _PatternOffsetX, out _PatternOffsetY);
|
|
Log.I($"PatternOffsetX : {_PatternOffsetX}, PatternOffsetY : {_PatternOffsetY}");
|
|
|
|
//스캐너 구동 후 다시 한번 FindPattern후 DecisioCheckOffset으로 넘어감
|
|
if (_FindPatternCount < 1) {
|
|
_FindPatternCount++;
|
|
//_Scanner.JumpRel(patternOffsetX, patternOffsetY);
|
|
_Scanner.JumpRel(_PatternOffsetX, _PatternOffsetY);
|
|
Log.I(string.Format($"Move Rel Position [{_PatternOffsetX},{_PatternOffsetY}"));
|
|
Thread.Sleep(_JumpSleepTime); //스캐너 점프 이동 후 안정화 시간 추가
|
|
|
|
ClearCameraDisplay();
|
|
return SEQ_FIND_PATTERN;
|
|
} else {
|
|
_FindPatternCount = 0;
|
|
return SEQ_DECISION_CHECK_OFFSET;
|
|
}
|
|
} else {
|
|
if (_InitParam.Is1StepCalibration)
|
|
{
|
|
_Is1stepCount++;
|
|
Log.I(string.Format($"Is1stepCount : {_Is1stepCount} "));
|
|
return SEQ_FIND_PATTERN;
|
|
}
|
|
else
|
|
{
|
|
if(_NotFoundCount > 5)
|
|
{
|
|
Log.I(string.Format($"Pattern Not Found. NotFoundCount OverFlow. Next Sequnece : SetVisionPositionFailed."));
|
|
return SEQ_SET_VISION_POSITION_FAILED;
|
|
}
|
|
else
|
|
{
|
|
_NotFoundCount++;
|
|
Log.I(string.Format($"NotFoundCount : {_NotFoundCount} "));
|
|
return SEQ_FIND_PATTERN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void TranslateImageToField(double imgPosX, double imgPosY, out double realPosX, out double realPosY)
|
|
{
|
|
//여기 수정 필요.. 하드 코딩 되어있으면 안되겠네..
|
|
var camConfig = VisionEnv.AuroraEnv.DeviceManager.GetDeviceConfig(eCamId.CAM1.ToString()) as CamConfig;
|
|
|
|
//var imageWidthChild = camConfig.ImageSize.Width / 2;
|
|
//var imageHeightChild = camConfig.ImageSize.Height / 2;
|
|
var imageWidthChild = _FieldScanParams.GetimageSizeWidthChild();
|
|
var imageHeightChild = _FieldScanParams.GetimageSizeHeightChild();
|
|
double moveOffsetX = 0;
|
|
double moveOffsetY = 0;
|
|
var cameraROIWidth = ((imageWidthChild * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
var cameraROIHeight = ((imageHeightChild * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
|
|
moveOffsetX = ((imgPosX * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0 - cameraROIWidth * 0.5;
|
|
moveOffsetY = cameraROIHeight * 0.5 - ((imgPosY * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
|
|
//Jin : X Filp, Y Flip에 따라서 Offset 수식을 변경해줄 필요 없을 듯.. Flip을 사용하던 안하던 Scanner 입장에서는 동일할테니깐
|
|
//if (camConfig.FlipAndRotation.ImageFlip == eImageFlip.LeftToRight) {
|
|
// //X Flip
|
|
// moveOffsetX = cameraROIWidth * 0.5 - ((imgPosX * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
//} else {
|
|
// moveOffsetX = ((imgPosX * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0 - cameraROIWidth * 0.5;
|
|
//}
|
|
//if (camConfig.FlipAndRotation.ImageFlip == eImageFlip.TopToBottom) {
|
|
// //Y Flip
|
|
// moveOffsetY = ((imgPosY * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0 - cameraROIHeight * 0.5;
|
|
//} else {
|
|
// moveOffsetY = cameraROIHeight * 0.5 - ((imgPosY * _SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
|
//}
|
|
|
|
//angle은 현재 사용하지 않네..
|
|
//double angle = GrabAngle * Math.PI / 180;
|
|
double angle = 0;
|
|
|
|
realPosX = moveOffsetX * Math.Cos(angle) + moveOffsetY * Math.Sin(angle);
|
|
realPosY = -moveOffsetX * Math.Sin(angle) + moveOffsetY * Math.Cos(angle);
|
|
}
|
|
|
|
private string DecisionCheckOffset(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
Log.I(string.Format($"Find Pattern Result Offset:[{_PatternOffsetX},{_PatternOffsetY}] Score:[{_Score}]"));
|
|
|
|
if (Math.Max(Math.Abs(_PatternOffsetX), Math.Abs(_PatternOffsetY)) < _InitParam.CheckOffset) {
|
|
Log.I(string.Format($"Check Offset Result True Criteria:[{_InitParam.CheckOffset}] Max Offset:[{Math.Max(Math.Abs(_PatternOffsetX), Math.Abs(_PatternOffsetY))}"));
|
|
return SEQ_SET_VISION_POSITION;
|
|
} else if (_FindPatternCount < 10) {
|
|
_CheckOffsetCount++;
|
|
Log.I(string.Format($"Check Offset Result True Criteria:[{_InitParam.CheckOffset}] Max Offset:[{Math.Max(Math.Abs(_PatternOffsetX), Math.Abs(_PatternOffsetY))}"));
|
|
return SEQ_FIND_PATTERN;
|
|
} else {
|
|
Log.E(String.Format("ERROR_CHECK_OFFSET_COUNT_OVER"));
|
|
return SEQ_SET_VISION_POSITION_FAILED;
|
|
}
|
|
}
|
|
|
|
private SequenceActionResult SetVisionPosition(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
double currentX, currentY;
|
|
|
|
//_Scanner.GetXYPos(out currentX, out currentY);
|
|
_Scanner.GetXYPos(out currentX, out currentY);
|
|
|
|
if (_InitParam.IsVisionCalibration) {
|
|
// Vision Scanner Calibration인 경우
|
|
int visionBitX = (int)(currentX * _Scanner.Config.ScaleXYFactor);
|
|
int visionBitY = (int)(currentY * _Scanner.Config.ScaleXYFactor);
|
|
|
|
//DataGrid에 Vision 좌표 업데이트
|
|
//ViewModel에서 이벤트 생성하고 시퀀스에서 이벤트로 주고 TreadSleep 줘보자.. 몇초 줘야하는지는 확인해보자
|
|
var updateDataGridItem = new UpdateDataGridItem(_PositionIndex, visionBitX, visionBitY);
|
|
context.EventPublisher.Publish(new EventMessage(context.SequenceId, context.SequenceId, updateDataGridItem));
|
|
Thread.Sleep(100);
|
|
Log.I(string.Format($"UPDATE_VISION_CORRECTION_TABLE;{_PositionIndex};{visionBitX};{visionBitY}"));
|
|
|
|
} else {
|
|
// Laser Scanner Calibration인 경우
|
|
int visionBitX = (int)(((_CurrentPositionX - _InitParam.MasterPosOffsetX) * 2 - currentX) * _Scanner.Config.ScaleXYFactor);
|
|
int visionBitY = (int)(((_CurrentPositionY - _InitParam.MasterPosOffsetY) * 2 - currentY) * _Scanner.Config.ScaleXYFactor);
|
|
|
|
var updateDataGridItem = new UpdateDataGridItem(_PositionIndex, (int)visionBitX, (int)visionBitY);
|
|
context.EventPublisher.Publish(new EventMessage(context.SequenceId, context.SequenceId, updateDataGridItem));
|
|
Thread.Sleep(100);
|
|
Log.I(string.Format($"UPDATE_LASER_CORRECTION_TABLE;{_PositionIndex};{visionBitX};{visionBitY}"));
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult SetVisionPositionFailed(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
if (_InitParam.IsVisionCalibration) {
|
|
//DataGrid에 Vision 좌표 업데이트
|
|
//ViewModel에서 이벤트 생성하고 시퀀스에서 이벤트로 주고 TreadSleep 줘보자.. 몇초 줘야하는지는 확인해보자
|
|
var updateDataGridItem = new UpdateDataGridItem(_PositionIndex, 0, 0);
|
|
context.EventPublisher.Publish(new EventMessage(context.SequenceId, context.SequenceId, updateDataGridItem));
|
|
Thread.Sleep(100);
|
|
Log.I(string.Format($"UPDATE_VISION_CORRECTION_TABLE;{_PositionIndex};{0};{0}"));
|
|
} else {
|
|
// Laser Scanner Calibration인 경우
|
|
var updateDataGridItem = new UpdateDataGridItem(_PositionIndex, 0, 0);
|
|
context.EventPublisher.Publish(new EventMessage(context.SequenceId, context.SequenceId, updateDataGridItem));
|
|
Thread.Sleep(100);
|
|
Log.I(string.Format($"UPDATE_VISION_CORRECTION_TABLE;{_PositionIndex};{0};{0}"));
|
|
}
|
|
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private string DecisionCheckNextPostionExists(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
|
{
|
|
if (_InitParam.Is1StepCalibration) {
|
|
return SEQ_SAVE_RESULT_DATA;
|
|
} else {
|
|
_PositionIndex++;
|
|
|
|
if (_PositionIndex < _MarkingPositionList_MM.Count) {
|
|
return SEQ_CAPTURE_NEXT_POSITION;
|
|
} else {
|
|
return SEQ_SAVE_RESULT_DATA;
|
|
}
|
|
}
|
|
}
|
|
private SequenceActionResult SaveResultData(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 결과 Data 를 업데이트 함. format 유지, ScannerCalibration 없음
|
|
context.PutValue(ContextKey.KEY_SEQUENCE_RESULT, true);
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult WriteCompletionPLCBit(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
// 완료 비트 write 하는 Node 추가 필요. format 유지, ScannerCalibration 없음
|
|
|
|
Log.D("ScannerCalibration Sequence WriteCompletionPLCBit");
|
|
return SequenceAction.Ok();
|
|
}
|
|
|
|
private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param)
|
|
{
|
|
RestoreDeviceStatus();
|
|
Log.I("ScannerCalibration Complete");
|
|
|
|
context.TryGetValue(ContextKey.KEY_SEQUENCE_RESULT, out bool seqResult);
|
|
SeqScannerCalibration_OutParam result = new SeqScannerCalibration_OutParam() { Success = seqResult };
|
|
|
|
if (seqResult == false) {
|
|
AlarmManager.Alarm(AlarmCode.ALARM_SEQUENCE_ScannerCalibration_ResultFailed);
|
|
}
|
|
|
|
Log.D("ScannerCalibration Sequence Complete");
|
|
return SequenceAction.Ok(result);
|
|
}
|
|
|
|
private bool RestoreDeviceStatus()
|
|
{
|
|
//vision correctiontable로 원복
|
|
_Scanner.SelectCorrectionTable(1);
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
return true;
|
|
}
|
|
|
|
private void OnForceError(SequenceContext arg1, string arg2)
|
|
{
|
|
//List 실행 종료
|
|
_Scanner.StopExecution();
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
Log.E("ScannerCalibration Sequence is stopped");
|
|
}
|
|
|
|
private void OnStopped(SequenceContext obj)
|
|
{
|
|
//List 실행 종료
|
|
_Scanner.StopExecution();
|
|
//Anlog 출력 0으로 변경, efunctiontype을 command로 변경해주면 list가 아니라 직접 변경됨
|
|
_Scanner.WriteDA((uint)eAnalogPortOut.DA1, 0, eFunctionType.COMMAND);
|
|
//Scanner 원점 복귀
|
|
_Scanner.JumpAbs(0, 0, eFunctionType.COMMAND);
|
|
|
|
Log.E("ScannerCalibration Sequence is stopped");
|
|
}
|
|
|
|
}
|
|
|
|
public class SeqScannerCalibration_InitParam : InitParam
|
|
{
|
|
public FovInfo FovInfo { get; set; }
|
|
//public eDisplayType _DisplayType { get; set; }
|
|
|
|
public bool IsVisionCalibration { get; set; }
|
|
|
|
public int ColumnCount { get; set; }
|
|
public int RowCount { get; set; }
|
|
public float UnitLength { get; set; }
|
|
public float TiltingDegree { get; set; }
|
|
|
|
public double CheckOffset { get; set; }
|
|
public double MasterPosOffsetX { get; set; }
|
|
public double MasterPosOffsetY { get; set; }
|
|
public bool Is1StepCalibration { get; set; }
|
|
public int RetryNum { get; set; }
|
|
public int SelectedRowIndex { get; set; }
|
|
}
|
|
|
|
public class SeqScannerCalibration_OutParam : OutParam
|
|
{
|
|
// TODO: 몇개가 Vision Fail 되었는지가 나오면 좋음.
|
|
}
|
|
}
|