ikarus_177
17.01.2009, 21:52
Hi,
ich beschäftige mich in letzter Zeit mit dem "modernen Wunderland" der inversen Kinematik für Hexapods. Das Ganze wird in Bascom realisiert. Ich habe die Kinematik auf verschiedene Funktionen aufgeteilt, von denen jede eine bestimmte Bewegung ausübt.
Die Berechnung der auftretenden Winkel sowie die Umrechnung in PWM - Werte für die Servos funktioniert auch ganz brav und ordentlich.
Die ersten Tests habe ich mit einer Funktion gemacht, die die Höhe eines Beines sowie dessen Entfernung zum Befestigungspunkt verändern kann. Zuerst habe die Funktion mit einer for-Schleife ständig aufgerufen, anfangs mit 1mm Unterschied in der Höhe. Das Bein bewegte sich auf und ab, allerdings sehr "holprig" ;-)
Also habe ich den Höhenunterschied auf einen zehntel Millimeter erniedrigt, mit dem Ergebnis, dass das Bein wild um sich schlug ;-)
Nun habe ich mir gedacht, eine zusätzliche Funktion in das Programm "einzuschleusen", welche die Servos langsam und kontrolliert an die berechnete Position annähert - mit mäßigem Erfolg.
Ich hatte mir das anfangs so vorgestellt:
- Es werden die zurückzulegenden Wege der Servos berechnet
- Der Servo mit dem kleineren Weg wird im folgenden pro Schleifendurchlauf um 1 erhöht.
- Der andere Servo wird nun genau um einen Wert erhöht, der bewirkt, dass beide Servos gleichzeitig an ihren Positionen ankommen.
Hier der dafür verantwortliche Codeschnipsel:
Smooth_driving:
Drivingbuffer(2) = Servo(2) - Servo2buffer
Drivingbuffer(2) = Abs(drivingbuffer(2))
If Drivingbuffer(2) = 0 Then Drivingbuffer(2) = 1
Drivingbuffer(3) = Servo(3) - Servo3buffer
Drivingbuffer(3) = Abs(drivingbuffer(3))
If Drivingbuffer(3) = 0 Then Drivingbuffer(3) = 1
If Drivingbuffer(2) >= Drivingbuffer(3) Then
Smin = 3
Smax = 2
Buffer = Drivingbuffer(3)
Drivingbuffer(smin) = Servo3buffer
Drivingbuffer(smax) = Servo2buffer
End If
If Drivingbuffer(3) >= Drivingbuffer(2) Then
Smin = 2
Smax = 3
Buffer = Drivingbuffer(2)
Drivingbuffer(smin) = Servo2buffer
Drivingbuffer(smax) = Servo3buffer
End If
'Assertion: smin ist der Servo, der am wenigsten Weg zurückzulegen hat, smax muss hingegen am meisten zurücklegen
'Berechnen der Schritte, die Servo(smax) zurückzulegen hat, während Servo(smin) einen Schritt macht.
For K = 0 To 1
If Servo(smin) > Drivingbuffer(smin) Then Decr Servo(smin)
If Servo(smin) < Drivingbuffer(smin) Then Incr Servo(smin)
Diff(smin) = Drivingbuffer(smin) - Servo(smin)
Diff(smin) = Abs(diff(smin))
If Servo(smax) > Drivingbuffer(smax) Then Servo(smax) = Servo(smax) - Addk
If Servo(smax) < Drivingbuffer(smax) Then Servo(smax) = Servo(smax) + Addk
Diff(smax) = Drivingbuffer(smax) - Servo(smax)
Diff(smax) = Abs(diff(smax))
Grenze(1) = Drivingbuffer(smax) - 2
Grenze(2) = Drivingbuffer(smax) + 2
Singlebuffer = Diff(smax) / Diff(smin)
Addk = Round(singlebuffer)
If Addk < 1 Then Addk = 1
'Abbruchbedingung überprüfen:
If Servo(smin) = Drivingbuffer(smin) And Servo(smax) = Drivingbuffer(smax) Then Exit For
Waitus 500
Decr K
Next
Servo(2) = Servo2buffer
Servo(3) = Servo3buffer
Return
ich hoffe, das ist jetzt einigermaßen verständlich ;-)
Meiner Meinung nach müsste das eigentlich so funktionieren - ich sitze da jetzt schon einige Wochenenden dran, ohne dass es befriedigend funktioniert.
Hat vielleicht jemand eine Idee zur Lösung des Problems?
Viele Grüße
ikarus_177
EDIT: Ich hab natürlich weiter experimentiert, und dabei die Funktion "SmoothDriving" wieder aus dem Programm entfernt, sodass jetzt die berechneten Werte (die laut Simulator stimmig sind!) direkt an die Servos weitergereicht werden. Das Intervall der Höhe wurde auf 0,1mm festgelegt, d.h. das Programm berechnet bei jedem Durchlauf eine Höhe, die um einen Zehntel Millimeter von der vorherigen Höhe abweicht. Das Servosignal, bzw. die Servowerte schauen im Simulator vollkommen korrekt aus, in der Praxis allerdings zucken die Beine wie verrückt, ohne eine erkennbare Bewegung erahnen zu lassen...
Wird das Intervall auf einen Millimeter angehoben, sind nur "hi und da" Zuckungen zu beobachten, allerdings ist der Bewegungsablauf wegen der geringeren Anzahl an Berechnungen sehr "holprig".
Könnte das Zucken gar auf Störung der Servos durch irgendwelche Störquellen zurückzuführen sein? Was würde helfen? Ferritkerne?
Ich bitte um Rat, bin momentan echt am Ende meines Lateins...
ich beschäftige mich in letzter Zeit mit dem "modernen Wunderland" der inversen Kinematik für Hexapods. Das Ganze wird in Bascom realisiert. Ich habe die Kinematik auf verschiedene Funktionen aufgeteilt, von denen jede eine bestimmte Bewegung ausübt.
Die Berechnung der auftretenden Winkel sowie die Umrechnung in PWM - Werte für die Servos funktioniert auch ganz brav und ordentlich.
Die ersten Tests habe ich mit einer Funktion gemacht, die die Höhe eines Beines sowie dessen Entfernung zum Befestigungspunkt verändern kann. Zuerst habe die Funktion mit einer for-Schleife ständig aufgerufen, anfangs mit 1mm Unterschied in der Höhe. Das Bein bewegte sich auf und ab, allerdings sehr "holprig" ;-)
Also habe ich den Höhenunterschied auf einen zehntel Millimeter erniedrigt, mit dem Ergebnis, dass das Bein wild um sich schlug ;-)
Nun habe ich mir gedacht, eine zusätzliche Funktion in das Programm "einzuschleusen", welche die Servos langsam und kontrolliert an die berechnete Position annähert - mit mäßigem Erfolg.
Ich hatte mir das anfangs so vorgestellt:
- Es werden die zurückzulegenden Wege der Servos berechnet
- Der Servo mit dem kleineren Weg wird im folgenden pro Schleifendurchlauf um 1 erhöht.
- Der andere Servo wird nun genau um einen Wert erhöht, der bewirkt, dass beide Servos gleichzeitig an ihren Positionen ankommen.
Hier der dafür verantwortliche Codeschnipsel:
Smooth_driving:
Drivingbuffer(2) = Servo(2) - Servo2buffer
Drivingbuffer(2) = Abs(drivingbuffer(2))
If Drivingbuffer(2) = 0 Then Drivingbuffer(2) = 1
Drivingbuffer(3) = Servo(3) - Servo3buffer
Drivingbuffer(3) = Abs(drivingbuffer(3))
If Drivingbuffer(3) = 0 Then Drivingbuffer(3) = 1
If Drivingbuffer(2) >= Drivingbuffer(3) Then
Smin = 3
Smax = 2
Buffer = Drivingbuffer(3)
Drivingbuffer(smin) = Servo3buffer
Drivingbuffer(smax) = Servo2buffer
End If
If Drivingbuffer(3) >= Drivingbuffer(2) Then
Smin = 2
Smax = 3
Buffer = Drivingbuffer(2)
Drivingbuffer(smin) = Servo2buffer
Drivingbuffer(smax) = Servo3buffer
End If
'Assertion: smin ist der Servo, der am wenigsten Weg zurückzulegen hat, smax muss hingegen am meisten zurücklegen
'Berechnen der Schritte, die Servo(smax) zurückzulegen hat, während Servo(smin) einen Schritt macht.
For K = 0 To 1
If Servo(smin) > Drivingbuffer(smin) Then Decr Servo(smin)
If Servo(smin) < Drivingbuffer(smin) Then Incr Servo(smin)
Diff(smin) = Drivingbuffer(smin) - Servo(smin)
Diff(smin) = Abs(diff(smin))
If Servo(smax) > Drivingbuffer(smax) Then Servo(smax) = Servo(smax) - Addk
If Servo(smax) < Drivingbuffer(smax) Then Servo(smax) = Servo(smax) + Addk
Diff(smax) = Drivingbuffer(smax) - Servo(smax)
Diff(smax) = Abs(diff(smax))
Grenze(1) = Drivingbuffer(smax) - 2
Grenze(2) = Drivingbuffer(smax) + 2
Singlebuffer = Diff(smax) / Diff(smin)
Addk = Round(singlebuffer)
If Addk < 1 Then Addk = 1
'Abbruchbedingung überprüfen:
If Servo(smin) = Drivingbuffer(smin) And Servo(smax) = Drivingbuffer(smax) Then Exit For
Waitus 500
Decr K
Next
Servo(2) = Servo2buffer
Servo(3) = Servo3buffer
Return
ich hoffe, das ist jetzt einigermaßen verständlich ;-)
Meiner Meinung nach müsste das eigentlich so funktionieren - ich sitze da jetzt schon einige Wochenenden dran, ohne dass es befriedigend funktioniert.
Hat vielleicht jemand eine Idee zur Lösung des Problems?
Viele Grüße
ikarus_177
EDIT: Ich hab natürlich weiter experimentiert, und dabei die Funktion "SmoothDriving" wieder aus dem Programm entfernt, sodass jetzt die berechneten Werte (die laut Simulator stimmig sind!) direkt an die Servos weitergereicht werden. Das Intervall der Höhe wurde auf 0,1mm festgelegt, d.h. das Programm berechnet bei jedem Durchlauf eine Höhe, die um einen Zehntel Millimeter von der vorherigen Höhe abweicht. Das Servosignal, bzw. die Servowerte schauen im Simulator vollkommen korrekt aus, in der Praxis allerdings zucken die Beine wie verrückt, ohne eine erkennbare Bewegung erahnen zu lassen...
Wird das Intervall auf einen Millimeter angehoben, sind nur "hi und da" Zuckungen zu beobachten, allerdings ist der Bewegungsablauf wegen der geringeren Anzahl an Berechnungen sehr "holprig".
Könnte das Zucken gar auf Störung der Servos durch irgendwelche Störquellen zurückzuführen sein? Was würde helfen? Ferritkerne?
Ich bitte um Rat, bin momentan echt am Ende meines Lateins...