using System; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using ABB.Robotics.Controllers; using ABB.Robotics.Controllers.Discovery; using ABB.Robotics.Controllers.EventLogDomain; using ABB.Robotics.Controllers.RapidDomain; using ABB.Robotics.Controllers.MotionDomain; using ABB.Robotics.Controllers.FileSystemDomain; using ABB.Robotics.Controllers.IOSystemDomain; using System.Threading; using System.IO; using System.IO.Ports; using Emgu.CV.Structure; using Intel.RealSense; using Emgu.CV; using Image = System.Drawing.Image; using RealSence_PathMove; using System.Numerics; using System.Collections.Generic; using System.Threading.Tasks; using OpenCvSharp; using OpenCvSharp.Extensions; using Point = System.Drawing.Point; namespace WindowsFormsApp1 { public partial class Form1 : Form { public static Form1 Instance { get; private set; } // 用來保存相機讀取執行緒 private Thread cameraThread; private OpenCvSharp.VideoCapture capture; // 相機裝置 [Obsolete] public Form1() { InitializeComponent(); intelRealSense = new IntelRealSense(this); // 初始化 IntelRealSense實例 ABBrobot = new ABBrobot(this); //初始化 ABBrobo實例 Form.CheckForIllegalCrossThreadCalls = false;//讓跨執行續可以執行UI Instance = this; // 設定實例 } //=================全域變數宣告================== string[] type = { "RS232", "TCP" }; Modbus modbus = new Modbus(); private NetworkScanner scanner = null; public static Controller controller = null; public static ABB.Robotics.Controllers.RapidDomain.Task[] tasks = null; public static bool isConnect; public static bool isconnecttask; private bool isconnectmodule; public int taskint; public string taskstring; public int moduleint; public string modulestring; public int routineunt; public string routinestring; private bool iscanchangetext; private string[] alllines; private int postionindex; private int motionindex; private string m_fileName; private string m_filePath; private ThreadStart Run2; Thread thread2; private string[] imageFiles; private int currentImageIndex = 0; //RealSenseL515相機中心點與手臂法蘭面中心的位置差 mm public float camoffset_x = 88f; public float camoffset_y = 0; public float camoffset_z = -17f; //工具末端與手臂法蘭面中心的位置差 mm public float CCDoffset_x = 125f; public float CCDoffset_z = 120f; //手臂的拍攝影像當前姿態法蘭面位置 public float ArmOrg_x = 468.70f; public float ArmOrg_y = -6.58f; public float ArmOrg_z = 380.53f; public double camera_distance; internal ABBrobot ABBrobot { get; } public Vector3 firstCameraPoint { get; private set; } public PointF Compare_yolo { get; private set; } public bool ROI; public bool GoldStandard = false; public event EventHandler Button6StateChanged; public int left, top, right, bottom; public double Gx, Gy, Gz, GRx, GRy, GRz,dx,dy, newGx, newGy, newGz; public string gx, gy, gz, gRx, gRy, gRz; private Bitmap drawingBitmap; //================視窗載入 初始宣告=============== private void Form1_Load(object sender, EventArgs e) { pictureBox_PLC.BackColor = Color.Silver; gpb_Type_TCP.Enabled = false; gpb_RS232.Enabled = false; btn_Connect.Enabled = false; btn_Disconnect.Enabled = false; cmb_Type.Items.AddRange(type); timer2.Enabled = true; timer2.Interval = 100; StartCamera(); // 啟動相機 } //================視窗關閉========================== private void Form1_FormClosing(object sender, FormClosingEventArgs e) { cts?.Cancel(); // 當按鈕被按下時,取消所有等待操作 cts?.Dispose(); // 釋放資源 cts = null; // 重置為 null,以便下次使用時重新初始化 // 停止之前的背景任務(如果有的話) backgroundCts?.Cancel(); backgroundCts?.Dispose(); backgroundCts = null; backgroundCts1?.Cancel(); backgroundCts1?.Dispose(); backgroundCts1 = null; this.Invoke((Action)(() => { pictureBox4.Image = null; pictureBox4.Refresh(); pictureBox5.Image = null; pictureBox5.Refresh(); })); modbus.Disconnect(); //取消任务 if (cam == true || cam != false) { intelRealSense.cts.Cancel(); } if (isConnect == true) { MessageBox.Show("ABB手臂斷開連線"); } // 關閉相機執行緒 if (cameraThread != null && cameraThread.IsAlive) { cameraThread.Abort(); // 停止執行緒 } // 釋放相機資源 if (capture != null) { capture.Release(); capture.Dispose(); } } #region PLC部分 public void ComportName()//============= ComPort_Name載入combobox ==================== { cmb_Comport.Items.Clear(); cmb_Comport.Items.AddRange(SerialPort.GetPortNames()); } private void timer2_Tick(object sender, EventArgs e)//Timer掃描內容(PLC) { //============= Comport狀態 ========================== modbus.IsOpen(); if (modbus.isopen) { pictureBox_PLC.BackColor = Color.GreenYellow; modbus.Command("010205000001", cmb_Type.Text); } else { pictureBox_PLC.BackColor = Color.Silver; } //====================== 按鈕權限 ======================== if (cmb_Comport.Text != "" || txb_Tcp_Ip.Text != "" && txb_Tcp_Port.Text != "") { btn_Connect.Enabled = true; btn_Disconnect.Enabled = true; } else { btn_Connect.Enabled = false; btn_Disconnect.Enabled = false; } } private void btn_Connect_Click(object sender, EventArgs e)//連線PLC { if (cmb_Type.Text == "TCP") { modbus.Connert(cmb_Type.Text, txb_Tcp_Ip.Text, txb_Tcp_Port.Text); } else if (cmb_Type.Text == "RS232") modbus.Connert(cmb_Type.Text, cmb_Comport.Text); } private void btn_Restart_Click(object sender, EventArgs e)//重置comport { ComportName(); } private void cmb_Type_SelectedIndexChanged(object sender, EventArgs e)//TCP/RS232區域是否開啟 { { modbus.Disconnect(); if (cmb_Type.Text == "TCP") { gpb_Type_TCP.Enabled = true; gpb_RS232.Enabled = false; } else if (cmb_Type.Text == "RS232") { ComportName(); gpb_Type_TCP.Enabled = false; gpb_RS232.Enabled = true; } } } private void btn_Disconnect_Click(object sender, EventArgs e)//中斷連線 { modbus.Disconnect(); } private void btn_Command_Click(object sender, EventArgs e)//命令輸出 { rtb_response.Text = modbus.Command(rtb_Command.Text, cmb_Type.Text); rtb_response.Text = modbus.Command(rtb_Command.Text, cmb_Type.Text); } private void btn_Command_clear_Click(object sender, EventArgs e)//命令欄清除 { rtb_Command.Clear(); } public static string HexStringToASCII(string hexstring)//string to ascii { byte[] bt = HexStringToBinary(hexstring); string lin = ""; for (int i = 0; i < bt.Length; i++) { lin = lin + bt[i] + " "; } string[] ss = lin.Trim().Split(new char[] { ' ' }); char[] c = new char[ss.Length]; int a; for (int i = 0; i < c.Length; i++) { a = Convert.ToInt32(ss[i]); c[i] = Convert.ToChar(a); } string b = new string(c); return b; } public static byte[] HexStringToBinary(string hexstring) { string[] tmpary = hexstring.Trim().Split(' '); byte[] buff = new byte[tmpary.Length]; for (int i = 0; i < buff.Length; i++) { buff[i] = Convert.ToByte(tmpary[i], 16); } return buff; } #endregion #region 手臂部分 //=====================================ABB 連線部分================================= private void button1_Click(object sender, EventArgs e)//搜尋機器人 { if (scanner == null) { scanner = new NetworkScanner(); } scanner.Scan(); ControllerInfoCollection controls = scanner.Controllers; this.listView1.Items.Clear(); foreach (ControllerInfo info in controls) { ListViewItem item = new ListViewItem(info.SystemName); item.SubItems.Add(info.IPAddress.ToString()); //顯示IP地址 item.SubItems.Add(info.Version.ToString()); //顯示robotware版本 item.SubItems.Add(info.IsVirtual.ToString()); //顯示是否為虛擬控制 item.SubItems.Add(info.ControllerName.ToString()); //顯示控制器名稱 item.Tag = info; this.listView1.Items.Add(item); } } [Obsolete] private void connectrobot(object sender, EventArgs e)//選擇連接機器人 { if (this.listView1.Items.Count > 0) { ListViewItem item = this.listView1.SelectedItems[0]; if (item != null) { ControllerInfo info = (ControllerInfo)item.Tag; if (info.Availability == Availability.Available) { if (controller != null) { controller.Logoff(); controller.Dispose(); controller = null; } controller = ControllerFactory.CreateFrom(info); controller.Logon(UserInfo.DefaultUser); ABBrobot.Motorstatus(); MessageBox.Show("已經登陸控制器" + info.SystemName); //botClient.SendTextMessageAsync( //chatId: "-1001758058968", //text: "ABB手臂連線成功", //disableNotification: false); isConnect = true; timer1.Enabled = true; } } } hScrollBar1.Value = controller.MotionSystem.SpeedRatio; //獲取控制器速度率 tasks = controller.Rapid.GetTasks(); radioButton1.Checked = true; } public void timer1_Tick(object sender, EventArgs e) { //讀取當前程式指針與手臂位置 Run2 = new ThreadStart(Test_thread2);//先把test_thread2變成ThreadStart的物件 thread2 = new Thread(Run2);//用ThreadStart的物件建立一個執行緒 thread2.Start(); //開始掃描狀態 //label1.Text = controller.MotionSystem.SpeedRatio.ToString()+ "%";//將ABB速度與滑動塊實時連接並控制速率。 //關節座標 if (radioButton1.Checked) { JointTarget RJ = controller.MotionSystem.ActiveMechanicalUnit.GetPosition(); px.Text = "J1"; py.Text = "J2"; pz.Text = "J3"; rx.Text = "J4"; ry.Text = "J5"; rz.Text = "J6"; textBox3.Text = RJ.RobAx.Rax_1.ToString(format: "0.00"); textBox4.Text = RJ.RobAx.Rax_2.ToString(format: "0.00"); textBox5.Text = RJ.RobAx.Rax_3.ToString(format: "0.00"); textBox6.Text = RJ.RobAx.Rax_4.ToString(format: "0.00"); textBox7.Text = RJ.RobAx.Rax_5.ToString(format: "0.00"); textBox8.Text = RJ.RobAx.Rax_6.ToString(format: "0.00"); } //基座標 if (radioButton2.Checked) { double tx; double ty; double tz; RobTarget robTarget = controller.MotionSystem.ActiveMechanicalUnit.GetPosition(CoordinateSystemType.World); px.Text = "PX"; py.Text = "PY"; pz.Text = "PZ"; rx.Text = "RX"; ry.Text = "RY"; rz.Text = "RZ"; textBox3.Text = robTarget.Trans.X.ToString(format: "0.00"); textBox4.Text = robTarget.Trans.Y.ToString(format: "0.00"); textBox5.Text = robTarget.Trans.Z.ToString(format: "0.00"); robTarget.Rot.ToEulerAngles(out tx, out ty, out tz); textBox6.Text = tx.ToString(format: "0.00"); textBox7.Text = ty.ToString(format: "0.00"); textBox8.Text = tz.ToString(format: "0.00"); } } private void button6_Click(object sender, EventArgs e)//電機開關 { if (isConnect == true && controller.OperatingMode == ControllerOperatingMode.Auto)//判斷是否連接機器人 { if (controller.State == ControllerState.MotorsOn) { ABBrobot.Closemotor(); } else if (controller.State == ControllerState.MotorsOff) { ABBrobot.Openmotor(); } } else { MessageBox.Show("未識別到機器人,請連接機器人!!或開啟自動模式!!"); } } private void button2_Click(object sender, EventArgs e)//選擇任務 { ABBrobot.Isconnectrobot(); if (isConnect == true) { comboBox1.Items.Clear(); for (int i = 0; i < (int)tasks.Count(); i++) { comboBox1.Items.Add(tasks[i].Name); } isconnecttask = true; } else { MessageBox.Show("未識別到機器人,請連接機器人!"); } } private void button3_Click(object sender, EventArgs e)//選擇模塊 { comboBox2.Items.Clear(); if (isconnecttask == true) { int taskint = comboBox1.SelectedIndex; Module[] modules = controller.Rapid.GetTasks()[taskint].GetModules(); for (int i = 0; i < (int)modules.Count(); i++) { comboBox2.Items.Add(modules[i].Name); }; isconnectmodule = true; } else { MessageBox.Show("請指定某個任務"); isconnectmodule = false; } } private void button4_Click(object sender, EventArgs e)//選擇程序 { comboBox3.Items.Clear(); if (isconnectmodule == true) { int taskint = comboBox1.SelectedIndex; int moduleint = comboBox2.SelectedIndex; Routine[] routines1 = controller.Rapid.GetTasks()[taskint].GetModules()[moduleint].GetRoutines(); for (int i = 0; i < (int)routines1.Count(); i++) { comboBox3.Items.Add(routines1[i].Name); } } else { MessageBox.Show("請指定某個模塊"); } } private void button5_Click(object sender, EventArgs e)//確認將所选的任務、模塊、程序保存 { taskint = comboBox1.SelectedIndex; taskstring = comboBox1.SelectedItem.ToString(); moduleint = comboBox2.SelectedIndex; modulestring = comboBox2.SelectedItem.ToString(); routineunt = comboBox3.SelectedIndex; routinestring = comboBox3.SelectedItem.ToString(); } private void MyScrollBar1_Scroll(object sender, ScrollEventArgs e)//機器人控速比 { if (isConnect == true) { if (controller.OperatingMode == ControllerOperatingMode.Auto) { controller.MotionSystem.SpeedRatio = Convert.ToInt32(hScrollBar1.Value);//myScrollBar1為滑塊控件名 label9.Text = "速度設定值" + controller.MotionSystem.SpeedRatio.ToString() + "%"; } else { MessageBox.Show("請打開自動模式"); } } } private void button8_Click(object sender, EventArgs e)//查看座標值 { RapidSymbolSearchProperties date = RapidSymbolSearchProperties.CreateDefault(); date.Types = SymbolTypes.Data; date.SearchMethod = SymbolSearchMethod.Block; date.Recursive = true; date.InUse = false; date.LocalSymbols = false; RapidSymbol[] symbols = tasks[taskint].SearchRapidSymbol(date, "robtarget", string.Empty); this.comboBox4.Items.Clear(); foreach (RapidSymbol symbol in symbols) { try { RapidData rD = tasks[taskint].GetRapidData(symbol); comboBox4.Items.Add(rD.Name); } catch (Exception) { return; } } if (comboBox4.Items == null) { comboBox4.Text = "沒有座標變量"; } else { comboBox4.SelectedIndex = 0; } } private void button11_Click(object sender, EventArgs e)//日誌 { try { EventLog log = controller.EventLog; EventLogCategory cat = log.GetCategory(0); this.textBox10.Text = ""; { foreach (EventLogMessage emsg in cat.Messages) { int alarmNo; alarmNo = emsg.CategoryId * 1000 + emsg.Number; this.textBox10.Text = this.textBox10.Text + "" + alarmNo.ToString() + "" + emsg.Title + "" + emsg.Timestamp + "\r\n"; } } } catch (Exception ex) { MessageBox.Show("出現錯誤" + ex.Message); } } private void button9_Click(object sender, EventArgs e)//查看座標值(確定) { if (comboBox1.SelectedItem.ToString() != null || comboBox4.SelectedItem.ToString() != null) { RapidSymbolSearchProperties date = RapidSymbolSearchProperties.CreateDefault(); date.Types = SymbolTypes.Data; date.SearchMethod = SymbolSearchMethod.Block; date.Recursive = true; date.InUse = false; date.LocalSymbols = false; RapidSymbol[] symbols = tasks[taskint].SearchRapidSymbol(date, "robtarget", string.Empty); this.listView2.Items.Clear(); foreach (RapidSymbol symbol in symbols) { try { RapidData rD = tasks[taskint].GetRapidData(symbol); if (rD.Name == comboBox4.SelectedItem.ToString()) { ListViewItem item2 = new ListViewItem(symbol.Name); if (rD.Value != null) { item2.SubItems.Add(rD.Value.ToString()); } else { item2.SubItems.Add("0"); } item2.Tag = symbol; this.listView2.Items.Add(item2); } else { continue; } } catch (Exception) { return; } } } else { MessageBox.Show("請選擇任務!"); } } [Obsolete] private void button10_Click_1(object sender, EventArgs e)//修改點座標 { string strvariable = comboBox4.SelectedItem.ToString(); Form2 form2 = new Form2();//實例化Form2 form2.ShowDialog();//展示Form2 if (form2.oKorCancel == true) { try { using (Mastership.Request(controller.Rapid))//獲得訪問示教器內部管理權限 { RapidData rd = controller.Rapid.GetRapidData(taskstring, modulestring, strvariable);//設定座標 RobTarget rob = (RobTarget)rd.Value; rob.Trans.X = form2.dx; rob.Trans.Y = form2.dy; rob.Trans.Z = form2.dz; rob.Rot.Q1 = form2.dq1; rob.Rot.Q2 = form2.dq2; rob.Rot.Q3 = form2.dq3; rob.Rot.Q4 = form2.dq4; rd.Value = rob; MessageBox.Show(strvariable + "修改成功!"); button9_Click(sender, e); } } catch (Exception ex) { MessageBox.Show("發生錯誤:" + ex.Message); } form2.oKorCancel = false; } else { } } private void button14_Click(object sender, EventArgs e)//打開程序 { OpenFileDialog fileDialog = new OpenFileDialog(); fileDialog.Filter = ".mod文件(*.mod)|*.mod"; fileDialog.ValidateNames = true; fileDialog.CheckPathExists = true; fileDialog.CheckFileExists = true; if (fileDialog.ShowDialog() == DialogResult.OK) { m_fileName = fileDialog.SafeFileName; m_filePath = fileDialog.FileName; m_filePath = m_filePath.Replace("\\", "//"); Console.WriteLine("name: " + m_fileName); Console.WriteLine("path: " + m_filePath); this.textBox9.Text = fileDialog.FileName; FileStream fileStream = new FileStream(this.textBox9.Text, FileMode.Open, FileAccess.Read); byte[] arraydate = new byte[(int)fileStream.Length]; int index = 0; int code = fileStream.ReadByte(); while (code != -1) { arraydate[index] = Convert.ToByte(code); code = fileStream.ReadByte(); index++; } this.textBox14.Text = Encoding.Default.GetString(arraydate); fileStream.Close(); } else { m_fileName = m_filePath = " "; } } [Obsolete] private void button15_Click(object sender, EventArgs e)//PP to main { firstButtonClick = true; try { if (controller.OperatingMode == ControllerOperatingMode.Auto) { using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } using (Mastership.Request((IMastershipResourceController)controller)) { int taskIndex = 0; // 要操作的任務索引 ABB.Robotics.Controllers.RapidDomain.Task[] tasks = controller.Rapid.GetTasks(); if (tasks.Length > 0 && taskIndex >= 0 && taskIndex < tasks.Length) { tasks[taskIndex].ResetProgramPointer(); MessageBox.Show("程序指針已經復位"); } } } else { MessageBox.Show("請切換自動模式"); } } catch (System.InvalidOperationException ex) { MessageBox.Show("權限已經占用" + ex.Message); } catch (Exception ex) { MessageBox.Show("PP to main有誤" + ex.ToString()); } iscanchangetext = true; } [Obsolete] private void button16_Click(object sender, EventArgs e)//指針移到指定程式 { firstButtonClick = true; try { if (controller.OperatingMode == ControllerOperatingMode.Auto) { using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } tasks = controller.Rapid.GetTasks(); using (Mastership.Request((IMastershipResourceController)controller)) { tasks = controller.Rapid.GetTasks(); tasks[0].SetProgramPointer(modulestring, routinestring); MessageBox.Show("程序指針已經設置到了" + routinestring); } } else { } } catch (Exception ex) { MessageBox.Show("指針移到指定程式錯誤: " + ex.Message); } } private void Test_thread2()//副程式////讀取當前程式指針與手臂位置 { if (iscanchangetext == true && tasks[taskint].ProgramPointer != null && tasks[taskint].MotionPointer != null) { try { alllines = textBox14.Text.Split('\n'); ProgramPosition programPosition = tasks[taskint].ProgramPointer; string programstr = programPosition.Range.End.Row.ToString(); postionindex = Convert.ToInt32(programstr); string changeprogram = postionindex.ToString() + " ->" + alllines[postionindex - 1].Trim();//指針 textBox13.Text = changeprogram; ProgramPosition position = tasks[taskint].MotionPointer; string motionstr = position.Range.End.Row.ToString(); motionindex = Convert.ToInt32(motionstr); string changemotion = motionindex.ToString() + " Z*" + alllines[motionindex].Trim();//機器人 textBox12.Text = changemotion; //有需要時再用 // string[] changePointx = alllines[postionindex - 1].Trim().Split(' '); //changePoint = changePointx[1].Split(','); } catch (Exception) { } } } [Obsolete] private void button17_Click(object sender, EventArgs e)//程序啟動 { // botClient.SendTextMessageAsync( //chatId: "-1001758058968", // text: "手臂啟動", //disableNotification: false); try { if (controller.OperatingMode == ControllerOperatingMode.Auto) { using (Mastership.Request(controller.Rapid)) { StartResult s = controller.Rapid.Start(); } } else { MessageBox.Show("請切換自動模式"); } } catch (Exception ex) { MessageBox.Show("出錯了!" + ex.Message); } iscanchangetext = true; } [Obsolete] private void button18_Click(object sender, EventArgs e)//程序停止 { //mythread.Abort();//停止讀取執行緒 //thread.Abort();//停止讀取執行緒 // botClient.SendTextMessageAsync( //chatId: "-1001758058968", //text: "手臂停止", // disableNotification: false); try { using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } } catch (Exception ex) { MessageBox.Show("出錯了!" + ex.Message); } iscanchangetext = false; } private void button19_Click(object sender, EventArgs e)//保存程序 { OpenFileDialog fileDialog = new OpenFileDialog(); if (fileDialog.ShowDialog() == DialogResult.OK) { File.WriteAllText(fileDialog.FileName, this.textBox14.Text); MessageBox.Show("保存成功"); } else { return; } } class ListViewNF : System.Windows.Forms.ListView //解決ListView閃爍 { public ListViewNF() { // 開啟雙緩沖 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.EnableNotifyMessage, true); } } private void button21_Click(object sender, EventArgs e)//I/O讀取 { timer5.Enabled = true; button22.Enabled = true; comboBox5.Enabled = true; } private void timer5_Tick(object sender, EventArgs e)//掃描I/O { this.listView3.Items.Clear(); Thread.Sleep(100); SignalCollection signals = controller.IOSystem.GetSignals(IOFilterTypes.Unit, "d652"); foreach (Signal signal in signals) { ListViewItem item = new ListViewItem(signal.Name); item.SubItems.Add(signal.Type.ToString()); item.SubItems.Add(signal.Value.ToString()); item.SubItems.Add(signal.Unit.ToString()); item.Tag = signal; this.listView3.Items.Add(item); } } private void button22_Click(object sender, EventArgs e)//I/O寫入 { ABBrobot.IO(); } private void button23_Click(object sender, EventArgs e) //取得機器人資訊 { label14.Text = controller.RobotWare.Name.ToString(); richTextBox1.Text = ""; richTextBox2.Text = ""; MechanicalUnitServiceInfo unitServiceInfo = controller.MotionSystem.ActiveMechanicalUnit.ServiceInfo; richTextBox2.Text += "生產總時間: " + unitServiceInfo.ElapsedProductionTime.TotalHours.ToString() + "小時\r\n"; richTextBox2.Text += "自上次服務後的生產總時間: " + unitServiceInfo.ElapsedProductionTimeSinceLastService.TotalHours.ToString() + "小時\r\n"; //richTextBox2.Text += "上次開機時間: " + unitServiceInfo.LastStart.ToString() + "小時\r\n"; richTextBox2.Text += "自上次維修時間: " + unitServiceInfo.ElapsedCalenderTimeSinceLastService.TotalDays.ToString() + "天\r\n"; richTextBox1.Text += "RW版本: " + controller.RobotWare.Version.ToString() + "\r\n"; RobotWareOptionCollection options = controller.RobotWare.Options; foreach (RobotWareOption option in options) { richTextBox1.Text += "option: " + option.ToString() + "\r\n"; } } private void button25_Click(object sender, EventArgs e)//備份 { if (controller != null) { UserAuthorizationSystem uas = controller.AuthenticationSystem; if (uas.CheckDemandGrant(Grant.BackupController)) { string str = controller.SystemName + "_backup_" + DateTime.Now.ToString("yyyy-MM-dd"); string pathStr = controller.FileSystem.RemoteDirectory; controller.Backup(pathStr + @"\backup\" + str); MessageBox.Show("備份完成"); } else { MessageBox.Show("沒有權限"); } } } private void button26_Click(object sender, EventArgs e)//上傳 { if (m_fileName == "" || m_fileName == "") { MessageBox.Show("文件為空"); return; } try { string remoteDir = controller.FileSystem.RemoteDirectory; FileSystem file = controller.FileSystem; //存在就替換(不加該程式,存在相同文件會回報當前操作無效) if (controller.FileSystem.FileExists(m_fileName) == true) { file.PutFile(m_filePath, true); MessageBox.Show("覆蓋成功,位於HOME目錄下"); } else { file.PutFile(m_filePath); MessageBox.Show("上傳成功,位於HOME目錄下"); } } catch (System.InvalidOperationException ex) { MessageBox.Show(ex.Message + ",上傳失敗"); } catch (System.Exception ex) { MessageBox.Show(ex.Message + ",上傳失敗"); } } [Obsolete] private void button29_Click(object sender, EventArgs e)//模擬路徑 { #region 直接在手臂控制器內修改現有的程式路徑(控制器內 Module 及 Routine 需要先創建並先在教導器撰寫程式流程,這邊只負責修改路徑) firstButtonClick = true; using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } using (Mastership master = Mastership.Request(controller.Rapid)) { // 直接使用路径点数量 RapidData rd = controller.Rapid.GetRapidData(tasks[taskint].Name, "MainModule", "count"); if (rd.Value is Num) { Num num = (Num)rd.Value; num.Value = aa; rd.Value = num; } rd = controller.Rapid.GetRapidData(tasks[taskint].Name, "MainModule", "path"); for (int i = 0; i < aa; i++) { RobTarget rt = (RobTarget)rd.ReadItem(i); rt.Trans.FillFromString2("[" + dataGridView1.Rows[i].Cells[0].Value.ToString() + ',' + dataGridView1.Rows[i].Cells[1].Value.ToString() + ',' + dataGridView1.Rows[i].Cells[2].Value.ToString() + "]"); rt.Rot.FillFromEulerAngles(Convert.ToDouble(dataGridView1.Rows[i].Cells[3].Value), Convert.ToDouble(dataGridView1.Rows[i].Cells[4].Value), Convert.ToDouble(dataGridView1.Rows[i].Cells[5].Value)); rt.Robconf.FillFromString("[0,0,0,0]"); rt.Extax.FillFromString("[9E+09,9E+09,9E+09,9E+09,9E+09,9E+09]"); rd.WriteItem(rt, i); } tasks[taskint].SetProgramPointer("MainModule", "WeldingPath"); controller.Rapid.Start(); } #endregion } [Obsolete] public void Home() // 手臂回原點 { ABBrobot.Isconnectrobot(); if (controller.OperatingMode == ControllerOperatingMode.Auto && Form1.controller.State == ControllerState.MotorsOn) { using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } int taskIndex = 0; // 獲取用戶任務 Module[] modules = controller.Rapid.GetTasks()[taskIndex].GetModules(); // 獲取任務列表 string moduleNameToFind = "MainModule"; // 指定要查找的模塊名稱 Module foundModule = modules.FirstOrDefault(module => module.Name == moduleNameToFind); // 在模塊列表中查找指定名稱的模塊 if (foundModule != null) // 如果找到了匹配的模塊 { Routine[] routines = foundModule.GetRoutines();// 獲取程序列表,這裡使用 foundModule string routineNameToFind = "home"; // 指定要查找的程序名稱 Routine foundRoutine = routines.FirstOrDefault(routine => routine.Name == routineNameToFind); // 在程序列表中查找指定名稱的程序 if (foundRoutine != null) // 如果找到了匹配的程序,PP移至例行程序 { using (Mastership.Request((IMastershipResourceController)controller)) { tasks = controller.Rapid.GetTasks(); if (tasks.Length > 0 && taskIndex >= 0 && taskIndex < tasks.Length) { tasks[taskIndex].SetProgramPointer(moduleNameToFind, routineNameToFind); iscanchangetext = true; StartResult s = controller.Rapid.Start(); } } } } } else { MessageBox.Show("請切換自動模式,電機是否開啟"); } } #endregion #region 相機 //--------------------------------------------- 影像部分*---------------------------------------------------------- private readonly IntelRealSense intelRealSense; // 将 IntelRealSense 实例作为类成员 //public int objectCounter = 1; // 初始化物體編號為1 public static bool firstButtonClick = true;//判別是否第一下 public bool cameraOpened = false;//相機狀態 public Image ColorImg = null; public Image FilteredImg; public VideoFrame colorFrame; public Intel.RealSense.Frame filtered; public IntelRealSense RealSense; public bool cam; public delegate void SetEnabledCallback(bool enabled); public int aa; private List selectedPoints = new List(); private float scaleX; private float scaleY; // 創建一個變數來控制執行緒是否繼續運行 public volatile bool ImageProcessing = false; public volatile bool ImageProcessing1 = false; public volatile bool goldsample; // 啟動相機並使用執行緒讀取影像 private void StartCamera() { // 初始化相機,0是默認相機 capture = new OpenCvSharp.VideoCapture(2); if (!capture.IsOpened()) { MessageBox.Show("無法打開相機"); return; } // 開始一個新執行緒來讀取影像 cameraThread = new Thread(() => { while (true) { using (OpenCvSharp.Mat frame = new OpenCvSharp.Mat()) { capture.Read(frame); // 讀取相機影像 if (!frame.Empty()) { // 轉換影像格式為Bitmap Bitmap image = BitmapConverter.ToBitmap(frame); UpdatePictureBox(image); // 更新畫面 } Thread.Sleep(30); // 控制影像更新速率 } } }); cameraThread.IsBackground = true; // 設定為背景執行緒 cameraThread.Start(); // 啟動執行緒 } // 更新PictureBox上的影像 private void UpdatePictureBox(Bitmap image) { if (pictureBox1.InvokeRequired) { // 如果不是在UI執行緒,使用Invoke來進行UI更新 pictureBox1.Invoke(new Action(() => { pictureBox7.Image?.Dispose(); // 釋放之前的影像 pictureBox7.Image = image; // 顯示新影像 })); } else { pictureBox7.Image?.Dispose(); // 釋放之前的影像 pictureBox7.Image = image; // 顯示新影像 } } // 在視窗加載時,初始化圖片列表 private void LoadImage(int index) { if (index >= 0 && index < imageFiles.Length) { string imagePath = imageFiles[index]; var image = Image.FromFile(imagePath); pictureBox1.Image = image; intelRealSense.ProcessImage(image); } } [Obsolete] private void Button7_Click_1(object sender, EventArgs e) { ROI = false; selectedPoints.Clear(); // 清空 PictureBox 上的標記 pictureBox2.Invalidate(); ABBrobot.Isconnectrobot(); } public void PlanningAOI() { DigitalSignal digitalSignalDo3 = (DigitalSignal)controller.IOSystem.GetSignal("Do3"); while (true) { if (digitalSignalDo3.Value == 1) { // 提示使用者點選四個點 MessageBox.Show("請在彩色影像上點選ROI範圍(四個點)","提示", MessageBoxButtons.OK); digitalSignalDo3.Value = 0; break; } } } private void PictureBox2_MouseClick_1(object sender, MouseEventArgs e) { // 根据解析度和 PictureBox 的大小计算缩放比例 scaleX = (float)pictureBox2.Width / 640f; scaleY = (float)pictureBox2.Height / 480f; if (e.Button == MouseButtons.Left) { // 限制只能选取四个点 if (selectedPoints.Count < 4) { selectedPoints.Add(e.Location); pictureBox2.Invalidate(); } else { MessageBox.Show("以選四個點,請勿繼續點擊。", "提示", MessageBoxButtons.OK); } } } // 在需要显示点位的地方,根据校正后的 selectedPoints 列表绘制点 private void DrawPoints(PaintEventArgs e) { foreach (Point point in selectedPoints) { // 将控件坐标转换为图像坐标 int imageX = (int)(point.X / scaleX); int imageY = (int)(point.Y / scaleY); // 绘制点 int controlX = (int)(imageX * scaleX); int controlY = (int)(imageY * scaleY); e.Graphics.FillEllipse(Brushes.Red, controlX - 5, controlY - 5, 10, 10); // 显示坐标 string coordinate = "(" + imageX.ToString() + ", " + imageY.ToString() + ")"; e.Graphics.DrawString(coordinate, this.Font, Brushes.Black, controlX + 10, controlY - 10); } } private void DrawRectangle(PaintEventArgs e) { if (selectedPoints.Count == 4) { // 将图像坐标转换为控件坐标 Point[] controlPoints = selectedPoints.Select(p => new Point((int)(p.X * scaleX), (int)(p.Y * scaleY))).ToArray(); // 计算矩形的左上角和右下角坐标(图像坐标系统) left = selectedPoints.Min(p => (int)(p.X / scaleX)); top = selectedPoints.Min(p => (int)(p.Y / scaleY)); right = selectedPoints.Max(p => (int)(p.X / scaleX)); bottom = selectedPoints.Max(p => (int)(p.Y / scaleY)); // 绘制矩形 e.Graphics.DrawRectangle(Pens.Blue, (int)(left * scaleX), (int)(top * scaleY), (int)((right - left) * scaleX), (int)((bottom - top) * scaleY)); ROI = true; } } private void PictureBox2_Paint_1(object sender, PaintEventArgs e) { DrawPoints(e); DrawRectangle(e); } private void PictureBox4_Paint(object sender, PaintEventArgs e) { if (!cameraOpened) // 如果相机未打开,则打开它 { } else { DrawRectangle(e); } } [Obsolete] private void Button28_Click(object sender, EventArgs e)//提取金樣本 { intelRealSense.TakeImage = false; ROI = false; pictureBox1.Image = null; pictureBox2.Image = null; pictureBox3.Image = null; selectedPoints.Clear(); // 清空 PictureBox 上的標記 pictureBox2.Invalidate(); ABBrobot.Isconnectrobot(); button7.Enabled = true; if (controller.OperatingMode == ControllerOperatingMode.Auto && Form1.controller.State == ControllerState.MotorsOn && cameraOpened == true) { using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } int taskIndex = 0; // 獲取用戶任務 Module[] modules = controller.Rapid.GetTasks()[taskIndex].GetModules(); // 獲取任務列表 string moduleNameToFind = "MainModule"; // 指定要查找的模塊名稱 Module foundModule = modules.FirstOrDefault(module => module.Name == moduleNameToFind); // 在模塊列表中查找指定名稱的模塊 if (foundModule != null) // 如果找到了匹配的模塊 { Routine[] routines = foundModule.GetRoutines();// 獲取程序列表,這裡使用 foundModule string routineNameToFind = "TakeImage"; // 指定要查找的程序名稱 Routine foundRoutine = routines.FirstOrDefault(routine => routine.Name == routineNameToFind); // 在程序列表中查找指定名稱的程序 if (foundRoutine != null) // 如果找到了匹配的程序,PP移至例行程序 { using (Mastership.Request((IMastershipResourceController)controller)) { tasks = controller.Rapid.GetTasks(); if (tasks.Length > 0 && taskIndex >= 0 && taskIndex < tasks.Length) { tasks[taskIndex].SetProgramPointer(moduleNameToFind, routineNameToFind); iscanchangetext = true; groupBox2.Enabled = false; listView4.Items.Clear(); label16.Text = null; ImageProcessing = true; intelRealSense.CaptureImagesAndSave(); button7.Enabled = true; } } } } } else { MessageBox.Show("請切換自動模式,電機是否開啟"); } } [Obsolete] private async void Button27_Click(object sender, EventArgs e)//開關相機 { if (!cameraOpened) // 如果相机未打开,则打开它 { cam = true; intelRealSense.OpenCamera(); // 打開像機 button28.Enabled = true; cameraOpened = true; label17.Text = "相機狀態:開"; button27.Text = "關相機"; label17.BackColor = Color.Red; } else // 如果相机已经打开,则关闭它 { cam = false; cameraOpened = false; label17.Text = "相機狀態:關"; button27.Text = "開相機"; button7.Enabled = false; button28.Enabled = false; label17.BackColor = Color.Transparent; await intelRealSense.CloseCamera(); // 關閉相機 groupBox2.Enabled = true; this.Invoke((Action)(() => { pictureBox4.Image = null; pictureBox4.Refresh(); pictureBox5.Image = null; pictureBox5.Refresh(); pictureBox6.Image = null; pictureBox6.Refresh(); })); } } private void Button12_Click(object sender, EventArgs e) //選擇資料夾 { using (var folderDialog = new FolderBrowserDialog()) { if (folderDialog.ShowDialog() == DialogResult.OK) { // 獲取所選文件夹中的所有.jpg.bmp文件 imageFiles = Directory.GetFiles(folderDialog.SelectedPath, "*.jpg") .Concat(Directory.GetFiles(folderDialog.SelectedPath, "*.bmp")) .ToArray(); if (imageFiles.Length > 0) { currentImageIndex = 0; LoadImage(currentImageIndex); } } } } private void Button13_Click(object sender, EventArgs e) // 上一張圖片按钮 { listView4.Items.Clear(); // 上一張圖片按钮 if (imageFiles == null || imageFiles.Length == 0) { MessageBox.Show("請先選擇資料夾!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } currentImageIndex--; if (currentImageIndex < 0) { currentImageIndex = 0; } // 重置物體編號1 intelRealSense.objectCounter = 1; LoadImage(currentImageIndex); } private void Button20_Click(object sender, EventArgs e) // 下一張圖片按钮 { listView4.Items.Clear(); if (imageFiles == null || imageFiles.Length == 0) { MessageBox.Show("請先選擇資料夾!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } currentImageIndex++; if (currentImageIndex >= imageFiles.Length) { currentImageIndex = imageFiles.Length - 1; } // 重置物體編號1 intelRealSense.objectCounter = 1; LoadImage(currentImageIndex); } private void Button13_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) //按鍵連動 { // 使用鍵盤A键切换上一張圖片 if (e.KeyCode == Keys.A) { Button13_Click(sender, e); } // 使用键盤B键切换下一張圖片 else if (e.KeyCode == Keys.D) { Button20_Click(sender, e); } } public void SetPictureBox4Image(Bitmap bitmap1) //pictureBox4更新 { if (pictureBox4.InvokeRequired) // 檢查是否需要進行跨執行緒的操作 { pictureBox4.Invoke(new Action(() => // 如果需要跨執行緒,使用Invoke方法在UI執行緒上執行影像更新 { pictureBox4.Image = bitmap1; })); } else { pictureBox4.Image = bitmap1; // 如果不需要跨執行緒,直接在當前執行緒上更新pictureBox2的影像 } } public void SetPictureBox5Image(Bitmap depthBitmap)//pictureBox5更新 { if (pictureBox5.InvokeRequired) { pictureBox5.Invoke(new Action(() => { pictureBox5.Image = depthBitmap; })); } else { pictureBox5.Image = depthBitmap; } } [Obsolete] private void Button24_Click(object sender, EventArgs e)//路徑生成 { Home(); // 彈出視窗詢問是否執行 DialogResult result = MessageBox.Show("是否生成路徑?", "提示", MessageBoxButtons.OKCancel); // 根據使用者的選擇執行或不執行相應的程式碼 if (result == DialogResult.OK) { if (ROI == true && intelRealSense.TakeImage == true) { try { camera_distance = Convert.ToDouble(textBox1.Text); } catch { textBox1.Text = "0"; camera_distance = 0; } aa = intelRealSense.storedCoordinates.Count; DataTable dt = new DataTable(); // 清除 DataTable 的內容 dt.Clear(); dt.Columns.Add("X", typeof(string)); dt.Columns.Add("Y", typeof(string)); dt.Columns.Add("Z", typeof(string)); dt.Columns.Add("Rx", typeof(string)); dt.Columns.Add("Ry", typeof(string)); dt.Columns.Add("Rz", typeof(string)); foreach (Vector3 cameraPoint in intelRealSense.storedCoordinates) { // 顯示 coordinate 的值 Console.WriteLine($"Coordinate: X={cameraPoint.X}, Y={cameraPoint.Y}, Z={cameraPoint.Z} mm"); // 將相機座標轉換為向量 var pointVector = MathNet.Numerics.LinearAlgebra.Vector.Build.DenseOfArray(new double[] { cameraPoint.X, cameraPoint.Y, cameraPoint.Z }); // 計算相對於Z軸的旋轉角度 var rotationAngles = CalculateRotationAngles(pointVector); // 顯示旋轉信息 Console.WriteLine($"Rotation Angles:"); Console.WriteLine($" thetaX: {rotationAngles[0]} degrees"); Console.WriteLine($" thetaY: {rotationAngles[1]} degrees"); Console.WriteLine($" thetaZ: {rotationAngles[2]} degrees"); //高30寬20 //(深度相機由後往前拍,手臂法蘭面向前) DataRow dr = dt.NewRow(); // 根據 eye-in-hand 校正計算手臂座標 Gx = ArmOrg_x + camoffset_x + (cameraPoint.Z - (camera_distance + CCDoffset_x)); Gy = ArmOrg_y + camoffset_y - cameraPoint.X - Math.Tan((rotationAngles[0]) * Math.PI / 180) * (camera_distance + CCDoffset_x); Gz = ArmOrg_z + camoffset_z - cameraPoint.Y + CCDoffset_z;// - Math.Tan((rotationAngles[1]) * Math.PI / 180) * (camera_distance + CCDoffset_x); GRx = 0; GRy = 90;// - rotationAngles[1]; GRz = 3 + rotationAngles[0]; dr["X"] = Gx; dr["Y"] = Gy; dr["Z"] = Gz; dr["Rx"] = GRx; dr["Ry"] = GRy; dr["Rz"] = GRz; dt.Rows.Add(dr); } // 将 DataTable 显示在 dataGridView1 中 dataGridView1.DataSource = dt; button29.Enabled = true; checkBox1.Enabled = true; checkBox2.Enabled = true; } else { MessageBox.Show("請確認是否取像與選取ROI範圍"); } } else { // 使用者按下取消,不執行任何程式碼 } } public double[] CalculateRotationAngles(MathNet.Numerics.LinearAlgebra.Vector vector) { // 1. 正規化輸入向量 var normalizedVector = vector.Normalize(2); // 2. 定義基準座標系(這裡是Z軸) var zAxis = MathNet.Numerics.LinearAlgebra.Vector.Build.Dense(new[] { 0.0, 0.0, 1.0 }); // 3. 計算旋轉矩陣 var rotationMatrix = CalculateRotationMatrix(zAxis, normalizedVector); // 4. 從旋轉矩陣提取旋轉角度 var angles = ExtractRotationAngles(rotationMatrix); return angles; } // 使用Rodrigues旋轉公式計算旋轉矩陣// 計算fromVector到toVector的旋轉矩陣 private MathNet.Numerics.LinearAlgebra.Matrix CalculateRotationMatrix(MathNet.Numerics.LinearAlgebra.Vector fromVector, MathNet.Numerics.LinearAlgebra.Vector toVector) { // 建立零向量 var v = MathNet.Numerics.LinearAlgebra.Vector.Build.Dense(new[] { 0.0, 0.0, 0.0 }); // 如果兩向量相同,返回單位矩陣 if (fromVector.Equals(toVector)) return MathNet.Numerics.LinearAlgebra.Matrix.Build.DenseIdentity(3); // 計算兩向量的點積 var cosTheta = fromVector.DotProduct(toVector); // v為fromVector在toVector方向投影的垂直分量 v = fromVector - (cosTheta * toVector); // 計算v的L2範數 var k = v.L2Norm(); // 規範化v if (k > 1e-17) v = (1.0 / k) * v; // v的外積矩陣 var vvT = v.OuterProduct(v); // v的反對稱交叉矩陣 var vSkew = SkewSymmetricCrossProductMatrix(v); // 3階單位矩陣 var eye = MathNet.Numerics.LinearAlgebra.Matrix.Build.DenseIdentity(3); // 利用Rodrigues公式計算旋轉矩陣 var rotationMatix = eye * cosTheta + (1 - cosTheta) * vvT + vSkew * Math.Sin(Math.Acos(cosTheta)); return rotationMatix; } // Construct skew-symmetric cross product matrix// 输入一个3维向量v,构建对应的反对称交叉乘矩阵 private MathNet.Numerics.LinearAlgebra.Matrix SkewSymmetricCrossProductMatrix(MathNet.Numerics.LinearAlgebra.Vector v) { // 直接构建一个3x3矩阵 return MathNet.Numerics.LinearAlgebra.Matrix.Build.DenseOfArray(new[,] { {0, -v[2], v[1]}, {v[2], 0, -v[0]}, {-v[1], v[0], 0} }); } private double[] ExtractRotationAngles(MathNet.Numerics.LinearAlgebra.Matrix R) { var thetaX = Math.Atan2(R[2, 1], R[2, 2]) * 180 / Math.PI; var thetaY = Math.Atan2(-R[2, 0], Math.Sqrt(R[0, 0] * R[0, 0] + R[1, 0] * R[1, 0])) * 180 / Math.PI; var thetaZ = Math.Atan2(R[1, 0], R[0, 0]) * 180 / Math.PI; return new[] { thetaX, thetaY, thetaZ }; } private CancellationTokenSource backgroundCts; private CancellationTokenSource backgroundCts1; [Obsolete] private async void button30_Click(object sender, EventArgs e) { DigitalSignal digitalSignalDo2 = (DigitalSignal)Form1.controller.IOSystem.GetSignal("Do2"); button29.Enabled = false; button30.Enabled = false; digitalSignalDo2.Value = 0; backgroundCts = new CancellationTokenSource(); // 啟動新的背景任務 _ = MonitorDigitalSignalAsync(digitalSignalDo2, backgroundCts.Token); // 判斷哪個RadioButton被勾選 if (checkBox1.Checked) { //Semiautomatic(); await System.Threading.Tasks.Task.Run(() => Semiautomatic()); } else if (checkBox2.Checked) { await FullyautomaticAsync(); } //await System.Threading.Tasks.Task.Run(async () => //{ // while (true) // { // if (digitalSignalDo2.Value == 1) // { // // Enable the button in the UI thread // this.Invoke(new Action(() => button30.Enabled = true)); // ok1 = true; // hasTriggered = false; // } // // 每隔5秒檢查一次 // await System.Threading.Tasks.Task.Delay(1000); // } //}); } private async System.Threading.Tasks.Task MonitorDigitalSignalAsync(DigitalSignal signal, CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { if (signal.Value == 1) { button30.Enabled = true; ok1 = true; hasTriggered = false; } await System.Threading.Tasks.Task.Delay(1000, cancellationToken); } } [Obsolete] public void Semiautomatic()//半自動化 { TakeImage(); } public bool ok1; public bool hasTriggered = false; CancellationTokenSource cts = new CancellationTokenSource(); [Obsolete] public async System.Threading.Tasks.Task FullyautomaticAsync()//全智動化 { using (cts = new CancellationTokenSource()) { try { while (!cts.Token.IsCancellationRequested) { string textBoxValue = textBox2.Text; if (string.IsNullOrEmpty(textBoxValue)) { MessageBox.Show("請輸入等待時間"); button30.Enabled = true; return; } if (!int.TryParse(textBoxValue, out int waitTime)) { MessageBox.Show("請輸入有效的數字"); button30.Enabled = true; return; } else { if (!hasTriggered) { ok1 = true; hasTriggered = true; } if (ok1 == true) { ok1 = false; await TakeImageAsync(); // 使用 Task.Delay 并检查取消标记 await System.Threading.Tasks.Task.Delay(40 * 1000, cts.Token); } // 使用 Task.Delay 并检查取消标记 await System.Threading.Tasks.Task.Delay(waitTime * 1000, cts.Token); } } } catch (OperationCanceledException) { // 任务被取消,可以在这里处理清理工作 Console.WriteLine("操作已被取消"); } finally { // 确保在方法结束时重置状态 ok1 = false; hasTriggered = false; button30.Enabled = true; } } } private void button31_Click(object sender, EventArgs e) //自動模式結束 { cts?.Cancel(); // 當按鈕被按下時,取消所有等待操作 // cts 将在 FullyautomaticAsync 方法的 using 块结束时自动释放 // 停止之前的背景任务(如果有的话) backgroundCts?.Cancel(); backgroundCts?.Dispose(); backgroundCts = null; } [Obsolete] private async System.Threading.Tasks.Task TakeImageAsync() { await System.Threading.Tasks.Task.Run(() => TakeImage(), cts.Token); } [Obsolete] public void TakeImage()//拍取待測物 { ABBrobot.Isconnectrobot(); if (controller.OperatingMode == ControllerOperatingMode.Auto && Form1.controller.State == ControllerState.MotorsOn && cameraOpened == true) { using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } int taskIndex = 0; // 獲取用戶任務 Module[] modules = controller.Rapid.GetTasks()[taskIndex].GetModules(); // 獲取任務列表 string moduleNameToFind = "MainModule"; // 指定要查找的模塊名稱 Module foundModule = modules.FirstOrDefault(module => module.Name == moduleNameToFind); // 在模塊列表中查找指定名稱的模塊 if (foundModule != null) // 如果找到了匹配的模塊 { Routine[] routines = foundModule.GetRoutines();// 獲取程序列表,這裡使用 foundModule string routineNameToFind = "TakeImage"; // 指定要查找的程序名稱 Routine foundRoutine = routines.FirstOrDefault(routine => routine.Name == routineNameToFind); // 在程序列表中查找指定名稱的程序 if (foundRoutine != null) // 如果找到了匹配的程序,PP移至例行程序 { using (Mastership.Request((IMastershipResourceController)controller)) { tasks = controller.Rapid.GetTasks(); if (tasks.Length > 0 && taskIndex >= 0 && taskIndex < tasks.Length) { tasks[taskIndex].SetProgramPointer(moduleNameToFind, routineNameToFind); iscanchangetext = true; ImageProcessing1 = true; intelRealSense.CompareSamples(); } } } } } else { MessageBox.Show("請切換自動模式,電機是否開啟"); } } private void CheckBox1_CheckedChanged(object sender, EventArgs e) { if (checkBox1.Checked) { button29.Enabled = false; button30.Enabled = true; checkBox2.Checked = false; button24.Enabled = false; textBox1.Enabled = false; } else if(checkBox2.Checked) { textBox2.Enabled = true; button30.Enabled = true; button24.Enabled = false; textBox1.Enabled = false; } else { textBox2.Enabled = false; button29.Enabled = true; button30.Enabled = false; button24.Enabled = true; textBox1.Enabled = true; } } private void CheckBox2_CheckedChanged(object sender, EventArgs e) { if (checkBox2.Checked) { textBox2.Enabled = true; button29.Enabled = false; button30.Enabled = true; checkBox1.Checked = false; button24.Enabled = false; textBox1.Enabled = false; } else if (checkBox1.Checked) { textBox2.Enabled = false; button30.Enabled = true; button24.Enabled = false; textBox1.Enabled = false; } else { textBox2.Enabled = false; button29.Enabled = true; button30.Enabled = false; button24.Enabled = true; textBox1.Enabled = true; } } [Obsolete] public void Pathchange() //修改路徑顯示 { cam = true; intelRealSense.OpenCamera(); // 打開像機 cameraOpened = true; label17.Text = "相機狀態:開"; button27.Text = "關相機"; label17.BackColor = Color.Red; // 将 DataGridView1 的 DataSource 转换为 DataTable DataTable dt = dataGridView1.DataSource as DataTable; // 创建新的 DataTable 来存储修改后的路径 DataTable dt1 = new DataTable(); dt1.Columns.Add("X", typeof(double)); dt1.Columns.Add("Y", typeof(double)); dt1.Columns.Add("Z", typeof(double)); dt1.Columns.Add("Rx", typeof(double)); dt1.Columns.Add("Ry", typeof(double)); dt1.Columns.Add("Rz", typeof(double)); // 遍历原 DataTable 的每一行并修改 foreach (DataRow dr in dt.Rows) { DataRow dr_new = dt1.NewRow(); newGx = Convert.ToDouble(dr["X"]) - intelRealSense.z; newGy = Convert.ToDouble(dr["Y"]) + intelRealSense.x; newGz = Convert.ToDouble(dr["Z"]) - intelRealSense.y; double newGRx = Convert.ToDouble(dr["Rx"]) + intelRealSense.Rz; double newGRy = Convert.ToDouble(dr["Ry"]) + intelRealSense.Rx; double newGRz = Convert.ToDouble(dr["Rz"]) + intelRealSense.Ry; // 将修改后的值添加到新的 DataRow if (intelRealSense.z > 1 || intelRealSense.z < -1 ) { dr_new["X"] = newGx; gx = "X位移了"+ -intelRealSense.z; } else { dr_new["X"] = Convert.ToDouble(dr["X"]); gx = "X不變"; } if (intelRealSense.x > 1 || intelRealSense.x < -1) { dr_new["Y"] = newGy; gy = "Y位移了" + intelRealSense.x; } else { dr_new["Y"] = Convert.ToDouble(dr["Y"]); gy = "Y不變"; } if (intelRealSense.y > 1 || intelRealSense.y < 1) { dr_new["Z"] = newGz; gz = "Z位移了" + -intelRealSense.y; } else { dr_new["Z"] = Convert.ToDouble(dr["Z"]); gz = "Z不變"; } if (intelRealSense.Rz > 1 && intelRealSense.Rz < 90 || intelRealSense.Rz < -1 && intelRealSense.Rz > -90) { dr_new["Rx"] = newGRx; gRx = "Rx位移了" + intelRealSense.Rz; } else { dr_new["Rx"] = Convert.ToDouble(dr["Rx"]); gRx = "Rx不變"; } if (intelRealSense.Rx > 1 && intelRealSense.Rx < 90 || intelRealSense.Rx < -1 && intelRealSense.Rx > -90) { dr_new["Ry"] = newGRy; gRy = "Ry位移了" + intelRealSense.Rx; } else { dr_new["Ry"] = Convert.ToDouble(dr["Ry"]); gRy = "Ry不變"; } if (intelRealSense.Ry > 1 && intelRealSense.Ry < 90 || intelRealSense.Ry < -1 && intelRealSense.Ry > -90) { dr_new["Rz"] = newGRz; gRz = "Rz位移了" + intelRealSense.Ry; } else { dr_new["Rz"] = Convert.ToDouble(dr["Rz"]); gRz = "Rz不變"; } dt1.Rows.Add(dr_new); } // 将新的 DataTable 绑定到 DataGridView2 dataGridView2.DataSource = dt1; label23.Text = $"修改路徑:\n{gx}\n{gy}\n{gz}\n{gRx}\n{gRy}\n{gRz}\n"; Performwelding(); } public System.Numerics.Vector2 Compute2DCoordinate(Vector3 displacementPoint) { // 步驟1: 將深度點從毫米轉換為米 Vector3 depthPointMeters = displacementPoint / 1000; //// 步驟2: 應用外參,將點從深度坐標系轉換到彩色坐標系 //Vector3 colorPoint = Vector3.Transform(depthPointMeters, new Matrix4x4( // intelRealSense.depthExtrinsics.rotation[0], intelRealSense.depthExtrinsics.rotation[1], intelRealSense.depthExtrinsics.rotation[2], 0, // intelRealSense.depthExtrinsics.rotation[3], intelRealSense.depthExtrinsics.rotation[4], intelRealSense.depthExtrinsics.rotation[5], 0, // intelRealSense.depthExtrinsics.rotation[6], intelRealSense.depthExtrinsics.rotation[7], intelRealSense.depthExtrinsics.rotation[8], 0, // intelRealSense.depthExtrinsics.translation[0], intelRealSense.depthExtrinsics.translation[1], intelRealSense.depthExtrinsics.translation[2], 1 //)); // 应用投影方程 float x = (depthPointMeters.X * intelRealSense.colorIntrinsics.fx / depthPointMeters.Z) + intelRealSense.colorIntrinsics.ppx; float y = (depthPointMeters.Y * intelRealSense.colorIntrinsics.fy / depthPointMeters.Z) + intelRealSense.colorIntrinsics.ppy; // 步驟4: 應用畸變校正(如果需要) if (intelRealSense.colorIntrinsics.model == Distortion.ModifiedBrownConrady) { float r2 = x * x + y * y; float f = 1 + intelRealSense.colorIntrinsics.coeffs[0] * r2 + intelRealSense.colorIntrinsics.coeffs[1] * r2 * r2 + intelRealSense.colorIntrinsics.coeffs[4] * r2 * r2 * r2; float ux = x * f + 2 * intelRealSense.colorIntrinsics.coeffs[2] * x * y + intelRealSense.colorIntrinsics.coeffs[3] * (r2 + 2 * x * x); float uy = y * f + 2 * intelRealSense.colorIntrinsics.coeffs[3] * x * y + intelRealSense.colorIntrinsics.coeffs[2] * (r2 + 2 * y * y); x = ux; y = uy; } Console.WriteLine($"Depth to Color 2D: {x} pixels, {y} pixels"); //Console.WriteLine($"Compute2DCoordinate: {x} 像素, {y} 像素"); return new Vector2(x, y); } private async System.Threading.Tasks.Task CurrentlocationSignalAsync(CancellationToken cancellationToken) { float x, y; DigitalSignal digitalSignalDo4 = (DigitalSignal)controller.IOSystem.GetSignal("Do4"); HashSet processedPoints = new HashSet(); if (intelRealSense.storedCoordinates.Count > 0) { firstCameraPoint = intelRealSense.storedCoordinates[0]; Console.WriteLine($"First Coordinate: X={firstCameraPoint.X}, Y={firstCameraPoint.Y}, Z={firstCameraPoint.Z} mm"); } float changex, changey, changez; changex = (float)(firstCameraPoint.X + intelRealSense.x); changey = (float)(firstCameraPoint.Y + intelRealSense.y); changez = (float)(firstCameraPoint.Z + intelRealSense.z); Vector3 displacementPoint = new Vector3(changex, changey, changez); Vector2 colorPixel = Compute2DCoordinate(displacementPoint); if (intelRealSense.yoloFeaturePoints.Count > 0) { Compare_yolo = intelRealSense.yoloFeaturePoints[0]; Console.WriteLine($"First Coordinate: X={Compare_yolo.X}pixels, Y={Compare_yolo.Y}pixels"); } while (!cancellationToken.IsCancellationRequested) { if (digitalSignalDo4.Value == 1) // 檢查 digitalSignalDo4.Value 是否為 1 { foreach (System.Drawing.PointF featurePoint in intelRealSense.yoloFeaturePoints) { if (processedPoints.Add(featurePoint)) // 如果這個點是新的,就會被加入 HashSet { int Difference_x = (int)(colorPixel.X - Compare_yolo.X); int Difference_y = (int)(colorPixel.Y - Compare_yolo.Y); int u = (int)featurePoint.X; int v = (int)featurePoint.Y; Console.WriteLine($"yolo: {u} px, {v} px"); x = u - Difference_x; y = v - Difference_y; Console.WriteLine($"偏移: {x} px, {y} px"); DrawPointOnBitmap(x, y); // 繪製點 break; // 一旦繪製了一個點,就跳出迴圈 } } digitalSignalDo4.Value = 0; // 重置 digitalSignalDo4.Value } await System.Threading.Tasks.Task.Delay(100, cancellationToken); // 添加延遲,避免過快重複繪製 } } private void DrawPointOnBitmap(float x, float y, float diameter = 15f, Color? color = null) { using (Graphics g = Graphics.FromImage(drawingBitmap)) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; using (SolidBrush brush = new SolidBrush(color ?? Color.Red)) { float radius = diameter / 2f; g.FillEllipse(brush, x - radius, y - radius, diameter, diameter); } } pictureBox6.Invoke((MethodInvoker)delegate { pictureBox6.Refresh(); // 使用 Refresh 而不是 Invalidate }); } private void DrawPointOnBitmap1(float x, float y, float diameter = 15f, Color? color = null) { using (Graphics g = Graphics.FromImage(drawingBitmap)) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; using (SolidBrush brush = new SolidBrush(color ?? Color.Blue)) { float radius = diameter / 2f; g.FillEllipse(brush, x - radius, y - radius, diameter, diameter); } } pictureBox6.Invoke((MethodInvoker)delegate { pictureBox6.Refresh(); // 使用 Refresh 而不是 Invalidate }); } [Obsolete] public void Performwelding() //執行焊接 { // 假設 pictureBox6.Image 已經設置了一張圖片 if (pictureBox6.Image != null) { drawingBitmap = new Bitmap(pictureBox6.Image); } else { drawingBitmap = new Bitmap(pictureBox6.Width, pictureBox6.Height); } pictureBox6.Image = drawingBitmap; backgroundCts1 = new CancellationTokenSource(); // 啟動新的背景任務 _ = CurrentlocationSignalAsync(backgroundCts1.Token); #region 直接在手臂控制器內修改現有的程式路徑(控制器內 Module 及 Routine 需要先創建並先在教導器撰寫程式流程,這邊只負責修改路徑) firstButtonClick = true; using (Mastership.Request(controller.Rapid)) { controller.Rapid.Stop(StopMode.Immediate); } using (Mastership master = Mastership.Request(controller.Rapid)) { // 直接使用路径点数量 RapidData rd = controller.Rapid.GetRapidData(tasks[taskint].Name, "MainModule", "count"); if (rd.Value is Num) { Num num = (Num)rd.Value; num.Value = aa; rd.Value = num; } rd = controller.Rapid.GetRapidData(tasks[taskint].Name, "MainModule", "path"); for (int i = 0; i < aa; i++) { RobTarget rt = (RobTarget)rd.ReadItem(i); rt.Trans.FillFromString2("[" + dataGridView2.Rows[i].Cells[0].Value.ToString() + ',' + dataGridView2.Rows[i].Cells[1].Value.ToString() + ',' + dataGridView2.Rows[i].Cells[2].Value.ToString() + "]"); rt.Rot.FillFromEulerAngles(Convert.ToDouble(dataGridView2.Rows[i].Cells[3].Value), Convert.ToDouble(dataGridView2.Rows[i].Cells[4].Value), Convert.ToDouble(dataGridView2.Rows[i].Cells[5].Value)); rt.Robconf.FillFromString("[0,0,0,0]"); rt.Extax.FillFromString("[9E+09,9E+09,9E+09,9E+09,9E+09,9E+09]"); rd.WriteItem(rt, i); } tasks[taskint].SetProgramPointer("MainModule", "WeldingPath"); controller.Rapid.Start(); } #endregion } #endregion //-------------------------------------PLC人機按鈕部分--------------------------------------- } }