Grundlage: Die Klasse Motor
Motoren bewegen
Die KlasseMotor
bildet die Grundlage zum Ansteuern der Servomotoren. Sie stellt Methoden zum Vor- und Zurückfahren,
Auslesen und Zurücksetzen des Tachometers, Setzen der Geschwindigkeit und Einstellen des Betriebsmodus eines Motors bereit.
Anstelle eines Konstruktors besitzt Motor
3 statische Instanzen ihrer selbst: Motor.A, Motor.B
und Motor.C
,
die zum Ansteuern des jeweiligen Motorports dienen. Zum Vorwärtsbewegen eines Motors gibt es drei Möglichkeiten:
Motor.A.forward(); // Unbegrenztes Vorwärtsfahren, sofortige Rückkehr zum Programm Motor.A.forward(300); // Begrenztes Vorwärtsfahren, Rückkehr zum Programm nach Beenden der Fahrt Motor.A.forward(300, true); // Begrenztes Vorwärtsfahren, sofortige Rückkehr zum ProgrammAnaloges gilt für das Rückwärtsfahren. Die übergebenen Zahlenwerte sind hier die Anzahl der "Ticks": 360 Ticks entsprechen ungefähr einer 360°-Drehung des Motors.
Geschwindigkeit
Die Geschwindigkeit regulieren kann man mit der MethodesetSpeed(int)
, wobei die
Geschwindigkeit als Zahlenwert zwischen 0 und 100 übergeben wird. Durch einige sehr einfache Versuche mit der Stoppuhr konnten folgende Werte ermittelt werden:
Übergebener Zahlenwert | Gemessene Zeit auf 1m | Geschwindigkeit in m/s |
25 | 0:13.48 s | 0,07418 m/s |
50 | 0:05.71 s | 0,17513 m/s |
75 | 0:03.65 s | 0,27397 m/s |
100 | 0:02.84 s | 0,35211 m/s |
Vorwärts- und Rückwärtsfahren
Um den Legoroboter Vorwärtsfahren zu lassen, muss man i.d.R. zwei Motoren gleichzeitig fahren lassen. Wenn man dies mit dem offensichtlichsten AnsatzMotor.B.forward(); Motor.C.forward();probiert, führt dies zu Problemen: Die Motoren springen unterschiedlich schnell an, der Mindstorm dreht sich, bevor er geradeaus losfährt. Um zwei Motoren gleichzeitig starten zu können, muss man die beiden synchronisieren:
Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC); Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC); Motor.C.forward(1080, true); Motor.B.forward(1080, false);und anschließend z.B. mit
REGULATION_MODE_MOTOR_SPEED
wieder die Synchronisation entfernen:
Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED); Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED);Würde man die Synchronisation nicht wieder herausnehmen, würde ein Befehl an einen einzelnen Motor wie z.B.
Motor.C.forward(300);den NXT verwirren und er beginnt entweder planlos den Motor zu bewegen oder tut nichts mehr.
SyncMotors
Um nicht ständig mit den Regulation Modes der Motoren jonglieren zu müssen gibt es die KlasseSyncMotors
,
die neben den bereits oben genannten Fähigkeiten von Motor
auch noch zwei Motoren synchronisieren kann. Selbstverständlich sollte man es vermeiden,
mit SyncMotors
verbundene Motoren über Motor
anzusteuern. Denn ist der Motor im Moment im Synchronisationsmodus sind die Reaktionen
des NXT nicht vorhersehbar. An dieser Stelle bin ich in der iCommand API auf einen Bug gestoßen:
Die Methoden left(...)
und right(...)
haben die Synchronisation nicht aufgehoben, weshalb ich eine Methode
setSync(boolean)
eingefügt habe, die die Synchronisation setzen und wieder aufheben kann.
Um also zwei Motoren mit SyncMotors
zu verbinden muss einfach ein Objekt der Klasse erstellt werden:
SyncMotors sm = new SyncMotors(Motor.C, Motor.B);Der erste Parameter ist hier der linke Motor und der zweite der rechte. Vorwärts- und Rückwärtsfahren und Setzen der Geschwindigkeit funktioniert hier genau wie bei
Motor
.
Rotation
Lediglich die Möglichkeit der Rotation ist hinzugekommen. Mit den beiden Methodenleft(...)
und right(...)
kann man die Motoren einzeln ansteuern und so den Roboter
nach links bzw. rechts rotieren lassen. Hierbei dreht er sich um das jeweils ruhende Rad. Für diese beiden Methoden muss der NXT allerdings erst zum stehen kommen.
Um den NXT während der Fahrt die Richtung ändern zu lassen, muss man ein bisschen tricksen. Erst lassen wir den Roboter vorwärts fahren
SyncMotors sm = new SyncMotors(Motor.C, Motor.B); sm.setSpeed(24); sm.forward();und warten erstmal 3 Sekunden.
wait(3000);Nun deaktivieren wir die Synchronisation,
Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED); Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SPEED);setzen die Geschwindigkeit vom linken Rad hoch,
sm.left.setSpeed(48); sm.right.setSpeed(24);geben dem linken Rad das Geschwindigkeitsupdate durch
sm.left.forward();und warten wieder erstmal 7 Sekunden.
wait(7000);Nun synchronisieren wir die Motoren wieder
Motor.B.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC); Motor.C.setRegulationMode(icommand.nxtcomm.NXTProtocol.REGULATION_MODE_MOTOR_SYNC);und halten an
sm.stop();Die zweimal auftauchende Funktion
wait
ist wie folgt implementiert:
public static void wait(int ms) { long start_time = System.currentTimeMillis(); while(System.currentTimeMillis() - start_time < ms) {} }Wartet also einfach die in Millisekunden übergebene Zeit ab.
1:
http://mindstorms.lego.com/Overview/Interactive_Servo_Motors.aspx
2:
http://lejos.sourceforge.net/p_technologies/nxt/icommand/api/icommand/platform/nxt/Motor.html
<Lokale Kopie>
3:
http://lejos.sourceforge.net/p_technologies/nxt/icommand/api/icommand/platform/nxt/SyncMotors.html
<Lokale Kopie>
ServoNavigator
Um den Roboter zu bewegen reicht im Prinzip die Klasse SyncMotors
aus. Allerdings gibt es noch die Klasse
ServoNavigator
, mit der man etwas einfacher navigieren kann.
So gibt es in dieser Klasse Methoden, mit denen man den Roboter eine gewisse Strecke (angegeben in Abständen in metrischen Einheiten) lassen kann
oder ihn um eine bestimmte Gradzahl drehen lassen kann. Außerdem speichert diese Klasse die aktuelle Position in einer x und y Koordinate.
Hierfür muss man dem Konstruktor einige physikalische Parameter übergeben:
SyncMotors sm = new SyncMotors(Motor.C, Motor.B); ServoNavigator sn = new ServoNavigator(56.0, 11.5, 360.0, sm);Der erste Parameter ist hier der Durchmesser eines Reifens (in mm). Der zweite gibt an, wie weit die Reifen voneinander entfernt sind (in cm) und der Dritte wieviele Ticks für eine volle Umdrehung des Reifens benötigt werden. Ist der Reifen direkt am Motor befestigt, kann dieser Parameter auch weggelassen werden, er ist dann standardmäßig 360.0.
Genauigkeit
Beim Vorwärtsfahren
Hierzu das Testprogramm Forward.javaimport icommand.platform.nxt.*; import icommand.nxtcomm.*; import icommand.robotics.*; public class Forward { public static void usage() { System.out.println("Usage:"); System.out.println(" java Forward <speed> <distance>"); System.out.println(""); System.out.println(" speed: Integeger between 1 and 255"); System.out.println(" distance: Distance in cm"); } public static void main(String[] args) { if(args.length < 2) { usage(); return; } int speed = Integer.parseInt(args[0]); int distance = Integer.parseInt(args[1]); SyncMotors sm = new SyncMotors(Motor.C, Motor.B); sm.setSpeed(speed); ServoNavigator sn = new ServoNavigator(56.0, 11.5, 360.0, sm); sn.travel(distance); NXTCommand.close(); } }und dieser Versuchsaufbau
liefert die Werte
zu fahrende Entfernung | gefahrene Entfernung bei Geschwindigkeit | |||
25 | 50 | 75 | 100 | |
20 | 18 | 20 | 23 | 25 |
50 | 48 | 50 | 52 | 54 |
100 | 96 | 99 | 100 | 105 |
Beim Rotieren
Mit einem simplen Versuch mit der Testunterlage von Lego und dem Programm Rotate.java kann man die Genauigkeit der Rotation messen. Allerdings geht es auch hier rein um das Abfahren von vorher definierten Strecken, die Genauigkeit verhält sich bei der Rotation also genauso wie beim Geradeausfahren.
1:
http://lejos.sourceforge.net/p_technologies/nxt/icommand/api/icommand/robotics/ServoNavigator.html
<Lokale Kopie>