Mixer Formeln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
nordish1982
User
Beiträge: 7
Registriert: Sonntag 16. März 2008, 20:46

Donnerstag 20. März 2008, 10:44

Moin Moin,

ich habe ein Problem mit einem V-Mixer, der die Bewegung eines Joystick in die Rotation zweier Motoren Links und Rechts umsetzen soll.
Input: x und y (Joystick) als Werte zwischen -1 und 1, 0 ist die Mittelstellung.
Output soll für Motor l und r ein Wert zwischen -1 und 1 sein.

Bislang habe ich die Formeln l=(y+x)/2 und r=(y-x)/2 ermittelt. Das funktioniert auch soweit, nur ergibt das zum Beispiel
bei "Volle Kraft voraus", also y=1;x=0 nur 0.5 auf beide Motoren, also halbe Kraft voraus.

Kennt jemand eine bessere Mischerformel oder muss alles per if Konstruktion aufgeschlüsselt werden?

Vielen Dank im Voraus...
MfG
Nordish
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Donnerstag 20. März 2008, 11:50

Verstehe ich das richtig, daß y die Vorwärts- / Rückwärtsrichtung (Geschwindigkeit) beeinflussen soll und x links / rechts (Fahrtrichtung)?
EDIT: Vielleicht wäre eine Tabelle von xy zu lr sinnvoll, in etwa so?

Code: Alles auswählen

 x | y | l | r
---------------
-1 | 1 |0,1| 1
---------------
 0 | 1 | 1 | 1
---------------
-1 | 0 | -1| 1
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Donnerstag 20. März 2008, 15:22

Folgende Bedingungen finde ich auf den ersten Blick inituitiv sinnvoll:

Code: Alles auswählen

l+r = 2y
l-r = x
Damit hat man aber schon ein vollstaendig bestimmtes lineares System und kommt auf:

Code: Alles auswählen

l = (2y+x)/2
r = (2y-x)/2
Das sieht fast so aus wie bei dir und erfuellt auch die Anforderung, dass y=1, x=0 ergeben soll l=1, r=1
Dummerweise kann man fuer r,l hier betragsmaessig Werte von bis zu 3/2 bekommen... Vlt. koennte man die Werte einfach oben abschneiden:

Code: Alles auswählen

l = min(1, (2y+x)/2)
r = min(1, (2y-x)/2)
Tja, wie sich das Fahrverhalten wohl anfuehlt? (Geht's ueberhaupt ums Fahren...?)

Mehr ist mir in der Mittagspause nicht eingefallen. :wink:
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
nordish1982
User
Beiträge: 7
Registriert: Sonntag 16. März 2008, 20:46

Donnerstag 20. März 2008, 19:01

Moin Moin,

erstmal danke für den beitrag, ich werde das nachher mal durchspielen.
es geht im endeffekt ums fahren unter wasser, also ein ROV.

als zwischenschritt werde ich eine plattform mit rädern bauen um das prinzip trocken zu erproben. beide fahrzeuge steuern ähnlich wie ein kettenfahrzeug über antriebe rechts und links. die joystickbewegung wird über pygame ausgelesen und via telnet (testweise) an einen weiteren rechner auf dem fahrzeug gesendet. dort werden die telnet-befehle in steuerbefehle für einen servocontroller umgesetzt (wieder python). der servocontroller steuert dann über modellbau-fahrtregler die die motoren an. ein hardware-v-mixer auf dem fahrzeug währe zwar auch möglich, aber natürlich weniger elegant.

EDIT: es funktioniert schon, allerdings wird beim vollausschlag in x-richtung der eine antrieb 0 und der andere 1. um den wendekreis zu verringern wäre es cool wenn bei vollauschlag die motoren gegenläufig drehen, das fahrzeug sich also auf der stelle dreht (wie ein panzer)

ausserdem wird bei x=-1 und y=-1 der linke motor -2. der fall müsste also auch noch abgefangen werden.
Holzdolph
User
Beiträge: 23
Registriert: Donnerstag 22. November 2007, 17:43

Donnerstag 20. März 2008, 22:57

nordish1982 hat geschrieben: Bislang habe ich die Formeln l=(y+x)/2 und r=(y-x)/2 ermittelt. Das funktioniert auch soweit, nur ergibt das zum Beispiel
bei "Volle Kraft voraus", also y=1;x=0 nur 0.5 auf beide Motoren, also halbe Kraft voraus.
Die Beschreibung von deinem 2ten eintrag und deine Formeln hier können irgendwie nicht zusammenpassen.
Denn für folgendes Beispiel: y = 0.5 und x = 0.5 passiert bei dir ja folgendes: l = 0.5 und r = 0. dh. das fahrzeug dreht sich am stand nach rechts. y = 0.5 sollte aber doch eine vorwärtsbewegung mit immerhin der halben Leistung erzeugen oder nicht ?

Eigentlich hast du viele Möglichkeiten wie du von deinem Joysticksignal auf eine Steuerung kommst. Wie wärs mit folgender:
Nehmen wir an x und y bilden ein Koordinatensystem mit den üblichen Bezeichnungen - also x-achse = Horizontale und y-Achse die vertikale (ich verwechsle immer abszisse/ordinate).
dann würde zb y=0.5 und x=0.5 bedeuten das fahrzeug begwegt sich mit halber leistung nach vorne und 50% des möglichen einschlags nach rechts. ein negatives x heisst das fahrzeug fährt nach links und y<0 bedeutet das teil fährt rückwärts.
dann komme ich auf folgenden code:

Code: Alles auswählen

wmax = 2  # maximale Leistung (beide motoren auf vollgas)
g = 2 # gewichtung des verhältnisses bewegung/einlenken

w = y * wmax   # die leistung die beide motoren liefern sollen
if y == 0:         # voller einschlag falls nur links/rechts betätigt wird
    r = -x
    l = x
else:
    t = w / (g+abs(x))
    if x >= 0:
        r = t
        l = w - t
    else:
        r = w - t
        l = t
Ein Beispiel:
y = 0.3, x = 0.5: vorwärtsbewegung mit 30% maximalleistung und 50% einschlag nach rechts
w = 0.6 -> t=6/25 = 0.24
also r = 0.24 und l = w - t = 0.36
der linke motor bringt also 36% seiner leistung und der rechte 24%, damit macht das fahrzeug eine vorwärtsbewegung mit insgesamt 50% leistung und dreht sich mit 50% nach rechts.
Auch für alle anderen Möglichkeiten liefert das brauchbare ergebnisse.

noch zur Formel t = w / (g + abs(x))
die kommt von folgender Umformung:

[t] + {(1+x) * t }= w
mit [eckige klammer] = linke motorleistung und {runde klammer} = rechte motorleistung (für positive x werte) sollen zusammen ja die leistung w ergeben, vereinfacht also l + r = w
da ja x und w bekannt ist formt man das ganze um und kommt auf obigen ausdruck für t, wobei für g eben 2 gesetzt wird. in diesem fall bedeutet das x also um wieviel % stärker nach rechts eingelenkt werden soll. änderst du das g, verändert sich das verhältnis von vorwärts/einlenk bewegung, kannst ja ein bisschen damit rumspielen um eine optimale steuerung rauszukriegen. dh ein wert kleiner 2 verstärkt den lenkeffekt und ein wert größer 2 macht die lenkung träger.

ich hoffe das funktioniert auch alles :) habs am heimweg vom büro mal durchgedacht
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Freitag 21. März 2008, 08:42

nordish1982 hat geschrieben:EDIT: es funktioniert schon, allerdings wird beim vollausschlag in x-richtung der eine antrieb 0 und der andere 1. um den wendekreis zu verringern wäre es cool wenn bei vollauschlag die motoren gegenläufig drehen, das fahrzeug sich also auf der stelle dreht (wie ein panzer)
Deshalb meine Idee mit der Tabelle Eingabewerte -> gewünschte Werte.
Man könnte das Ganze eventuell auch ähnlich wie in AmoebaWorld simulieren.
nordish1982 hat geschrieben:ausserdem wird bei x=-1 und y=-1 der linke motor -2. der fall müsste also auch noch abgefangen werden.
Stimmt, das ist mir auch heute Nacht eingefallen, die Formel hätte also auch einen negativen und einen positiven Teil.
Die Frage ist vermutlich wirklich, wie du es genau haben willst, danach kann man dann eine Funktion modellieren.
EDIT: Satz vervollständigt.
nordish1982
User
Beiträge: 7
Registriert: Sonntag 16. März 2008, 20:46

Sonntag 23. März 2008, 10:55

Moin Moin,

erstmal danke für die hilfe, ich hab das mal in einem schnellen schmutzigen testproggi verhackstückt.


Code: Alles auswählen

loop=1
while(loop==1):
    y= input("y-richtung:")
    x= input("x-richtung:")

    wmax = 2  # maximale Leistung (beide motoren auf vollgas)
    g = 2 # gewichtung des verhältnisses bewegung/einlenken

    w = y * wmax   # die leistung die beide motoren liefern sollen
    if y == 0:         # voller einschlag falls nur links/rechts betätigt wird
        r = -x
        l = x
    else:
        t = w / (g+abs(x))
        if x >= 0:
            r = t
            l = w - t
        else:
            r = w - t
            l = t
        
    print "Links:", l
    print "Rechts:", r
    loop=input("drueck 1 fuer weiteren durchlauf:")
print "ende"
hat leider auch den fehler das bei x=1 und y=1 für l(links) 2 rauskommt.
Holzdolph
User
Beiträge: 23
Registriert: Donnerstag 22. November 2007, 17:43

Montag 24. März 2008, 00:58

stimmt, aber nur weil dann in der formel keine floats mehr vorkommen und die division dann mit reinen integer-typen durchgeführt wird. gibst du 1.0 ein statt nur 1 rechnet er sinnvollere zahlen aus.

richtig ists aber trotzdem nicht, da dann 1.33 und 0.67 rauskommt. das problem ist die anfangsbed. l + r = 2 . damit wird nicht verhindert das l oder r > 1 ist. das muss man noch irgendwie einbinden, aber heute (nacht) fällt mir dazu nichts brauchbares mehr ein.
Holzdolph
User
Beiträge: 23
Registriert: Donnerstag 22. November 2007, 17:43

Montag 24. März 2008, 14:53

also am einfachsten ists einfach am ende nochmal zu prüfun ob r oder l > 1 ist und dann gegebenfalls die 2 werte auf 1 zu beschränken. und der fehler bei der division tritt auf wenn alle variablen ganze zahlen sind. darum am besten:

wmax = 2.0

verwenden dann kommt immer ein float typ in der division vor.

Code: Alles auswählen

loop=1
while(loop==1):
    y= input("y-richtung:")
    x= input("x-richtung:")

    wmax = 2  # maximale Leistung (beide motoren auf vollgas)
    g = 2 # gewichtung des verhältnisses bewegung/einlenken

    w = y * wmax   # die leistung die beide motoren liefern sollen
    if y == 0:         # voller einschlag falls nur links/rechts betätigt wird
        r = -x
        l = x
    else:
        t = w / (g+abs(x))
        if x >= 0:
            r = t
            l = w - t
        else:
            r = w - t
            l = t
    if l > 1:
        r = r / l
        l = 1
    elif r > 1:
        l = l / r
        r = 1
   
    print "Links:", l
    print "Rechts:", r
    loop=input("drueck 1 fuer weiteren durchlauf:")
print "ende"
Damit funktionierts jetzt zwar endlich, dafür gibts aber einen Totbereich. Eventuell hilfts ja die konstante g ein bisschen kleiner zu machen oder aber gleich einen neuen Ansatz zu wählen. Aber zumindest fahren sollte das Teil jetzt mal sinnvoll :)
nordish1982
User
Beiträge: 7
Registriert: Sonntag 16. März 2008, 20:46

Dienstag 25. März 2008, 19:31

Moin Moin,

ich hatte heute selbst nochmal zeit drüber nachzudenken. wenn der joystick um 45 grad verdreht wird entsteht der mischer-effekt von allein. in dem fall ist "volle kraft" voraus X=1.0 und Y=1.0, also sehr einfach auf motoren umzulegen.

manchmal sind die einfachen lösungen nicht die schlechtesten.

Danke nochmal an alle die sich Gedanken gemacht haben.

cu
Antworten