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
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)
00041 commName.removePrimitiveListener(this);
00042 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00043 if(comm!=NULL)
00044 comm->close();
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
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
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();
00116
00117 std::ostream os(&comm->getWriteStreambuf());
00118
00119 for (unsigned int i = 0; i < bytes.size(); i++) {
00120 os << bytes[i];
00121
00122 }
00123 os << std::flush;
00124
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
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
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
00220
00221
00222
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)
00386 commName.removePrimitiveListener(this);
00387 }
00388
00389 void KobukiDriver::doUnfreeze() {
00390 MarkScope sl(poller.getStartLock());
00391 if(!poller.isStarted()) {
00392
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
00407 if(&pl==&commName) {
00408
00409
00410 if(poller.isStarted())
00411 poller.stop().join();
00412
00413 CommPort * comm = CommPort::getRegistry().getInstance(commName.getPreviousValue());
00414 if(comm!=NULL) {
00415
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
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
00438 poller.start();
00439 }
00440 } else if(&pl==sensorFramerate) {
00441
00442 }
00443 }
00444 #endif