Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

KobukiDriver.cc

Go to the documentation of this file.
00001 #include "Shared/RobotInfo.h"
00002 #if defined(TGT_IS_KOBUKI)
00003 
00004 #include "KobukiDriver.h"
00005 #include "Shared/MarkScope.h"
00006 #include "Shared/get_time.h"
00007 #include "Shared/debuget.h"
00008 #include "Shared/TimeET.h"
00009 #include "Shared/CalliopeUInfo.h"
00010 
00011 #include <arpa/inet.h>
00012 #include <stdio.h>
00013 
00014 using namespace std; 
00015 using namespace Kobuki;
00016 
00017 const std::string KobukiDriver::autoRegisterKobukiDriver = KobukiDriver::getRegistry().registerType<KobukiDriver>("Kobuki");
00018 
00019 void KobukiDriver::motionStarting() {
00020   //  std::cout << "motionStarting called!" << std::endl;
00021   MotionHook::motionStarting();
00022   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00023   if(comm==NULL)
00024     std::cerr << "KobukiDriver \"" << instanceName << "\": could not find CommPort \"" << commName << "\"" << std::endl;
00025   else if(!comm->open())
00026     std::cerr << "KobukiDriver \"" << instanceName << "\": unable to open comm port \"" << commName << "\"" << std::endl;
00027   else
00028     connect();
00029   motionActive=true;
00030   commName.addPrimitiveListener(this);
00031 }
00032 
00033 bool KobukiDriver::isConnected() {
00034   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00035   return (comm!=NULL && comm->isWriteable());
00036 }
00037 
00038 void KobukiDriver::motionStopping() {
00039   motionActive=false;
00040   if(!sensorsActive) // listener count is not recursive, so only remove if we're the last one
00041     commName.removePrimitiveListener(this);
00042   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00043   if(comm!=NULL)
00044     comm->close(); // this *is* recursive, so we always close it to match our open() in motionStarting()
00045   MotionHook::motionStopping();
00046 }
00047 
00048 
00049 void KobukiDriver::motionCheck(const float outputs[][NumOutputs]) {
00050   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00051   if (comm == NULL || !comm->isWriteable())
00052      return;
00053 
00054   BaseControl basecontrol;
00055   vector<unsigned char> commands(0);
00056   short output;
00057   KobukiCommand commandkobuki;
00058   commandkobuki.Length = 6;
00059   commandkobuki.commandData = 1;
00060   commandkobuki.commandDataSize = sizeof(basecontrol);
00061   float speed = outputs[NumFrames - 1][RobotInfo::SpeedOffset];
00062   output = (short)speed;
00063   commandkobuki.speedLow = output & 0xff;
00064   commandkobuki.speedHigh = output >> 8;
00065   float radius = outputs[NumFrames - 1][RobotInfo::RadiusOffset];
00066   output = (short)radius;
00067   commandkobuki.radiusLow = output & 0xff;
00068   commandkobuki.radiusHigh = output >> 8;
00069   
00070   //std::cout << "KobukiDriver: speed= " << speed << " radius= " << radius << std::endl;
00071 
00072   commands.push_back(0xaa);
00073   commands.push_back(0x55); 
00074   commands.push_back((char)commandkobuki.Length);
00075   commands.push_back((char)commandkobuki.commandData); 
00076   commands.push_back((char)commandkobuki.commandDataSize); 
00077   commands.push_back(commandkobuki.speedLow);
00078   commands.push_back(commandkobuki.speedHigh); 
00079   commands.push_back(commandkobuki.radiusLow);
00080   commands.push_back(commandkobuki.radiusHigh);
00081   
00082   unsigned char checksum = 0; 
00083   for (unsigned int i = 2; i < commands.size(); i++)
00084     checksum ^= commands.at(i);
00085  
00086   commands.push_back(checksum);
00087     
00088   unsigned int dt = static_cast<unsigned int> (NumFrames * FrameTime / ((getTimeScale() > 0) ?getTimeScale():1.f)); 
00089     
00090   sendCommand(commands, dt*3/4);
00091     
00092   MotionHook::motionCheck(outputs);
00093 }
00094 
00095 bool KobukiDriver::sendCommand(vector<unsigned char> bytes, unsigned int timeout) {
00096   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00097   if(comm==NULL)
00098     return false;
00099   Thread::Lock& l = comm->getLock();
00100   
00101   //  cout << "KOBUKI: Trying to get lock for write." << endl;
00102   
00103   unsigned int t = get_time();
00104   unsigned int giveup = t + timeout;
00105   
00106   while (!l.trylock()) {
00107     if (get_time() >= giveup) {
00108       if(MotionHook::verbose>0)
00109   cerr << "KOBUKI: Unable to send command: couldn't get lock on comm port" << endl;
00110       return false;
00111     }
00112     usleep(1000);
00113   }
00114   
00115   MarkScope autolock(l); l.unlock(); //transfer lock to MarkScope
00116   
00117   std::ostream os(&comm->getWriteStreambuf());
00118   //cout << endl << "W";
00119   for (unsigned int i = 0; i < bytes.size(); i++) { // sending one byte at a time or the whole buffer?
00120     os << bytes[i];
00121     //cout << " " << (int)bytes[i];
00122   }
00123   os << std::flush;
00124   //cout << endl;
00125   
00126   return true;
00127 }
00128 
00129 
00130 void KobukiDriver::connect() {
00131   vector<unsigned char> commands(6);
00132   commands[0] = 0xaa;
00133   commands[1] = 0x55;
00134   commands[2] = 3;
00135   commands[3] = 4;
00136   commands[4] = 1;
00137   commands[5] = 0;
00138   sendCommand(commands, 3000000);
00139   // cout << "Connecting to KOBUKI\n" << flush;
00140 }
00141 
00142 unsigned int KobukiDriver::nextTimestamp() {
00143   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00144   if(comm==NULL || !comm->isReadable())
00145     return -1U;
00146   return get_time();
00147 }
00148 
00149 bool KobukiDriver::readPacket(std::istream &is) {
00150   
00151   State currentState = lookingForHeader0;
00152   unsigned char data[1];
00153   unsigned char packetChecksum[1];
00154   unsigned int packetLength;
00155   unsigned char packet[256];
00156   
00157     while (currentState != gotPacket) {
00158     
00159       switch (currentState) {
00160         case lookingForHeader0:
00161           is.read((char*)data,1);
00162           if (data[0] == 0xaa)
00163             currentState = lookingForHeader1;
00164           break;
00165         case lookingForHeader1:
00166           is.read((char*)data,1);
00167           if (data[0] == 0x55)
00168             currentState = waitingForPacket;
00169           else if (data[0] == 0xaa)
00170             currentState = lookingForHeader1;
00171           else
00172             currentState = lookingForHeader0;
00173           break;
00174         case waitingForPacket:
00175           is.read((char*)data,1);
00176           packetLength = data[0];
00177           is.read((char*)packet, packetLength);
00178           currentState = gotPacket;
00179           is.read((char*)packetChecksum,1);
00180           break;
00181         case gotPacket:
00182           currentState = lookingForHeader0;
00183         default:
00184           break;
00185       }
00186     }
00187     
00188     
00189   
00190     unsigned char checksum = packetLength;
00191     for (unsigned int i = 0; i < packetLength; i++)
00192       checksum ^= packet[i];
00193       
00194       
00195     if (checksum == packetChecksum[0]) {
00196       packetParser(packet, packetLength);
00197       currentState = lookingForHeader0;
00198       return true;
00199     }
00200     else {
00201       currentState = lookingForHeader0;
00202       return false;
00203     }
00204 }
00205 
00206 void KobukiDriver::packetParser(unsigned char packet[], const unsigned int packetLength) {
00207   
00208   
00209   unsigned int index = 0;
00210     while (index < packetLength-1) {
00211       switch (packet[index]) {
00212         case coreSensor:
00213         {
00214           CoreSensor *data = (CoreSensor*) &packet[index];
00215           //unsigned short int time_stamp = (data->timestamp[1] << 8) | data->timestamp[0];
00216           short int left_encoder = (data->leftEncoder[1] << 8) | data->leftEncoder[0];
00217           short int right_encoder = (data->rightEncoder[1] << 8) | data->rightEncoder[0];
00218 
00219           //std::cout << "left_encoder = " << left_encoder << " right encoder = " << right_encoder << std::endl;
00220 
00221           //setSensorValue(TimestampOffset, time_stamp);
00222           //setSensorValue(CliffOffset, data->cliff);
00223           setSensorValue(LeftEncoderOffset, left_encoder);
00224           setSensorValue(RightEncoderOffset, right_encoder);
00225           setSensorValue(LeftPwmOffset, data->leftPwm);
00226           setSensorValue(RightPwmOffset, data->rightPwm);
00227           setSensorValue(ChargerOffset, data->charger);
00228           setSensorValue(BatteryOffset, data->battery);
00229           setSensorValue(OverCurrentOffset, data->overCurrent);
00230           
00231           
00232           setButtonValue(B0ButOffset,(data->buttons >> 0) & 0x1);
00233           setButtonValue(B1ButOffset,(data->buttons >> 1) & 0x1);
00234           setButtonValue(B2ButOffset,(data->buttons >> 2) & 0x1);
00235           setButtonValue(DropLeftWheelButOffset,(data->wheelDrop >> 1) & 0x1);
00236           setButtonValue(DropRightWheelButOffset,(data->wheelDrop >> 0) & 0x1);
00237           setButtonValue(BumpLeftButOffset,(data->bumper >> 2) & 0x1);
00238           setButtonValue(BumpRightButOffset,(data->bumper >> 0) & 0x1);
00239           setButtonValue(BumpCenterButOffset,(data->bumper >> 1) & 0x1);
00240           setButtonValue(CliffLeftButOffset,(data->cliff >> 2) & 0x1);
00241           setButtonValue(CliffRightButOffset,(data->cliff >> 0) & 0x1);
00242           setButtonValue(CliffCenterButOffset,(data->cliff >> 1) & 0x1);
00243           
00244           index += sizeof(CoreSensor);
00245           break;
00246         }
00247         case dockInfraRed:
00248         {
00249           DockInfraRed *data = (DockInfraRed*) &packet[index];;
00250           
00251           setSensorValue(Docking0Offset, data->docking[0]);
00252           setSensorValue(Docking1Offset, data->docking[1]);
00253           setSensorValue(Docking2Offset, data->docking[2]);
00254           
00255           index += sizeof(DockInfraRed);
00256           break;
00257         }
00258         case inertia:
00259         {
00260           Inertia *data = (Inertia*) &packet[index];
00261           short int angle = (data->angle[1] << 8) | data->angle[0];
00262           short int angle_rate = (data->angleRate[1] << 8) | data->angleRate[0];
00263           
00264           setSensorValue(AngleOffset, angle);
00265           setSensorValue(AngleRateOffset, angle_rate);
00266           setSensorValue(Acc0Offset, data->acc[0]);
00267           setSensorValue(Acc1Offset, data->acc[1]);
00268           setSensorValue(Acc2Offset, data->acc[2]);
00269           
00270           index += sizeof(Inertia);
00271           break; 
00272         }
00273         case cliff:
00274         {
00275           Cliff *data = (Cliff*) &packet[index];
00276           short int cliffBottom0 = (data->bottom0[1] << 8) | data->bottom0[0];
00277           short int cliffBottom1 = (data->bottom1[1] << 8) | data->bottom1[0];
00278           short int cliffBottom2 = (data->bottom2[1] << 8) | data->bottom2[0];
00279           
00280           setSensorValue(Bottom0Offset, cliffBottom0);
00281           setSensorValue(Bottom1Offset, cliffBottom1);
00282           setSensorValue(Bottom2Offset, cliffBottom2);
00283         
00284           index += sizeof(Cliff);
00285           break;
00286         }
00287         case current:
00288         {
00289           Current *data = (Current*) &packet[index];
00290           
00291           setSensorValue(Current0Offset, data->current[0]);
00292           setSensorValue(Current1Offset, data->current[1]);
00293           
00294           index += sizeof(Current);
00295           break;
00296         }
00297         case threeAxisGyro:
00298         {
00299           ThreeAxisGyro *data = (ThreeAxisGyro*) &packet[index];
00300             
00301           setSensorValue(FrameIdOffset, data->frameId);
00302           setSensorValue(FollowedDataLenghtOffset, data->followedDataLength);
00303             
00304           if(data->followedDataLength == 6) { 
00305             setSensorValue(GyroParam0Offset, (data->parameters[1] << 8) | data->parameters[0]);
00306             setSensorValue(GyroParam1Offset, (data->parameters[3] << 8) | data->parameters[2]);
00307             setSensorValue(GyroParam2Offset, (data->parameters[5] << 8) | data->parameters[4]);
00308             setSensorValue(GyroParam3Offset, (data->parameters[7] << 8) | data->parameters[6]);
00309             setSensorValue(GyroParam4Offset, (data->parameters[9] << 8) | data->parameters[8]);
00310             setSensorValue(GyroParam5Offset, (data->parameters[11] << 8) | data->parameters[10]);
00311           }
00312           else {
00313             setSensorValue(GyroParam0Offset, (data->parameters[1] << 8) | data->parameters[0]);
00314             setSensorValue(GyroParam1Offset, (data->parameters[3] << 8) | data->parameters[2]);
00315             setSensorValue(GyroParam2Offset, (data->parameters[5] << 8) | data->parameters[4]);
00316             setSensorValue(GyroParam3Offset, (data->parameters[7] << 8) | data->parameters[6]);
00317             setSensorValue(GyroParam4Offset, (data->parameters[9] << 8) | data->parameters[8]);
00318             setSensorValue(GyroParam5Offset, (data->parameters[11] << 8) | data->parameters[10]);
00319             setSensorValue(GyroParam5Offset, (data->parameters[13] << 8) | data->parameters[12]);
00320             setSensorValue(GyroParam5Offset, (data->parameters[15] << 8) | data->parameters[14]);
00321             setSensorValue(GyroParam5Offset, (data->parameters[17] << 8) | data->parameters[16]);
00322           }
00323           index += sizeof(ThreeAxisGyro) + 2 * data->followedDataLength;
00324           break;
00325         }
00326         case gpInput:
00327         {
00328           GpInput *data = (GpInput*) &packet[index]; 
00329             
00330           setSensorValue(DigitalInputOffset, (data->digitalInput[1] << 8) | data->digitalInput[0]);
00331           setSensorValue(AnalogInput0Offset,(data->analogInput[1] << 8) | data->analogInput[0]);
00332           setSensorValue(AnalogInput1Offset,(data->analogInput[3] << 8) | data->analogInput[2]);
00333           setSensorValue(AnalogInput2Offset,(data->analogInput[5] << 8) | data->analogInput[4]);
00334           setSensorValue(AnalogInput3Offset,(data->analogInput[7] << 8) | data->analogInput[6]);
00335           setSensorValue(AnalogInput4Offset,(data->analogInput[9] << 8) | data->analogInput[8]);
00336           setSensorValue(AnalogInput5Offset,(data->analogInput[11] << 8) | data->analogInput[10]);
00337           setSensorValue(AnalogInput6Offset,(data->analogInput[13] << 8) | data->analogInput[12]);
00338           
00339           index += sizeof(GpInput);
00340           break;
00341         }
00342         default:
00343           index += packetLength;
00344           break;
00345       }
00346     }
00347 }
00348 
00349 bool KobukiDriver::advance() {
00350   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00351   if (comm == NULL || !comm->isReadable() || !comm->isWriteable())
00352     return false;
00353     
00354   Thread::testCurrentCancel();
00355   
00356   std::istream is(&comm->getReadStreambuf());
00357   
00358   bool valid = readPacket(is);
00359   if (valid) {
00360     ++frameNumber;
00361     return true;
00362   }
00363   else
00364     return false;
00365 }
00366 
00367 void KobukiDriver::registerSource() {
00368   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00369   if(comm==NULL) {
00370     std::cerr << "KobukiDriver \"" << instanceName << "\": could not find CommPort \"" << commName << "\"" << std::endl;
00371   } else if(!comm->open()) {
00372     std::cerr << "KobukiDriver \"" << instanceName << "\": unable to open comm port \"" << commName << "\"" << std::endl;
00373   } else {
00374     connect();
00375   }
00376   sensorsActive=true;
00377   commName.addPrimitiveListener(this);
00378 }
00379 
00380 void KobukiDriver::deregisterSource() {
00381   CommPort * comm = CommPort::getRegistry().getInstance(commName);
00382   if(comm!=NULL)
00383     comm->close();
00384   sensorsActive=false;
00385   if(!motionActive) // listener count is not recursive, so only remove if we're the last one
00386     commName.removePrimitiveListener(this);
00387 }
00388 
00389 void KobukiDriver::doUnfreeze() {
00390   MarkScope sl(poller.getStartLock());
00391   if(!poller.isStarted()) {
00392     //poller.resetPeriod(1.0/(*sensorFramerate));
00393     poller.start();
00394   }
00395   sensorFramerate->addPrimitiveListener(this);
00396 }
00397 
00398 void KobukiDriver::doFreeze() {
00399   MarkScope sl(poller.getStartLock());
00400   if(poller.isStarted())
00401     poller.stop().join();
00402   sensorFramerate->removePrimitiveListener(this);
00403 }
00404 
00405 void KobukiDriver::plistValueChanged(const plist::PrimitiveBase& pl) {
00406   // std::cout << "plistvalueChanged Called!" << std::endl;
00407   if(&pl==&commName) {
00408     // if here, then motionStarted or setDataSourceThread has been called, thus when commName changes,
00409     // need to close old one and reopen new one
00410     if(poller.isStarted())
00411       poller.stop().join();
00412     
00413     CommPort * comm = CommPort::getRegistry().getInstance(commName.getPreviousValue());
00414     if(comm!=NULL) {
00415       // close each of our old references
00416       if(sensorsActive)
00417   comm->close();
00418       if(motionActive)
00419   comm->close();
00420     }
00421     comm = CommPort::getRegistry().getInstance(commName);
00422     if(comm==NULL) {
00423       std::cerr << "KobukiDriver \"" << instanceName << "\": could not find CommPort \"" << commName << "\"" << std::endl;
00424     } else {
00425       // open each of our new references
00426       if(sensorsActive)
00427   comm->open();
00428       if(motionActive) {
00429   if(!comm->open())
00430     std::cerr << "KobukiDriver \"" << instanceName << "\": unable to open comm port \"" << commName << "\"" << std::endl;
00431   else
00432     connect();
00433       }
00434     }
00435     
00436     if(getTimeScale()>0) {
00437       //poller.resetPeriod(1.0/(*sensorFramerate));
00438       poller.start();
00439     }
00440   } else if(&pl==sensorFramerate) {
00441     //poller.resetPeriod(1.0/(*sensorFramerate));
00442   }
00443 }
00444 #endif

Tekkotsu Hardware Abstraction Layer 5.1CVS
Generated Mon May 9 05:01:38 2016 by Doxygen 1.6.3