00001 #include "BeoPilot.H" 00002 #include "ros/ros.h" 00003 #include <control_toolbox/pid.h> 00004 #include <iostream> 00005 #include <stdio.h> 00006 #include <sys/types.h> 00007 #include <sys/stat.h> 00008 #include <dirent.h> 00009 #include <unistd.h> 00010 // ###################################################################### 00011 BeoPilot::BeoPilot(): 00012 itsSerial(new Serial()), 00013 itsRCChannels(7, -1), 00014 itsEmergencyMode(-1) 00015 { 00016 //Connect to the serial motor board 00017 //itsSerial->configureSearch ("motorboard", 115200); 00018 itsSerial->configure ("/dev/ttyUSB0", 115200); 00019 itsPidSpeed.initPid(0.4,0.0,0.0,2.5,0.0); 00020 itsPidRot.initPid( 1.0,0.5,0.02,2.5,0.0); 00021 } 00022 void BeoPilot::start() 00023 { 00024 itsSerial->start(); 00025 usleep(1000); 00026 if(itsSerial->isSerialOk()) 00027 printf("[%s] found on [%s]\n", itsSerial->getDeviceDescriptor().c_str(), itsSerial->getDevName().c_str()); 00028 itsPreviousTime = ros::Time::now(); 00029 itsLastLeftEncoder = 0; 00030 itsLastRightEncoder = 0; 00031 itsRightEncoder = 0; 00032 itsLeftEncoder = 0; 00033 00034 itsPidSpeed.reset(); 00035 itsPidRot.reset(); 00036 } 00037 00038 // ###################################################################### 00039 BeoPilot::~BeoPilot() 00040 { 00041 //Kill the motors on exit 00042 SetMotors(0,0); 00043 } 00044 void BeoPilot::UpdateRCStatus() 00045 { 00046 unsigned char cmd = 107; 00047 itsSerial->write(cmd); 00048 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255); 00049 if(frame.size() == 26) 00050 { 00051 itsRCChannels[0] = ((0x0FF & frame[ 0]) << 8) | ((0x0FF & frame[ 1]) << 0); 00052 itsRCChannels[1] = ((0x0FF & frame[ 2]) << 8) | ((0x0FF & frame[ 3]) << 0); 00053 itsRCChannels[2] = ((0x0FF & frame[ 4]) << 8) | ((0x0FF & frame[ 5]) << 0); 00054 itsRCChannels[3] = ((0x0FF & frame[ 6]) << 8) | ((0x0FF & frame[ 7]) << 0); 00055 itsRCChannels[4] = ((0x0FF & frame[ 8]) << 8) | ((0x0FF & frame[ 9]) << 0); 00056 itsRCChannels[5] = ((0x0FF & frame[10]) << 8) | ((0x0FF & frame[11]) << 0); 00057 itsRCChannels[6] = ((0x0FF & frame[12]) << 8) | ((0x0FF & frame[13]) << 0); 00058 00059 itsEmergencyMode = frame[14]; 00060 if(itsRCChannels[2] > 1800) 00061 itsEmergencyMode = 255; 00062 itsRemoteMode = frame[15]; 00063 itsMotor1Speed = (frame[16] - 64.0) / 64.0; 00064 itsMotor2Speed = (frame[17] - 64.0) / 64.0; 00065 00066 itsLastLeftEncoder = itsLeftEncoder; 00067 itsLastRightEncoder = itsRightEncoder; 00068 itsLeftEncoder = ((0x0FF & frame[18]) << 24) | 00069 ((0x0FF & frame[19]) << 16) | 00070 ((0x0FF & frame[20]) << 8) | 00071 ((0x0FF & frame[21]) << 0); 00072 00073 itsRightEncoder = ((0x0FF & frame[22]) << 24) | 00074 ((0x0FF & frame[23]) << 16) | 00075 ((0x0FF & frame[24]) << 8) | 00076 ((0x0FF & frame[25]) << 0); 00077 printf("RMode[%d],M1[%f]M2[%f],LE[%d],RE[%d]\n", 00078 itsRemoteMode, 00079 itsMotor1Speed, 00080 itsMotor2Speed, 00081 itsLeftEncoder, 00082 itsRightEncoder 00083 ); 00084 UpdatePosition(); 00085 00086 } 00087 else 00088 { 00089 //printf("BAD FRAME RECIEVED!"); 00090 } 00091 } 00092 unsigned int BeoPilot::getRCChannel(int channel) 00093 { 00094 if(channel < 0 || channel > 7) 00095 return 0; 00096 00097 unsigned char cmd[2] = {104, channel}; 00098 00099 itsSerial->write(cmd, 2); 00100 std::vector<unsigned char> frame = itsSerial->readFrame(cmd[0], 255); 00101 00102 if(frame.size() == 4) 00103 { 00104 unsigned int val = ((0x0FF & frame[0]) << 24) | 00105 ((0x0FF & frame[1]) << 16) | 00106 ((0x0FF & frame[2]) << 8) | 00107 ((0x0FF & frame[3]) << 0); 00108 return val; 00109 } 00110 else 00111 printf("Bad Frame Size! (%lu)", frame.size()); 00112 00113 return 0; 00114 00115 } 00116 00117 unsigned char BeoPilot::getRCStatus() 00118 { 00119 unsigned char cmd = 103; 00120 00121 itsSerial->write(cmd); 00122 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255); 00123 00124 if(frame.size() == 1) 00125 return frame[0]; 00126 00127 else 00128 printf("Bad Frame Size! (%lu)", frame.size()); 00129 return 0; 00130 00131 } 00132 00133 unsigned char BeoPilot::getRCEnabled() 00134 { 00135 unsigned char cmd = 105; 00136 00137 itsSerial->write(cmd); 00138 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255); 00139 00140 if(frame.size() == 1) 00141 return frame[0]; 00142 else 00143 printf("Bad Frame Size! (%lu)", frame.size()); 00144 return 0; 00145 } 00146 00147 unsigned int BeoPilot::getRCSpeed() 00148 { 00149 unsigned char cmd = 106; 00150 00151 itsSerial->write(cmd); 00152 std::vector<unsigned char> frame = itsSerial->readFrame(cmd, 255); 00153 00154 if(frame.size() == 4) 00155 { 00156 unsigned int val = ((0x0FF & frame[0]) << 24) | 00157 ((0x0FF & frame[1]) << 16) | 00158 ((0x0FF & frame[2]) << 8) | 00159 ((0x0FF & frame[3]) << 0); 00160 return val; 00161 } 00162 else 00163 printf("Bad Frame Size! (%lu)", frame.size()); 00164 00165 return 0; 00166 00167 } 00168 // ###################################################################### 00169 void BeoPilot::SetMotorsPid(float rotationalSpeed, float translationalSpeed) 00170 { 00171 00172 double currentRot = (itsLeftMotorVelocity - itsRightMotorVelocity)/2; 00173 double currentTrans = (itsLeftMotorVelocity + itsRightMotorVelocity)/2; 00174 double rotErr = currentRot - rotationalSpeed; 00175 double transErr = currentTrans - translationalSpeed; 00176 00177 double pidRot = itsPidRot.updatePid(rotErr,dt); 00178 double pidTrans = itsPidSpeed.updatePid(transErr,dt); 00179 00180 SetMotors(pidRot,pidTrans); 00181 00182 00183 00184 } 00185 // ###################################################################### 00186 void BeoPilot::SetMotors(float rotationalSpeed, float translationalSpeed) 00187 { 00188 //Clamp the motor speeds to [-1 .. 1] 00189 00190 //float vx = itsVelocity.x; 00191 //float vy = itsVelocity.y; 00192 //float th = itsVelocity.z; 00193 00194 00195 00196 00197 00198 if(rotationalSpeed > 1.0) 00199 rotationalSpeed = 1.0; 00200 if(rotationalSpeed < -1.0) 00201 rotationalSpeed = -1.0; 00202 if(translationalSpeed > 1.0) 00203 translationalSpeed = 1.0; 00204 if(translationalSpeed < -1.0) 00205 translationalSpeed = -1.0; 00206 00207 char rotSpeed = char(rotationalSpeed * 100.0); 00208 char tranSpeed = char(translationalSpeed * 100.0); 00209 00210 00211 00212 //Send the command for the first motor 00213 unsigned char cmd[3]; 00214 cmd[0] = 100; //Command: Set Motor 1 00215 cmd[1] = rotSpeed; //Command: Rotational Speed? 00216 itsSerial->write(cmd, 2); 00217 usleep(10000); 00218 00219 //Send the command for the second motor 00220 cmd[0] = 101; //Command: Set Motor 2 00221 cmd[1] = tranSpeed; //Command: Translational Speed? 00222 itsSerial->write(cmd, 2); 00223 usleep(10000); 00224 } 00225 00226 00227 // We have 10 inch diameter wheel 00228 // Motor Shaft will turn 21 times for one wheel spin 00229 // The encoder have 4000 tick per revolution 00230 // When the wheel have one revolution, it travels 10 * pi inch 00231 // 00232 // 10* pi inch = 0.797964534 meters 00233 // Which have 1000 * 21 ticks 00234 // (10 * pi)/84,000 * 0.0254 = 9.49957779 * 10^(-6) = 0.000009.49957779 meter 00235 // Which means for every tick, 00236 // the wheel will move meter 00237 // 00238 // Width between two wheel W = 510 mm = 0.51m 00239 // To convert odometry data to position, we need do some math again... 00240 // Ot+1 = Ot + (Dr - Dl) / W 00241 // Dt,t+1 = (Dr + Dl) / 2 00242 // Xt+1 = Xt + Dt,t+1 * cos(Ot+1) 00243 // Yt+1 = Yt + Dt,t+1 * sin(Ot+1) 00244 void BeoPilot::UpdatePosition(void) 00245 { 00246 if(itsLastRightEncoder == 0.0 && itsLastLeftEncoder == 0.0) 00247 itsPreviousTime = ros::Time::now(); 00248 dt = ros::Time::now() - itsPreviousTime; 00249 double time = dt.toSec(); 00250 //double time = (double) itsEncoderTimer.getReset()/1000000.0;//sec 00251 00252 // double meterPerTick = 0.00000949957779 ; 00253 double ticksPerMeter = 105267.836; 00254 double dr = (itsRightEncoder - itsLastRightEncoder) / ticksPerMeter; 00255 double dl = (itsLeftEncoder - itsLastLeftEncoder) / ticksPerMeter; 00256 double w = 0.51; 00257 double ot = itsPosition.z + ((dr - dl) / w ); 00258 double dt = (dr + dl)/2; 00259 double xt = itsPosition.x + dt * cos(ot); 00260 double yt = itsPosition.y + dt * sin(ot); 00261 00262 00263 // compute motor velocity 00264 if(time != 0.0){ 00265 itsLeftMotorVelocity = -(dl/time); 00266 itsRightMotorVelocity = -(dr/time); 00267 } 00268 printf("Time[%f] Left V %f Right V %f,dl %f,dr %f",time,itsLeftMotorVelocity, 00269 itsRightMotorVelocity,dl,dr); 00270 00271 // the difference in position between the current and previous time step 00272 itsDiffPosition.x = dt * cos(ot); 00273 itsDiffPosition.y = dt * sin(ot); 00274 itsDiffPosition.z = ((dr - dl) / w ); //use z as orientation data 00275 00276 itsVelocity.x = itsDiffPosition.x/time; 00277 itsVelocity.y = itsDiffPosition.y/time; 00278 itsVelocity.z = itsDiffPosition.z/time; 00279 itsPosition.x = xt; 00280 itsPosition.y = yt; 00281 itsPosition.z = ot;//use z as orientation data 00282 00283 } 00284 00285 void BeoPilot::resetEncoder() 00286 { 00287 00288 unsigned char cmd = 108; 00289 itsSerial->write(cmd); 00290 00291 itsPosition.x = 0; 00292 itsPosition.y = 0; 00293 itsPosition.z = 0; 00294 itsDiffPosition.x = 0; 00295 itsDiffPosition.y = 0; 00296 itsDiffPosition.z = 0; 00297 00298 itsVelocity.x = 0; 00299 itsVelocity.y = 0; 00300 itsVelocity.z = 0; 00301 itsPidSpeed.reset(); 00302 itsPidRot.reset(); 00303 00304 }