7 Using the PC SDK. ABB RobotWare 5.0
Robot Application Builder (RAB) is a software tool, which enables ABB programmers to develop customized operator interfaces for the IRC5 robot controller. Robot Application Builder is fully integrated with Microsoft Visual Studio, which means that a .NET programmer will recognize wizards for project setup, tools for visual design support, and debug etc.
Advertisement
Advertisement
7 Using the PC SDK
7 Using the PC SDK
6.4. Reliability
3HAC028083-001 Revision: D 199
7 Using the PC SDK
7.1. Controller API
7.1. Controller API
PC SDK domains
The PC SDK class libraries are organized in the following domains:
• Controllers
•
ConfigurationDomain
• Discovery
•
EventLogDomain
• FileSystemDomain
•
Hosting
• IOSystemDomain
•
Messaging
• MotionDomain
•
RapidDomain
• UserAuthorizationManagement
CAPI illustration
The classes used to access robot controller functionality together make up the Controller API
(CAPI). Part of the CAPI object model is illustrated below:
200
8.2.2_1
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.1. Controller API
Continued
PC SDK Reference
This User’s Guide covers some of the PC SDK functionality, but is by no means a complete guide to the PC SDK.
The PC SDK Reference is the complete reference of the PC SDK class libraries. It should be your companion while programming.
It can be launched from Windows Start menu by pointing at Programs - ABB Industrial IT
- Robotics IT - Robot Application Builder 5.xx and selecting PC SDK Reference.
3HAC028083-001 Revision: D 201
7 Using the PC SDK
7.2. Create a simple PC SDK application
7.2. Create a simple PC SDK application
Overview
To get started programming let us create a simple application that will display all virtual and real controllers on the network. It should then be possible to log on to a controller and start
RAPID execution.
CAUTION!
Remote access to controllers must be handled carefully. Make sure you do not unintentionally disturb a system in production.
Set up the project
Follow these steps to set up a PC SDK project.
Step Action
1. On the File menu in Visual Studio, point to New and then click Project. Select a
Windows Application project.
2. Add the references to the PC SDK assemblies, ABB.Robotics.dll and ABB.Robot-
ics.Controllers.dll, to the project. The assemblies are located in the installation directory, by default at C:\Program Files\ABB Industrial IT\Robotics IT\Robot
Application Builder 5.xx\PC SDK.
3. Open Form1.cs and add the needed namespace statements at the top of the source code page:
VB:
Imports ABB.Robotics
Imports ABB.Robotics.Controllers
Imports ABB.Robotics.Controllers.Discovery
Imports ABB.Robotics.Controllers.RapidDomain
C#: using ABB.Robotics; using ABB.Robotics.Controllers; using ABB.Robotics.Controllers.Discovery; using ABB.Robotics.Controllers.RapidDomain;
4. In the Solution Explorer right-click Form1.cs and select View Designer. Create the Graphical User Interface according to the instruction in the next section.
202
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.2. Create a simple PC SDK application
Continued
Create the user interface
This picture shows the running PC SDK application that we will create. As you see both virtual and real controllers on the network are included in a network scan.
7.1_1
Follow these steps to create the user interface of the application:
Step Action
1. Change the Text property of the form to “Network scanning window”.
2. Change its Size to 850; 480.
3. Add a
ListView
control to the form. Set the following properties to get a similar look as in the figure above:
FullRowSelect - True
GridLines - True
View - Details
4. Add the columns for IPAdress, ID, Availability, Virtual, System name, RW Version and Controller name and adjust the width of the columns.
5. Add a
Panel
with a
Button
under the listview. Set the
Text
of the button.
Implement network scanning
To find all controllers on the network we start by declaring these member variables in the class
Form1
VB:
Private scanner As NetworkScanner = Nothing
Private controller As Controller = Nothing
Private tasks As Task() = Nothing
Private networkWatcher As NetworkWatcher = Nothing
3HAC028083-001 Revision: D
Continues on next page
203
7 Using the PC SDK
7.2. Create a simple PC SDK application
Continued
204
C#: private NetworkScanner scanner = null; private Controller controller = null; private Task[] tasks = null; private NetworkWatcher networkwatcher = null;
As the application is supposed to scan the network as soon as it is started, we can put the code for it in the
Form1_Load
event handler, like this:
VB:
Me.scanner = New NetworkScanner
Me.scanner.Scan()
Dim controllers As ControllerInfoCollection =
Me.scanner.Controllers
Dim controllerInfo As ControllerInfo = Nothing
Dim item As ListViewItem
For Each controllerInfo In controllers item = New ListViewItem(controllerInfo.IPAddress.ToString()) item.SubItems.Add(controllerInfo.Id) item.SubItems.Add(controllerInfo.Availability.ToString()) item.SubItems.Add(controllerInfo.IsVirtual.ToString()) item.SubItems.Add(controllerInfo.SystemName) item.SubItems.Add(controllerInfo.Version.ToString()) item.SubItems.Add(controllerInfo.ControllerName)
Me.listView1.Items.Add(item) item.Tag = controllerInfo
Next
C#: this.scanner = new NetworkScanner(); this.scanner.Scan();
ControllerInfoCollection controllers = scanner.Controllers;
ListViewItem item = null; foreach (ControllerInfo controllerInfo in controllers)
{
item = new ListViewItem(controllerInfo.IPAddress.ToString());
item.SubItems.Add(controllerInfo.Id);
item.SubItems.Add(controllerInfo.Availability.ToString());
item.SubItems.Add(controllerInfo.IsVirtual.ToString());
item.SubItems.Add(controllerInfo.SystemName);
item.SubItems.Add(controllerInfo.Version.ToString());
item.SubItems.Add(controllerInfo.ControllerName);
this.listView1.Items.Add(item);
}
item.Tag = controllerInfo;
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.2. Create a simple PC SDK application
Continued
Add a network watcher
By implementing a
NetworkWatcher
the application can supervise the network and detect when controllers are lost or added. This example shows how to program network supervision, and how to add a detected controller to the listview.
After having added a
NetworkWatcher
object to the
FormLoad
event handler, we add a subscription to its
Found
event.
VB:
Me.networkWatcher = New NetworkWatcher(Me.scanner.Controllers)
AddHandler Me.networkWatcher.Found, AddressOf Me.HandleFoundEvent
AddHandler Me.networkWatcher.Lost, AddressOf Me.HandleLostEvent
Me.networkWatcher.EnableRaisingEvents = True
C#: this.networkwatcher = new NetworkWatcher(scanner.Controllers); this.networkwatcher.Found += new EventHandler
<NetworkWatcherEventArgs>(HandleFoundEvent); this.networkwatcher.Lost += new EventHandler
<NetworkWatcherEventArgs>(HandleLostEvent); this.networkwatcher.EnableRaisingEvents = true;
NOTE!
In C# the event handler skeleton is auto generated using the Tab key twice after “+=” in the above statements. If you prefer, you can use a simplified syntax when using generic event handlers: networkwatcher.Found += HandleFoundEvent;
Handle event
As the events will be received on a background thread and should result in an update of the user interface the
Invoke
method must be called in the event handler. See
about how to force execution from background to GUI thread.
VB:
Private Sub HandleFoundEvent(ByVal sender As Object, ByVal e As
NetworkWatcherEventArgs)
Me.Invoke(New NetworkWatcherEventHandler(AddressOf
AddControllerToListView), New Object() {sender, e})
End Sub
C#: void HandleFoundEvent(object sender, NetworkWatcherEventArgs e)
{ this.Invoke(new
EventHandler<NetworkWatcherEventArgs>(AddControllerToList
View), new Object[] { sender, e });
}
3HAC028083-001 Revision: D
Continues on next page
205
7 Using the PC SDK
7.2. Create a simple PC SDK application
Continued
This event handler updates the user interface:
VB:
Private Sub AddControllerToListView(ByVal sender
As Object, ByVal e As NetworkWatcherEventArgs)
Dim controllerInfo As ControllerInfo = e.Controller
Dim item As ListViewItem = New ListViewItem( controllerInfo.IPAddress.ToString()) item.SubItems.Add(controllerInfo.Id) item.SubItems.Add(controllerInfo.Availability.ToString()) item.SubItems.Add(controllerInfo.IsVirtual.ToString()) item.SubItems.Add(controllerInfo.SystemName) item.SubItems.Add(controllerInfo.Version.ToString()) item.SubItems.Add(controllerInfo.ControllerName)
Me.listView1.Items.Add(item) item.Tag = controllerInfo
End Sub
C#: private void AddControllerToListView(object sender,
NetworkWatcherEventArgs e)
{
ControllerInfo controllerInfo = e.Controller;
ListViewItem item = new
ListViewItem(controllerInfo.IPAddress.ToString()); item.SubItems.Add(controllerInfo.Id); item.SubItems.Add(controllerInfo.Availability.ToString()); item.SubItems.Add(controllerInfo.IsVirtual.ToString()); item.SubItems.Add(controllerInfo.SystemName); item.SubItems.Add(controllerInfo.Version.ToString()); item.SubItems.Add(controllerInfo.ControllerName); this.listView1.Items.Add(item); item.Tag = controllerInfo;
}
Establish connection to controller
When the user double-clicks a controller in the list a connection to that controller should be established and the user should be logged on. Follow these steps to implement this functionality:
Step Action
1. Generate the
DoubleClick event of the
ListView
.
2. In the event handler create a
Controller
object that represents the selected robot controller.
3. Log on to the selected controller. See the code sample of
Implement event handler on page 207
206
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.2. Create a simple PC SDK application
Continued
Implement event handler
This example shows the code of the
ListView.DoubleClick
event handler:
VB:
Dim item As ListViewItem = Me.listView1.SelectedItems(0)
If Not item.Tag Is Nothing Then
Dim controllerInfo As ControllerInfo controllerInfo = DirectCast(item.Tag, ControllerInfo)
If controllerInfo.Availability = Availability.Available Then
If Not Me.controller Is Nothing Then
Me.controller.Logoff()
Me.controller.Dispose()
Me.controller = Nothing
End If
Me.controller = ControllerFactory.CreateFrom(controllerInfo)
Me.controller.Logon(UserInfo.DefaultUser)
End If
Else
MessageBox.Show("Selected controller not available.")
End If
C#:
ListViewItem item = this.listView1.SelectedItems[0]; if (item.Tag != null)
{
ControllerInfo controllerInfo = (ControllerInfo) item.Tag; if (controllerInfo.Availability == Availability.Available)
{ if (this.controller != null)
{ this.controller.Logoff(); this.controller.Dispose(); this.controller = null;
} this.controller =
ControllerFactory.CreateFrom(controllerInfo); this.controller.Logon(UserInfo.DefaultUser);
} else
{
MessageBox.Show("Selected controller not available.");
}
}
3HAC028083-001 Revision: D
Continues on next page
207
7 Using the PC SDK
7.2. Create a simple PC SDK application
Continued
NOTE!
The check to see whether the
Controller
object already exists is important, as you should explicitly log off and dispose of any existing controller object before creating a new one. The reason is that a logon session allocates resources that should not be kept longer than necessary.
Start program execution
The
Click
event handler of the Start RAPID Program button should start program execution of the first RAPID task.
Starting RAPID execution in manual mode can only be done from the FlexPendant, so we need to check that the controller is in automatic mode before trying. We then need to request mastership of
Rapid
and call the
Start
method. If mastership is already held, by ourselves or another client, an
InvalidOperationException
will be thrown. For further information see
It is necessary to release mastership whether or not the start operation succeeds. This can be done by calling
Release()
or
Dispose()
in a finally clause, as shown in the VB example, or by applying the using
mechanism, as shown in the C# example.
VB:
Private m As Mastership = Nothing
...
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click
Dim m As ABB.Robotics.Controllers.Mastership = Nothing
Try
If controller.OperatingMode = ControllerOperatingMode.Auto
Then tasks = controller.Rapid.GetTasks() m = Mastership.Request(controller.Rapid)
'Perform operation tasks(0).Start()
Else
MessageBox.Show("Automatic mode is required to start execution from a remote client.")
End IfCatch ex As InvalidOperationException
MessageBox.Show("Mastership is held by another client.")
Catch ex As System.Exception
MessageBox.Show("Unexpected error occurred: " + ex.Message)
Finally
If Not m Is Nothing Then
If (m.IsMaster()) Then m.Release()
End If
End If
End Try
End Sub
208
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.2. Create a simple PC SDK application
Continued
C#: private void Button1_Click(object sender, EventArgs e)
{ try
{ if (_controller.OperatingMode ==
ControllerOperatingMode.Auto)
{ tasks = controller.Rapid.GetTasks();
}
} else
{ using (Mastership m =
Mastership.Request(controller.Rapid))
{
//Perform operation tasks[0].Start();
MessageBox.Show("Automatic mode is required to start execution from a remote client.");
}
} catch (System.InvalidOperationException ex)
{
MessageBox.Show("Mastership is held by another client.");
} catch (System.Exception ex)
{
MessageBox.Show("Unexpected error occurred: " + ex.Message);
}
}
3HAC028083-001 Revision: D 209
7 Using the PC SDK
7.3. Discovery domain
7.3. Discovery domain
Overview
To create a connection to the controller from a PC SDK application it has to make use of the
Netscan functionality of the
Discovery
namespace. A
NetworkScanner
object must be created and a
Scan
call must be performed.
For the PC SDK to be able to establish a connection either RobotStudio or Robot
Communications Runtime must be installed on the PC hosting the PC SDK application.
Robot Communications Runtime can be installed from C:\Program Files\ABB Industrial
IT\Robotics IT\Robot Application Builder
5.xx\redistributable\RobotCommunicationRuntime if RobotStudio is not installed.
To find out what controllers are available on the network you use the
NetworkScanner methods
Scan
,
Find
,
GetControllers
and
GetRemoteControllers
.
NetworkScanner
The
NetworkScanner
class can be declared and instantiated at class level. No scanning is done until the
Scan
method is called. When the
GetControllers
method is called a collection of
ControllerInfo
objects is returned. Each such object holds information about a particular controller connected to the local network. Both virtual and real controllers are detected this way.
VB:
Private AScanner As NetworkScanner = New NetworkScanner
...’ Somewhere in the code
AScanner.Scan()
Dim ACollection As ControllerInfo() = AScanner.GetControllers()
C#: private NetworkScanner aScanner = new NetworkScanner();
... // Somewhere in the code aScanner.Scan();
ControllerInfo[] aCollection = aScanner.GetControllers();
Implement network scanning on page 203
for a complete code sample.
If only real controllers are of interest, you can first scan the network and then request only real controllers using the
NetworkScannerSearchCriterias
enumeration in the
GetControllers
method.
VB:
Dim ACollection As ControllerInfo() =
AScanner.GetControllers(NetworkScannerSearchCriterias.Real)
C#:
ControllerInfo[] aCollection = aScanner.GetControllers(NetworkScannerSearchCriterias.Real)
;
210
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.3. Discovery domain
Continued
If you know which controller system you want to connect to you can call the
Find
method, which finds a specified controller on the network. It takes the system ID as a System.Guid data type as argument. The system’s globally unique identifier (GUID) can be find in the
system.guid file in the INTERNAL folder of the robot system file system.
ControllerInfo object
When a network scan is performed a collection of
ControllerInfo
objects is returned. The
ControllerInfo object has information about availability. Remember that the ControllerInfo object is not updated when controller status changes. If you again need to find out if a controller is available, you need to perform a new network scan or use an existing
Controller
object and check the status directly.
Add controllers from outside local network
A network scan is done only on the local network. To detect controllers outside the local network you need to supply the IP address of the controller using the static
AddRemoteController
method or configuring it in the App.config file. See
PC application configuration on page 43
If you supply the controller IP address you either use a string argument or a
System.Net.IPAddress
object.
VB:
Dim AnIPAddress As System.Net.IPAddress
Try
AnIPAddress = System.Net.IPAddress.Parse(Me.TextBox1.Text)
NetworkScanner.AddRemoteController(AnIPAddress)
Catch ex As FormatException
Me.TextBox1.Text = "Wrong IP address format"
End Try
C#:
System.Net.IPAddress ipAddress; try
{
} catch (FormatException ex)
{ ipAddress = System.Net.IPAddress.Parse(Me.textBox1.Text);
NetworkScanner.AddRemoteController(ipAddress);
Me.textBox1.Text = "Wrong IP address format";
}
NetworkWatcher
By using a
NetworkWatcher
object you can supervise network changes and find out when a new controller is found or when a controller is lost. See
Add a network watcher on page 205
for a complete code example.
3HAC028083-001 Revision: D 211
7 Using the PC SDK
7.4. Accessing the controller
7.4. Accessing the controller
Controller object
By using a
Controller
object you can get access to the different domains of the robot controller, e.g. IO signals, RAPID, file system and elog messages.
To create a
Controller
object you normally make a call to the
ControllerFactory
:
VB:
Private AController As Controller
AController = ControllerFactory.CreateFrom(info As
ControllerInfo)
C#: private Controller aController; aController = ControllerFactory.CreateFrom(ControllerInfo info);
212
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.4. Accessing the controller
Continued
The argument is a
ControllerInfo
object, which may have been retrieved during a network scan, see
. It is also possible to add an optional
argument if the IP address of the controller or the system ID (guid) should be used.
If the PC application is supposed to work with a single controller it can be specified in an
app.config file. The default constructor can then be used to create the controller object, e.g. aController = new Controller()
for details.
If several classes in your application need to access the controller, it is recommended that they all reference the same
Controller
object. This is done either by passing the
Controller object as an argument to the constructor or by using a
Controller
property.
NOTE!
You should be aware that the .NET objects created for operations toward the robot controller will access native resources (C++ and COM code). The .NET garbage collector does not collect such objects, but these must be disposed of explicitly by the application programmer.
Memory management in PC applications on page 213
Memory management in PC applications
An important feature of the .NET runtime environment is the garbage collector, which reclaims not referenced memory from the managed heap. Generally, this means that the programmer does not have to free memory that has been allocated by the use of new
. There is no way of knowing exactly when garbage collection will be performed however.
For a PC application indeterministic deallocation of resources is usually not a problem (as opposed to a FlexPendant application, which runs on a small device with limited memory).
The
IDisposable
interface, however, can be used in a PC application to obtain deterministic deallocation of resources. Using this interface you can make an explicit call to the
Dispose
method of any disposable object.
If your application is running in a Single Threaded Apartment (STA) the
Dispose
call will dispose of managed objects, but native resources (created internally by the PC SDK) will remain. To release these native objects, the method
ReleaseUnmanagedResources
should be called periodically, for example when the user presses a certain button or each time data has been written to the controller. The method call is not costly.
For an application running in a Multi Threaded Apartment (MTA) the
Dispose
call will remove both managed and native objects.
NOTE!
The method
Controller.ReleaseUnmanagedResources
should be called once in a while to avoid memory leaks in PC SDK applications running in STA.
Dispose
It is the creator of a disposable object that is responsible for its lifetime and for calling
Dispose
. A check should be done that the object still exists and any subscriptions to controller events should be removed before the
Dispose
call. This is how you dispose of a
Controller
object:
3HAC028083-001 Revision: D
Continues on next page
213
7 Using the PC SDK
7.4. Accessing the controller
Continued
VB:
C#:
If Not AController Is Nothing Then
RemoveHandler AController.OperatingModeChanged, AddressOf
UpdateOpMode
AController.Dispose()
AController = Nothing
End If if (aController != null)
{
AController.OperatingModeChanged -= new UpdateOpMode; aController.Dispose(); aController = null;
}
Logon and logoff
Before accessing a robot controller the PC SDK application has to log on to the controller.
The
UserInfo
parameter of the
Logon
method has a
DefaultUser
property that can be used. By default all robot systems have such a user configured.
VB:
C#:
AController.Logon(UserInfo.DefaultUser) aController.Logon(UserInfo.DefaultUser);
If it is necessary for your application to handle users with different rights, these users can be configured by using the
UserAuthorizationManagement
namespace or by using the UAS administration tool in RobotStudio. This is how you create a new
UserInfo
object for login purposes.
VB:
Dim AUserInfo As UserInfo = New UserInfo("name", "password")
C#:
UserInfo aUserInfo = new UserInfo("name", "password");
214
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.4. Accessing the controller
Continued
NOTE!
It is necessary to log off from the controller at application shut down at the latest.
VB:
AController.LogOff()
C#: aController.LogOff();
Mastership
In order to get write access to some of the controller domains the application has to request mastership. The
Rapid
domain, i.e. tasks, programs, modules, routines and variables that exist in the robot system, is one such domain. The
Configuration
domain is another.
for detailed information on this topic.
It is important to release mastership after a modification operation. One way of doing this is applying the using
statement, which results in an automatic disposal of the
Mastership object at the end of the block. Another possibility is releasing mastership in a
Finally
block, which is executed after the
Try
and
Catch
blocks. See how it can be coded in the examples
Start program execution on page 208
Controller events
The
Controller
object provides several public events, which enable you to listen to operating mode changes, controller state changes, mastership changes etc.
VB:
AddHandler AController.OperatingModeChanged, AddressOf
UpdateOpMode
AddHandler AController.StateChanged, AddressOf UpdateState
AddHandler AController.ConnectionChanged, AddressOf UpdateConn
C#:
AController.OperatingModeChanged += new UpdateOpMode;
AController.StateChanged += new UpdateState;
AController.ConnectionChanged += new UpdateConn;
3HAC028083-001 Revision: D
Continues on next page
215
7 Using the PC SDK
7.4. Accessing the controller
Continued
NOTE!
Controller events use their own threads. Carefully study
Controller events and threads on page 67
NOTE!
PC SDK 5.09 and onwards uses the generic event handling introduced by .NET Framework
2.0.
CAUTION!
Do not rely on receiving an initial event when setting up/activating a controller event. There is no guarantee an event will be triggered, so you had better read the initial state from the controller.
Backup and Restore
Using the
Controller
object you can call the
Backup
method. The argument is a string describing the directory path on the controller where the backup should be stored. You can also restore a previously backed up system. This requires mastership of
Rapid
and
Configuration
and can only be done in Auto mode.
Backup sample
As the backup process is performed asynchronously you can add an event handler to receive a
BackupCompleted
event when the backup is completed. The backup directory should be created in the system backup directory, or else an exception will be thrown.
VB:
Dim BackupDir As String = "(BACKUP)$"+BackupDirName
AddHandler Me.AController.BackupCompleted, AddressOf
AController_BackupCompleted)
Me.AController.Backup(BackupDir)
C#: string backupDir = "(BACKUP)$"+backupDirName; this.aController.BackupCompleted += new
BackupEventHandler(controller_BackupCompleted); this.aController.Backup(backupDir);
Restore sample
216
The
Restore
method is synchronous, i.e. execution will not continue until the restore operation is completed.
VB:
Dim RestoreDir As String = "(BACKUP)$"+dirName
Dim M As Mastership
Try
MC = Mastership.Request(Me.AController.Configuration)
MR = Mastership.Request(Me.AController.Rapid)
Me.AController.Restore(RestoreDir, RestoreIncludes.All,
RestoreIgnores.All)
Finally
MC.Release()
MR.Release()
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.4. Accessing the controller
Continued
C#:
End Try string restoreDir = "(BACKUP)$"+dirName; using (Mastership mc =
Mastership.Request(this.aController.Configuration), mr =
Mastership.Request(this.aController.Rapid))
{ this.aController.Restore(restoreDir, RestoreIncludes.All,
RestoreIgnores.All);
}
VirtualPanel
You can programmatically change the operating mode of the virtual IRC5 using the
VirtualPanel
class and its
ChangeMode
method. This blocks the application thread until the user manually accepts the mode change to Auto using the Virtual FlexPendant. An alternative to blocking the application thread eternally is to add a time-out and use a
trycatch
block to catch the
TimeoutException
.
VB:
Dim vp As VirtualPanel = VirtualPanel.Attach(AController)
Try vp.ChangeMode(ControllerOperatingMode.Auto, 5000)
Catch ex As TimeoutException
Me.TextBox1.Text = "Timeout occurred at change to auto"
End Try vp.Dispose()
C#:
VirtualPanel vp = VirtualPanel.Attach(aController); try
{
} vp.ChangeMode(ControllerOperatingMode.Auto, 5000); catch (TimeoutException ex)
{ this.textBox1.Text = "Timeout occurred at change to auto";
} vp.Dispose();
There are also the asynchronous method calls
BeginChangeOperatingMode
and
EndChangeOperatingMode
. It is important to use the second method in the callback since it returns the waiting thread to the thread-pool.
VB:
Dim vp As VirtualPanel = VirtualPanel.Attach(AController) vp.BeginChangeOperatingMode(ControllerOperatingMode.Auto, New
AsyncCallback(AddressOf ChangeMode), vp)
3HAC028083-001 Revision: D
Continues on next page
217
7 Using the PC SDK
7.4. Accessing the controller
Continued
C#:
VirtualPanel vp = VirtualPanel.Attach(aController); vp.BeginChangeOperatingMode(ControllerOperatingMode.Auto, new
AsyncCallback(ChangedMode), vp);
The callback method must have the following signature and call the
EndChangeOperatingMode
as well as dispose the
VirtualPanel
.
VB:
Private Sub ChangeMode(ByVal iar As IAsyncResult)
Dim vp As VirtualPanel = DirectCast(iar.AsyncState,
VirtualPanel) vp.EndChangeOperatingMode(iar) vp.Dispose()
.....
C#: private void ChangedMode(IAsyncResult iar)
{
VirtualPanel vp = (VirtualPanel) iar.AsyncState; vp.EndChangeOperatingMode(iar); vp.Dispose();
....
Learn more
This User’s Guide only covers some of the PC SDK functionality. To get the full potential of the PC SDK you should make use of the PC SDK Reference located in the PC SDK installation directory. See
.
You can also learn a lot by becoming an active member of the RobotStudio Community. Its
Robot Application Builder User Forum should be your number one choice when you find yourself stuck with a coding issue you cannot solve on your own. See
for further information.
218 3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.1. Working with RAPID data
7.5 Rapid domain
7.5.1. Working with RAPID data
Overview
The
RapidDomain
namespace enables access to RAPID data in the robot system. There are numerous PC SDK classes representing the different RAPID data types. There is also a
UserDefined
class used to reference RECORD structures in RAPID.
The
ValueChanged
event enables notification from the controller when persistent RAPID data has changed.
To speed up event notification from the controller there is new functionality in PC SDK 5.10, which allows you to set up subscription priorities. This possibility applies to I/O signals and persistent RAPID data. This mechanism is further described in
Implementing high priority data subscriptions on page 226
.
NOTE!
To read RAPID data you need to log on to the controller. To modify RAPID data you must also request mastership of the
Rapid
domain.
Providing the path to the RAPID data
To read or write to RAPID data you must first create a
RapidData
object. The path to the declaration of the data in the controller is passed as argument. If you don’t know the path you need to search for the RAPID data by using the
SearchRapidSymbol
functionality. See
RAPID symbol search on page 157
for further information.
Direct access
Direct access requires less memory and is faster, and is therefore recommended if you do not need to use the task and module objects afterwards.
The example below shows how to create a
RapidData
object that refers to the instance
“reg1” in the USER module.
VB:
Dim Rd As RapidData = Me.AController.Rapid.GetRapidData(
"T_ROB1", "USER", "reg1")
C#:
RapidData rd = aController.Rapid.GetRapidData("T_ROB1", "USER",
"reg1");
Hierarchical access
If you need the task and module objects hierarchical access can be more efficient.
GetRapidData
exists in the Rapid, Task and Module class.
VB:
Rd = AController.Rapid.GetTask("T_ROB1").GetModule("USER").
GetRapidData("reg1")
C#: rd = aController.Rapid.GetTask("T_ROB1").GetModule("USER").
GetRapidData("reg1");
3HAC028083-001 Revision: D
Continues on next page
219
7 Using the PC SDK
7.5.1. Working with RAPID data
Continued
Accessing data declared in a shared module
If your application is to be used with a multi-move system (one controller and several motion tasks/robots), it may happen that the RAPID instance you need to access is declared in a -
Shared RAPID module. Such a module can be used by all tasks, T_ROB1, T_ROB2 etc.
This example shows how to create a
RapidData
object that refers to the instance “reg100”, which is declared in a shared module.
C#:
Task tRob1 = aController.Rapid.GetTask("T_ROB1"); if (tRob1 != null)
{
RapidData rData = tRob1.GetRapidData("reg100");
}
NOTE!
If the data is declared in a -Shared -Hidden module it cannot be accessed by the PC SDK.
Creating an object representing the RAPID data value
The
RapidData
object stores the path to the RAPID data. But this is not enough if you want to access its value (at least not if you want to modify it). To do that you need to create another object, which represents the value of the RAPID data.
In the
RapidDomain
namespace there are types representing the different RAPID data types.
To create the object needed to represent the RAPID data value you use the
RapidData property
Value
and cast it to the corresponding type, e.g.
Num, Bool or
Tooldata
.
This is how this is done if you want to access the value of a RAPID data of the RAPID data type bool
:
VB:
’declare a variable of data type RapidDomain.Bool
Dim rapidBool As RapidDomain.Bool
Dim rd As RapidData = Me.AController.Rapid.GetRapidData( "T_ROB1",
"MainModule", "flag" )
’test that data type is correct before cast
If TypeOf rd.Value Is RapidDomain.Bool Then rapidBool = DirectCast(rd.Value, RapidDomain.Bool)
’check if the value of the RAPID data is true
If (rapidBool.Value) Then
’ Do something...
End If
EndIf
220
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.1. Working with RAPID data
Continued
C#:
//declare a variable of data type RapidDomain.Bool
RapidDomain.Bool rapidBool;
RapidDomain.RapidData rd = aController.Rapid.GetRapidData("T_ROB1", "MainModule",
"flag");
//test that data type is correct before cast if (rd.Value is ABB.Robotics.Controllers.RapidDomain.Bool)
{ rapidBool =
(ABB.Robotics.Controllers.RapidDomain.Bool)rd.Value;
//assign the value of the RAPID data to a local variable bool boolValue = rapidBool.Value;
}
If you just want to read this variable you can use this technique instead of creating a
RapidDomain.
Bool
object:
VB:
Dim b As Boolean = Convert.ToBoolean(rd.Value.ToString)
C#: bool b = Convert.ToBoolean(rd.Value.ToString());
The .NET type
ToolData
(representing the RAPID data type tooldata)
can be created like this:
VB:
Dim ATool As ToolData
If Rd.Value Is ToolData Then
ATool = DirectCast(Rd.Value, ToolData)
End If
C#:
ToolData aTool; if (rd.Value is ToolData)
{ aTool = (ToolData) rd.Value;
}
IRapidData.ToString method
All RapidDomain structures representing RAPID data types implement the
IRapidData interface. It has a
ToString
method, which returns the value of the RAPID data in the form of a string. This is a simple example: string boolValue = rapidBool.ToString();
3HAC028083-001 Revision: D
Continues on next page
221
7 Using the PC SDK
7.5.1. Working with RAPID data
Continued
The string is formatted according to the principle described in
IRapidData.FillFromString method on page 222
Below is an example of a more complex data type. The
ToolData Tframe
property is of type
Pose
. Its
Trans
value is displayed in a label in the format [x, y, z].
VB:
Me.Label1.Text = ATool.Tframe.Trans.ToString()
C#: this.label1.Text = aTool.Tframe.Trans.ToString();
IRapidData.FillFromString method
The
IRapidData
interface also has a
FillFromString
method, which fills the object with a valid RAPID string representation. The method can always be used when you need to modify RAPID data. Using the method with the
RapidDomain.Bool
variable used earlier in the chapter will look like this: rapidBool.FillFromString("True")
Using it for a
RapidDomain.Num
variable is similar: rapidNum.FillFromString("10")
String format
222
The format is constructed recursively. An example is the easiest way of illustrating this.
Example:
The
RapidDomain.Pose
structure represents the RAPID data type pose
, which describes how a coordinate system is displaced and rotated around another coordinate system.
public struct Pose : IRapidData
{ public Pos trans; public Orient rot;
}
This is an example in RAPID:
VAR pose frame1;
...
frame1.trans := [50, 0, 40]; frame1.rot := [1, 0, 0, 0];
The frame1 coordinate transformation is assigned a value that corresponds to a displacement in position where X=50 mm, Y=0 mm and Z=40 mm. There is no rotation.
The
RapidDomain.Pose
structure consists of two struct variables called trans and rot of the data types
Pos
and
Orient
.
Pos
has three floats and
Orient
consists of four doubles. The
FillFromString
format for a
Pose
object is “[[1.0, 0.0, 0.0, 0.0][10.0, 20.0, 30.0]]”.
The example shows how to write a new value to a RAPID pose
variable:
VB:
If TypeOf rd.Value Is Pose Then
Dim rapidPose As Pose = DirectCast(rd.Value, Pose) rapidPose.FillFromString("[[1.0, 0.0, 0.0, 0.0][10, 20, 30]]") rd.Value = rapidPose
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.1. Working with RAPID data
Continued
C#:
End If if (rd.Value is Pose)
{
Pose rapidPose = (Pose) rd.Value; rapidPose.FillFromString("[[1.0, 0.5, 0.0, 0.0][10, 15, 10]]"); rd.Value = rapidPose;
}
NOTE!
The string format must be carefully observed. If the string argument has the wrong format, a
RapidDataFormatException
is thrown.
Writing to RAPID data
Writing to RAPID data is only possible using the type cast
RapidData
value, to which the new value is assigned. To write the new value to the RAPID data in the controller you must then assign the .Net object to the
Value
property of the
RapidData
object. This example uses the rapidBool object created in
Creating an object representing the RAPID data value on page 220
.
VB:
’Assign new value to .Net variable rapidBool.Value = False
’Request mastership of Rapid before writing to the controller
Me.master = Mastership.Request(Me.AController.Rapid)
’Write the new value to the data in the controller rd.Value = rapidBool
’Release mastership as soon as possible
Me.master.Dispose
C#:
//Assign new value to .Net variable rapidBool.Value = false;
//Request mastership of Rapid before writing to the controller this.master = Mastership.Request(this.controller.Rapid); rd.Value = rapidBool;
//Release mastership as soon as possible this.master.Dispose();
3HAC028083-001 Revision: D
Continues on next page
223
7 Using the PC SDK
7.5.1. Working with RAPID data
Continued
for detailed information about on how the controller handles write
access and
Start program execution on page 208
for another code example of implementing
mastership in a PC SDK application.
This was an easy example, as the value to change was a simple bool
. Often, however, RAPID uses complex structures. By using the
FillFromString
method you can assign a new
Value
to any
RapidData
and write it to the controller.
The string must be formatted according to the principle described in the previous section. The following example shows how to write a new value to the pos
structure (x, y, z) of a RAPID tooldata:
VB:
Dim APos As Pos = New Pos
APos.FillFromString("[2,3,3]")
Me.ATool.Tframe.Trans = APos
Me.Rd.Value = Me.ATool
C#:
Pos aPos = new Pos(); aPos.FillFromString("[2,3,3]"); this.aTool.Tframe.Trans = aPos; this.rd.Value = this.aTool;
NOTE!
The new value is not written to the controller until the last statement is executed.
Letting the user know that RAPID data has changed
In order to be notified that RAPID data has changed you need to add a subscription to the
ValueChanged
event of the
RapidData
instance. Note, however, that this only works for
persistent RAPID data.
Add subscription
This is how you add a subscription to the
ValueChanged
event:
VB:
C#:
Addhandler Rd.ValueChanged, AddressOf Rd_ValueChanged this.rd.ValueChanged += rd_ValueChanged;
224
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.1. Working with RAPID data
Continued
Handle event
The implementation of the event handler may look like this. Remember that controller events use their own threads, and avoid Winforms threading problems by the use of
Control.Invoke
, which forces the execution from the background thread to the GUI thread.
VB:
Private Sub Rd_ValueChanged(ByVal sender As Object, ByVal e As
DataValueChangedEventArgs)
Me.Invoke(New EventHandler (AddressOf UpdateGUI), sender, e)
End Sub
C# private void rd_ValueChanged(object sender,
DataValueChangedEventArgs e)
{ this.Invoke(new EventHandler (UpdateGUI), sender, e);
}
Controller events and threads on page 67
to learn more about potential threading conflicts in RAB applications.
Read new value from controlller
Update the user interface with the new value. As the value is not part of the event argument, you must use the
RapidData Value
property to retrieve the new value:
VB:
Private Sub UpdateGUI(ByVal sender As Object, ByVal e As
System.EventArgs)
Dim Tool1 As ToolData = DirectCast(Me.Rd.Value, ToolData)
Me.Label1.Text = Tool1.Tframe.Trans.ToString()
End Sub
C# private void UpdateGUI(object sender, System.EventArgs e)
{
ToolData tool1= (ToolData)this.rd.Value; this.label1.Text = tool1.Tframe.Trans.ToString();
}
3HAC028083-001 Revision: D
Continues on next page
225
7 Using the PC SDK
7.5.1. Working with RAPID data
Continued
NOTE!
Subscriptions work only for RAPID data declared as PERS.
Implementing high priority data subscriptions
To speed up event notification from the controller it is possible to set up subscription priorities for persistent RAPID data. To do this you use the
Subscribe
method and the enumeration
EventPriority
as argument. The example shows an ordinary signal subscription and a subscription with high priority:
VB:
Addhandler Rd.ValueChanged, AddressOf Rd_ValueChanged
Rd.Subscribe(AddressOf Rd_Changed, EventPriority.High)
C#: rd.ValueChanged += rd_ValueChanged; rd.Subscribe(rd_Changed, EventPriority.High);
To deactivate subscriptions with high priority you call the
Unsubscribe
method like this:
VB:
C#:
Rd.Unsubscribe(AddressOf Rd_ValueChanged) rd.Unsubscribe(rd_Changed);
NOTE!
High priority subscriptions can be used for I/O signals and RAPID data declared PERS. The controller can handle 64 high priority subscriptions.
RapidData disposal
You are recommended to dispose of
RapidData
objects when they are no longer needed. See
Memory management in PC applications on page 213
VB:
If Not Rd Is Nothing Then
Rd.Dispose()
Rd = Nothing
End If
C#: if (rd != null)
{ rd.Dispose(); rd = null;
}
226 3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.2. Handling arrays
7.5.2. Handling arrays
Overview
In RAPID you can have up to three dimensional arrays. These are accessible by using a
RapidData
object like for any other RAPID data.
There are mainly two ways of accessing each individual element of an array: by indexers or by an enumerator.
ArrayData object
If the
RapidData references a RAPID array is
Value
property returns an object of
ArrayData
type. Before making a cast, check the type using the is
operator or by using the
IsArray
property on the
RapidData
object.
VB:
Dim RD As RapidData = AController.Rapid.GetRapidData("T_ROB1",
"User", "string_array")
If RD.IsArray Then
Dim AD As ArrayData = DirectCast( RD.Value,ArrayData)
.....
End If
C#:
RapidData rd = aController.Rapid.GetRapidData("T_ROB1", "User",
"string_array"); if (rd.IsArray)
{
ArrayData ad = (ArrayData)rd.Value;
.....
}
Array dimensions
The dimension of the array is returned by the Rank property. If you need to check the length of the individual arrays you can use the
GetLength
method on the
ArrayData
object passing the dimension index as argument.
VB:
Dim ARank As Integer = AD.Rank
Dim Len As Integer = AD.GetLength(ARank)
C#: int aRank = ad.Rank; int len = ad.GetLength(aRank);
3HAC028083-001 Revision: D
Continues on next page
227
7 Using the PC SDK
7.5.2. Handling arrays
Continued
Array item access by using indexers
By the use of indexers you can access each array element, even in three dimensional arrays.
A combination of the
GetLength
method and
For
loops makes it possible to access any item:
VB:
Dim ASum As Double = 0R
Dim ANum As Num
If AD.Rank = 1 Then
For I As Integer = 1 To AD.Length
ANum = DirectCast(ad.[I], Num)
ASum += DirectCast(ANum, Double)
Next
ElseIf AD.Rank = 2 Then
For I As Integer = 1 To AD.GetLength(1)
For J As Integer = 1 To AD.GetLength(2)
ANum = DirectCast(ad[I, J], Num)
ASum += DirectCast(ANum, Double)
Next
Next
Else
For I As Integer = 1 To AD.GetLength(1)
For J As Integer = 1 To AD.GetLength(2)
For K As Integer = 1 To AD.GetLength(3)
ANum = DirectCast(ad[I, J, K], Num)
ASum += DirectCast(ANum, Double)
Next
Next
Next
End If
228
C#: double sum = 0d;
Num aNum; if (ad.Rank == 1) { for (int i = 1; i <= ad.Length; i++) { aNum = (Num)ad.[i]; aSum += (double)ANum;
}
} elseif (ad.Rank == 2) { for(int i = 1; i< ad.GetLength(1); i++) { for (int j = 1; j <= ad.Length; j++) { aNum = (Num)ad.[i,j]; aSum += (double)ANum;
}
}
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.2. Handling arrays
Continued
} else { for(int i = 1; i< ad.GetLength(1); i++) { for(int j = 1; j< ad.GetLength(2); j++) { for (int k = 1; k <= ad.GetLength(3); k++) { aNum = (Num)ad.[i, j, k]; aSum += (double)ANum;
}
}
}
}
Array item access using enumerator
You can also use the enumerator operation ( foreach
) like it is used by collections in .NET.
Notice that it can be used for both one dimension and multi-dimensional arrays to access each individual element. The previous example is a lot simpler this way:
VB:
C#:
Dim ASum As Double = 0R
Dim ANum As Num
For Each ANum As Num In AD
ASum += DirectCast(ANum, Double)
Next double sum = 0d;
Num aNum; foreach(Num aNum in ad)
{ aSum += (double)ANum;
}
3HAC028083-001 Revision: D 229
7 Using the PC SDK
7.5.3. ReadItem and WriteItem methods
7.5.3. ReadItem and WriteItem methods
Overview
An alternative way of accessing RAPID data stored in an array are the
ReadItem
and
WriteItem
methods.
ReadItem method
Using the
ReadItem
method you can directly access a
RapidData
item in an array, e.g. an array with RobTargets or Nums. The index to the item is explicitly specified in the
ReadItem call. The first item is in position 1, i.e. the array is 1-based as in RAPID.
VB:
Dim ANum As Num aNum = DirectCast(rd.ReadItem(1, 2), Num)
C#:
Num aNum = (Num)rd.ReadItem(1, 2);
This example retrieves the second Num value in the first array of the RAPID data variable referenced by rd.
WriteItem method
In the same manner it is possible to use the
WriteItem
method to write to an individual
RAPID data item in an array. This example shows how to write the result of an individual robot operation into an array representing a total robot program with several operations:
VB:
Dim ANum As Num = New Num(OPERATION_OK) rd.WriteItem(ANum, 1, 2)
C#:
Num aNum = new Num(OPERATION_OK); rd.WriteItem(aNum, 1, 2);
NOTE!
If the index is out of bounds an
IndexOutOfRangeException
will be thrown.
230 3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.4. UserDefined data
7.5.4. UserDefined data
Overview
RECORD structures are common in RAPID code. To handle these unique data types a
UserDefined
class is available. This class has properties and methods to handle individual components of a RECORD.
In some cases implementing your own structure can improve application design and code maintenance.
Creating UserDefined object
The
UserDefined
constructor takes a
RapidDataType
object as argument. To retrieve a
RapidDataType
object you need to provide a
RapidSymbol
or the path to the declaration of the RAPID data type.
This example creates a
UserDefined
object representing the RAPID RECORD
processdata:
VB:
Dim rdt As RapidDataType rdt = Me.controller.Rapid.GetRapidDataType("T_ROB1", "MyModule",
"processdata")
Dim processdata As UserDefined = New UserDefined(rdt)
C#
RapidDataType rdt; rdt = this.controller.Rapid.GetRapidDataType("T_ROB1",
"MyModule", "processdata");
UserDefined processdata = new UserDefined(rdt);
Reading UserDefined data
UserDefined
can be used to read any kind of RECORD variable from the controller. The individual components of the RECORD are accessible using the
Components
property and an index. Each
Component
can be read as a string.
VB:
C#:
Dim processdata As UserDefined = DirectCast(rd.Value, UserDefined)
Dim No1 As String = processdata.Components(0).ToString()
Dim No2 AS String = processdata.Components(1),ToString()
UserDefined processdata = (UserDefined) rd.Value; string no1 = processdata.Components[0].ToString(); string no2 = processdata.Components[1].ToString();
Each individual string can then be used in a
FillFromString
method to convert the component into a specific data type, e.g.
RobTarget
or
ToolData
. See
IRapidData.FillFromString method on page 222
3HAC028083-001 Revision: D
Continues on next page
231
7 Using the PC SDK
7.5.4. UserDefined data
Continued
Writing to UserDefined data
If you want to modify
UserDefined
data and write it to the controller you must first read the
UserDefined
object and the apply new values using the
FillFromString
method. Then you need to perform a write operation using the
RapidData.Value
property.
VB: processdata.Components(0).FillFromString("[0,0,0]") processdata.Components(1).FillFromString("10") rd.Value = ud
C#: processdata.Components[0].FillFromString("[0,0,0]"); processdata.Components[1].FillFromString("10"); rd.Value = ud;
IRapidData.FillFromString method on page 222
Writing to RAPID data on page 223
for further information and code samples.
Recursively reading the structure of any RECORD data type
If you need to know the structure of a RECORD data type (built-in or user-defined) you must first retrieve the record components of the record. Then you need to iterate the record components and check if any of them are also records. This procedure must be repeated until all record components are atomic types.This code example shows how to get information about the robtarget data type. The robtarget URL is “RAPID/robtarget” or just “robtarget”.
private void SearchRobtarget()
{
RapidSymbol[ ] rsCol = tRob1.SearchRapidSymbol(sProp, "RAPID/ robtarget", "p10");
RapidDataType theDataType; if (rsCol.Length > 0)
{
Console.WriteLine("RapidSymbol name = " + rsCol[0].Name); theDataType = RapidDataType.GetDataType(rsCol[0]);
Console.WriteLine("DataType = " + theDataType.Name); if (theDataType.IsRecord)
{
RapidSymbol[] syms = theDataType.GetComponents();
SearchSymbolStructure(syms);
}
}
}
232
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.4. UserDefined data
Continued
private void SearchSymbolStructure(RapidSymbol[] rsCol)
{
RapidDataType theDataType; foreach (RapidSymbol rs in rsCol)
{
Console.WriteLine("RapidSymbol name = " + rs.Name); theDataType = RapidDataType.GetDataType(rs);
Console.WriteLine("DataType = " + theDataType.Name); if (theDataType.IsRecord)
{
RapidSymbol[] syms = theDataType.GetComponents();
SearchSymbolStructure(syms);
}
}
}
3HAC028083-001 Revision: D
Continues on next page
233
7 Using the PC SDK
7.5.4. UserDefined data
Continued
234
The code example above produces the following printout:
RapidSymbol name = p10
DataType = robtarget
RapidSymbol name = trans
DataType = pos
RapidSymbol name = x
DataType = num
RapidSymbol name = y
DataType = num
RapidSymbol name = z
DataType = num
RapidSymbol name = rot
DataType = orient
RapidSymbol name = q1
DataType = num
RapidSymbol name = q2
DataType = num
RapidSymbol name = q3
DataType = num
RapidSymbol name = q4
DataType = num
RapidSymbol name = robconf
DataType = confdata
RapidSymbol name = cf1
DataType = num
RapidSymbol name = cf4
DataType = num
RapidSymbol name = cf6
DataType = num
RapidSymbol name = cfx
DataType = num
RapidSymbol name = extax
DataType = extjoint
RapidSymbol name = eax_a
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.4. UserDefined data
Continued
DataType = num
RapidSymbol name = eax_b
DataType = num
RapidSymbol name = eax_c
DataType = num
RapidSymbol name = eax_d
DataType = num
RapidSymbol name = eax_e
DataType = num
RapidSymbol name = eax_f
DataType = num
Implement your own struct representing a RECORD
This example shows how you can create your own .NET data type representing a RECORD in the controller instead of using the
UsefDefined
type.
Creating ProcessData type
VB:
Dim rdt As RapidDataType = Me.ARapid.GetRapidDataType("T_ROB1",
"MyModule", "processdata")
Dim pc As ProcessData = New ProcessData(rdt) pc.FillFromString(rd.Value.ToString())
C#
RapidDataType rdt = this.aRapid.GetRapidDataType("T_ROB1",
"MyModule", "processdata");
ProcessData pc = new ProcessData(rdt); pc.FillFromString(rd.Value.ToString());
Implementing ProcessData struct
This example shows how the new data type
ProcessData
may be implemented. As you see, this is done by using a .NET struct and letting
ProcessData
wrap the
UserDefined
object.
The struct implementation should include a
FillFromString
and
ToString
method, i.e. inherit the
IRapidData
interface. Any properties and methods may also be implemented.
VB:
Public Structure ProcessData
Implements IRapidData
Private data As UserDefined
Public Sub New(ByVal rdt As RapidDataType) data = New UserDefined(rdt)
End Sub
Private Property IntData() As UserDefined
Get
Return data
3HAC028083-001 Revision: D
Continues on next page
235
7 Using the PC SDK
7.5.4. UserDefined data
Continued
End Get
Set(ByVal Value As UserDefined) data = Value
End Set
End Property
.....
End Structure
C#: public struct ProcessData: IRapidData
{ private UserDefined data; public ProcessData(RapidDataType rdt)
{ data = new UserDefined(rdt);
} private UserDefined IntData
{ get { return data; } set { data = value; }
} public int StepOne
{ get
{ int res =
Convert.ToInt32(IntData.Components[0].ToString())
; return res;
} set
{
IntData.Components[0] = new Num(value);
}
}
}
Implementing IRapidData methods
This piece of code shows how the two
IRapidData
methods
ToString
and
FillFromString
can be implemented.
VB:
Public Sub FillFromString(ByVal newValue As String) Implements
ABB.Robotics.Controllers.RapidDomain.IRapidData.FillFromStr
ing
IntData.FillFromString(newValue)
236
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.4. UserDefined data
Continued
End Sub
Public Overrides Function ToString() As String Implements
ABB.Robotics.Controllers.RapidDomain.IRapidData.ToString
Return IntData.ToString()
End Function
C#: public void FillFromString(string newValue)
{
IntData.FillFromString(newValue);
} public override string ToString()
{ return IntData.ToString();
}
NOTE! The
ToString
method has to use the
Overrides
keyword in Visual Basic and the override
keyword in C#.
Property implementation
Each item in the RECORD structure should have a corresponding property in the extended
.NET data type. The get and set methods have to implement the conversion from/to controller data type to .NET data type.
VB:
Public Property Step() As Integer
Get
Dim res As Integer =
Convert.ToInt32(IntData.Components(0).ToString())
Return res
End Get
Set(ByVal Value As Integer)
Dim tmp As Num = New Num tmp.FillFromNum(Value)
IntData.Components(0) = tmp
End Set
End Property
C#: public int Step
{ get
{ int res =
Convert.ToInt32(IntData.Components[0].ToString()); return res;
3HAC028083-001 Revision: D
Continues on next page
237
7 Using the PC SDK
7.5.4. UserDefined data
Continued
}
} set
{
Num tmp = new Num(); tmp.FillFromNum(value);
IntData.Components[0] = tmp;
}
238 3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.5. RAPID symbol search
7.5.5. RAPID symbol search
Overview
Most RAPID elements (variables, modules, tasks, records etc.) are members of a symbol table, in which their names are stored as part of a program tree structure.
It is possible to search this table and get a collection of
RapidSymbol
objects, each one including the RAPID object name, location and type.
Search method
The search must be configured carefully, due to the large amount of RAPID symbols in a system. To define a query you need to consider from where in the program tree the search should be performed, which symbols are of interest and what information you need for the symbols of interest.To enable search from different levels the
SearchRapidSymbol
method is a member of several different SDK classes, e.g.
Task
,
Module
and
Routine
. This example shows a search performed with
Task
as the starting point:
VB:
Dim RSCol As RapidSymbol()
RSCol = ATask.SearchRapidSymbol(SProp, "num", string.Empty)
C#:
RapidSymbol[] rsCol; rsCol = aTask.SearchRapidSymbol(sProp, "num", string.Empty);
The
SearchRapidSymbol
method has three arguments. The first argument, of data type
RapidSymbolSearchProperties
, is detailed in the next section. The second and third arguments are detailed in the following sections.
Search properties
The
RapidSymbolSearchProperties
type is rather complex and requires some knowledge about RAPID concepts.
It is used to specify search method, type of RAPID symbol to search for, whether the search should be recursive, whether the symbols are local and/or global and whether or not the search result should include only symbols currently used by a program. If a property is not valid for a particular symbol, it will be discarded and will not exclude the symbol from the search result.
The table describes the different properties of
RapidSymbolSearchProperties
.
Property Description
SearchMethod Specifies the direction of the search, which can be
Block
(down) or
Scope
(up). Example: If the starting point of the search is a routine, a block-search will return the symbols declared within the routine, whereas a scope-search will return the symbols accessible from the routine.
3HAC028083-001 Revision: D
Continues on next page
239
7 Using the PC SDK
7.5.5. RAPID symbol search
Continued
Property
Types
Recursive
GlobalSymbols
LocalSymbols
InUse
Description
Specifies which RAPID type(s) you want to search for. The
SymbolTypes
enumeration includes
Constant
,
Variable
,
Persistent
,
Function
,
Procedure
,
Trap
,
Module
,
Task
,
Routine
,
RapidData
. etc. (
Routine
includes
Function
,
Procedure
and
Trap. RapidData
includes
Constant
,
Variable
and
Persistent
.)
For both block and scope search it is possible to choose if the search should stop at the next scope or block level or recursively continue until the root (or leaf) of the symbol table tree is reached.
Specifies whether global symbols should be included.
Specifies whether local symbols should be included.
Specifies whether only symbols in use by the loaded RAPID program should be searched.
Default instance
RapidSymbolSearchProperties
has several static methods that return a default instance.
VB:
C#:
Dim SProp As RapidSymbolSearchProperties =
RapidSymbolSearchProperties.CreateDefault()
RapidSymbolSearchProperties sProp =
RapidSymbolSearchProperties.CreateDefault();
The default instance has the following values:.
Property Description
SearchMethod
Types
Recursive
GlobalSymbols
LocalSymbols
InUse
SymbolSearchMethod.Block
SymbolTypes.NoSymbol
True
True
True
True
Using this instance you can specify the search properties of the search you want to perform.
Example:
VB:
SProp.SearchMethod = SymbolSearchMethod.Scope
SProp.Types = SymbolTypes.Constant Or SymbolTypes.Persistent
SProp.Recursive = False
240
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.5. RAPID symbol search
Continued
C#: sProp.SearchMethod = SymbolSearchMethod.Scope; sProp.Types = SymbolTypes.Constant | SymbolTypes.Persistent
sProp.Recursive = false;
3HAC028083-001 Revision: D
Continues on next page
241
7 Using the PC SDK
7.5.5. RAPID symbol search
Continued
NOTE!
The default instance has the property
Types
set to
NoSymbol.
It must be specified in order for a meaningful search to be performed!
NOTE!
The
Types
property allows you to combine several types in a search. See the example above.
NOTE!
See PC SDK Reference for the static methods
CreateDefaultForData
and
CreateDefaultForRoutine
.
Data type argument
The second argument of the
SearchRapidSymbol
method is the RAPID data type written as a string. The data type should be written with small letters, e.g. “num”, “string” or
“robtarget”. It can also be specified as string.Empty
.
NOTE!
To search for a
UserDefined
data type the complete path to the module that holds the
RECORD definition must be passed, like this: result = tRob1.SearchRapidSymbol(sProp,"RAPID/T_ROB1/MyModule/
MyDataType", string.Empty);
However, if
MyModule
is configured as -Shared the system sees its data types as installed, and the task or module should not be included in the path result = tRob1.SearchRapidSymbol(sProp,"MyDataType", string.Empty);
Symbol name argument
The third argument is the name of the RAPID symbol. It can be specified as string.Empty
if the name of the symbol to retrieve is not known, or if the purpose is to search ALL “num” data in the system for example.
Instead of the name of the RAPID symbol a regular expression can be used. The search mechanism will then match the pattern of the regular expression with the symbols in the symbol table. The regular expression string is not case sensitive
A regular expression is a powerful mechanism. It may consist of ordinary characters and meta characters. A meta character is an operator used to represent one or several ordinary characters, and the purpose is to extend the search.
Within a regular expression, all alphanumeric characters match themselves, i.e. the pattern
“abc” will only match a symbol named “abc”. To match all symbol names containing the character sequence “abc”, it is necessary to add some meta characters. The regular expression for this is “.*abc.*”.
The available meta character set is shown below:
.
Expression Meaning
Any single character
242
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.5. RAPID symbol search
Continued
Expression
^
[s]
[^s] r* r+ r?
(r) r | r’
.*
Meaning
Any symbol starting with
Any single character in the non-empty set s, where s is a sequence of characters. Ranges may be specified as c-c.
Any single character not in the set s.
Zero or more occurrences of the regular expression r.
One or more occurrences of the regular expression r.
Zero or one occurrence of the regular expression r.
The regular expression r. Used for separate that regular expression from another.
The regular expressions r or r’.
Any character sequence (zero, one or several characters).
Example 1
"^c.*"
Returns all symbols starting with c or C.
Example 2
"^reg[1-3]"
Returns reg1, Reg1, REG1, reg2, Reg2, REG2, reg3, Reg3 and REG3.
Example 3
"^c.*|^reg[1,2]"
Returns all symbols starting with c or C as well as reg1, Reg1, REG1, reg2, Reg2 and REG2.
SearchRapidSymbol example
This example searches for VAR, PERS or CONST num data in a task and its modules. The search is limited to globally declared symbols. By default the search method is
Block
, so it does not have to be set.
VB:
Dim SProp As RapidSymbolSearchProperties =
RapidSymbolSearchProperties.CreateDefault()
SProp.Types = SymbolTypes.RapidData
SProp.LocalSymbols = False
Dim RSCol As RapidSymbol()
RSCol = ATask.SearchRapidSymbol(SProp, "num", string.Empty)
C#:
RapidSymbolSearchProperties sProp =
RapidSymbolSearchProperties.CreateDefault(); sProp.Types = SymbolTypes.RapidData; sProp.LocalSymbols = false;
RapidSymbol[] rsCol; rsCol = aTask.SearchRapidSymbol(sProp, "num", string.Empty);
3HAC028083-001 Revision: D
Continues on next page
243
7 Using the PC SDK
7.5.5. RAPID symbol search
Continued
Search for UserDefined RAPID data - example
In this example a user defined RECORD data type (“mydata”) is declared in a module
(“myModule”). Assuming that the end-user can declare and use data of this data type in any program module, the search method must be Block (default). A search for all “mydata” instances may look like this:
VB:
C#:
Dim SProp As RapidSymbolSearchProperties =
RapidSymbolSearchProperties.CreateDefault()
SProp.Types = SymbolTypes.RapidData
Dim RSCol As RapidSymbol()
RSCol = ATask.SearchRapidSymbol(SProp, "RAPID/T_ROB1/myModule/ mydata", string.Empty)
RapidSymbolSearchProperties sProp =
RapidSymbolSearchProperties.CreateDefault(); sProp.Types = SymbolTypes.RapidData;
RapidSymbol[] rsCol; rsCol = aTask.SearchRapidSymbol(sProp, "RAPID/T_ROB1/myModule/ mydata", string.Empty);
NOTE!
If myModule is configured as -Shared and all myData instances are declared in myModule the search method must be set to
Scope
and the
SearchRapidSymbol
call should look like this: rsCol = aTask.SearchRapidSymbol(sProp, "mydata", string.Empty);
244 3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.6. Working with RAPID modules and programs
7.5.6. Working with RAPID modules and programs
Overview
Using the
Task
object it is possible to load and save individual modules and programs. You can also unload programs, as well as reset the program pointer and start program execution.
NOTE!
All these operations require mastership of the RAPID domain. See
for details.
Load modules and programs
To load a module or program file you need the path to the file on the controller. When the file is loaded into memory the
RapidLoadMode
enumeration argument,
Add
or
Replace,specifies whether or not it should replace old modules or programs.
If the file extension is not a valid module (mod or sys) or program (pgf) extension an
ArgumentException
is thrown.
VB:
Try
ATask.LoadProgramFromFile(APrgFileName, RapidLoadMode.Replace)
ATask.LoadModuleFromFile(AModFileName, RapidLoadMode.Add)
Catch ex As ArgumentException
Return
End Try
C#: try
{ aTask.LoadProgramFromFile(aPrgFileName, RapidLoadMode.Replace); aTask.LoadModuleFromFile(aModFileName, RapidLoadMode.Add);
} catch (ArgumentException ex)
{ return;
}
3HAC028083-001 Revision: D
Continues on next page
245
7 Using the PC SDK
7.5.6. Working with RAPID modules and programs
Continued
NOTE!
All program files must reside in the file system of the controller and not locally on the PC. In order to load a program from the PC you must first download it to the controller by using the
FileSystem.PutFile
method. See
for details.
NOTE!
If the User Authorization System of the controller is used by the PC SDK application, it is required that the logged on user has the UAS grant UAS_RAPID_LOADPROGRAM to load and unload RAPID programs. See the PC SDK Reference for further information about which grants are necessary for a specific PC SDK method.
Save programs and modules
You can save programs using the
Task.SaveProgramToFile
method and a single module by using the
Module.SaveToFile
method.
To unload a program after it has been saved to file you call
DeleteProgram()
.
VB:
Dim TaskCol As Task() = AController.Rapid.GetTasks()
Dim AnObject As Object
For Each AnObject in TaskCol
ATask = DirectCast(AnObject, Task)
ATask.ProgramName = ATask.Name
ATask.SaveProgramToFile(SaveDir)
ATask.DeleteProgram()
Next
C#:
Task[] taskCol = aController.Rapid.GetTasks(); foreach (Task aTask in taskCol)
{ aTask.ProgramName = aTask.Name; aTask.SaveProgramToFile(saveDir); aTask.DeleteProgram();
}
In this example a module is saved to file:
VB:
AModule.SaveToFile(AFilePath)
C# aModule.SaveToFile(aFilePath);
ResetProgramPointer method
Using
ResetProgramPointer
you can set the program pointer to the main entry point of the task.
VB:
ATask.ResetProgramPointer()
246
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.6. Working with RAPID modules and programs
Continued
C#: aTask.ResetProgramPointer();
Start program
Starting program execution in the robot controller can only be done in automatic operating mode. There are several overloaded
Start
methods to use, the simplest way to start RAPID execution of a controller task is:
VB:
ATask.Start()
C#: aTask.Start();
NOTE!
If your application uses the User Authorization System of the controller (see
Authorization System on page 70
) you should also check that the current user has the grant
UAS_RAPID_EXECUTE before calling the
Start
method.
Execution change event
It is possible to subscribe to events that occur when a RAPID program starts and stops. It is done like this:
VB:
AddHandler AController.Rapid.ExecutionStatusChanged, AddressOf
UpdateUI
C# aController.Rapid.ExecutionStatusChanged += UpdateUI;
Avoiding threading conflicts on page 259
Letting the user know that RAPID data has changed on page 224
for information about how to write the event handler that is needed to update the GUI due to a controller event.
3HAC028083-001 Revision: D 247
7 Using the PC SDK
7.5.7. Enable operator response to RAPID UI-instructions from a PC
7.5.7. Enable operator response to RAPID UI-instructions from a PC
Remote operator dialog
RAB 5.12 supports operator dialogs to be launched on a PC instead of the FlexPendant when
RAPID UI- and TP-instructions are executed. In this chapter this new feature is referred to as
Remote operator dialog. It enables an operator to give the feedback required by the RAPID program from a PC instead of using the FlexPendant.
NOTE!
Remote operator dialog can only be used with RobotWare 5.12 and later.
Supported RAPID instructions
The following RAPID instructions are supported:
•
UIAlphaEntry
• UIListView
•
UIMessageBox
• UIMsgBox
•
UINumEntry
• UINumTune
•
TPErase
• TPReadFK
•
TPReadNum
• TPWrite
UIInstructionType
The PC SDK
UIInstructionType
enumeration defines the different RAPID instructions listed above. For a description of each instruction type, see PC SDK Reference. Below is an example of such a description.
Example
UIInstructionType.UIAlphaEntry
:
Member Description
UIAlphaEntry The UIAlphaEntry (User Interaction Alpha Entry) is used to let an operator communicate with the robot system via RAPID, by enabling him to enter a string from the FlexPendant or from a
PC SDK application. After the operator has entered the text, it is transferred back to the RAPID program by calling UIAlphaEntryEventArgs.SendAnswer.
248
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.7. Enable operator response to RAPID UI-instructions from a PC
Continued
TIP!
For complete information about the usage in RAPID refer to RAPID Technical reference
manual (easily accessed from within RobotStudio for example).
Increased flexibility
Making use of the Remote operator dialog feature, the end-user of the robot system can choose whether to use the FlexPendant or the PC SDK application to answer a RAPID UI- or
TP-instruction.
The FlexPendant will always show the operator dialog the usual way. If the operator responds from the PC the message on the FlexPendant will disappear.
NOTE!
Likewise, the dialog of the PC SDK application should disappear if the operator chooses to respond from the FlexPendant. This is handled by the PC SDK programmer.
Basic approach
The basic procedure for implementing Remote operator dialog in a PC SDK application is shown below. The same approach is used internally by the FlexPendant when it launches its operator view.
Step Action
1
2
3
4
Set up a subscription to
UIInstructionEvent
.
In the event handler check the
UIInstructionEventType
from the event arguments. If
Post
or
Send
create an operator dialog by using the information provided by the event arguments.
To transfer the response of the end-user to the RAPID program call the
SendAnswer
method of the specialized
UIInstructionEventArgs
object.
Remove any existing operator dialog if you get a
UIInstructionEvent of
UIInstructionEventType.Abort
.
3HAC028083-001 Revision: D
Continues on next page
249
7 Using the PC SDK
7.5.7. Enable operator response to RAPID UI-instructions from a PC
Continued
NOTE!
Remember that controller events are always received on a background thread and that you need to enforce execution to the GUI thread by the use of
Invoke
before launching the operator dialog. See
Controller events and threads on page 67
UIInstructionEvent
To be notified when a UI-instruction event has occurred in the controller, you need to set up a subscription to
UIInstructionEvent
. To do that you use the
UIInstruction
property of the
Rapid
class, like this:
Controller c = new Controller(); c.Rapid.UIInstruction.UIInstructionEvent += OnUIInstructionEvent;
TIP!
For a code example including an event handler see UIInstructionEvent in the PC SDK
Reference.
UIInstruction event arguments
To create the dialog in accordance with the arguments of the RAPID instruction and to transfer the response of the operator back to the executing RAPID program, you use the information of the event arguments.
UIInstructionEventArgs
The
UIInstructionEventArgs object holds information about which RAPID task and which UI- or TP-instruction triggered the event. The picture below shows all
UIInstructionEventArgs
members.
250
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.7. Enable operator response to RAPID UI-instructions from a PC
Continued
7.5.7_1
UIInstructionEventArgs
is a base class of several specialized classes, one for each UI- and TP- instruction. The specialized class holds the additional information needed to create the operator dialog, so type casting the
UIInstructionEventArgs object to the correct specialized type is necessary. To do that you first check the
InstructionType
property, which you can see in the picture above.
3HAC028083-001 Revision: D
Continues on next page
251
7 Using the PC SDK
7.5.7. Enable operator response to RAPID UI-instructions from a PC
Continued
UIListViewEventArgs
As an example of a specialized type, the members of the
UIListViewEventArgs
class are shown below. The
Buttons
and
ListItems
properties are of course crucial for creating the operator dialog.
7.5.7_2
UIInstructionEventType
An important property in the picture above is
UIInstructionEventType
. It is inherited from the base class and comes with all UI- and TP- instruction events.
The table shows the members of the
UIInstructionEventType
enumeration.
Member Description
Undefined Undefined. Should not occur.
Post Post event type, e.g. TPWrite, TPErase. When the event is of this type RAPID expects no response from the operator.
252
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.5.7. Enable operator response to RAPID UI-instructions from a PC
Continued
Member
Send
Abort
Description
Send event type, e.g. TPReadNum, UIListView. When the event is of this type the running RAPID program expects feedback from the operator before execution continuous.
When the controller gets a response from a client (the FlexPendant or a PC
SDK application) it sends an event of
Abort
type. This tells all subscribing clients that the UI-Instruction has been aborted, closed or confirmed by the operator. When you get an event of this type you should remove any open operator dialog.
NOTE!
If the robot system has several RAPID tasks it is of course necessary to keep track of which operator dialog belongs to which task etc.
A RAPID task can only handle ONE pending
Send
, and it is not guaranteed that an
Abort event will always follow a
Send
event. Therefore, if you receive a new
Send
event from the same task without a preceding
Abort event, you should remove the existing dialog and display the new one.
SendAnswer method
To transfer the response of the end-user back to the RAPID program you call the
SendAnswer
method. See the picture of the
UIListViewEventArgs
class above.
SendAnswer
is called with different arguments depending on the RAPID instruction.
For example, if it is a
UIAlphaEntry
instruction you just send the string that the operator has entered as argument. But if it is a
UIListView
instruction the
SendAnswer
method will look like this: public void SendAnswer(int listItemIdx, UIButtonResult btnRes);
NOTE!
There is no mastership handling involved in using Remote operator dialog.
3HAC028083-001 Revision: D 253
7 Using the PC SDK
7.6. IO system domain
7.6. IO system domain
Overview
A robot system uses input and output signals to control processes. Signals can be of digital, analog or group signal type. Such IO signals are accessible using the SDK.
Signal changes in the robot system are often significant, and there are many scenarios where end-users of the system need notification of signal changes.
To speed up event notification from the controller there is new functionality in PC SDK 5.10, which allows you to set up subscription priorities. This possibility applies to I/O signals and
persistent RAPID data. This mechanism is further described in
Implementing high priority event subscription on page 258
Accessing signals
Accessing signals is done through the
Controller
object and its property
IOSystem
, which represents the IO signal space in the robot controller.
To access a signal you need the system name of the signal. The object that is returned from the
IOSystem
.
GetSignal
method is of type
Signal
.
VB:
Dim Signal1 As Signal = AController.IOSystem.GetSignal("signal name")
C#:
Signal signal1 = aController.IOSystem.GetSignal("signal name");
The returned
Signal
object has to be typecast to digital, analog or group signal. This example shows a how a signal of type
DigitalSignal
is created:
VB:
Dim DISig As DigitalSignal = DirectCast(Signal1, DigitalSignal)
C#:
DigitalSignal diSig = (DigitalSignal) signal1;
This example shows a how an
AnalogSignal
is created:
VB:
Dim AISig As AnalogSignal = DirectCast(Signal1, AnalogSignal)
C#:
AnalogSignal aiSig = (AnalogSignal) signal1;
This example shows a how a
GroupSignal
is created:
VB:
Dim GISig As GroupSignal = DirectCast(Signal1, GroupSignal)
C#:
GroupSignal giSig = (GroupSignal) signal1;
254
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.6. IO system domain
Continued
NOTE!
Remember to call the
Dispose
method of the signal when it should no longer be used.
Getting signals using SignalFilter
Instead of just getting one signal at a time you can get a signal collection using a signal filter.
Some of the
SignalFilter
flags are mutually exclusive, e.g.
SignalFilter.Analog
and
SignalFilter.Digital
. Others are inclusive, e.g.
SignalFilter.Digital
and
SignalFilter.Input
. You can combine the filter flags using the “|” character in C# and the
Or
operator in VB:
VB:
C#:
Dim ASigFilter As SignalFilter = SignalFilter.Digital Or
SignalFilter.Input
Dim Signals As SignalCollection =
AController.IOSystem.GetSignals(ASigFilter)
SignalFilter aSigFilter = SignalFilter.Digital |
SignalFilter.Input;
SignalCollection signals = aController.IOSystem.GetSignals(aSigFilter);
This piece of code iterates the signal collection and adds all signals to a
ListView
control.
The list has three columns displaying signal name, type and value:
VB:
For Each ASignal As Signal In Signals
Item = New ListViewItem(ASignal.Name)
Item.SubItems.Add(ASignal.Type.ToString())
Item.SubItems.Add(ASignal.Value.ToString())
Me.ListView1.Items.Add(Item)
Next
C#: foreach(Signal signal in signals)
{ item = new ListViewItem(signal.Name); item.SubItems.Add(signal.Type.ToString()); item.SubItems.Add(signal.Value.ToString()); this.listView1.Items.Add(item);
}
If the signal objects are no longer needed they should be disposed of:
VB:
For Each ASignal As Signal In Signals
ASignal.Dispose()
Next
3HAC028083-001 Revision: D
Continues on next page
255
7 Using the PC SDK
7.6. IO system domain
Continued
C#: foreach(Signal signal in signals)
{ signal.Dispose();
}
Reading IO signal values
These examples show how to read a digital and an analog signal.
Digital signal
This piece of code reads the digital signal DO1 and checks a checkbox if the signal value is
1 (ON):
VB:
Dim Sig As Signal = AController.IOSystem.GetSignal("DO1")
Dim DigitalSig As DigitalSignal = DirectCast(Sig, DigitalSignal)
Dim val As Integer = DigitalSig.Get
If val = 1 Then
Me.CheckBox1.Checked = True
EndIf
C#:
Signal sig = aController.IOSystem.GetSignal("DO1");
DigitalSignal digitalSig = (DigitalSignal)sig; int val = digitalSig.Get(); if (val == 1)
{ this.checkBox1.Checked = true;
}
Analog signal
This piece of code reads the value of the analog signal AO1 and displays it in a textbox:
VB:
Dim Sig As Signal = AController.IOSystem.GetSignal("AO1")
Dim AnalogSig As AnalogSignal = DirectCast(Sig, AnalogSignal)
Dim AnalogSigVal As Single = AnalogSig.Value
Me.TextBox1.Text = AnalogSigVal.ToString()
C#:
Signal sig = aController.IOSystem.GetSignal("AO1");
AnalogSignal analogSig = (AnalogSignal)sig; float analogSigVal = analogSig.Value; this.textBox1.Text = analogSigVal.ToString();
256
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.6. IO system domain
Continued
Writing IO signal values
This section shows how the value of a digital or an analog IO signal can be modified by a
RAB application.
NOTE!
In manual mode a signal value can be modified only if the Access Level of the signal is ALL.
If not, the controller has to be in auto mode.
Digital signal
This piece of code changes the value of a digital signal in the controller when the user checks/ unchecks a checkbox:
VB:
Private Sub CheckBox1_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles CheckBox1.Click
If Me.CheckBox1.Checked Then
DigitalSig.Set()
Else
DigitalSig.Reset()
End If
End Sub
C#: private void checkBox1_Click(object sender, EventArgs e)
{ if (this.checkBox1.Checked)
{ digitalSig.Set();
} else
{ digitalSig.Reset();
}
}
NOTE! You can also set the value using the
Value
property.
Analog signal
This piece of code writes the value entered in a text box to the analog signal AO1. The value is converted from string to a float before it is written to the controller:
VB:
Dim AnalogSigVal As Single = Convert.ToSingle(Me.TextBox1.Text)
AnalogSig.Value = AnalogSigVal
3HAC028083-001 Revision: D
Continues on next page
257
7 Using the PC SDK
7.6. IO system domain
Continued
C#: float analogSigVal = Convert.ToSingle(this.textBox1.Text); analogSig.Value = analogSigVal;
Listening to signal changes
Once a
Signal
object is available it is possible to add a subscription to its Changed event, which is triggered at a signal change such as changed value, changed simulated status or changed signal quality.
Visual Basic
Friend WithEvents Sig As AnalogSignal
...
AddHandler Sig.Changed, AddressOf AISig_Changed
...
Private Sub Sig_Changed(sender As Object, e As
SignalChangedEventArgs) Handles Sig.Changed
End Sub
C# this.sig.Changed += sig_Changed;
...
private void sig_Changed(object sender, SignalChangedEventArgs e)
{ }
Start and stop subscriptions
It is recommended that you activate and deactivate subscriptions to the
Changed
event if these are not necessary throughout the lifetime of the application:
VB:
AddHandler Sig.Changed, AddressOf Sig_Changed
RemoveHandler Sig.Changed, AddressOf Sig_Changed
C#: this.sig.Changed += sig_Changed; this.sig.Changed -= sig_Changed;
Implementing high priority event subscription
To speed up event notification from the controller it is possible to set up subscription priorities for I/O signals. To do this you use the
Subscribe
method and the enumeration
EventPriority
as argument. The example shows an ordinary signal subscription and a subscription with high priority:
VB:
AddHandler Sig.Changed, AddressOf Sig_Changed
Sig.Subscribe(AddressOf Sig_Changed, EventPriority.High)
258
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.6. IO system domain
Continued
C#: signal.Changed += sig_Changed; signal.Subscribe(sig_Changed, EventPriority.High);
To deactivate subscriptions with high priority you call the
Unsubscribe
method like this:
VB:
C#: sig.Unsubscribe(AddressOf sig_Changed) signal.Unsubscribe(sig_Changed);
Limitations for high priority events
High priority subscriptions can be used for I/O signals and RAPID data declared PERS. The controller can handle 64 high priority subscriptions.
Avoiding threading conflicts
It is important to keep in mind that all controller events use their own threads, which are different from the application GUI thread. This can cause problems if you want to display signal changes in the application GUI. See
Controller events and threads on page 67
further information.
If an update of the user interface is not necessary, you do not need to take any special action, but can execute the event handler on the event thread. If, however, you need to show to the user that the signal has changed you should use the
Invoke
method. It forces execution to the window control thread and thus provides a solution to potential threading conflicts.
VB:
Me.Invoke(New EventHandler(AddressOf UpdateUI), New Object()
{sender, e})
C#: this.Invoke(new EventHandler<SignalChangedEventArgs>(UpdateUI), new Object[] { sender, e });
Reading the new value
The
SignalChangedEventArgs
object has a
NewSignalState
property, which has information about signal value, signal quality and whether the signal is simulated or not:
VB:
Private Sub UpdateUI(ByVal Sender As Object, ByVal e As
SignalChangedEventArgs)
Dim State As SignalState = e.NewSignalState
Dim val As Single
Val = State.Value
Me.TextBox1.Text = Val.ToString()
....
End Sub
3HAC028083-001 Revision: D
Continues on next page
259
7 Using the PC SDK
7.6. IO system domain
Continued
C#: private void UpdateUI(object sender, SignalChangeEventArgs e)
{
SignalState state = e.NewSignalState;
....
float val = state.Value
this.textBox1.Text = val.ToString()
}
NOTE!
There is no guarantee you will receive an initial event when setting up the subscription. To get initial information about the value of a signal you should read it using the
Value
property.
NOTE!
Make sure the subscription is removed before you dispose of the signal. See
Memory management in PC applications on page 213
for further information.
260 3HAC028083-001 Revision: D
7 Using the PC SDK
7.7. Event log domain
7.7. Event log domain
Overview
Event log messages may contain information about controller status, RAPID execution, the running processes of the controller etc.
Using the SDK it is possible to either read messages in the queue or to use an event handler that will receive a copy of each new log message. An event log message contains queue type, event type, event time, event title and message.
Accessing the controller event log
You access the event log domain through the
Controller
property
EventLog
.
VB:
Private Log As EventLog = AController.EventLog
C#: private EventLog log = aController.EventLog;
Accessing event log categories
All event log messages are organized into categories. To search for an individual message you have to know what category it belongs to. The enumeration type,
CategoryType
, defines all available categories. You can get a category either by using the method
GetCategory
or by using the
Categories
property, which is an array of all available categories.
VB:
Dim Cat As EventLogCategory
Cat = Log.GetCategory(CategoryType.Program) or
C#:
Cat = Log.Categories(4)
EventLogCategory cat; cat = log.GetCategory(CategoryType.Program); or cat = log.GetCategory[4];
NOTE!
The
EventLogCategory
should be disposed of when it is no longer used.
Accessing event log messages
To access a message you use the
Messages
property of the
Category
object. A collection of messages is returned. The collection implements the
ICollection
and
IEnumerable interfaces , which means you can use the common operations for collections. Access is done either using an index or by iterating using foreach
.
VB:
Dim Msg As EventLogMessage = Cat.Messages(1)
3HAC028083-001 Revision: D
Continues on next page
261
7 Using the PC SDK
7.7. Event log domain
Continued
or
Dim Msg As EventLogMessage
For Each Msg In Cat.Messages
Me.TextBox1.Text = Msg.Title
.....
Next Item
C#:
EventLogMessage msg = cat.Messages[1]; or foreach(EventLogMessage msg in cat.Messages)
{ this.textBox1.Text = msg.Title;
.....
}
MessageWritten event
It is possible to add an event handler that is notified when a new messages is written to the controller event log. This is done by subscribing to the EventLog event
MessageWritten
.
The event argument is of type
MessageWrittenEventArgs
and has a
Message
property, which holds the latest event log message.
VB:
Private Sub Log_MessageWritten(sender As Object, e As
MessageWrittenEventArgs) Handles Log.MessageWritten
Dim Msg As EventLogMessage = e.Message
End Sub
C#: private void log_MessageWritten(object sender,
MessageWrittenEventArgs e)
{
EventLogMessage msg = e.Message;
}
NOTE!
If the application user interface needs to be updated as a result of the event, you must delegate this job to the GUI thread using the
Invoke
method. See
further information and code samples.
TIP!
Find out more about the
EventLogDomain
in the PC SDK Reference help.
262 3HAC028083-001 Revision: D
7 Using the PC SDK
7.8. Motion domain
7.8. Motion domain
Overview
The
MotionDomain
namespace lets you access the mechanical units of the robot system.
Motion system
You access the motion system by using the
Controller
property
MotionSystem
.
VB:
Private AMotionSystem As MotionSystem
AMotionSystem = AController.MotionSystem
C# private MotionSystem aMotionSystem; aMotionSystem = aController.MotionSystem;
By using the
MotionSystem
object you can, for example, use its
SpeedRatio
property to find out about the current speed of the robot.
Accessing Mechanical units
The mechanical units can be of different types, e.g. a robot with a TCP, a multiple axes manipulator or a single axis unit. All these are available through the MotionSystem property
MechanicalUnits
. If only the currently active mechanical unit is of interest you had better use the
ActiveMechanicalUnit
property.
VB:
Dim AMechCol As MechanicalUnitCollection =
AController.MotionSystem.MechanicalUnits
Dim AMechUnit As MechanicalUnit =
AController.MotionSystem.ActiveMechanicalUnit;
C#:
MechanicalUnitCollection aMechCol = aController.MotionSystem.MechanicalUnits;
MechanicalUnit aMechUnit = aController.MotionSystem.ActiveMechanicalUnit;
Mechanical unit properties and methods
There are numerous properties available for the mechanical unit, e.g.
Name,Model,
NumberOfAxes,SerialNumber,CoordinateSystem
,
MotionMode
,
IsCalibrated
,
Tool
and
WorkObject
etc. It is also possible to get the current position of a mechanical unit as a
RobTarget
or
JointTarget
.
VB:
Dim ARobTarget As RobTarget =
AController.MotionSystem.GetActiveMechanicalUnit.GetPositio
n(CoordinateSystemType.World)
Dim AJointTarget As JointTarget =
AController.MotionSystem.ActiveMechanicalUnit.GetPosition()
3HAC028083-001 Revision: D
Continues on next page
263
7 Using the PC SDK
7.8. Motion domain
Continued
C#:
RobTarget aRobTarget = aController.MotionSystem.GetActiveMechanicalUnit.GetPositio
n(CoordinateSystemType.World);
JointTarget aJointTarget = aController.MotionSystem.ActiveMechanicalUnit.GetPosition()
;
TIP!
Find out more about the
MotionDomain
in the PC SDK Reference help.
264 3HAC028083-001 Revision: D
7 Using the PC SDK
7.9. File system domain
7.9. File system domain
Overview
Using the SDK it is possible to create, save, load, rename and delete files in the controller file system. It is also possible to create and delete directories.
Accessing files and directories
You access the file system domain through the
Controller
property
FileSystem
.
VB:
Private AFileSystem As FileSystem = AController.FileSystem
C#:
FileSystem aFileSystem = aController.FileSystem;
Controller and PC directory
You can get and set the directory on the controller and on the local PC system using the
RemoteDirectory
and
LocalDirectory
properties.
VB:
C#:
Dim RemoteDir As String = AController.FileSystem.RemoteDirectory
Dim LocalDir As String = AController.FileSystem.LocalDirectory
string remoteDir = aController.FileSystem.RemoteDirectory; string localDir = aController.FileSystem.LocalDirectory;
Environment variables
When specifying file system paths you can use environment variables to denote the HOME, system, backup and temp directories of the currently used system. When an application uses
“(BACKUP)$” it is internally interpreted as the path to the backup directory of the current system. The other environment variables are: HOME, TEMP and SYSTEM.
Loading files
You can load a file from the controller to the PC using the
GetFile
method. The method generates an exception if the operation did not work. The arguments are complete paths including filenames.
VB:
AController.FileSystem.FileSystem.GetFile(RemoteFilePath,
LocalFilePath)
C#: aController.FileSystem.GetFile(remoteFilePath, localFilePath);
Saving files
You can save a file on the controller file system by using the
PutFile
method. The method generates an exception if the operation did not work. The arguments are complete paths including filenames.
VB:
AController.FileSystem.PutFile(LocalFilePath, RemoteFilePath)
3HAC028083-001 Revision: D
Continues on next page
265
7 Using the PC SDK
7.9. File system domain
Continued
C#: aController.FileSystem.PutFile(localFilePath, remoteFilePath);
CopyFile and CopyDirectory
The
PutFile
/
GetFile
methods generate a copy of a file and transfer it to or from the controller file system. Using the
CopyFile
and
CopyDirectory
you can create a copy directly on the controller:
VB:
AController.FileSystem.CopyFile(FromFilePath, ToFilePath)
AController.FileSystem.CopyDirectory(FromDirPath, ToDirPath)
C#: aController.FileSystem.CopyFile(fromFilePath, toFilePath); aController.FileSystem.CopyDirectory(fromDirPath, toDirPath);
Getting multiple files and directories
The
FileSystem
class has a method called
GetFilesAndDirectories
. It can be used to retrieve an array of
ControllerFileSystemInfo
objects with information about individual files and directories. The
ControllerFileSystemInfo
object can then be cast to either a
ControllerFileInfo
object or a
ControllerDirectoryInfo
object.
This example uses search pattern to limit the search.
VB:
Dim AnArray As ControllerFileSystemInfo()
Dim info As ControllerFileSystemInfo
AnArray = AController.FileSystem.GetFilesAndDirectories("search pattern")
Dim I As Integer
For I = 0 To array.Length -1 info = AnArray(I)
......
Next
C#:
ControllerFileSystemInfo[] anArray;
ControllerFileSystemInfo info; anArray = aController.FileSystem.GetFilesAndDirectories("search pattern"); for (int i=0;i<anArray.Length;i++) { info = anArray[i];
......
}
266
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.9. File system domain
Continued
Using search patterns
As seen in the example above, you can use search patterns to locate files and directories using the
GetFilesAndDirectories
method. The matching process follows the Wildcard pattern matching in Visual Studio. This is a brief summary:
Character in pattern
?
*
#
[charlist]
[!charlist]
Matches in string
Any single character
Zero or more characters
Any single digit (0–9)
Any single character in charlist
Any single character not in charlist
TIP!
Find out more about the
FileSystemDomain
in the PC SDK Reference help.
3HAC028083-001 Revision: D 267
7 Using the PC SDK
7.10. Messaging domain
7.10. Messaging domain
Overview
The
Messaging
domain of the PC SDK can be used to send and receive data between a PC
SDK application and a RAPID task.
The corresponding RAPID functionality, RAPID Message Queue, includes RAPID data types and RAPID instructions and functions for sending and receiving data. It enables communication between RAPID tasks or between a RAPID task and a RAB application.
This chapter provides information about how to implement messaging in a PC SDK application. To make it work it is necessary to do part of the implementation in RAPID. In order to show how this can be done a simple but complete code example in C# and RAPID is provided at the end of the chapter.
NOTE!
See Application manual - Robot communication and I/O Control for detailed information about how to implement messaging in RAPID.
RobotWare option
The functionality in RAPID that is needed to utilize messaging - RAPID Message Queue - is included in the RobotWare options PC Interface, FlexPendant Interface and Multitasking. As
PC Interface is required on a robot controller to be used with a PC SDK client, this means no extra option is needed to start using RAPID Message Queue with a PC SDK application.
Messaging illustration
The illustration shows possible senders and receivers in the robot system. The arrows represent ways to communicate by posting a message to a queue.
268 en0700000430
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.10. Messaging domain
Continued
NOTE!
In principle, messages might as well be sent between a PC SDK client and a RAB application running on the FlexPendant.
NOTE!
The messaging functionality of the FlexPendant SDK has not yet been made public, but in
RAB 5.11 a mechanism has been implemented, which allows advanced users access to it. You should contact support if you need information about how to use it.
Benefits
Together with RAPID Message Queue the functionality of the
Messaging
domain represent a new, flexible way for a RAB application to interact with a RAPID task.
Messaging is usually done when a RAPID task is executing, but it is also possible to send a message to a RAPID task when it has been stopped. The RAPID interrupt will then occur once the RAPID task has been started.
An simple example of usage would be to set a flag from a RAB application in order to control the program flow in the RAPID program.
NOTE!
Sending messages can be done in both manual and auto mode. As opposed to using
RapidData
to modify a RAPID variable no mastership is required.
The Messaging namespace
The Microsoft Windows operating system provides mechanisms for facilitating communications and data sharing between applications. Collectively, activities enabled by these mechanisms are called Interprocess communications (IPC).
These are the classes and enumerations available in the
Messaging
namespace:
3HAC028083-001 Revision: D
Continues on next page
269
7 Using the PC SDK
7.10. Messaging domain
Continued
7.9_1
270
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.10. Messaging domain
Continued
The
Ipc
class is used to handle message queues with methods like
GetQueue
,
CreateQueue
,
DeleteQueue
etc. When you have an
IpcQueue
object you can use its
Send method to send an
IpcMessage
to a RAPID task or its
Receive
method to receive a message from a RAPID task.
When sending a message you use an existing queue in the controller as the
IpcQueue
object.
The naming principle of queues in the controller is using the name of the corresponding task prefixed with “RMQ_”, e.g “RMQ_T_ROB1”. To be able to receive a message from RAPID you must first create your own message queue and use that object with the
Receive
method.
NOTE!
When the execution context in a RAPID task is lost, e.g. when the program pointer is moved to main, the corresponding queue is emptied.
Basic approach
To utilize messaging in a PC SDK application you need to do the implementation both in
RAPID and in the PC application.
This is the general approach for sending data from a PC application and receiving it in a
RAPID task:
1. In the PC application connect to the queue of the RAPID task.
2. Create the message.
3. Send the message.
4. In the RAPID program set up a trap routine that reads the message. Connect an interrupt so that the trap routine is called each time a new message appears.
For a complete code example using this scenario see
3HAC028083-001 Revision: D
Continues on next page
271
7 Using the PC SDK
7.10. Messaging domain
Continued
What can be sent in a message?
In RAPID there is a rmqmessage data type
. In the PC SDK the corresponding type is
IpcMessage
. An
IpcMessage
object stores the actual data in the message, but also information about message size, who the sender is etc.
The data in a message is a pretty-printed string with data type name (and array dimensions) followed by the actual data value. The data type can be any RAPID data type. Arrays and user defined records are allowed.
Message data - examples:
“robtarget;[[930,0,1455],[1,0,0,0],[0,0,0,0],[9E9,9E9,9E9,9E9,9E9,9E9]]”
“string;“Hello world!””
“num;23”
“bool;FALSE”
“bool{2, 2};[[TRUE,TRUE],[FALSE,FALSE]]”
“msgrec;[100,200]” (user defined data type)
The method
IpcMessage.SetData
is used to fill the
IpcMessage
with the appropriate data. Likewise, the
GetData
method retrieves the data from an
IpcMessage
object.
NOTE!
The
IpcMessage.Data
is set and retrieved as a byte array,
SetData(byte[] data) and byte[] GetData()
. This means you must convert the message data string to a byte array before calling the
SetData
method. It may look like this in C#:
Byte[] data = new UTF8Encoding().GetBytes("string;\"Hello world\"");
for a few other examples.
NOTE!
The RAPID program can specify what RAPID data type it expects to receive by connecting it to a TRAP routine. A message containing data of a data type that no interrupt is connected to will be discarded with only an event log warning.
RAPID Message Queue system parameters
This is a brief description of each system parameter of RAPID Message Queue. For further information, see the respective parameter in Technical reference manual - System parameters.
These parameters belong to the Task type in the Controller topic:.
Parameter Description
RmqType The following values are possible:
• None - Disables the RAPID Message Queue functionality in this
RAPID task. This is the default value.
• Internal - Enables the RAPID Message Queue for local usage on the controller.
• Remote - Enables the RAPID Message Queue for local usage and for PC and FlexPendant applications.
272
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.10. Messaging domain
Continued
Parameter Description
RmqMode • Interrupt mode - A message can be received either by connecting a trap routine to a specified message type or by using the send-wait functionality. Any messages that are not the answer to an active send-wait instruction or have the type connected to a trap routine will be discarded. This is the default mode.
• Synchronous mode - All messages will be queued and can only be received through the new read-wait instruction
RMQReadWait
. No messages will be discarded unless the queue is full. The send-wait instruction is not available in this mode. New mode from 5.12.
RmqMaxMsgSize The maximum data size, in bytes, for a message. The default value is
350. The value cannot be changed in RobotStudio or on the FlexPendant.
RmqMaxNoOfMsg Maximum number of messages in queue. The default value is 5. The value cannot be changed in RobotStudio or on the FlexPendant.
NOTE!
To read the values of these system parameter from the PC SDK you use the
IpcQueue properties
RemoteAccessible, MessageSizeLimit
and
Capacity.
Remote RmqType
The system parameter RmqType must be set to Remote to enable messaging between RAPID and RAB:
7.9_2
3HAC028083-001 Revision: D
Continues on next page
273
7 Using the PC SDK
7.10. Messaging domain
Continued
Code example
This simple messaging example can be tested with a virtual or a real controller. The system parameter RmqType must be set to Remote as shown in
RAPID Message Queue system parameters on page 272
The following code sample creates a message and sends it to a RAPID task, which reads it and sets a RAPID variable accordingly. Then an “Acknowledged” message is sent back to the
PC SDK queue. Finally, the PC SDK application launches the received message in a Message
Box.
PC SDK - C#
A message is created and sent to the RAPID queue “RMQ_T_ROB1”. An answer message is then received from RAPID and launched in a Message Box.
C#:
//declarations private Controller c; private IpcQueue tRob1Queue; private IpcQueue myQueue; private IpcMessage sendMessage; private IpcMessage recMessage;
...
//initiation code, eg in constructor c = new Controller(); //default ctrl used here (App.config)
//get T_ROB1 queue to be able to send msgs to RAPID task tRob1Queue = c.Ipc.GetQueue("RMQ_T_ROB1");
//create my own RAB queue to be able to receive msgs if (!c.Ipc.Exists("RAB_Q"))
{ myQueue = c.Ipc.CreateQueue("RAB_Q", 5, Ipc.IPC_MAXMSGSIZE); myQueue = c.Ipc.GetQueue("RAB_Q");
274
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.10. Messaging domain
Continued
}
//Create IpcMessage objects for sending and receiving sendMessage = new IpcMessage(); recMessage = new IpcMessage();
...
//in an event handler, eg. button_Click
SendMessage(true);
CheckReturnMsg();
...
public void SendMessage(bool boolMsg)
{
Byte[] data = null;
//Create message data if (boolMsg)
{ data = new UTF8Encoding().GetBytes("bool;TRUE");
} else
{ data = new UTF8Encoding().GetBytes("bool;FALSE");
}
//Place data and sender information in message sendMessage.SetData(data); sendMessage.Sender = myQueue.QueueId;
}
//Send message to the RAPID queue tRob1Queue.Send(sendMessage);
3HAC028083-001 Revision: D
Continues on next page
275
7 Using the PC SDK
7.10. Messaging domain
Continued
RAPID private void CheckReturnMsg()
{
IpcReturnType ret = IpcReturnType.Timeout; string answer = string.Empty; int timeout = 5000;
//Check for msg in the RAB queue ret = myQueue.Receive(timeout, recMessage); if (ret == IpcReturnType.OK)
{
//convert msg data to string answer = new UTF8Encoding().GetString(recMessage.Data);
MessageBox.Show(answer);
}
//MessageBox should show: string;"Acknowledged"
} else
{
MessageBox.Show("Timeout!");
}
A trap is created for a message of data type bool
. In the trap the value of the message data is assigned to the flag variable. Then an “Acknowledged” message is sent back to the PC SDK client. In main the WHILE loop is executed until a message with a TRUE value is received.
MODULE RAB_COMMUNICATION
VAR bool flag := FALSE;
VAR intnum connectnum;
PROC main()
CONNECT connectnum WITH RABMsgs;
IRMQMessage flag, connectnum;
WHILE flag = FALSE DO
!do something, eg. normal processing...
WaitTime 3;
ENDWHILE
!PC SDK message received - do something...
TPWrite "Message from PC SDK, will now...";
IDelete connectnum;
EXIT;
276
Continues on next page
3HAC028083-001 Revision: D
7 Using the PC SDK
7.10. Messaging domain
Continued
ENDPROC
TRAP RABMsgs
VAR rmqmessage msg;
VAR rmqheader header;
VAR rmqslot rabclient;
VAR num userdef;
VAR string ack := "Acknowledged";
RMQGetMessage msg;
RMQGetMsgHeader msg \Header:= header\SenderId:=rabclient\UserDef:=userdef;
!check data type and assign value to flag variable
IF header.datatype = "bool" THEN
RMQGetMsgData msg, flag;
!return receipt to sender
RMQSendMessage rabclient, ack;
ELSE
TPWrite "Unknown data received in RABMsgs...";
ENDIF
ENDTRAP
ENDMODULE
NOTE!
Error handling should be implemented in C#, as well as in RAPID.
NOTE!
From RW 5.12 there is a new RAPID instruction,
RMQEmptyQueue
that can be used to empty the queue in a task.
3HAC028083-001 Revision: D 277
7 Using the PC SDK
7.10. Messaging domain
278 3HAC028083-001 Revision: D
Download
Advertisement
Key features
Develop custom operator interfaces
FlexPendant SDK
PC SDK
Visual Studio integration
.NET programming
Virtual IRC5
Frequently asked questions
Robot Application Builder (RAB) is a software tool, which enables programmers to develop customized operator interfaces for the IRC5 robot controller.
The supported operating systems are Microsoft Windows XP + SP2 or Windows Vista + SP1.
The supported versions are Visual Studio 2005 and Visual Studio 2008.
The supported programming languages are C# and Visual Basic.NET for FlexPendant applications. For PC applications, any of the .NET languages should work, however, ABB support is only offered for Visual Basic and C#.