Liste der Anhänge anzeigen (Anzahl: 1)
LUISE - LUftInhalierendes Saug Experiment (Saugroboter)
Liebes Forum,
ich wollte Euch an meinem Projekt LUISE beteiligen. Luise, weil es mit den autonomen Roboter ja ein ach so weites Feld ist.
Luise soll autonom meine Wohnung saugen. Es gibt hier keine Türen aber große Flächen - ein Fall für Luise.
Luise soll mit einem handelsüblichen Staubsauger ca. 1800 W ausgestattet sein, kein Akku, sondern ein Schleppkabel - evtl. mit einem mehr oder weniger inteligentem Kabelaufrollmechanismus.
Die innovative Idee ist bei Luise die Raumorientierung: Luise ist mit einer IR-empfindlichen Webcam ausgestattet. Weil Luise auch mit kräftigen IR-LED Strahlern ausgestattet ist, kann sie (auch bei Dunkelheit) an der Decke klebene "fiducials" aus dem Sourgeforgeprojekt "ReacTIVision" erkennen.
Die ReacTIVision-Engine funktioniert auf allen Plattformen ziemlich gut. Sie ist ursprünglich gedacht über Lichttische Synthesizer zu bedienen.
Der Output ist ein TUIO-Stream über das Netzwerk, dass neben der ID (es gibt über 200 Stück) des fiducials auch dessen Position im Kamerablickfeld und dessen "Verdrehung" ausgibt. Ich finde sehr vielversprechende Voraussetzungen für eine ordentliche Lokalisierung.
Die Nahorientierung und Hindernisserkennung soll Luise mit einem Sick Laserscanner bewerkstelligen.
Mechanisch besteht Luise in erster Linie aus einem Brett, auf dem der Staubsauger, die Rechenmaschinen, die Netzteile, die Schleppkabelwickel und der Sick aufgeschraubt sind. Rechts und links hinten sind zwei Scheibenwischermotoren angebracht. Vorn stützt eine drehbare Rolle.
Luise - Luise - das ist ein weites Feld... die angestrebte Autonomie soll Luise in Modulen erhalten: Ein ITX-Mainboard mit WLAN steht im Zentrum. Ein Arduino übernimmt die Motorik. Ein MD22 sorgt für die Kraft.
Als ich vor ca. drei Wochen mit dem Projekt begann, war mir bei weitem nicht klar, dass jeder Minischritt von so grossen Problemen begleitet ist. Deshalb möchte ich mit Luise jetzt in dieses Forum treten, in der Hoffnung konstruktive Kritiker und mitfühlende Begleiter zu finden.
Liste der Anhänge anzeigen (Anzahl: 1)
Probleme - die erste
Beim Mainboard gingen die Probleme schon los:
1. die SATA Notbookplatte Toshiba MK1652GSX, die extra wegen dem SATA gekauft habe wurde vom Mainboard VIA Epia SP-13000 nicht erkannt. Musste dann noch einen SATA-IDE Converter kaufen. Das Epia hatte ich mir ausgesucht, weil es alle möglichen Anschlüsse hat. Sogar I2C (SMBus), Firewire, seriell, parallel und natuerlich USB.
2. die Webcam Speedlink VAD Laplace versprach eine echte HD-Auflösung im Videomodus - aber es gibt ausschliesslich Treiber für Windows. Eigendlich wollte ich alles auf Linux laufen lassen - grrr.
Als Workarround habe ich dann XP installiert und dortdrin dann mit SUNs VirtualBox ein Debian Lenny.
3. Der Billig WLAN-Stick den ich eigendlich einsetzen wollte, liess sich aber nicht durch VirtualBox auf Windows bridgen, so dass ich auf die D-Link DWL-G520 ausgewichen bin. Dies bereue ich aber überhaupt nicht, weil die echt super stabil mit Top-Übertragungsraten sowohl unter Windows als auch Linux glänzt.
4. Weil Luise ja keinen Moni oder Tastatur haben soll, wurde auf dem XP der RemoteDesktop freigegeben und die IP aus dem WLAN-Netz fest vergeben.
5. Die nächste Schwierigkeit war, die VirtualBox als Windowsdienst zu starten, damit auch die LinuxLuise automatisch am Start ist.
6. Nachdem dies klappte, begab ich mich auf die Suche nach einer Robotersoftware, die für mich einigermaßen verständlich war. Beim Installieren vom Mikrosoft freien Robotikkram und den sicher 10 Mikrosoftabhängigkeiten .... bin ich doch wieder dazu übergegangen mich auf mein vertrautes Linux zurückzukommen und entschied mich für Player/Stage.
7. Leider braucht man zumindest für Stage eine grafische Oberfläche, die mein Konsolen Linux mit SSH-Zugriff nicht bot. So habe ich dann noch NoMashines NX Server auf dem Lenny installiert und mein erster DemoRobot konnte über WLAN auf meinem OSX Powerbook Bildschirm sein Labyrinth erkunden.
Nebenbei habe ich auch versucht, den SMBus auf dem EPIA in Betrieb zu nehmen. Irgendwann habe ich auch ein paar Daten, die vom Mainboard bereitgestellt werden auf die WindowsKonsole bekommen, das Schreiben allerdings hat überhaupt nicht hingehauen: entweder passiert nix oder der Rechner friert ein. Falls an dem Punkt jemand noch Tipps hat, wäre ich dankbar.
Diese Apt-Pakete mussten nach der reinen Lenny-Basis-Installation installiert werden:
- ---- basic ---
ssh
apt-file
---- develop ---
linux-libc-dev
subversion
gcc
bzip2
g++
libglib2.0-0
libncurses5-dev
autoconf
make
libperl-dev
libtool
docbook
kernel-package
linux-source-2.6.26
linux-headers-2.6.26-2-486
libmpfr-dev
gnat-4.3
bison
flex
gcc-avr
uisp
avrdude
avr-libc
libftdi-dev
texlive-base-bin
texlive-latex-base
texlive-latex-recommended
---- Desktop -----
xorg
gdm
xfce4
---- nxserver ------
libaudiofile0
dpkg -i nxclient_3.3.0-6_i386.deb
cups
dpkg -i nxnode_3.3.0-17_i386.deb
dpkg -i nxserver_3.3.0-22_i386.deb
---- carmen ----
compile http://www.kvaser.com/cgi-bin/files/linuxcan.tar.gz
libgtk1.2-dev
libreadline5-dev
libgtk2.0-dev
gdk-imlib11-dev
libwrap0-dev
imagemagick
libmagick9-dev
java-common
sun-java6-bin
sun-java6-jre
sun-java6-jdk
ant
doxygen
swig
compile carmen
Liste der Anhänge anzeigen (Anzahl: 1)
Probleme 2
Lange Zeit habe ich auch damit verbracht, den ReaTIVision Engine dazu zu bringen, auch als Dienst unter Windows zu starten, was mir noch nicht gelungen ist, weil die unbedingt auf einen Desktop will. Wenn ich remote angemeldet bin, gibt es keine Probleme. Ausserdem habe ich mich schwergetan, das die Engine ihre TUIO Daten an die VirtualBox statt auf den Localhost schickt, bis ich dann die IP der vBox hardgecodet in den Sourcen eingetrage und neu kompliert habe. Danach habe ich dann allerdings das XML-File zur Konfiguration entdeckt, womit das wohl einfacher gewesen wäre.
Als ich dann die TUIO-Daten mit TUIODump zuverlässig auf der Konsole hatte, habe ich mich erstmal wieder der Hardware zugewendet.
Ich wollte aus der Webcam gern den IR-wegfilternden Filter ausbauen und dann einen nur IR-durchlassenden Filter einbauen, damit die Erkennungsrate von ReacTIVision verbessert wird. Leider habe ich beim Rumpulen mit dem Teppichmesser einen dicken Kratzer auf das Winz-Objektiv bekommen, aber die Engine erkennt zwar schlechter als bisher, aber immer noch die Fiducials, die im übrigen auch unter der Zimmerdecke recht dekorativ sind.
Liste der Anhänge anzeigen (Anzahl: 2)
Probleme 3
Zur Entspannung, glaubte ich, bin ich dann an meinen Arduino, dem ich die folgende Funtion zuweisen wollte:
Empfange seriell den Befehl "gehe x cm y Grad". Er soll dann die Motoren selbständig steuern und in regelmäßigen Abständen auch seriell "z % erlegigt" zurückgeben. Beispiel: gehe(100,0) wäre 1Meter geradeaus. gehe(0,90) -> dreht 90° rechtsrum auf der Stelle. gehe(-50,-180) -> Fährt einen 0,5 Meter langen Kreisbogen rückwärts linksrum.
Er soll ausserdem noch auf einen "notstop" Befehl reagieren, bei dem beide Motoren auf der Stelle angehalten werden.
Der Motortreiber MD22 kann analog, i2c-seriell und über PWM angesprochen werden. Ich dachte "bleibe ich doch solang wie möglich digital" und habe mich auf den i2c bus konzentriert und wäre fast verzweifel, weil nichts ging. Zum Glück bin ich gestern abend noch auf einer Webseite auf ein Script gestossen, in dem eine andere Basis-Adresse verwendet wurde. Entgegen aller Beschreibungen und Manuals hört der MD22 rev.10 NICHT auf 0xB0, sondern auf 0x58. Dann klappts auch mit den Nachbarn.
Gestern und heute schliesslich, sollte der Odometer ausprobiert werden. Bei Pollin gabs für ein paar Cent die IR-Gabel TCYS5201 mit Schmitt-Trigger Ausgang. Die dann an meinen Arduino angeschlossen und als Interrupttrigger verwendet. Bei LOW alles supi, aber bei HIGH zählte mein Arduino in ein paar Sekunden so viele Ticks, dass er übergelaufen steckenblieb. Erst dachte ich, die Verwendung von externen Interrupts sei vielleicht gar nicht gleichzeitig mit Serial.begin möglich, weil dort ja auch Interrupts ausgelöst wurden. Aber wer liest ist klar im Vorteil: im Datenblatt der Gabel wird empfohlen, einen Kondensator möglichst nah am Sensor zwischen VCC und GRD zu legen und dann zählte mein Ardu wie gewünscht.
Code:
/******************************************************************************
* Luises - Motorsteuerung - erste Erfolge
* Arduino analog input 5 - I2C SCL
* Arduino analog input 4 - I2C SDA
* Arne Groh 2009-04-03
* ******************************************************************************/
#include <WString.h>
#include <Wire.h>
volatile unsigned int LeftEncoderTick = 0;
int l_enc_v0 = 12;
int left_speed = 60;
int right_speed = 128;
int incomingByte = 0; // for incoming serial data
int revision;
int mot1;
int mot2;
int accel;
#define md22Address 0x58 // !! NOT 0xB0 !!
void setup() {
pinMode(l_enc_v0, OUTPUT);
digitalWrite(l_enc_v0, HIGH);
Wire.begin(0x53); // Host Address
Wire.beginTransmission(md22Address); // MD22 Address (All Switches ON = 0x58)
Wire.send(0x00); // Set Register 0 (Mode)
Wire.send(0x00); // Send Data Mode to 0 (0 to 255)
Wire.endTransmission();
Wire.beginTransmission(md22Address); // MD22 Address (All Switches ON = 0x58)
Wire.send(0x03); // Register of Acceleration
Wire.send(128); // Send Data for Acceleration
Wire.endTransmission();
readMD22();
attachInterrupt(0, LeftEncoderEvent, HIGH);
Serial.begin(9600);
write_MD22();
}
void loop() {
readSpeed();
delay(10);
}
void write_MD22(){
Wire.beginTransmission(md22Address); // MD22 Address (All Switches ON = 0x58)
Wire.send(0x01); // Register of Motor 1
Wire.send(left_speed); // Send Data for left Motor(1) Speed (0 = Full Reverse | 128 = Stop | 255 = Full Forward)
Wire.send(right_speed); // Send Data for right Motor(2) Speed
Wire.endTransmission();
}
void readSpeed(){
if (Serial.available() > 0){
char string[8] = " "; // declare string variable
for (int i = 0; i < 7; i++){
if (Serial.available() > 0) // send data only when you receive data:
{string[i] = Serial.read();}
}
String sstring = String(string);
String l_string = sstring.substring(0, 3);
String r_string = sstring.substring(4, 7);
left_speed = (atoi(l_string));
right_speed = (atoi(r_string));
write_MD22();
printmessage();
}
}
void readMD22(){ // Reads Data from MD22
Wire.beginTransmission(md22Address); // Calles software register
Wire.send(0x07); // Register of SoftwareRevision
Wire.endTransmission();
Wire.requestFrom(md22Address, 1); // Requests one byte
while(Wire.available() < 1); // Wait for it to arrive
revision = Wire.receive(); // Get byte
Wire.beginTransmission(md22Address); // Calles software register
Wire.send(0x01); // Register of Motor 1
Wire.endTransmission();
Wire.requestFrom(md22Address, 1); // Requests one byte
while(Wire.available() < 1); // Wait for it to arrive
mot1 = Wire.receive(); // Get byte
Wire.beginTransmission(md22Address);
Wire.send(0x02); // Register of Motor 2
Wire.endTransmission();
Wire.requestFrom(md22Address, 1); // Requests one byte
while(Wire.available() < 1); // Wait for it to arrive
mot2 = Wire.receive(); // Get byte
Wire.beginTransmission(md22Address);
Wire.send(0x03); // Register of Acceleration
Wire.endTransmission();
Wire.requestFrom(md22Address, 1); // Requests one byte
while(Wire.available() < 1); // Wait for it to arrive
accel = Wire.receive(); // Get byte
}
void LeftEncoderEvent(){
LeftEncoderTick++;
}
void printmessage(){
readMD22();
Serial.print("MD22-Ver: "); // Print to Serial
Serial.print(revision);
Serial.print(" | Current Mot 1 Speed: ");
Serial.print(mot1);
Serial.print(" | Current Mot 2 Speed: ");
Serial.print(mot2);
Serial.print(" | Current Accel: ");
Serial.print(accel); // Print to serial and CR
Serial.print(" | LeftEncoderTick: ");
Serial.println(LeftEncoderTick);
}
Als nächstes werde ich versuchen, meine Trigonometrie-Erinnerungen aufzufrischen, um die Kursumsetzung zu implementieren. Ich hatte anfangs mit dem Gedanken gespielt, hier einen PID-Regler einzusetzen, aber ich verstehe nicht wirklich, was der treibt...
Liste der Anhänge anzeigen (Anzahl: 2)
Der Sick
Mitte letzter Woche kam der bei ebay ersteigerte Sick PLS 101-312 an. Nachdem ich gepeilt hatte, das die seriellen Leitungen so angerschlossen werden:
SICK Pin 5 GND -> PC Pin 5 GND
SICK Pin 2 RXD -> PC Pin 3 TXD
SICK Pin 3 TXD -> PC Pin 2 RXD
konnte ich auch mit dem Sick -Konfigurationsprogramm auf meinen Laserscanner unter Windows zugreifen und konfigurieren.
Die nächste Herausforderung war der Zugriff von Linux aus:
Fast alle Beschreibungen und Tools aus dem Netz beziehen sich auf den Sick LMS und nicht auf den PLS (meistens wird gesagt, dass es keinen Unterschied gibt) - jedenfall ist mir der Zugriff (mit den LMS-Treibern) nicht direkt gelungen.
Zuerst habe ich mit den Treibern von PlayerStage probiert. Dann mit der sicktoolbox-1.0, dann mit LMSdemo.c, danach stundenlang versucht DROS-0.98 zu kompellieren (ohne Erfolg). Versucht habe ich auch noch zaza und Aria. Leider konnte ich keinem dieser Programme einen Output meines Lasers entlocken.
Schliesslich habe ich dann noch Carmen ausprobiert und habe mit diesen Einstellungen einem ersten Teilerfolg errungen (siehe Bild):
Code:
In der carmen/src/carmen.ini:
[b21]
base_type b21
# laser parameters
#laser_laser1_dev /dev/cur60
laser_front_laser_dev /dev/ttyS0
#laser_laser1_dev /dev/ttyS0
#laser_laser1_type PLS
laser_front_laser_type PLS
laser_front_laser_baud 38400
laser_front_laser_resolution 0.5
laser_front_laser_fov 180
laser_front_laser_flipped 0
laser_front_laser_use_remission no # none / direct / normalized
laser_rear_laser_dev none
laser_laser2_dev none
laser_laser3_dev none
laser_laser4_dev none
laser_laser5_dev none
dann das Carmen-System starten mit diesen Befehlen:
Code:
l-robot-01:~/carmen-0.7.4-beta/bin# ./central &
l-robot-01:~/carmen-0.7.4-beta/bin# ./param_daemon -r b21 ../data/freiburg.map &
l-robot-01:~/carmen-0.7.4-beta/bin# ./laser &
Der "laser" - Befehl hat glücklicheweise mit dieser Ausgabe geantwortet:
Code:
###########################################
INFO: select mode ..................... on
INFO: LASER type ...................... PLS
INFO: connect TTY /dev/ttyS0 ...... ok
INFO: set port param 9600:8E1 ....... ok
INFO: detect connected baudrate: ...... 9600
INFO: set LASER in config-mode ........ ok
INFO: set LASER baudrate to 38400 .... ok
INFO: using remission mode ............ none
INFO: start LASER continuous mode ..... ok
###########################################
Daraufhin habe ich mich getraut, unter X den Befehl "laserview" aufzurufen und wurde mit dem anhängenden Laserscann belohnt.
Das bisherige Fazit:
Luise wird mit Carmen statt PlayerStage laufen!
Liste der Anhänge anzeigen (Anzahl: 1)
neu Motoren
Die alten Motoren liefen doch etwas schnell. Ausserdem erschienen mir die zuletzt verwendeten Räder zu "spackelig".
Jetzt habe ich die ganz langsamen Pollin-Scheibenwischermotoren verwendet. Ausgerüstet mit Luftreifen, macht das Chassis jetzt einen soliden Eindruck.
Liste der Anhänge anzeigen (Anzahl: 1)
neue Odometrie Sensoren
Mit den neuen Rädern hat Luise jetzt auch "Phase-Quadratur Encoder" erhalten. Dazu habe ich jeweils zwei Gabellichtschranken nebeneinander geklebt. Die neuen Encoderscheiben mussten dadurch etwas grober ausfallen. Sie haben jetzt pro Umdrehund nur noch 9 High/Low Phasen (die alten hatten 12). Dadurch kann Luise jetzt aber auch die Drehrichtung erkennen und die Encoder-Ticks bei Rückwärtsdrehungen wieder abziehen.
Die Auswertung der Quadratursignale werde ich wahrscheinlich mit einer alten BasicStamp machen, von denen ich noch ein paar rumliegen habe. Bin im Netz auf einen prima Zusammenhang gestoßen, der im RN offensichtlich auch nicht betrachtet wurde:
Code:
von Scott Edwards
0 1 3 2 0 state
----> ----> ----> ----> CW
0 _ 1 _ 1 _ 0 _ 0 B
/ / / / all 0->1 or 1->0
0 - 0 - 1 - 1 - 0 A
0 1 3 2 0 state
<---- <---- <---- <---- CCW
0 _ 1 _ 1 _ 0 _ 0 B
\ \ \ \ all 0->0 or 1->1
0 - 0 - 1 - 1 - 0 A
Es zeigt sich nämlich, dass wenn man die Übergänge der Statusänderungen der beiden Encoder betrachtet, bei der Vorwärtsfahrt der Status des einen Encoders vor der Änderung IMMER genau invers zu dem aktuellen des anderen ist.
Bei der Rückwärtsfahrt sind die Zustände IMMER gleich.
Dies ermöglicht eine simple XOR Auswertung bei gleichzeitiger Filterung von Signalen die sich nur auf einem "Tick" abspielen (Ruckel der Räder auf der Stelle).