PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 5 DOF Roboterarm: Arduino-Programme für Kinematik u. inverse Kinematik?



HaWe
23.09.2018, 11:57
hallo,
ich vermute, es gibt nur sehr wenige, hoffe aber dennoch wenigstens ein paar hier im Forum, die sich damit auskennen und es auch schon benutzen:

Wer hat Erfahrung mit Arduino-Programmen für 5-6 DOF Roboterarme für Kinematik u. inverse Kinematik?
Literatur gibt es zwar zuhauf, aber extrem vermathematischt und mit irrsinnig viel Matrizenrechnung, die mich ehrlich gesagt überfordert, um sie in arduinisch zu programmieren.

In meinem Fall handelt es sich um diesen Robotarm hier (5 drehbare Achsen plus Greifer, die erste Ache (Schulter) und die letzte Achse (Handgelenk) vor dem Greifer sind rotierbar entlang der Auslenkung, die anderen knicken senkrecht zur Auslenkung) :

https://www.ebay.de/itm/Assembled-6DOF-Robot-Arm-Mechanical-Robotic-Clamp-Claw-with-Servos-Controller/252317775624?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2060353.m1438.l2649

Was das Ziel sein soll:
Nach Definition der Armlängen und Rotationsachs-Dimensionen (Knicken oder rotieren innerhalb der Achse) sollte man folgendes machen können:

a) Kinematik:
Wenn man eine beliebige Kombination von Drehwinkeln für jede einzelne Achse eingibt (alpha, beta, gamma, delta, epsilon), dann soll als Ergebnis die absolute Raumposition (x,y,z) errechnet werden (z.B. für die Greifer-Mitte);

b) Inverse Kinematik:
Nach Eingabe einer absoluten Ziel-Koordinate (x,y,z) z.B. für die Greifer-Mitte soll für alle Servos eine Lösung für die erforderlichen absoluten Drehwinkel berechnet werden, sodass man sie per analogWrite-pwm dann dorthin bewegen kann (es gibt u.U. mehrere Lösungen, welche man dann bekommt oder verwendet, wäre dann noch zu überlegen).

Wer kennt sich damit selber wirklich gut aus?

Moppi
28.09.2018, 15:37
Hmm, immer noch nicht weiter gekommen?

Ich kenne mich mit Deiner Problemstellung nicht aus. Aber ein Tipp von mir:
Die Position auf einer Kreisbahn kannst Du über den Radius berechnen. Stichwort: Berechnungen im Kreis oder Kreisberechnungen.
Damit kannst Du die Positionen ausrechnen, die Du auf einer Kreisbahn, ausgehend von einem Mittelpunkt (die Achse eines Motors) unter Angabe des Radius (Armlänge/Armteillänge bis zum nächsten Gelenk), maximal erreichen kannst.
Ist eine Position nicht erreichbar, müsste man auf den nächsten Drehpunkt übergehen (zum Beispiel einen zurück) und von dort aus rechnen.

Gemacht habe ich das noch nicht, aber das wäre mein Ansatz.

MfG, Moppi

Mxt
28.09.2018, 15:59
Ich denke der Lösungsweg ist nicht das Problem. Es wird halt jemand gesucht, der ihn gehen soll.

Weg a) geht im Prinzip so
https://de.wikipedia.org/wiki/Denavit-Hartenberg-Transformation

Weg b) macht man wohl heute meist mit einer Kombination aus
https://de.wikipedia.org/wiki/Jacobi-Matrix
https://de.wikipedia.org/wiki/Pseudoinverse

Eigentlich muss man das aber nicht wirklich wissen, weil es diverse C++ Bibliotheken gibt, die das schon fertig können.
http://roboop.sourceforge.net/
https://moveit.ros.org/
http://www.orocos.org/kdl
Die sind aber nicht geeignet, weil keine fertigen Portierungen auf Arduino existieren oder möglich sind.

Auch Rechnen mit mehr Handarbeit mit den gängigen C++ Matrix Libs wie z.B.
http://eigen.tuxfamily.org/index.php?title=Main_Page
http://arma.sourceforge.net/
ist wohl nicht gefragt, weil es zumindest keine fertigen Portierungen auf Arduino gibt.

Das ist alles, was ich beitragen könnte, ist aber keine fertige Lösung, daher zu verwerfen.

Moppi
28.09.2018, 16:59
Ich halte von so fertigen Sachen nicht wirklich viel. Es sei denn, es wäre sehr sehr kompliziert. Dass man nicht selbst einen Lösungsweg suchen könnte. Es gibt für viele , per mathematischer Formel sehr komplizierte Sachen einfache Lösungswege, auch für 8-Bit-Computer oder 16 Bit Computer. Als Beispiel sehe ich immer auf Doom, was ich als erstes 3D-Spiel hatte. Echtzeit 3D-Berechnung der Grafik-Engine hätte mit komplexen mathematischen Formeln, auf den damaligen leistungsschwachen Computern gar nicht funktioniert. Da werden Punkte im 3D-Koordinatensystem in Echtzeit auf einer 16MHz-CPU berechnet. Innerhalb Bruchteilen von Sekunden sind das oft mehr als 8 Punkte pro Objekt. Wenn man dann sieht, wie es gemacht wird, staunt man, wie einfach die Lösung gewesen ist. Daher denke ich, lohnt es, zu versuchen, das selber zu lösen. Da weiß man hinterher, warum es funktioniert oder warum auch etwas nicht funktioniert.

Mxt
28.09.2018, 17:17
Richtung a) ist nicht rechenaufwändig. Ohne das würde kein Industrieroboter funktionieren. Ging natürlich schon mit den allerersten und bevor es überhaupt Prozessoren als eigenständiges IC gab.

Mit b) ist das zumindest "live" während der Bewegung anders. Bei den japanischen Robotern, mit denen ich an der Arbeit zu tun habe, kam das erst bei den Modellen in den 1990ern, die schon 32 Bit Prozessoren hatten (damals Intel i960).

HaWe
28.09.2018, 18:03
wer immer die inverse Kinematik auf Arduino selber portieren möchte, möge das gerne tun!
Bewährt hat sich wohl die Denavit–Hartenberg Konvention
https://en.wikipedia.org/wiki/Denavit%E2%80%93Hartenberg_parameters

IMO wäre es als User-Schnittstelle am einfachsten, und für verschiedene Robotarm-Designs am flexibelsten, wenn der Nutzer seine Robotmaße einfach eingeben könnte in eine Reihe von arrays. Statt die genauen Achs-Positionen einzugeben, könnte man sich auch auf "TILT" fürs abknicken und "ROTATE" fürs drehen in der Armlängsrichtung beschränken, für lineare Aktuatoren und auch für die virtuelle Greifposition in der Zange auch Typ "LINEAR":

// cusomize your arbitrary robot arm dimensions and design.

#define MAXJOINTS 6


Jtype[0] = ROTATE; // turntable joint
Jangl[0] = 270; // max turn angle
Lleng[0] = 95; // turntable height in mm

Jtype[1] = TILT; // shoulder joint
Jangl[1] = 180; // max turn angle
Lleng[1] = 105; // upper arm length in mm

Jtype[2] = TILT; // elbow joint
Jangl[2] = 180; // max turn angle
Lleng[2] = 97; // forarm length in mm

Jtype[3] = TILT; // wrist tilt
Jangl[3] = 90; // max turn angle
Lleng[3] = 65; // wrist length: not exaclty linear mounted!

Jtype[4] = ROTATE; // metacarpal rotate.
Jangl[4] = 90; // max turn angle
Lleng[4] = 50; // metacarpal length

Jtype[5] = LINEAR; // longitudinal finger length (not opening!!)
Jangl[5] = 0; // virtual grab position, no motor used (claw open/close external cmd)
Lleng[5] = 60; // finger length = grab area length metacarpal to fingertip

https://i.ebayimg.com/images/g/92EAAOSwnFZXWm9k/s-l1600.jpg

und das Robot-Programm verkettet dann diese Werte zur Kette der Teil-Arme, in dem es sie in seine Matrizen einsetzt.

Für mich persönlich überschreitet das meine Kompetenzen bei weitem, sonst würde ich es selber machen.
Daher, insb. @moppi: wenn du es dir zutraust: Immer gerne!

Zum Rechnen würde sich sicher ein M3 (Due) oder auch ein M4 mit fpu anbieten.

Mxt
28.09.2018, 18:04
IMO wäre es als User-Schnittstelle am einfachsten, und für verschiedene Robotarm-Designs am flexibelsten, wenn der Nutzer seine Robotmaße einfach eingeben könnte in eine Reihe von arrays,
[...]
und das Robot-Programm verkettet dann diese Werte zur Kette der Teil-Arme, in dem es sie in seine Matrizen einsetzt.


Das ist im wesentlichen das Vorgehen bei dem oben verlinkten Roboop, auch wenn da eine etwas andere Schreibweise verwendet wird. Hier ein auf die Schnelle im Code gefundenes Beispiel für den historischen Unimation Puma 560


const Real PUMA560_data[] =
{0, 0, 0, 0, M_PI/2.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.35, 0, 0, 0,
0, 0, 0, 0.4318, 0, 0, 0, 0, 17.4, -0.3638, 0.006, 0.2275, 0.13, 0, 0, 0.524, 0, 0.539, 0,
0, 0, 0.15005, 0.0203, -M_PI/2.0, 0, 0, 0, 4.8, -0.0203, -0.0141, 0.07, 0.066, 0, 0, 0.086, 0, 0.0125, 0,
0, 0, 0.4318, 0.0, M_PI/2.0, 0, 0, 0, 0.82, 0, 0.019, 0, 0.0018, 0, 0, 0.0013, 0, 0.0018, 0,
0, 0, 0, 0.0, -M_PI/2.0, 0, 0, 0, 0.34, 0.0, 0.0, 0.0, 0.0003, 0.0, 0.0, 0.0004, 0.0, 0.0003, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0.09, 0.0, 0.0, 0.032, 0.00015, 0.0, 0.0, 0.00015, 0.0, 0.00004, 0};

Vorwärts- und Rückwärtskinematik macht dann die Lib. Aber diese Software ist für Microsoft Visual C++ gedacht, von 1996 bis 2013 aktiv entwickelt worden und hängt von der schon reichlich veralteten C++ Matrizenlibrary newmat ab. Um das in die Arduino IDE hineinzukriegen wäre schon einiges an Detailwissen erforderlich.

Die anderen Libs habe ich mir noch nicht im Detail angesehen.

HaWe
28.09.2018, 18:17
ja, ich sagte ja selber: extremst kompliziert, für mich ZU kompliziert, ich bin ja absolut nicht vom Fach.
Ein anderer User, der selber auch Robotik studiert, drückte es so aus:
"What would have to be done for such a library is to have an algorithm that assigns these DH parameters automatically based on the parameters the user inputs into it; For each joint i: Theta_i, D_i, Alpha_i, A_i. I think why this hasn't been implemented on Arduino yet is because it is a very difficult problem to generalize and Scientists aren't really interested in implementing things like this for Arduino. As I have said before, all this have been implemented in Matlab in Robotics Toolbox and it is very powerful. I find it very hard though to implement this in an Arduino library, but I guess it's not impossible, it just has to get a bit limited that's all. But note that not anyone can do this, it takes someone with knowledge within this area to implement a library for this."


PS,
bei "meinem" obigen Robotarm kommt erschwerend dazu, dass die vorletzte Achse einen Zwischen-Winkel nach oben hat, weil die Servos aufeinander montiert sind und nicht hintereinander, und daher der Rest dann nicht mehr in der Fluchtlinie liegt, sondern nach oben abgeknickt ist. Wie man das mathematisch beschreibt, ist mir noch völlig schleierhaft.

Nein, nicht völlig schleierhaft ntl, man müsste die Resultierende nehmen, aber dann sind es in jedem Falle keine rechten Winkel mehr hinterher.

Mxt
28.09.2018, 18:44
bei "meinem" obigen Robotarm kommt erschwerend dazu, dass die vorletzte Achse einen Zwischen-Winkel nach oben hat, weil die Servos aufeinander montiert sind und nicht hintereinander, und daher dann nicht mehr in der Fluchtlinie liegt, sondern nach oben abgeknickt ist. Wie man das mathematisch beschreibt, ist mir noch völlig schleierhaft.

Ich denke das ist kein Problem, weil es sich nur um eine Kette von Verschiebungen und Drehungen handelt.

Doom war ja ein interessanter Hinweis von Moppi, zumindest in den Computergrafik Vorlesungen hatte ich diese Matrizen. Das ist zwar schon ewig her, aber das Grundprinzip von a) ist mir soweit klar. Ich versuchs mal:

Wichtig ist zu wissen, das man jede "Roboterposition" im Raum als Koordinatensystem darstellen kann. Also als einen "Punkt mit Orientierung" aus dem die X-, Y- und Z-Achse eines in diesem Punkt liegenden Koordinatensystems "herauswachsen". Der berühmte Tool-Center-Point so eines Greifarms wird so dargestellt. Der Greifer ist an einem Punkt im Raum und zeigt in eine bestimmte Richtung.

Diese 4x4 Matrizen haben einen Aufbau, den man sich gut vorstellen kann:


1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Das ist die Position des Nullpunktes im Weltkoordinatensystem. Wie man sieht, stehen da Einsen drin, nicht nur Nullen. Die haben eine spezielle Bedeutung.

Erstmal zu den X,Y,Z-Koordinaten. Die Matrix vom Punkt mit den Koordinaten X= 100, Y=200, Z=300 (nicht verdreht zum Koordinatensystem) sieht so aus:


1 0 0 100
0 1 0 200
0 0 1 300
0 0 0 1

Man sieht diese drei Felder kodieren die Position im Raum.

Was machen die anderen Spalten ? Ganz einfach, das sind die drei Achsen des Koordinatensystems.


1 . . .
0 . . .
0 . . .
. . . .

Das ist die X-Achse. Ein 3D-Vector der immer die Länge Eins hat. Die drei Zahlen sind die Komponente in Welt-X Richtung, Welt-Y Richtung und Welt-Z Richtung. Weil es hier ein nicht gegenüber dem Weltkoordinatensystem verdrehter Punkt ist, zeigt die Punkt X-Achse natürlich voll und ganz in Richtung Welt-X.

Y- und Z-Achse kann man entsprechend sehen.

So, diese tollen Matrizen im Wikipediaartikel dienen jetzt dazu diese Punkte um einen X,Y,Z-Wert zu verschieben, oder um die (lokale oder Welt-) X-, Y- oder Z-Achse zu verdrehen. Diese Verschiebung und die drei Drehungen sind die Grundoperationen. Mehr braucht man nicht. Verkettet werden die Dinger in dem man sie multipliziert.

Vorwärtskinematik ist jetzt nur, das man für jeden Freiheitsgrad des Roboters so eine Matrix aufstellt, wie man von der Basis von Segment x zur Basis von Segment x+1 kommt. Da kommt die jeweilige Achsdrehung noch als Variable hinein.

Das ist Weg a). Das kriegt man im Prinzip zu Fuss hin. D-H ist nur eine Konvention, da gibt es auch andere Varianten.

HaWe
28.09.2018, 18:48
schon klar, das sind die oben zitierten Matrizen, am ehesten verkettet nach Denavit–Hartenberg, und berechnet "vorwärts" und dann auch invers.
Aber wenn du das ausrechnen und programiieren kannst, das wäre großartig - ICH kann es nicht, daher suche ich eine fertige Lib.

Mxt
28.09.2018, 18:54
Du hattest ja letztens diesen Benchmark. Da sind Matrixmultiplikationen drin. Mehr braucht man für Richtung a) im Prinzip nicht.

HaWe
28.09.2018, 19:37
ja, diese einfachen Dinger habe ich mal irgendwo abgeschrieben, weil ich damals schon wusste, dass man ohne Matrizen für IK nicht auskommt (und um IK geht es ja ebenso), daher habe ich sie schon mal in den BrickBench mit reingenommen.
Beide Richtungen sind also wichtig:
a) Eingabe aller Einzelwinkel => Endposition des Greifers samt seiner Stellung (Eulerwinkel yaw, pitch, roll),
b) Eingabe einer Raumkoordinate samt Winkelstellung des Greifers => Berechnung aller Einzelwinkel

Aber wenn dir das bisschen schon reicht mit der Matrizenmultiplikation für so eine Lib, dann machs einfach damit 8)

Mxt
28.09.2018, 19:44
Da geht ja was:
https://github.com/bolderflight/Eigen
Von einer der wichtigsten oben verlinkten Libs gibt es einen Port für den Teensy. Damit dürfte einiges aus dem Roboticbereich darauf laufen, ROS oder die Robotics Library der TU München verwenden alle Eigen.

HaWe
28.09.2018, 19:47
das ist jetzt vielleicht ein kleiner Mosaikstein, aber nicht die Lösung der TOP Frage...

a) Eingabe aller Einzelwinkel => Endposition des Greifers samt seiner Stellung (Eulerwinkel yaw, pitch, roll),
b) Eingabe einer Raumkoordinate samt Winkelstellung des Greifers => Berechnung aller Einzelwinkel

Moppi
29.09.2018, 09:37
Na ja, es fertige Sachen. Zu einem ausgereiften Industriellen Roboterarm bekommt man sicher auch die passende Software, Dokumentation und Bibliotheken. Allerdings kann ich mir vorstellen, dass man dann dort wieder an eine andere Hochsprache gebunden ist.

Um einen Arm zu bewegen gibt es verschiedene Winkel, die entstehen, das wird nicht neu sein:

33663

Hier noch mal Winkelberechnung, von ganz einfach bis kompliziert: https://www.frustfrei-lernen.de/mathematik/winkel-berechnen-winkel-rechnen.html
Wobei: kompliziert muss nicht sein. Meine Meinung. Daher würde ich persönlich zunächst einen andern Weg versuchen und die Winkel berechnen, die benötigt werden um den Punkt zu erreichen. Die Servos wollen doch wohl sowieso Winkel haben(!?). Berücksichtigen muss man, dass es auch negative Winkel gibt, also ob ich den Motor in die eine oder andere Richtung drehen lasse. Wenn ich das für eine Achse habe, würde ich das für die andere Achse auch noch machen. Hier wäre jetzt z.B. zuerst nur die X-Achse (Breite) und Y ist Höhe. Die Winkel entstehen hier zwischen diesen beiden Achsen. Dann bleibt noch die Z-Achse für die Tiefe. Z-Achse und X-Achse bilden einen rechten Winkel. Dazwischen befindet sich der Arm, bzw. die Armsegmente, wobei jedes wieder seine Winkel zur X-Achse und Z-Achse hat.

MfG

HaWe
29.09.2018, 10:45
@moppi, bin gespannt wie weit du kommst, alle Autoren verwenden ja 32bit float und sogar 64bit double, um die nötige Exaktheit zu erreichen. Für 2 oder max. 3 Achsen/Gelenke ist das ja auch überschaubar, für 6 wird es aber schon deutlich anspruchsvoller, auch mit Drehungen in der Arm-Richtungsdimension, nicht nur für Knicken.
Aber nimm ruhig mal meinen 6DOF Robot mit den obigen Maßen und Achsgeometrien, die ich ja schon gepostet habe, sowie später dann auch anpassungsfähig für andere Arm-Geometrien vom 5- oder 6DOF-Typ, die davon abweichen:
bin sehr neugierig, was du hier für FK- und IK-Libs entwickeln kannst!

Moppi
29.09.2018, 22:23
Ja tut mir leid, dass es Dir zu schwierig ist!

Das andere mit 256Bit Quaddouble rechnen müssen, heißt ja noch lange nicht, dass es nicht auch anders möglich wäre. Warum tun die anderen denn mit 32Bit Float und 64Bit Double - Typen rechnen? Was ist der Grund dafür? Willst Du es wissen? Ich sage es Dir: weil sie es nicht anders können oder weil sie es nicht anders können müssen.

Welche Genauigkeit hat denn so ein Motor? Wie genau solls denn sein? Auf ein Zehntel Millimeter? Ich bezweifle stark, dass das mit so einem Teil möglich ist!

Man stelle sich nur mal vor, dass man 1991 in 8Bit-Rechenoperationen Spiegelbilder in Kugeln in Echtzeit berechnet hat und dabei das Ganze noch auf den arschlangsamen Grafikkarten ausgegeben, wobei das dann das war, was die meiste Zeit verschlungen hat. Und dennoch war es flüssig möglich. - Klar auch mit dem ein oder anderen gerissenen Trick, ob mathematisch oder optisch. Obwohl, auch wie bei Doom - weil ich das schon mal anführte - auch mit einfachen 8 Bit vom Prinzip keine 3D-Welt berechnet werden konnte. Dafür musste man auch dort mit mindestens mit Nachkommastellen rechnen, was nur nicht wirklich ging, weil es keinen Co-Prozessor gab, mit dem man hätte in einem Rutsch einen Punkt im Raum berechnen können. Also was jetzt dann, gab es diese Spiele dann gar nicht, bilde ich mir das nur ein und viele andere haben einfach irgendeine Fata Morgana gesehen und sich was vorgemacht? - Natürlich nicht! Man kann auch mit 8-Bit Datentypen durchaus auf mehrere Nachkommastellen genau rechnen. Zum Glück ist das ja heute dann so nicht mehr nötig.

Es soll nur zeigen, dass man auch anders zum Ziel kommen kann, als nur auf irgendwelche Libs zu hoffen, die das richten werden.

Ich will Dir auch nichts aufschwatzen, wollte nur behilflich sein, mal eine andere Denkrichtung einzuschlagen. Wenn ich es bräuchte, würde ich mich damit auch auseinandersetzen. Tue ich aber eben jetzt nicht. Und in fünf Minuten ist das auch nicht erledigt, weil ich diese Problemstellung noch nie hatte. Da würde ich auch von vorne anfangen.


MfG

HaWe
30.09.2018, 10:04
es ist weniger eine Frage, ob man nicht auch mit int- oder long-basierten sin/cos/tan- und den entsprechenden arcus-Umkehrfunktionen arbeiten könnte, es ist eher eine Frage, wie man die Bewegung an einer Achse auf die nachfolgenden 3,4,5 Achsen weiterrechnet (das ist in dieser FK-Richtung eher vergleichsweise einfach), die Frage ist vor allem, wie man eine Soll-Position auf die mögliche(n) Stellung(en) der einzeln, nicht ganz frei beweglichen Achsen zurückrechnet (IK). Durch die Verkettung wird aus kleinen Fehlern am Anfang zum einen eine exponentielle Fehlervergrößerung bei den abhängigen Armgliedern, und zum anderen ist die IK-Rückrechnung bei 6 Armgliedern nicht mehr trivial und auch nicht eindeutig, und kann nur dann sinnvoll gelöst werden, wenn man den gesamten Arbeitsraum für alle erdenklichen Stellungen kennt.

Der Ansatz über Matrizen ist daher naheliegend und enleuchtend, auch wenn mir die Mathematik zu komplex für mein Verständnis ist:
Matrizen bieten sich deshalb sehr gut an, weil sie die Raumkoordinaten repräsentieren und die Bewegungsrichtungen, quasi tabellarisch zusammengefasst aus linearen Einzelpositionen und Einzel-Bewegungs-Vektoren. Das schöne bei Matrizen ist, soweit habe ich es verstanden, dass man sowohl eine geradlinige als auch eine Dreh-Bewegung als einfache Matrizenmultiplikation begreifen kann, es werden (sehr einfach ausgedrückt) nur andere Zeilen und Spalten miteinander multiliziert, einmal die linearen Positionswerte, und einmal die durch sin/cos- oder Winkelwerte (Bruchteile von Pi) eingetragenen Rotationswerte.

Man verkettet also alle Armglieder samt ihrer Rotations- und Stellungsmöglichkeiten über ein Matrizensystem, und über Matrizenmultiplikation erhält man bei gegebenen Winkeln eine Endstellung für die FK, ebenfalls als Matrize.

Hat man für die IK eine Anfangs- und eine eine Endstellung, die es zu erreichen gilt (beide als Matrizen), so wendet man nun exakt die gleichen Matrizenoperationen wie in der FK Hinwärtsrichtung an, allerdings invers, d.h. mit den inversen Bewegungsmatrizen, und zum Berechnen der Inversen Matrizen verwendet man u.a. deren Determinanten; Schritt für Schritt arbeitet man sich damit zu der Anfangsmatrix vor. Es ist wie eine Multiplikation in der FK Hinwärts-Richtung und eine Division in der IK-Rück-Richtung, und Division ist Multiplikation mit dem Inversen Element, also auch wieder Multiplikation:

theoretisch ist mir das klar, nur die Matrix-Mathematik dafür ist mir zu komplex. Es gibt dafür bewährte Konzepte (siehe Denavit–Hartenberg), doch für so etwas fehlt mir die mathematische Erfahrung und Kenntnis. Ich bezweifle auch ehrlich gesagt sehr, dass du, moppi, es ohne Matrizen schaffen könntest, was die IK Richtung angeht, aber lasse mich sehr gerne überraschen.

Mxt
30.09.2018, 10:38
Es ist nicht so, dass es da nur einen Ansatz gäbe.

Hier wird das für Anwendungen in der Computergrafik ein wenig beschrieben, gilt aber auch so für Roboter
https://wwwcg.in.tum.de/fileadmin/user_upload/Lehrstuehle/Lehrstuhl_XV/Teaching/WS10_11/Proseminar_Seminar/Talks/Benedikt_Hirmer.pdf

Was Moppi da andeutet ist im Prinzip der "analytische Ansatz" wie da in 3.4 beschrieben. Geht eventuell in CCD über, siehe Abschnitt 3.6.1.

Die oben verlinkten fertigen Lösungen verwenden die Methode, die da in 3.5.x beschrieben ist. Diese Jakobi-Matrizen funktionieren ein wenig anders. Sie geben im Prinzip an, wie sich der Tool-Center-Point ändert, wenn sich ein Gelenkwinkel ändert. Es ist quasi die Ableitung der Vorwärtskinematik. Die muss man dann invertieren, was ein Näherungsverfahren braucht, weil meist nicht invertierbar. Dann wird iterativ die IK-Lösung gesucht, wie im Link beschrieben.

Dann gibt es auch noch die Variante über halbwegs normale numerische Löser für Gleichungssysteme. Das ist auch wieder iterativ und braucht Rechenleistung.

HaWe
30.09.2018, 11:07
ja, klar gibt es nicht nur 1 Weg, aber eben bewährte und weniger bewährte. Meinetwegen auch noch 1 oder 2 neben Denavit–Hartenberg.
Aber die iterativen Lösungen scheiden faktisch bei >3DOF aus.

Zu moppis Ansatz mit integer-Arithmetik habe ich aber schon in einem anderen Topic etwas geschrieben:

Dabei muss man auch wissen, dass floats oder deren int16-Repräsentationen oft nicht genau genug sind, um bestimmte Berechnungen zu lösen (wie z.B. Matrix-Determinanten) und dadurch extremst falsche Ergebnisse liefern, daher muss man dann zwingend double verwenden.
Ich hatte schon oft bei meinen ersten Gehversuchen mit Matrizen mit dem Mega2560 (8bit-AVR, kann nur float, kein double) das "unerklärliche" Ergebnis, dass oft Determinanten einen Wert von deutlich größer null hatten (z.B. ein- oder zweistellig positiv), per float berechnet, obwohl die Matrizen antisymmetrisch waren oder ihre Zeilen nicht linear unabhängig, also die det(M) Null hätten sein müssen. Man kann eine Matrix mit Determinante Null aber nicht invertieren (genausowenig wie man durch Null dividieren darf), und die linearen Gleichungssysteme sind bei det(M)=0 nicht lösbar, und das falsche Ergebnis mit floats hätte dies fälschlich erwarten lassen.
Erst double-fp auf 32-bit ARMs erbrachte dann die korrekten Ergebnisse.

Dennoch, ish suche ja eine Lib als Lösung, und wenn moppi meint er kann das mit seinem Weg machen, ist es mir ntl absolut recht, und ich warte dann gerne auf seine fertige Lib 8)

Mxt
30.09.2018, 11:14
Ja, das hat dann weitreichende Bedeutung.

Der analytische Ansatz funktioniert ja nur für konkrete Roboter. Je nach Form des Arms, muss man die Dreiecke anders setzen. In der Regel braucht man auch Fallunterscheidungen, weil man je nach Gelenkstellung die Dreiecke anders setzen muss. Es ist aber das einzige bekannte Verfahren, die IK ohne Iteration zu lösen.

HaWe
30.09.2018, 12:07
Eben: es geht also bei float vs. double nicht (nur) um Genauigkeit des Endergebnisses, sondern u.U. sogar tatsächlich darum, ob das Problem überhaupt grundsätzlich lösbar ist.

Der analytische Ansatz funktioniert aber dennoch für viele verschiedene Roboterarm-Typen, wenn man anfangs die Geometrien (Winkel, Gliedlängen) definiert, die dann in die in der Lib mit ihren allgemein gehaltenen Matrizen mit den entsprechenden Platzhaltern per user-Interface-Funktionen eingesetzt werden.


PS, es hat auf meine Anfrage hin inzwischen jemand etwas "in Arbeit"...
https://github.com/henriksod/6DOFLib/tree/master/src
bin sehr gespannt... 8)

Moppi
30.09.2018, 12:09
Da war noch was, durch Zufall gerade gefunden:

https://www.roboternetz.de/community/threads/58800-Suche-Hilfe-bei-Kinematik-%286-Achs-Roboter%29

Mxt
30.09.2018, 12:10
es geht also bei float vs. double nicht (nur) um Genauigkeit des Endergebnisses
Ich glaube, das gehört in einen anderen Thread.

Ich glaube da hast du etwas noch nicht verstanden.

Analytischer Ansatz bedeutet eben den Verzicht auf die Platzhalter sondern die Aufstellung geschlossener Formeln speziell für einen Arm. Meines Wissens nach, wäre das die einzige Methode, um bei IK um Iterationen herumzukommen. Nicht Lösbarkeit zeigt sich dort dann in Division durch 0, unglültige Parameter bei Winkelfuntionen usw.

Deswegen schreibe ich ja, eine analytische Lösung, die sich über Eingabeparamter parametrieren lässt, wäre von allgemeiner Bedeutung. Meines Wissens nach gibt es das noch nicht.

Allerdings gibt es bei konkreten Roboterarmen noch eine zweite Ebene möglicher Unlösbarkeit. Ab 5-DOF ist ja, je nach Konstruktion, die Gelenkstellung des Arms aus dem TCP nicht mehr eindeutig herleitbar. (Analoges Beispiel: Man kann seine Hand auf der selben Position halten, aber den Ellenbogen dahinter bewegen.) Wenn jetzt ein Arm sein Werkzeug z.B. auf einer Linie bewegen soll, reichen für die einzelnen Punkte auf der Linie nicht mehr beliebige IK-Lösungen, man muss die ganze Linie mit konsistenten Ellenbogenpositionen fahren können.

Moppi
30.09.2018, 12:24
Also Arduino kann cos, tan und sin. So weit ich gesehen habe mit Double. Ich denke mir, dass die Entwickler der Atmegas wissen, warum. Damit sollte man schon eine ganze Ecke weit kommen.


es ist eher eine Frage, wie man die Bewegung an einer Achse auf die nachfolgenden 3,4,5 Achsen weiterrechnet

Weiß ich bis jetzt auch nicht. Ich denke mir aber, dass sich vielleicht eine gemeinsame Basis finden lässt, eben was, was für jeden Motor Gültigkeit hat. Dann könnte man vielleicht alle nacheinander durchrechnen.

Ob sich Matrizen besser eignen würden, vermag ich nicht zu sagen. Man kann da sicherlich verschiedene Wege einschlagen. Allerdings hat man ja bereits sämtliche Winkel vorliegen, jederzeit. Winkel müssen nur neu berechnet werden, wenn sie verändert werden sollen. Addition und Subtraktion ist dort auch kein Geheimnis.

Am Ende kommt es drauf an, was Du machen willst. Es gibt einfache Lösungen, da wird der R-Arm angelernt. Dann führt er immer dasselbe aus. Dann kann man Teilbewegungen anlernen und kombinieren. Auch wieder eine Lösung. Dann hast Du ja jetzt diese Sache: ich kenne einen Punkt mit seinen Koordinaten und nun Blackbox sag mir bitte, in welchem Winkel jeder Motor zu steuern ist, damit ich den Zielpunkt erreiche.


MfG

HaWe
30.09.2018, 12:35
das verstehe ich anders:
analytische Geometrie verwendet ja gerade auch Matrizenoperationen, und um IK auszurechnen, dazu brauchst du u.a. die Inversen von den Ausgangsmatrizen.
Matrizen-Inverse existieren aber nur, wenn die Determinanten ungleich Null sind, und die det(M) gehen auch in die Berechnung der Inversen Matrizen mit ein.
Falsche det => falsche Inverse => Laufzeitfehler oder Rechenfehler per falscher Ergebnisse oder nans (Division durch Null, auch ohne Matrizen an dieser Stelle ntl., z.B bei Division durch sin(x) wenn x=pi).
@mxt: In den Matrizen stehen aber u.a. auch die Teilarm-Längen und die Orientierung der Drehachsen, und die kann man - trotz geschlossener Formeln - variabel halten pro Anwendungsfall.

@moppi: AVR Arduinos aber können kein double, das ist bei denen identisch mit float!!

Aber die Diskussion können wir uns eigentlich sparen, mein Ziel ist es ja nicht, so etwas selber zu programmieren, allein die Diskussion zeigt ja die Kompliziertheit überdeutlich: mein Ziel ist es, eine fertige Lib zu nutzen, egal ob von Henrik, von dir, mxt, oder von moppi 8)

was das Ziel ist, habe ich indes ja bereits mehrmals geschrieben:


Beide Richtungen sind also wichtig:
a) Eingabe aller Einzelwinkel => Endposition des Greifers samt seiner Stellung (Eulerwinkel yaw, pitch, roll),
b) Eingabe einer Raumkoordinate samt Winkelstellung des Greifers => Berechnung aller Einzelwinkel

Mxt
30.09.2018, 12:35
Da kommt halt zweimal das Wort "analytisch" in etwas unterschiedlicher Bedeutung vor.

Im oben verlinkten PDF heißt es

Die Idee hinter diesem Ansatz ist es das Problem geometrisch mittels Kosinussatz zu lösen
Geht ganz ohne Matrizen. Aber eben nicht allgemein formulierbar.

Aber egal. Das Github-Projekt ist der eben schon zitierte Ansatz mit der Jacobi-Matrix. Und im Prinzip das, was alle von mir verlinkten fertigen Lösungen auch machen. Könnte sein, dass der Code auch irgendwie von der Matlab Vorlage abstammt. Kommt mir teilweise vor, als hätte ich Teile davon schon mal gesehen. Verwendet übrigens float, aber ich denke, das ist ok.

HaWe
30.09.2018, 13:07
Ja, sicher geht es auch ohne Matrizen, Matrizen "formalisieren und vereinen " ja nur einzelne "normale" trigonometrische Berechnungen, die man auch für sich genommen einzeln durchführen kann, nur dadurch eben "handhabbarer" auch für Rückrechnungen, und daher sind Matrizen für die, die was davon verstehen, universeller und einfacher zu verwenden, samt aller ebenfalls per Matrizen formulierter Hilfs-Libs (wie Eigen und Denavit–Hartenberg etc.).

Und ja, der Autor hatte bereits auf eine ihm bekannte und von ihm genutzte MATLAB Lösung hingewiesen. Der Link zur Denavit–Hartenberg Konvention stammt in diesem ZUsammenhang auch von diesem Autor, diese beschreibt ja v.a. die Achs- und Arm-Winkel-Stellungen in Matrizenschreibweise.

Float reicht übrigens auch für die FK, nur für die det und die Inversen für die IK wird man eher double brauchen. Darüber hatte ich schon mit dem Autor gesprochen. Die IK aber ist ja noch überhaupt nicht fertig.

Moppi
30.09.2018, 21:45
Vorgehensweise würde ich mal so versuchen:

Voraussetzung, das Ziel ist mit der Armlänge überhaupt zu erreichen.

33667

Wie könnten die einzelnen Armsegmente nun ausgerichtet werden?

Das kann man so machen, dass der Anfang meiner geraden Linie, der Basispunkt (Bezugspunkt/Standpunkt)
meines Arms ist. - Das kann nur der erste Drehpunkt sein. Das Ende meiner geraden gedachten Linie ist
das Gelenk am Greifer (hinzu kommt die Greiferlänge, muss berücksichtigt werden bei der Gesamtlänge).
Nun dreh ich alle Gelenke so, dass der Anfangs und Endpunkt auf meiner gedachten geraden Linie zu liegen kommen.
Aber nicht irgendwie, sondern so, dass genau die Entfernung überbrückt wird, die ich bis zum Zielpunkt habe.


1. Möglichkeit jetzt: Die Summe aller einzustellenden Winkel hat eine bestimmte Größe.
Die gedachte Linie (gerade Entfernungslinie) kann man als Durchmesser eines Kreises sehen.
Die Summe aller Winkel an den Drehpunkten müsste im Zusammenhang mit dem Durchmesser eines Kreises stehen.
Die Winkel sind aber auch abhängig von den Segmentlängen des Arms. So dass man das insgesamt vielleicht
über Dreiecke ausrechnen kann.

2, Möglichkeit: Wenn man die Segmente einstellt, so dass sie eine bestimmte Strecke überbrücken, kann man die Winkel messen.
Die Winkel müssen im Zusammenhang mit der überbrückten Strecke und den Segmentlängen stehen. Wenn das ein
paar mal wiederholt wird, sollte sich etwas zu erkennen geben, womit ich was anfangen kann und also dann
die Winkel für die Überbrückung jeder beliebigen Strecke berechnen kann. Vielleicht nimmt man dazu Pappstreifen, bindet
die an den vorgesehenen Drehpunkten zusammen und probiert das auf einem Tisch mal aus.

Die Lösung dafür parat habe ich jetzt auch nicht, bin viel zu lang aus der Materie raus. Mein ehemaliger Mathelehrer
wüsste sicher weiter.

Wenn ich das aber weiter spekuliere, denke ich, dass die Winkel an den Drehpunkten zwar immer abhängig von den
vorhergehenden Segmentlängen sind, dass sie aber in einem festen Verhältnis zur überbrückenden Strecke stehen.
Diese Verhältnis würde man aber nur einmal ausrechnen, weil sich die Segmentlängen ja nicht dauernd ändern. Man könnte
theor. also von der Länge direkt auf die einzelnen Winkel schließen.




MfG

HaWe
01.10.2018, 10:07
ja, das klingt nach einem guten Ansatz, eben noch ein nur theoretisches Konzept, wobei noch rechts/links-Rotationen in manchen Teilarm-Achsen zu berechnen wären, nicht nur Abwickeln rauf/runter, samt Berechnung der Orientierung des Greifers (Schachfiguren senkrecht von oben mit den Fingerspitzen und Öffnung zur Seite, eine Flasche von beliebigen Seiten waagerecht mit der ganzen Hand, für schräg liegende Objekte mit einer diagonalen Position annähern und greifen...)
Aber wenn du so eine Lib mal in einem ersten Teststadium fertig hast, sag bitte gleich Bescheid, dann teste ich es hier gleich aus!

HaWe
12.01.2019, 11:50
inzwischen hat sich herausgestellt, dass 5 DOF zu wenig sind, gebraucht werden 6 DOF für den Arm (auch für seitwärts-Drehung im Unterarm für die Zange), unabhängig von zus. 1 DOF (auf/zu) für die Zange - im Wesentlichen ähnelt er "großen" Kuka Roboterarmen:




\ /
\ / finger length 50 mm
|-| 6 claw spread
| metacarpal length 55 mm
|
o 5 metacarpal rotate
|
| wrist length 95 mm
|
v 4 wrist tilt
|
| forearm segment2 50 mm
|
o 3 forearm rotate
|
| forearm segment1 100 mm
|
v 2 elbow tilt
|
|
| upper arm length 180 mm
|
|
v 1 shoulder tilt
|
| shoulder height 15 mm
o 0 trunc rotate horiz
|
| trunc base 85 mm
|
___ floor




Leider hat der oben erwähnte Autor aber bisher seine angekündigte Lib weder für 5 noch für 6 DOF weiter entwickelt, es ist in den allerersten Anfängen stecken geblieben. Vermutlich ist er selber überfordert, auch ich kriege es ja mit meinen rudimentären Kenntnissen über Matrizen und anayltische-Geometrie nicht hin.
Also noch mal zurück auf Los:
Wer kennt brauchbare, auf den oben skizzierten Arm anwendbare Libs, wo man nur die Länge der Arm-Segmente und die Orientierung der Knick-/Dreh-Achsen definieren muss, und dann FK und RK Funktionen frei nutzen kann?