2221 lines
85 KiB
C#
2221 lines
85 KiB
C#
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人機按鈕部分---------------------------------------
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|