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
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
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
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!
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…
:stuck_out_tongue_winking_eye: 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
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
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
Nowadays you can use Rand().
Can you give an example? I am not finding much in the documentation.
See attached extract from the RAPID manual
Rand.pdf (826 KB)