Hi all,
I have an array of RECORD like below. How can I access it with struct in PC-SDK?
RECORD rec
num myNum;
pos myPos;
ENDRECORD
PERS rec myArray{2}:=[ [ 2, [ 1, 2, 3 ] ], [ 3,[ 4, 5, 6 ] ] ];
Thanks for the help.
Hi all,
I have an array of RECORD like below. How can I access it with struct in PC-SDK?
RECORD rec
num myNum;
pos myPos;
ENDRECORD
PERS rec myArray{2}:=[ [ 2, [ 1, 2, 3 ] ], [ 3,[ 4, 5, 6 ] ] ];
Thanks for the help.
Hi,
Hereby a sample program. If you have any questions about it, just let me know :smile:
using System;
using ABB.Robotics.Controllers;
using ABB.Robotics.Controllers.Discovery;
using ABB.Robotics.Controllers.RapidDomain;
using System.Linq;
using System.Windows.Media.Media3D;
namespace PCSDKTest2
{
class Program
{
public struct Rec
{
public double myNum { get; set; }
public Vector3D myPos { get; set; }
}
private static Pos VectorToPos(Vector3D v)
{
return new Pos() { X = (float)v.X, Y = (float)v.Y, Z = (float)v.Z };
}
private static Vector3D PosToVector(Pos p)
{
return new Vector3D(p.X, p.Y, p.Z);
}
private static RapidData[] LoadData(Controller c, Task t, string rapidType)
{
// variables
RapidSymbolSearchProperties searchProps;
RapidSymbol[] rapidSymbols;
RapidData[] rapidDatas = null;
// check arguments
if (c != null && t != null && !string.IsNullOrEmpty(rapidType))
{
// define search properties
searchProps = RapidSymbolSearchProperties.CreateDefaultForData();
searchProps.Recursive = true;
searchProps.Types = SymbolTypes.Persistent;
// search for results
rapidSymbols = t.SearchRapidSymbol(searchProps);
// convert results to rapid-data
rapidDatas = rapidSymbols.Select(rs => new RapidData(c, rs)).Where(rs => rs.RapidType == rapidType).ToArray();
}
// return
return rapidDatas;
}
private static Rec[] ConvertToRec(RapidData rapid)
{
// variables
Num num;
Pos pos;
ArrayData value;
UserDefined element;
Rec[] rec;
// check arguments
if (rapid?.Value != null && rapid.IsArray)
{
// convert to ArrayData
value = (ArrayData)rapid.Value;
// define resulting array
rec = new Rec[value.Length];
for (int i = 0; i<value.Length; i++)
{
// get the struct-data
element = (UserDefined)rapid.ReadItem(i + value.BaseIndex);
// get the pos and num
num = (Num)element.Components[0];
pos = (Pos)element.Components[1];
// create Rec
rec[i] = new Rec()
{
myNum = num.Value,
myPos = PosToVector(pos)
};
}
// return
return rec;
}
else
{
throw new ArgumentException("The RapidData should be defined as ArrayData");
}
}
private static void Save(Controller c, RapidData rapid, Rec[] rec)
{
// variables
ArrayData value;
UserDefined element;
if (c != null && rapid?.Value != null && rapid.IsArray)
{
try
{
// request mastership, needed to write values
using (Mastership ms = Mastership.Request(c.Rapid))
{
// convert to ArrayData
value = (ArrayData)rapid.Value;
// write items
for (int i = 0; i < value.Length; i++)
{
// get the struct-data
element = (UserDefined)rapid.ReadItem(i + value.BaseIndex);
// update
element.Components[0] = new Num(rec[i].myNum);
element.Components[1] = VectorToPos(rec[i].myPos);
// save
rapid.WriteItem(element, i + value.BaseIndex);
}
}
}
catch(Exception ex) { }
}
}
static void Main(string[] args)
{
// variables
NetworkScanner ns;
Controller c;
Task t;
Rec[] rec;
RapidData[] rapidDatas;
try
{
// scan network
ns = new NetworkScanner();
ns.Scan();
// get first found controller
if (ns.Controllers.Count > 0)
{
// create the controller
c = new Controller(ns.Controllers[0]);
if (c != null)
{
// log on
c.Logon(UserInfo.DefaultUser);
t = c.Rapid.GetTask("T_ROB1");
if (t != null)
{
// load data
rapidDatas = LoadData(c, t, "rec");
if (rapidDatas.Length > 0)
{
// conver to Rec
rec = ConvertToRec(rapidDatas[0]);
if (rec.Length > 0)
{
// increment values
rec[0].myNum += 1;
rec[0].myPos += new Vector3D(2, 3, 4);
}
// save
Save(c, rapidDatas[0], rec);
}
}
//log off
c.Logoff();
// dispose controller
c.Dispose();
}
}
}
catch (Exception e) { }
}
}
}
Thanks, John_Verheij!! I will give this a go and let you know how it goes.
Thank you very much for this John_Verheij. Works like magic!
I also took it further by making the structure implement IRapidData like below. This allows the variable to have more or less the same function as the other RapidDomain structures.
In this sample, rec RECORD is defined in RS as follows:
RECORD rec
num num1;
robtarget tgt;
ENDRECORD
public struct Rec : IRapidData
{
// Structure fields
private Num num;
private RobTarget tgt;
private RapidData refRapidData;
// Structure properties
public Num NumVal
{
get { return num; }
set { num = value; }
}
public RobTarget TgtVal
{
get { return tgt; }
set { tgt = value; }
}
public static Rec Empty
{
get;
}
public Rec(RapidData input)
{
UserDefined ud = (UserDefined)input.Value;
// Initialise struct fields from the RapidData:
// ~ refRapidData takes the REFERENCE of the RapidData. This is useful in SaveToRapidData() method.
// ~ num & tgt takes the VALUE of the RapidData components. This is useful in making internal temporary
// changes before saving it (back) to the RapidData by SaveToRapidData() method.
this.num = (Num)ud.Components[0];
this.tgt = (RobTarget)ud.Components[1];
refRapidData = input;
}
public override string ToString()
{
return "[" + NumVal + "," + TgtVal + "]";
}
public void SaveToRapidData()
{
// c is the controller defined globally. Required to request mastership.
using (Mastership ms = Mastership.Request(c.Rapid))
{
refRapidData.StringValue = this.ToString();
}
}
public void Fill(string value)
{
char[] delimiterChars = { ' ', ',', '[', ']' }; // Get rid of these chars from the value input
string[] tokens = value.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries);
// Assign struct's fields: NumVal
NumVal = new Num(Convert.ToDouble(tokens[0]));
// Assign struct's fields: TgtVal
RobTarget newTgt = new RobTarget();
newTgt.Trans.X = Convert.ToSingle(tokens[1]);
newTgt.Trans.Y = Convert.ToSingle(tokens[2]);
newTgt.Trans.Z = Convert.ToSingle(tokens[3]);
newTgt.Rot.Q1 = Convert.ToSingle(tokens[4]);
newTgt.Rot.Q2 = Convert.ToSingle(tokens[5]);
newTgt.Rot.Q3 = Convert.ToSingle(tokens[6]);
newTgt.Rot.Q4 = Convert.ToSingle(tokens[7]);
newTgt.Robconf.Cf1 = Convert.ToInt32(tokens[7]);
newTgt.Robconf.Cf4 = Convert.ToInt32(tokens[8]);
newTgt.Robconf.Cf6 = Convert.ToInt32(tokens[9]);
newTgt.Robconf.Cfx = Convert.ToInt32(tokens[10]);
newTgt.Extax.Eax_a = Convert.ToSingle(tokens[11]);
newTgt.Extax.Eax_b = Convert.ToSingle(tokens[12]);
newTgt.Extax.Eax_c = Convert.ToSingle(tokens[13]);
newTgt.Extax.Eax_d = Convert.ToSingle(tokens[14]);
newTgt.Extax.Eax_e = Convert.ToSingle(tokens[15]);
newTgt.Extax.Eax_f = Convert.ToSingle(tokens[16]);
TgtVal = newTgt;
}
public void Fill(DataNode root)
{
throw new NotImplementedException();
}
public void FillFromString(string newValue)
{
Fill(newValue);
}
public DataNode ToStructure()
{
throw new NotImplementedException();
}
}