Working with RAPID data
Overview
The Rapid Domain
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 for referring to the 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 a new functionality in PC SDK, 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.
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 do not know the path, you need to search for the RAPID data by using the SearchRapidSymbol
functionality.
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 following example shows how to create a RapidData
object that refers to the instance “reg1” in the USER module.
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.
rd = aController.Rapid.GetTask("T_ROB1").GetModule("user")
.GetRapidData("reg1");
Accessing data declared in a shared module
If your application is to be used with a MultiMove system (one controller and several motion tasks/robots), it may happen that the RAPID instance you need to access is declared in a RAPID module. Such a module can be used by all tasks, T_ROB1, T_ROB2 and so on.
The following example shows how to create a RapidData
object that refers to the instance “reg100”, which is declared in a
shared module.
Task tRob1 = aController.Rapid.GetTask("T_ROB1");
if (tRob1 != null)
{
RapidData rData = tRob1.GetRapidData("user", "reg1");
}
Note
From RobotWare 5.12 onwards, even if the data is declared in a Shared module it 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 it). To do that you need to create another object, which represents the 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, for example Num, Bool
or Tooldata
.
To access the value of a RAPID data of the RAPID data type bool
.
//declare a variable of data type RapidDomain.Bool
ABB.Robotics.Controllers.RapidDomain.Bool rapidBool;
ABB.Robotics.Controllers.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 want only to read this variable you can use the following technique instead of creating a RapidDomain.Bool
object:
bool b = Convert.ToBoolean(rd.Value.ToString());
The .NET type ToolData
(representing the RAPID data type tooldata
can be created like this:
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 bValue = rapidBool.ToString();
The string is formatted according to the principle described in IRapidData.FillFromString
method.
The following is an example of a complex data type. The ToolDataTframe
property is of type Pose
.
Its Trans
value is displayed in a label in the format [x, y, z].
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 variable is similar:
rapidNum.FillFromString("10")
String format
The format is constructed recursively. The following example illustrate it.
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;
}
The following 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=50mm, Y=0mm, and Z=40mm. 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:
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 a wrong format, a RapidDataFormatException
is thrown.
Writing to RAPID data
Writing to RAPID data is possible only by 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 assign the .NET object to the Value
property of the
RapidData
object.
The following example uses the rapidBool object created in Creating an object representing the RAPID data value.
//Assign new value to .Net variable
rapidBool.Value = false;
//Request mastership of Rapid before writing to the controller
this.master = Mastership.Request(this.aController.Rapid);
//Change: controller is repaced by aController
rd.Value = rapidBool;
//Release mastership as soon as possible
this.master.Dispose();
For more information on how the controller handles write access, see Mastership and for another code example of implementing mastership in a PC SDK application, see Start program execution.
The preceding example is simple, 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 RapidData.FillFromString
section. T
he following example shows how to write a new value to the pos
structure (x, y, z) of a RAPID tooldata:
Pos aPos = new Pos();
aPos.FillFromString("[2,3,3]");
aTool.Tframe.Trans = aPos;
using (Mastership.Request(aController.Rapid))
{
rd.Value = 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. However, that this only works for persistent RAPID data.
Add subscription
This is how you add a subscription to the ValueChanged
event:
rd.ValueChanged += new EventHandler<DataValueChangedEventArgs>(rd_ValueChanged);
Handle event
The following example shows the implementation of the event handler.
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.
Private Sub rd_ValueChanged(ByVal sender As Object, ByVal e As DataValueChangedEventArgs)
Me.Invoke(New EventHandler(UpdateGUI), sender, e)
End Sub
To learn more about potential threading conflicts in PC SDK applications, see Controller events and threads.
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 RapidDataValue
property to retrieve the new value:
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
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 can use the Subscribe
method and the enumeration EventPriority
as argument. The following example shows an
ordinary signal subscription and a subscription with high priority:
rd.Subscribe(rd_ValueChanged, EventPriority.High);
.
.
.
rd.Unsubscribe(rd_ValueChanged)
To deactivate subscriptions with high priority you can call the Unsubscribe
method as described in the following example:
rd.Unsubscribe(rd_ValueChanged)
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 the RapidData
objects when they are no longer needed. For more information,
see Memory management in PC applications.
if (rd != null)
{
rd.Dispose();
rd = null;
}