quorti Geschrieben 23. Mai 2013 Geschrieben 23. Mai 2013 Hallo zusammen, ein Kumpel und ich sind im Rahmen eines kleinen Projektes dabei eine CNC-Fräse an den Achsen mit Schrittmotoren auszustatten, welche mit einem Arduino verbunden sind. Der Arduino bekommt seine Befehle vom Parser, der wiederum seine Kommandos von G-Code kriegt. Da wir nur eine dreiachsige Fräse haben können wir keine Bogen fahren und somit den G02 von G-Code nicht ausführen. Dafür bin ich seit einiger Zeit dabei die Koordinaten einer Kugel in das Kartesische Koordinatensystem zu übersetzen. Gegeben (vom Parser) werden: der Startpunkt, der Endpunkt und der Mittelpunkt. Zum Testen habe ich eine kleine Klasse, die mir die Punkte in ein dreidimensionales Koordinatensystem einzeichnet. Soweit so gut - und auf der x/y-Ebene funktioniert das wunderbar. Soviel kurz zu Einleitung. Jetzt mein Problem: kommen z-Werte dazu (^= bewegen wir uns im dreidimensionalen Raum) gibt es auf der x/z- und auf der y/z-Ebene ein gestrecktes "S" (sieht eher wie das Integral-Zeichen aus), wenn man direkt von oben drauf schaut (logischerweise sollte der Kreisbogen dann wie eine Linie aussehen). Ich gehe bei der Berechnung so vor, dass ich anhand der zwei gegebenen Punkte zu allererst den Radius berechnen. Dann berechne ich die Winkel Berechnung "winkel" (Winkel zwischen z-Achse und dem Punkt): winkel = 180*Math.acos(((_p3dPointMin.z - _p3dUrsprung.z) / _intRadius))/Math.PI Berechnung phi (Winkel zwischen x-Achse und dem Punkt): if(point.x > 0) phi = Math.atan(point.y/point.x); if(point.x == 0) phi = Math.signum(point.y)*Math.PI/2; if(point.x < 0 && point.y >= 0) phi = Math.atan(point.y / point.x) + Math.PI; if(point.x < 0 && point.y < 0) phi = Math.atan(point.y / point.x) - Math.PI; Die Berechnung dieser beiden Winkel führe ich für beide gegeben Punkte durch. Damit habe ich dann insgesamt vier Winkel: 1. winkelVon 2. winkelBis 3. phiVon 4. phiBis Dann schaue ich bei welchem der "Hauptwinkel" die Differenz zwischen Von und Bis höher ist und nehme diese Differenz als die Anzahl der zu laufenden Schritte und setzte die Schrittgröße dieses Winkels auf 1. Die Schrittgröße des anderen "Hauptwinkels" errechnet sich dann über dessen Differenz geteilt durch die Anzahl der zu laufenden Schritte. Habe ich diese Werte, laufe ich in einer Schleife von 0 bis zur Anzahl der Schritte und erhöhe "winkel" und "phi" jeweils um deren Schrittgröße. Für jede "Winkelkombination" errechne ich dann wie folgt den jeweiligen Punkt: x = _p3dUrsprung.x + _intRadius * Math.sin(Math.PI*winkel/180) * Math.cos(Math.PI*phi/180); y = _p3dUrsprung.y + _intRadius * (Math.sin(Math.PI*winkel/180)) * Math.sin(Math.PI*phi/180); z = _p3dUrsprung.z + _intRadius * Math.cos(Math.PI*winkel/180); Wobei _p3dUrsprung der Kugelmittelpunkt und _intRadius der Radius der Kugel sind. (Darauf werden die Werte gerundet und es wird geprüft, ob sie innerhalb der angegeben Toleranz liegen (also für die Fräse abildbar sind), aber das klammere ich an dieser Stelle erstmal aus). Als letztes schreibe ich diesen Punkt in eine ArrayList, welche am Ende dann zurückgegeben wird, wenn die Schleife fertig gelaufen ist. Da die x/y-Ebene korrekt dargestellt wird ist meine Vermutung, dass das Problem entweder in der Berechnung von "winkel" oder in meiner Schleifenlogik liegt. Ich wäre äußerst glücklich, wenn mir vielleicht jemand weiterhelfen könnte. Achja: geschrieben ist das Ganze aktuell in Java, aber hier geht es eher um den Algorithmus, daher habe ich das mal hier gepostet. LG und schon im Voraus vielen Dank, quorti (PS: SuFu habe ich benutzt, aber nichts hilfreiches gefunden) Zitieren
Gast runtimeterror Geschrieben 24. Mai 2013 Geschrieben 24. Mai 2013 Hi, kannst du deine Zielsetzung etwas zusammenraffen? Es klingt vom Thema her nicht allzu kompliziert, ich kann deiner Beschreibung allerdings kaum folgen. Ps: schau dir mal Math.atan2 () und Math.toRad ()/toDeg () an. Zitieren
quorti Geschrieben 24. Mai 2013 Autor Geschrieben 24. Mai 2013 Hi, kannst du deine Zielsetzung etwas zusammenraffen? Hi runtimeterror. Mein ziel ist quasi einen Kreisbogen mit linearen Koordinaten abzubilden. So ein bisschen wie beim Malen nach Zahlen, dass die Punkte mit Linien verbunden (nahezu) einen Kreis ergeben. Zitieren
Gast runtimeterror Geschrieben 24. Mai 2013 Geschrieben 24. Mai 2013 Es gibt mehrere Möglichkeiten in Abhängigkeit davon, welche Informationen gegeben sind. m = Mittelpunkt des Kreises/der Kugel right = ein Vektor in der Ebene in der sich der Kreis befindet und mit der Länge des Kreisradius (m + right = Position deines Punktes bei phi = 0°) up = ein Vektor in der Ebene in der sich der Kreis befindet und mit der Länge des Kreisradius (und der senkrecht zu right steht) (m + up = Position deines Punktes bei phi = 90°) phi = der Winkel im Bogenmaß Die Anzahl der Dimensionen ist hierfür irrelevant p = m + right * cos(phi) + up * sin(phi); Oder in Java für 3D p.x = m.x + right.x * Math.cos(phi) + up.x * Math.sin(phi); p.y = m.y + right.y * Math.cos(phi) + up.y * Math.sin(phi); p.z = m.z + right.z * Math.cos(phi) + up.z * Math.sin(phi); Das ist die einfachste Form. Die Frage ist, welche Informationen du über die Lages des Kreisbogens im Raum besitzt. Es gibt auch die Möglichkeit einen bekannten Punkt um eine Achse im Raum zu rotieren. Hierfür wird der Mittelpunkt und die Achsrichtung/-Orientierung des Kreises benötigt. Zitieren
Gast runtimeterror Geschrieben 24. Mai 2013 Geschrieben 24. Mai 2013 Gegeben (vom Parser) werden: der Startpunkt, der Endpunkt und der Mittelpunkt. Ah - das hatte ich überlesen. Ich schau mal, ob ich das auf die Schnelle hinbekomme ... Zitieren
Gast runtimeterror Geschrieben 24. Mai 2013 Geschrieben 24. Mai 2013 s = Startpunkt (gegeben) e = Endpunkt (gegeben) m = Mittelpunkt (gegeben) u = s - m v = e - m axis = u X v = (Kreuzmultiplikation; Achse, um die sich der Kopf dreht) angle = acos((u * v) / (u.length * v.length)) = Winkel zwischen Start und Endposition (* = Skalarprodukt) right = u up = (axis X right).normalize() Also: (fiktive Vektor-Klasse, aus dem Kopf, ungetestet!!, auf die Schnelle -> muss weg ) Vector3D u = new Vector3D(s.x - m.x, s.y - m.y, s.z - m.z); Vector3D v = new Vector3D(e.x - m.x, e.y - m.y, e.z - m.z); double angle = Math.acos((u.x * v.y + u.y * v.y + u.z * v.z) / (u.length() * v.length())); double radius = u.length(); Vector3D right = u; Vector3D up = Vector3D.xmul(axis, right).normalize().mul(radius); for (int i = 0; i <= STEP_COUNT; i++) { double phi = angle * i / STEP_COUNT; p.x = m.x + right.x * Math.cos(phi) + up.x * Math.sin(phi); p.y = m.y + right.y * Math.cos(phi) + up.y * Math.sin(phi); p.z = m.z + right.z * Math.cos(phi) + up.z * Math.sin(phi); pointList.add(p); } normalize() teilt den Vektor durch seine Länge, welcher dann eine Länge von 1 hat. xmul() ist das Kreuzprodukt zweier Vektoren Der Radius wird dem Startpunkt entnommen! Wenn der Endpunkt einen anderen hat -Pech Viel Erfolg! Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.