<!> Totally outdated page <!>






Further Concepts

The following text is in German and was originally not intended to be released to public. It is some sort of a developer's daily notebook that reflects some of the To-Dos, possible improvements, bugs and concerns relating the toolbox. It is posted here for German developers to get some sort of understanding, what has already been tried or is considered for future ideas. Things that are mentioned here do not need to be posted as bug report and should be read carefully before trying to change certain toolbox issues…

The following text file has grown over a long time (more than half a year now), so some of the issues may not be as imported now as they were some time during development…


NXT Name

Sofern der NXT Name bekannt ist, sollte dieser an das NXT Handle hinzugefügt werden. Idee war das automatische Einrichten einer Bluetoothverbindung.


NXT handle Verarbeitung in High Level Funktionen

Aufgrund der Multi-NXT-Verarbeitung sollten die High Level Funktionen auch die Angabe eines spezifischen NXT Handles berücksichtigen. Wird dieser optionale Parameter nicht angegeben so wird das Default Handle (wie derzeit implementiert) verwendet.


libusb für Windows / LeJoS Unterstützung

Erste Test zeigten eine das die libusb unter Windows auch funktioniert (mit LeJoS System). Es gilt den Code zur Ansteuerung der libusb zu überprüfen und neben dem Modus für LeJoS auch für die Original Firmware zu implementieren.

Derzeit überprüft die Implementierung (/branches/behrens/mfiles/) welche Library verwendet werden soll (libusb oder fantom) und verwendete dann die benötigten Funktionen. Die Information der Library (Name und Nummer (zum schnellen if Vergleich)) wurde dabei dem NXT Handle hinzugefügt. (Übrigens: die libusb Library unter Windows heißt "libusb0" und unter Linux "libusb"). Mit der primitiven Hilfsfunktion ChooseLibrary.m kann man derzeit manuell die zu verwendete Library festlegen.

Achtung! Derzeit wird die libusb unter Windows nur für ein LeJoS NXT unterstützt! Rainer Zitat: Bei der Original-Firmware muss man (nach Hinweisen im Internet) wohl den "Normalmodus" statt des stream-Modus neben, bzw. im Internet habe ich eben gefunden, dass bei Lejos im Moment nur der Streammodus funktioniert. Ich habe das aber bis jetzt noch nicht weiterverfolgt.

Die Handhabung müsste eigentlich analog zu der unter Linux sein. Habe die Protofiles für Windows auch dementsprechend schon angepasst. Aber eine erfolgreiche libusb Windows Paketübertragung mit einem NXT mit originaler Firmware ist mir noch nicht bisher geglückt.

Konzept libusb und fantom

Da wir derzeit noch nicht wissen welches NXT (LeJoS oder orignal Firmware) wir benutzen und bereits eine fantom Implementierung besteht, sollten wir beide Modi unterstützen. D.h. Die Fantom Implementierung scheint derzeit stabil und bleibt auf dem jetzigen Entwicklungsstand. Die Unterstützung von libusb unter Windows muss vorangetrieben werden, sowohl für ein LeJoS als auch ein Original Flash NXT. (Unterschied wohl ob man den Streammodus verwendet oder nicht!).

Der Benutzer kann dann entscheiden, welche USB-Library er für die Ansteuerung für sein NXT verwenden will. Beide können gleichzeitig auf einem Rechner installiert sein. Das funktioniert (selbst getestet). D.h. aber das man diese Option irgendwo abspeichern bzw. festlegen muss. Da würde sich die ini-Datei anbieten → also dann würde auch im USB Betrieb eine ini-Datei benötigt! (falls keine explizite Library genannt ist kann man natürlich mit default Werten arbeiten).

Schwieriger ist es zu bestimmen, welche Firmware (LeJoS oder Original) auf dem NXT vorliegt. Die Ini-Datei ist bisher immer noch NXT unabhängig und beschreibt nur das PC-System (Finde ich eine klare und logische Trennung!). Welche Firmware auf dem NXT vorliegt und damit welcher USB Modus verwendet wird (und libusb muss dann auch installiert sein) müsste dann der Nutzer bei einem COM_OpenNXT oder COM_OpenNXTEx angeben. Diese Information sollte wahrscheinlich auch im NXT handle gespeichert werden.

Kurzes Brainstorming: COM_OpenNXTEx(ConnectionMode, UseThisNXTMAC, infilename, 'check', 'LeJoS') oder Com_OpenNXT('LeJoS') d.h. wir wären gezwungen beim Funktionausruf doch den Parameter für die verwendete Firmware mit anzugeben.

Automatischer BT Verbindungsaufbau

Das Konzept von Johannes mit dem automatisierten Verbindungsaufbau finde ich sehr gut. Sollten wir auch so implementieren. Vielleicht können wir diese Feature aber als eine Art PlugIn oder AddOn implementiere, so dass wir nicht den Support von bt_connect etc. direkt leisten müssen. Denn derzeit gehen wir davon aus das die Hardwareverbindung zwischen PC und NXT über Bluetooth oder USB für die Toolbox bereits besteht. Die automatisierte bt_connect Lösung wäre dann ein zusätzliches Feature auf der Live-CD für unser Projekt.

Optimierung des Code

Optimierung des Code bzgl. Schnelligkeit. Ich denke wir können uns an manchen Stellen leisten, wenn wir nicht mehr alles so hart auf eine Gültigkeit prüfen, auch wenn das die Lesbarkeit und Transparenz des Codes verringern könnte. Änderungen und Annahmen sollten dann aber an der jeweiligen Stelle gut kommentiert sein!

Weitere Sensorik

Erste Funktionen befinden sich unter /branches/schnitzler/Sensoren. Unterstützung von RFID und Compass Sensor. Implementierungen und Knowledge ist oft von icommand abgeschaut. Diese Funktionen sollten angepasst, gut dokumentiert und in die Toolbox eingebunden werden. Zusätzlich sollte der Beschleunigungssensor auch unterstützt werden.

Beispiel Demos

Wir sollten die Anzahl der Demos in der Toolbox deutlich erhöhen. Für jeden Sensor sollte zumindest eine kleine Demo bereitgestellt werden. Z.B. das Lichtradar. Für die anderen teilweise neuen Sensoren wie z.B. Beschleuningungs- oder Compasssensor sollten auch kleinere!!! Demos bereitgestellt werden, die man gut auch für Präsentationszwecken gut und schnell verwenden kann!


Split GET-Functions into REQUEST and COLLECT parts

(for more flexibility / better performance)

%%
% Every function that retrieves (i.e. "gets") values from the
% NXT is internally split into two parts.
% We've got

NXT_RequestBatteryLevel;

%%
% on one hand, and its brother,

voltage = NXT_CollectBatteryLevel;

%%
% So what's the use? Well, in this case it should be definitely better to
% just use |NXT_GetBatteryLevel|, and the same is true for all |NXT_Get*|
% functions. This is by the way all what the get-functions do: First
% request, then collect.
%
% The reason for this split is more complex: Later on the professional user
% might want do something between requesting and collecting a packet (e.g.
% sensor reading). Of course the NXT will not be accessable during this
% 60ms of "black out" (it receives the request, sends back the answer). But
% the user might want to do something with Matlab during this time. And
% that's why you CAN split this command on your own in case you need it. If
% you don't, thats fine, but Matlab will be blocked a while (just like
% synchronous (or also called blocking) socket operations in other
% programming languages).
%
% _I personally haven't found a specific situation where this would be
% useful_ — yet ;-). So let's stick to the simple way of |NXT_Get*|, but
% keep in mind our options.

  • Auszug aus einer Mail:

NewContents.m (reads Contents.m)

  • Delete Contents.m, rename NewContents.m to Contents.m (silly step, change th

Es geht halt um den größten Flaschenhals der Bluetooth-Kommunikation:

Zum Auslesen von Daten jeglicher Art vom NXT benötigen wir ja immer 2 Pakete: Wir schicken den Request, und danach schickt das NXT die Response. Da ist leider die wohlbekannte "Wechsel-Zwischen-Senden-Und-Empfangen"-Pause zwischen. Ein einzelner Aufruf von z.B. GetInputValues benötigt also rund 60ms. Dieser Aufruf ist simpel zu benutzen (1 Funktion), aber unflexibel, wenn man die Rechenzeit benötigt: Denn ein Großteil dieser 60ms Wartezeit findet nach dem Abschicken unseres Request-Pakets und damit vor Eintreffen der Antwort statt. Die Zeit geht also in der Get-Funktion "verloren".

Der Ansatz ist jetzt: Möchte jemand in diesen doch recht langen 60ms etwas sinnvolles machen (z.B. eine Figure aktualisieren, damit sie — sollte man eine Animation zeichnen wollen — nicht ruckelt), kann er die Get-Funktionen in 2 Teile Aufsplitten, um dazwischen etwas anderes mit Matlab machen. Also erst einen Request-Befehl, dann irgendetwas, und wenn man damit fertig ist, den Collect-Befehl. Alles, auf was man achten muss, ist, die Reihenfolge zugehöriger Befehle zu wahren: Nach einemRequestInputValues muss also, egal wie spät, als nächstes ein CollectInputValues folgen, sonst bekommt man den Fehler/ die Warnung "Received packet not expected".

Konkrete Anwendungen dafür haben wir bis jetzt noch keine (zumindest nach meinem Kenntnis-Stand. Man kann das Ganze auch von dieser Seite betrachten:

Wenn ich ohnehin nur ca. 12 Sensor-Werte pro Sekunde auslesen kann, wird die meiste Zeit von dieser Sekunde auf Bluetooth-Pakete gewartet. Wenn ich jetzt irgendetwas berechnen oder zeichnen möchte, wäre es doch schade, das genau in der Zeit zu machen, wo das NXT nichts zu tun hat. Denn das wirkt dann direkt ganz kritisch auf die Sensorwert-Ausleserate. Also als Zahlen-Beispiel: 60ms Wert auslesen + 50ms irgendetwas mit dem Wert berechnen + 60ms nächsten Wert auslesen + 50ms berechnen…

Dann hätte ich in diesem Beispiel 110ms pro "Zyklus", also etwas ungeschickt. Wenn ich es aber schaffen könnte, die 50ms Berechnung (oder graphische Darstellung oder was auch immer) in der 60ms Wartezeit durchzuführen, hätte ich keinen Verlust in meinen ohnehin schon knapp bemessenen Sensor-Abfragen. Und wäre damit wie gewünscht am unteren technisch realisierbaren Limit von 60ms pro Zyklus.

Ähnliches Verhalten gibt es bei vielen Sockets bzw. Protokoll-Implementierungen: Synchrone bzw. "blocking" Funktionen warten (und damit blockieren) die weitere Ausführung des Programms so lange, bis die Daten da sind. Unsynchrone ("unblocking") Funktionen geben dazwischen die Ausführung weiterer Befehle frei.

Eine weitere kleine Idee dahinter: Findige Programmierer können ihre Roboter-Programme evtl optimieren: Sie schauen sich ganz genau an, wann sie welche Befehle an den Roboter SENDEN, und wo sie welche Sensordaten ANFORDERN. Dann könnte man durch sehr vorsichtige und geschickte Umordnung/Aufteilung? der Befehle die Anzahl der Sende-Empfang-Umschalt-Vorgänge des NXT minimieren (also dadurch versuchen, effektiv ein paar der 30ms-Pausen zu sparen).

Allerdings habe ich das noch nicht wirklich getestet. Theoretisch müsste Matlab wieder "frei" sein, sobald ein zu sendendes Datenpaket an den Bluetooth-Stack übergeben ist. Aber in der Realität muss man auch da mit kleinen Wartezeiten in der Größenordnung von 10ms rechnen, befürchte ich….


Verbosity-Level in textOut (damit wichtige Sachen nicht untergehen)

  • Auszug aus einer Mail:

Konzept für besseres Logging / textOut / Verbosity-Level:

Jede Nachricht, die wir zur Zeit irgendwo im gesamten Modules-Ordner eingebaut haben, kriegt eine zusätzliche Zahl als varargin hinten verpasst. Also aus

textOut(sprintf('Opening bluetooth connection…'))

wird dann z.B.

textOut(sprintf('Opening bluetooth connection…'), 1)

Das soll dann das "verbosity level" sein.

Je "höher" eine Funktion in unserer high-level-Kategorie ist, desto höher diese Zahl. Man könnte also ungefähr beispielsweise sagen:

1 - BT Meldungen, die genaue Paket-Details betreffen 2 - BT Meldungen, die nur Verbindungen / handles betreffen 3 - Generelle Statuszeilen zum Sensoren-Auslesen. 4 - Wenn neue Sensor / Motor-Modi gesetzt werden.. usw..

Dann könnte man die gesamten Log-Messages nochmal etwas vereinheitlichen (ich hatte mal angefangen, ein "+" vor manche zu setzen, das sollte der Übersichtlichkeit dienen, ist aber noch nicht ausgereift)

Die gesamte Idee dahinter ist:

Es ist standardmäßig ein Verbosity Level gesetzt. Sagen wir 5 oder so. Das ist default, und sorgt dafür, dass nur ganz wenig Meldungen im Log erscheinen. Z.b.: "Connection open. NXT working. Connection closed."

Hat jemand Probleme mit seinem Programm, benutzt er den Befehl textOut('SetVerbosityLevel', 4) oder sowas, und kriegt dadurch dann ab dieser Stelle auch die Meldungen, die neue Sensor-Einstellungen beschreiben. Das könnte bei der Fehlersuche helfen, wenn man z.B. Sieht:

Connection open. NXT working. Setting sensor mode "LIGHT_ACTIVE" on port 3 Setting sensor mode "SOUND_DB" on port 3 Connection closed.

(In diesem Fall würde man erkennen können, dass man 2mal den Port 3 für verschiedene Sensoren verwendet hat).

Oder man könnte auf VerbosityLevel 3 schalten, und dann würde man dauernd noch sehen:

Requesting Sensor data from port 2, value is 100. Requesting Sensor data from port 2, value is 123. Requesting Sensor data from port 2, value is 140. Requesting Sensor data from port 2, value is 160. Stopping motor 1.

Jemand, der weitere I²C Funktionen entwickelt, könnte also meinetwegen auf verbosity level 0 bzw 1 schalten und wirklich den kompletten Paket-Log sehen. Und andere Leute schalten es ganz aus. Oder Schalten 3 + 5 ein.

Das wäre sehr leicht umzusetzen. Man müsste nur 2 Dinge tun:

  1. textOut.m einmal vernünftig überarbeiten. Dann fragt textOut das (als globale Variable gesetzte) verbosity level ab und entscheidet, ob die aktuelle Meldung jetzt ausgegeben oder halt verworfen werden soll (wäre im Prinzip nur 1 if-Abfrage).
  1. JEDE Stelle, wo textOut aufgerufen wird, wird mit einer Zahl versehen. Da könnte man gleichzeitig die Log-Meldungen auch verbessern oder kürzen bzw. in den Motor-Funktionen vielleicht auch welche hinzufügen.

Ich persönlich halte solche Log-Meldungen für SEHR wichtig. Wenn man mit Pausen im Programm arbeitet, und sich z.B. irgendwo vertut (ich setze meinen Roboter erst auf stop und warte 5s, dabei wollte ich das eigentlich andersrum machen), helfen solche Log-Meldungen doch sehr (in diesem Fall würde man sehen, dass "Stopping all motors" schon VOR der 5s-Pause auf dem Bildschirm erscheint).

Man erhält also einen besseren Überblick über den Programm-Ablauf.


Check readasync für COM-Port

(maybe better performance / less bluetooth lag)

Siehe Matlab-Hilfe zum Thema readasync. Kann man damit den COM-Port "schneller" auslesen? Hat das überhaupt etwas mit Bluetooth zu tun, oder änderen wir damit an unserem Timeout-Problem rein gar nichts???


Seit NXT Firmware 1.05 ist das Bluetooth-Packet-Handling überarbeitet

(Timeouts treten nur noch selten auf?)

Es wäre zu untersuchen, ob die automatisch erzeugten Pausen in BT_SendPacket und BT_CollectPacket überhaupt noch notwendig sind. Können sie das sporadisch auftretende 10s-Timeout-Problem überhaupt verhindern oder die Eintritts-Wahrscheinlichkeit verringern? Falls nicht, vermindern sie nur die gesamte Performanz, ohne einen positiven Effekt zu haben.

Timeouts scheinen mit aktuellem Release 0.3.4 und mit aktueller Firmware 1.05 am LfB nach wie vor ein Problem zu sein (zumindest mit GUI_WatchAnalogSensor).


textOut bzw. dec2hex ist langsam!

Es fällt auf, dass die Gesamt-Performanz unnötig leidet, wenn das globale Logging deaktiviert ist, aber textOut trotzdem immer Statusmeldungen annimmt (die dann verworfen werden). Dies liegt am außerordentlich langsamen String-Handling von Matlab, insbesondere an der Funktion dec2hex. Abhilfe: Ein flag (z.b. DisableScreenOut) VOR dem Aufruf von textOut schon abfragen, um Rechenzeit zu sparen. Mit dem Profiler nachprüfen!!!


Pause und tic / toc haben nur ca. 15ms Genauigkeit unter Windows / Linux?

Muss noch überprüft werden. Sind clock / etime auch betroffen? Gibt es Möglichkeiten, in Matlab feinere Zeiten aufzulösen? Falls nicht, muss das gesamte Timing-Konzept der BT_Send und Collect Funktionen neu überdacht werden.

(Mit dem Profiler nachprüfen?)


Wir checken zu häufig das Bluetooth-Handle (ob es gültig ist)

In vielen Funktionen findet eine isserial(handle) Überprüfung statt (bzw. die erweiterte Linux-handle-Abfrage mit ispc usw). Das ist eigentlich deutlich übertrieben: ENTWEDER wir fragen nur in den High-Level-Funktionen das Handle ab, dann ist sichergestellt, dass in den low-level Funktionen (BT_SendPacket und BT_CollectPacket) immer ein gültiges handle ankommt (denn sonst hätte es schon vorher beim Check einen Fehler gegeben). So könnte man sich die wiederholte Sicherheitsabfrage in den BT-Funktionen sparen → Performance-Improvement / schlankere Funktion.

Oder aber, man verzichtet auf den Check in den High-Level-Funktionen, und fragt erst (und auch wirklich nur dort) in BT_Send und BT_Collect ab. Spätestens dort "unten" kommt früher oder später sowieso jeder Funktionsaufruf an. Man könnte ohne Probleme eine ungültiges BT-Handle so lange "weitergeben", bis es hier zum Fehler kommt — MATLAB zeigt schließlich den Aufruf-Stack bei einem Fehler sehr übersichtlich von top-level bis low-level an… Auch dies hätte ein Performance-Improvement zur Folge (sowie schlankere High-Level-Functions), und den deutlichen Vorteil, dass die "höheren" Funktionen sich nicht um Handles mehr kümmern müssen, bzw. muss man, wenn man neue Funktionen entwickelt, nicht zwingendermaßen eine Sicherheitsabfrage einbauen (und es hätte sonst unangenehme Konsequenzen, wenn es dort vergessen würde).

Diese (eigentlich durchaus simple Vereinfachung) sollte beim nächsten Toolbox-Update erfolgen, und ich empfehle sehr Variante 2 zu verwenden…

Das Gleiche gilt übrigens für viele Invalid-Port-Number Checks in den zwei-geteilten Funktionen (wo wir einen Request*- und einen Collect*-Teil haben). Auch hier würde es eigentlich reichen, in den tieferen Request*- und Collect*-Funktionen zu prüfen und so die Get*-Funktionen zu vereinfachen…


Kompatibilität für mehre NXTs (also mehrere Bluetooth handles parallel) besteht noch nicht 100%

Das Problem ist, dass in BT_OpenHandle die Parameter SendSendPause und SendReceivePause nur EINMAL GLOBAL gesetzt werden. In BT_SendPacket und BT_CollectPacket wird dann — UNABHÄNGIG VOM ÜBERGEBENEN HANDLE leider — auf diese globalen Variablen zugegriffen, um eine eventuelle Pause vor dem Senden / Empfangen einzulegen. Das führt dazu, dass wir also effektiv die Bluetooth-Pakete auf "1 Packet alle 30ms" (Beispiel) begrenzen, INSGESAMT, und nicht — wie vorgesehen — separat je NXT. Wir "verschwenden" also wieder wertvolle Zeit bzw. warten zu viel. Also nur für den Fall, dass jemand mehrere handles mit mehreren NXTs in einem m-file benutzt. Schnelle Abhilfe: Einfach SendSendPause und SendReceivePause deaktivieren (also auf 0 setzen). Langfristige Abhilfe: Entweder diese inifile-Parameter zusätzlich zu einem handle speichern, da irgendwie mit dranhängen, und dann in den BT_Send und Collect Funktionen nicht die globale Zeitstempel var abfragen, sondern die "lokalen" zum jeweiligen handle gehörigen. Im Prinzip ähnlich wie tictic und toctoc. Aber besser :-)

Andere Möglichkeit: Auf Dauer das SendSendPause und SendReceivePause Konzept (war je eh eine Notlösung für schwache Rechner) nicht mehr supporten / droppen / rausnehmen. Oder eben schlicht und einfach sagen: "So Leute, für eine einzelne Verbindung Funktionieren diese ini-Settings, für mehrere gleichzeitig aber nich, setzt dann bitte das jeweils auf 0 in den files, sonst verschwendet ihr viel Bluetooth-Performance."


USB-Support. Wie Schnittstelle ansprechen, wie BT-Funktionen weiterverwenden?



Last modified 9 years ago Last modified on Dec 7, 2009, 3:52:06 PM