Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 package com.github.c77.base_driver.kobuki;
00018
00023 import com.github.c77.base_driver.BaseDevice;
00024 import com.github.c77.base_driver.BaseStatus;
00025 import com.github.c77.base_driver.OdometryStatus;
00026 import com.hoho.android.usbserial.driver.UsbSerialDriver;
00027 import com.hoho.android.usbserial.util.SerialInputOutputManager;
00028
00029 import org.apache.commons.logging.Log;
00030 import org.apache.commons.logging.LogFactory;
00031
00032 import java.io.IOException;
00033 import java.nio.ByteBuffer;
00034 import java.util.concurrent.ExecutorService;
00035 import java.util.concurrent.Executors;
00036
00037 import org.ros.exception.RosRuntimeException;
00038
00039 public class KobukiBaseDevice implements BaseDevice {
00040
00041 private final byte SetBaudrate115200 = (byte) 6;
00042
00043 private final byte Header0 = (byte) 0xAA;
00044 private final byte Header1 = (byte) 0x55;
00045 private final byte BaseControl = (byte) 0x01;
00046 private final byte SoundSequence = (byte) 0x04;
00047
00048 private final KobukiPacketReader packetReader = new KobukiPacketReader();
00049 private final KobukiPacketParser packetParser = new KobukiPacketParser();
00050 private BaseStatus baseStatus = new BaseStatus();
00051 private KobukiOdometryStatus odometryStatus = new KobukiOdometryStatus();
00052
00053 private static final Log log = LogFactory.getLog(KobukiBaseDevice.class);
00054
00055 private final UsbSerialDriver serialDriver;
00056
00057 private class BaseSpeedValues {
00058 private final int linearSpeed;
00059 private final int rotationRadius;
00060
00061 private BaseSpeedValues(int linearSpeed, int rotationRadius) {
00062 this.linearSpeed = linearSpeed;
00063 this.rotationRadius = rotationRadius;
00064 }
00065
00066 public int getLinearSpeed() {
00067 return linearSpeed;
00068 }
00069
00070 public int getRotationRadius() {
00071 return rotationRadius;
00072 }
00073 }
00074
00075 public KobukiBaseDevice(UsbSerialDriver driver) throws Exception {
00076 if(driver == null) {
00077 throw new Exception("null USB driver provided");
00078 }
00079 serialDriver = driver;
00080 try {
00081 serialDriver.open();
00082 serialDriver.setParameters(115200, UsbSerialDriver.DATABITS_8,
00083 UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE);
00084 } catch (IOException e) {
00085 log.info("Error setting up device: " + e.getMessage(), e);
00086 try {
00087 serialDriver.close();
00088 } catch (IOException e1) {
00089 e1.printStackTrace();
00090 }
00091 }
00092
00093 final ExecutorService executorService = Executors.newSingleThreadExecutor();
00094
00095 SerialInputOutputManager serialInputOutputManager;
00096
00097 final SerialInputOutputManager.Listener listener =
00098 new SerialInputOutputManager.Listener() {
00099 @Override
00100 public void onRunError(Exception e) {
00101 }
00102
00103 @Override
00104 public void onNewData(final byte[] data) {
00105 KobukiBaseDevice.this.updateReceivedData(data);
00106 }
00107 };
00108
00109 serialInputOutputManager = new SerialInputOutputManager(serialDriver, listener);
00110 executorService.submit(serialInputOutputManager);
00111 }
00112
00113 public BaseStatus getBaseStatus() {
00114 return baseStatus;
00115 }
00116
00117 @Override
00118 public OdometryStatus getOdometryStatus() {
00119 return odometryStatus;
00120 }
00121
00122 private void updateReceivedData(final byte[] bytes) {
00123 int readBytes = bytes.length;
00124 packetReader.newPacket(ByteBuffer.allocateDirect(readBytes).put(bytes, 0, readBytes));
00125 baseStatus = packetParser.parseBaseStatus(packetReader.getSensorPacket());
00126 odometryStatus.update(baseStatus);
00127 }
00128
00129 public void initialize() {
00130 byte[] baud = new byte[]{SetBaudrate115200};
00131 write(baud);
00132 }
00133
00134 public void move(double linearVelX, double angVelZ) {
00135 BaseSpeedValues speeds = twistToBase(linearVelX, angVelZ);
00136 sendMovementPackage(speeds);
00137 }
00138
00139 private BaseSpeedValues twistToBase(double linearVelX, double angVelZ) {
00140
00141
00142 final double epsilon = 0.0001;
00143 final double bias = 0.23;
00144 double radius;
00145 double speed;
00146
00147
00148 if (Math.abs(angVelZ) < epsilon) {
00149 radius = 0.0f;
00150 speed = 1000.0f * linearVelX;
00151 return new BaseSpeedValues((int) speed, (int) radius);
00152 }
00153
00154 radius = linearVelX * 1000.0f / angVelZ;
00155
00156 if (Math.abs(linearVelX) < epsilon || Math.abs(radius) <= 1.0f) {
00157 speed = 1000.0f * bias * angVelZ / 2.0f;
00158 radius = 1.0f;
00159 return new BaseSpeedValues((int) speed, (int) radius);
00160 }
00161
00162
00163 if (radius > 0.0f) {
00164 speed = (radius + 1000.0f * bias / 2.0f) * angVelZ;
00165 } else {
00166 speed = (radius - 1000.0f * bias / 2.0f) * angVelZ;
00167 }
00168 return new BaseSpeedValues((int) speed, (int) radius);
00169 }
00170
00171 private void sendMovementPackage(BaseSpeedValues speeds) {
00172 int linearSpeed = speeds.getLinearSpeed();
00173 int rotationRadius = speeds.getRotationRadius();
00174
00175 byte[] baseControlMsg = new byte[]{
00176 BaseControl,
00177 (byte) 0x04,
00178 (byte) linearSpeed,
00179 (byte) (linearSpeed >> 8),
00180 (byte) rotationRadius,
00181 (byte) (rotationRadius >> 8),
00182 };
00183
00184 write(buildPackage(baseControlMsg));
00185 }
00186
00187 private void sendSoundPackage(int sound) {
00188 byte[] soundSequenceMsg = new byte[]{
00189 SoundSequence,
00190 (byte) 0x01,
00191 (byte) sound
00192 };
00193
00194 write(buildPackage(soundSequenceMsg));
00195 }
00196
00197 byte checkSum(byte[] cmdPackage) {
00198 byte checksum = 0;
00199
00200 for (int i = 2; i < (cmdPackage.length - 1); i++) {
00201 checksum ^= cmdPackage[i];
00202 }
00203 return checksum;
00204 }
00205
00206 byte[] buildPackage(byte[] payload) {
00207 int payloadLength = payload.length;
00208 byte[] pkg = new byte[payloadLength + 4];
00209 pkg[0] = Header0;
00210 pkg[1] = Header1;
00211 pkg[2] = (byte) (payloadLength);
00212 for (int i = 3; i < payloadLength + 3; i++) {
00213 pkg[i] = payload[i - 3];
00214 }
00215 pkg[pkg.length - 1] = checkSum(pkg);
00216
00217 return pkg;
00218 }
00219
00220 private void write(byte[] command) {
00221 try {
00222 log.info("Writing a command to USB Device.");
00223 serialDriver.write(command, 1000);
00224 } catch (IOException e) {
00225 throw new RosRuntimeException(e);
00226 }
00227 }
00228 }