1   import interfaces.Controller;
2   import interfaces.AbstractRobot;
3   
4   /**
5   * This class is a 4-1 net (plus bias) whos input comes from 
6   * preprocessing 3 sensor inputs.
7   *
8   * The net was trained on 4 training patterns and generalises
9   * across 16 possible sets of binary inputs.
10  * see GBN3.training file for details.
11  * This robot tends to turn left when it thinks it is pointing
12  * the wrong way. See GBN4 for an implementation using only
13  * 3 training patterns and 8 possible sets of binary inputs.
14  *
15  * @author Graeme Bell
16  * @see GBN4
17  */
18  
19  public class GBN3 extends Controller {
20  
21  AbstractRobot r;
22  boolean initcalled;
23  boolean running;
24  private boolean paused=false;
25  
26  private int[] sensors={Controller.SENSOR_TYPE_LIGHT,Controller.SENSOR_TYPE_LIGHT,Controller.SENSOR_TYPE_LIGHT};
27  
28  // this looks rubbish - but it will compile to run extremely fast 
29  // this is because the weights will be inlined and the inputs/outputs
30  // won't need dereferencing or array overhead.
31  
32  float sens0;
33  float sens1;
34  float sens2;
35  
36  float input0;
37  float input1;
38  float input2;
39  float input3;
40  
41  // bias input is assumed to be +1
42  
43  float output0;
44  
45  final float weight00 = -0.75f;
46  final float weight10 = -0.75f;
47  final float weight20 = 0.1857f;
48  final float weight30 = 1.1088f;
49  final float weightb0 = -0.2127f;
50  
51      public void run(){
52  
53          running=true;
54              
55          while (running) {
56  
57                
58                  // get input
59                                                          
60                  sens0=r.getSensor1()/100.0f;
61                  sens1=r.getSensor2()/100.0f;
62                  sens2=r.getSensor3()/100.0f;
63                  
64                  // preprocessing
65                  
66                  if (sens0>sens1 && sens1>sens2) { input0=1.0f; } else {input0=0.0f;}
67                  if (sens0>sens1 && sens1<sens2) { input1=1.0f; } else {input1=0.0f;}
68                  if (sens0<sens1 && sens1>sens2) { input2=1.0f; } else {input2=0.0f;}
69                  if (sens0<sens1 && sens1<sens2) { input3=1.0f; } else {input3=0.0f;}
70  
71                  // this could be optimised by just adding weights according to value of inputs.
72                  // want to keep it looking like an FF neural net though to avoid worried looks.
73  
74                  //Sigmoidal activation function 1.0/1.0+exp(excitation)
75  
76                  output0 = 1.0f/(1.0f+(float)(Math.exp(  weight00*input0+
77                              weight10*input1+
78                              weight20*input2+
79                              weight30*input3+
80                              weightb0)));
81  
82                  //decide what to do.
83  
84                  if (output0<0.4) {r.right();}
85                  if (output0<0.6 && output0>=0.4) {r.forward();}
86                  if (output0>=0.6) {r.left();}
87                  
88                  try{Thread.sleep(500);}catch(Exception e){}
89            }
90      }
91  
92      
93      public void initController(AbstractRobot r) {
94  
95          this.r=r;
96          initcalled=true;
97      }
98      
99      public int[] getSensors(){
100     
101         return sensors;
102     }
103     
104     public void halt(){
105     
106         running=false;
107         r.stopMoving();
108     }
109     
110     public AbstractRobot getRobot(){
111     
112         return r;
113     }
114     
115     public GBN3() { }
116 
117 }   
118