En nu kom je in mijn vaarwater ;)

SLAM is een moeilijk probleem om op te lossen. Wat je bij klassieke (probabilistische) SLAM gaat doen is het volgende (om je een idee te geven, er zijn nog meer tussenstappen die ervoor zorgen dat het werkt, maar dit is het idee):
1) Je doet een meting met je sensoren en identificieert "landmarks" in die data
2) Je gaat rijden met je robot en je schat de verplaatsing van de robot op basis van de snelheden die je aan de wielen hebt opgegeven.
3) Je voorspelt hoe de verschillende landmarks bewogen zullen zijn op basis van een model van je sensor en een model van je beweging (je robot dus)
4) Je gaat meten met je sensoren wat de werkelijke positie is van de landmarks (en hier zit het addertje: je moet dezelfde landmarks terug gaan vinden in je data, en da's tricky)
5) Je gaat, via bayesiaanse kansberekeningen, de schatting van je positie van je robot aanpassen zodat die beter overeenkomt met zowel je sensordata als je encoder data
6) terug naar stap 2

Je hebt eigenlijk een kalman filter op de robot state (de positie van de robot in de wereld), met als sensoren die gefused moeten worden de encoders en de externe sensoren (lidar, sonar, ...)

Het is dus in probabilistische SLAM noodzakelijk dat je een goede(!) sensor voor je omgeving hebt. Lidars bijvoorbeeld, of een kinect, of iets dergelijks. Heb je dat niet, zijn er nog andere opties.

Er zijn SLAM systemen die het over een totaal andere boeg gooien: je gaat je sensordata anders behandelen -> je gaat niet op zoek naar individuele landmarks in de sensordata, maar gaat elke sensormeting als een soort fingerprint gebruiken, dat, tot op een zekere ambiguiteit na, je iets verteld over je positie in de omgeving. Als je dan, na een leerfase, een sensormeting doet die goed trekt op een oudere sensormeting, kan de robot daaruit afleiden wat zijn werkelijke positie is in de omgeving.

Een heel bekende is RatSLAM. Wij hebben hier in ons lab dat RatSLAM algoritme aangepast zodat het ook met een sonar kan werken. Toegegeven, de sonar was vrij geavanceerd, maar het zou met een set eenvoudigere sensoren ook wel kunnen lukken. Zie bijvoorbeeld http://repositorium.sdum.uminho.pt/bitstream/1822/18887/1/Proceedings_… , P.86 voor meer details.

Voordeel van die RatSLAM: er is python code voor... R-PI heeft python, numpy en scipy, dus... Ik ga, vanaf ik mijn R-PI binnen heb, die BatSLAM porteren naar de R-PI en op een kleine stingray robot zetten.

Als ik het goed begrijp hoef ik enkel sonar en encoder data vast te leggen, dit aan een platform waarop een slam programma draait te voeren en dat programma verteld dan waar de robot zich op dit moment is en waar hij geweest is?

En hoe nauwkeuriger de sonar en encoder data is, des te beter zal de kaart en actuele locatie zijn?
Is het ook mogelijk om uit de kaart op te maken waar er nog gezogen moet worden, voor de robot dan?

Ik denk dat ik toch maar is moet kijken of ik aan een raspberry pi kan komen (die dingen zijn voortdurend uitverkocht...)

Jb

Dat klopt deels. Hoe nauwkeuriger je encoder data, hoe kleiner de fouten van de pad-integratie zullen zijn en hoe minder het SLAM algoritme moet compenseren. Maar de encoder fouten mogen vrij groot zijn (zoals je kan zien in de resultaten figuur), om toch nog stabiel te blijven.

De sonar data mag niet té nauwkeurig zijn: wij smoothen die data grof om kleine positieverschillen en orientatieverschillen op te vangen. De kaart kan je inderdaad gebruiken om bij te houden waar je reeds geweest bent, en daaruit kan je afleiden waar je nog moet zijn (als je de kaart dan hebt opgebouwdin het verleden).

Maar: waarom een kaart voor een stofzuiger? Is dat niet wat overkill? Lees eens Rodney Brooks zijn papers, of het boek van Arkin: Behavior based robotics. Ik denk namelijk niet dat je SLAM nodig hebt voor een goeie stofzuigrobot... Maar leuk is het natuurlijk wel :)

Nodig? nee zeker niet voor mijn kamer :P max 6 vierkante meter...

Wellicht dat ik enkel met 3 sonar sensoren en wat slimme algoritmes het klusje ook geklaard krijg.

Jb

Als je eens naar probabilistische SLAM wil kijken zou je aan de slag kunnen met een webcam en zo van die augmented reality tags, die je in je kamer plakt. Die tags zijn dan de landmarks die je voor je slam algoritme kan gebruiken

Die simpele sonar sensoren hebben als nadeel dat je totaal geen informatie over de positie van de reflector terug krijgt (binnen de bundelbreedte van de sonar dan), enkel de afstand tot de eerste. Dat gaat je meestal in de problemen brengen. Als je het analoge signaal dat uit de versterker komt kan digitaliseren, en je twee zulke sensoren pakweg 20° draait tenopzichte van elkaar, kom je er mischien wel

Ik was van plan om met die 3 sonars de bumper te vervangen.
Als ik toch slam zou willen proberen met zo'n sonar dan zou ik hem waarschijnlijk op een kleine stappenmotor monteren en die dan laten draaien terwijl hij aan het scannen is.

Zou je kunnen uitleggen wat je bedoeld met digitaliseren en 2 sonars onder een hoek? dat begrijp ik niet helemaal...

Ik heb even een motor van de roomba eruit gehaald, om te kijken hoe het zit met zijn encoder. Er zit een optische encoder in, helaas wel direct op het wiel, met 32 openingen.
Dat komt dus neer op 11,25 graden per "klik" en plus minus 6,3mm per "klik" en als ik het goed heb uitgerekend heeft hij een resolutie van 3 graden met draaien om zijn eigen as...

Niet heel nauwkeurig dus, zodra ik de motoren aan een arduino heb gehangen en heb uitgevogeld hoe de encoder aan te sluiten zal ik is gaan testen hoe erg de afwijking van de odometrie is.

[Bericht gewijzigd door Henry S. op (43%)]

Wel, uit je sonar sensor, wat eigenlijk niet meer is dan een microfoon gevoelig voor 40kHz, komt een analoog signaal. Dat analoog signaal bevat VEEL meer informatie dan enkel range tot target. De sterte encodeert ook wat voor de hoek. Als je dus twee sensoren hebt met elks een gevoeligheid die in het horizontale vlak iets gedraaid is, kan je uit de verschilsterktes (interaural intensity differences, IID) een indicatie voor de hoek krijgen. Die informatie moet je niet expliciet extraheren (zie onze paper), maar gaat je wel helpen in je local view database.

Met digitaliseren bedoel ik dan dat je het signaal via een ADC binnen neemt.

Op korte termijn (enkele secondenà is odometrie vaak niet zo verkeerd, het is maar als je lange tijd gaat bijhouden dat het fout gaat, omdat je de fouten integreert. Dus om je experiment goed te doen moet je zeker de lange-termijn fouten in kaart brengen

Ik heb de 5105 gestript en enkel de sensoren die ik wil gaan gebruiken of die nuttig zijn tijdens het testen zitten er nu nog op.

De eerste stap is de motors aansturen, daar heb ik een TB6612FNG dual hbridge breakout voor. Momenteel heb ik wel een probleempje daarmee... De ene keer doen de motoren het beide kanten op, soms maar 1 kant en net opeens helemaal niet..., soms hoor ik een zoem uit de motor als hij zou moeten draaien, maar ook dat niet altijd...

Ik heb een 12V 50W voeding eraan hangen en met een motor tester (de motor inloop functie van mijn nimh lader) doen ze het gewoon vanaf 4V goed zonder problemen...

Dit is de code die ik gebruik om de motors aan te sturen:

//motor A connected between A01 and A02
//motor B connected between B01 and B02

int STBY = 10; //standby

//Motor A
int PWMA = 5; //Speed control 
int AIN1 = 9; //Direction
int AIN2 = 8; //Direction

//Motor B
int PWMB = 6; //Speed control
int BIN1 = 11; //Direction
int BIN2 = 12; //Direction

void setup(){
  pinMode(STBY, OUTPUT);

  pinMode(PWMA, OUTPUT);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);

  pinMode(PWMB, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);
}

void loop(){
  move(1, 200, 1); 
  move(2, 200, 1);

  delay(3000); //go for 3 second
  stop(); //stop
  delay(250); //hold for 250ms until move again

  move(1, 200, 0); 
  move(2, 200, 0); 

  delay(3000);
  stop();
  delay(250);
}

void move(int motor, int speed, int direction){
//Move specific motor at speed and direction
//motor: 0 for B 1 for A
//speed: 0 is off, and 255 is full speed
//direction: 0 clockwise, 1 counter-clockwise

  digitalWrite(STBY, HIGH); //disable standby

  boolean inPin1 = LOW;
  boolean inPin2 = HIGH;

  if(direction == 1){
    inPin1 = HIGH;
    inPin2 = LOW;
  }

  if(motor == 1){
    digitalWrite(AIN1, inPin1);
    digitalWrite(AIN2, inPin2);
    analogWrite(PWMA, speed);
  }else{
    digitalWrite(BIN1, inPin1);
    digitalWrite(BIN2, inPin2);
    analogWrite(PWMB, speed);
  }
}

void stop(){
//enable standby  
  digitalWrite(STBY, LOW);
}

Ik heb helaas de motor driver gesloopt... Per ongeluk tijdens testen de kabel van de 12V op de rij van VCC laten vallen... en daarbij volgens mij ook mijn arduino omzeep geholpen.

Gelukkig had ik ook nog een protosnap liggen (een arduino mini clone) en ben ik dus maar verder gegaan met een test van de sonar scanner.
Test opstelling:
http://i691.photobucket.com/albums/vv274/zenoah/48006eaf.jpg

Ik heb een protosnap met daaraan een openlog om alle data naar toe te schrijven en de sonar heb ik op een stepper motor geplaatst (uit een printer) en die wordt aangestuurd door een A4983 stepper driver.

De huidige code maakt 3 volle rondjes (elke ronde bestaat uit 48 metingen), maar ik wil het programma aanpassen zodat hij eerst rechtsom en daarna linksom gaat (anders komt de kabel van de sonar in de knoop...).

Als ik de data in excel stop dan krijg ik er zo'n grafiekje uit:
http://i691.photobucket.com/albums/vv274/zenoah/sonarscan1.jpg

Morgen als ik er tijd voor heb zal ik nog een paar testjes draaien met duidelijke voorwerpen erin en dan metingen vanaf verschillende plaatsen.

Voor het testen van de odometrie moet ik helaas weer een nieuwe driver bestellen...

Jb

Ziet er al cool uit zo in excel. Ga je nog een encoder op de stappenmotor zetten? Want nu ben je toch niet 100% zeker waar je aan het scannen bent?

Hebben jullie ook wel is het gevoel dat de elektronica je niet mag...
Eerst die motor driver, vervolgens lijkt die sonar scanner het goed te doen. Maar toen ik later meer wilde testen begon de motor eerst 2 volle rondjes heel snel te draaien voordat hij pas echt begon met het programma en vervolgens draait hij alleen nog maar als een gek rond...
Niks veranderd aan de software en aansluitingen ook allemaal het zelfde, dus zal wel aan de driver liggen...

Sonar later apart getest (om te kijken of er misschien iets met de uC aan de hand was) maar die deed het gewoon helemaal goed...

Niet erg bemoedigend...

Jb

Check op zwevende ingangen en reset pinnen. Ontkoppeling etc. Dat kan soms voor de meest vreemde spookwerkingen zorgen.

Ik weet niks van arduinos maar het valt me op dat je pinregisters een waarde geeft voordat je ze hebt verteld dat ze ingang of uitgang zijn. Persoonlijk doe ik dat liever andersom.

[Bericht gewijzigd door MAH op (44%)]

Doel je op het deel van de code waarin ik de integers een naam geef en er een pin aan toe wijs? En dan pas in de void setup vertel of ze in of output zijn? Voor zover ik weet is dit de juiste manier (met andere woorden iedereen met arduino code doet dit zo, maar wil niet zeggen dat het mooier kan uiteraard)

[Bericht gewijzigd door Henry S. op (40%)]