arm/WindowsFormsApp1/Form1.cs
2025-02-04 20:09:10 +08:00

2221 lines
85 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Bgr, byte> ColorImg = null;
public Image<Rgb, byte> 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<Point> selectedPoints = new List<Point>();
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<double>.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<double> vector)
{
// 1. 正規化輸入向量
var normalizedVector = vector.Normalize(2);
// 2. 定義基準座標系(這裡是Z軸)
var zAxis = MathNet.Numerics.LinearAlgebra.Vector<double>.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<double> CalculateRotationMatrix(MathNet.Numerics.LinearAlgebra.Vector<double> fromVector, MathNet.Numerics.LinearAlgebra.Vector<double> toVector)
{
// 建立零向量
var v = MathNet.Numerics.LinearAlgebra.Vector<double>.Build.Dense(new[] { 0.0, 0.0, 0.0 });
// 如果兩向量相同,返回單位矩陣
if (fromVector.Equals(toVector))
return MathNet.Numerics.LinearAlgebra.Matrix<double>.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<double>.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<double> SkewSymmetricCrossProductMatrix(MathNet.Numerics.LinearAlgebra.Vector<double> v)
{
// 直接构建一个3x3矩阵
return MathNet.Numerics.LinearAlgebra.Matrix<double>.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<double> 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<System.Drawing.PointF> processedPoints = new HashSet<System.Drawing.PointF>();
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人機按鈕部分---------------------------------------
}
}