Forum: Mikrocontroller und Digitale Elektronik Random Walk ohne drift


von Florian R. (rager)


Lesenswert?

Hallo,
ich baue gerade eine Wettersimulation für mein Terrarium:
-Wind (Ventilationen)
-Nebel
-Regen
-Licht

Nun möchte ich für den Wind gerne naturnahe Schwankungen einbauen. mit 
bestimmten Tendenzen.
Morgens und Abends eher kein Wind.
Tagüber darf es auch mal stärker pusten.
Jetzt habe ich ein wenig am PC rumprobiert und im prinzip das hier 
gemacht:
1
int randomWalk(int moveSize){
2
  static int  place;     // variable to store value in random walk - declared static so that it stores
3
  // values in between function calls, but no other functions can mess with its value
4
5
  place = place + (random(-moveSize, moveSize + 1));
6
7
  if (place < randomWalkLowRange){                    // check lower and upper limits
8
    place = place + (randomWalkLowRange - place);     // reflect number back in positive direction
9
  }
10
  else if(place > randomWalkHighRange){
11
    place = place - (place - randomWalkHighRange);     // reflect number back in negative direction
12
  }
13
14
  return place;
15
}

Das Hat auf dem PC gut funktioniert, ich denke weil die Random Funktion 
dort besser ist. Nur auf meinem Atmega(Arduino) ist die Random Funktion 
leider mit einer recht starken tendenz belastet. Das fürt zu ständigen 
Randbewegungen und dort bleibt es dann auch. Der gesammte bereich wird 
nie genutzt. Habt Ihr eine Idee wie ich das besser machen kann? Ohne 
Drift in eine bestimmte richtung.

LG,
Florian

: Bearbeitet durch User
von jonas biensack (Gast)


Lesenswert?

>Habt Ihr eine Idee wie ich das besser machen kann? Ohne
>Drift in eine bestimmte richtung.

Wie sieht dein randomSeed(); aus?

Gruß Jonas

von Florian R. (rager)


Lesenswert?

Der wurde nicht genutzt. Ist der Nötig?

von jonas biensack (Gast)


Lesenswert?

http://arduino.cc/en/Reference/Random

Ich denke schon.

Gruß Jonas

von Florian R. (rager)


Lesenswert?

RandomSeed scheint nur den Startpunkt festzulegen.
Macht vielleicht ein anderer Ansatz mehr Sinn?

von Kaj (Gast)


Lesenswert?

jonas biensack schrieb:
> Wie sieht dein randomSeed(); aus?

Florian Roesner schrieb:
> Ist der Nötig?

jonas biensack schrieb:
> Ich denke schon.

Nein, ist er nicht. der Seed veraendert lediglich die "Startbedingung". 
Ohne seed bekommst bei jedem neustart des zufallszahlengenerators die 
selben werte, z.B.
1,8,0,348,29,4, usw...
Das ist mit einem statischen seed (also hard gecoded, in etwa seed = 
1337) nicht anders, nur das die zahlen jetzt andere sind, als ohne seed. 
bei einem neustart des zufallszahlengeneratos mit dem gleichen seed 
erhaelts du wieder die selben Zahlen, z.B. 96,111, 350,1,0 usw.

Der Seed sollte bzw. darf keine auswirkung auf das Verhalten des 
Zufallszahlengenerators haben, so wie es hier beschrieben wurde.

Florian Roesner schrieb:
> Das Hat auf dem PC gut funktioniert
int auf einem PC sind in der Regel 4 Byte gross, auf einem Atmega in der 
Regel aber nur 2 Byte. Hast du das bedacht?

Florian Roesner schrieb:
> place = place + (random(-moveSize, moveSize + 1));
Wenn movesize negativ ist so wird aus -movesize ein -(-movesize) was das 
gleiche ist wie +movesize. ( 10 - (-5) = 15 )
D.h. im schlechtesten falle wird place immer groesser und groesse. Durch 
das static wird place auch nie geloescht. Irgendwann kommt ein 
ueberlauf...

Sicher das es das ist, was du willst?

Florian Roesner schrieb:
> if (place < randomWalkLowRange){
>     place = place + (randomWalkLowRange - place);
>   }
>   else if(place > randomWalkHighRange){
>     place = place - (place - randomWalkHighRange);
>   }
Was passiert wenn place genau zwischen randomWalkLowRange und 
randomWalkHighRange liegt? sicher das du dann einfach nur place zurueck 
geben willst?
Wie sind randomWalkLowRange  und randomWalkHighRange  definiert?

von Gustav (Gast)


Lesenswert?

Florian Roesner schrieb:
> Das fürt zu ständigen
> Randbewegungen und dort bleibt es dann auch.

Wenn du erstmal am Rand bist, dann bleibst du bei einem Random Walk halt 
tendentiell auch in Randnähe. Warum denn nicht?

Oder löst der sich nie mehr vom Rand?

von .... (Gast)


Lesenswert?

ich finde deinen ansatz komisch.
Mit einem Rauschgenerator für weißen gaussches Rauschen kommst in 
Verbindung mit einer Fensterfunktion viel natürlicher weg....
Arduino-Krankheit... vorgefertigtes schränkt die Möglichghkeiten und die 
Kreativität ein. Ist halt für kinder und FH-Abslventen ;-)

von Florian R. (rager)


Lesenswert?

> Wenn du erstmal am Rand bist, dann bleibst du bei einem Random Walk halt
> tendentiell auch in Randnähe. Warum denn nicht?
>
> Oder löst der sich nie mehr vom Rand?
Es löst sich eher schlecht


> Wie sind randomWalkLowRange  und randomWalkHighRange  definiert?
in diesem Fall:
randomWalkLowRange = 0;
randomWalkHighRange = 255;


> Wenn movesize negativ ist so wird aus -movesize ein -(-movesize) was das
> gleiche ist wie +movesize. ( 10 - (-5) = 15 )
Wird nicht passieren, da ich keine Negativen eingebe ^^


> ich finde deinen ansatz komisch.
> Mit einem Rauschgenerator für weißen gaussches Rauschen kommst in
> Verbindung mit einer Fensterfunktion viel natürlicher weg....
Muss man halt auch erstmal kennen. Dafür sind solche Orte hier ja da Für 
Informationsaustausch, es geht ja nicht alles zu kennen.
Ich schau mir mal das Gauß'sche  Rauschen an :)

von Purzel H. (hacky)


Lesenswert?

Man kann natuerlich eine ruecktreibende Kraft einfuehren. Zb wenn der 
Schritt ein Feld verlassen wuerde, nimmt den negierten Schritt oder so.

von .... (Gast)


Lesenswert?

das Rauschen ist mittelwertfrei und du kannst über die 
Standardabweichung die "härte" einstellen. (Wie stark/oft sind die 
richtig krassen ausreiser?)
Wenn du das Rauschen etwas tiefpassfilterst, bekommt man recht 
zufälliges verhalten hin.

Du kannst dann eine grobe Hüllkurve designen, sodass zu abends und 
morgens ruhe hast. also eine art Gaußglocke, oder einen Sinusberg oder 
sowas.
Wenn du auf diese Hüllkurve noch etwas rauschen addierst, hast du jeden 
tag ein anderes verhalten.

Zum schluss bekommst du:

(Hüllkurve+Rauschen1_Langzeit)*Rauschen2_kurzzeit.

Das weiße gaussche rauschen wird Werte außerhalb deines Wertebereichs 
genrieren. Du kannst den Output einfach auf einen bereich begrenzen und 
über die standardabweichung z.B. festlegen, dass die werte nur zu 5% der 
Zeit gesättigt sind. Das ist alles recht einfach, da es nur von ein paar 
Parametern abhöngt die man sehr gut auch per experiment bestimmen kann.

von Kaj (Gast)


Lesenswert?

Florian Roesner schrieb:
>> Wenn movesize negativ ist so wird aus -movesize ein -(-movesize) was das
>> gleiche ist wie +movesize. ( 10 - (-5) = 15 )
> Wird nicht passieren, da ich keine Negativen eingebe ^^
Dann mach auch bitte den parameter als unsigned int, nur so als tipp.
Und noch ein tipp:
du solltest place vielleicht initialisieren...

Florian Roesner schrieb:
> static int  place;
Ich weiss grad nicht wie es bei static variablen ist, aber so
Florian Roesner schrieb:
> place = place + (random(-moveSize, moveSize + 1));
addierst du auf irgendeinen wert etwas drauf.

Variablen immer initialisieren, und wenn es nur mit 0 ist. Spart im 
schlimmsten falle tage lange fehler suche.

von Peter II (Gast)


Lesenswert?

Kaj schrieb:
> Variablen immer initialisieren, und wenn es nur mit 0 ist. Spart im
> schlimmsten falle tage lange fehler suche.

static (sowie alle globalen Variablen) sind immer mit 0 initialisiert.

von Florian R. (rager)


Lesenswert?

Danke euch allen für eure Ideen,ich werde mal in den nächten Tagen 
schauen was ich daraus machen kann ^^

Liebe Grüße,
Florian

von Mathe-Gott (Gast)


Lesenswert?

In deinen Formeln zur Korrektur von place falls es außerhalb der Range 
ist fehlt ein Faktor 2.

Zur Zeit wird der Wert nur auf randomWalkLowRange bzw. 
randomWalkHighRange korrigiert und nicht "reflect"ed.

von P. M. (o-o)


Lesenswert?

Ein Random-Walk hat nunmal die Tendenz, wegzulaufen. Der Erwartungswert 
für die Entfernung nimmt mit der Wurzel der Anzahl Schritte zu. Du 
kannst einen noch so guten Zufallsgenerator haben, du wirst immer am 
Rand landen.

Die Idee mit der rücktreibenden Kraft finde ich deshalb gut. Du kannst 
es z.B. als Kugel in einer Parabel a*x^2 modellieren. Die Kugel erfährt 
zufällige Stösse nach links und rechts, aber je weiter sie von x = 0 
entfernt ist, desto steiler ist dort die Parabel und desto stärker auch 
die rücktreibende Kraft.

Bewegungsgleichung:

Kraft F = a * x + zufälliger Stoss
Geschwindigkeit v = v + F / m
Position x = x + v

Eine Hüllkurve über den Tagesverlauf könnte man implementieren, indem 
man a und der Betrag der zufälligen Stösse über den Tagesverlauf 
variiert.

von Purzel H. (hacky)


Lesenswert?

Wenn die ruecktreibenede Kraft proportional der Auslenkung ist, dann 
erhaelt man, ohne Random Walk, einen Sinusgenerator. Also aufpassen

von Thomas (Gast)


Lesenswert?

>erhaelt man, ohne Random Walk, einen Sinusgenerator.

Nö, ne flache Linie.

von P. M. (o-o)


Lesenswert?

Siebzehn Zu Fuenfzehn schrieb:
> Wenn die ruecktreibenede Kraft proportional der Auslenkung ist, dann
> erhaelt man, ohne Random Walk, einen Sinusgenerator. Also aufpassen

Das ist auch ungefähr, was man haben möchte. Eine Kurve, die periodisch 
auf- und ab geht, mit einer hohen Zufälligkeit darin. Man könnte 
zusätzlich noch eine Dämpfung/Reibung einbauen. Die Steigung der 
Parabel, die Reibung und die Stärke der Stösse sollten viele 
Möglichkeiten zum Formen der Kurve ergeben. Anstatt eine Parabel kann 
man sich jede andere Rückstellfunktion vorstellen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.