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.
The following example creates a UserDefined object representing the RAPID RECORD processdata:
RapidDataType rdt;
rdt = this.aController.Rapid.GetRapidDataType("T_ROB1", "user", "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.
UserDefined processdata = new UserDefined(rdt);
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,
for example RobTarget or ToolData. For more information,
see IRapidData.FillFromString method.
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.
processdata.Components[0].FillFromString("[0,0,0]");
processdata.Components[1].FillFromString("10");
rd.Value = processdata;
For more information and code samples, see IRapidData.FillFromString method and Writing to RAPID data.
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.The following code example shows how to get information about the robtarget
data type. The robtarget URL is “RAPID/robtarget” or just “robtarget”.
private void SearchRobtarget()
{
RapidSymbolSearchProperties sProp = RapidSymbolSearchProperties.CreateDefault();
sProp.Recursive = true;
sProp.Types = SymbolTypes.Constant | SymbolTypes.Persistent;
sProp.SearchMethod = SymbolSearchMethod.Block;
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);
}
}
}
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);
}
}
}
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
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
The following example shows how you can create your own .NET data type representing a RECORD in the controller instead of
using the UserDefined type.
RapidDataType rdt = ctr.Rapid.GetRapidDataType("T_ROB1", "MyModule", "processdata");
ProcessData pc = new ProcessData(rdt);
pc.FillFromString(rd.Value.ToString());
Implementing ProcessData struct
The following example shows how the new data type ProcessData may be implemented. 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, that is, inherit the IRapidData interface.
Any properties and methods may also be implemented.
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.
public void FillFromString(string newValue)
{
IntData.FillFromString(newValue);
}
public override string ToString()
{
return IntData.ToString();
}
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.
Note
If FillFromNum() does not work, use FillFromString for records ud.FillFromString("[\"10\",50,60,\"apa\"]"); does not work.
public int Step
{
get
{
int res = Convert.ToInt32(IntData.Components[0].ToString());
return res;
}
set
{
Num tmp = new Num();
tmp.FillFromNum(value);
IntData.Components[0] = tmp;
}
}