RobotStudio event

Parsing Bad Target Data

Hello,

I am receiving arbitrary robtarget data from a PC via sockets. I am testing for if the user sent a "bad character" in the target data.
Example: (X, Y, Z) or (100, 200, string) or (100, 200, 300BadCharacter)
I am also receiving Quaternions, Axis Configurations, and Velocity data the same method. So far, whenever the robot encounters a bad character in the data, it just makes the bad character a 0 and any other data numbers after that a 0 as well, even if they are numeric (except in the translation data, where RAPID crashes if a bad character is input into the (X,Y,Z)).

My question is, is there a way to parse the bad character out and/or not make the numbers after that a 0? Or is there a way to notify the user that a bad character has been entered? Here is a snippet of how I am receiving said data:
FUNC robtarget ParseTargetData(VAR rawbytes targetData)
        ! Parse a string of bytes into a robot target
        ! Inputs:
        !   -targetData: byte string
        ! Returns:
        !   -position: robtarget
        VAR robtarget target;
        !Read a position (x,y,z).     
        UnpackRawBytes targetData\Network,2,target.trans.x\Float4;
        UnpackRawBytes targetData\Network,6,target.trans.y\Float4;
        UnpackRawBytes targetData\Network,10,target.trans.z\Float4;
        !Read tool orientation (quaternion angles).
        UnpackRawBytes targetData\Network,14,target.rot.q1\Float4;
        UnpackRawBytes targetData\Network,18,target.rot.q2\Float4;
        UnpackRawBytes targetData\Network,22,target.rot.q3\Float4;
        UnpackRawBytes targetData\Network,26,target.rot.q4\Float4;
        !Read axes configuration (axis1,axis4,axis6,axisX)
        UnpackRawBytes targetData\Network,30,target.robconf.cf1\Float4;
        UnpackRawBytes targetData\Network,34,target.robconf.cf4\Float4;
        UnpackRawBytes targetData\Network,38,target.robconf.cf6\Float4;
        UnpackRawBytes targetData\Network,42,target.robconf.cfX\Float4;
        RETURN target;
ENDFUNC

 
Thanks in advance for any help!
SM



Comments

  • The most easiest solution is to notify the user that the value is not correct. 

    You can do something like this:

    Var string tmpNum;<br>Var bool correctChar;<br><br>UnpackRawBytes targetData\Network,2,tmpNum\ASCII:=4;<br>correctChar := StrToVal(tmpNum,&nbsp;target.trans.x);<br>IF NOT correctChar ...

    If you want to filter out any 'bad character', then you have to create a loop (FOR/WHILE) and test if every character of the string is a digit.


  • SteveMob
    SteveMob
    edited September 2016
    John,

    Thanks for the reply. By doing the method you showed above for checking if the character is correct, I guess I would need to check that for each item I am unpacking? In my case, 11 times?

    How can I test if the character of the string is a digit/number or not?

    Thanks for the help,
    SM
    Post edited by SteveMob on
  • StrToVal will return true if conversion was ok otherwise false
    Per Svensson
    Robotics and Vision Specialist
    Consat Engineering
  • Yes, by using the StrToVal function you need to perform the check for every unpacked item.

    Another way is to first unpack the whole RobTarget to string and then iterate over the string.

    <div>&nbsp; &nbsp; tmpNum1 := "a1b2";<br></div><div>&nbsp; &nbsp; tmpNum2 := "";<br></div><div>&nbsp; &nbsp;&nbsp;<br></div><div>&nbsp; &nbsp; FOR i FROM 1 TO STRLEN(tmpNum1) DO&nbsp;<br></div><div>&nbsp; &nbsp; &nbsp; IF Not StrMemb(tmpNum1, i, STR_DIGIT) THEN<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; tmpNum2 := tmpNum2 + StrPart(tmpNum1, i, 1);<br></div><div>&nbsp; &nbsp; &nbsp; ENDIF<br></div><div>&nbsp; &nbsp; ENDFOR</div>
    After running this code, tmpNum2 will have the value "ab"


  • SteveMob
    SteveMob
    edited September 2016
    John,

    Thanks for the reply, I will use it the way you suggested. But I first I have to get the whole byte string into a single string.
    I am trying to unpack the whole thing and put it into a string. The problem is, I am sending the data via sockets and TCP/IP from LabVIEW, so when it converts it to string, it is just a bunch of weird numbers and characters?

    Thanks for all the help!
    SM


    Post edited by SteveMob on
  • Is the best way to unpack the entire robtarget just unpack the individual elements and then combine them into a single string? Because the target data have a bunch of decimals and I think the string would be over the limit for bytes for a string (80)?

    Would it be better to just unpack all the elements separately, and combine them for the 3 data types (position, quaternions, and config data)? And then parse out the bad characters via John's method?

    Thanks,
    SM
  • In your first post you use around 44 bytes, based on this number parsing them directly to a string is possible. But if you have to parse more data, then it can be a solution to parse the elements separately. 

    I do not have much experience with sending data through sockets in LabView, but normally the transmitted and received string should be the same. You could check if LabView also uses ASCII based encoding (and not Base64 for example). 

    Maybe you can show the (transmitted) robtarget and which characters you get after parsing?
  • John,

    Right now I am creating 3 different strings (pos data, quat data, config data) using the method in this post:
    https://forums.robotstudio.com/discussion/9700/receive-robtarget-from-string

    Once I get that done I will try to parse out the bad data using your method. Will it work this way?

    Thanks
    SM

  • SteveMob
    SteveMob
    edited September 2016
    So I am having trouble converting to and from strings and robtargets... I can't first unpack the robtarget (with bad characters) and then convert to string, because when I unpack the robtarget with bad characters, the bad character and any other characters after that are 0's. So I need to unpack the target data straight into a string before placing into robtarget data, but I am not sure how to do that?

    I don't know what the length of the incoming strings will be, so using the: target.trans.x\ASCII:=some number, won't really work, because it only unpacks the characters within that number. Is there a way to check and see what the length of the incoming string is before I unpack it? Or another method to unpack all the data within that translation portion?

    Summing all that up, is there a way to unpack rawbytes (that are sent in robtarget format) straight into a string, without knowing what the string length will be?


    Thanks for any help!
    SM
  • All,

    Since the subject has changed from what the initial question was, I posted it to a new thread:
    https://forums.robotstudio.com/discussion/9952/unpacking-rawbytes-to-string#latest

    Thanks for all the help!
    SM


  • SteveMob
    SteveMob
    edited September 2016
    Now that I was able to unpack the entire message into a single string, I can begin parsing the bad characters out of the data. The problem is, using the method John posted above, it parses out my decimals and my negative signs as well. I still need those. Is there another method to check for a bad character?

    Also, this is what the incoming string looks like:"[0~100~0]~[0.96593~-0.25882~0~0]~[1~0~0~0]~[150~50]". I am having to use "~" (tilde) because I am bringing in the target data in LV from a comma delimited file. So what I need to do, is to check the data in between the "~" and brackets (well first, ensure that there are even brackets or tilde's), and make sure they are numeric values and/or negative signs and decimal places.

    Thanks,
    SM

  • You can check for every character you want right? 
    <br><div>&nbsp; &nbsp; FOR i FROM 1 TO STRLEN(tmpNum1) DO&nbsp;<br></div><div>&nbsp; &nbsp; &nbsp; IF StrMemb(tmpNum1, i, STR_DIGIT) THEN<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ! -> &nbsp;digit<br></div><div>&nbsp; &nbsp; &nbsp; ELSEIF StrMemb(tmpNum1, i, ".,-") THEN<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ! -> &nbsp;, or . or -<br></div><div>&nbsp; &nbsp; &nbsp; ELSEIF StrMemb(tmpNum1, i, "~[]") THEN<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ! -> &nbsp;~, or [ or ]<br></div><div>&nbsp; &nbsp; &nbsp; ELSE<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<br></div><div>&nbsp; &nbsp; &nbsp; ENDIF<br></div><div>&nbsp; &nbsp; ENDFOR</div>

  • SteveMob
    SteveMob
    edited September 2016
    John,

    Thanks for the reply. I didn't know you could specify certain characters to keep like that.

    If it is a STR_DIGIT or one of the specified characters, what do I do under IF statements? Like how can I parse out the non specified characters, then concatenate them to be a whole robtarget string?

    Thanks,
    SM
  • Something like this?

    <div>&nbsp; FUNC bool ParseRobtarget(string sValue,INOUT robtarget pResult)<br></div><div><br></div><div>&nbsp; &nbsp; VAR string sParts{17};<br></div><div>&nbsp; &nbsp; VAR num nParts{17};<br></div><div>&nbsp; &nbsp; VAR num nCounter:=1;<br></div><div>&nbsp; &nbsp; VAR num nCounterPrev:=0;<br></div><div>&nbsp; &nbsp; VAR bool bResult:=True;<br></div><div><br></div><div>&nbsp; &nbsp; ! loop all characters<br></div><div>&nbsp; &nbsp; FOR i FROM 1 TO StrLen(sValue) DO<br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; ! check if it is valid value or a value-seperator<br></div><div>&nbsp; &nbsp; &nbsp; IF StrMemb(sValue,i,"-0123456789.") THEN<br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ! save valid character&nbsp;<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; sParts{nCounter}:=sParts{nCounter}+StrPart(sValue,i,1);<br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ! update counter<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; nCounterPrev:=nCounter;<br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; ELSEIF StrMemb(sValue,i,"~[]") THEN<br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ! when there was no previous increment<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; IF (nCounter=nCounterPrev) THEN<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! convert to num<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bResult:=StrToVal(sParts{nCounter},nParts{nCounter}) AND bResult;<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ! increment counter<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Incr nCounter;<br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ENDIF<br></div><div>&nbsp; &nbsp; &nbsp; ENDIF<br></div><div>&nbsp; &nbsp; ENDFOR<br></div><div><br></div><div>&nbsp; &nbsp; ! parse robtarget<br></div><div>&nbsp; &nbsp; IF (bResult) AND nCounter = 18 THEN<br></div><div>&nbsp; &nbsp; &nbsp; pResult.trans:=[nParts{1},nParts{2},nParts{3}];<br></div><div>&nbsp; &nbsp; &nbsp; PREsult.rot:=[nParts{4},nParts{5},nParts{6},nParts{7}];<br></div><div>&nbsp; &nbsp; &nbsp; PResult.robconf:=[nParts{8},nParts{9},nParts{10},nParts{11}];<br></div><div>&nbsp; &nbsp; &nbsp; pResult.extax:=[nParts{12},nParts{13},nParts{14},nParts{15},nParts{16},nParts{17}];<br></div><div>&nbsp; &nbsp; ENDIF<br></div><div>&nbsp; &nbsp; RETURN bResult;<br></div><div><br></div><div>&nbsp; ENDFUNC</div>