diff --git a/HexcalMC/Base/DebugDfn.cs b/HexcalMC/Base/DebugDfn.cs index 46393d6..3c2e731 100644 --- a/HexcalMC/Base/DebugDfn.cs +++ b/HexcalMC/Base/DebugDfn.cs @@ -73,7 +73,7 @@ namespace HexcalMC.Base SetColor = m_Color; } - string strText = DateTime.Now.ToString("HH:mm:ss.ff") + "--" + str + Environment.NewLine; + string strText = DateTime.Now.ToString("HH:mm:ss.fff") + "--" + str + Environment.NewLine; textBox_Msg.SelectionStart = textBox_Msg.TextLength; if (string.IsNullOrEmpty(str)) SetText(textBox_Msg, str, SetColor, false, 16); diff --git a/HexcalMC/MainFrom.Designer.cs b/HexcalMC/MainFrom.Designer.cs index 60720b0..9149ec4 100644 --- a/HexcalMC/MainFrom.Designer.cs +++ b/HexcalMC/MainFrom.Designer.cs @@ -140,6 +140,8 @@ this.btnEnable = new System.Windows.Forms.Button(); this.btnDisable = new System.Windows.Forms.Button(); this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.rdoTCP = new System.Windows.Forms.RadioButton(); + this.rdoSimu = new System.Windows.Forms.RadioButton(); this.lamp_acs = new HexcalMC.Lamp(); this.txtPort = new System.Windows.Forms.TextBox(); this.txtIP = new System.Windows.Forms.TextBox(); @@ -855,9 +857,9 @@ this.grpSafety.Controls.Add(this.label20); this.grpSafety.Controls.Add(this.label19); this.grpSafety.Controls.Add(this.label17); - this.grpSafety.Location = new System.Drawing.Point(516, 15); + this.grpSafety.Location = new System.Drawing.Point(569, 15); this.grpSafety.Name = "grpSafety"; - this.grpSafety.Size = new System.Drawing.Size(199, 133); + this.grpSafety.Size = new System.Drawing.Size(146, 133); this.grpSafety.TabIndex = 12; this.grpSafety.TabStop = false; this.grpSafety.Text = "安全限位"; @@ -1009,7 +1011,7 @@ this.grpMst.Controls.Add(this.lblAcc0); this.grpMst.Controls.Add(this.lblMoving0); this.grpMst.Controls.Add(this.label13); - this.grpMst.Location = new System.Drawing.Point(332, 15); + this.grpMst.Location = new System.Drawing.Point(381, 15); this.grpMst.Name = "grpMst"; this.grpMst.Size = new System.Drawing.Size(178, 133); this.grpMst.TabIndex = 11; @@ -1188,7 +1190,7 @@ // this.groupBox6.Controls.Add(this.btnEnable); this.groupBox6.Controls.Add(this.btnDisable); - this.groupBox6.Location = new System.Drawing.Point(233, 15); + this.groupBox6.Location = new System.Drawing.Point(283, 15); this.groupBox6.Name = "groupBox6"; this.groupBox6.Size = new System.Drawing.Size(93, 133); this.groupBox6.TabIndex = 10; @@ -1217,6 +1219,8 @@ // // groupBox2 // + this.groupBox2.Controls.Add(this.rdoTCP); + this.groupBox2.Controls.Add(this.rdoSimu); this.groupBox2.Controls.Add(this.lamp_acs); this.groupBox2.Controls.Add(this.txtPort); this.groupBox2.Controls.Add(this.txtIP); @@ -1226,15 +1230,37 @@ this.groupBox2.Controls.Add(this.label1); this.groupBox2.Location = new System.Drawing.Point(14, 15); this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(209, 133); + this.groupBox2.Size = new System.Drawing.Size(263, 133); this.groupBox2.TabIndex = 1; this.groupBox2.TabStop = false; this.groupBox2.Text = "通讯状态"; // + // rdoTCP + // + this.rdoTCP.AutoSize = true; + this.rdoTCP.Checked = true; + this.rdoTCP.Location = new System.Drawing.Point(6, 25); + this.rdoTCP.Name = "rdoTCP"; + this.rdoTCP.Size = new System.Drawing.Size(43, 17); + this.rdoTCP.TabIndex = 32; + this.rdoTCP.TabStop = true; + this.rdoTCP.Text = "TCP"; + this.rdoTCP.UseVisualStyleBackColor = true; + // + // rdoSimu + // + this.rdoSimu.AutoSize = true; + this.rdoSimu.Location = new System.Drawing.Point(6, 48); + this.rdoSimu.Name = "rdoSimu"; + this.rdoSimu.Size = new System.Drawing.Size(64, 17); + this.rdoSimu.TabIndex = 31; + this.rdoSimu.Text = "模拟器"; + this.rdoSimu.UseVisualStyleBackColor = true; + // // lamp_acs // this.lamp_acs.Font = new System.Drawing.Font("宋体", 16F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel, ((byte)(134))); - this.lamp_acs.Location = new System.Drawing.Point(57, 50); + this.lamp_acs.Location = new System.Drawing.Point(120, 42); this.lamp_acs.LText = ""; this.lamp_acs.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.lamp_acs.Name = "lamp_acs"; @@ -1245,7 +1271,7 @@ // // txtPort // - this.txtPort.Location = new System.Drawing.Point(103, 52); + this.txtPort.Location = new System.Drawing.Point(166, 44); this.txtPort.Name = "txtPort"; this.txtPort.Size = new System.Drawing.Size(91, 21); this.txtPort.TabIndex = 21; @@ -1253,7 +1279,7 @@ // // txtIP // - this.txtIP.Location = new System.Drawing.Point(103, 29); + this.txtIP.Location = new System.Drawing.Point(166, 21); this.txtIP.Name = "txtIP"; this.txtIP.Size = new System.Drawing.Size(91, 21); this.txtIP.TabIndex = 22; @@ -1261,7 +1287,7 @@ // // btn_ACSStop // - this.btn_ACSStop.Location = new System.Drawing.Point(113, 84); + this.btn_ACSStop.Location = new System.Drawing.Point(176, 76); this.btn_ACSStop.Name = "btn_ACSStop"; this.btn_ACSStop.Size = new System.Drawing.Size(81, 30); this.btn_ACSStop.TabIndex = 20; @@ -1271,7 +1297,7 @@ // // btn_ACSStart // - this.btn_ACSStart.Location = new System.Drawing.Point(18, 84); + this.btn_ACSStart.Location = new System.Drawing.Point(81, 76); this.btn_ACSStart.Name = "btn_ACSStart"; this.btn_ACSStart.Size = new System.Drawing.Size(81, 30); this.btn_ACSStart.TabIndex = 19; @@ -1282,7 +1308,7 @@ // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(18, 56); + this.label2.Location = new System.Drawing.Point(81, 48); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(33, 13); this.label2.TabIndex = 17; @@ -1291,7 +1317,7 @@ // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(18, 33); + this.label1.Location = new System.Drawing.Point(81, 25); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(71, 13); this.label1.TabIndex = 18; @@ -1497,5 +1523,7 @@ private Telerik.WinControls.UI.RadButtonElement rtb_home; private Telerik.WinControls.UI.RadRibbonBarGroup radRibbonBarGroup9; private Telerik.WinControls.UI.RadButtonElement rtb_etalon; + private System.Windows.Forms.RadioButton rdoTCP; + private System.Windows.Forms.RadioButton rdoSimu; } } diff --git a/HexcalMC/MainFrom.cs b/HexcalMC/MainFrom.cs index 6a4d895..08cfaab 100644 --- a/HexcalMC/MainFrom.cs +++ b/HexcalMC/MainFrom.cs @@ -1,9 +1,4 @@ -using ACS.SPiiPlusNET; -using HexcalMC.Base; -using HexcalMC.Form; -using HexcalMC.Hexcal; -using HexcalMC.Properties; -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -11,1399 +6,1605 @@ using System.Net; using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; +using ACS.SPiiPlusNET; +using HexcalMC.Base; +using HexcalMC.Form; +using HexcalMC.Hexcal; +using HexcalMC.Properties; using Telerik.WinControls.UI; using static HexcalMC.EtalonForm; namespace HexcalMC { - //定一个 回家状态枚举,包括 从未回家,正在回家,已经回家 - public enum HomeStates - { - None, //默认状态 - NotHome, //未回家 - Homing, //回家中 - Homed //回家完成 - } + //定一个 回家状态枚举,包括 从未回家,正在回家,已经回家 + public enum HomeStates + { + None, //默认状态 + NotHome, //未回家 + Homing, //回家中 + Homed //回家完成 + , + } - //定义 运动状态枚举,包括 正在运动,运动到位,Jog运动 - public enum MotionStates - { - None, //默认状态 - Moving, //运动中 - InPos, //运动到位 - Jogging //jog中 - } + //定义 运动状态枚举,包括 正在运动,运动到位,Jog运动 + public enum MotionStates + { + None, //默认状态 + Moving, //运动中 + InPos, //运动到位 + Jogging //jog中 + , + } - public partial class MainFrom : RadRibbonForm - { - private readonly List _pointCloud = new List(); //运动中点集合 + public partial class MainFrom : RadRibbonForm + { + private readonly List _pointCloud = new List(); //运动中点集合 - private bool _mBHexcalConnected; + private bool _mBHexcalConnected; - private TcpIpServer _mTcpIpServer; //创建tcpserver,用于接收hexcal传来的指令,并解析传递平台 + private TcpIpServer _mTcpIpServer; //创建tcpserver,用于接收hexcal传来的指令,并解析传递平台 - private int m_nTotalAxis; //定义总轴数 - private Axis[] m_arrAxisList = null; - //定一个运动到位次数的变量和三个方法,开始统计运动到位次数,停止统计运动到位次数,获取运动到位次数 + private int m_nTotalAxis; //定义总轴数 + private Axis[] m_arrAxisList = null; - #region 运动到位次数 + //定一个运动到位次数的变量和三个方法,开始统计运动到位次数,停止统计运动到位次数,获取运动到位次数 + + #region 运动到位次数 - // 记录运动到位次数的变量 - private int m_nInPosCount = 0; - private bool isCounting = false; + // 记录运动到位次数的变量 + private int m_nInPosCount = 0; + private bool isCounting = false; + private bool isInPose = false; //运动到位状态 + + // 开始统计运动到位次数 + public void StartCounting() + { + isCounting = true; + m_nInPosCount = 0; // 重置计数器 + } + + // 停止统计运动到位次数 + public void StopCounting() + { + isCounting = false; + m_nInPosCount = 0; // 重置计数器 + } + + // 获取运动到位次数 + public int GetInPosCount() + { + return m_nInPosCount; + } + + public bool GetIsMoving() + { + return isInPose; + } + #endregion + + public MainFrom() + { + InitializeComponent(); + + // 处理未被捕获的线程异常 + Application.ThreadException += Application_ThreadException; + + // 处理未被捕获的非UI线程异常 + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + } + + private void MainFrom_Load(object sender, EventArgs e) + { + FormBorderStyle = FormBorderStyle.FixedSingle; // 设置窗体边框样式为固定大小 + MaximizeBox = false; // 禁用窗体的最大化按钮 + DebugDfn.textBox_Msg = TextBoxMsg; + + //加载配置文件 + LoadConfig(); + _acs = new Api(); //初始化 ACS运动控制类 + + //启动界面刷新 + timer_RefreshUI.Start(); + + Point3D point3D = new Point3D(800, 980, -290); + IsWithinLimit(point3D); - // 开始统计运动到位次数 - public void StartCounting() - { - isCounting = true; - m_nInPosCount = 0; // 重置计数器 } - // 停止统计运动到位次数 - public void StopCounting() - { - isCounting = false; - m_nInPosCount = 0; // 重置计数器 - } - - // 获取运动到位次数 - public int GetInPosCount() - { - return m_nInPosCount; - } - - #endregion - - public MainFrom() - { - InitializeComponent(); - - // 处理未被捕获的线程异常 - Application.ThreadException += Application_ThreadException; - - // 处理未被捕获的非UI线程异常 - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - } - - private void MainFrom_Load(object sender, EventArgs e) - { - FormBorderStyle = FormBorderStyle.FixedSingle; // 设置窗体边框样式为固定大小 - MaximizeBox = false; // 禁用窗体的最大化按钮 - DebugDfn.textBox_Msg = TextBoxMsg; - - //加载配置文件 - LoadConfig(); - _acs = new Api(); //初始化 ACS运动控制类 - - //启动界面刷新 - timer_RefreshUI.Start(); - } - - private void MainFrom_Shown(object sender, EventArgs e) //窗体显示准备好接受用户输入时发生 - { - ////启动服务端,用于接收hexcal传来的指令 - //StartServer(); - - //if (_enableAcs) - //{ - // Btn_ACSStart_Click(null, null); //模拟连接运动平台 - //} - } - - private void MainFrom_FormClosed(object sender, FormClosedEventArgs e) - { - MyBase.TraceWriteLine("关闭程序"); - DebugDfn._strEndTime = DateTime.Now.ToString("yyyy.MM.dd HH-mm-ss"); - timer_RefreshUI.Stop(); - - Btn_StopServer_Click(null, null); - Btn_ACSStop_Click(null, null);//关闭ACS - - string copyFileName = DebugDfn.StrDebugSavePath + "\\Debug(" + DebugDfn._strStartTime + " To " + - DebugDfn._strEndTime + ")" + ".txt"; - if (!File.Exists(DebugDfn.StrDebugSavePath)) - { - //创建文件夹 DebugDfn.StrDebugSavePath - Directory.CreateDirectory(DebugDfn.StrDebugSavePath); - } - - File.Copy(DebugDfn.StrDebugFile, copyFileName); - - if (Errors.ErrorWrite != null) - Errors.ErrorWrite.Close(); - if (Errors.OtherWrite != null) - Errors.OtherWrite.Close(); - if (Errors.StatusWrite != null) - Errors.StatusWrite.Close(); - } - - private void LoadConfig() //加载配置文件 - { - //判断配置文件是否存在 - if (!File.Exists(StrConfigFile)) - { - MessageBox.Show("配置文件不存在,请检查配置文件", "异常", MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - - MotionSpeed = FileIni.ReadDouble(StrConfigFile, "MOTOR", "MOTION_SPEED"); //运动定位速度 - //正限位 - XMaxstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "X_MAXSTROKESW"); - YMaxstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Y_MAXSTROKESW"); - ZMaxstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Z_MAXSTROKESW"); - - //负限位 - XMinstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "X_MINSTROKESW"); - YMinstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Y_MINSTROKESW"); - ZMinstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Z_MINSTROKESW"); - - port = FileIni.ReadInt(StrConfigFile, "MOTOR", "Port"); - DebugDfn.AddLogText($"当前监听端口配置为: {port}"); - DebugDfn.AddLogText($"当前运动速度配置为: {MotionSpeed}"); - } - - private void Plot2D(List pointCloud) - { - // 清空画布 - formsPlot1.Plot.Clear(); - - //pointCloud 是否为空 - if (pointCloud.Count <= 0) - { - return; - } - - List dataX = new List(); - List dataY = new List(); - - foreach (Point3D point3D in pointCloud) - { - dataX.Add(point3D.X); - dataY.Add(point3D.Y); - } - - formsPlot1.Plot.AddScatter(dataX.ToArray(), dataY.ToArray()); - formsPlot1.Refresh(); - } - - #region 运动平台变量区 - - public Api _acs; - - private const int MaxUiLimitCnt = 24; - private int _mNTotalAxis; - - //private int _mNTotalBuffer = 0; - //private Axis[] _mArrAxisList = null; - public bool _mAcsConnected; //ACS通讯状态 - - // For update values - private MotorStates _mNMotorState; //运动状态 - - private ProgramStates _mNProgramState; //程序状态 - private object _mObjReadVar; - private Array _mArrReadVector; - private double _mLfRPos, _mLfFPos, _mLfPe, _mLfFvel; //参考位置,反馈位置 位置误差 反馈速度 double类型 - private int _mNValues, _mNOutputState; - - private Label[] _mLblLeftLimit; //左限位 - private Label[] _mLblRightLimit; //右限位 - private Label[] _mlblMoving; //运动中 - private Label[] _mlblAcc; //加速中 - private Label[] _mlblInPos; //轴就位 - private Label[] _mlblEnable; //使能 - private bool[] axisEnabled = new bool[MaxUiLimitCnt]; //轴使能状态 - public bool totalAxisEnabled = false; - - private HomeStates _homeStates; //回家状态 - private MotionStates _currentMotionState; //当前运动状态 - private MotionStates _currentMotorStateLast; - private readonly int _motionTimeout = 50000; //定义运动超时时间 - - //定义启用的轴,后面运动时会使用 - public static Axis[] UseAxis = - { Axis.ACSC_AXIS_1, Axis.ACSC_AXIS_0, Axis.ACSC_AXIS_8, Axis.ACSC_NONE }; - - //定义 XYZ三个轴的左右行程范围 - public string StrConfigFile = Application.StartupPath + "\\File\\config.ini"; - - public static double MotionSpeed = 60; - public static double XMaxstrokesw = 730; //正限位 - public static double YMaxstrokesw = 1000; - public static double ZMaxstrokesw = 5; - - public static double XMinstrokesw = -30; //负限位 - public static double YMinstrokesw = -10; - public static double ZMinstrokesw = -280; - public static int port = 1234; //默认监听端口 - - //定义一个3D点,存储当前平台实时位置 - public Point3D _mPoint3D; - - #endregion 运动平台变量区 - - #region hexcal软件交互 - - private void StartServer() - { - // 对_mTcpIpServer增加判断是否已经启动且存在设备连接 - if (_mTcpIpServer != null && _mTcpIpServer.ConnectStatus) - { - //弹窗提醒已经启动 - MyBase.TraceWriteLine("TCP服务端已经启动,请勿重复启动"); - MessageBox.Show("TCP服务端已经启动,请勿重复启动", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - //启动服务器,并获取数据,解析 - _mTcpIpServer = new TcpIpServer(IPAddress.Any.ToString(), Convert.ToString(port)); - _mTcpIpServer.UseMode = 1; //设置通讯返回数据流格式 - try - { - //启动监听 - if (_mTcpIpServer.StartListen()) - { - //绑定两个事件 OnRaisedStatus 和OnRaisedMessage - _mTcpIpServer.OnRaisedMessage += ReceiveMessage; //接收消息回调 - _mTcpIpServer.OnRaisedStatus += ReceiveStatus; //连接状态 - _mTcpIpServer.DataReceived += ReceiveByte; - } - else - { - MessageBox.Show("TCP服务端启动失败,请检查网络连接,重新打开软件", "异常", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - catch (Exception ex) - { - DebugDfn.AddLogText("启动TCP服务端异常" + ex); - } - } - - private void ReceiveByte(object sender, byte[] e) - { - DebugDfn.AddLogText("接收到" + BitConverter.ToString(e)); - } - - private void ReceiveMessage(string clientIp, string msg) //接收的内容 - { - //打印ClientIP 和 Msg - DebugDfn.AddLogText("接收到" + clientIp + ": " + msg); - - //根据源地址的不同,执行不同处理 - string sourceIp = clientIp.Split(':')[0]; - switch (sourceIp) - { - case "100.0.0.1": - ParseHexcalMsg(msg); - break; - - case "100.0.0.2": - ParseHexcalMsg(msg); - break; - - default: - DebugDfn.AddLogText("未知来源,没有应答"); - break; - } - } - - public static string ConstructString(string variableName, double[] values) - { - string result = variableName + " "; - for (int i = 0; i < values.Length; i++) - { - result += values[i].ToString("F6"); - if (i < values.Length - 1) - { - result += ", "; - } - } - - return result; - } - - public static string ConstructPosString(Point3D point) - { - double[] values = { point.X, point.Y, point.Z, 0.0, 0.0, 0.0, 0.0 }; - return ConstructString("POS", values); - } - - public static Point3D ParsePoint3DFromCommand(string input) - { - string[] parts = input.Split(' ')[1].Split(','); - if (parts.Length >= 3) - { - double x = double.Parse(parts[0]); - double y = double.Parse(parts[1]); - double z = double.Parse(parts[2]); - return new Point3D(x, y, z); - } - - throw new ArgumentException("输入字符串格式不正确。"); - } - - private void CheckPlatformStatus() - { - //检查平台状态,如果运动中,返回BUSY,否则返回READY - if (_currentMotionState == MotionStates.None || _currentMotionState == MotionStates.InPos) //默认或到位 - { - SendMsgToHexcal("READY"); - } - else - { - SendMsgToHexcal("BUSY"); - } - } - - private void ParseHexcalMsg(string msg) //编写一个Hexcal协议解析函数 - { - //DebugDfn.AddLogText("正在解析 " + msg); - - //去除Msg中\r\n - msg = msg.Replace("\r\n", ""); - - //判断是否含有故障ERROR字样 - if (msg.Contains("ERROR")) - { - //弹窗提醒 - MessageBox.Show("CMM错误", msg, MessageBoxButtons.OK, MessageBoxIcon.Error); - return; - } - - if (msg.Contains("\x02") || msg.Contains("\u0002")) - { - //DebugDfn.AddLogText("接收到STX,开始解析"); - CheckPlatformStatus(); - } - else if (msg.Contains("\x03") || msg.Contains("\u0003")) - { - CheckPlatformStatus(); - } - //else if (msg.Contains("^B")) //查询状态, READY或BUSY - //{ - // checkPlatformStatus(); - //} - else if (msg.Contains("CMMTYP")) //测量机类型 - { - SendMsgToHexcal("CMMTYP MA 19617, FDC V15.00, 10 8 3 , 0"); - } - else if (msg.Contains("VERSION")) //版本号 - { - SendMsgToHexcal("00-000-000-00000 FDC V51.04.0000 DATE: 12/21/22 TIME: 12:50:55"); - } - else if (msg.Contains("SHOW MAXSTROKESW")) //最大行程,根据实际情况填写 - { - //MAXSTROKESW 233.200000,346.500000,15.100000,0.000000,0.000000,0.000000,0.000000 - - double[] values = { XMaxstrokesw, YMaxstrokesw, ZMaxstrokesw, 0.0, 0.0, 0.0, 0.0 }; - string resultString = ConstructString("MAXSTROKESW", values); - SendMsgToHexcal(resultString); - } - else if (msg.Contains("SHOW MINSTROKESW")) //最小行程,根据实际情况填写 - { - //MINSTROKESW -68.800000,-55.500000,-286.900000,0.000000,0.000000,0.000000,0.000000 - - double[] values = { XMinstrokesw, YMinstrokesw, ZMinstrokesw, 0.0, 0.0, 0.0, 0.0 }; - string resultString = ConstructString("MINSTROKESW", values); - SendMsgToHexcal(resultString); - } - else if (msg.Contains("SHOW MAXVEL")) //最大速度 - { - SendMsgToHexcal("MAXVEL 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000"); - } - else if (msg.Contains("SHOW MAXACC")) //最大加速度 - { - SendMsgToHexcal( - "MAXACC 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000"); - } - else if (msg.Contains("SHOW SENSWKP")) - { - SendMsgToHexcal("X_ SENSWKP 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); - } - else if (msg.Contains("SHOW X_SENSAXIS")) - { - SendMsgToHexcal("X_SENSAXIS 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); - } - else if (msg.Contains("SHOW Y_SENSAXIS")) //查询Y轴 - { - SendMsgToHexcal("Y_SENSAXIS 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); - } - else if (msg.Contains("SHOW Z_SENSAXIS")) //查询Z轴 - { - SendMsgToHexcal("Z_SENSAXIS 7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); - } - else if (msg.Contains("SHOW TEMPCOMPTYPE")) //温度补偿,温度补偿 >1 表示支持温度补偿,此处不支持 - { - SendMsgToHexcal("TEMPCOMPTYPE 0"); - } - else if (msg.Contains("READTP")) - { - SendMsgToHexcal("READTP 0.000000"); - } - else if (msg.Contains("SHOW ESTOP")) //查询急停状态,根据真是情况调整 - { - SendMsgToHexcal("ESTOP FALSE"); - } - else if (msg.Contains("CMHWST")) - { - SendMsgToHexcal("CMHWST 8257,0,1792,0"); - } - else if (msg.Contains("SHOW MOVPAR")) //查询速度 - { - SendMsgToHexcal( - "MOVPAR 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.00000 0,0.000000"); - } - else if (msg.Contains("SHOW MAXVEL")) //查询最大速度 - { - SendMsgToHexcal("MAXVEL 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000"); - } - else if (msg.Contains("SHOW ACCEL")) //查询加速度 - { - SendMsgToHexcal( - "ACCEL 1000.000000,1000.000000,1000.000000,0.000000,0.000000,0.000000,0.000000,0.000000"); - } - else if (msg.Contains("MOVPAR")) //设置速度 xyz 轴的速度 - { - SendMsgToHexcal("%"); - } - else if (msg.Contains("ACCEL")) //设置加速度 - { - SendMsgToHexcal("%"); - } - else if (msg.Contains("PRBPIN")) //设置侧头偏置 - { - SendMsgToHexcal("%"); - } - else if (msg.Contains("ENABLE TEMP")) //设置温度补偿 - { - SendMsgToHexcal("%"); - } - else if (msg.Contains("WKPPAR")) - { - SendMsgToHexcal("%"); - } - else if (msg.Contains("SCLTMP")) - { - SendMsgToHexcal("%"); - } - else if (msg.Contains("DISABLE GEO")) - { - SendMsgToHexcal("%"); - } - else if (msg.Contains("AUTZER")) //回家指令 - { - SendMsgToHexcal("%"); //收到并执行,同时状态改为忙碌 - - //执行回家 - IsHomed(); - } - else if (msg.Contains("MOVABS")) //移动指令,解析移动位置 - { - //收到指令 ,形如 MOVABS 0.015000,127.172997,-114.897003,0.000000\r\n - SendMsgToHexcal("%"); - - Point3D point = ParsePoint3DFromCommand(msg); - SetPositionXyz(point); //开始移动 - - _pointCloud.Add(point); //添加到点集合 - } - else if (msg.Contains("GETPOS")) //获取位置 - { - //POS 167.553898,-55.400421,-208.548678,0.000000,0.000000,0.000000,0.000000 - Point3D point3D = GetPositionXyz(); //获取当前位置 - string resultString = ConstructPosString(point3D); - SendMsgToHexcal(resultString); - } - else - { - DebugDfn.AddLogText("未知命令,没有应答"); - } - } - - private void ReceiveStatus(TcpIpServer.EnumTcpIpServer iType, string msg) - { - //记录到日志 - DebugDfn.AddLogText(iType + " : " + msg); - - //根据连接状态,更新界面 - switch (iType) - { - case TcpIpServer.EnumTcpIpServer.ClientConnect: - _mBHexcalConnected = true; - break; - - default: - _mBHexcalConnected = false; - break; - } - } - - private void SendMsgToHexcal(string msg) - { - if (_mTcpIpServer == null) return; - - //发送数据 - DebugDfn.AddLogText("回复 " + msg); - _mTcpIpServer.SendMessageToAllClients(msg += "\r\n"); //回复内容末尾加上\r\n,协议要求 - } - - private void Btn_StartServer_Click(object sender, EventArgs e) - { - Btn_StartServer.Enabled = false; - Btn_StopServer.Enabled = true; - StartServer(); - DebugDfn.AddLogText("TCP服务端启动成功 "); - } - - private void Btn_StopServer_Click(object sender, EventArgs e) - { - //关闭服务端 - if (_mTcpIpServer != null) - { - _mTcpIpServer.StopListen(); - } - - Btn_StopServer.Enabled = false; - Btn_StartServer.Enabled = true; - _mBHexcalConnected = false; - DebugDfn.AddLogText("TCP服务端已关闭"); - } - - #endregion hexcal软件交互 - - #region ACS平台相关 - - #region 异常抓取 - - //实现函数 - - private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) - { - // 防止程序终止 - MessageBox.Show("发生了未处理的异常:" + e.Exception.Message, "提示", MessageBoxButtons.OK, - MessageBoxIcon.Information); - } - - private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - if (e.ExceptionObject is Exception ex) - { - HandleException(ex); - } - } - - private static void HandleException(Exception ex) - { - MessageBox.Show($"发生了未处理的异常:{ex.Message}", "提示", MessageBoxButtons.OK, - MessageBoxIcon.Information); - } - - //订阅报错 - private void EnableFaultEvent() - { - _acs.EnableEvent(Interrupts.ACSC_INTR_COMM_CHANNEL_CLOSED); - _acs.EnableEvent(Interrupts.ACSC_INTR_EMERGENCY); - _acs.EnableEvent(Interrupts.ACSC_INTR_SYSTEM_ERROR); - _acs.EnableEvent(Interrupts.ACSC_INTR_ETHERCAT_ERROR); - _acs.EnableEvent(Interrupts.ACSC_INTR_MOTOR_FAILURE); - _acs.EnableEvent(Interrupts.ACSC_INTR_MOTION_FAILURE); - _acs.EnableEvent(Interrupts.ACSC_INTR_PHYSICAL_MOTION_END); - _acs.COMMCHANNELCLOSED += _acs_COMMCHANNELCLOSED; - _acs.MOTORFAILURE += _acs_MOTORFAILURE; - _acs.MOTIONFAILURE += _acs_MOTIONFAILURE; - _acs.SYSTEMERROR += _acs_SYSTEMERROR; - _acs.ETHERCATERROR += _acs_ETHERCATERROR; - _acs.EMERGENCY += _acs_EMERGENCY; - _acs.PHYSICALMOTIONEND += _acs_PHYSICAL_MOTION_END; - } - - private void DisableFaultEvent() - { - _acs.COMMCHANNELCLOSED -= _acs_COMMCHANNELCLOSED; - _acs.MOTORFAILURE -= _acs_MOTORFAILURE; - _acs.MOTIONFAILURE -= _acs_MOTIONFAILURE; - _acs.SYSTEMERROR -= _acs_SYSTEMERROR; - _acs.ETHERCATERROR -= _acs_ETHERCATERROR; - _acs.EMERGENCY -= _acs_EMERGENCY; - _acs.PHYSICALMOTIONEND -= _acs_PHYSICAL_MOTION_END; - - _acs.DisableEvent(Interrupts.ACSC_INTR_COMM_CHANNEL_CLOSED); - _acs.DisableEvent(Interrupts.ACSC_INTR_EMERGENCY); - _acs.DisableEvent(Interrupts.ACSC_INTR_SYSTEM_ERROR); - _acs.DisableEvent(Interrupts.ACSC_INTR_ETHERCAT_ERROR); - _acs.DisableEvent(Interrupts.ACSC_INTR_MOTOR_FAILURE); - _acs.DisableEvent(Interrupts.ACSC_INTR_MOTION_FAILURE); - _acs.DisableEvent(Interrupts.ACSC_INTR_PHYSICAL_MOTION_END); - } - - //关联函数 - private void _acs_EMERGENCY(ulong param) - { - DebugDfn.AddLogText($"[EStopError] Error Message:{_acs.GetErrorString((int)param)}"); - } - - private void _acs_ETHERCATERROR(ulong param) - { - DebugDfn.AddLogText($"[EtherCatError] Error Message:{_acs.GetErrorString((int)param)}"); - } - - private void _acs_SYSTEMERROR(ulong param) - { - DebugDfn.AddLogText($"[SystemError] Error Message:{_acs.GetErrorString((int)param)}"); - } - - private void _acs_MOTIONFAILURE(AxisMasks axis) - { - for (int i = 0; i < _acs.GetAxesCount(); i++) - { - if (((int)axis & (int)Math.Pow(2, i)) == Math.Pow(2, i)) - { - if (_acs.GetMotionError((Axis)i) != 0) - { - //Motor无法自动捕获,需要在motion报错中获取 - int errorcode = _acs.GetMotionError((Axis)i); - - DebugDfn.AddLogText( - $"[MotionError] Axis:{i} Error Code:{errorcode} Error Message: {_acs.GetErrorString(errorcode)}"); - - int errorcodes = _acs.GetMotorError((Axis)i); - - DebugDfn.AddLogText( - $"[MotorError] Axis:{i} Error Code:{errorcodes} Error Message:{_acs.GetErrorString(errorcodes)}"); - } - } - } - } - - private void _acs_MOTORFAILURE(AxisMasks axis) - { - for (int i = 0; i < _acs.GetAxesCount(); i++) - { - if (((int)axis & (int)Math.Pow(2, i)) == Math.Pow(2, i)) - { - int errorcode = _acs.GetMotorError((Axis)i); - - DebugDfn.AddLogText( - $"[MotorError] Axis:{i} Error Code:{errorcode} Error Message:{_acs.GetErrorString(errorcode)}"); - } - } - } - - private void _acs_COMMCHANNELCLOSED(ulong param) - { - DebugDfn.AddLogText($"[CommError] Error Message:{_acs.GetErrorString((int)param)}"); - } - - private void _acs_PHYSICAL_MOTION_END(AxisMasks axis) - { - int bit = 0x01; - int axisNo = 0; - - for (int i = 0; i < 64; i++) - { - if ((int)axis == bit) - { - axisNo = i; - break; - } - - bit = bit << 1; - } - - //DebugDfn.AddLogText(string.Format(" - Axis {0}, Stoppped", axisNo)); - } - - #endregion 异常抓取 - - private void BtnEnable_Click(object sender, EventArgs e) //使能所有轴 - { - if (_mAcsConnected) - { - //!!!! Important !! Must insert '-1' at the last - _acs.EnableM(UseAxis); - } - else - { - //弹窗提醒尚未连接 - MessageBox.Show("未连接到运动平台,请先点击连接"); - } - } - - private void BtnDisable_Click(object sender, EventArgs e) //轴取消 - { - // Disable all of axes - _acs.DisableAll(); - } - - private bool IsMotionInPose() - { - bool x_inpose = false, y_inpose = false, z_inpose = false; - - _mNMotorState = _acs.GetMotorState(Axis.ACSC_AXIS_1); - if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) - { - x_inpose = true; - } - - _mNMotorState = _acs.GetMotorState(Axis.ACSC_AXIS_0); - if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) - { - y_inpose = true; - } - - _mNMotorState = _acs.GetMotorState(Axis.ACSC_AXIS_8); - if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) - { - z_inpose = true; - } - - if (x_inpose && y_inpose && z_inpose) - { - return true; - } - - return false; - } - - private void TmrMonitor_Tick(object sender, EventArgs e) //用于刷新状态 - { - if (_mAcsConnected) - { - try - { - _mPoint3D = GetPositionXyz(); //取平台当前位置 - - #region 更新限位及运动状态 - - //左右限位刷新 - _mObjReadVar = - _acs.ReadVariableAsVector("FAULT", ProgramBuffer.ACSC_NONE, 0, _mNTotalAxis - 1); - if (_mObjReadVar != null) - { - _mArrReadVector = _mObjReadVar as Array; - if (_mArrReadVector != null) - { - UpdateLimitState(0, (int)_mArrReadVector.GetValue(1)); //获取X轴 - UpdateLimitState(1, (int)_mArrReadVector.GetValue(0)); - UpdateLimitState(2, (int)_mArrReadVector.GetValue(8)); - } - } - - UpdateSingleAxisStatus(); //刷新运动状态 - - #endregion 更新限位及运动状态 - - #region 到位判断 - - if (IsMotionInPose()) - { - _currentMotionState = MotionStates.InPos; - //DebugDfn.AddLogText("运动到位"); - } - else - { - _currentMotionState = MotionStates.Moving; - DebugDfn.AddLogText("运动中"); - } - - //增加判断 运动中到 运动到位,主动发送READY - if (_currentMotionState == MotionStates.InPos && _currentMotionState != _currentMotorStateLast) - { - DebugDfn.AddLogText("运动到位"); - if (isCounting) - { - m_nInPosCount++; - } - } - - _currentMotorStateLast = _currentMotionState; - - #endregion 到位判断 - } - catch (Exception ex) - { - DebugDfn.AddLogText("ACS平台刷新异常" + ex); - MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); - Btn_ACSStop_Click(null, null); - } - } - } - - private void Btn_ACSStart_Click(object sender, EventArgs e) //连接 - { - btn_ACSStart.Enabled = false; - btn_ACSStop.Enabled = true; - - try - { - _acs.OpenCommEthernetTCP( - txtIP.Text, // IP Address (Default : 10.0.0.100) - Convert.ToInt32(txtPort.Text.Trim())); // default : 701 - - _mAcsConnected = true; - - //运动相关初始化操作 - InitMotion(); - - // 启动定时器 - tmrMonitor.Interval = 50; - tmrMonitor.Start(); - } - catch (COMException comex) - { - MessageBox.Show("Connection fail", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - Debug.WriteLine("Connection fail" + comex.Message); - - _mAcsConnected = false; - } - catch (Exception ex) - { - DebugDfn.AddLogText("ACS平台连接异常" + ex); - MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - private void Btn_ACSStop_Click(object sender, EventArgs e) //断开连接 - { - if (_mAcsConnected) - { - //DisableFaultEvent(); //取消注册事件 - _acs.CloseComm(); - } - - tmrMonitor.Stop(); - _mAcsConnected = false; - btn_ACSStart.Enabled = true; - btn_ACSStop.Enabled = false; - } - - private void UpdateLimitState(int axisNo, int fault) //刷新限位 - { - if (axisNo < MaxUiLimitCnt) - { - if ((fault & (int)SafetyControlMasks.ACSC_SAFETY_LL) != 0) - _mLblLeftLimit[axisNo].Image = Resources.Error; - else _mLblLeftLimit[axisNo].Image = Resources.Off; - if ((fault & (int)SafetyControlMasks.ACSC_SAFETY_RL) != 0) - _mLblRightLimit[axisNo].Image = Resources.Error; - else _mLblRightLimit[axisNo].Image = Resources.Off; - } - } - - public int TranslateAxisNumber(Axis originalAxisNumber) - { - int newAxisNumber = -1; - - switch (originalAxisNumber) - { - case Axis.ACSC_AXIS_1: //X轴 - newAxisNumber = 0; - break; - - case Axis.ACSC_AXIS_0: - newAxisNumber = 1; //Y轴 - break; - - case Axis.ACSC_AXIS_8: - newAxisNumber = 2; - break; - } - - return newAxisNumber; - } - - private void UpdateSingleAxisStatus() - { - Axis axis = 0; - int _axisNo = 0; - for (int i = 0; i < UseAxis.Length; i++) - { - axis = UseAxis[i]; - - _axisNo = TranslateAxisNumber(UseAxis[i]); - - // Get Motor State ACSPL+ Variable : MST (integer) - _mNMotorState = _acs.GetMotorState(axis); - - if (_axisNo == -1) - { - return; - } - - // 运动中 - if ((_mNMotorState & MotorStates.ACSC_MST_MOVE) != 0) - { - _mlblMoving[_axisNo].Image = Resources.On; - } - else - { - _mlblMoving[_axisNo].Image = Resources.Off; - } - - // 就位 - if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) - { - _mlblInPos[_axisNo].Image = Resources.On; - } - else - { - _mlblInPos[_axisNo].Image = Resources.Off; - } - - // 加速 - if ((_mNMotorState & MotorStates.ACSC_MST_ACC) != 0) - { - _mlblAcc[_axisNo].Image = Resources.On; - } - else - { - _mlblAcc[_axisNo].Image = Resources.Off; - } - - // 使能 - if ((_mNMotorState & MotorStates.ACSC_MST_ENABLE) != 0) - { - _mlblEnable[_axisNo].Image = Resources.On; - axisEnabled[_axisNo] = true; //轴使能 - } - else - { - _mlblEnable[_axisNo].Image = Resources.Off; - axisEnabled[_axisNo] = false; - } - } - - totalAxisEnabled = CalculateTotalEnabled(axisEnabled, 0, 1, 8); - DebugDfn.AddLogText($"总的使能状态为:{(totalAxisEnabled ? "使能" : "未使能")}"); - } - - private void IsHomed() //读取回家状态,当未回家时执行回家指令 - { - // 1、连接状态检查,如果未连接,提示 - if (!_mAcsConnected) - { - DebugDfn.AddLogText("[IsHomed] ACS平台未连接,请先点击连接"); - MessageBox.Show("ACS平台未连接,请先点击连接", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - // 2、回家状态检查是否已经回家 - if (_mAcsConnected && _homeStates == HomeStates.Homed) - { - //弹窗提示 - MessageBox.Show("轴已经回家", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - // 3、读取回家状态 - if (_acs != null && _mAcsConnected) - - { - var yawHome = _acs.ReadVariable("YAW_HOME_DONE"); - - if (Convert.ToBoolean(yawHome)) - { - //弹窗提示 - MessageBox.Show("轴已经回家", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - _homeStates = HomeStates.Homed; - return; - } - // 4、执行回家指令,弹窗等待用户确认 - - DialogResult result = MessageBox.Show("轴未回家,即将执行回家指令", "提示", MessageBoxButtons.OK, - MessageBoxIcon.Information); - - if (result == DialogResult.OK) - { - // 在这里执行接下来的操作,例如回家指令 - - _acs.RunBuffer(ProgramBuffer.ACSC_BUFFER_6, null); //执行回家指令,这里的buffer6是回家指令的buffer - _homeStates = HomeStates.Homing; - _currentMotionState = MotionStates.Moving; - DebugDfn.AddLogText("回家运动中"); - - //等待回家完成 - for (int i = 0; i < UseAxis.Length; i++) - { - _acs.WaitMotionEnd(UseAxis[i], _motionTimeout); //等待回家完成 - } - - _homeStates = HomeStates.Homed; - _currentMotionState = MotionStates.InPos; - DebugDfn.AddLogText("回家完成"); - } - else - { - //弹窗提醒 - MessageBox.Show("点击了取消,未进行任何动作", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } - } - - private void InitMotion() //定义 运动状态初始化函数,包括内部变量,轴启用,回家判断等 - { - string strTemp; - //运动相关变量初始化 - _homeStates = HomeStates.None; - _currentMotionState = MotionStates.None; - _currentMotionState = MotionStates.None; - - if (!_mAcsConnected) - { - MessageBox.Show("未连接运动平台,请先连接运动平台"); - return; - } - - //轴启用,加电 - _acs.EnableM(UseAxis); - for (int i = 0; i < UseAxis.Length; i++) - { - _acs.WaitMotorEnabled(UseAxis[i], 1, _motionTimeout); //等待电机使能 - } - - DebugDfn.AddLogText("电机已启用"); - - //回家 - IsHomed(); - - //设置定位速度 - SetSpeedXyz(MotionSpeed); - - //获取轴数量 - strTemp = _acs.Transaction("?SYSINFO(13)"); - _mNTotalAxis = Convert.ToInt32(strTemp.Trim()); - _mLblLeftLimit = new Label[MaxUiLimitCnt]; //左限位 - _mLblLeftLimit[0] = lblLL0; - _mLblLeftLimit[1] = lblLL1; - _mLblLeftLimit[2] = lblLL2; - - _mLblRightLimit = new Label[MaxUiLimitCnt]; //右限位 - _mLblRightLimit[0] = lblRL0; - _mLblRightLimit[1] = lblRL1; - _mLblRightLimit[2] = lblRL2; - - _mlblMoving = new Label[MaxUiLimitCnt]; //运动中 - _mlblMoving[0] = lblMoving0; - _mlblMoving[1] = lblMoving1; - _mlblMoving[2] = lblMoving2; - - _mlblAcc = new Label[MaxUiLimitCnt]; // 加速中 - _mlblAcc[0] = lblAcc0; - _mlblAcc[1] = lblAcc1; - _mlblAcc[2] = lblAcc2; - - _mlblInPos = new Label[MaxUiLimitCnt]; //就位 - _mlblInPos[0] = lblInPos0; - _mlblInPos[1] = lblInPos1; - _mlblInPos[2] = lblInPos2; - - _mlblEnable = new Label[MaxUiLimitCnt]; //轴使能 - _mlblEnable[0] = lblEnable0; - _mlblEnable[1] = lblEnable1; - _mlblEnable[2] = lblEnable2; - - //EnableFaultEvent(); //订阅错误事件 - } - - public static bool IsWithinLimit(Point3D point) //判断点是否在行程范围内 - { - if (point.X >= XMinstrokesw && point.X <= XMaxstrokesw && - point.Y >= YMinstrokesw && point.Y <= YMaxstrokesw && - point.Z >= ZMinstrokesw && point.Z <= ZMaxstrokesw) - { - return true; - } - - return false; - } - - public static bool IsWithinLimit(Point point) //判断点是否在行程范围内 - { - if (point.X >= XMinstrokesw && point.X <= XMaxstrokesw && - point.Y >= YMinstrokesw && point.Y <= YMaxstrokesw && - point.Z >= ZMinstrokesw && point.Z <= ZMaxstrokesw) - { - return true; - } - - return false; - } - - private void SetPositionXyz(Point3D point3D) //运动到指定位置 - { - if (!_mAcsConnected) - { - DebugDfn.AddLogText("ACS平台未连接,请先点击连接"); - MessageBox.Show("ACS平台未连接,请先点击连接", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - if (_currentMotionState != MotionStates.Moving) - { - _currentMotionState = MotionStates.Moving; //设置当前运动状态 - //判断 point3D是否合法 - if (point3D != null) - { - if (IsWithinLimit(point3D)) //判断点是否在行程范围内 - { - double[] pointsArray = - { - point3D.X, - point3D.Y, - point3D.Z - }; - //判断各轴使能状态,如果未使能,则使能 - - if (!totalAxisEnabled) - { - _acs.EnableM(UseAxis); - for (int i = 0; i < UseAxis.Length; i++) - { - _acs.WaitMotorEnabled(UseAxis[i], 1, _motionTimeout); //等待电机使能 - } - - DebugDfn.AddLogText("电机已启用"); - } - - //执行运动指令 - _acs.ToPointM(MotionFlags.ACSC_NONE, UseAxis, pointsArray); //多轴运动到指定位置 - } - else - { - DebugDfn.AddLogText("目标位置超出行程范围,请重新设置"); - MessageBox.Show("目标位置超出行程范围,请重新设置", "异常", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - else - { - DebugDfn.AddLogText("目标位置为空,请重新设置"); - MessageBox.Show("目标位置为空,请重新设置", "异常", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - } - - private Point3D GetPositionXyz(int positionMode = 1) //获取当前位置 - { - double xPosition = 0, yPosition = 0, zPosition = 0; - Point3D point3D = new Point3D(xPosition, yPosition, zPosition); - if (!_mAcsConnected) - { - DebugDfn.AddLogText("ACS平台未连接,请先点击连接"); - MessageBox.Show("ACS平台未连接,请先点击连接", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - return point3D; - } - - //获取当前位置, 两种 GetRPosition,GetFPosition - if (positionMode == 1) - { - //获取反馈位置 Feedback position (Encoder value) ACSPL+ Variable : FPO (real) - xPosition = _acs.GetFPosition(UseAxis[0]); - yPosition = _acs.GetFPosition(UseAxis[1]); - zPosition = _acs.GetFPosition(UseAxis[2]); - //DebugDfn.AddLogText("反馈位置: " + xPosition + " " + yPosition + " " + zPosition); - } - else - { - //获取参考位置 ACSPL+ Variable : RPOS (real) - xPosition = _acs.GetRPosition(UseAxis[0]); - yPosition = _acs.GetRPosition(UseAxis[1]); - zPosition = _acs.GetRPosition(UseAxis[2]); - DebugDfn.AddLogText("参考位置: " + xPosition + " " + yPosition + " " + zPosition); - } - - //构造point3D格式 - point3D = new Point3D(xPosition, yPosition, zPosition); - - return point3D; - } - - private void SetSpeedXyz(double speed) //获取运动参数 - { - //获取实际速度 - double feedbackVelocity = (double)_acs.ReadVariable("FVEL", ProgramBuffer.ACSC_NONE, 0, 0); - DebugDfn.AddLogText("实际速度: " + feedbackVelocity); - - //设置Y轴 速度参数 - _acs.SetVelocity(Axis.ACSC_AXIS_0, speed); - _acs.SetAcceleration(Axis.ACSC_AXIS_0, speed * 10); - _acs.SetDeceleration(Axis.ACSC_AXIS_0, speed * 10); - - //设置X轴速度参数 - _acs.SetVelocity(Axis.ACSC_AXIS_1, speed); - _acs.SetAcceleration(Axis.ACSC_AXIS_1, speed * 10); - _acs.SetDeceleration(Axis.ACSC_AXIS_1, speed * 10); - - //设置Z轴速度参数 - _acs.SetVelocity(Axis.ACSC_AXIS_8, speed); - _acs.SetAcceleration(Axis.ACSC_AXIS_8, speed * 10); - _acs.SetDeceleration(Axis.ACSC_AXIS_8, speed * 10); - - DebugDfn.AddLogText($"速度设置完成 {speed}"); - } - - private void rtb_quick_loc_Click(object sender, EventArgs e)//快速定位 - { - // 获取文本框的值 - double x = double.Parse(rtb_SetX.Text); - double y = double.Parse(rtb_Sety.Text); - double z = double.Parse(rtb_SetZ.Text); - - // 构造 Point3D 对象 - Point3D point = new Point3D(x, y, z); - - SetPositionXyz(point); - } - - private static bool CalculateTotalEnabled(bool[] axisEnabled, params int[] axisIndices)//判断轴使能状态 - { - bool totalEnabled = true; - foreach (int index in axisIndices) - { - bool isEnabled = axisEnabled[index]; - if (!isEnabled) - { - totalEnabled = false; - break; - } - } - return totalEnabled; - } - - private void rtb_stop_Click(object sender, EventArgs e) - { - try - { - Axis[] m_arrAxisList = new Axis[] { Axis.ACSC_AXIS_0, Axis.ACSC_AXIS_1, Axis.ACSC_AXIS_8, Axis.ACSC_NONE }; - - if (m_arrAxisList != null) _acs.HaltM(m_arrAxisList); - - DebugDfn.AddLogText("立即停止 已发送命令"); - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); - Debug.WriteLine(ex.Message); - } - } - - private void rtb_home_Click(object sender, EventArgs e) - { - //弹窗提醒用户,是否执行回家指令 - DialogResult result = MessageBox.Show("是否执行回家指令", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information); - - if (result == DialogResult.Cancel) - { - return; - } - - DebugDfn.AddLogText("回家指令已发送"); - if (!_mAcsConnected) - { - DebugDfn.AddLogText("ACS平台未连接,请先点击连接"); - MessageBox.Show("ACS平台未连接,请先点击连接", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - return; - } - - if (_currentMotionState != MotionStates.Moving) - { - _currentMotionState = MotionStates.Moving; //设置当前运动状态 - - _acs.RunBuffer(ProgramBuffer.ACSC_BUFFER_6, null); //执行回家指令,这里的buffer6是回家指令的buffer - _homeStates = HomeStates.Homing; - _currentMotionState = MotionStates.Moving; - DebugDfn.AddLogText("回家运动中"); - - //等待回家完成 - for (int i = 0; i < UseAxis.Length; i++) - { - _acs.WaitMotionEnd(UseAxis[i], _motionTimeout); //等待回家完成 - } - - _homeStates = HomeStates.Homed; - _currentMotionState = MotionStates.InPos; - DebugDfn.AddLogText("回家完成"); - } - } - - private void rtb_etalon_Click(object sender, EventArgs e) //etalon校准 - { - DebugDfn.AddLogText("Etalon校准"); - //判断通讯对象是否存在 - if (_acs == null || !_acs.IsConnected) - { - DebugDfn.AddLogText("未建立与运动平台通讯,请在主界面先建立通讯"); - - // 在合适的位置调用 MessageBox.Show() 方法 - MessageBox.Show("未建立与运动平台通讯,请在主界面先建立通讯", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - - return; - } - else - { - EtalonForm etalonForm = new EtalonForm(this); - etalonForm.Show(); - } - } - - #endregion ACS平台相关 - - #region 菜单栏 - - private void btn_motion_Click(object sender, EventArgs e) - { - //判断通讯对象是否存在 - if (_acs == null || !_acs.IsConnected) - { - DebugDfn.AddLogText("未建立与运动平台通讯,请在主界面先建立通讯"); - - // 在合适的位置调用 MessageBox.Show() 方法 - MessageBox.Show("未建立与运动平台通讯,请在主界面先建立通讯", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); - - return; - } - else - { - Motion motion = new Motion(this); - motion.Show(); - } - } - - private void Rtb_about_Click(object sender, EventArgs e) //关于界面 - { - AboutBox mAboutBox = new AboutBox(); - mAboutBox.StartPosition = FormStartPosition.CenterScreen; - mAboutBox.Show(); - } - - private void rtb_demo_Click(object sender, EventArgs e) - { - DemoShow demoShow = new DemoShow(_acs); - demoShow.Show(); - demoShow.BringToFront(); - } - - private void Timer_RefreshUI_Tick(object sender, EventArgs e) //UI刷新 - { - //状态灯刷新 - lamp_acs.State = _mAcsConnected ? LampColor.Green : LampColor.Silver; - lamp_hexcal.State = _mBHexcalConnected ? LampColor.Green : LampColor.Silver; - - //时间栏 - //获取当前时间,构造形如 精确到秒,例如 2023-10-08 16:01:23 - rle_timer.Text = "当前时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); - - Plot2D(_pointCloud); //绘图 - - //更新位置 - if (_mPoint3D != null) - { - rtb_xPos.Text = _mPoint3D.X.ToString("F3"); - rtb_yPos.Text = _mPoint3D.Y.ToString("F3"); - rtb_zPos.Text = _mPoint3D.Z.ToString("F3"); - } - } - - #endregion 菜单栏 - } -} \ No newline at end of file + private void MainFrom_Shown(object sender, EventArgs e) //窗体显示准备好接受用户输入时发生 + { + ////启动服务端,用于接收hexcal传来的指令 + //StartServer(); + + //if (_enableAcs) + //{ + // Btn_ACSStart_Click(null, null); //模拟连接运动平台 + //} + } + + private void MainFrom_FormClosed(object sender, FormClosedEventArgs e) + { + MyBase.TraceWriteLine("关闭程序"); + DebugDfn._strEndTime = DateTime.Now.ToString("yyyy.MM.dd HH-mm-ss"); + timer_RefreshUI.Stop(); + + Btn_StopServer_Click(null, null); + Btn_ACSStop_Click(null, null); //关闭ACS + + string copyFileName = + DebugDfn.StrDebugSavePath + + "\\Debug(" + + DebugDfn._strStartTime + + " To " + + DebugDfn._strEndTime + + ")" + + ".txt"; + if (!File.Exists(DebugDfn.StrDebugSavePath)) + { + //创建文件夹 DebugDfn.StrDebugSavePath + Directory.CreateDirectory(DebugDfn.StrDebugSavePath); + } + + File.Copy(DebugDfn.StrDebugFile, copyFileName); + + if (Errors.ErrorWrite != null) + Errors.ErrorWrite.Close(); + if (Errors.OtherWrite != null) + Errors.OtherWrite.Close(); + if (Errors.StatusWrite != null) + Errors.StatusWrite.Close(); + } + + private void LoadConfig() //加载配置文件 + { + //判断配置文件是否存在 + if (!File.Exists(StrConfigFile)) + { + MessageBox.Show( + "配置文件不存在,请检查配置文件", + "异常", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + return; + } + + MotionSpeedxy = FileIni.ReadDouble(StrConfigFile, "MOTOR", "MOTION_SPEEDXY"); //运动定位速度 + MotionSpeedz = FileIni.ReadDouble(StrConfigFile, "MOTOR", "MOTION_SPEEDZ"); + + //正限位 + XMaxstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "X_MAXSTROKESW"); + YMaxstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Y_MAXSTROKESW"); + ZMaxstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Z_MAXSTROKESW"); + + //负限位 + XMinstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "X_MINSTROKESW"); + YMinstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Y_MINSTROKESW"); + ZMinstrokesw = FileIni.ReadDouble(StrConfigFile, "MOTOR", "Z_MINSTROKESW"); + + port = FileIni.ReadInt(StrConfigFile, "MOTOR", "Port"); + DebugDfn.AddLogText($"当前监听端口配置为: {port}"); + DebugDfn.AddLogText($"当前xy运动速度配置为: {MotionSpeedxy}"); + DebugDfn.AddLogText($"当前z运动速度配置为: {MotionSpeedz}"); + } + + private void Plot2D(List pointCloud) + { + // 清空画布 + formsPlot1.Plot.Clear(); + + //pointCloud 是否为空 + if (pointCloud.Count <= 0) + { + return; + } + + List dataX = new List(); + List dataY = new List(); + + foreach (Point3D point3D in pointCloud) + { + dataX.Add(point3D.X); + dataY.Add(point3D.Y); + } + + formsPlot1.Plot.AddScatter(dataX.ToArray(), dataY.ToArray()); + formsPlot1.Refresh(); + } + + #region 运动平台变量区 + + public Api _acs; + + private const int MaxUiLimitCnt = 24; + private int _mNTotalAxis; + + //private int _mNTotalBuffer = 0; + //private Axis[] _mArrAxisList = null; + public bool _mAcsConnected; //ACS通讯状态 + + // For update values + private MotorStates _mNMotorState; //运动状态 + + private ProgramStates _mNProgramState; //程序状态 + private object _mObjReadVar; + private Array _mArrReadVector; + private double _mLfRPos, + _mLfFPos, + _mLfPe, + _mLfFvel; //参考位置,反馈位置 位置误差 反馈速度 double类型 + private int _mNValues, + _mNOutputState; + + private Label[] _mLblLeftLimit; //左限位 + private Label[] _mLblRightLimit; //右限位 + private Label[] _mlblMoving; //运动中 + private Label[] _mlblAcc; //加速中 + private Label[] _mlblInPos; //轴就位 + private Label[] _mlblEnable; //使能 + private bool[] axisEnabled = new bool[MaxUiLimitCnt]; //轴使能状态 + public bool totalAxisEnabled = false; + + private HomeStates _homeStates; //回家状态 + private MotionStates _currentMotionState; //当前运动状态 + private MotionStates _currentMotorStateLast; + private readonly int _motionTimeout = 50000; //定义运动超时时间 + + //定义启用的轴,后面运动时会使用 + public static Axis[] UseAxis = + { + Axis.ACSC_AXIS_1, + Axis.ACSC_AXIS_0, + Axis.ACSC_AXIS_8, + Axis.ACSC_NONE, + }; + + //定义 XYZ三个轴的左右行程范围 + public string StrConfigFile = Application.StartupPath + "\\File\\config.ini"; + + public static double MotionSpeedxy = 60; + public static double MotionSpeedz = 30; + public static double XMaxstrokesw = 730; //正限位 + public static double YMaxstrokesw = 1000; + public static double ZMaxstrokesw = 5; + + public static double XMinstrokesw = -30; //负限位 + public static double YMinstrokesw = -10; + public static double ZMinstrokesw = -280; + public static int port = 1234; //默认监听端口 + + //定义一个3D点,存储当前平台实时位置 + public Point3D _mPoint3D; + + #endregion 运动平台变量区 + + #region hexcal软件交互 + + private void StartServer() + { + // 对_mTcpIpServer增加判断是否已经启动且存在设备连接 + if (_mTcpIpServer != null && _mTcpIpServer.ConnectStatus) + { + //弹窗提醒已经启动 + MyBase.TraceWriteLine("TCP服务端已经启动,请勿重复启动"); + MessageBox.Show( + "TCP服务端已经启动,请勿重复启动", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + return; + } + + //启动服务器,并获取数据,解析 + _mTcpIpServer = new TcpIpServer(IPAddress.Any.ToString(), Convert.ToString(port)); + _mTcpIpServer.UseMode = 1; //设置通讯返回数据流格式 + try + { + //启动监听 + if (_mTcpIpServer.StartListen()) + { + //绑定两个事件 OnRaisedStatus 和OnRaisedMessage + _mTcpIpServer.OnRaisedMessage += ReceiveMessage; //接收消息回调 + _mTcpIpServer.OnRaisedStatus += ReceiveStatus; //连接状态 + _mTcpIpServer.DataReceived += ReceiveByte; + } + else + { + MessageBox.Show( + "TCP服务端启动失败,请检查网络连接,重新打开软件", + "异常", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + } + } + catch (Exception ex) + { + DebugDfn.AddLogText("启动TCP服务端异常" + ex); + } + } + + private void ReceiveByte(object sender, byte[] e) + { + DebugDfn.AddLogText("接收到" + BitConverter.ToString(e)); + } + + private void ReceiveMessage(string clientIp, string msg) //接收的内容 + { + //打印ClientIP 和 Msg + DebugDfn.AddLogText("接收到" + clientIp + ": " + msg); + + //根据源地址的不同,执行不同处理 + string sourceIp = clientIp.Split(':')[0]; + switch (sourceIp) + { + case "100.0.0.1": + ParseHexcalMsg(msg); + break; + + case "100.0.0.2": + ParseHexcalMsg(msg); + break; + + default: + DebugDfn.AddLogText("未知来源,没有应答"); + break; + } + } + + public static string ConstructString(string variableName, double[] values) + { + string result = variableName + " "; + for (int i = 0; i < values.Length; i++) + { + result += values[i].ToString("F6"); + if (i < values.Length - 1) + { + result += ", "; + } + } + + return result; + } + + public static string ConstructPosString(Point3D point) + { + double[] values = { point.X, point.Y, point.Z, 0.0, 0.0, 0.0, 0.0 }; + return ConstructString("POS", values); + } + + public static Point3D ParsePoint3DFromCommand(string input) + { + string[] parts = input.Split(' ')[1].Split(','); + if (parts.Length >= 3) + { + double x = double.Parse(parts[0]); + double y = double.Parse(parts[1]); + double z = double.Parse(parts[2]); + return new Point3D(x, y, z); + } + + throw new ArgumentException("输入字符串格式不正确。"); + } + + private void CheckPlatformStatus() + { + //检查平台状态,如果运动中,返回BUSY,否则返回READY + if ( + _currentMotionState == MotionStates.None + || _currentMotionState == MotionStates.InPos + ) //默认或到位 + { + SendMsgToHexcal("READY"); + } + else + { + SendMsgToHexcal("BUSY"); + } + } + + private void ParseHexcalMsg(string msg) //编写一个Hexcal协议解析函数 + { + //DebugDfn.AddLogText("正在解析 " + msg); + + //去除Msg中\r\n + msg = msg.Replace("\r\n", ""); + + //判断是否含有故障ERROR字样 + if (msg.Contains("ERROR")) + { + //弹窗提醒 + MessageBox.Show("CMM错误", msg, MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + if (msg.Contains("\x02") || msg.Contains("\u0002")) + { + //DebugDfn.AddLogText("接收到STX,开始解析"); + CheckPlatformStatus(); + } + else if (msg.Contains("\x03") || msg.Contains("\u0003")) + { + CheckPlatformStatus(); + } + //else if (msg.Contains("^B")) //查询状态, READY或BUSY + //{ + // checkPlatformStatus(); + //} + else if (msg.Contains("CMMTYP")) //测量机类型 + { + SendMsgToHexcal("CMMTYP MA 19617, FDC V15.00, 10 8 3 , 0"); + } + else if (msg.Contains("VERSION")) //版本号 + { + SendMsgToHexcal("00-000-000-00000 FDC V51.04.0000 DATE: 12/21/22 TIME: 12:50:55"); + } + else if (msg.Contains("SHOW MAXSTROKESW")) //最大行程,根据实际情况填写 + { + //MAXSTROKESW 233.200000,346.500000,15.100000,0.000000,0.000000,0.000000,0.000000 + + double[] values = { XMaxstrokesw, YMaxstrokesw, ZMaxstrokesw, 0.0, 0.0, 0.0, 0.0 }; + string resultString = ConstructString("MAXSTROKESW", values); + SendMsgToHexcal(resultString); + } + else if (msg.Contains("SHOW MINSTROKESW")) //最小行程,根据实际情况填写 + { + //MINSTROKESW -68.800000,-55.500000,-286.900000,0.000000,0.000000,0.000000,0.000000 + + double[] values = { XMinstrokesw, YMinstrokesw, ZMinstrokesw, 0.0, 0.0, 0.0, 0.0 }; + string resultString = ConstructString("MINSTROKESW", values); + SendMsgToHexcal(resultString); + } + else if (msg.Contains("SHOW MAXVEL")) //最大速度 + { + SendMsgToHexcal( + "MAXVEL 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000" + ); + } + else if (msg.Contains("SHOW MAXACC")) //最大加速度 + { + SendMsgToHexcal( + "MAXACC 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000" + ); + } + else if (msg.Contains("SHOW SENSWKP")) + { + SendMsgToHexcal("X_ SENSWKP 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + } + else if (msg.Contains("SHOW X_SENSAXIS")) + { + SendMsgToHexcal("X_SENSAXIS 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + } + else if (msg.Contains("SHOW Y_SENSAXIS")) //查询Y轴 + { + SendMsgToHexcal("Y_SENSAXIS 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + } + else if (msg.Contains("SHOW Z_SENSAXIS")) //查询Z轴 + { + SendMsgToHexcal("Z_SENSAXIS 7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"); + } + else if (msg.Contains("SHOW TEMPCOMPTYPE")) //温度补偿,温度补偿 >1 表示支持温度补偿,此处不支持 + { + SendMsgToHexcal("TEMPCOMPTYPE 0"); + } + else if (msg.Contains("READTP")) + { + SendMsgToHexcal("READTP 0.000000"); + } + else if (msg.Contains("SHOW ESTOP")) //查询急停状态,根据真是情况调整 + { + SendMsgToHexcal("ESTOP FALSE"); + } + else if (msg.Contains("CMHWST")) + { + SendMsgToHexcal("CMHWST 8257,0,1792,0"); + } + else if (msg.Contains("SHOW MOVPAR")) //查询速度 + { + SendMsgToHexcal( + "MOVPAR 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.00000 0,0.000000" + ); + } + else if (msg.Contains("SHOW MAXVEL")) //查询最大速度 + { + SendMsgToHexcal( + "MAXVEL 300.000000,300.000000,300.000000,0.000000,0.000000,0.000000,0.000000,0.000000" + ); + } + else if (msg.Contains("SHOW ACCEL")) //查询加速度 + { + SendMsgToHexcal( + "ACCEL 1000.000000,1000.000000,1000.000000,0.000000,0.000000,0.000000,0.000000,0.000000" + ); + } + else if (msg.Contains("MOVPAR")) //设置速度 xyz 轴的速度 + { + SendMsgToHexcal("%"); + } + else if (msg.Contains("ACCEL")) //设置加速度 + { + SendMsgToHexcal("%"); + } + else if (msg.Contains("PRBPIN")) //设置侧头偏置 + { + SendMsgToHexcal("%"); + } + else if (msg.Contains("ENABLE TEMP")) //设置温度补偿 + { + SendMsgToHexcal("%"); + } + else if (msg.Contains("WKPPAR")) + { + SendMsgToHexcal("%"); + } + else if (msg.Contains("SCLTMP")) + { + SendMsgToHexcal("%"); + } + else if (msg.Contains("DISABLE GEO")) + { + SendMsgToHexcal("%"); + } + else if (msg.Contains("AUTZER")) //回家指令 + { + SendMsgToHexcal("%"); //收到并执行,同时状态改为忙碌 + + //执行回家 + IsHomed(); + } + else if (msg.Contains("MOVABS")) //移动指令,解析移动位置 + { + //收到指令 ,形如 MOVABS 0.015000,127.172997,-114.897003,0.000000\r\n + SendMsgToHexcal("%"); + + Point3D point = ParsePoint3DFromCommand(msg); + SetPositionXyz(point); //开始移动 + + _pointCloud.Add(point); //添加到点集合 + } + else if (msg.Contains("GETPOS")) //获取位置 + { + //POS 167.553898,-55.400421,-208.548678,0.000000,0.000000,0.000000,0.000000 + Point3D point3D = GetPositionXyz(); //获取当前位置 + string resultString = ConstructPosString(point3D); + SendMsgToHexcal(resultString); + } + else + { + DebugDfn.AddLogText("未知命令,没有应答"); + } + } + + private void ReceiveStatus(TcpIpServer.EnumTcpIpServer iType, string msg) + { + //记录到日志 + DebugDfn.AddLogText(iType + " : " + msg); + + //根据连接状态,更新界面 + switch (iType) + { + case TcpIpServer.EnumTcpIpServer.ClientConnect: + _mBHexcalConnected = true; + break; + + default: + _mBHexcalConnected = false; + break; + } + } + + private void SendMsgToHexcal(string msg) + { + if (_mTcpIpServer == null) + return; + + //发送数据 + DebugDfn.AddLogText("回复 " + msg); + _mTcpIpServer.SendMessageToAllClients(msg += "\r\n"); //回复内容末尾加上\r\n,协议要求 + } + + private void Btn_StartServer_Click(object sender, EventArgs e) + { + Btn_StartServer.Enabled = false; + Btn_StopServer.Enabled = true; + StartServer(); + DebugDfn.AddLogText("TCP服务端启动成功 "); + } + + private void Btn_StopServer_Click(object sender, EventArgs e) + { + //关闭服务端 + if (_mTcpIpServer != null) + { + _mTcpIpServer.StopListen(); + } + + Btn_StopServer.Enabled = false; + Btn_StartServer.Enabled = true; + _mBHexcalConnected = false; + DebugDfn.AddLogText("TCP服务端已关闭"); + } + + #endregion hexcal软件交互 + + #region ACS平台相关 + + #region 异常抓取 + + //实现函数 + + private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) + { + // 防止程序终止 + MessageBox.Show( + "发生了未处理的异常:" + e.Exception.Message, + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + } + + private static void CurrentDomain_UnhandledException( + object sender, + UnhandledExceptionEventArgs e + ) + { + if (e.ExceptionObject is Exception ex) + { + HandleException(ex); + } + } + + private static void HandleException(Exception ex) + { + MessageBox.Show( + $"发生了未处理的异常:{ex.Message}", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + } + + //订阅报错 + private void EnableFaultEvent() + { + _acs.EnableEvent(Interrupts.ACSC_INTR_COMM_CHANNEL_CLOSED); + _acs.EnableEvent(Interrupts.ACSC_INTR_EMERGENCY); + _acs.EnableEvent(Interrupts.ACSC_INTR_SYSTEM_ERROR); + _acs.EnableEvent(Interrupts.ACSC_INTR_ETHERCAT_ERROR); + _acs.EnableEvent(Interrupts.ACSC_INTR_MOTOR_FAILURE); + _acs.EnableEvent(Interrupts.ACSC_INTR_MOTION_FAILURE); + _acs.EnableEvent(Interrupts.ACSC_INTR_PHYSICAL_MOTION_END); + _acs.COMMCHANNELCLOSED += _acs_COMMCHANNELCLOSED; + _acs.MOTORFAILURE += _acs_MOTORFAILURE; + _acs.MOTIONFAILURE += _acs_MOTIONFAILURE; + _acs.SYSTEMERROR += _acs_SYSTEMERROR; + _acs.ETHERCATERROR += _acs_ETHERCATERROR; + _acs.EMERGENCY += _acs_EMERGENCY; + _acs.PHYSICALMOTIONEND += _acs_PHYSICAL_MOTION_END; + } + + private void DisableFaultEvent() + { + _acs.COMMCHANNELCLOSED -= _acs_COMMCHANNELCLOSED; + _acs.MOTORFAILURE -= _acs_MOTORFAILURE; + _acs.MOTIONFAILURE -= _acs_MOTIONFAILURE; + _acs.SYSTEMERROR -= _acs_SYSTEMERROR; + _acs.ETHERCATERROR -= _acs_ETHERCATERROR; + _acs.EMERGENCY -= _acs_EMERGENCY; + _acs.PHYSICALMOTIONEND -= _acs_PHYSICAL_MOTION_END; + + _acs.DisableEvent(Interrupts.ACSC_INTR_COMM_CHANNEL_CLOSED); + _acs.DisableEvent(Interrupts.ACSC_INTR_EMERGENCY); + _acs.DisableEvent(Interrupts.ACSC_INTR_SYSTEM_ERROR); + _acs.DisableEvent(Interrupts.ACSC_INTR_ETHERCAT_ERROR); + _acs.DisableEvent(Interrupts.ACSC_INTR_MOTOR_FAILURE); + _acs.DisableEvent(Interrupts.ACSC_INTR_MOTION_FAILURE); + _acs.DisableEvent(Interrupts.ACSC_INTR_PHYSICAL_MOTION_END); + } + + //关联函数 + private void _acs_EMERGENCY(ulong param) + { + DebugDfn.AddLogText($"[EStopError] Error Message:{_acs.GetErrorString((int)param)}"); + } + + private void _acs_ETHERCATERROR(ulong param) + { + DebugDfn.AddLogText( + $"[EtherCatError] Error Message:{_acs.GetErrorString((int)param)}" + ); + } + + private void _acs_SYSTEMERROR(ulong param) + { + DebugDfn.AddLogText($"[SystemError] Error Message:{_acs.GetErrorString((int)param)}"); + } + + private void _acs_MOTIONFAILURE(AxisMasks axis) + { + for (int i = 0; i < _acs.GetAxesCount(); i++) + { + if (((int)axis & (int)Math.Pow(2, i)) == Math.Pow(2, i)) + { + if (_acs.GetMotionError((Axis)i) != 0) + { + //Motor无法自动捕获,需要在motion报错中获取 + int errorcode = _acs.GetMotionError((Axis)i); + + DebugDfn.AddLogText( + $"[MotionError] Axis:{i} Error Code:{errorcode} Error Message: {_acs.GetErrorString(errorcode)}" + ); + + int errorcodes = _acs.GetMotorError((Axis)i); + + DebugDfn.AddLogText( + $"[MotorError] Axis:{i} Error Code:{errorcodes} Error Message:{_acs.GetErrorString(errorcodes)}" + ); + } + } + } + } + + private void _acs_MOTORFAILURE(AxisMasks axis) + { + for (int i = 0; i < _acs.GetAxesCount(); i++) + { + if (((int)axis & (int)Math.Pow(2, i)) == Math.Pow(2, i)) + { + int errorcode = _acs.GetMotorError((Axis)i); + + DebugDfn.AddLogText( + $"[MotorError] Axis:{i} Error Code:{errorcode} Error Message:{_acs.GetErrorString(errorcode)}" + ); + } + } + } + + private void _acs_COMMCHANNELCLOSED(ulong param) + { + DebugDfn.AddLogText($"[CommError] Error Message:{_acs.GetErrorString((int)param)}"); + } + + private void _acs_PHYSICAL_MOTION_END(AxisMasks axis) + { + int bit = 0x01; + int axisNo = 0; + + for (int i = 0; i < 64; i++) + { + if ((int)axis == bit) + { + axisNo = i; + break; + } + + bit = bit << 1; + } + + //DebugDfn.AddLogText(string.Format(" - Axis {0}, Stoppped", axisNo)); + } + + #endregion 异常抓取 + + private void BtnEnable_Click(object sender, EventArgs e) //使能所有轴 + { + if (_mAcsConnected) + { + //!!!! Important !! Must insert '-1' at the last + _acs.EnableM(UseAxis); + } + else + { + //弹窗提醒尚未连接 + MessageBox.Show("未连接到运动平台,请先点击连接"); + } + } + + private void BtnDisable_Click(object sender, EventArgs e) //轴取消 + { + // Disable all of axes + _acs.DisableAll(); + } + + private bool IsMotionInPose() + { + bool x_inpose = false, + y_inpose = false, + z_inpose = false; + + _mNMotorState = _acs.GetMotorState(Axis.ACSC_AXIS_1); + if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) + { + x_inpose = true; + } + + _mNMotorState = _acs.GetMotorState(Axis.ACSC_AXIS_0); + if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) + { + y_inpose = true; + } + + _mNMotorState = _acs.GetMotorState(Axis.ACSC_AXIS_8); + if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) + { + z_inpose = true; + } + + if (x_inpose && y_inpose && z_inpose) + { + return true; + } + + return false; + } + + private void TmrMonitor_Tick(object sender, EventArgs e) //用于刷新状态 + { + if (_mAcsConnected) + { + try + { + _mPoint3D = GetPositionXyz(); //取平台当前位置 + #region 更新限位及运动状态 + + //左右限位刷新 + _mObjReadVar = _acs.ReadVariableAsVector( + "FAULT", + ProgramBuffer.ACSC_NONE, + 0, + _mNTotalAxis - 1 + ); + if (_mObjReadVar != null) + { + _mArrReadVector = _mObjReadVar as Array; + if (_mArrReadVector != null) + { + UpdateLimitState(0, (int)_mArrReadVector.GetValue(1)); //获取X轴 + UpdateLimitState(1, (int)_mArrReadVector.GetValue(0)); + UpdateLimitState(2, (int)_mArrReadVector.GetValue(8)); + } + } + + UpdateSingleAxisStatus(); //刷新运动状态 + #endregion 更新限位及运动状态 + + #region 到位判断 + + if (IsMotionInPose()) + { + _currentMotionState = MotionStates.InPos; + //DebugDfn.AddLogText("运动到位"); + } + else + { + _currentMotionState = MotionStates.Moving; + //DebugDfn.AddLogText("运动中"); + isInPose = false; + } + + //增加判断 运动中到 运动到位,主动发送READY + if ( + _currentMotionState == MotionStates.InPos + && _currentMotionState != _currentMotorStateLast + ) + { + DebugDfn.AddLogText("运动到位"); + isInPose = true; + + if (isCounting) + { + m_nInPosCount++; + DebugDfn.AddLogText("到位次数" + m_nInPosCount); + } + } + + _currentMotorStateLast = _currentMotionState; + + #endregion 到位判断 + } + catch (Exception ex) + { + DebugDfn.AddLogText("ACS平台刷新异常" + ex); + MessageBox.Show( + ex.Message, + "ERROR", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + Btn_ACSStop_Click(null, null); + } + } + } + + private void Btn_ACSStart_Click(object sender, EventArgs e) //连接 + { + btn_ACSStart.Enabled = false; + btn_ACSStop.Enabled = true; + + try + { + if (rdoTCP.Checked) + { + // TCP/IP (Ethernet) + // TCP/IP (Ethernet) + _acs.OpenCommEthernetTCP( + txtIP.Text, // IP Address (Default : 10.0.0.100) + Convert.ToInt32(txtPort.Text.Trim()) + ); // TCP/IP Port nubmer (default : 701) + } + else if (rdoSimu.Checked) + { + // Simmulation mode + _acs.OpenCommSimulator(); + } + + _mAcsConnected = true; + + //运动相关初始化操作 + InitMotion(); + + // 启动定时器 + tmrMonitor.Interval = 50; + tmrMonitor.Start(); + } + catch (COMException comex) + { + MessageBox.Show( + "Connection fail", + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + Debug.WriteLine("Connection fail" + comex.Message); + + _mAcsConnected = false; + } + catch (Exception ex) + { + DebugDfn.AddLogText("ACS平台连接异常" + ex); + MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void Btn_ACSStop_Click(object sender, EventArgs e) //断开连接 + { + if (_mAcsConnected) + { + //DisableFaultEvent(); //取消注册事件 + _acs.CloseComm(); + } + + tmrMonitor.Stop(); + _mAcsConnected = false; + btn_ACSStart.Enabled = true; + btn_ACSStop.Enabled = false; + } + + private void UpdateLimitState(int axisNo, int fault) //刷新限位 + { + if (axisNo < MaxUiLimitCnt) + { + if ((fault & (int)SafetyControlMasks.ACSC_SAFETY_LL) != 0) + _mLblLeftLimit[axisNo].Image = Resources.Error; + else + _mLblLeftLimit[axisNo].Image = Resources.Off; + if ((fault & (int)SafetyControlMasks.ACSC_SAFETY_RL) != 0) + _mLblRightLimit[axisNo].Image = Resources.Error; + else + _mLblRightLimit[axisNo].Image = Resources.Off; + } + } + + public int TranslateAxisNumber(Axis originalAxisNumber) + { + int newAxisNumber = -1; + + switch (originalAxisNumber) + { + case Axis.ACSC_AXIS_1: //X轴 + newAxisNumber = 0; + break; + + case Axis.ACSC_AXIS_0: + newAxisNumber = 1; //Y轴 + break; + + case Axis.ACSC_AXIS_8: + newAxisNumber = 2; + break; + } + + return newAxisNumber; + } + + private void UpdateSingleAxisStatus() + { + Axis axis = 0; + int _axisNo = 0; + for (int i = 0; i < UseAxis.Length; i++) + { + axis = UseAxis[i]; + + _axisNo = TranslateAxisNumber(UseAxis[i]); + + // Get Motor State ACSPL+ Variable : MST (integer) + _mNMotorState = _acs.GetMotorState(axis); + + if (_axisNo == -1) + { + return; + } + + // 运动中 + if ((_mNMotorState & MotorStates.ACSC_MST_MOVE) != 0) + { + _mlblMoving[_axisNo].Image = Resources.On; + } + else + { + _mlblMoving[_axisNo].Image = Resources.Off; + } + + // 就位 + if ((_mNMotorState & MotorStates.ACSC_MST_INPOS) != 0) + { + _mlblInPos[_axisNo].Image = Resources.On; + } + else + { + _mlblInPos[_axisNo].Image = Resources.Off; + } + + // 加速 + if ((_mNMotorState & MotorStates.ACSC_MST_ACC) != 0) + { + _mlblAcc[_axisNo].Image = Resources.On; + } + else + { + _mlblAcc[_axisNo].Image = Resources.Off; + } + + // 使能 + if ((_mNMotorState & MotorStates.ACSC_MST_ENABLE) != 0) + { + _mlblEnable[_axisNo].Image = Resources.On; + axisEnabled[_axisNo] = true; //轴使能 + } + else + { + _mlblEnable[_axisNo].Image = Resources.Off; + axisEnabled[_axisNo] = false; + } + } + + totalAxisEnabled = CalculateTotalEnabled(axisEnabled, 0, 1, 8); + DebugDfn.AddLogText($"总的使能状态为:{(totalAxisEnabled ? "使能" : "未使能")}"); + } + + private void IsHomed() //读取回家状态,当未回家时执行回家指令 + { + // 1、连接状态检查,如果未连接,提示 + if (!_mAcsConnected) + { + DebugDfn.AddLogText("[IsHomed] ACS平台未连接,请先点击连接"); + MessageBox.Show( + "ACS平台未连接,请先点击连接", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + return; + } + + // 2、回家状态检查是否已经回家 + if (_mAcsConnected && _homeStates == HomeStates.Homed) + { + //弹窗提示 + MessageBox.Show( + "轴已经回家", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + return; + } + + // 3、读取回家状态 + if (_acs != null && _mAcsConnected) + { + var yawHome = _acs.ReadVariable("YAW_HOME_DONE"); + + if (Convert.ToBoolean(yawHome)) + { + //弹窗提示 + MessageBox.Show( + "轴已经回家", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + _homeStates = HomeStates.Homed; + return; + } + // 4、执行回家指令,弹窗等待用户确认 + + DialogResult result = MessageBox.Show( + "轴未回家,即将执行回家指令", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + + if (result == DialogResult.OK) + { + // 在这里执行接下来的操作,例如回家指令 + + _acs.RunBuffer(ProgramBuffer.ACSC_BUFFER_6, null); //执行回家指令,这里的buffer6是回家指令的buffer + _homeStates = HomeStates.Homing; + _currentMotionState = MotionStates.Moving; + DebugDfn.AddLogText("回家运动中"); + + //等待回家完成 + for (int i = 0; i < UseAxis.Length; i++) + { + _acs.WaitMotionEnd(UseAxis[i], _motionTimeout); //等待回家完成 + } + + _homeStates = HomeStates.Homed; + _currentMotionState = MotionStates.InPos; + DebugDfn.AddLogText("回家完成"); + } + else + { + //弹窗提醒 + MessageBox.Show( + "点击了取消,未进行任何动作", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + } + } + } + + private void InitMotion() //定义 运动状态初始化函数,包括内部变量,轴启用,回家判断等 + { + string strTemp; + //运动相关变量初始化 + _homeStates = HomeStates.None; + _currentMotionState = MotionStates.None; + _currentMotionState = MotionStates.None; + + if (!_mAcsConnected) + { + MessageBox.Show("未连接运动平台,请先连接运动平台"); + return; + } + + //轴启用,加电 + _acs.EnableM(UseAxis); + for (int i = 0; i < UseAxis.Length; i++) + { + _acs.WaitMotorEnabled(UseAxis[i], 1, _motionTimeout); //等待电机使能 + } + + DebugDfn.AddLogText("电机已启用"); + + //回家 + IsHomed(); + + //设置定位速度 + SetSpeedXyz(MotionSpeedxy, MotionSpeedz); + + //获取轴数量 + strTemp = _acs.Transaction("?SYSINFO(13)"); + _mNTotalAxis = Convert.ToInt32(strTemp.Trim()); + _mLblLeftLimit = new Label[MaxUiLimitCnt]; //左限位 + _mLblLeftLimit[0] = lblLL0; + _mLblLeftLimit[1] = lblLL1; + _mLblLeftLimit[2] = lblLL2; + + _mLblRightLimit = new Label[MaxUiLimitCnt]; //右限位 + _mLblRightLimit[0] = lblRL0; + _mLblRightLimit[1] = lblRL1; + _mLblRightLimit[2] = lblRL2; + + _mlblMoving = new Label[MaxUiLimitCnt]; //运动中 + _mlblMoving[0] = lblMoving0; + _mlblMoving[1] = lblMoving1; + _mlblMoving[2] = lblMoving2; + + _mlblAcc = new Label[MaxUiLimitCnt]; // 加速中 + _mlblAcc[0] = lblAcc0; + _mlblAcc[1] = lblAcc1; + _mlblAcc[2] = lblAcc2; + + _mlblInPos = new Label[MaxUiLimitCnt]; //就位 + _mlblInPos[0] = lblInPos0; + _mlblInPos[1] = lblInPos1; + _mlblInPos[2] = lblInPos2; + + _mlblEnable = new Label[MaxUiLimitCnt]; //轴使能 + _mlblEnable[0] = lblEnable0; + _mlblEnable[1] = lblEnable1; + _mlblEnable[2] = lblEnable2; + + //EnableFaultEvent(); //订阅错误事件 + } + + public static bool IsWithinLimit(Point3D point) //判断点是否在行程范围内 + { + if ( + point.X >= XMinstrokesw + && point.X <= XMaxstrokesw + && point.Y >= YMinstrokesw + && point.Y <= YMaxstrokesw + && point.Z >= ZMinstrokesw + && point.Z <= ZMaxstrokesw + ) + { + + return true; + } + + DebugDfn.AddLogText(point.X.ToString() + " " + point.Y.ToString() + " " + point.Z.ToString()); + //打印 XMinstrokesw 等值 + DebugDfn.AddLogText("XMinstrokesw超限: " + XMinstrokesw); + DebugDfn.AddLogText("XMaxstrokesw超限: " + XMaxstrokesw); + DebugDfn.AddLogText("YMinstrokesw超限: " + YMinstrokesw); + DebugDfn.AddLogText("YMaxstrokesw超限: " + YMaxstrokesw); + DebugDfn.AddLogText("ZMinstrokesw超限: " + ZMinstrokesw); + DebugDfn.AddLogText("ZMaxstrokesw超限: " + ZMaxstrokesw); + return false; + } + + public static bool IsWithinLimit(Point point) //判断点是否在行程范围内 + { + if ( + point.X >= XMinstrokesw + && point.X <= XMaxstrokesw + && point.Y >= YMinstrokesw + && point.Y <= YMaxstrokesw + && point.Z >= ZMinstrokesw + && point.Z <= ZMaxstrokesw + ) + { + return true; + } + + return false; + } + + public void SetPositionXyz(Point3D point3D) //运动到指定位置 + { + if (!_mAcsConnected) + { + DebugDfn.AddLogText("ACS平台未连接,请先点击连接"); + MessageBox.Show( + "ACS平台未连接,请先点击连接", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + return; + } + + if (_currentMotionState != MotionStates.Moving) + { + _currentMotionState = MotionStates.Moving; //设置当前运动状态 + //判断 point3D是否合法 + if (point3D != null) + { + if (IsWithinLimit(point3D)) //判断点是否在行程范围内 + { + double[] pointsArray = { point3D.X, point3D.Y, point3D.Z }; + //判断各轴使能状态,如果未使能,则使能 + + if (!totalAxisEnabled) + { + _acs.EnableM(UseAxis); + for (int i = 0; i < UseAxis.Length; i++) + { + _acs.WaitMotorEnabled(UseAxis[i], 1, _motionTimeout); //等待电机使能 + } + + //DebugDfn.AddLogText("电机已启用"); + } + + //执行运动指令 + _acs.ToPointM(MotionFlags.ACSC_NONE, UseAxis, pointsArray); //多轴运动到指定位置 + } + else + { + DebugDfn.AddLogText("目标位置超出行程范围,请重新设置"); + //MessageBox.Show( + // "目标位置超出行程范围,请重新设置", + // "异常", + // MessageBoxButtons.OK, + // MessageBoxIcon.Error + //); + } + } + else + { + DebugDfn.AddLogText("目标位置为空,请重新设置"); + MessageBox.Show( + "目标位置为空,请重新设置", + "异常", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + } + } + } + + private Point3D GetPositionXyz(int positionMode = 1) //获取当前位置 + { + double xPosition = 0, + yPosition = 0, + zPosition = 0; + Point3D point3D = new Point3D(xPosition, yPosition, zPosition); + if (!_mAcsConnected) + { + DebugDfn.AddLogText("ACS平台未连接,请先点击连接"); + MessageBox.Show( + "ACS平台未连接,请先点击连接", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + return point3D; + } + + //获取当前位置, 两种 GetRPosition,GetFPosition + if (positionMode == 1) + { + //获取反馈位置 Feedback position (Encoder value) ACSPL+ Variable : FPO (real) + xPosition = _acs.GetFPosition(UseAxis[0]); + yPosition = _acs.GetFPosition(UseAxis[1]); + zPosition = _acs.GetFPosition(UseAxis[2]); + //DebugDfn.AddLogText("反馈位置: " + xPosition + " " + yPosition + " " + zPosition); + } + else + { + //获取参考位置 ACSPL+ Variable : RPOS (real) + xPosition = _acs.GetRPosition(UseAxis[0]); + yPosition = _acs.GetRPosition(UseAxis[1]); + zPosition = _acs.GetRPosition(UseAxis[2]); + DebugDfn.AddLogText("参考位置: " + xPosition + " " + yPosition + " " + zPosition); + } + + //构造point3D格式 + point3D = new Point3D(xPosition, yPosition, zPosition); + + return point3D; + } + + private void SetSpeedXyz(double speedxy, double speedz) //获取运动参数 + { + //获取实际速度 + double feedbackVelocity = (double) + _acs.ReadVariable("FVEL", ProgramBuffer.ACSC_NONE, 0, 0); + DebugDfn.AddLogText("实际速度: " + feedbackVelocity); + + //设置Y轴 速度参数 + _acs.SetVelocity(Axis.ACSC_AXIS_0, speedxy); + _acs.SetAcceleration(Axis.ACSC_AXIS_0, speedxy * 10); + _acs.SetDeceleration(Axis.ACSC_AXIS_0, speedxy * 10); + _acs.SetKillDeceleration(Axis.ACSC_AXIS_0, speedxy * 100); + _acs.SetJerk(Axis.ACSC_AXIS_0, speedxy * 100); + + //设置X轴速度参数 + _acs.SetVelocity(Axis.ACSC_AXIS_1, speedxy); + _acs.SetAcceleration(Axis.ACSC_AXIS_1, speedxy * 10); + _acs.SetDeceleration(Axis.ACSC_AXIS_1, speedxy * 10); + _acs.SetKillDeceleration(Axis.ACSC_AXIS_1, speedxy * 100); + _acs.SetJerk(Axis.ACSC_AXIS_1, speedxy * 100); + + //设置Z轴速度参数 + + _acs.SetVelocity(Axis.ACSC_AXIS_8, speedz); + _acs.SetAcceleration(Axis.ACSC_AXIS_8, speedz * 10); + _acs.SetDeceleration(Axis.ACSC_AXIS_8, speedz * 10); + _acs.SetKillDeceleration(Axis.ACSC_AXIS_8, speedz * 100); + _acs.SetJerk(Axis.ACSC_AXIS_8, speedz * 100); + + DebugDfn.AddLogText($"速度设置完成 "); + } + + private void rtb_quick_loc_Click(object sender, EventArgs e) //快速定位 + { + // 获取文本框的值 + double x = double.Parse(rtb_SetX.Text); + double y = double.Parse(rtb_Sety.Text); + double z = double.Parse(rtb_SetZ.Text); + + // 构造 Point3D 对象 + Point3D point = new Point3D(x, y, z); + + SetPositionXyz(point); + } + + private static bool CalculateTotalEnabled(bool[] axisEnabled, params int[] axisIndices) //判断轴使能状态 + { + bool totalEnabled = true; + foreach (int index in axisIndices) + { + bool isEnabled = axisEnabled[index]; + if (!isEnabled) + { + totalEnabled = false; + break; + } + } + return totalEnabled; + } + + private void rtb_stop_Click(object sender, EventArgs e) + { + try + { + Axis[] m_arrAxisList = new Axis[] + { + Axis.ACSC_AXIS_0, + Axis.ACSC_AXIS_1, + Axis.ACSC_AXIS_8, + Axis.ACSC_NONE, + }; + + if (m_arrAxisList != null) + _acs.HaltM(m_arrAxisList); + + DebugDfn.AddLogText("立即停止 已发送命令"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); + Debug.WriteLine(ex.Message); + } + } + + private void rtb_home_Click(object sender, EventArgs e) + { + //弹窗提醒用户,是否执行回家指令 + DialogResult result = MessageBox.Show( + "是否执行回家指令", + "提示", + MessageBoxButtons.OKCancel, + MessageBoxIcon.Information + ); + + if (result == DialogResult.Cancel) + { + return; + } + + DebugDfn.AddLogText("回家指令已发送"); + if (!_mAcsConnected) + { + DebugDfn.AddLogText("ACS平台未连接,请先点击连接"); + MessageBox.Show( + "ACS平台未连接,请先点击连接", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + return; + } + + if (_currentMotionState != MotionStates.Moving) + { + _currentMotionState = MotionStates.Moving; //设置当前运动状态 + + _acs.RunBuffer(ProgramBuffer.ACSC_BUFFER_6, null); //执行回家指令,这里的buffer6是回家指令的buffer + _homeStates = HomeStates.Homing; + _currentMotionState = MotionStates.Moving; + DebugDfn.AddLogText("回家运动中"); + + //等待回家完成 + for (int i = 0; i < UseAxis.Length; i++) + { + _acs.WaitMotionEnd(UseAxis[i], _motionTimeout); //等待回家完成 + } + + _homeStates = HomeStates.Homed; + _currentMotionState = MotionStates.InPos; + DebugDfn.AddLogText("回家完成"); + } + } + + private void rtb_etalon_Click(object sender, EventArgs e) //etalon校准 + { + DebugDfn.AddLogText("Etalon校准"); + //判断通讯对象是否存在 + if (_acs == null || !_acs.IsConnected) + { + DebugDfn.AddLogText("未建立与运动平台通讯,请在主界面先建立通讯"); + + // 在合适的位置调用 MessageBox.Show() 方法 + MessageBox.Show( + "未建立与运动平台通讯,请在主界面先建立通讯", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + + return; + } + else + { + EtalonForm etalonForm = new EtalonForm(this); + etalonForm.Show(); + } + } + + #endregion ACS平台相关 + + #region 菜单栏 + + private void btn_motion_Click(object sender, EventArgs e) + { + //判断通讯对象是否存在 + if (_acs == null || !_acs.IsConnected) + { + DebugDfn.AddLogText("未建立与运动平台通讯,请在主界面先建立通讯"); + + // 在合适的位置调用 MessageBox.Show() 方法 + MessageBox.Show( + "未建立与运动平台通讯,请在主界面先建立通讯", + "提示", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + + return; + } + else + { + Motion motion = new Motion(this); + motion.Show(); + } + } + + private void Rtb_about_Click(object sender, EventArgs e) //关于界面 + { + AboutBox mAboutBox = new AboutBox(); + mAboutBox.StartPosition = FormStartPosition.CenterScreen; + mAboutBox.Show(); + } + + private void rtb_demo_Click(object sender, EventArgs e) + { + DemoShow demoShow = new DemoShow(_acs); + demoShow.Show(); + demoShow.BringToFront(); + } + + private void Timer_RefreshUI_Tick(object sender, EventArgs e) //UI刷新 + { + //状态灯刷新 + lamp_acs.State = _mAcsConnected ? LampColor.Green : LampColor.Silver; + lamp_hexcal.State = _mBHexcalConnected ? LampColor.Green : LampColor.Silver; + + //时间栏 + //获取当前时间,构造形如 精确到秒,例如 2023-10-08 16:01:23 + rle_timer.Text = "当前时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + Plot2D(_pointCloud); //绘图 + + //更新位置 + if (_mPoint3D != null) + { + rtb_xPos.Text = _mPoint3D.X.ToString("F3"); + rtb_yPos.Text = _mPoint3D.Y.ToString("F3"); + rtb_zPos.Text = _mPoint3D.Z.ToString("F3"); + } + } + + #endregion 菜单栏 + } +} diff --git a/HexcalMC/Motion/EtalonForm.Designer.cs b/HexcalMC/Motion/EtalonForm.Designer.cs index 5df80f6..843c017 100644 --- a/HexcalMC/Motion/EtalonForm.Designer.cs +++ b/HexcalMC/Motion/EtalonForm.Designer.cs @@ -28,6 +28,7 @@ /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EtalonForm)); this.btn_draw_test = new System.Windows.Forms.Button(); this.checkMirrorY = new System.Windows.Forms.CheckBox(); @@ -47,8 +48,9 @@ this.btn_startmove = new System.Windows.Forms.Button(); this.btn_stop = new System.Windows.Forms.Button(); this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.label1 = new System.Windows.Forms.Label(); this.text_etalon_info = new System.Windows.Forms.RichTextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.timer_move = new System.Windows.Forms.Timer(this.components); this.editor3D = new Plot3D.Editor3D(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); @@ -260,6 +262,14 @@ this.groupBox2.TabStop = false; this.groupBox2.Text = "etalon操作"; // + // text_etalon_info + // + this.text_etalon_info.Location = new System.Drawing.Point(6, 249); + this.text_etalon_info.Name = "text_etalon_info"; + this.text_etalon_info.Size = new System.Drawing.Size(440, 361); + this.text_etalon_info.TabIndex = 50; + this.text_etalon_info.Text = ""; + // // label1 // this.label1.AutoSize = true; @@ -269,13 +279,10 @@ this.label1.TabIndex = 49; this.label1.Text = "输出"; // - // text_etalon_info + // timer_move // - this.text_etalon_info.Location = new System.Drawing.Point(6, 249); - this.text_etalon_info.Name = "text_etalon_info"; - this.text_etalon_info.Size = new System.Drawing.Size(440, 361); - this.text_etalon_info.TabIndex = 50; - this.text_etalon_info.Text = ""; + this.timer_move.Interval = 500; + this.timer_move.Tick += new System.EventHandler(this.timer_move_Tick); // // editor3D // @@ -335,5 +342,6 @@ private System.Windows.Forms.Button btn_clear; private System.Windows.Forms.Label label1; private System.Windows.Forms.RichTextBox text_etalon_info; + private System.Windows.Forms.Timer timer_move; } } \ No newline at end of file diff --git a/HexcalMC/Motion/EtalonForm.cs b/HexcalMC/Motion/EtalonForm.cs index d2d80ba..fe1a102 100644 --- a/HexcalMC/Motion/EtalonForm.cs +++ b/HexcalMC/Motion/EtalonForm.cs @@ -1,641 +1,783 @@ -using ScottPlot.Plottable; -using ScottPlot; -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Diagnostics; using System.Drawing; +using System.Drawing.Imaging; +using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; +using System.Threading; using System.Threading.Tasks; +using System.Timers; using System.Windows.Forms; - +using ACS.SPiiPlusNET; +using HexcalMC.Base; using Plot3D; - -// enums -using eRaster = Plot3D.Editor3D.eRaster; -using ePolygonMode = Plot3D.Editor3D.ePolygonMode; -using eSelEvent = Plot3D.Editor3D.eSelEvent; -using eSelType = Plot3D.Editor3D.eSelType; -using eObjType = Plot3D.Editor3D.eObjType; -using eTooltip = Plot3D.Editor3D.eTooltip; -using eNormalize = Plot3D.Editor3D.eNormalize; -using eMouseCtrl = Plot3D.Editor3D.eMouseCtrl; -using eScatterShape = Plot3D.Editor3D.eScatterShape; -using eColorScheme = Plot3D.Editor3D.eColorScheme; -using eInvalidate = Plot3D.Editor3D.eInvalidate; -using eLegendPos = Plot3D.Editor3D.eLegendPos; - +using ScottPlot; +using ScottPlot.Plottable; +using Telerik.WinControls; +using Telerik.WinControls.UI; +using static Plot3D.Editor3D; +using static Telerik.WinControls.UI.ValueMapper; +using cColorScheme = Plot3D.Editor3D.cColorScheme; +using cLine3D = Plot3D.Editor3D.cLine3D; +using cLineData = Plot3D.Editor3D.cLineData; +using cMessgData = Plot3D.Editor3D.cMessgData; // classes using cObject3D = Plot3D.Editor3D.cObject3D; using cPoint3D = Plot3D.Editor3D.cPoint3D; -using cShape3D = Plot3D.Editor3D.cShape3D; -using cLine3D = Plot3D.Editor3D.cLine3D; using cPolygon3D = Plot3D.Editor3D.cPolygon3D; -using cColorScheme = Plot3D.Editor3D.cColorScheme; -using cMessgData = Plot3D.Editor3D.cMessgData; -using cSurfaceData = Plot3D.Editor3D.cSurfaceData; -using cScatterData = Plot3D.Editor3D.cScatterData; -using cLineData = Plot3D.Editor3D.cLineData; using cPolygonData = Plot3D.Editor3D.cPolygonData; +using cScatterData = Plot3D.Editor3D.cScatterData; +using cShape3D = Plot3D.Editor3D.cShape3D; +using cSurfaceData = Plot3D.Editor3D.cSurfaceData; using cUserInput = Plot3D.Editor3D.cUserInput; - // callback function using delRendererFunction = Plot3D.Editor3D.delRendererFunction; -using static Plot3D.Editor3D; -using System.Diagnostics; -using System.Drawing.Imaging; -using System.Text.RegularExpressions; -using System.IO; -using Telerik.WinControls; -using static Telerik.WinControls.UI.ValueMapper; -using HexcalMC.Base; -using ACS.SPiiPlusNET; +using eColorScheme = Plot3D.Editor3D.eColorScheme; +using eInvalidate = Plot3D.Editor3D.eInvalidate; +using eLegendPos = Plot3D.Editor3D.eLegendPos; +using eMouseCtrl = Plot3D.Editor3D.eMouseCtrl; +using eNormalize = Plot3D.Editor3D.eNormalize; +using eObjType = Plot3D.Editor3D.eObjType; +using ePolygonMode = Plot3D.Editor3D.ePolygonMode; +// enums +using eRaster = Plot3D.Editor3D.eRaster; +using eScatterShape = Plot3D.Editor3D.eScatterShape; +using eSelEvent = Plot3D.Editor3D.eSelEvent; +using eSelType = Plot3D.Editor3D.eSelType; +using eTooltip = Plot3D.Editor3D.eTooltip; namespace HexcalMC { - internal enum eDemo - { - Math_Callback, - Math_Formula, - Surface_Fill, - Surface_Grid, - Surface_Fill_Missing, - Surface_Grid_Missing, - Nested_Graphs, - Scatter_Plot, - Connected_Lines, - Scatter_Shapes, - Pyramid, - Sphere_Fill_Closed, - Sphere_Fill_Open, - Sphere_Grid, - Valentine, - Animation, - } + internal enum eDemo + { + Math_Callback, + Math_Formula, + Surface_Fill, + Surface_Grid, + Surface_Fill_Missing, + Surface_Grid_Missing, + Nested_Graphs, + Scatter_Plot, + Connected_Lines, + Scatter_Shapes, + Pyramid, + Sphere_Fill_Closed, + Sphere_Fill_Open, + Sphere_Grid, + Valentine, + Animation, + } - public partial class EtalonForm : System.Windows.Forms.Form - { - private eDemo me_Demo; - private eColorScheme me_ColorScheme; - private Timer mi_StatusTimer = new Timer(); - private cMessgData mi_MesgTop = new cMessgData("", -7, 7, Color.Blue); // For special hint - private cMessgData mi_MesgBottom = new cMessgData("", -7, -7, Color.Gray); // For selection mode + public partial class EtalonForm : System.Windows.Forms.Form + { + private eDemo me_Demo; + private eColorScheme me_ColorScheme; + private System.Windows.Forms.Timer mi_StatusTimer = new System.Windows.Forms.Timer(); + private cMessgData mi_MesgTop = new cMessgData("", -7, 7, Color.Blue); // For special hint + private cMessgData mi_MesgBottom = new cMessgData("", -7, -7, Color.Gray); // For selection mode - // Only for demo "Animation" - private Timer mi_AnimationTimer = new Timer(); + // Only for demo "Animation" + private System.Windows.Forms.Timer mi_AnimationTimer = new System.Windows.Forms.Timer(); - private cScatterData mi_SinusData; - private cPoint3D[] mi_Pyramid; - private int ms32_AnimationAngle; + private cScatterData mi_SinusData; + private cPoint3D[] mi_Pyramid; + private int ms32_AnimationAngle; - // etalon解析变量 - private List etalon_points = new List(); + // etalon解析变量 + private List etalon_points = new List(); - private List filteredPoints = new List(); //过滤后的点 - private List dwellTimes = new List(); + private List filteredPoints = new List(); //过滤后的点 + private List dwellTimes = new List(); - private static Timer refresh_time = new Timer(); - private static int currentIndex = 0; + private static System.Windows.Forms.Timer refresh_time = new System.Windows.Forms.Timer(); + private static int currentIndex = 0; - private readonly MainFrom mainFrom; - private readonly Api _acs; //ACS控制器 + private readonly MainFrom mainFrom; + private readonly Api _acs; //ACS控制器 - public EtalonForm(MainFrom _mainFrom) - { - InitializeComponent(); - mainFrom = _mainFrom; - this._acs = _mainFrom._acs; - } + public Axis[] axes = + { + Axis.ACSC_AXIS_0, + Axis.ACSC_AXIS_1, + Axis.ACSC_AXIS_8, + Axis.ACSC_NONE, + }; //使能的轴 - private void EtalonForm_Load(object sender, EventArgs e) - { - InitScatterPlot(); //清空绘图 + public class Point + { + public double X { get; } + public double Y { get; } + public double Z { get; } - DebugDfn.textBox_Msg = this.text_etalon_info; - } + public Point(double x, double y, double z) + { + X = x; + Y = y; + Z = z; + } - private void InitScatterPlot() //绘图区初始化 - { - comboColors.Sorted = false; - foreach (eColorScheme e_Scheme in Enum.GetValues(typeof(eColorScheme))) - { - comboColors.Items.Add(e_Scheme.ToString().Replace('_', ' ')); - } - comboColors.SelectedIndex = (int)eColorScheme.Monochrome; //默认色卡 + // 从 Point 转换 + public static Point3D FromPoint(Point point) + { + return new Point3D(point.X, point.Y, point.Z); + } + } - comboRaster.Sorted = false; - foreach (eRaster e_Raster in Enum.GetValues(typeof(eRaster))) - { - comboRaster.Items.Add(e_Raster); - } - comboRaster.SelectedIndex = (int)eRaster.Labels; //坐标系栅格样式 + public EtalonForm(MainFrom _mainFrom) + { + InitializeComponent(); + mainFrom = _mainFrom; + this._acs = _mainFrom._acs; + } - //设置默认 - comboMouse.SelectedIndex = 0; + private void EtalonForm_Load(object sender, EventArgs e) + { + InitScatterPlot(); //清空绘图 - // 设置定时器 - refresh_time.Interval = 100; - refresh_time.Tick += new EventHandler(OnAnimationTimer); - refresh_time.Start(); - } + DebugDfn.textBox_Msg = this.text_etalon_info; + } - private void DemoScatterPlot(bool b_Lines) - { - comboColors.Enabled = true; // Some of the demos will disable this combobox - me_ColorScheme = (eColorScheme)comboColors.SelectedIndex; + #region 绘图区功能 + private void InitScatterPlot() //绘图区初始化 + { + comboColors.Sorted = false; + foreach (eColorScheme e_Scheme in Enum.GetValues(typeof(eColorScheme))) + { + comboColors.Items.Add(e_Scheme.ToString().Replace('_', ' ')); + } + comboColors.SelectedIndex = (int)eColorScheme.Monochrome; //默认色卡 - checkMirrorX.Checked = editor3D.AxisX.Mirror; - checkMirrorY.Checked = editor3D.AxisY.Mirror; + comboRaster.Sorted = false; + foreach (eRaster e_Raster in Enum.GetValues(typeof(eRaster))) + { + comboRaster.Items.Add(e_Raster); + } + comboRaster.SelectedIndex = (int)eRaster.Labels; //坐标系栅格样式 - // 3 pixels for line width and for circle radius - const int SIZE = 3; + //设置默认 + comboMouse.SelectedIndex = 0; - cColorScheme i_Scheme = new cColorScheme(me_ColorScheme); - cScatterData i_ShapeData = new cScatterData(i_Scheme); - cLineData i_LineData = new cLineData(i_Scheme); - List i_Points = new List(); + // 设置定时器 + refresh_time.Interval = 100; + refresh_time.Tick += new EventHandler(OnAnimationTimer); + refresh_time.Start(); + } - for (double P = -22.0; P < 22.0; P += 0.1) - { - double d_X = Math.Sin(P) * P; - double d_Y = Math.Cos(P) * P; - double d_Z = P; - if (d_Z > 0.0) d_Z /= 3.0; + private void DemoScatterPlot(bool b_Lines) + { + comboColors.Enabled = true; // Some of the demos will disable this combobox + me_ColorScheme = (eColorScheme)comboColors.SelectedIndex; - cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); - if (b_Lines) - { - i_Points.Add(i_Point); - } - else // Shapes - { - // You can store the returned shape in a variable and later modify it's properties - cShape3D i_Shape = i_ShapeData.AddShape(i_Point, eScatterShape.Circle, SIZE, null); - } - } + checkMirrorX.Checked = editor3D.AxisX.Mirror; + checkMirrorY.Checked = editor3D.AxisY.Mirror; - // You can store the returned lines in a variable and later modify their properties - cLine3D[] i_Lines = i_LineData.AddConnectedLines(i_Points, SIZE, null); + // 3 pixels for line width and for circle radius + const int SIZE = 3; - // Depending on your use case you can also specify MaintainXY or MaintainXYZ here - editor3D.Clear(); - editor3D.Normalize = eNormalize.Separate; - editor3D.AddRenderData(i_ShapeData, i_LineData); + cColorScheme i_Scheme = new cColorScheme(me_ColorScheme); + cScatterData i_ShapeData = new cScatterData(i_Scheme); + cLineData i_LineData = new cLineData(i_Scheme); + List i_Points = new List(); - editor3D.Selection.HighlightColor = Color.FromArgb(90, 90, 90); - editor3D.Selection.Callback = OnSelectEvent; - editor3D.Selection.MultiSelect = true; - editor3D.Selection.Enabled = true; - editor3D.UndoBuffer.Enabled = true; - editor3D.Invalidate(); - } + for (double P = -22.0; P < 22.0; P += 0.1) + { + double d_X = Math.Sin(P) * P; + double d_Y = Math.Cos(P) * P; + double d_Z = P; + if (d_Z > 0.0) + d_Z /= 3.0; - private eInvalidate OnSelectEvent(eSelEvent e_Event, Keys e_Modifiers, int s32_DeltaX, int s32_DeltaY, cObject3D i_Object)// - { - eInvalidate e_Invalidate = eInvalidate.NoChange; + cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); + if (b_Lines) + { + i_Points.Add(i_Point); + } + else // Shapes + { + // You can store the returned shape in a variable and later modify it's properties + cShape3D i_Shape = i_ShapeData.AddShape( + i_Point, + eScatterShape.Circle, + SIZE, + null + ); + } + } - bool b_CTRL = (e_Modifiers & Keys.Control) > 0; + // You can store the returned lines in a variable and later modify their properties + cLine3D[] i_Lines = i_LineData.AddConnectedLines(i_Points, SIZE, null); - // The left mouse button went down with ALT key down and CTRL key up - if (e_Event == eSelEvent.MouseDown && !b_CTRL && i_Object != null) - { - i_Object.Selected = !i_Object.Selected; + // Depending on your use case you can also specify MaintainXY or MaintainXYZ here + editor3D.Clear(); + editor3D.Normalize = eNormalize.Separate; + editor3D.AddRenderData(i_ShapeData, i_LineData); - // After changing the selection status the object must be redrawn. - e_Invalidate = eInvalidate.Invalidate; - } - else if (e_Event == eSelEvent.MouseDrag && b_CTRL) - { - // The user is dragging the mouse with ALT + CTRL keys down. Convert the mouse - // movement in the 2D space into a movement in the 3D space. - cPoint3D i_Project = editor3D.ReverseProject(s32_DeltaX, s32_DeltaY); + editor3D.Selection.HighlightColor = Color.FromArgb(90, 90, 90); + editor3D.Selection.Callback = OnSelectEvent; + editor3D.Selection.MultiSelect = true; + editor3D.Selection.Enabled = true; + editor3D.UndoBuffer.Enabled = true; + editor3D.Invalidate(); + } - // GetSelectedPoints() returns only unique points. - cPoint3D[] i_Selected = editor3D.Selection.GetSelectedPoints(eSelType.All); - foreach (cPoint3D i_Point in i_Selected) - { - switch (me_Demo) - { - case eDemo.Pyramid: - case eDemo.Scatter_Shapes: - case eDemo.Scatter_Plot: - case eDemo.Connected_Lines: - // The pyramid line end points / scatter shapes can be moved freely in - // the 3D space - i_Point.Move(i_Project.X, i_Project.Y, i_Project.Z); - break; + private eInvalidate OnSelectEvent( + eSelEvent e_Event, + Keys e_Modifiers, + int s32_DeltaX, + int s32_DeltaY, + cObject3D i_Object + ) // + { + eInvalidate e_Invalidate = eInvalidate.NoChange; - case eDemo.Surface_Fill: - case eDemo.Surface_Grid: - case eDemo.Surface_Fill_Missing: - case eDemo.Surface_Grid_Missing: - // The points in the Surface grid have a fixed X,Y position, only Z can - // be modified. - i_Point.Move(0, 0, i_Project.Z); - break; + bool b_CTRL = (e_Modifiers & Keys.Control) > 0; - default: - Debug.Assert(false); - break; - } - } + // The left mouse button went down with ALT key down and CTRL key up + if (e_Event == eSelEvent.MouseDown && !b_CTRL && i_Object != null) + { + i_Object.Selected = !i_Object.Selected; - // Set flag to recalculate the coordinate system, then Invalidate() - e_Invalidate = eInvalidate.CoordSystem; - } + // After changing the selection status the object must be redrawn. + e_Invalidate = eInvalidate.Invalidate; + } + else if (e_Event == eSelEvent.MouseDrag && b_CTRL) + { + // The user is dragging the mouse with ALT + CTRL keys down. Convert the mouse + // movement in the 2D space into a movement in the 3D space. + cPoint3D i_Project = editor3D.ReverseProject(s32_DeltaX, s32_DeltaY); - mi_StatusTimer.Stop(); + // GetSelectedPoints() returns only unique points. + cPoint3D[] i_Selected = editor3D.Selection.GetSelectedPoints(eSelType.All); + foreach (cPoint3D i_Point in i_Selected) + { + switch (me_Demo) + { + case eDemo.Pyramid: + case eDemo.Scatter_Shapes: + case eDemo.Scatter_Plot: + case eDemo.Connected_Lines: + // The pyramid line end points / scatter shapes can be moved freely in + // the 3D space + i_Point.Move(i_Project.X, i_Project.Y, i_Project.Z); + break; - mi_StatusTimer.Start(); - return e_Invalidate; - } + case eDemo.Surface_Fill: + case eDemo.Surface_Grid: + case eDemo.Surface_Fill_Missing: + case eDemo.Surface_Grid_Missing: + // The points in the Surface grid have a fixed X,Y position, only Z can + // be modified. + i_Point.Move(0, 0, i_Project.Z); + break; - private void comboRaster_SelectedIndexChanged(object sender, EventArgs e) //坐标栅格样式 - { - editor3D.Raster = (eRaster)comboRaster.SelectedIndex; - editor3D.Invalidate(); - } + default: + Debug.Assert(false); + break; + } + } - private void checkMirrorY_CheckedChanged(object sender, EventArgs e) //Y轴镜像 - { - editor3D.AxisY.Mirror = checkMirrorY.Checked; - editor3D.Invalidate(); - } + // Set flag to recalculate the coordinate system, then Invalidate() + e_Invalidate = eInvalidate.CoordSystem; + } - private void checkMirrorX_CheckedChanged(object sender, EventArgs e) //x轴镜像 - { - editor3D.AxisX.Mirror = checkMirrorX.Checked; - editor3D.Invalidate(); - } + mi_StatusTimer.Stop(); - private void btnReset_Click(object sender, EventArgs e) //重置视图 - { - editor3D.SetCoefficients(1350, 70, 230); - editor3D.Invalidate(); - } + mi_StatusTimer.Start(); + return e_Invalidate; + } - private void btnScreenshot_Click(object sender, EventArgs e) //截图保存 - { - SaveFileDialog i_Dlg = new SaveFileDialog(); - i_Dlg.Title = "Save as PNG image"; - i_Dlg.Filter = "PNG Image|*.png"; - i_Dlg.DefaultExt = ".png"; + private void comboRaster_SelectedIndexChanged(object sender, EventArgs e) //坐标栅格样式 + { + editor3D.Raster = (eRaster)comboRaster.SelectedIndex; + editor3D.Invalidate(); + } - if (DialogResult.Cancel == i_Dlg.ShowDialog(this)) - return; + private void checkMirrorY_CheckedChanged(object sender, EventArgs e) //Y轴镜像 + { + editor3D.AxisY.Mirror = checkMirrorY.Checked; + editor3D.Invalidate(); + } - Bitmap i_Bitmap = editor3D.GetScreenshot(); - try - { - i_Bitmap.Save(i_Dlg.FileName, ImageFormat.Png); - } - catch (Exception Ex) - { - MessageBox.Show(this, Ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } + private void checkMirrorX_CheckedChanged(object sender, EventArgs e) //x轴镜像 + { + editor3D.AxisX.Mirror = checkMirrorX.Checked; + editor3D.Invalidate(); + } - private void comboMouse_SelectedIndexChanged(object sender, EventArgs e) //鼠标控制方式 - { - switch (comboMouse.SelectedIndex) - { - case 0: - editor3D.SetUserInputs(eMouseCtrl.L_Theta_R_Phi); - labelMouseInfo.Text = "鼠标左键:升高,鼠标右键:旋转"; - break; + private void btnReset_Click(object sender, EventArgs e) //重置视图 + { + editor3D.SetCoefficients(1350, 70, 230); + editor3D.Invalidate(); + } - case 1: - editor3D.SetUserInputs(eMouseCtrl.L_Theta_L_Phi); - labelMouseInfo.Text = "鼠标左键:升高和旋转"; - break; + private void btnScreenshot_Click(object sender, EventArgs e) //截图保存 + { + SaveFileDialog i_Dlg = new SaveFileDialog(); + i_Dlg.Title = "Save as PNG image"; + i_Dlg.Filter = "PNG Image|*.png"; + i_Dlg.DefaultExt = ".png"; - case 2: - editor3D.SetUserInputs(eMouseCtrl.M_Theta_M_Phi); - labelMouseInfo.Text = "鼠标中键:升高和旋转"; - break; + if (DialogResult.Cancel == i_Dlg.ShowDialog(this)) + return; - default: - Debug.Assert(false); - break; - } + Bitmap i_Bitmap = editor3D.GetScreenshot(); + try + { + i_Bitmap.Save(i_Dlg.FileName, ImageFormat.Png); + } + catch (Exception Ex) + { + MessageBox.Show( + this, + Ex.Message, + "Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + } + } - labelMouseInfo.Text += ", 鼠标左键 + SHIFT:移动、鼠标左键 + CTRL 或滚轮:缩放、鼠标左键 + ALT:选择"; - } + private void comboMouse_SelectedIndexChanged(object sender, EventArgs e) //鼠标控制方式 + { + switch (comboMouse.SelectedIndex) + { + case 0: + editor3D.SetUserInputs(eMouseCtrl.L_Theta_R_Phi); + labelMouseInfo.Text = "鼠标左键:升高,鼠标右键:旋转"; + break; - private void comboColors_SelectedIndexChanged(object sender, EventArgs e) - { - me_ColorScheme = (eColorScheme)comboColors.SelectedIndex; + case 1: + editor3D.SetUserInputs(eMouseCtrl.L_Theta_L_Phi); + labelMouseInfo.Text = "鼠标左键:升高和旋转"; + break; - //判断 points 是否为空,表示当前是否已经有真实数据 - if (etalon_points.Count > 0) - { - PointScatterPlot(etalon_points); //更新真实数据 - } - //else - //{ - // DemoScatterPlot(false); //更新虚拟数据 - //} - } + case 2: + editor3D.SetUserInputs(eMouseCtrl.M_Theta_M_Phi); + labelMouseInfo.Text = "鼠标中键:升高和旋转"; + break; - private void btn_startmove_Click(object sender, EventArgs e) //开始运动 - { - DebugDfn.AddLogText("开始运动"); - int timeout = 5000; + default: + Debug.Assert(false); + break; + } - Axis[] axes = { Axis.ACSC_AXIS_0, Axis.ACSC_AXIS_1, Axis.ACSC_AXIS_8, Axis.ACSC_NONE }; + labelMouseInfo.Text += + ", 鼠标左键 + SHIFT:移动、鼠标左键 + CTRL 或滚轮:缩放、鼠标左键 + ALT:选择"; + } - //判断电机状态 - if (!mainFrom.totalAxisEnabled) - { - DebugDfn.AddLogText("存在电机未使能"); + private void comboColors_SelectedIndexChanged(object sender, EventArgs e) + { + me_ColorScheme = (eColorScheme)comboColors.SelectedIndex; - _acs.WaitMotorEnabled(Axis.ACSC_AXIS_0, 1, timeout); //Y轴 - // Wait axis 1 enabled during 5 sec - _acs.WaitMotorEnabled(Axis.ACSC_AXIS_1, 1, timeout); + //判断 points 是否为空,表示当前是否已经有真实数据 + if (etalon_points.Count > 0) + { + PointScatterPlot(etalon_points); //更新真实数据 + } + //else + //{ + // DemoScatterPlot(false); //更新虚拟数据 + //} + } + #endregion - _acs.WaitMotorEnabled(Axis.ACSC_AXIS_8, 1, timeout); + #region etalon文件解析 + private void moveToPoint() + { + DebugDfn.AddLogText("添加到运动队列"); + int timeout = 5000; - DebugDfn.AddLogText("电机已启用"); - } + //判断电机状态 + if (!mainFrom.totalAxisEnabled) + { + DebugDfn.AddLogText("存在电机未使能"); - // 创建多点运动 - double dwellTime = dwellTimes.Average()*1000; //将秒转换为毫秒 - DebugDfn.AddLogText("平均停顿时间(毫秒):" + dwellTime); - _acs.MultiPointM(MotionFlags.ACSC_NONE, axes, dwellTime); + _acs.WaitMotorEnabled(Axis.ACSC_AXIS_0, 1, timeout); //Y轴 + // Wait axis 1 enabled during 5 sec + _acs.WaitMotorEnabled(Axis.ACSC_AXIS_1, 1, timeout); - //判断是否有点 - if (filteredPoints.Count == 0) - { - DebugDfn.AddLogText("没有点"); - return; - } + _acs.WaitMotorEnabled(Axis.ACSC_AXIS_8, 1, timeout); - // 添加符合条件的点到运动路径中 - foreach (var point in filteredPoints) - { - double[] points = new double[3]; - points[0] = point.Y; - points[1] = point.X; - points[2] = point.Z; - _acs.AddPointM(axes, points); + //DebugDfn.AddLogText("电机已启用"); + } - } - // 打印添加点的数量 - DebugDfn.AddLogText("添加点的数量:" + filteredPoints.Count); + // 创建多点运动 + double dwellTime = dwellTimes.Average() * 1000; //将秒转换为毫秒 + DebugDfn.AddLogText("平均停顿时间(毫秒):" + dwellTime); + _acs.MultiPointM(MotionFlags.ACSC_NONE, axes, dwellTime); - // Finish the motion End of the multi-point motion - _acs.EndSequenceM(axes); + //判断是否有点 + if (filteredPoints.Count == 0) + { + DebugDfn.AddLogText("没有点"); + return; + } + //打印点的数量 + DebugDfn.AddLogText("待添加点的数量:" + filteredPoints.Count); + // 添加符合条件的点到运动路径中 + foreach (var point in filteredPoints) + { + double[] points = new double[3]; + points[0] = point.Y; + points[1] = point.X; + points[2] = point.Z; + _acs.AddPointM(axes, points); + //打印添加的点 + DebugDfn.AddLogText("添加点:" + points[0] + " " + points[1] + " " + points[2]); + } + // 打印添加点的数量 + DebugDfn.AddLogText("已添加点的数量:" + filteredPoints.Count); - //启动统计 - mainFrom.StartCounting(); - } + // Finish the motion End of the multi-point motion + _acs.EndSequenceM(axes); - private void btn_stop_Click(object sender, EventArgs e) //停止运动 - { - DebugDfn.AddLogText("停止运动"); - try - { - Axis[] m_arrAxisList = new Axis[] { Axis.ACSC_AXIS_0, Axis.ACSC_AXIS_1, Axis.ACSC_AXIS_8, Axis.ACSC_NONE }; + mainFrom.StopCounting(); + //启动统计 + mainFrom.StartCounting(); + } - if (m_arrAxisList != null) _acs.HaltM(m_arrAxisList); + private void btn_startmove_Click(object sender, EventArgs e) //开始运动 + { + int timeout = 5000; + //判断电机状态 + if (!mainFrom.totalAxisEnabled) + { + DebugDfn.AddLogText("存在电机未使能"); - DebugDfn.AddLogText("立即停止 已发送命令"); - } - catch (Exception ex) - { - MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); - Debug.WriteLine(ex.Message); - } + _acs.WaitMotorEnabled(Axis.ACSC_AXIS_0, 1, timeout); //Y轴 + // Wait axis 1 enabled during 5 sec + _acs.WaitMotorEnabled(Axis.ACSC_AXIS_1, 1, timeout); - //停止统计 - mainFrom.StopCounting(); + _acs.WaitMotorEnabled(Axis.ACSC_AXIS_8, 1, timeout); + + //DebugDfn.AddLogText("电机已启用"); + } + + //判断是否有点 + if (filteredPoints.Count == 0) + { + MessageBox.Show("没有需要移动的点,请先导入", "ERROR"); + return; + } + //打印点的数量 + DebugDfn.AddLogText("待添加点的数量:" + filteredPoints.Count); + + //启动运动定时器 + timer_move.Start(); + refresh_time.Start(); + } + + private void btn_stop_Click(object sender, EventArgs e) //停止运动 + { + DebugDfn.AddLogText("停止运动"); + try + { + Axis[] m_arrAxisList = new Axis[] + { + Axis.ACSC_AXIS_0, + Axis.ACSC_AXIS_1, + Axis.ACSC_AXIS_8, + Axis.ACSC_NONE, + }; + + if (m_arrAxisList != null) + _acs.HaltM(m_arrAxisList); + + DebugDfn.AddLogText("立即停止 已发送命令"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); + Debug.WriteLine(ex.Message); + } + + //停止统计 + mainFrom.StopCounting(); + refresh_time.Stop(); + timer_move.Stop(); + currentIndex = 0; + + } private void btn_etalon_import_Click(object sender, EventArgs e) //解析Etalon文件 - { - //打开文件对号框,选择 mpf格式文件 - OpenFileDialog i_Dlg = new OpenFileDialog(); - i_Dlg.Title = "导入Etalon文件"; - i_Dlg.Filter = "Etalon文件|*.mpf"; - i_Dlg.DefaultExt = ".mpf"; - i_Dlg.Multiselect = false; + { + //打开文件对号框,选择 mpf格式文件 + OpenFileDialog i_Dlg = new OpenFileDialog(); + i_Dlg.Title = "导入Etalon文件"; + i_Dlg.Filter = "Etalon文件|*.mpf"; + i_Dlg.DefaultExt = ".mpf"; + i_Dlg.Multiselect = false; - if (DialogResult.Cancel == i_Dlg.ShowDialog(this)) - return; + if (DialogResult.Cancel == i_Dlg.ShowDialog(this)) + return; - //读取文件 - string s_File = i_Dlg.FileName; + //读取文件 + string s_File = i_Dlg.FileName; - //设置路径显示 + //设置路径显示 - DebugDfn.AddLogText("导入Etalon文件:" + s_File); + DebugDfn.AddLogText("导入Etalon文件:" + s_File); - //解析文件 - parse_mpf_file(s_File); + //解析文件 + parse_mpf_file(s_File); - DebugDfn.AddLogText("Etalon文件解析完成"); - } + DebugDfn.AddLogText("Etalon文件解析完成"); + } - private bool parse_mpf_file(string mpf_file_path) // 编写解析mpf文件的函数 - { - //; Machine: ZIM - //; Position: 1 - //; Created: 2/15/2023 12:29:13 PM - //; Program: TRAC-CAL V48, Build: 10, 5/13/2022 8:29:25 AM - //; File: 'cncData.xml' - //G71 - //G90 - //G500 - //G01 X8000.000 Y200.000 Z-1400.000 F2000 //坐标 - //G04 F=2 // 停顿时间 - //G01 X7800.000 Y300.000 Z-1400.000 F2000 - //G04 F=2 - //G01 X7600.000 Y400.000 Z-1400.000 F2000 - //G04 F=2 - //G01 X7400.000 Y500.000 Z-1400.000 F2000 - //G04 F=2 - //G01 X7200.000 Y600.000 Z-1400.000 F2000 + private bool parse_mpf_file(string mpf_file_path) // 编写解析mpf文件的函数 + { + //; Machine: ZIM + //; Position: 1 + //; Created: 2/15/2023 12:29:13 PM + //; Program: TRAC-CAL V48, Build: 10, 5/13/2022 8:29:25 AM + //; File: 'cncData.xml' + //G71 + //G90 + //G500 + //G01 X8000.000 Y200.000 Z-1400.000 F2000 //坐标 + //G04 F=2 // 停顿时间 + //G01 X7800.000 Y300.000 Z-1400.000 F2000 + //G04 F=2 + //G01 X7600.000 Y400.000 Z-1400.000 F2000 + //G04 F=2 + //G01 X7400.000 Y500.000 Z-1400.000 F2000 + //G04 F=2 + //G01 X7200.000 Y600.000 Z-1400.000 F2000 - //判断文件是否存在 - if (!File.Exists(mpf_file_path)) - { - MessageBox.Show("文件不存在"); - return false; + //判断文件是否存在 + if (!File.Exists(mpf_file_path)) + { + MessageBox.Show("文件不存在"); + return false; + } + + //清空之前的数据 + etalon_points.Clear(); + filteredPoints.Clear(); + dwellTimes.Clear(); + + //读取文件 + string[] lines = File.ReadAllLines(mpf_file_path); + Regex regex = new Regex( + @"G01 X(?[-+]?\d*\.?\d+) Y(?[-+]?\d*\.?\d+) Z(?[-+]?\d*\.?\d+)" + ); + Regex dwellRegex = new Regex(@"G04 F=(?\d+)"); + + foreach (string line in lines) + { + Match match = regex.Match(line); + if (match.Success) + { + double x = double.Parse(match.Groups["X"].Value); + double y = double.Parse(match.Groups["Y"].Value); + double z = double.Parse(match.Groups["Z"].Value); + etalon_points.Add(new Point(x, y, z)); + } + + Match dwellMatch = dwellRegex.Match(line); + if (dwellMatch.Success) + { + int f = int.Parse(dwellMatch.Groups["F"].Value); + dwellTimes.Add(f); + } + } + + // 输出解析结果 + //Console.WriteLine("Points:"); + //foreach (var point in etalon_points) + //{ + // Console.WriteLine($"X: {point.X}, Y: {point.Y}, Z: {point.Z}"); + //} + + //Console.WriteLine("Dwell Times:"); + //foreach (var dwellTime in dwellTimes) + //{ + // Console.WriteLine($"F: {dwellTime}"); + //} + + //过滤点集 + foreach (var point in etalon_points) + { + if (MainFrom.IsWithinLimit(point)) //判断点是否在行程范围内 + { + filteredPoints.Add(point); + } + } + + //打印过滤后的点集大小 + DebugDfn.AddLogText("过滤后的点集大小:" + filteredPoints.Count); + PointScatterPlot(filteredPoints); //绘制散点图 + return true; + } + + #endregion + + #region 3D绘图逻辑 + private void PointScatterPlot(List points) //绘制散点图 + { + //清空绘图 + editor3D.Clear(); + editor3D.Normalize = eNormalize.Separate; + editor3D.Invalidate(); + + //判断点集是否为空 + comboColors.Enabled = true; // Some of the demos will disable this combobox + me_ColorScheme = (eColorScheme)comboColors.SelectedIndex; + + checkMirrorX.Checked = editor3D.AxisX.Mirror; + checkMirrorY.Checked = editor3D.AxisY.Mirror; + + // 3 pixels for line width and for circle radius + const int SIZE = 3; + + cColorScheme i_Scheme = new cColorScheme(me_ColorScheme); + cScatterData i_ShapeData = new cScatterData(i_Scheme); + cLineData i_LineData = new cLineData(i_Scheme); + List i_Points = new List(); + + foreach (var point in points) + { + double d_X = point.X; + double d_Y = point.Y; + double d_Z = point.Z; + + cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); + + // You can store the returned shape in a variable and later modify it's properties + cShape3D i_Shape = i_ShapeData.AddShape(i_Point, eScatterShape.Circle, SIZE, null); + } + + // You can store the returned lines in a variable and later modify their properties + cLine3D[] i_Lines = i_LineData.AddConnectedLines(i_Points, SIZE, null); + + // Depending on your use case you can also specify MaintainXY or MaintainXYZ here + editor3D.Clear(); + editor3D.Normalize = eNormalize.Separate; + editor3D.AddRenderData(i_ShapeData, i_LineData); + + editor3D.Selection.HighlightColor = Color.FromArgb(90, 90, 90); + editor3D.Selection.Callback = OnSelectEvent; + editor3D.Selection.MultiSelect = true; + editor3D.Selection.Enabled = true; + editor3D.UndoBuffer.Enabled = true; + editor3D.Invalidate(); + } + + private void btn_clear_Click(object sender, EventArgs e) //清空绘图 + { + editor3D.Clear(); + editor3D.Normalize = eNormalize.Separate; + editor3D.Invalidate(); + } + + private void btn_draw_test_Click(object sender, EventArgs e) + { + DemoScatterPlot(false); + } + + private void OnAnimationTimer(object sender, EventArgs e) + { + cScatterData i_ShapeData = new cScatterData(); + //currentIndex = mainFrom.GetInPosCount();//获取当前点的数量 + + if (currentIndex < filteredPoints.Count) + { + + + // 更新点的颜色 + for (int i = 0; i <= currentIndex; i++) + { + double d_X = filteredPoints[i].X; + double d_Y = filteredPoints[i].Y; + double d_Z = filteredPoints[i].Z; + + cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); + SolidBrush i_brush = new SolidBrush(Color.Red); + // You can store the returned shape in a variable and later modify it's properties + cShape3D i_Shape = i_ShapeData.AddShape( + i_Point, + eScatterShape.Circle, + 5, + i_brush, + null + ); + } + + // 对于剩余部分的点,不做颜色更新 + for (int i = currentIndex; i < filteredPoints.Count; i++) + { + double d_X = filteredPoints[i].X; + double d_Y = filteredPoints[i].Y; + double d_Z = filteredPoints[i].Z; + + cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); + SolidBrush i_brush = new SolidBrush(Color.Gray); + // You can store the returned shape in a variable and later modify it's properties + cShape3D i_Shape = i_ShapeData.AddShape( + i_Point, + eScatterShape.Circle, + 3, + i_brush, + null + ); + } + + editor3D.Clear(); + editor3D.Normalize = eNormalize.Separate; + editor3D.AddRenderData(i_ShapeData); + editor3D.Invalidate(); } + } + #endregion - //清空之前的数据 - etalon_points.Clear(); - filteredPoints.Clear(); - dwellTimes.Clear(); + #region 队列移动逻辑 + private void timer_move_Tick(object sender, EventArgs e) + { + // 检查是否到达目标点 + if (IsAtTarget()) + { + // 移动到下一个点 + MoveToNextPoint(); + } + } - //读取文件 - string[] lines = File.ReadAllLines(mpf_file_path); - Regex regex = new Regex(@"G01 X(?[-+]?\d*\.?\d+) Y(?[-+]?\d*\.?\d+) Z(?[-+]?\d*\.?\d+)"); - Regex dwellRegex = new Regex(@"G04 F=(?\d+)"); + private void MoveToNextPoint() + { + if (filteredPoints.Count > 0 && currentIndex < filteredPoints.Count) + { + //增加2秒延时 + Thread.Sleep(2000); - foreach (string line in lines) - { - Match match = regex.Match(line); - if (match.Success) - { - double x = double.Parse(match.Groups["X"].Value); - double y = double.Parse(match.Groups["Y"].Value); - double z = double.Parse(match.Groups["Z"].Value); - etalon_points.Add(new Point(x, y, z)); - } + Point nextPoint = filteredPoints[currentIndex]; + //打印 nextPoint + DebugDfn.AddLogText("下发指令:" + currentIndex + " 点:" + nextPoint.X + " " + nextPoint.Y + " " + nextPoint.Z ); - Match dwellMatch = dwellRegex.Match(line); - if (dwellMatch.Success) - { - int f = int.Parse(dwellMatch.Groups["F"].Value); - dwellTimes.Add(f); - } - } + mainFrom.SetPositionXyz(Point.FromPoint(nextPoint)); //移动到下一个点 - // 输出解析结果 - //Console.WriteLine("Points:"); - //foreach (var point in etalon_points) - //{ - // Console.WriteLine($"X: {point.X}, Y: {point.Y}, Z: {point.Z}"); - //} + currentIndex++; + } + else + { + DebugDfn.AddLogText("All points have been visited."); + timer_move.Stop(); + } + } - //Console.WriteLine("Dwell Times:"); - //foreach (var dwellTime in dwellTimes) - //{ - // Console.WriteLine($"F: {dwellTime}"); - //} + private bool IsAtTarget() + { + // 这里你需要实现实际的到位判断逻辑 + // 例如,通过读取传感器数据或运动控制器的状态 + // 这里假设总是返回 true 作为示例 - //过滤点集 - foreach (var point in etalon_points) - { - if (MainFrom.IsWithinLimit(point)) //判断点是否在行程范围内 - { - filteredPoints.Add(point); - } - } + return mainFrom.GetIsMoving(); + } - //打印过滤后的点集大小 - DebugDfn.AddLogText("过滤后的点集大小:" + filteredPoints.Count); - PointScatterPlot(filteredPoints);//绘制散点图 - return true; - } - - private void PointScatterPlot(List points) //绘制散点图 - { - comboColors.Enabled = true; // Some of the demos will disable this combobox - me_ColorScheme = (eColorScheme)comboColors.SelectedIndex; - - checkMirrorX.Checked = editor3D.AxisX.Mirror; - checkMirrorY.Checked = editor3D.AxisY.Mirror; - - // 3 pixels for line width and for circle radius - const int SIZE = 3; - - cColorScheme i_Scheme = new cColorScheme(me_ColorScheme); - cScatterData i_ShapeData = new cScatterData(i_Scheme); - cLineData i_LineData = new cLineData(i_Scheme); - List i_Points = new List(); - - foreach (var point in points) - { - double d_X = point.X; - double d_Y = point.Y; - double d_Z = point.Z; - - cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); - - // You can store the returned shape in a variable and later modify it's properties - cShape3D i_Shape = i_ShapeData.AddShape(i_Point, eScatterShape.Circle, SIZE, null); - } - - // You can store the returned lines in a variable and later modify their properties - cLine3D[] i_Lines = i_LineData.AddConnectedLines(i_Points, SIZE, null); - - // Depending on your use case you can also specify MaintainXY or MaintainXYZ here - editor3D.Clear(); - editor3D.Normalize = eNormalize.Separate; - editor3D.AddRenderData(i_ShapeData, i_LineData); - - editor3D.Selection.HighlightColor = Color.FromArgb(90, 90, 90); - editor3D.Selection.Callback = OnSelectEvent; - editor3D.Selection.MultiSelect = true; - editor3D.Selection.Enabled = true; - editor3D.UndoBuffer.Enabled = true; - editor3D.Invalidate(); - } - - public class Point - { - public double X { get; } - public double Y { get; } - public double Z { get; } - - public Point(double x, double y, double z) - { - X = x; - Y = y; - Z = z; - } - } - - private void btn_clear_Click(object sender, EventArgs e) //清空绘图 - { - editor3D.Clear(); - editor3D.Normalize = eNormalize.Separate; - editor3D.Invalidate(); - } - - private void btn_draw_test_Click(object sender, EventArgs e) - { - DemoScatterPlot(false); - } - - private void OnAnimationTimer(object sender, EventArgs e) - { - cScatterData i_ShapeData = new cScatterData(); - currentIndex = mainFrom.GetInPosCount();//获取当前点的数量 - - - if (currentIndex < filteredPoints.Count) - { - // 更新点的颜色 - for (int i = 0; i <= currentIndex; i++) - { - double d_X = filteredPoints[i].X; - double d_Y = filteredPoints[i].Y; - double d_Z = filteredPoints[i].Z; - - cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); - SolidBrush i_brush = new SolidBrush(Color.Red); - // You can store the returned shape in a variable and later modify it's properties - cShape3D i_Shape = i_ShapeData.AddShape(i_Point, eScatterShape.Circle, 5, i_brush, null); - } - - // 对于剩余部分的点,不做颜色更新 - for (int i = currentIndex; i < filteredPoints.Count; i++) - { - double d_X = filteredPoints[i].X; - double d_Y = filteredPoints[i].Y; - double d_Z = filteredPoints[i].Z; - - cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point"); - SolidBrush i_brush = new SolidBrush(Color.Gray); - // You can store the returned shape in a variable and later modify it's properties - cShape3D i_Shape = i_ShapeData.AddShape(i_Point, eScatterShape.Circle, 3, i_brush, null); - } - - //打印 所有点的数量和 currentIndex - Console.WriteLine("所有点的数量:" + filteredPoints.Count + "当前点的数量:" + currentIndex); - - - } - - - editor3D.Clear(); - editor3D.Normalize = eNormalize.Separate; - editor3D.AddRenderData(i_ShapeData); - editor3D.Invalidate(); - } - } -} \ No newline at end of file + #endregion + } +} diff --git a/HexcalMC/Motion/EtalonForm.resx b/HexcalMC/Motion/EtalonForm.resx index abbc23a..e08eed7 100644 --- a/HexcalMC/Motion/EtalonForm.resx +++ b/HexcalMC/Motion/EtalonForm.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 4 + 25 diff --git a/HexcalMC/Motion/Motion.Designer.cs b/HexcalMC/Motion/Motion.Designer.cs index afad344..85283f5 100644 --- a/HexcalMC/Motion/Motion.Designer.cs +++ b/HexcalMC/Motion/Motion.Designer.cs @@ -28,7 +28,6 @@ /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Motion)); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.txtPort = new System.Windows.Forms.TextBox(); @@ -37,7 +36,7 @@ this.btnOpen = new System.Windows.Forms.Button(); this.label2 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); - this.tmrMonitor = new System.Windows.Forms.Timer(this.components); + this.tmrMonitor = new System.Windows.Forms.Timer(); this.grpMotionTest = new System.Windows.Forms.GroupBox(); this.btnHallAll = new System.Windows.Forms.Button(); this.btnHalt = new System.Windows.Forms.Button(); @@ -200,6 +199,8 @@ this.groupBox6 = new System.Windows.Forms.GroupBox(); this.button1 = new System.Windows.Forms.Button(); this.btn_home = new System.Windows.Forms.Button(); + this.rdoSimu = new System.Windows.Forms.RadioButton(); + this.rdoTCP = new System.Windows.Forms.RadioButton(); this.groupBox1.SuspendLayout(); this.grpMotionTest.SuspendLayout(); this.grpMst.SuspendLayout(); @@ -221,6 +222,8 @@ // // groupBox1 // + this.groupBox1.Controls.Add(this.rdoTCP); + this.groupBox1.Controls.Add(this.rdoSimu); this.groupBox1.Controls.Add(this.txtPort); this.groupBox1.Controls.Add(this.txtIP); this.groupBox1.Controls.Add(this.btnClose); @@ -236,7 +239,7 @@ // // txtPort // - this.txtPort.Location = new System.Drawing.Point(103, 37); + this.txtPort.Location = new System.Drawing.Point(171, 37); this.txtPort.Name = "txtPort"; this.txtPort.Size = new System.Drawing.Size(91, 21); this.txtPort.TabIndex = 15; @@ -244,7 +247,7 @@ // // txtIP // - this.txtIP.Location = new System.Drawing.Point(103, 14); + this.txtIP.Location = new System.Drawing.Point(171, 14); this.txtIP.Name = "txtIP"; this.txtIP.Size = new System.Drawing.Size(91, 21); this.txtIP.TabIndex = 16; @@ -252,7 +255,7 @@ // // btnClose // - this.btnClose.Location = new System.Drawing.Point(113, 62); + this.btnClose.Location = new System.Drawing.Point(181, 62); this.btnClose.Name = "btnClose"; this.btnClose.Size = new System.Drawing.Size(81, 23); this.btnClose.TabIndex = 14; @@ -262,7 +265,7 @@ // // btnOpen // - this.btnOpen.Location = new System.Drawing.Point(7, 62); + this.btnOpen.Location = new System.Drawing.Point(75, 62); this.btnOpen.Name = "btnOpen"; this.btnOpen.Size = new System.Drawing.Size(81, 23); this.btnOpen.TabIndex = 13; @@ -273,7 +276,7 @@ // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(15, 41); + this.label2.Location = new System.Drawing.Point(83, 41); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(29, 12); this.label2.TabIndex = 11; @@ -282,7 +285,7 @@ // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(15, 18); + this.label1.Location = new System.Drawing.Point(83, 18); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(71, 12); this.label1.TabIndex = 12; @@ -1964,6 +1967,28 @@ this.btn_home.UseVisualStyleBackColor = true; this.btn_home.Click += new System.EventHandler(this.btn_home_Click); // + // rdoSimu + // + this.rdoSimu.AutoSize = true; + this.rdoSimu.Location = new System.Drawing.Point(6, 40); + this.rdoSimu.Name = "rdoSimu"; + this.rdoSimu.Size = new System.Drawing.Size(59, 16); + this.rdoSimu.TabIndex = 10; + this.rdoSimu.TabStop = true; + this.rdoSimu.Text = "模拟器"; + this.rdoSimu.UseVisualStyleBackColor = true; + // + // rdoTCP + // + this.rdoTCP.AutoSize = true; + this.rdoTCP.Location = new System.Drawing.Point(6, 17); + this.rdoTCP.Name = "rdoTCP"; + this.rdoTCP.Size = new System.Drawing.Size(41, 16); + this.rdoTCP.TabIndex = 17; + this.rdoTCP.TabStop = true; + this.rdoTCP.Text = "TCP"; + this.rdoTCP.UseVisualStyleBackColor = true; + // // Motion // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; @@ -2188,6 +2213,8 @@ private System.Windows.Forms.Button btn_Z_Down; private System.Windows.Forms.Button btn_Z_Up; private System.Windows.Forms.Button button1; + private System.Windows.Forms.RadioButton rdoSimu; + private System.Windows.Forms.RadioButton rdoTCP; } } diff --git a/HexcalMC/Motion/Motion.cs b/HexcalMC/Motion/Motion.cs index 805938f..3fe1baf 100644 --- a/HexcalMC/Motion/Motion.cs +++ b/HexcalMC/Motion/Motion.cs @@ -292,13 +292,7 @@ namespace HexcalMC { DebugDfn.AddLogText("运动平台已连接"); } - else - { - // TCP/IP (Ethernet) - _acs.OpenCommEthernetTCP( - txtIP.Text, // IP Address (Default : 10.0.0.100) - Convert.ToInt32(txtPort.Text.Trim())); // TCP/IP Port nubmer (default : 701) - } + InitMotion(); _mBConnected = true; diff --git a/HexcalMC/bin/x64/Debug/File/Config.ini b/HexcalMC/bin/x64/Debug/File/Config.ini index c95d206..1ed7e06 100644 --- a/HexcalMC/bin/x64/Debug/File/Config.ini +++ b/HexcalMC/bin/x64/Debug/File/Config.ini @@ -7,14 +7,17 @@ ENABLE_ACS=1 Port = 1234 ;运动速度 -MOTION_SPEED=60.0 - -;最大行程极限 -X_MAXSTROKESW = 795 -Y_MAXSTROKESW = 995 -Z_MAXSTROKESW = 20 +MOTION_SPEEDXY=100 +MOTION_SPEEDZ=30 ;最小行程极限 -X_MINSTROKESW = -5 -Y_MINSTROKESW = -5 -Z_MINSTROKESW = -280 +X_MINSTROKESW = 0 +Y_MINSTROKESW = 0 +Z_MINSTROKESW = -295 + +;最大行程极限 +X_MAXSTROKESW = 800 +Y_MAXSTROKESW = 980 +Z_MAXSTROKESW = 0 + + diff --git a/HexcalMC/bin/x64/Debug/HexcalMC.application b/HexcalMC/bin/x64/Debug/HexcalMC.application index ce349ec..c55418f 100644 --- a/HexcalMC/bin/x64/Debug/HexcalMC.application +++ b/HexcalMC/bin/x64/Debug/HexcalMC.application @@ -21,7 +21,7 @@ - 3I+Sdzke39z2xPBTFN2cGyU/DYa1hH93nKjBGpXTzUw= + 5BAu5mmkGH6UcqUDfkL6WCaAYDZ3v+HSBDiHWDwiFF0= diff --git a/HexcalMC/bin/x64/Debug/HexcalMC.exe b/HexcalMC/bin/x64/Debug/HexcalMC.exe index f567cb3..525c080 100644 Binary files a/HexcalMC/bin/x64/Debug/HexcalMC.exe and b/HexcalMC/bin/x64/Debug/HexcalMC.exe differ diff --git a/HexcalMC/bin/x64/Debug/HexcalMC.exe.manifest b/HexcalMC/bin/x64/Debug/HexcalMC.exe.manifest index 3f66852..13156c5 100644 --- a/HexcalMC/bin/x64/Debug/HexcalMC.exe.manifest +++ b/HexcalMC/bin/x64/Debug/HexcalMC.exe.manifest @@ -55,14 +55,14 @@ - + - Pllh2aI7tVRTnfFfbvwT2qdIQZ30ZwrhlbF820ogi8o= + cGpoIhg/anGo/O6Lnll6V35Q+gP3ExIYb7ltMw03hpA= diff --git a/HexcalMC/bin/x64/Debug/HexcalMC.pdb b/HexcalMC/bin/x64/Debug/HexcalMC.pdb index 60efdb7..ed4e33d 100644 Binary files a/HexcalMC/bin/x64/Debug/HexcalMC.pdb and b/HexcalMC/bin/x64/Debug/HexcalMC.pdb differ diff --git a/HexcalMC/bin/x64/Debug/app.publish/HexcalMC.exe b/HexcalMC/bin/x64/Debug/app.publish/HexcalMC.exe index de34627..cc1f403 100644 Binary files a/HexcalMC/bin/x64/Debug/app.publish/HexcalMC.exe and b/HexcalMC/bin/x64/Debug/app.publish/HexcalMC.exe differ diff --git a/Motion/ACS Motion/ACS Motion.csproj b/Motion/ACS Motion/ACS Motion.csproj index 160e655..15f0045 100644 --- a/Motion/ACS Motion/ACS Motion.csproj +++ b/Motion/ACS Motion/ACS Motion.csproj @@ -5,7 +5,7 @@ x86 8.0.30703 2.0 - {19741897-37D8-43EE-94A2-637975035CEA} + {A9C5B87B-031B-4450-AB03-5D85EFFB0636} WinExe Properties ACS_DotNET_Library_Advanced_Demo