/*
* Datei: RobEinfach.java
* Autor(en): Lukas König
* Java-Version: 6.0
* Erstellt: 13.03.2009
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
* author or licensor (but not in any way that suggests that they endorse
* you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
* distribute the resulting work only under the same or a similar license to
* this one.
*
* + Detailed license conditions (Germany):
* http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
* http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/
package eas.startSetup.marbBuilder.traceBetrachter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Observer;
import java.util.Random;
import eas.math.fundamentalAlgorithms.type2grammars.EarleyParser;
import eas.math.geometry.Vector2D;
import eas.miscellaneous.StaticMethods;
import eas.plugins.Plugin;
import eas.simulation.ConstantsSimulation;
import eas.simulation.agent.GenericSensor;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.AutomatenNummer;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.EndlicherAutomat;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.GlobaleMARBVariablen;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.Transition;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.ZInfo;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.conditions.Condition;
import eas.simulation.spatial.sim2D.marbSimulation.endlAutomat.conditions.ConditionNummer;
import eas.simulation.spatial.sim2D.marbSimulation.fitness.FitnessVerfahren;
import eas.simulation.spatial.sim2D.marbSimulation.mutation.CondMutVerfahren;
import eas.simulation.spatial.sim2D.marbSimulation.translator.ConstantsTranslator;
import eas.simulation.spatial.sim2D.marbSimulation.translator.Translator;
import eas.simulation.spatial.sim2D.marbSimulation.translator.script.ScriptInterpreter;
import eas.simulation.spatial.sim2D.marbSimulation.translator.versionOhneErgKante.ConstantsTranslatorWOC;
import eas.startSetup.ParCollection;
import eas.startSetup.marbBuilder.graph.Knoten;
/**
* Beschreibt einen Roboter, der im Wesentlichen ein endlicher Automat mit
* einigen Zusatzeigenschaften ist. Insbesondere wird in dieser Klasse nicht
* auf die Besonderheit mutierbarer übersetzer eingegangen. Wenn mutierbare
* übersetzer (Translatoren) verwendet werden sollen, dann muss die abgeleitete
* Klasse <code>Roboter</code> verwendet werden.
*
* @author Lukas König
*/
public class RobEinfach implements Serializable {
/**
* Die Codes der Verhaltensautomaten (i.A. nicht in der Standardkodierung).
*/
private LinkedList<Integer>[] verhCodes;
/**
* Die Versions-ID.
*/
private static final long serialVersionUID = -9000974806198171190L;
/**
* Die aktuelle Position des Roboters.
*/
private Vector2D position;
/**
* Der Winkel der Blickrichtung (gemessen zu einem Nullwinkel, der in
* die Richtung (1, 0) zeigt).
*/
private double winkel;
/**
* Vektor zur Beschreibung der Blickrichtung.
*/
private Vector2D blickrichtung;
/**
* Die Ausdehnung als Rechteck in X- und Y-Richtung.
*/
private Vector2D ausd;
/**
* Die Steuerungsautomaten des Roboters.
*/
private EndlicherAutomat[] vAut;
/**
* Die zu den Steuerungsautomaten gehörenden Fitnessfunktionen.
*/
private FitnessVerfahren[] fitVs;
/**
* Die Fitnesswerte der aktuellen Automaten.
*/
private int[] fits;
/**
* Die Bedingungen, die festlegen, welcher Automat aktiviert wird.
*/
private Condition[] conds;
/**
* Die aktuellen Zustand, in denen sich die endlichen Automaten des
* Roboters befinden.
*/
private Knoten[] aktZustand;
/**
* Vektor der Aktivzeiten in Zyklen der Automaten des Roboters.
*/
private long[] aktivZyklen;
/**
* Der aktuell aktive Automat.
*/
private int aktAut;
/**
* Die Sensoren. Wenn ein Sensor den Wert -1 enthält, wird er als
* "nicht aktuell" betrachtet und ein neues Ausrechnen beim nächsten
* Abfragen veranlasst.
*/
private int[] sensoren;
/**
* Liste generischer Sensoren
*/
private LinkedList<GenericSensor<?, ?, ?>> genericSensors;
/**
* Mapping von Sensor-IDs zu internen Sensornummern.
*/
private HashMap<String, Integer> sensorMapping;
/**
* Die Umgebung, auf der der Roboter steht.
*/
private Umgebung umg;
/**
* Speichert die Exkpunkte des Roboters.
*/
private Vector2D[] eckPunkte;
/**
* Speichert, ob die Eckpunkte aktuell berechnet sind.
*/
private boolean eckPunkteAktuell;
/**
* Die Winkel der Sensoren, gemessen am aktuellen Blickwinkel.
*/
private double[] absSensorWink;
/**
* Die Winkel der Sensoren, gemessen am aktuellen Nullwinkel.
*/
private double[] relSensorWink;
/**
* Die �ffnungswinkel der Sensoren.
*/
private double[] sensOeffn;
/**
* Die Anzahl der Sensoren.
*/
private int sensAnzIR;
/**
* Speichert alle zu prüfenden Sensorrichtungen (d.h. evtl. n / Sensor).
*
*/
private Vector2D[][] alleAbsSensRicht;
/**
* Die Bewegung, die aktuell ausgeführt wird (parallel zur Weiterausf�hrung
* des endlichen Automaten).
*/
private int aktBewegung;
/**
* Der Parameter für die aktuelle Bewegung, das ist die Anzahl der noch
* durchzuFührenden Bewegungsschritte.
*/
private int aktBewegungPar;
/**
* Speichert alle aktuell abzuarbeitenden Befehle, die KEINE
* Bewegungsbefehle sind.
*/
private ArrayList<Integer> aktBefehle;
/**
* Die Parameter für die aktuell abzuarbeitenden Befehle.
*/
private ArrayList<Double> aktBefehlePar;
/**
* Die Startzeit des Timers.
*/
private Date timerStart;
/**
* Das Mutationsverfahren für diesen Roboter.
*/
private CondMutVerfahren mut;
/**
* Die Zyklen zwischen zwei Mutationen.
*/
private long mutZyklen;
/**
* Die aktuelle Dauer des Experiments in Zyklen.
*/
private long expAktZyklen;
/**
* Die Zyklen zwischen zwei Fitnessberechnungen.
*/
private long[] fitAktZyklen;
/**
* Die Zyklen zwischen zwei FitnessRedberechnungen.
*/
private long[] fitRedAktZyklen;
/**
* Die Zyklen seit der letzten Mutation.
*/
private long mutAktZyklen;
/**
* Die Zyklen seit der letzten Fitnessberechnung.
*/
private long fitZyklen;
/**
* Die Zyklen seit der letzten FitnessRedberechnung.
*/
private long fitRedZyklen;
/**
* Der Wert, durch den bei der Reduktion dividiert wird.
*/
private double fitRedWert;
/**
* Der zuletzt ausgeführte Befehl.
*/
private int lastBf;
/**
* Der Earley-Erkenner.
*/
private EarleyParser earlErk;
/**
* Identifizierungsnummer des Roboters (-1 heißt ungültig).
*/
private int id;
/**
* Der Zufallsgenerator.
*/
private Random rand;
/**
* Die Parameter.
*/
private ParCollection pars;
/**
* Die zuletzt ausgeführten Befehle.
*/
private ArrayList<Integer> befehle;
/**
* Die Koordinaten bei der letzten Fitnessberechnung.
* (Wird nur von au�en gesetzt!)
*/
private Vector2D letztKoord;
/**
* Ob der Roboter selektiert ist.
*/
private boolean selektiert;
/**
* Ein Observer der Klasse.
*/
private Observer observer;
/**
* Ab welcher Sensornummer nicht mehr berechnet werden muss.
*/
public static final int NICHT_BER_AB = 7;
/**
* Die Anzahl der bisher registrierten Unf�lle.
*/
private int anzUnfaelle = 0;
/**
* Der Scriptinterpreter.
*/
private ScriptInterpreter scriptInt;
/**
* Ob das Verhalten bei der nächsten Mutation mutiert werden soll.
*/
private boolean mutV;
/**
* Die aktuell verwendeten Plugins für diesen Roboter.
*/
private List<Plugin<?>> pluginsAkt;
/**
* Die Anzahl generischer Sensoren, die evolviert werden.
*/
private int anzahlGenSensEvolv;
/**
* Initialisiert einen Roboter mit Werten von einem übergebenen Roboter.
* Dabei wird NICHT der Automat des Roboters kopiert und die ID des neuen
* Roboters wird auf einen UNG�LTIGEN Wert gesetzt.
*
* @param andererRob Der Roboter, dessen Werte übernommen werden sollen.
* @param params ParCollection.
* @param zufall Der Zufallsgenerator.
* @param sel Ob der Roboter selektiert ist.
*/
public RobEinfach(
final RobEinfach andererRob,
final ParCollection params,
final Random zufall,
final boolean sel) {
this(andererRob.getPosition().x,
andererRob.getPosition().y,
andererRob.getWinkel(),
andererRob.getAusd().x,
andererRob.getAusd().y,
andererRob.umg,
andererRob.earlErk,
andererRob.mut,
-1,
params,
zufall,
sel,
(VisMantel) andererRob.observer,
andererRob.vAuts()[0].getScriptInterpreter(),
andererRob.vAuts().length,
andererRob.pluginsAkt);
this.expAktZyklen = andererRob.expAktZyklen;
}
/**
* Initialisiert den Roboter.
*
* @param x X-Koordinate der Anfangsposition.
* @param y Y-Koordinate der Anfangsposition.
* @param wink Anfangswinkel der Blickrichtung in Grad.
* @param xAusd X-Ausdehnung.
* @param yAusd Y-Ausdehnung.
* @param umgebung Die Elternumgebung des Roboters.
* @param earl Der Earley-Erkenner für die Sequenz-Grammatik.
* @param mutation Das Mutationsverfahren für diesen Roboter.
* @param ident Die Identifikationsnummer des Roboters.
* @param params Die Parameter.
* @param zufall Der Zufallsgenerator.
* @param sel Ob der Roboter selektiert ist.
* @param obs Ein Observer der Klasse.
* @param scriInt Der ScriptInterpreter.
* @param autAnzahl Die Anzahl der Automaten, mit denen der Roboter
* ausgestattet sein soll.
*/
@SuppressWarnings(value = { "unchecked" })
public RobEinfach(
final double x,
final double y,
final double wink,
final double xAusd,
final double yAusd,
final Umgebung umgebung,
final EarleyParser earl,
final CondMutVerfahren mutation,
final int ident,
final ParCollection params,
final Random zufall,
final boolean sel,
final VisMantel obs,
final ScriptInterpreter scriInt,
final int autAnzahl,
final List<Plugin<?>> plugins) {
this.pars = params;
this.observer = obs;
this.verhCodes = new LinkedList[autAnzahl];
this.earlErk = earl;
this.scriptInt = scriInt;
this.initAuts(autAnzahl);
if (autAnzahl == 0) {
StaticMethods.log(StaticMethods.LOG_ERROR,
"Keine Startautomaten fuer Roboter "
+ ident
+ " angegeben.",
params);
}
this.selektiert = sel;
this.befehle = new ArrayList<Integer>();
this.id = ident;
this.rand = zufall;
double alpha = wink * Math.PI / 180;
this.timerStart = null;
this.aktBefehle = new ArrayList<Integer>();
this.aktBefehlePar = new ArrayList<Double>();
this.aktBewegung = 0;
this.aktBewegungPar = 0;
this.sensoren = new int[256];
this.position = new Vector2D(x, y);
this.ausd = new Vector2D(xAusd, yAusd);
this.blickrichtung = new Vector2D(
Math.cos(alpha) * this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR),
Math.sin(alpha) * this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR));
this.winkel = this.gultWinkel(wink);
this.umg = umgebung;
this.eckPunkte = new Vector2D[4];
this.setEckpVeraendert();
this.sensAnzIR = ConstantsSimulation.SENS_RICHT.length;
this.absSensorWink = new double[this.sensAnzIR];
this.sensOeffn = ConstantsSimulation.SENS_OEFFN;
this.relSensorWink = new double[this.sensAnzIR];
this.alleAbsSensRicht = new Vector2D[ConstantsSimulation.ABSTUFUNGEN]
[this.sensAnzIR];
for (int i = 0; i < this.sensAnzIR; i++) {
this.relSensorWink[i] = ConstantsSimulation.SENS_RICHT[i];
}
this.setzeSensorRicht();
this.mut = mutation;
this.mutAktZyklen = 0;
this.expAktZyklen = 0;
this.mutV = false;
this.lastBf = 0;
// Generische Sensoren.
this.anzahlGenSensEvolv = 0;
if (plugins == null) {
this.pluginsAkt = new LinkedList<Plugin<?>>();
} else {
this.pluginsAkt = plugins;
}
this.genericSensors = new LinkedList<GenericSensor<?, ?, ?>>();
for (int i = 0; i < this.sensoren.length; i++) {
this.sensoren[i] = -1;
this.genericSensors.add(null);
}
this.sensorMapping = new HashMap<String, Integer>();
this.genSensZuordnen();
this.genStateZuordnen();
}
/**
* Generische Zustände zuordnen.
*/
public void genStateZuordnen() {
}
/**
* Ordnet die generischen Sensoren zu Nummern zu.
*/
private void genSensZuordnen() {
}
/**
* @return Die Liste der generischen Sensoren in der Anordnung wie sie
* intern sortiert sind.
*/
public LinkedList<GenericSensor<?, ?, ?>> getGenSensListOrdered() {
return this.genericSensors;
}
/**
* Gibt zurück, ob der aktuelle Roboter selektiert ist.
*
* @return Ob selektiert.
*/
public boolean isSelektiert() {
return this.selektiert;
}
/**
* Erzeugt einen gültigen Winkel zwischen 0�(=) und 360�(<).
*
* @param w Der zu normalisierende Winkel.
*
* @return Der normalisierte Winkel.
*/
private double gultWinkel(final double w) {
double w2 = w;
while (w2 >= 360) { // Modulo??
w2 = w2 - 360;
}
while (w2 < 0) {
w2 = w2 + 360;
}
return w2;
}
/**
* Setzt die Sensorrichtungen in abhängigkeit des aktuellen Blickwinkels.
*/
private void setzeSensorRicht() {
double betaRAD;
double beta;
double teilWinkel;
for (int i = 0; i < this.sensAnzIR; i++) {
this.absSensorWink[i] = this.gultWinkel(
this.winkel
+ this.relSensorWink[i]);
// Der Startwinkel für die Sensor�ffnung.
beta = this.absSensorWink[i] - this.sensOeffn[i] / 2;
// Der Teilwinkel der Messung.
teilWinkel = this.sensOeffn[i]
/ ((double) ConstantsSimulation.ABSTUFUNGEN - 1);
for (int j = 0; j < ConstantsSimulation.ABSTUFUNGEN; j++) {
betaRAD = Math.PI * beta / 180;
this.alleAbsSensRicht[j][i] = new Vector2D(
Math.cos(betaRAD),
Math.sin(betaRAD));
beta = beta + teilWinkel;
}
}
}
/**
* @return Der zu setzende String für diesen Roboter.
*/
private String setzString() {
// if (this.pars.getAnzModus() == 1) {
// if (this.isSelektiert()) {
// return this.getFitString();
// }
// } else if (this.pars.getAnzModus() == 2) {
// return this.getFitString();
// }
return "";
}
/**
* Setzt die Position des Roboters.
*
* @param x X-Koordinate.
* @param y Y-Koordinate.
* @param gegKollIgnore Ob die Kollision mit einem Gegenstand ignoriert
* werden soll (führt NICHT zu Verschieben des
* Gegenstands).
*
* @return Ob der Roboter gesetzt werden konnte.
*/
public boolean setPos(final double x,
final double y,
final boolean gegKollIgnore) {
double xOld = this.position.x;
double yOld = this.position.y;
byte farbe;
if (this.isSelektiert()) {
farbe = ConstantsSimulation.FARBE_SEL;
} else {
farbe = ConstantsSimulation.FARBE_ROB;
}
this.position.setzeKoord(x, y);
this.setEckpVeraendert();
if (this.umg.setzeRobWennMoegl((Roboter) this,
gegKollIgnore,
farbe,
this.setzString())) {
return true;
} else {
this.position.setzeKoord(xOld, yOld);
this.setEckpVeraendert();
return false;
}
}
/**
* Setzt die Blickrichtung auf einen bestimmten Winkel in Grad. Dabei wird
* auch die SchrittLänge durch die _Länge_ des Blickrichtungs-Vektors
* gesetzt (automatisch). Der Winkel wird relativ zu einem Nullwinkel
* gemessen.
*
* @param alph Der Winkel der Blickrichtung in Grad.
*
* @return Ob der Blickwinkel geändert werden konnte.
*/
public boolean setBlck(final double alph) {
double alpha = this.gultWinkel(alph) * Math.PI / 180;
double winkOld = this.winkel;
double bxOld = this.blickrichtung.x;
double byOld = this.blickrichtung.y;
byte farbe;
if (this.isSelektiert()) {
farbe = ConstantsSimulation.FARBE_SEL;
} else {
farbe = ConstantsSimulation.FARBE_ROB;
}
this.winkel = this.gultWinkel(alph);
this.blickrichtung.setzeKoord(
Math.cos(alpha) * this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR),
Math.sin(alpha) * this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR));
this.setEckpVeraendert();
if (this.umg.setzeRobWennMoegl((Roboter) this,
true,
farbe,
this.setzString())) {
this.setzeSensorRicht();
return true;
} else {
this.blickrichtung.setzeKoord(bxOld, byOld);
this.winkel = winkOld;
this.setEckpVeraendert();
return false;
}
}
/**
* Setzt einen Roboter unbedingt in das Feld. Kollisionen werden nicht
* betrachtet.
*
* @param x X-Koordinate der Position.
* @param y Y-Koordinate der Position.
* @param alpha Winkel der Blickrichtung.
*/
protected void setRobUnbed(final double x,
final double y,
final double alpha) {
byte farbeRob;
if (this.isSelektiert()) {
farbeRob = ConstantsSimulation.FARBE_SEL;
} else {
farbeRob = ConstantsSimulation.FARBE_ROB;
}
this.umg.setzeRob(this.getEckPunkte(),
ConstantsSimulation.FARBE_HGND,
true,
false,
true);
this.setPosition(new Vector2D(x, y));
this.setBlickRicht(alpha);
this.umg.setzeRob(this.getEckPunkte(),
farbeRob,
true,
false,
true);
}
/**
* @return Returns the blickrichtung.
*/
public Vector2D getBlickrichtung() {
return this.blickrichtung;
}
/**
* @return Returns the position.
*/
public Vector2D getPosition() {
return this.position;
}
/**
* @return Returns the winkel.
*/
public double getWinkel() {
return this.winkel;
}
/**
* Erh�ht den aktuellen Parameter um den angegebenen Wert und normiert
* Werte >255 auf 255 und Werte <0 auf 0.
*
* @param wert Wert, um den erh�ht wird (dieser kann auch negativ sein).
*/
private void erhoeheAktPar(final int wert) {
if (this.aktBewegungPar + wert > 255) {
this.aktBewegungPar = 255;
} else if (this.aktBewegungPar + wert <= 0) {
this.aktBewegungPar = 0;
} else {
this.aktBewegungPar = this.aktBewegungPar + wert;
}
}
/**
* Erh�ht den Parameter des angegebenen Befehls in der Warteschlange um
* den angegebenen Wert und normiert Werte >255 auf 255 und Werte <0 auf 0.
*
* @param bef Befehlsnummer in der Liste abzuarbeitender Befehle, deren
* Parameter erh�ht werden soll.
* @param wert Wert, um den erh�ht wird (dieser kann auch negativ sein).
*/
private void erhoeheBefPar(final int bef,
final double wert) {
if (this.aktBefehlePar.get(bef).doubleValue()
+ wert > 255) {
this.aktBefehlePar.set(bef, new Double(255));
} else if (this.aktBefehlePar.get(bef).doubleValue()
+ wert <= 0) {
this.aktBefehlePar.set(bef, new Double(0));
} else {
this.aktBefehlePar.set(bef,
new Double(this.aktBefehlePar.get(bef).doubleValue()
+ wert));
}
}
/**
* Setzt einen neue aktuelle Bewegung und den Parameter.
*
* @param akt Der neue aktuelle Befehl.
* @param par Der Parameter für die Bewegung.
*/
private void setzeAktBewegung(final int akt,
final int par) {
this.aktBewegung = akt;
this.aktBewegungPar = par;
}
/**
* Simuliert einen Unfall, bei dem der Roboter um zufällige Grad gedreht
* und um einige Pixel verschoben wird. Ein Unfall sollte bei einer
* Kollision eingeleitet werden. Die Verschiebung findet nur statt, falls
* eine Kollision NACH dem Unfall vermieden werden kann (der Unfallzähler
* wird in jedem Fall hochgezählt).
*
* @param maxWinkel Der Winkel, um den der Roboter maximal gedreht wird.
* @return Ob der Unfall stattgefunden hat.
*/
public boolean unfallSimulation(final double maxWinkel) {
boolean erfolgreich = false;
double xVersch = 0;
double yVersch = 0;
int modus;
ArrayList<Integer> modi = new ArrayList<Integer>(6);
modi.add(new Integer(0));
modi.add(new Integer(1));
modi.add(new Integer(2));
modi.add(new Integer(3));
modi.add(new Integer(4));
modi.add(new Integer(5));
this.anzUnfaelle++;
GlobaleMARBVariablen.setCollCount(GlobaleMARBVariablen.getCollCount() + 1);
while (!erfolgreich && modi.size() > 0) {
modus = this.rand.nextInt(modi.size());
switch (modi.get(modus).intValue()) {
case 0:
xVersch = 1;
yVersch = 0;
break;
case 1:
xVersch = 0;
yVersch = 1;
break;
case 2:
xVersch = 1;
yVersch = 1;
break;
case 3:
xVersch = -1;
yVersch = 0;
break;
case 4:
xVersch = 0;
yVersch = -1;
break;
case 5:
xVersch = -1;
yVersch = -1;
break;
default:
break;
}
if (this.setPos(this.position.x + xVersch * ConstantsSimulation.SCHRITTW,
this.position.y + yVersch * ConstantsSimulation.SCHRITTW,
true)) {
erfolgreich = true;
}
modi.remove(modus);
}
if (this.setBlck(this.getWinkel()
- (this.rand.nextDouble() * maxWinkel))) {
erfolgreich = true;
}
return erfolgreich;
}
/**
* Drehung im Falle eines Unfalls.
*/
private double unfallSimDrehung = 360;
/**
* @param unfallDrehung The unfallSimDrehung to set.
*/
public void setUnfallSimDrehung(double unfallDrehung) {
this.unfallSimDrehung = unfallDrehung;
}
/**
* führt eine einzelne Aktion aus.
*
* @param akt Die Nummer der Aktion (0..255).
* @param bew Gibt an, ob es sich um einen Bewegungsbefehl handelt.
*
* @return Ob die Aktion ausgeführt werden konnte.
*/
private boolean aktion(
final int akt,
final boolean bew) {
boolean b = true;
int bewegungsWeite = 0;
double befehlsKonstante = 0;
final String befehl = ConstantsSimulation.befehlName(akt, this.pars);
if (!this.umg.getAgenten().contains(this)) {
throw new RuntimeException("Roboter ist nicht auf Feld.");
}
if (bew && this.aktBewegungPar <= 0) {
return false;
}
if (befehl.equals("Mov")) {
if (this.setPos(this.position.x
+ this.blickrichtung.x
* ConstantsSimulation.SCHRITTW,
this.position.y
+ this.blickrichtung.y
* ConstantsSimulation.SCHRITTW,
false)) {
b = true;
bewegungsWeite = (int) ConstantsSimulation.SCHRITTW;
} else {
b = unfallSimulation(this.unfallSimDrehung);
}
} else if (befehl.equals("TnR")) {
if (this.setBlck(this.winkel + ConstantsSimulation.WINKEL_SCHRITT)) {
b = true;
bewegungsWeite = (int) ConstantsSimulation.WINKEL_SCHRITT;
} else {
b = unfallSimulation(this.unfallSimDrehung);
}
} else if (befehl.equals("TnL")) {
if (this.setBlck(this.winkel - ConstantsSimulation.WINKEL_SCHRITT)) {
bewegungsWeite = (int) ConstantsSimulation.WINKEL_SCHRITT;
} else {
b = unfallSimulation(this.unfallSimDrehung);
}
} else if (befehl.equals("Tmr")) {
if (this.timerStart == null) {
this.timerStart = new Date();
} else {
Date aktZeit = new Date();
befehlsKonstante = ((double) (aktZeit.getTime()
- this.timerStart.getTime())) / 1000;
this.sensoren[7] = (int) ((this.aktBefehlePar.get(
this.aktBefehle.indexOf(new Integer(akt)))).doubleValue()
- befehlsKonstante) + 1;
this.timerStart = new Date();
}
} else if (!befehl.equals("Idl") && !befehl.equals("Stp")) {
}
if (bew) {
this.erhoeheAktPar(-bewegungsWeite);
} else {
this.erhoeheBefPar(this.aktBefehle.indexOf(new Integer(akt)),
-befehlsKonstante);
}
return b;
}
/**
* führt alle anstehenden Aktionen und die übergebene neue Aktion aus.
*
* @param akt Die Nummer der neuen Aktion (0..255).
* @param par Der Parameter für die neue Aktion (0..255).
*
* @return Ob alle anstehenden Aktionen ausgeführt werden konnten.
*/
public boolean gesamtAktion(
final int akt,
final int par) {
boolean b;
Iterator<Integer> itB;
Iterator<Double> itP;
byte aktB;
if (eas.miscellaneous.StaticMethods.enthaelt(
ConstantsSimulation.BEWEGUNGSBEFEHLE, akt)
|| GlobaleMARBVariablen.GENERISCHE_ZUSTAENDE.containsKey(akt)) {
if (this.aktBewegung == akt) {
this.erhoeheAktPar(par);
} else {
this.setzeAktBewegung(akt, par);
}
} else {
if (this.aktBefehle.contains(new Integer(akt))) {
this.erhoeheBefPar(this.aktBefehle.indexOf(new Integer(akt)),
par);
} else {
this.aktBefehle.add(new Integer(akt));
this.aktBefehlePar.add(new Double(par));
}
}
// Führe aktuelle Bewegung aus:
b = this.aktion(this.aktBewegung, true);
// Führe alle sonst anstehenden Aktionen aus:
itB = this.aktBefehle.iterator();
itP = this.aktBefehlePar.iterator();
while (itB.hasNext() && itP.hasNext()) {
aktB = itB.next().byteValue();
b = b & this.aktion(aktB, false);
}
return b;
}
/**
* Berechnet die Eckpunkte des Roboters.
*/
private void berechneEckpunkte() {
Vector2D e1 = new Vector2D(this.position.x, this.position.y);
Vector2D e2 = new Vector2D(this.position.x, this.position.y);
Vector2D e3 = new Vector2D(this.position.x, this.position.y);
Vector2D e4 = new Vector2D(this.position.x, this.position.y);
Vector2D b = this.blickrichtung;
Vector2D bn = new Vector2D(-this.blickrichtung.y, this.blickrichtung.x);
e1.x = e1.x + (b.x * this.ausd.x + bn.x * this.ausd.y) / 2;
e1.y = e1.y + (b.y * this.ausd.x + bn.y * this.ausd.y) / 2;
e2.x = e2.x + (b.x * this.ausd.x - bn.x * this.ausd.y) / 2;
e2.y = e2.y + (b.y * this.ausd.x - bn.y * this.ausd.y) / 2;
e3.x = e3.x + (-b.x * this.ausd.x + bn.x * this.ausd.y) / 2;
e3.y = e3.y + (-b.y * this.ausd.x + bn.y * this.ausd.y) / 2;
e4.x = e4.x + (-b.x * this.ausd.x - bn.x * this.ausd.y) / 2;
e4.y = e4.y + (-b.y * this.ausd.x - bn.y * this.ausd.y) / 2;
this.eckPunkte[0] = e1;
this.eckPunkte[1] = e2;
this.eckPunkte[2] = e3;
this.eckPunkte[3] = e4;
this.eckPunkteAktuell = true;
}
/**
* @return Returns the eckPunkte.
*/
public Vector2D[] getEckPunkte() {
if (!this.eckPunkteAktuell) {
this.berechneEckpunkte();
}
return this.eckPunkte;
}
/**
* Ob die Methode naechsterZustand() initial aufgerufen wird.
*/
private boolean initial = true;
/**
* Geht in den nächsten Zustand über.
*/
protected void naechsterZustand() {
int aktion;
int parameter;
LinkedList<Transition> bedingungen;
Transition aktBed;
ZInfo zusatz;
int folgeZ = 0;
Iterator<Transition> it;
int i = 0;
while (i < this.conds.length) {
if (this.conds[i].evaluiere(this)) {
if (this.initial || i != this.aktAut) {
this.aktAut = i;
this.vAut[this.aktAut].setzeChanged();
this.vAut[this.aktAut].notifyObservers(
new Integer(this.aktAut));
this.initial = false;
}
break;
}
i++;
}
this.expAktZyklen++;
this.fitAktZyklen[this.aktAut]++;
this.fitRedAktZyklen[this.aktAut]++;
this.aktivZyklen[this.aktAut]++;
this.mutAktZyklen++;
if (this.fitRedAktZyklen[this.aktAut] > this.fitRedZyklen) {
this.setFitness(this.aktAut,
(int) (this.getFitness()[this.aktAut]
/ this.fitRedWert));
this.fitRedAktZyklen[this.aktAut] = 0;
}
if (this.fitAktZyklen[this.aktAut] > this.fitZyklen) {
this.befehle.clear();
this.befehle.add(new Integer(this.lastBf));
this.fitAktZyklen[this.aktAut] = 0;
}
// if (this.pars.getEvol().booleanValue()) {
if (this.umg.getSimulation().isEvolution()) {
if (this.mutAktZyklen > this.mutZyklen) {
this.mutV = true;
this.mutiere();
this.mutAktZyklen = 0;
this.mutV = false;
GlobaleMARBVariablen.setVMutationInLetztemZyklus(true);
} else {
this.mutV = false;
GlobaleMARBVariablen.setVMutationInLetztemZyklus(false);
}
}
if (this.aktZustand[this.aktAut] == null) {
this.aktZustand[this.aktAut]
= this.vAut[this.aktAut].holeStartzustand();
}
if (this.isSelektiert()) {
if (this.aktZustand[this.aktAut] != null) {
this.vAut[this.aktAut].setzeChanged();
this.vAut[this.aktAut].notifyObservers(
this.aktZustand[this.aktAut]);
}
}
if (this.aktZustand[this.aktAut] != null) {
zusatz = this.aktZustand[this.aktAut].getInfo();
aktion = zusatz.getAktion();
parameter = zusatz.getParam();
this.gesamtAktion(aktion, parameter);
this.lastBf = aktion;
bedingungen = zusatz.getBeds();
it = bedingungen.iterator();
this.aktZustand[this.aktAut] = null;
while (it.hasNext() && folgeZ == 0) {
aktBed = it.next();
if (aktBed.evaluiere(this)) {
folgeZ = aktBed.getFolgezustand();
this.aktZustand[this.aktAut]
= this.vAut[this.aktAut].holeKnoten(
new Integer(folgeZ));
}
}
} else {
this.lastBf = 0;
}
}
/**
* Gibt einen Sensorenwert als den zugehörigen in der Umgebung gemessenen
* Wert zurück. Außerdem wird der betreffende Sensor im Array auf den
* entsprechenden Wert gesetzt, falls es ein statischer Sensor ist.
*
* @param sensNum Die Nummer des zu berechnenden Sensors.
*
* @return Der gemessene Sensorwert.
*/
public Object getSensorWert(final int sensNum) {
if (sensNum < NICHT_BER_AB) {
if (this.sensoren[sensNum] < 0) {
this.sensoren[sensNum] = this.umg.berSensWerte(
(Roboter) this, sensNum);
}
}
return this.sensoren[sensNum];
}
/**
* Gibt einen generischen Sensorenwert als den zugehörigen in der Umgebung
* gemessenen Wert zurück.
*
* @param sensID Der Name des zu berechnenden Sensors.
*
* @return Der berechnete Sensorwert.
*/
public Object getGenSensWert (final String sensID) {
return this.getSensorWert(this.getGenSensInternalNum(sensID));
}
/**
* Die intern verwendete Nummer für diesen Sensor.
*
* @param sensID Die ID des Sensors (String).
*
* @return Die interne ID (int). RuntimeException, falls nicht vorhanden.
*/
public int getGenSensInternalNum(final String sensID) {
return this.sensorMapping.get(sensID);
}
/**
* Achtung, diese Methode sollte nicht in jedem Zyklus aufgerufen werden,
* da sie zeitaufw�ndig sein kann.
*
* @return Alle Sensorwerte.
*/
public int[] getSensorWerte() {
for (int i = 0; i < 7; i++) {
this.getSensorWert(i);
}
return this.sensoren;
}
/**
* @return Returns the alleAbsSensRicht.
*/
public Vector2D[][] getAlleAbsSensRicht() {
this.setzeSensorRicht();
return this.alleAbsSensRicht;
}
/**
* @return Returns the sensOeffn.
*/
public double[] getSensOeffn() {
return this.sensOeffn;
}
/**
* Markiert die aktuellen Eckpunkte und berechneten Sensorwerte als
* ungültig.
*/
private void setEckpVeraendert() {
this.eckPunkteAktuell = false;
for (int i = 0; i < NICHT_BER_AB; i++) {
this.sensoren[i] = -1;
}
}
/**
* ACHTUNG! Diese Methode garantiert kein gültiges Platzieren des Roboters
* auf dem Feld. Sie ist nur dazu gedacht, den Roboter einmalig zu Beginn
* der Simulation zu verschieben. Es muss jedoch immer geprüft werden, ob
* die Verschiebung gültig war!
*
* @param pos The position to set.
*/
protected void setPosition(final Vector2D pos) {
this.setEckpVeraendert();
this.position = pos;
}
/**
* ACHTUNG! Diese Methode garantiert kein gültiges Platzieren des Roboters
* auf dem Feld. Sie ist nur dazu gedacht, den Roboter einmalig zu Beginn
* der Simulation zu verschieben. Es muss jedoch immer geprüft werden, ob
* die Verschiebung gültig war!
*
* @param beta Die Blickrichtung des Roboters.
*/
protected void setBlickRicht(final double beta) {
this.setEckpVeraendert();
this.winkel = beta;
double alpha = this.gultWinkel(beta) * Math.PI / 180;
this.winkel = this.gultWinkel(beta);
this.blickrichtung.setzeKoord(
Math.cos(alpha) * this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR),
Math.sin(alpha) * this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR));
}
/**
* Setzt den aktuellen Zustand des aktiven Automaten auf den Startzustand
* zurück.
*/
private void zustZuruecksetzen() {
this.aktZustand[this.aktAut]
= this.vAut[this.aktAut].holeStartzustand();
}
/**
* Mutiert die zu <code>this</code> gehörenden Automaten.
*/
public void mutiere() {
}
/**
* Mutiert die Bedingungen.
*/
public void mutiereBeds() {
for (int i = 0; i < this.conds.length; i++) {
this.conds[i] = this.mut.mutiere(this.conds[i]);
if (this.isSelektiert()) {
this.vAut[i].setzeChanged();
this.vAut[i].notifyObservers(
new ConditionNummer(this.conds[i].toString(),
i));
}
}
}
/**
* Setzt die Attribute des Objekts zurück.
*/
public void zuruecksetzen() {
this.expAktZyklen = 0;
for (int i = 0; i < this.vAut.length; i++) {
this.fitAktZyklen[i] = 0;
this.fitRedAktZyklen[i] = 0;
}
this.mutAktZyklen = 0;
this.lastBf = 0;
// Reset Fitness.
// this.sensoren[Konstanten.FIT_SENS - 1] = 0;
this.timerStart = null;
this.zustZuruecksetzen();
}
/**
* Setzt den Fitnesswert eines Automaten.
*
* @param autNum Die Nummer des Automaten.
* @param wert Der Wert, auf den gesetzt wird.
*/
public void setFitness(final int autNum, final int wert) {
this.fits[autNum] = wert;
//
// // Setze den entsprechenden Sensor, falls der 0. Automat gesetzt wird.
// if (autNum == 0) {
// this.sensoren[Konstanten.FIT_SENS - 1] = wert;
// }
}
/**
* @return Returns the umgebung.
*/
public Umgebung getUmg() {
return this.umg;
}
/**
* @return Returns the id.
*/
public int getId() {
return this.id;
}
/**
* Eine Textausgabe von <code>this</code>.
*
* @return Eine Textausgabe.
*/
@Override
public String toString() {
String s = "\n(";
s = s + this.id;
for (int i = 0; i < this.vAut.length; i++) {
s = s + " <" + this.getFitness()[i] + ": ";
s = s + this.conds[i] + ", ";
s = s + this.vAut[i].generateSequence() + "> ";
}
s = s + ")";
return s;
}
/**
* @return Returns the ausd.
*/
public Vector2D getAusd() {
return this.ausd;
}
/**
* @return Returns the aktZustand.
*/
public Knoten getAktZustand() {
return this.aktZustand[this.aktAut];
}
/**
* @return Returns the befehle.
*/
public ArrayList<Integer> getBefehle() {
return this.befehle;
}
/**
* @return Returns the letztKoord.
*/
public Vector2D getLetztKoord() {
return this.letztKoord;
}
/**
* @param letztK The letztKoord to set.
*/
public void setLetztKoord(final Vector2D letztK) {
this.letztKoord = letztK;
}
/**
* Selektiert den aktiven Roboter.
*
* @param sel The selektiert to set.
*/
public void setSelektiert(final boolean sel) {
if (this.selektiert != sel) {
this.selektiert = sel;
this.vAut[this.aktAut].setzeChanged();
this.vAut[this.aktAut].notifyObservers(
new AutomatenNummer(this.vAut[this.aktAut].erzeugeStringSeq(),
this.aktAut));
}
}
/**
* führt abschließende Aktionen nach Abschluss einer Simulation aus.
*/
public void simBeendet() {
for (int i = 0; i < this.vAut.length; i++) {
this.vAut[i].setzeChanged();
this.vAut[i].notifyObservers(
new AutomatenNummer(this.vAut[i].erzeugeStringSeq(),
i));
}
}
/**
* Initialisiert alle Variablen, die zu jedem Automaten separat Daten
* speichern (Arrays) oder von einer änderung der Automatenanzahl
* betroffen sein können.
*
* @param anzAuts Die Anzahl der Automaten.
*/
@SuppressWarnings(value = { "unchecked" })
protected void initAuts(final int anzAuts) {
this.aktAut = 0;
this.aktZustand = new Knoten[anzAuts];
this.conds = new Condition[anzAuts];
this.fits = new int[anzAuts];
this.aktivZyklen = new long[anzAuts];
this.fitVs = new FitnessVerfahren[anzAuts];
this.vAut = new EndlicherAutomat[anzAuts];
this.fitAktZyklen = new long[anzAuts];
this.fitRedAktZyklen = new long[anzAuts];
this.verhCodes = new LinkedList[anzAuts];
for (int i = 0; i < anzAuts; i++) {
this.aktivZyklen[i] = 0;
this.fitAktZyklen[i] = 0;
this.fitRedAktZyklen[i] = 0;
this.aktZustand[i] = null;
if (i < ConstantsSimulation.AUT_CONDS.length) {
this.conds[i] = ConstantsSimulation.AUT_CONDS[i];
} else {
this.conds[i]
= StaticMethods.ausFormatBed(this.conds[i - 1].formatted());
}
this.fits[i] = 0;
this.vAut[i] = new EndlicherAutomat(this.earlErk, this.scriptInt);
if (this.observer != null) {
this.vAut[i].addObserver(this.observer);
}
this.verhCodes[i] = this.getVAut()[i].generateSequence();
}
}
/**
* Erzeugt die Automaten neu aus den übergebenen Sequenzen.
* Wenn die Anzahl neuer Automaten nicht der Anzahl der bereits
* vorhandenen entspricht, werden die Automaten neu initialisiert, d.h.
* die meisten laufenden Variablen und zähler werden zurückgesetzt (siehe
* dazu Methode <code>private void initAuts(final int anzAuts)</code>.
* <P>
* Die Bedingungen werden nur initialisiert, wenn sie nicht als
* <code>null</code> übergeben wurden; anderenfalls werden die Bedingungen
* aus den Konstanten geladen.
*
* @param seq Die Sequenzen.
* @param cond Die Bedingungen (<code>null</code> erlaubt).
* @param trans Die Translatoren, die übersetzung der jeweiligen
* Verhaltensautomaten vornehmen sollen.
* @param pruefen Ob die Sequenzen syntaktisch geprüft werden sollen.
*/
public void erzeugeAusSequenzen(final String[] seq,
final Condition[] cond,
final Translator[] trans,
final boolean pruefen) {
Translator[] trans2 = trans;
String bereinigt;
if (trans2 == null) {
trans2 = new Translator[seq.length];
}
if (seq != null) {
if (this.vAut.length != seq.length) {
this.initAuts(seq.length);
}
for (int i = 0; i < seq.length; i++) {
if (trans2[i] != null) {
trans2[i].setModus(StaticMethods.MODUS_VERHALTEN);
}
this.vAut[i].generateFromSequence(
seq[i],
trans2[i],
pruefen, this.getPars());
bereinigt = (new EndlicherAutomat()).bereinige(seq[i]);
this.verhCodes[i] = StaticMethods.listSeqAusString(bereinigt);
if (cond != null && i < cond.length && cond[i] != null) {
this.conds[i] = cond[i];
}
}
}
if (this.isSelektiert()) {
for (int i = 0; i < this.vAut.length; i++) {
this.vAut[i].setzeChanged();
this.vAut[i].notifyObservers(
new AutomatenNummer(this.vAut[i].erzeugeStringSeq(),
i));
}
}
}
/**
* Erzeugt einen Automaten des Roboters aus seiner Sequenz und einer
* Bedingung. Die Bedingung muss nicht angegeben werden. Wenn kein
* Translator angegeben wird, wird der Standardtranslator verwendet.
*
* @param autNum Die Automatennummer.
* @param seq Die Sequenz.
* @param cond Die Bedingung.
* @param trans Der Translator.
* @param pruefen Ob die Sequenz syntaktisch geprüft werden soll.
*/
public void erzeugeAusSequenz(final int autNum,
final String seq,
final Condition cond,
final Translator trans,
final boolean pruefen) {
this.vAut[autNum].generateFromSequence(
seq,
trans,
pruefen, this.getPars());
if (cond != null) {
this.conds[autNum] = cond;
if (this.isSelektiert()) {
this.vAut[autNum].setzeChanged();
this.vAut[autNum].notifyObservers(
new ConditionNummer(this.conds[autNum].toString(),
autNum));
}
}
if (this.isSelektiert()) {
this.vAut[autNum].setzeChanged();
this.vAut[autNum].notifyObservers(
new AutomatenNummer(this.vAut[autNum].erzeugeStringSeq(),
autNum));
}
}
/**
* Erzeugt einen Automaten des Roboters aus seiner Sequenz und einer
* Bedingung. Die Bedingung muss nicht angegeben werden. ACHTUNG: Es wird
* kein Translator, sondern die Standardkodierung verwendet!
*
* @param autNum Die Automatennummer.
* @param seq Die Sequenz.
* @param cond Die Bedingung.
* @param pruefen Ob die Sequenz syntaktisch geprüft werden soll.
*/
public void erzeugeAusSequenz(final int autNum,
final String seq,
final Condition cond,
final boolean pruefen) {
this.vAut[autNum].erzeugeAusStdSequenz(seq, pruefen);
if (cond != null) {
this.conds[autNum] = cond;
if (this.isSelektiert()) {
this.vAut[autNum].setzeChanged();
this.vAut[autNum].notifyObservers(
new ConditionNummer(this.conds[autNum].toString(),
autNum));
}
}
if (this.isSelektiert()) {
this.vAut[autNum].setzeChanged();
this.vAut[autNum].notifyObservers(
new AutomatenNummer(this.vAut[autNum].erzeugeStringSeq(),
autNum));
}
}
/**
* @return Returns the observer.
*/
public Observer getObserver() {
return this.observer;
}
/**
* @return Returns the anzUnfaelle.
*/
public int getAnzUnfaelle() {
return this.anzUnfaelle;
}
/**
* Setzt die Anzahl der Unf�lle zurück.
*/
public void resetAnzUnf() {
this.anzUnfaelle = 0;
}
/**
* @return Returns the pars.
*/
public ParCollection getPars() {
return this.pars;
}
/**
* Gibt die zu <code>this</code> gehörende Automatensequenz zurück.
*
* @param autNum Die Nummer des Automaten.
*
* @return Die Automatensequenz.
*/
public synchronized LinkedList<Integer> erzeugeSequenz(final int autNum) {
return this.vAut[autNum].generateSequence();
}
/**
* @return Returns the active vAutomat.
*/
public EndlicherAutomat getAktVAut() {
return this.vAut[this.aktAut];
}
/**
* Gibt alle Verhaltensautomaten zurück.
*
* @return Die V-Automaten.
*/
public EndlicherAutomat[] vAuts() {
return this.vAut;
}
/**
* Gibt zurück, ob der übergebene Knoten der Startknoten des aktiven
* Automaten ist.
*
* @param k Der zu überpf�fende Knoten.
* @return Ob der Knoten der Startknoten ist.
*/
public boolean istStartZ(final Knoten k) {
return this.vAut[this.aktAut].istStartZ(k);
}
/**
* @return Ein Array der Stringsequenzen der Automaten des Roboters.
*/
public String[] erzeugeStrSeqs() {
String[] sequenzen = new String[this.vAut.length];
for (int i = 0; i < sequenzen.length; i++) {
sequenzen[i] = this.erzeugeStringSequenz(i);
}
return sequenzen;
}
/**
* @param autNum Die Nummer des Automaten, dessen Sequenz erzeugt werden
* soll.
*
* @return Die String-Sequenz des Automaten mit der angegebenen Nummer.
*/
public String erzeugeStringSequenz(final int autNum) {
return this.vAut[autNum].erzeugeStringSeq();
}
/**
* @return Summe aller Fitnesswerte dieses Roboters.
*/
public long getFitSum() {
long sum = 0;
for (int i = 0; i < this.vAut.length; i++) {
sum += this.fits[i];
}
return sum;
}
/**
* @return Returns the fits.
*/
public int[] getFitness() {
return this.fits;
}
/**
* @return Returns the conds.
*/
public Condition[] getConds() {
return this.conds;
}
/**
* lädt den Roboter mit Verhaltensautomat, Translator und Bedingungen
* aus Dateien mit Namen, die dem Muster<BR>
* graphName.X<BR>
* entsprechen, wobei X \in {gra, tra, con} ist.
*
* @param graphName Der Name der Datei, aus der der Roboter geladen
* werden soll.
*/
protected void ladeAuts(final String graphName) {
String pfad = this.pars.getStdDirectory() + File.separator;
String[] sequenzen;
Condition[] bedingungen = null;
FileInputStream fs;
ObjectInputStream is;
String datRawName = pfad + graphName + ".";
Translator[] trans;
try {
fs = new FileInputStream(
datRawName + eas.startSetup.marbBuilder.ConstantsGraphVis.GRAPH_ENDUNG);
is = new ObjectInputStream(fs);
sequenzen = (String[]) is.readObject();
is.close();
} catch (final Exception e) {
throw new RuntimeException("Graph nicht geladen.");
}
try {
fs = new FileInputStream(datRawName
+ eas.startSetup.marbBuilder.ConstantsGraphVis.BED_ENDUNG);
is = new ObjectInputStream(fs);
bedingungen = (Condition[]) is.readObject();
is.close();
} catch (final Exception e) {
StaticMethods.log(StaticMethods.LOG_WARNING,
"Bedingung(en) nicht gefunden: "
+ datRawName
+ eas.startSetup.marbBuilder.ConstantsGraphVis.BED_ENDUNG,
this.pars);
}
// Erzeuge Translatoren für Verhaltensautomaten.
trans = new Translator[sequenzen.length];
if (this.pars.getParValueBoolean("UseTranslatorWITHCompletingTransitions")) {
for (int i = 0; i < trans.length; i++) {
trans[i] = ConstantsTranslator.getStdTranslatorBE(this.pars);
}
} else {
for (int i = 0; i < trans.length; i++) {
trans[i] = ConstantsTranslatorWOC.getStdTranslatorBE(this.pars);
}
}
this.erzeugeAusSequenzen(
sequenzen,
bedingungen,
trans,
false);
}
/**
* Speichert die Automaten des Roboters unter einem vorgegebenen Namen.
*
* @param graphName Der Dateiname, unter dem gespeichert werden soll.
*/
public void speichereAuts(final String graphName) {
String pfad = this.pars.getStdDirectory() + File.separator;
FileOutputStream fs;
ObjectOutputStream os;
try {
// Speichere Automaten.
fs = new FileOutputStream(
pfad
+ graphName
+ "."
+ eas.startSetup.marbBuilder.ConstantsGraphVis.GRAPH_ENDUNG);
os = new ObjectOutputStream(fs);
os.writeObject(this.erzeugeStrSeqs());
os.close();
// Speichere Bedingungen.
fs = new FileOutputStream(
pfad
+ graphName
+ "."
+ eas.startSetup.marbBuilder.ConstantsGraphVis.BED_ENDUNG);
os = new ObjectOutputStream(fs);
os.writeObject(this.conds);
os.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Gibt die Fitnesswerte als String zurück.
*
* @return Die Fitnesswerte als String.
*/
public String getFitString() {
String s = "";
for (int i = 0; i < this.fits.length - 1; i++) {
s += this.fits[i] + ",";
}
s += this.fits[this.fits.length - 1];
return s;
}
/**
* @param conditions Die Bedingungen.
*/
public void setConds(final Condition[] conditions) {
this.conds = conditions;
}
/**
* Setzt die Bedingung mit der Nummer <code>autNum</code>.
*
* @param autNum Die Automatennummer.
* @param cond Die zu setzende Bedingung.
*/
public void setCond(final int autNum, final Condition cond) {
this.conds[autNum] = cond;
}
/**
* Setzt die Aktivzeit des Automaten zurück.
*
* @param autNum Die Nummer des zurückzusetzenden Automaten.
*/
public void resetAktivZyk(final int autNum) {
this.aktivZyklen[autNum] = 0;
}
/**
* @param autNum Der Automat, dessen Aktivzyklen zurückgegeben werden
* sollen.
*
* @return Die Aktivzyklen des Automaten.
*/
public long getAktivZyklen(final int autNum) {
return this.aktivZyklen[autNum];
}
/**
* @return Die Nummer des aktiven Automaten.
*/
public int getAktAutNum() {
return this.aktAut;
}
/**
* @return Die Verhaltensautomaten.
*/
public EndlicherAutomat[] getVAut() {
return this.vAut;
}
/**
* @return Ob das Verhalten mutiert werden soll.
*/
public boolean isMutV() {
return this.mutV;
}
/**
* @return Der Earleyerkenner von <code>this</code>.
*/
public EarleyParser getEarlErk() {
return this.earlErk;
}
/**
* @return Das Mutationsverfahren.
*/
public CondMutVerfahren getMut() {
return this.mut;
}
/**
* @return Die aktuelle Zyklenzahl des Gesamtexperiments.
*/
public long getExpAktZyklen() {
return this.expAktZyklen;
}
/**
* @return Returns the lastBf.
*/
public int getLastBf() {
return this.lastBf;
}
/**
* @param lastBf The lastBf to set.
*/
public void setLastBf(int lastBf) {
this.lastBf = lastBf;
}
/**
* Gibt die Codes der Verhaltensautomaten zurück.
*
* @return Die Codes der Verhaltensautomaten.
*/
public LinkedList<Integer>[] getVerhCodes() {
return this.verhCodes;
}
/**
* @param vC Setzt die Verhaltenscodes.
*/
public void setVerhCodes(final LinkedList<Integer>[] vC) {
this.verhCodes = vC;
}
/**
* @param vc Setzt den aktiven Verhaltenscode.
*/
public void setAktVCode(final LinkedList<Integer> vc) {
this.verhCodes[this.getAktAutNum()] = vc;
}
/**
* @return Returns the fitVs.
*/
public FitnessVerfahren[] getFitVs() {
return this.fitVs;
}
/**
* Maximalgeschwidigkeit der Räder.
*/
private final double maxGesch = 10;
/**
* Minimalgeschwidigkeit der Räder.
*/
private final double minGesch = -10;
/**
* Geschwindigkeit des linken Rades in Winkel (Radians) / Zyklus.
*/
private double geschwRechts = 0;
/**
* Geschwindigkeit des rechten Rades in Winkel (Radians) / Zyklus.
*/
private double geschwLinks = 0;
/**
* Geschwindigkeit, unter der das Rad als nichtbewegend gilt.
*/
private final double epsilon = 1e-100;
/**
* Berechnet die Strecke, die ein Rad auf eine Ebene abrollt, wenn es sich
* bei einem angegeben Radius um einen bestimmten Winkel um die Mittelachse
* dreht. Die Reibung wird dabei als unendlich angesehen. (Also eigentlich
* wird einfach die Länge des Kreisbogens um den angegebenen Winkel
* berechnet.)
*
* @param winkRadians Der Winkel, um den sich das Rad dreht.
* @param radRadius Der Radius des Rades.
*
* @return Die vom Rad abgerollte Strecke.
*/
private double streckeGefahrenBeiWink(
final double winkRadians,
final double radRadius) {
return radRadius * winkRadians;
}
/**
* führt die angegebene Drehung / Zyklus der beiden Räder INVERTIERT ab.
* Für eine nicht invertierte Bewegung ist die Methode
* <code>vorwaerts</code> vorgesehen.
*
* @return Ob die Bewegung erfolgreich war (oder aufgrund von Kollisionen
* zurückgesetzt werden musste).
*/
public boolean rueckwaerts() {
double altdrehL = this.geschwLinks;
double altdrehR = this.geschwRechts;
boolean erfolgreich;
this.geschwLinks *= -1;
this.geschwRechts *= -1;
erfolgreich = this.vorwaerts();
this.geschwLinks = altdrehL;
this.geschwRechts = altdrehR;
return erfolgreich;
}
/**
* führt die angegebene Drehung / Zyklus der beiden Räder ab. Dabei wird
* die Drehrichtung so beibehalten, wie sie die Motoren angeben. Für eine
* Invertierung der Drehrichtung kann die Methode <code>rueckwaerts</code>
* verwendet werden.
*
* @return Ob die Bewegung erfolgreich war (oder aufgrund von Kollisionen
* zurückgesetzt werden musste).
*/
public boolean vorwaerts() {
// Bevor "getRadRadius" in die Umgebung verlagert wurde.
// double r = this.streckeGefahrenBeiWink(
// this.geschwRechts, this.pars.getRadRadius().x)
// * this.pars.getVerzerr();
// double l = this.streckeGefahrenBeiWink(
// this.geschwLinks, this.pars.getRadRadius().y)
// * this.pars.getVerzerr();
double r = this.streckeGefahrenBeiWink(
this.geschwRechts, 1)
* this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR);
double l = this.streckeGefahrenBeiWink(
this.geschwLinks, 1)
* this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR);
double b = this.ausd.x * this.pars.getParValueDouble(eas.statistics.ConstantsStatistics.VERZERR_ATTR);
double rad;
double alpha;
Vector2D neuPos = new Vector2D(this.getPosition());
Vector2D mitte = new Vector2D(this.getPosition());
Vector2D richtung = new Vector2D(this.getBlickrichtung());
Vector2D altePos;
double alteBlick;
boolean bool;
if (Math.abs(l) < this.epsilon && Math.abs(r) < this.epsilon) {
return true; // Beide Räder auf Null.
} else if (Math.abs(l - r) < this.epsilon) { // Differenz gleich.
neuPos = new Vector2D(this.getPosition());
richtung = new Vector2D(this.getBlickrichtung());
richtung.setLength(r);
neuPos.translate(richtung);
// umg.setzeLinie(mitte.x, mitte.y, neuPos.x, neuPos.y,
// Konstanten.FARBEN_BENUTZER[farbe], true, false, true, false);
return this.setPos(neuPos.x, neuPos.y, false);
} else if (Math.abs(l + r) < this.epsilon) { // Genau entgegengesetzt.
rad = b / 2;
alpha = r / rad;
// umg.setzeLinie(mitte.x, mitte.y, neuPos.x, neuPos.y,
// Konstanten.FARBEN_BENUTZER[farbe], true, false, true, false);
return this.setBlck(this.getWinkel() - alpha / Math.PI * 180);
} else if (Math.abs(l) > Math.abs(r)) {
rad = b / (l / r - 1) + b / 2;
richtung.ortho();
richtung.setLength(rad);
mitte.sub(richtung);
if (r * l > 0) { // r und l haben dasselbe Vorzeichen.
alpha = r / rad;
} else {
alpha = 2 * r / b;
}
alpha = l / rad;
neuPos.rotate(mitte, alpha);
altePos = new Vector2D(this.getPosition());
alteBlick = this.getWinkel();
bool = this.setPos(neuPos.x, neuPos.y, false);
// umg.setzeLinie(mitte.x, mitte.y, neuPos.x, neuPos.y,
// Konstanten.FARBEN_BENUTZER[farbe], true, false, true, false);
if (bool) {
bool = this.setBlck(this.getWinkel() + alpha / Math.PI * 180);
if (!bool) {
this.setBlck(alteBlick);
this.setPos(altePos.x, altePos.y, false);
return false;
}
return true;
} else {
this.setPos(altePos.x, altePos.y, false);
return false;
}
} else if (Math.abs(r) > Math.abs(l)) {
rad = b / (r / l - 1) + b / 2;
richtung.ortho();
richtung.setLength(rad);
mitte.translate(richtung);
if (r * l > 0) { // r und l haben dasselbe Vorzeichen.
alpha = r / rad;
} else {
alpha = 2 * r / b;
}
neuPos.rotate(mitte, -alpha);
altePos = new Vector2D(this.getPosition());
alteBlick = this.getWinkel();
bool = this.setPos(neuPos.x, neuPos.y, false);
// umg.setzeLinie(mitte.x, mitte.y, neuPos.x, neuPos.y,
// Konstanten.FARBEN_BENUTZER[farbe], true, false, true, false);
if (bool) {
bool = this.setBlck(this.getWinkel() - alpha / Math.PI * 180);
if (!bool) {
this.setBlck(alteBlick);
this.setPos(altePos.x, altePos.y, false);
return false;
}
return true;
} else {
this.setPos(altePos.x, altePos.y, false);
return false;
}
}
throw new RuntimeException("Fall nicht abgefangen in Methode vorwaerts"
+ ": l = " + l + " / r = " + r + ".");
}
/**
* Setzt die Radgeschwidigkeit des linken Rades
* in Winkel (Radians) / Zyklus. (Wird bei minGesch und maxGesch
* abgeschnitten.)
*
* @param wert Der Wert, auf den die Geschwindigkeit gesetzt werden soll.
*/
public void setGeschRadLinks(final double wert) {
double alterWert = this.geschwLinks;
this.geschwLinks = Math.min(
Math.max(wert, this.minGesch),
this.maxGesch);
if (Math.abs(alterWert - this.geschwLinks) >= this.epsilon) {
StaticMethods.log(
StaticMethods.LOG_STAGE1,
"Neue Geschwindigkeit linkes Rad - " + wert + " / Zyklus",
this.pars);
}
}
// int farbe = 0;
/**
* Setzt die Radgeschwidigkeit des rechten Rades
* in Winkel (Radians) / Zyklus. (Wird bei minGesch und maxGesch
* abgeschnitten.)
*
* @param wert Der Wert, auf den die Geschwindigkeit gesetzt werden soll.
*/
public void setGeschRadRechts(final double wert) {
double alterWert = this.geschwRechts;
this.geschwRechts = Math.min(
Math.max(wert, this.minGesch),
this.maxGesch);
if (Math.abs(alterWert - this.geschwRechts) >= this.epsilon) {
// farbe = new Random().nextInt(Konstanten.FARBEN_BENUTZER.length);
StaticMethods.log(
StaticMethods.LOG_STAGE1,
"Neue Geschwindigkeit rechtes Rad - " + wert + " / Zyklus",
this.pars);
}
}
/**
* @return Returns the anzahlGenSensEvolv.
*/
public int getAnzahlGenSensEvolv() {
return this.anzahlGenSensEvolv;
}
/**
* @return Returns the geschwRechts.
*/
public double getGeschwRechts() {
return this.geschwRechts;
}
/**
* @return Returns the geschwLinks.
*/
public double getGeschwLinks() {
return this.geschwLinks;
}
}