├── 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 --------------------------------------------------------------------------------