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 00019 import com.github.c77.base_driver.BaseStatus; 00020 import com.github.c77.base_driver.InertialInformation; 00021 00026 public class KobukiPacketParser { 00027 00028 private final int TIMESTAMP = 0; 00029 private final int BUMPER = 2; 00030 private final int WHEEL_DROP = 3; 00031 private final int CLIFF = 4; 00032 private final int BUTTON = 11; 00033 private final int CHARGER = 12; 00034 private final int BATTERY = 13; 00035 00036 private final int ANGLE = 0; 00037 private final int ANGLE_RATE = 2; 00038 00039 private final int LEFT_ENC = 5; 00040 private final int RIGHT_ENC = 7; 00041 00042 private final double TICKS_TO_MM = 11.7; 00043 00044 private int prevLeftEncoder; 00045 private int prevRightEncoder; 00046 private short leftLoops = 0; 00047 private short rightLoops = 0; 00048 private boolean firstPkg = true; 00049 00050 private void updateOdometry(byte[] sensorPacket, BaseStatus baseStatus) { 00051 final int MAX_ODOM = 65535; 00052 final int lowMark = (MAX_ODOM / 4); 00053 final int highMark = (MAX_ODOM - lowMark); 00054 short leftEncoder; 00055 short rightEncoder; 00056 int currLeftEncoder; 00057 int currRightEncoder; 00058 int acumLeftEncoder; 00059 int acumRightEncoder; 00060 00061 leftEncoder = ((short) ((sensorPacket[LEFT_ENC+1] << 8) | (sensorPacket[LEFT_ENC] & 0xFF))); 00062 rightEncoder = ((short) ((sensorPacket[RIGHT_ENC+1] << 8) | (sensorPacket[RIGHT_ENC] & 0xFF))); 00063 currLeftEncoder = (int) (leftEncoder & 0x0000ffffL); 00064 currRightEncoder = (int) (rightEncoder & 0x0000ffffL); 00065 00066 if (firstPkg) { 00067 prevLeftEncoder = currLeftEncoder; 00068 prevRightEncoder = currRightEncoder; 00069 firstPkg = false; 00070 } 00071 00072 if (prevLeftEncoder > highMark && currLeftEncoder < lowMark) { 00073 leftLoops++; 00074 } 00075 if (prevLeftEncoder < lowMark && currLeftEncoder > highMark) { 00076 leftLoops--; 00077 } 00078 00079 if (prevRightEncoder > highMark && currRightEncoder < lowMark) { 00080 rightLoops++; 00081 } 00082 if (prevRightEncoder < lowMark && currRightEncoder > highMark) { 00083 rightLoops--; 00084 } 00085 00086 acumLeftEncoder = (MAX_ODOM * leftLoops) + currLeftEncoder; 00087 acumRightEncoder = (MAX_ODOM * rightLoops) + currRightEncoder; 00088 // according to spec: this goes from 0 to 65535 and circles 00089 baseStatus.setLeftDistance((int)Math.round(acumLeftEncoder / TICKS_TO_MM)); 00090 baseStatus.setRightDistance((int)Math.round(acumRightEncoder / TICKS_TO_MM)); 00091 // Update prev values 00092 prevLeftEncoder = currLeftEncoder; 00093 prevRightEncoder = currRightEncoder; 00094 } 00095 00096 public BaseStatus parseBaseStatus(byte[] sensorPacket) { 00097 BaseStatus baseStatus = new BaseStatus(); 00098 baseStatus.setBumper(sensorPacket[BUMPER]); 00099 00100 baseStatus.setTimeStamp((short) (sensorPacket[TIMESTAMP + 1] << 8 | sensorPacket[TIMESTAMP])); 00101 baseStatus.setWheelDrop(sensorPacket[WHEEL_DROP]); 00102 baseStatus.setCliff(sensorPacket[CLIFF]); 00103 baseStatus.setButton(sensorPacket[BUTTON]); 00104 baseStatus.setCharger(sensorPacket[CHARGER]); 00105 baseStatus.setBattery(sensorPacket[BATTERY]); 00106 00107 updateOdometry(sensorPacket, baseStatus); 00108 return baseStatus; 00109 } 00110 00111 public InertialInformation getInertialInformation (byte[] imuPacket) { 00112 InertialInformation inertialInformation = new InertialInformation(); 00113 inertialInformation.setAngle((short) ((imuPacket[ANGLE+1] << 8)|(imuPacket[ANGLE] & 0xff))); 00114 inertialInformation.setAngleRate((short) ((imuPacket[ANGLE_RATE + 1] << 8) | (imuPacket[ANGLE_RATE] & 0xff))); 00115 return inertialInformation; 00116 } 00117 00118 }