RLPark 1.0.0
Reinforcement Learning Framework in Java
|
00001 package rlpark.plugin.irobot.internal.serial; 00002 00003 import gnu.io.CommPortIdentifier; 00004 import gnu.io.PortInUseException; 00005 import gnu.io.SerialPort; 00006 import gnu.io.SerialPortEvent; 00007 import gnu.io.SerialPortEventListener; 00008 import gnu.io.UnsupportedCommOperationException; 00009 00010 import java.io.IOException; 00011 import java.util.Arrays; 00012 import java.util.Collections; 00013 import java.util.HashMap; 00014 import java.util.Map; 00015 import java.util.TooManyListenersException; 00016 import java.util.concurrent.Semaphore; 00017 import java.util.concurrent.TimeUnit; 00018 00019 import rlpark.plugin.robot.internal.disco.drops.DropByteArray; 00020 import zephyr.plugin.core.api.signals.Listener; 00021 import zephyr.plugin.core.api.signals.Signal; 00022 00023 public class SerialPortToRobot implements SerialPortEventListener { 00024 static public final boolean ExpectedIgnored = false; 00025 static public boolean DebugSignals = false; 00026 00027 public static class SerialPortInfo { 00028 public int rate = 115200; 00029 public int databits = SerialPort.DATABITS_8; 00030 public int stopbits = SerialPort.STOPBITS_1; 00031 public int parity = SerialPort.PARITY_NONE; 00032 public int flowControl = SerialPort.FLOWCONTROL_NONE; 00033 00034 public SerialPortInfo() { 00035 this(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, SerialPort.FLOWCONTROL_NONE); 00036 } 00037 00038 public SerialPortInfo(int rate, int databits, int stopbits, int parity, int flowControl) { 00039 this.rate = rate; 00040 this.databits = databits; 00041 this.stopbits = stopbits; 00042 this.parity = parity; 00043 this.flowControl = flowControl; 00044 } 00045 } 00046 00047 protected final SerialStreams serialStreams; 00048 private final String serialPortFileName; 00049 private final CommPortIdentifier identifier; 00050 private final SerialPort serialPort; 00051 private final Map<Integer, Signal<SerialPortToRobot>> signals = Collections 00052 .synchronizedMap(new HashMap<Integer, Signal<SerialPortToRobot>>()); 00053 private boolean isClosed; 00054 00055 public SerialPortToRobot(String fileName, SerialPortInfo portInfo) throws PortInUseException, 00056 UnsupportedCommOperationException, TooManyListenersException, IOException { 00057 serialPortFileName = fileName; 00058 identifier = SerialPorts.getPortIdentifier(serialPortFileName); 00059 if (identifier == null) 00060 throw new RuntimeException("Port identifier " + serialPortFileName + " not found"); 00061 serialPort = (SerialPort) identifier.open("RLPark", 150); 00062 serialPort.addEventListener(this); 00063 serialPort.setFlowControlMode(portInfo.flowControl); 00064 serialPort.setSerialPortParams(portInfo.rate, portInfo.databits, portInfo.stopbits, portInfo.parity); 00065 serialStreams = new SerialStreams(serialPort); 00066 setNotifiers(); 00067 } 00068 00069 public void wakeupRobot() { 00070 serialPort.setRTS(false); 00071 serialPort.setDTR(false); 00072 try { 00073 Thread.sleep(500); 00074 } catch (InterruptedException e) { 00075 e.printStackTrace(); 00076 } 00077 serialPort.setRTS(true); 00078 serialPort.setDTR(true); 00079 } 00080 00081 private void setNotifiers() { 00082 serialPort.notifyOnDataAvailable(true); 00083 serialPort.notifyOnOutputEmpty(true); 00084 serialPort.notifyOnBreakInterrupt(true); 00085 serialPort.notifyOnCarrierDetect(true); 00086 serialPort.notifyOnCTS(true); 00087 serialPort.notifyOnDSR(true); 00088 serialPort.notifyOnFramingError(true); 00089 serialPort.notifyOnOverrunError(true); 00090 serialPort.notifyOnParityError(true); 00091 serialPort.notifyOnRingIndicator(true); 00092 } 00093 00094 public void register(int event, Listener<SerialPortToRobot> listener) { 00095 Signal<SerialPortToRobot> signal = signals.get(event); 00096 if (signal == null) { 00097 signal = new Signal<SerialPortToRobot>(); 00098 signals.put(event, signal); 00099 } 00100 signal.connect(listener); 00101 } 00102 00103 public void unregister(int event, Listener<SerialPortToRobot> listener) { 00104 signals.get(event).disconnect(listener); 00105 } 00106 00107 @Override 00108 public void serialEvent(SerialPortEvent event) { 00109 Signal<SerialPortToRobot> signal = signals.get(event.getEventType()); 00110 if (signal != null) 00111 signal.fire(this); 00112 if (!DebugSignals) 00113 return; 00114 switch (event.getEventType()) { 00115 case SerialPortEvent.OUTPUT_BUFFER_EMPTY: 00116 System.out.println("Event received: outputBufferEmpty"); 00117 break; 00118 00119 case SerialPortEvent.DATA_AVAILABLE: 00120 System.out.println("Event received: dataAvailable"); 00121 break; 00122 00123 case SerialPortEvent.BI: 00124 System.out.println("Event received: breakInterrupt"); 00125 break; 00126 00127 case SerialPortEvent.CD: 00128 System.out.println("Event received: carrierDetect"); 00129 break; 00130 00131 case SerialPortEvent.CTS: 00132 System.out.println("Event received: clearToSend"); 00133 break; 00134 00135 case SerialPortEvent.DSR: 00136 System.out.println("Event received: dataSetReady"); 00137 break; 00138 00139 case SerialPortEvent.FE: 00140 System.out.println("Event received: framingError"); 00141 break; 00142 00143 case SerialPortEvent.OE: 00144 System.out.println("Event received: overrunError"); 00145 break; 00146 00147 case SerialPortEvent.PE: 00148 System.out.println("Event received: parityError"); 00149 break; 00150 case SerialPortEvent.RI: 00151 System.out.println("Event received: ringIndicator"); 00152 break; 00153 default: 00154 System.out.println("Event received: unknown"); 00155 } 00156 } 00157 00158 public void send(byte[] bytes) throws IOException { 00159 serialStreams.write(bytes); 00160 } 00161 00162 public void send(char[] chars) throws IOException { 00163 serialStreams.write(DropByteArray.toBytes(chars)); 00164 } 00165 00166 public void send(String command) throws IOException { 00167 serialStreams.write(command.getBytes()); 00168 } 00169 00170 public void close() { 00171 // Produce a SEG FAULT 00172 // serialStreams.close(); 00173 if (isClosed) 00174 return; 00175 isClosed = true; 00176 } 00177 00178 public void sendAndReceive(String command, final String expectedAnswer) throws IOException { 00179 send(command.getBytes()); 00180 byte[] received = serialStreams.read(expectedAnswer.length()); 00181 if (!ExpectedIgnored && !Arrays.equals(received, expectedAnswer.getBytes())) 00182 throw new IOException(String.format("Return incorrect: expected <%s> was <%s>", expectedAnswer, 00183 new String(received))); 00184 } 00185 00186 public void sendAndWait(char[] chars) throws IOException { 00187 sendAndWait(DropByteArray.toBytes(chars)); 00188 } 00189 00190 public void sendAndWait(byte[] chars) throws IOException { 00191 final Semaphore semaphore = new Semaphore(0); 00192 Listener<SerialPortToRobot> listener = new Listener<SerialPortToRobot>() { 00193 @Override 00194 public void listen(SerialPortToRobot eventInfo) { 00195 semaphore.release(); 00196 } 00197 }; 00198 register(SerialPortEvent.OUTPUT_BUFFER_EMPTY, listener); 00199 serialStreams.write(chars); 00200 try { 00201 semaphore.tryAcquire(10, TimeUnit.SECONDS); 00202 } catch (InterruptedException e) { 00203 e.printStackTrace(); 00204 } 00205 unregister(SerialPortEvent.OUTPUT_BUFFER_EMPTY, listener); 00206 } 00207 00208 public boolean isClosed() { 00209 return isClosed; 00210 } 00211 00212 public byte[] read(int size) throws IOException { 00213 return serialStreams.read(size); 00214 } 00215 00216 static public SerialPortToRobot tryOpenPort(String serialPortFile, SerialPortInfo serialPortInfo) { 00217 for (int trial = 0; trial < 10; trial++) { 00218 SerialPortToRobot serialPort = openPort(serialPortFile, serialPortInfo); 00219 if (serialPort != null) 00220 return serialPort; 00221 try { 00222 Thread.sleep(4000); 00223 } catch (InterruptedException e) { 00224 e.printStackTrace(); 00225 } 00226 } 00227 return null; 00228 } 00229 00230 static public SerialPortToRobot openPort(String serialPortFile, SerialPortInfo serialPortInfo) { 00231 SerialPorts.refreshPortIdentifiers(); 00232 SerialPortToRobot serialPort = null; 00233 try { 00234 serialPort = new SerialPortToRobot(serialPortFile, serialPortInfo); 00235 } catch (Exception e) { 00236 e.printStackTrace(); 00237 } 00238 return serialPort; 00239 } 00240 00241 static public void fatalError(String message) { 00242 System.err.println(message); 00243 System.exit(1); 00244 } 00245 00246 public int purge() { 00247 try { 00248 return serialStreams.read(serialStreams.available()).length; 00249 } catch (IOException e) { 00250 e.printStackTrace(); 00251 } 00252 return 0; 00253 } 00254 }