max-4711 / libmirobot

Library to generate g code to control the (WLKATA) Mirobot. No official project and not affiliated to WLKATA at all.
MIT License
0 stars 1 forks source link

Arbeitet bei mir die Queue nicht vollständig ab #1

Closed dennisarmbruster95 closed 3 years ago

dennisarmbruster95 commented 3 years ago

Hey Max, hatte gesehen, dass du aus Stuttgart kommst, daher schreibe ich auf Deutsch. Jedenfalls möchte ich aktuell im Rahmen eines Projekts deine Mirobot Libary nutzen um mittels Netzwerk dem Mirobot eine Liste von Befehlen abzuarbeiten. Verbindung kann ich herstellen und Homeing funktioniert auch. Nun Gebe ich dem Mirobot eine Position an die er anfahren soll und tut dies auch. Gebe ich ihm nun die nächste Instruktion, tut er sie nicht mehr Anfahren. Hatte solch ein ähnliches Problem selbst bei der offiziellen API für Python. Es scheint, dass er kein Telegramm bekomme, dass er Fertig sei oder ähnliches. Es kommen zwar mehrere Status Updates mit der Information, dass er im IDLE sei, aber ändert das nichts am Verhalten. Ich bin mir unsicher, ob ichs verständlich formuliert habe, daher versuche ich es genauer anhand meines Codes zu erläutern. grafik Move und GotoZero rufen im wesentlichen nur die Funktion MoveToCartesian des Roboters (ISixAxisRobot) auf. Beim ersten Move bewegt er sich, und danach nicht mehr. Debugge ich das Ende des Abschnitts, kann ich folgende Queue sehen: grafik Und an diesem Zustand ändert sich nichts mehr. Ich weiß nicht ob Wlkata mit der Firmware was geändert hat oder warum sich dies so verhält, aber mit bisher keiner API kam ich weiter. Vielleicht ist es auch nur ein Fehler meinerseits zur Nutzung der API. Ich dachte auch daran einfach Sequentiell die Instruktionen zu übergeben und jedes mal so lange zu warten, bis der Roboter wieder im IDLE ist, aber hatte auch nicht geholfen.

Ich bedanke mich schonmal für die Mühe das durchzulesen und vielleicht kannst du mir bei diesem Anliegen helfen.

Mit freundlichen Grüßen,

@da84

max-4711 commented 3 years ago

Hi @da84 ,

freut mich, dass du meine Library verwenden möchtest! 🙂

Stuttgart ist nicht mehr ganz aktuell, da muss ich wohl mein Profil mal aktualisieren, aber Deutsch ist völlig in Ordnung 👍

Ich denke, ich habe dein Problem verstanden und auch schon eine Idee, woran es liegen könnte. Mein Mirobot ist gerade nicht aufgebaut, daher kann ich es gerade nicht prüfen, aber ich meine mich an ein Problem damit erinnern zu können: Nämlich, dass der Roboter manchmal den Status Idle zurückmeldet, obwohl er eigentlich noch in der Bewegung ist - und wenn man ihm dann sofort ein weiteres Telegramm sendet, dann verrenkt er sich und fährt in eine Position, in die er nicht fahren soll und aus der man ihn nur mit einem Reset wieder rausbekommt.

Aus diesem Grund habe ich in der Standardeinstellung eine Prüfung eingebaut, die bewirkt, dass die Library das nächste Telegramm erst sendet, wenn die vom Roboter gemeldete Position (die wird dafür automatisch zyklisch abgefragt) mit der beauftragten Position übereinstimmt. Lediglich eine kleine Abweichung wird toleriert - die Abweichung darf an keiner der Achsen 0.05 überschreiten. Ebenso meine ich mich erinnern zu können, auch mal das Problem gehabt zu haben, dass der Roboter am Ende seiner Bewegung eine zu hohe Abweichung hatte (ich glaube, ich musste ihn damals neu kalibrieren, um das Problem zu lösen).

Das offizielle Python-SDK kenne ich ehrlich gesagt gar nicht, als ich die Library hier initial gecoded habe, gab es das glaube ich noch nicht mal. Aber würde ich für nicht unwahrscheinlich halten, dass dort ein ähnlicher Mechanismus eingebaut wurde.

Um zu prüfen, ob mein Verdacht richtig ist: Kannst du mal prüfen, was für eine Position der Roboter dir in dem Telegramm zurückmeldet, in dem er den Idle-Status erreicht?

Das sollte wahlweise mit dem Debugger (Breakpoint in die Methode SendRobotStatusUpdate der Klasse SixAxisMirobot) oder noch einfacher mit dem Subscriben vom RobotStateChanged-Event des Roboters funktionieren.

Viele Grüße Max

dennisarmbruster95 commented 3 years ago

Guten Abend Max, Danke für deine ausführliche Antwort. Ich habe jetzt dann mal das über RobotStateChanged debuggt. Hier kommt ein Screenshot vom Triggern des Events, unmittelbar bevor IDLE true ist: grafik und hier folgt der nächste Aufruf mit IDLE als true: grafik

Grüße,

Dennis

PS: Ich mag zwar Python, aber eine gewisse Liebe für C# und Visual Studio habe ich schon entwickelt. Wäre da natürlich glücklich mit, wenn ich deine Lib nutzen kann.

dennisarmbruster95 commented 3 years ago

Beim Nächsten Aufruf sind die Werte jedoch unverändert: grafik

dennisarmbruster95 commented 3 years ago

Das Event wird weiterhin mit den gleichen Werten immer wieder getriggert.

dennisarmbruster95 commented 3 years ago

Habe testweise bei den oberen Thread.Sleep's mal eine Zeit von 20 Sekunden reingehauen und kam trotzdem nicht weiter.

max-4711 commented 3 years ago

Hi Dennis, die Library fragt, wenn der Roboter von sich aus nichts mehr schickt, zyklisch (müsste alle 15 Sekunden sein) den Status vom Roboter ab. Da ich mal annehme, dass der Roboter sich dann auch nicht mehr bewegt, dürfte das der Grund sein, warum das Event danach immer wieder mit den gleichen Werten kommt. Diese Situation (ein stehender Roboter mit gefüllter Queue und wiederkehrenden identischen Statustelegrammen) würde auch zumindest weiterhin zu meiner Vermutung aus meinem ersten Kommentar passen.

Die aus meiner Sicht kritische Frage ist: Was sind die Werte, mit denen du den Roboter beauftragt hast? Gibt es hier für einen der Werte eine Abweichung größer 0.05 verglichen mit den Werten, die du dann immer wieder bekommst? Dann wird die Library die Zielposition als nicht erreicht ansehen und mit dem Senden der nächsten Instruktion an den Roboter warten.

(Hier die betreffende Code-Passage, falls mit dem Debugger reinspringen möchtest: https://github.com/max-4711/libmirobot/blob/baf44e7beab6253ae559428e225ef3f8dff4162d/Libmirobot/Libmirobot/Core/RobotPositionParameter.cs#L96)

dennisarmbruster95 commented 3 years ago

Hab gerade mal ein Fork erstellt und die Stelle debuggt. Man sieht eine geringe Differenz: grafik

dennisarmbruster95 commented 3 years ago

Update: hab bisschen den Fork angepasst. Das Status Event wird nurnoch getriggert wenn sich der Wert geändert hat und sowas. Jedenfalls habs ichs inzwischen hinbekommen, dass er alles abarbeitet und wartet immer, dass der Roboter im IDLE ist. Jedoch dauert es eine gute Weile bis der Nächste Befehl ausgeführt wird. Werde mir dazu im Laufe des Tages mal anschauen wann die Einträge an den Mirobot übertragen werden.

Grüße

dennisarmbruster95 commented 3 years ago

Update: Das stocken kam von meinen Komponenten, hatte da noch die Sleeps vom ersten Screenshot drinnen.

Kurz meine Lösung des Problems zusammengefasst: Speichere Zustandsänderung bei RobotStateChangedEventArgs.IsIdle von true zu false und anderst ab, warte entspechende Veränderungen bis zur Befehlübergabe ab und ging.

max-4711 commented 3 years ago

Okay, freut mich, dass es jetzt funktioniert - und danke auch noch für dein Feedback!

Das Statusupdate-Event nur zu senden, wenn sich die Position wirklich verändert hat, klingt eigentlich nach einer guten Idee. Ich denke, das werde ich übernehmen.

Nur um sicherzugehen: Habe ich deinen letzten Kommentar jetzt insofern richtig verstanden, dass aber kein Fehler in der Library vorliegt, der behoben werden muss? Außerhalb der Library sollte eigentlich kein 'manuelles' zusätzliches Warten bzw. Prüfen auf IsIdle notwendig sein. Die Library soll schon selbstständig den nächsten Befehl in der Queue absenden, sobald der Roboter bereit ist 🤔

dennisarmbruster95 commented 3 years ago

Um das mit dem Statusupdate zu sehen, kannst ja ja meine zwei Commits dazu in meinem Fork anschauen: 1 und 2.

Doch irgendwo mit dem Timing des Sendens muss es in der Libary noch nicht richtig klappen. Er sendet da nachwievor etwas zu früh. Ich hab das jetzt nur von außen etwas umgangen, indem ich wie folgt vorgegangen bin: Habe 3 Boolean für den Status: IsReserved, IsMoving (anstatt IsIdle, liegt an der Strukur eines äußeren Projekts) und IsReady. IsReserved setze ich true, falls ich über deine API einen Befehl absetze und false, falls bei OnRobotStateChanged IsIdle von false auf true übergeht. IsMoving is das invertierte IsIdle, das beim OnRobotStateChanged Event übergeben wird. IsReady := !IsMoving && !IsReserved Nach jedem Befehl warte ich immer bis IsReady wieder true ist. (frech einfach while (!IsReady) ;)

Hab jetzt aber nicht zu viel an der Libary rumdoktoren wollen, weil mein Projekt den Mirobot bezogen eher proof of concept ist als etwas ganz großes. Aber vielleicht kann mein Ansatz in der Libary auch verwendung finden.

Liebe Grüße,

Dennis

max-4711 commented 3 years ago

Okay, dann noch mal vielen Dank für die Klarstellung. Ich hab meine library zwar schon auch selbst in zwei Projekten verwendet, das von dir beobachtete Verhalten ist mir dort aber nicht aufgefallen. Könnte allerdings daran liegen, dass ich dort jeweils eine eventgetriebene Architektur verwendet habe, könnte also sein, dass es dadurch "zufällig" gutgegangen ist. Wenn der Roboter mal wieder aufgebaut ist, werde ich mir das auf jeden Fall mal genauer anschauen.

Dir für dein Projekt noch viel Erfolg!

Viele Grüße Max

dennisarmbruster95 commented 3 years ago

Danke. Ich hatte auch mal in der Python API gelesen, dass WLkata auch eine neuere Firmware für den Mirobot aktuell verwendet und die wohl bei einigen dann grad mit älteren APIs für so Probleme sorgt. Kann ja auch vielleicht daran liegen.

Grüße. Dennis