KobukiBaseDevice.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2013 Creativa77.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
00005  * use this file except in compliance with the License. You may obtain a copy of
00006  * the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
00013  * License for the specific language governing permissions and limitations under
00014  * the License.
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     // Kobuki low level commands
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); // configure base baudrate
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         // vx: in m/s
00141         // wz: in rad/s
00142         final double epsilon = 0.0001;
00143         final double bias = 0.23;
00144         double radius;
00145         double speed;
00146 
00147         // Special Case #1 : Straight Run
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         // Special Case #2 : Pure Rotation or Radius is less than or equal to 1.0 mm
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         // General Case :
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 }


android_base_controller
Author(s):
autogenerated on Fri Aug 28 2015 10:04:47