Wenn Linien "line_detector" erkannt: Ereignisliste

Alles rund um TX(T) und RoboPro, mit ft-Hard- und Software
Computing using original ft hard- and software
Forumsregeln
Bitte beachte die Forumsregeln!
Antworten
Alter Fischer
Beiträge: 3
Registriert: 13 Nov 2022, 18:25

Wenn Linien "line_detector" erkannt: Ereignisliste

Beitrag von Alter Fischer » 15 Nov 2022, 18:42

Hallo zusammen,
seit neuestem arbeite ich mit dem TXT 4.0. Cooles Teil!
Mein Problem:
Mit dem Block - Wenn Linien "line_detector" erkannt: Ereignisliste - erkennt der Controller mit Hilfe der Kamera sehr zuverlässig Linien.
Jedoch, wenn die Linie nicht mehr da ist (z.B. weil der Roboter über eine Kreuzung von Linien hinweg gefahren ist) wird die letzte Info über die Linie, Position, Breite etc., nicht gelöscht.
Mit anderen Worten: Es gibt keinen Block - Wenn KEINE Linie... -
Aber wie lösche ich eine Variabel, die mir die Position der Linie im Detektor angibt, sobald die Linie nicht mehr da ist?

Die einzige Möglichkeit, die ich sehe ist, dass ich dann doch im Hauptprogramm abfragen muss, ob eine Linie da ist. Aber dann kann ich mir die Abfrage im Interrupt auch sparen, in der ich die Lage der Linie in einer Variablen abspeichere.

Jemand dazu eine Idee?

Ein zweites "Luxus-" Problem ist, dass ich meine Liniendetektoren nicht selbst benennen kann. Die werden automatisch mit line_detector, line_detector2, line_detector22, line_detector222 etc. benannt. Das ist leider sehr mühselig, weil ich ihnen dann keine sinnfälligen Namen geben kann: Links, Rechts, Unten, Oben wären viel einfacher zuzuordnen.

Oder übersehe ich da eine Möglichkeit?

Vielen Dank für eure Antworten.
Einen schönen Tag
Andreas

Cody
Beiträge: 17
Registriert: 24 Apr 2021, 03:25

Re: Wenn Linien "line_detector" erkannt: Ereignisliste

Beitrag von Cody » 16 Nov 2022, 14:07

Hallo Andreas,

der Code in deinem 'Wenn Linien "line_detector" erkannt: Ereignisliste' - Block wird als Callback genutzt, welches ausgeführt wird, wenn eine Linie erkannt wird. Daher wird der Code nicht ausgeführt, wenn es gerade keine Linie gibt. Das Problem ist jetzt aber, dass du in deiner Hauptschleife nicht abfragen kannst, ob gerade eine Linie vorhanden ist. Alle Blöcke unter der Rubrik "USB", die den Block "Ereignis" enthalten, sind nur innerhalb eines Callbacks einsetzbar, weil "Ereignis" der Parameter des Callbacks ist (event im python code); "Ereignis" ist also außerhalb dieses Blocks nicht definiert.

Deine Möglichkeit, die Linienposition doch in der Hauptschleife auszulesen, wäre über eigenen Python Code. Du kannst mit dem Block "get frame from" die Frames auslesen und dann selbst dort nach Linien suchen. Ist allerdings etwas umständlicher.

Die Methode, die ich nutzen würde, kommt ohne eigenen Python Code aus, du brauchst lediglich eine weitere Variable.
In deinem 'Wenn Linien "line_detector" erkannt: Ereignisliste' - Block speicherst du nicht nur die Lage der Linie in einer Variablen, sondern auch die aktuelle Zeit. In deiner Hauptschleife überprüfst du dann, ob im letzten Frame eine Linie war. Dafür liest du den Zeitstempel der letzten Linienposition aus, addierst eine Zeit zwischen 1 - 2 Frames (bei 15 fps ist 1 Frame 67 ms) und vergleichst diesen Wert mit der aktuellen Zeit. Ist der Wert kleiner, dann ist das letzte Update länger als 1 Frame her, d.h. im letzten Frame wurde keine Linie gefunden. Ist der Wert größer, gab es eine Linie und du kannst fortfahren und irgendwas mit der Linienposition machen.

Zu deinem Luxusproblem. Aktuell ist mir auch keine Möglichkeit bekannt, wie man die Liniendetektoren selbst benennen kann, aber ich gehe davon aus, dass das in einem der nächsten Updates kommt.
Allerdings heißen die bei mir line_detector, line_detector2, line_detector3, line_detector4, ...
Aber vielleicht benutzt du ja eine andere Version (meine ist 6.0.14).

Ich hoffe, das hilft weiter. Aber vielleicht gibt es ja noch weitere Ideen.

Viele Grüße,
Cody
Dateianhänge
Testprogramm LineDetection
Testprogramm LineDetection
Bildschirmfoto 2022-11-16 um 13.50.37.png (142.66 KiB) 931 mal betrachtet

Alter Fischer
Beiträge: 3
Registriert: 13 Nov 2022, 18:25

Re: Wenn Linien "line_detector" erkannt: Ereignisliste

Beitrag von Alter Fischer » 16 Nov 2022, 17:55

Hallo Cody,
vielen Dank für deine schnelle und ausführliche Antwort.

Das ist ein schlüssiger Ansatz, mit dem Zeitstempel. Mir gefällt er.

Dass ich die "USB-Blöcke" im Hauptprogramm nicht verwenden kann, habe ich dann leider auch noch festgestellt.

D.h. jedoch, dass der line_detector Block noch verändert werden sollte in
Zustände -line_detector-: Ereignisliste
Wenn ich drei mögliche Striche im Inspektor angegeben habe, müsste grundsätzlich eine Ziffernfolge zurück gegeben werden mit einer 1 für Linie vorhanden und 0 für keine Linie. Also z.B. 1, 1, 0. Für die Einsen müßte dann die Möglichleit bestehen, die Parameter der entsprechenden Linien abzufragen.
Also nicht ein "Wenn" sondern ein "So ist es". Für jedes Frame wird ein entsprechendes Array erzeugt, egal, ob da nun ein Strich ist oder nicht...

Aber erstmal geht es sicher prima mit dem Zeitstempel!!!

Zum Luxusproblem: Wo finde ich die Version, die auf meinem Computer läuft.

Einen schönen Tag
Andreas

Cody
Beiträge: 17
Registriert: 24 Apr 2021, 03:25

Re: Wenn Linien "line_detector" erkannt: Ereignisliste

Beitrag von Cody » 17 Nov 2022, 15:17

Hallo Andreas,

es freut mich, dass dir die Lösung mit dem Zeitstempel gefällt.

Der Callback-Parameter Ereignis ist immer ein Array, das die gefundenen Objekte (in deinem Fall Linien) beinhaltet. Es wird aber nicht mit None's oder Ähnlichem aufgefüllt, sollten weniger Linien als im Inspektor angegeben gefunden werden.
Daher kann man ein Array mit fixer Länge (= Anzahl der gesuchten Linien) an Linien in einer eigenen Variablen sichern. Im Callback kopiert man dann die gefundenen Linien in dieses Array und setzt die übrigen Array-Elemente auf None.
In der Hauptschleife überprüft man dann wie gehabt, ob im letzten Frame mindestens eine Linie gefunden wurde. Wenn das der Fall ist, durchläuft man das Array bis zum ersten Auftreten von None.
LineDetection mit mehreren Linien
LineDetection mit mehreren Linien
Bildschirmfoto 2022-11-17 um 03.13.10.png (176.15 KiB) 783 mal betrachtet
Hier sieht man übrigens, wie man in der Hauptschleife Blöcke aus USB nutzen kann. In diesen Blöcken ist nur der Ereignis-Parameter problematisch. Wenn du ihn wie hier durch eine andere Liste ersetzt, kann man diese durchaus verwenden, um aus gespeicherten Objekten wie z.B. Linien Eigenschaften auszulesen.

Wenn man nur einen Parameter der Linien braucht, wie z.B. Position, Breite oder Farbe, dann kann man die entsprechenden Parameter direkt in einem Array sichern, ohne das ganze Linien-Objekt zu speichern. In Blocky kann es relativ umständlich sein, mit Objekten zu arbeiten.
LineDetection mit mehreren Linien, Sicherung nur eines Parameters
LineDetection mit mehreren Linien, Sicherung nur eines Parameters
Bildschirmfoto 2022-11-17 um 14.59.10.png (153.52 KiB) 783 mal betrachtet

Die Version findest du über die drei Balken in der oberen linken Ecke.
RoboPro Coding Version
RoboPro Coding Version
IMG_4E4FF2DB36A6-1 2.jpeg (64.7 KiB) 783 mal betrachtet

Alter Fischer
Beiträge: 3
Registriert: 13 Nov 2022, 18:25

Re: Wenn Linien "line_detector" erkannt: Ereignisliste

Beitrag von Alter Fischer » 26 Nov 2022, 11:30

Hallo Cody,
endlich bin ich wieder dazu gekommen mich mit dem Problem zu beschäftigen.

Grundsätzlich ist dein Programm sehr gut aufgebaut.
Jedoch habe ich jetzt einige Zeit mit einer Fehlermeldung gekämpft:
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'.
Wenn am Anfang eine Variable nicht deklariert wird, funktioniert der Vergleich zwischen dem alten und dem aktuellen Zeitstempel nicht.
Du hast das natürlich in dein Programm implementiert, aber ich hatte es ignoriert.

Vielen Dank.
Einen schönen Tag
Andreas

Antworten