Random value needed

Is there a way to get a random value in RAPID?

I need it to introduce some "noise" in the control of a motor...

Something like a float ranging from 0 to 1 with a flat distribution.

Regards

Comments

  • Hello,
    No, there is no function to generate a random number in RAPID, so you have to implement it yourself. Here is a suggestion, which seems to work reasonably well:

     

    LOCAL VAR num nSeed:=320;
    LOCAL VAR num nSeed_age:=150;
    LOCAL FUNC num Random(

    VAR num nSeed,
    VAR num nSeed_age)
    CONST num nModulus:=655;
    CONST num nMultiplier:=251;
    CONST num nIncrement:=13849;
    IF nSeed_age>140 THEN

    nSeed:=GetTime(Sec)*GetTime(Min);
    nSeed_age:=0;
    ENDIF
    nSeed_age:=nSeed_age+1;
    nSeed:=((nMultiplier*Abs(nSeed))+nIncrement) MOD nModulus;
    RETURN (nSeed/nModulus);
    ENDFUNC

     BR,

    frpa
  • Laro88
    Laro88 Denmark
    Thanks for the suggestion, I will use that as a base and add some additional noise based upon the current robot position.

    Btw. I just skimmed the program. It looks like the nSeed can become 0 (when sec or min =0) and this will result in extended periods of returning nIncrement MOD nModulus.

  • You are right! The seeding needs to be redone so that the seed cannot be 0. Thanks for pointing that out!

  • Laro88
    Laro88 Denmark
    Here is a random generator, extend as needed.

    It uses 2. "random" seedings ( robot position, time) and a counter + Cosinus to generate a nice random number...

    image Please note that I haven't bothered to check for the "flatness" of the random distribtution - so this is most likely not TRUE random.


    MODULE RandomTesting


    VAR num callCount;

    FUNC NUM RANDOM()
    VAR num val:=1;


    var pos pos_current;
    pos_current := CPos(Tool:=tool0 WObj:=wobj0);

    !1 seeding, Seed by position
    val:=val*(Abs(ROUND(pos_current.x*100,Dec:=0)) +1); !+1 to avoid mul by 0 scenario
    val := 789 + val MOD 1000; !777 is just a bogus valu, since the mod might give 0

    !Feel free to seed with y,z, more

    !2. seeding, Seed by time
    val :=val * ( GetTime(Sec)+1);
    val :=val * ( GetTime(Min)+1);


    !3 seeding, increment callcount and handle large nuber
    callCount := callCount +1;
    IF callCount > 1000 THEN
        callCount := 234;
    ENDIF

    !finally a division to get something interesting large float number
    val := val / callCount;

    !get a value between 0 and 1 using COS ( math)
    RETURN (0.5 + COS(val)/2);

    ENDFUNC

    !Testprocedure, dump a couple of numbers to the logfile
    PROC TESTRANDOM()
    var num arandom;

    var string txt:="";

    var num count:=0;

    WHILE count < 18 DO
        arandom := RANDOM();
        txt:=txt + ValToStr(Round(arandom,Dec:=1)) + ";"; !Excel importable
        count := count+1;

    ENDWHILE
        ErrWrite I,"random values",txt;
    ENDPROC
    ENDMODULE


  • frpa!

    I tried your RandomGen, and it works sucesfully!

    But i have one question for you, how/can i decide the highest number i can get, ex no number higher then 200?

     

    BR
  • Laro88
    Laro88 Denmark
    the simplest is to call random and save it in a num variable, and then multiply by your max number.
    Simple pseudocode:

    var num MAXNUMBER:= 200;
    var num rand = RANDOM();
    var num newrandom := rand * MAXNUMBER; !This gives you from 0 to 200 random


  • Laro88
    Laro88 Denmark
    Updated RAPID code & tested it

    MODULE RandomNumber

    VAR num callCount;

    !Get a random number between 0 and 1
    FUNC NUM RANDOM()
    VAR num val:=1;


    var pos pos_current;
    pos_current := CPos(\Tool:=tool0 \WObj:=wobj0);

    !1 seeding, Seed by position
    val:=val*(Abs(ROUND(pos_current.x*100, \Dec:=0)) +1); !+1 to avoid mul by 0 scenario
    val := 789 + val MOD 1000; !777 is just a bogus valu, since the mod might give 0

    !Feel free to seed with y,z, more

    !2. seeding, Seed by time
    val :=val * ( GetTime(\Sec)+1);
    val :=val * ( GetTime(\Min)+1);


    !3 seeding, increment callcount and handle large number
    callCount := callCount +1;
    IF callCount > 1000 THEN
        callCount := 234;
    ENDIF

    !finally a division to get something interesting large float number
    val := val / callCount;

    !get a value between 0 and 1 using COS ( math)
    RETURN (0.5 + COS(val)/2);

    ENDFUNC

    !Testprocedure, dump a couple of numbers to the logfile
    PROC TESTRANDOM()
    var num arandom;

    var string txt:="";

    var num count:=0;

    WHILE count < 10 DO
        arandom := RANDOM();
        txt:=txt + ValToStr(Round(arandom, \Dec:=4)) + ";"; !Excel importable
        count := count+1;

    ENDWHILE
        ErrWrite \I, "random values",txt;
    ENDPROC
    ENDMODULE
  • Newman
    Newman Sweden
    Nowadays you can use Rand().
    -----------------
    David
    Swedish freelance ABB robot programmer