├── Control
├── Program.cs
└── T_ROB_1
│ ├── Module1.mod
│ └── T_ROB_1.pgf
├── LICENSE
├── README.md
├── Stream
├── ABB_RWS_JSON
│ └── Program.cs
└── ABB_RWS_XML
│ └── Program.cs
└── images
├── abb_1.PNG
├── abb_2.PNG
└── communication_scheme.png
/Control/Program.cs:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | MIT License
3 | Copyright(c) 2022 Roman Parak
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 | SOFTWARE.
19 | *****************************************************************************
20 | Author : Roman Parak
21 | Email : Roman.Parak @outlook.com
22 | Github : https://github.com/rparak
23 | File Name: Program.cs
24 | ****************************************************************************/
25 |
26 | // System Lib.
27 | using System.Net;
28 | using System.Xml;
29 | using System.Diagnostics;
30 | using System.Globalization;
31 | using System.Text;
32 |
33 | namespace ABB_RWS_Data_Processing_XML
34 | {
35 | public static class ABB_Data
36 | {
37 | // IP Port Number and IP Address
38 | public static string ip_address;
39 | // The target of reading the data: jointtarget / robtarget
40 | public static string xml_target = "";
41 | // Comunication Speed (ms)
42 | public static int time_step;
43 | // Joint Space:
44 | // Orientation {J1 .. J6} (°)
45 | public static string J_Orientation;
46 | }
47 |
48 | class Program
49 | {
50 | static void Main(string[] args)
51 | {
52 | // Initialization {Robot Web Services ABB}
53 | // Stream Data:
54 | ABB_Data.ip_address = "127.0.0.1";
55 | // The target of reading the data: jointtarget / robtarget
56 | ABB_Data.xml_target = "robtarget";
57 | // Communication speed (ms)
58 | ABB_Data.time_step = 12;
59 | // Joint Targets
60 | ABB_Data.J_Orientation = "value=[" +
61 | "[[0,0,0,0,0,0],[0,0,0,0,0,0]]," +
62 | "[[0,0,0,0,90,0],[0,0,0,0,0,0]]," +
63 | "[[20.0,-20.0,20.0,-20.0,20.0,-20.0],[0,0,0,0,0,0]]," +
64 | "[[-20.0,20.0,-20.0,20.0,-20.0,20.0],[0,0,0,0,0,0]]," +
65 | "[[0,0,0,0,0,0],[0,0,0,0,0,0]]" +
66 | "]";
67 |
68 | // Start Stream {ABB Robot Web Services - XML}
69 | ABB_Stream ABB_Stream_Robot_XML = new ABB_Stream();
70 | ABB_Stream_Robot_XML.Start();
71 |
72 | Console.WriteLine("[INFO] Stop (y):");
73 | // Stop communication
74 | string stop_rs = Convert.ToString(Console.ReadLine());
75 |
76 | if (stop_rs == "y")
77 | {
78 | // Destroy ABB {Stream}
79 | ABB_Stream_Robot_XML.Destroy();
80 |
81 | // Application quit
82 | Environment.Exit(0);
83 | }
84 | }
85 |
86 | }
87 | class ABB_Stream
88 | {
89 | // Initialization of Class variables
90 | // Thread
91 | private Thread robot_thread = null;
92 | private bool exit_thread = false;
93 | // Robot Web Services (RWS): XML Communication
94 | private CookieContainer c_cookie = new CookieContainer();
95 | private NetworkCredential n_credential = new NetworkCredential("Default User", "robotics");
96 |
97 | // Control state
98 | private int main_state = 0;
99 |
100 | public void ABB_Stream_Thread()
101 | {
102 | try
103 | {
104 | // Initialization timer
105 | var t = new Stopwatch();
106 |
107 | while (exit_thread == false)
108 | {
109 | // t_{0}: Timer start.
110 | t.Start();
111 |
112 | switch (main_state)
113 | {
114 | case 0:
115 | {
116 | // State: Reset PP to main
117 |
118 | // Create data to send
119 | string post_data = "";
120 |
121 | // Control data: Sending data to the robot controller
122 | Stream result = Control_Data(ABB_Data.ip_address, "execution?action=resetpp", post_data);
123 |
124 | main_state = 1;
125 | }
126 | break;
127 |
128 | case 1:
129 | {
130 | // State: Set Joint Targets
131 |
132 | // Control data: Sending data to the robot controller
133 | Stream result = Control_Data(ABB_Data.ip_address, "symbol/data/RAPID/T_ROB1/J_Orientation_Target?action=set", ABB_Data.J_Orientation);
134 |
135 | main_state = 2;
136 | }
137 | break;
138 |
139 | case 2:
140 | {
141 | // State: Start Rapid
142 |
143 | // Create data to send
144 | string post_data = "regain=continue&execmode=continue&cycle=forever&condition=none&stopatbp=disabled&alltaskbytsp=false";
145 |
146 | // Control data: Sending data to the robot controller
147 | Stream result = Control_Data(ABB_Data.ip_address, "execution?action=start", post_data);
148 |
149 | main_state = 3;
150 | }
151 | break;
152 |
153 | case 3:
154 | {
155 | // State: Wait
156 |
157 | // Get the system resource
158 | Stream source_data = Get_System_Resource(ABB_Data.ip_address, "in_position");
159 | // Current data streaming from the source page
160 | string value = Stream_Data(source_data);
161 |
162 | if(value == "1")
163 | {
164 | main_state = 4;
165 | }
166 | }
167 | break;
168 |
169 | case 4:
170 | {
171 | // State: Stop
172 |
173 | // Create data to send
174 | string post_data = "stopmode=stop&usetsp=normal";
175 |
176 | // Control data: Sending data to the robot controller
177 | Control_Data(ABB_Data.ip_address, "execution?action=stop", post_data);
178 |
179 | main_state = 5;
180 | }
181 | break;
182 |
183 | case 5:
184 | {
185 | // State: Empty
186 | }
187 | break;
188 | }
189 |
190 | Console.WriteLine("Current State: {0}", main_state);
191 |
192 | // t_{1}: Timer stop.
193 | t.Stop();
194 |
195 | // Recalculate the time: t = t_{1} - t_{0} -> Elapsed Time in milliseconds
196 | if (t.ElapsedMilliseconds < ABB_Data.time_step)
197 | {
198 | Thread.Sleep(ABB_Data.time_step - (int)t.ElapsedMilliseconds);
199 | }
200 |
201 | // Reset (Restart) timer.
202 | t.Restart();
203 | }
204 | }
205 | catch (Exception e)
206 | {
207 | Console.WriteLine("Communication Problem: {0}", e);
208 | }
209 | }
210 |
211 | Stream Control_Data(string host, string target, string value)
212 | {
213 | // http:// + ip address + xml address + target
214 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("http://" + host + "/rw/rapid/" + target));
215 |
216 | // Login: Default User; Password: robotics
217 | request.Credentials = n_credential;
218 | // don't use proxy, it's aussumed that the RC/VC is reachable without going via proxy
219 | request.Proxy = null;
220 | request.Method = "POST";
221 | request.PreAuthenticate = true;
222 | // re-use http session between requests
223 | request.CookieContainer = c_cookie;
224 |
225 | // Create data to send (Byte)
226 | ASCIIEncoding encoding = new ASCIIEncoding();
227 | byte[] value_byte = encoding.GetBytes(value);
228 |
229 | // set the length of the post data
230 | request.ContentLength = value_byte.Length;
231 |
232 | // Use form data when sending update etc to controller
233 | request.ContentType = "application/x-www-form-urlencoded";
234 |
235 | using (var stream = request.GetRequestStream())
236 | {
237 | stream.Write(value_byte, 0, value_byte.Length);
238 | stream.Close();
239 | }
240 |
241 | HttpWebResponse response = (HttpWebResponse)request.GetResponse();
242 | return response.GetResponseStream();
243 | }
244 |
245 | Stream Get_System_Resource(string host, string target)
246 | {
247 | // http:// + ip address + xml address + target
248 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("http://" + host + "/rw/rapid/symbol/data/RAPID/T_ROB1/" + target));
249 | // Login: Default User; Password: robotics
250 | request.Credentials = n_credential;
251 | // don't use proxy, it's aussumed that the RC/VC is reachable without going via proxy
252 | request.Proxy = null;
253 | request.Method = "GET";
254 | // re-use http session between requests
255 | request.CookieContainer = c_cookie;
256 | HttpWebResponse response = (HttpWebResponse)request.GetResponse();
257 | return response.GetResponseStream();
258 | }
259 | string Stream_Data(Stream source_data)
260 | {
261 | // Xml Node: Initialization Document
262 | XmlDocument xml_doc = new XmlDocument();
263 | // Load XML data
264 | xml_doc.Load(source_data);
265 |
266 | // Create an XmlNamespaceManager for resolving namespaces.
267 | XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml_doc.NameTable);
268 |
269 | nsmgr.AddNamespace("ns", "http://www.w3.org/1999/xhtml");
270 |
271 | // Get collection of nodes
272 | XmlNodeList xml_node = xml_doc.SelectNodes("//ns:li[@class='rap-data']", nsmgr);
273 |
274 | // Reading a value from a node and converting it to a string
275 | return xml_node[0].SelectSingleNode("ns:span[@class='value']", nsmgr).InnerText.ToString();
276 | }
277 |
278 | public void Start()
279 | {
280 | exit_thread = false;
281 | // Start a thread to stream ABB Robot
282 | robot_thread = new Thread(new ThreadStart(ABB_Stream_Thread));
283 | robot_thread.IsBackground = true;
284 | robot_thread.Start();
285 | }
286 | public void Stop()
287 | {
288 | exit_thread = true;
289 | // Stop a thread
290 | Thread.Sleep(100);
291 | }
292 | public void Destroy()
293 | {
294 | // Stop a thread (Robot Web Services communication)
295 | Stop();
296 | Thread.Sleep(100);
297 | }
298 | }
299 | }
--------------------------------------------------------------------------------
/Control/T_ROB_1/Module1.mod:
--------------------------------------------------------------------------------
1 | MODULE Module1
2 | VAR jointtarget J_Orientation_Target{5};
3 | VAR num in_position := 0;
4 | VAR num main_state := 0;
5 |
6 | PROC main()
7 | TEST main_state
8 | CASE 0:
9 | in_position := 0;
10 | main_state := 1;
11 |
12 | CASE 1:
13 | FOR i FROM 1 TO 5 DO
14 | MoveAbsJ J_Orientation_Target{i} \NoEOffs,v100,fine,tool0\WObj:=wobj0;
15 | ENDFOR
16 | main_state := 2;
17 |
18 | CASE 2:
19 | in_position := 1;
20 | main_state := 3;
21 | ENDTEST
22 | ENDPROC
23 | ENDMODULE
--------------------------------------------------------------------------------
/Control/T_ROB_1/T_ROB_1.pgf:
--------------------------------------------------------------------------------
1 |
2 |
3 | Module1.mod
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Roman Parak
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Robot Web Services (RWS) Communication between ABB IRB 120 (Server) and simple Client (C#)
2 |
3 | ## Requirements:
4 |
5 | **Software:**
6 | ```bash
7 | ABB RobotStudio, Visual Studio (or something similar)
8 | ```
9 |
10 | | Software/Package | Link |
11 | | --------------------- | ------------------------------------------------------------------------------------- |
12 | | ABB RobotStudio | https://new.abb.com/products/robotics/robotstudio/downloads |
13 | | Visual Studio | https://visualstudio.microsoft.com/downloads/ |
14 |
15 | **Programming Language:**
16 | ```bash
17 | C#, Another Language (Python, C/C++ -> similar implementation as C#)
18 | ```
19 |
20 | **Packages:**
21 | ```bash
22 | C# (.NET Framework 4.6.1)
23 | ```
24 |
25 | **Application Manual - Robot Web Services:**
26 |
27 | Link: https://developercenter.robotstudio.com/api/rwsApi/index.html
28 |
29 | ## Project Description:
30 |
31 | The project is focused on a simple demonstration of client-server communication via RWS (Robot Web Services). In this case, it is a industrial robot ABB IRB 120 (server), which communicates with the client via the C# application. An example of an application is reading data (Joint / Cartesian position) using multiple approaches (JSON, XML). However, it is possible to use JSON to read the joint position and XML to read the Cartesian position, or to use both in one approach (XML / JSON to read joints and Cartesian position).
32 |
33 | The project also includes data control through RWS, which is located in the Control folder. The control application is aimed at a simple demonstration of data exchange between a C# application and the ABB RobotStudio simulation environment.
34 |
35 | The application was tested on some of the robot types (ABB IRB 120 -> real hardware + simulation, ABB IRB 140, etc.)
36 |
37 | The application uses performance optimization using multi-threaded programming. Communication (C# application) can be used in Unity3D for digital twins / augmented reality or in other relevant applications.
38 |
39 | Sample application in the Unity3D program (Digital-Twin):
40 |
41 | [ABB IRB 120 - Unity3D Robotics](https://github.com/rparak/Unity3D_Robotics_ABB)
42 |
43 | The project was realized at the Institute of Automation and Computer Science, Brno University of Technology, Faculty of Mechanical Engineering (NETME Centre - Cybernetics and Robotics Division).
44 |
45 |
46 |
47 |
48 |
49 | ## Project Hierarchy:
50 |
51 | **Client JSON (C#) - Repository [/ABB_Robot_data_processing/Stream/ABB_RWS_JSON/]:**
52 |
53 | ```bash
54 | [ Main Program ] /Program.cs/
55 | ```
56 |
57 | **Client XML (C#) - Repository [/ABB_Robot_data_processing/Stream/ABB_RWS_XML/]:**
58 |
59 | ```bash
60 | [ Main Program ] /Program.cs/
61 | ```
62 |
63 | **Client XML (C#) - Repository [/ABB_Robot_data_processing/Control/]:**
64 |
65 | ```bash
66 | [ Main Program C# ] /Program.cs/
67 | [ RAPID program ABB RS] /T_ROB_1
68 | ```
69 |
70 | ## Example of reading Joint position and Cartesian position using different approaches (ABB IRB 120):
71 |
72 |
73 |
74 |
75 |
76 |
77 | ## Contact Info:
78 | Roman.Parak@outlook.com
79 |
80 | ## Citation (BibTex)
81 | ```bash
82 | @misc{RomanParak_DT_ABB,
83 | author = {Roman Parak},
84 | title = {Data collection from the ABB controller using Robot Web Services (RWS)},
85 | year = {2020-2022},
86 | publisher = {GitHub},
87 | journal = {GitHub repository},
88 | howpublished = {\url{https://github.com/rparak/ABB_Robot_data_processing/}}
89 | }
90 | ```
91 |
92 | ## License
93 | [MIT](https://choosealicense.com/licenses/mit/)
94 |
--------------------------------------------------------------------------------
/Stream/ABB_RWS_JSON/Program.cs:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | MIT License
3 | Copyright(c) 2020 Roman Parak
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 | SOFTWARE.
19 | *****************************************************************************
20 | Author : Roman Parak
21 | Email : Roman.Parak @outlook.com
22 | Github : https://github.com/rparak
23 | File Name: Program.cs
24 | ****************************************************************************/
25 |
26 | // System Lib.
27 | using System;
28 | using System.Net;
29 | using System.Net.Http;
30 | using System.Threading;
31 | using System.Diagnostics;
32 |
33 | namespace ABB_RWS_Data_Processing_JSON
34 | {
35 | public static class ABB_Stream_Data
36 | {
37 | // IP Port Number and IP Address
38 | public static string ip_address;
39 | // The target of reading the data: jointtarget / robtarget
40 | public static string json_target = "";
41 | // Comunication Speed (ms)
42 | public static int time_step;
43 | // Joint Space:
44 | // Orientation {J1 .. J6} (°)
45 | public static double[] J_Orientation = new double[6];
46 | // Cartesian Space:
47 | // Position {X, Y, Z} (mm)
48 | public static double[] C_Position = new double[3];
49 | // Orientation {Quaternion} (-):
50 | public static double[] C_Orientation = new double[4];
51 | }
52 |
53 | class Program
54 | {
55 |
56 | static void Main(string[] args)
57 | {
58 | // Initialization {Robot Web Services ABB}
59 | // Stream Data:
60 | ABB_Stream_Data.ip_address = "127.0.0.1";
61 | // The target of reading the data: jointtarget / robtarget
62 | ABB_Stream_Data.json_target = "robtarget";
63 | // Communication speed (ms)
64 | ABB_Stream_Data.time_step = 12;
65 |
66 | // Start Stream {Universal Robots TCP/IP}
67 | ABB_Stream ABB_Stream_Robot_JSON = new ABB_Stream();
68 | ABB_Stream_Robot_JSON.Start();
69 |
70 | Console.WriteLine("[INFO] Stop (y):");
71 | // Stop communication
72 | string stop_rs = Convert.ToString(Console.ReadLine());
73 |
74 | if (stop_rs == "y")
75 | {
76 | if (ABB_Stream_Data.json_target == "jointtarget")
77 | {
78 | Console.WriteLine("Joint Space: Orientation (radian)");
79 | Console.WriteLine("J1: {0} | J2: {1} | J3: {2} | J4: {3} | J5: {4} | J6: {5}",
80 | ABB_Stream_Data.J_Orientation[0], ABB_Stream_Data.J_Orientation[1], ABB_Stream_Data.J_Orientation[2],
81 | ABB_Stream_Data.J_Orientation[3], ABB_Stream_Data.J_Orientation[4], ABB_Stream_Data.J_Orientation[5]);
82 | }
83 | else if (ABB_Stream_Data.json_target == "robtarget")
84 | {
85 | Console.WriteLine("Cartesian Space: Position (metres), Orientation (radian):");
86 | Console.WriteLine("X: {0} | Y: {1} | Z: {2} | Q1: {3} | Q2: {4} | Q3: {5} | Q4: {6}",
87 | ABB_Stream_Data.C_Position[0], ABB_Stream_Data.C_Position[1], ABB_Stream_Data.C_Position[2],
88 | ABB_Stream_Data.C_Orientation[0], ABB_Stream_Data.C_Orientation[1], ABB_Stream_Data.C_Orientation[2], ABB_Stream_Data.C_Orientation[3]);
89 | }
90 |
91 | // Destroy ABB {Stream}
92 | ABB_Stream_Robot_JSON.Destroy();
93 |
94 | // Application quit
95 | Environment.Exit(0);
96 | }
97 | }
98 | }
99 |
100 | class ABB_Stream
101 | {
102 | // Initialization of Class variables
103 | // Thread
104 | private Thread robot_thread = null;
105 | private bool exit_thread = false;
106 |
107 | async void ABB_Stream_Thread()
108 | {
109 | var handler = new HttpClientHandler { Credentials = new NetworkCredential("Default User", "robotics") };
110 | // disable the proxy, the controller is connected on same subnet as the PC
111 | handler.Proxy = null;
112 | handler.UseProxy = false;
113 |
114 | try
115 | {
116 | // Send a request continue when complete
117 | using (HttpClient client = new HttpClient(handler))
118 | {
119 | // Initialization timer
120 | var t = new Stopwatch();
121 |
122 | while (exit_thread == false)
123 | {
124 | // t_{0}: Timer start.
125 | t.Start();
126 |
127 | // Current data streaming from the source page
128 | using (HttpResponseMessage response = await client.GetAsync("http://" + ABB_Stream_Data.ip_address + "/rw/rapid/tasks/T_ROB1/motion?resource=" + ABB_Stream_Data.json_target + "&json=1"))
129 | {
130 | using (HttpContent content = response.Content)
131 | {
132 | try
133 | {
134 | // Check that response was successful or throw exception
135 | response.EnsureSuccessStatusCode();
136 | // Get HTTP response from completed task.
137 | string result = await content.ReadAsStringAsync();
138 | // Deserialize the returned json string
139 | dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
140 |
141 | // Display controller name, version and version name
142 | var service = obj._embedded._state[0];
143 |
144 | if (ABB_Stream_Data.json_target == "jointtarget")
145 | {
146 | // Joint {1 .. 6} -> Read RWS JSON
147 | ABB_Stream_Data.J_Orientation[0] = (double)service.j1;
148 | ABB_Stream_Data.J_Orientation[1] = (double)service.j2;
149 | ABB_Stream_Data.J_Orientation[2] = (double)service.j3;
150 | ABB_Stream_Data.J_Orientation[3] = (double)service.j4;
151 | ABB_Stream_Data.J_Orientation[4] = (double)service.j5;
152 | ABB_Stream_Data.J_Orientation[5] = (double)service.j6;
153 | }
154 | else if (ABB_Stream_Data.json_target == "robtarget")
155 | {
156 | // TCP {X, Y, Z} -> Read RWS JSON
157 | ABB_Stream_Data.C_Position[0] = (double)service.x;
158 | ABB_Stream_Data.C_Position[1] = (double)service.y;
159 | ABB_Stream_Data.C_Position[2] = (double)service.z;
160 | // Quaternion {q1 .. q4} -> Read RWS JSON
161 | ABB_Stream_Data.C_Orientation[0] = (double)service.q1;
162 | ABB_Stream_Data.C_Orientation[1] = (double)service.q2;
163 | ABB_Stream_Data.C_Orientation[2] = (double)service.q3;
164 | ABB_Stream_Data.C_Orientation[3] = (double)service.q4;
165 | }
166 | }
167 | catch (Exception e)
168 | {
169 | Console.WriteLine(e.Message);
170 | }
171 | }
172 | }
173 |
174 | // t_{1}: Timer stop.
175 | t.Stop();
176 |
177 | // Recalculate the time: t = t_{1} - t_{0} -> Elapsed Time in milliseconds
178 | if (t.ElapsedMilliseconds < ABB_Stream_Data.time_step)
179 | {
180 | Thread.Sleep(ABB_Stream_Data.time_step - (int)t.ElapsedMilliseconds);
181 | }
182 |
183 | // Reset (Restart) timer.
184 | t.Restart();
185 | }
186 | }
187 | }
188 | catch (Exception e)
189 | {
190 | Console.WriteLine("Communication Problem: {0}", e);
191 | }
192 | }
193 |
194 | public void Start()
195 | {
196 | exit_thread = false;
197 | // Start a thread to stream ABB Robot
198 | robot_thread = new Thread(new ThreadStart(ABB_Stream_Thread));
199 | robot_thread.IsBackground = true;
200 | robot_thread.Start();
201 | }
202 | public void Stop()
203 | {
204 | exit_thread = true;
205 | // Stop a thread
206 | Thread.Sleep(100);
207 | }
208 | public void Destroy()
209 | {
210 | // Stop a thread (Robot Web Services communication)
211 | Stop();
212 | Thread.Sleep(100);
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/Stream/ABB_RWS_XML/Program.cs:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | MIT License
3 | Copyright(c) 2020 Roman Parak
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 | SOFTWARE.
19 | *****************************************************************************
20 | Author : Roman Parak
21 | Email : Roman.Parak @outlook.com
22 | Github : https://github.com/rparak
23 | File Name: Program.cs
24 | ****************************************************************************/
25 |
26 | // System Lib.
27 | using System;
28 | using System.Threading;
29 | using System.Net;
30 | using System.IO;
31 | using System.Xml;
32 | using System.Globalization;
33 | using System.Diagnostics;
34 |
35 | namespace ABB_RWS_Data_Processing_XML
36 | {
37 | public static class ABB_Stream_Data
38 | {
39 | // IP Port Number and IP Address
40 | public static string ip_address;
41 | // The target of reading the data: jointtarget / robtarget
42 | public static string xml_target = "";
43 | // Comunication Speed (ms)
44 | public static int time_step;
45 | // Joint Space:
46 | // Orientation {J1 .. J6} (°)
47 | public static double[] J_Orientation = new double[6];
48 | // Cartesian Space:
49 | // Position {X, Y, Z} (mm)
50 | public static double[] C_Position = new double[3];
51 | // Orientation {Quaternion} (-):
52 | public static double[] C_Orientation = new double[4];
53 | }
54 |
55 | class Program
56 | {
57 | static void Main(string[] args)
58 | {
59 | // Initialization {Robot Web Services ABB}
60 | // Stream Data:
61 | ABB_Stream_Data.ip_address = "127.0.0.1";
62 | // The target of reading the data: jointtarget / robtarget
63 | ABB_Stream_Data.xml_target = "robtarget";
64 | // Communication speed (ms)
65 | ABB_Stream_Data.time_step = 12;
66 |
67 | // Start Stream {ABB Robot Web Services - XML}
68 | ABB_Stream ABB_Stream_Robot_XML = new ABB_Stream();
69 | ABB_Stream_Robot_XML.Start();
70 |
71 | Console.WriteLine("[INFO] Stop (y):");
72 | // Stop communication
73 | string stop_rs = Convert.ToString(Console.ReadLine());
74 |
75 | if (stop_rs == "y")
76 | {
77 | if (ABB_Stream_Data.xml_target == "jointtarget")
78 | {
79 | Console.WriteLine("Joint Space: Orientation (radian)");
80 | Console.WriteLine("J1: {0} | J2: {1} | J3: {2} | J4: {3} | J5: {4} | J6: {5}",
81 | ABB_Stream_Data.J_Orientation[0], ABB_Stream_Data.J_Orientation[1], ABB_Stream_Data.J_Orientation[2],
82 | ABB_Stream_Data.J_Orientation[3], ABB_Stream_Data.J_Orientation[4], ABB_Stream_Data.J_Orientation[5]);
83 | }
84 | else if (ABB_Stream_Data.xml_target == "robtarget")
85 | {
86 | Console.WriteLine("Cartesian Space: Position (metres), Orientation (radian):");
87 | Console.WriteLine("X: {0} | Y: {1} | Z: {2} | Q1: {3} | Q2: {4} | Q3: {5} | Q4: {6}",
88 | ABB_Stream_Data.C_Position[0], ABB_Stream_Data.C_Position[1], ABB_Stream_Data.C_Position[2],
89 | ABB_Stream_Data.C_Orientation[0], ABB_Stream_Data.C_Orientation[1], ABB_Stream_Data.C_Orientation[2], ABB_Stream_Data.C_Orientation[3]);
90 | }
91 |
92 | // Destroy ABB {Stream}
93 | ABB_Stream_Robot_XML.Destroy();
94 |
95 | // Application quit
96 | Environment.Exit(0);
97 | }
98 | }
99 |
100 | }
101 | class ABB_Stream
102 | {
103 | // Initialization of Class variables
104 | // Thread
105 | private Thread robot_thread = null;
106 | private bool exit_thread = false;
107 | // Robot Web Services (RWS): XML Communication
108 | private CookieContainer c_cookie = new CookieContainer();
109 | private NetworkCredential n_credential = new NetworkCredential("Default User", "robotics");
110 |
111 | public void ABB_Stream_Thread()
112 | {
113 | try
114 | {
115 | // Initialization timer
116 | var t = new Stopwatch();
117 |
118 | while (exit_thread == false)
119 | {
120 | // t_{0}: Timer start.
121 | t.Start();
122 |
123 | // Get the system resource
124 | Stream source_data = Get_System_Resource(ABB_Stream_Data.ip_address, ABB_Stream_Data.xml_target);
125 | // Current data streaming from the source page
126 | Stream_Data(source_data);
127 |
128 | // t_{1}: Timer stop.
129 | t.Stop();
130 |
131 | // Recalculate the time: t = t_{1} - t_{0} -> Elapsed Time in milliseconds
132 | if (t.ElapsedMilliseconds < ABB_Stream_Data.time_step)
133 | {
134 | Thread.Sleep(ABB_Stream_Data.time_step - (int)t.ElapsedMilliseconds);
135 | }
136 |
137 | // Reset (Restart) timer.
138 | t.Restart();
139 | }
140 | }
141 | catch (Exception e)
142 | {
143 | Console.WriteLine("Communication Problem: {0}", e);
144 | }
145 | }
146 |
147 | Stream Get_System_Resource(string host, string target)
148 | {
149 | // http:// + ip address + xml address + target {joint, cartesian}
150 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri("http://" + host + "/rw/rapid/tasks/T_ROB1/motion?resource=" + target));
151 | // Login: Default User; Password: robotics
152 | request.Credentials = n_credential;
153 | // don't use proxy, it's aussumed that the RC/VC is reachable without going via proxy
154 | request.Proxy = null;
155 | request.Method = "GET";
156 | // re-use http session between requests
157 | request.CookieContainer = c_cookie;
158 | HttpWebResponse response = (HttpWebResponse)request.GetResponse();
159 | return response.GetResponseStream();
160 | }
161 |
162 | void Stream_Data(Stream source_data)
163 | {
164 | // Xml Node: Initialization Document
165 | XmlDocument xml_doc = new XmlDocument();
166 | // Load XML data
167 | xml_doc.Load(source_data);
168 |
169 | // Create an XmlNamespaceManager for resolving namespaces.
170 | XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml_doc.NameTable);
171 |
172 | nsmgr.AddNamespace("ns", "http://www.w3.org/1999/xhtml");
173 |
174 | if (ABB_Stream_Data.xml_target == "jointtarget")
175 | {
176 | // -------------------- Read State {Joint (1 - 6)} -------------------- //
177 | XmlNodeList xml_node = xml_doc.SelectNodes("//ns:li[@class='rapid-jointtarget']", nsmgr);
178 |
179 | // Joint (1 - 6) -> Read RWS XML
180 | ABB_Stream_Data.J_Orientation[0] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='j1']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
181 | ABB_Stream_Data.J_Orientation[1] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='j2']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
182 | ABB_Stream_Data.J_Orientation[2] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='j3']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
183 | ABB_Stream_Data.J_Orientation[3] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='j4']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
184 | ABB_Stream_Data.J_Orientation[4] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='j5']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
185 | ABB_Stream_Data.J_Orientation[5] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='j6']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
186 |
187 | }
188 | else if (ABB_Stream_Data.xml_target == "robtarget")
189 | {
190 | // -------------------- Read State {Cartesian (X,Y,Z, Quaternion {q1 - q4})} -------------------- //
191 | XmlNodeList xml_node = xml_doc.SelectNodes("//ns:li[@class='rapid-robtarget']", nsmgr);
192 |
193 | // x, y, z {Target positions} -> Read RWS XML
194 | ABB_Stream_Data.C_Position[0] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='x']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
195 | ABB_Stream_Data.C_Position[1] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='y']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
196 | ABB_Stream_Data.C_Position[2] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='z']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
197 | // q1, q2, q3, q4 {Orientation} -> Read RWS XML
198 | ABB_Stream_Data.C_Orientation[0] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='q1']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
199 | ABB_Stream_Data.C_Orientation[1] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='q2']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
200 | ABB_Stream_Data.C_Orientation[2] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='q3']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
201 | ABB_Stream_Data.C_Orientation[3] = double.Parse(xml_node[0].SelectSingleNode("ns:span[@class='q4']", nsmgr).InnerText.ToString(), CultureInfo.InvariantCulture.NumberFormat);
202 | }
203 | }
204 |
205 | public void Start()
206 | {
207 | exit_thread = false;
208 | // Start a thread to stream ABB Robot
209 | robot_thread = new Thread(new ThreadStart(ABB_Stream_Thread));
210 | robot_thread.IsBackground = true;
211 | robot_thread.Start();
212 | }
213 | public void Stop()
214 | {
215 | exit_thread = true;
216 | // Stop a thread
217 | Thread.Sleep(100);
218 | }
219 | public void Destroy()
220 | {
221 | // Stop a thread (Robot Web Services communication)
222 | Stop();
223 | Thread.Sleep(100);
224 | }
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/images/abb_1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rparak/ABB_Robot_data_processing/47fe845dec6d853315956625f5ab1ba7d6242eb1/images/abb_1.PNG
--------------------------------------------------------------------------------
/images/abb_2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rparak/ABB_Robot_data_processing/47fe845dec6d853315956625f5ab1ba7d6242eb1/images/abb_2.PNG
--------------------------------------------------------------------------------
/images/communication_scheme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rparak/ABB_Robot_data_processing/47fe845dec6d853315956625f5ab1ba7d6242eb1/images/communication_scheme.png
--------------------------------------------------------------------------------