00001 #ifdef HAVE_SKEWLZONE
00002
00003 #include "SkewlZoneDriver.h"
00004 #include "Shared/MarkScope.h"
00005 #include "Shared/get_time.h"
00006 #include "Shared/debuget.h"
00007
00008 using namespace std;
00009
00010 const unsigned int SkewlZoneDriver::NUM_SERVO;
00011 const int SkewlZoneDriver::UNUSED;
00012 const std::string SkewlZoneDriver::autoRegisterSkewlZoneDriver = DeviceDriver::getRegistry().registerType<SkewlZoneDriver>("SkewlZone");
00013
00014 void SkewlZoneDriver::motionStarting() {
00015 ASSERTRET(!motionActive,"SkewlZoneDriver::motionStarting, but motionActive is true");
00016 MotionHook::motionStarting();
00017 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00018 if(comm==NULL)
00019 std::cerr << "SkewlZoneDriver \"" << instanceName << "\": could not find CommPort \"" << commName << "\"" << std::endl;
00020 else
00021 comm->open();
00022 motionActive=true;
00023 commName.addPrimitiveListener(this);
00024 }
00025
00026 bool SkewlZoneDriver::isConnected() {
00027 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00028 return (comm!=NULL && comm->isWriteable());
00029 }
00030
00031 void SkewlZoneDriver::motionStopping() {
00032 ASSERTRET(motionActive,"SkewlZoneDriver::motionStopping, but motionActive is false");
00033 motionActive=false;
00034 if(!sensorsActive)
00035 commName.removePrimitiveListener(this);
00036 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00037 if(comm!=NULL)
00038 comm->close();
00039 MotionHook::motionStopping();
00040 }
00041
00042 void SkewlZoneDriver::motionCheck(const float outputs[][NumOutputs]) {
00043
00044 bool something_changed = false;
00045 int RCB3_index = 0;
00046
00047 for(unsigned int i=0; i<NUM_SERVO; i++) {
00048 int idx=servos[i];
00049 if(idx<0 || static_cast<unsigned int>(idx)>=NumOutputs) {
00050 if(idx!=UNUSED)
00051 std::cerr << "Warning: SkewlZone driver mapping servo " << i << " to invalid output index " << idx << std::endl;
00052 continue;
00053 }
00054
00055 if(isFirstCheck || lastOutputs[idx]!=outputs[NumFrames-1][idx] ) {
00056
00057 std::cout << "Servo:" << i << "=" << outputs[NumFrames-1][idx] << std::endl;
00058
00059 something_changed = true;
00060
00061
00062 RCB3_index = convertIndex(i);
00063
00064
00065
00066
00067 if(!bsMotorPosIsSpecial(vecMotorPos.m_fBuf[RCB3_index]) && !isFirstCheck)
00068 {
00069
00070 vecMotorMove.m_fBufSpeed[RCB3_index] = 100.0;
00071
00072
00073
00074 if(indexInverted(RCB3_index))
00075 {
00076 vecMotorMove.m_fBufPos[RCB3_index] = (-1)*(outputs[NumFrames-1][idx]);
00077 }
00078 else
00079 {
00080 vecMotorMove.m_fBufPos[RCB3_index] = outputs[NumFrames-1][idx];
00081 }
00082 }
00083 else
00084 {
00085
00086 vecMotorMove.m_fBufSpeed[RCB3_index] = 0.0;
00087 vecMotorMove.m_fBufPos[RCB3_index] = BSBOT_MOTOR_POS_NOOP;
00088 }
00089 }
00090 }
00091
00092 if(!isFirstCheck) {
00093 if(something_changed)
00094 {
00095 rc = bsBotMoveToPosAllMotors(pClient, &vecMotorMove);
00096 }
00097 }
00098
00099 MotionHook::motionCheck(outputs);
00100 }
00101
00102
00103 unsigned int SkewlZoneDriver::nextTimestamp() {
00104 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00105 if(comm==NULL || !comm->isReadable())
00106 return -1U;
00107 return static_cast<unsigned int>(lastSensorTime + 1000.f/(*sensorFramerate) + .5f);
00108 }
00109
00110 void SkewlZoneDriver::registerSource() {
00111 ASSERTRET(!sensorsActive,"SkewlZoneDriver::registerSource, but sensorsActive is true");
00112 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00113 if(comm!=NULL)
00114 comm->open();
00115 queryServos.addPrimitiveListener(this);
00116 if(queryServos) {
00117 for(unsigned int i=0; i<NUM_SERVO; i++) {
00118 provideOutput(servos[i]);
00119 servos[i].addPrimitiveListener(this);
00120 }
00121 }
00122 sensorsActive=true;
00123 commName.addPrimitiveListener(this);
00124 }
00125 void SkewlZoneDriver::deregisterSource() {
00126 ASSERTRET(sensorsActive,"SkewlZoneDriver::deregisterSource, but sensorsActive is false");
00127 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00128 if(comm!=NULL)
00129 comm->close();
00130 if(queryServos) {
00131 for(unsigned int i=0; i<NUM_SERVO; ++i) {
00132 servos[i].removePrimitiveListener(this);
00133 ignoreOutput(servos[i]);
00134 }
00135 }
00136 queryServos.removePrimitiveListener(this);
00137 sensorsActive=false;
00138 if(!motionActive)
00139 commName.removePrimitiveListener(this);
00140 }
00141 void SkewlZoneDriver::doUnfreeze() {
00142 MarkScope sl(poller.getStartLock());
00143 if(!poller.isStarted()) {
00144 poller.resetPeriod(1.0/(*sensorFramerate));
00145 poller.start();
00146 }
00147 sensorFramerate->addPrimitiveListener(this);
00148 }
00149 void SkewlZoneDriver::doFreeze() {
00150 MarkScope sl(poller.getStartLock());
00151 if(poller.isStarted())
00152 poller.stop().join();
00153 sensorFramerate->removePrimitiveListener(this);
00154 }
00155
00156
00157 bool SkewlZoneDriver::advance() {
00158 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00159 if(comm==NULL || !comm->isReadable() || !comm->isWriteable())
00160 return false;
00161
00162 MarkScope commlock(comm->getLock());
00163 std::ostream os(&comm->getWriteStreambuf());
00164 std::istream is(&comm->getReadStreambuf());
00165
00166
00167
00168 os.exceptions(ios_base::badbit);
00169 is.exceptions(ios_base::badbit);
00170
00171 MarkScope writelock(getSensorWriteLock());
00172
00173
00174
00175
00176 if((!isFirstCheck || DataSource::requiresFirstSensor) && queryServos) {
00177
00178 stringstream q;
00179 for(unsigned int i=0; i<NUM_SERVO; i++) {
00180 int idx=servos[i];
00181 if(idx<0 || static_cast<unsigned int>(idx)>=NumOutputs)
00182 continue;
00183 q << "QP " << i << ' ';
00184 }
00185 try {
00186 os << q.rdbuf() << '\r' << flush;
00187 } catch(const std::exception&) {}
00188 if(!os) {
00189 std::cerr << "SkewlZone position query failed (bad write)" << std::endl;
00190 return false;
00191 }
00192 for(unsigned int i=0; i<NUM_SERVO; i++) {
00193 int idx=servos[i];
00194 if(idx<0 || static_cast<unsigned int>(idx)>=NumOutputs)
00195 continue;
00196 int check=is.get();
00197 if(check==-1) {
00198 cerr << "SkewlZoneDriver: bad read!" << endl;
00199 return false;
00200 }
00201 unsigned int v=(unsigned char)check;
00202 setOutputValue(idx, getServo(i,v*10));
00203 }
00204 }
00205 stringstream aq,dq;
00206 bool acnt=0,dcnt=0;
00207 for(unsigned int i=0; i<NUM_INPUT; i++) {
00208 int idx=inputs[i];
00209 if(!buttonMode[i]) {
00210 if(idx<0 || static_cast<unsigned int>(idx)>=NumSensors) {
00211 if(idx!=UNUSED)
00212 std::cerr << "Warning: SkewlZone driver mapping input " << i << " to invalid sensor index " << idx << std::endl;
00213 continue;
00214 }
00215 ++acnt;
00216 aq << 'V' << char('A'+i) << ' ';
00217 } else {
00218 if(idx<0 || static_cast<unsigned int>(idx)>=NumButtons) {
00219 if(idx!=UNUSED)
00220 std::cerr << "Warning: SkewlZone driver mapping input " << i << " to invalid button index " << idx << std::endl;
00221 continue;
00222 }
00223 ++dcnt;
00224 dq << char('A'+i) << ' ' << char('A'+i) << "L ";
00225 }
00226 }
00227
00228
00229 try {
00230 if(dcnt>0)
00231 os << dq.str() << '\r';
00232 if(acnt>0)
00233 os << aq.str() << '\r';
00234 if(dcnt>0 || acnt>0)
00235 os << flush;
00236 } catch(const std::exception&) {}
00237 if(!os) {
00238 std::cerr << "SkewlZone sensor query failed (bad write)" << std::endl;
00239 return false;
00240 }
00241
00242
00243 if(dcnt>0) {
00244 for(unsigned int i=0; i<NUM_INPUT; i++) {
00245 int idx=inputs[i];
00246 if(idx>=0 && static_cast<unsigned int>(idx)<NumButtons && buttonMode[i]) {
00247 int check=is.get();
00248 if(check==-1) {
00249 cerr << "SkewlZoneDriver: bad read!" << endl;
00250 return false;
00251 }
00252 unsigned char cur=check;
00253 check=is.get();
00254 if(check==-1) {
00255 cerr << "SkewlZoneDriver: bad read!" << endl;
00256 return false;
00257 }
00258 unsigned char latch=check;
00259 setButtonValue(idx, getDigital(i,cur,latch));
00260 }
00261 }
00262 }
00263 if(acnt>0) {
00264 for(unsigned int i=0; i<NUM_INPUT; i++) {
00265 int idx=inputs[i];
00266 if(idx>=0 && static_cast<unsigned int>(idx)<NumSensors && !buttonMode[i]) {
00267 int check=is.get();
00268 if(check==-1) {
00269 cerr << "SkewlZoneDriver: bad read!" << endl;
00270 return false;
00271 }
00272 setSensorValue(idx, getAnalog(i,check));
00273 }
00274 }
00275 }
00276 lastSensorTime=get_time();
00277 ++frameNumber;
00278 return true;
00279 }
00280
00281 void SkewlZoneDriver::plistValueChanged(const plist::PrimitiveBase& pl) {
00282 if(&pl==&commName) {
00283
00284
00285 if(poller.isStarted())
00286 poller.stop().join();
00287
00288 CommPort * comm = CommPort::getRegistry().getInstance(commName.getPreviousValue());
00289 if(comm!=NULL) {
00290
00291 if(sensorsActive)
00292 comm->close();
00293 if(motionActive)
00294 comm->close();
00295 }
00296 comm = CommPort::getRegistry().getInstance(commName);
00297 if(comm==NULL) {
00298 std::cerr << "SkewlZoneDriver \"" << instanceName << "\": could not find CommPort \"" << commName << "\"" << std::endl;
00299 } else {
00300
00301 if(sensorsActive)
00302 comm->open();
00303 if(motionActive)
00304 comm->open();
00305 }
00306
00307 if(getTimeScale()>0) {
00308 poller.resetPeriod(1.0/(*sensorFramerate));
00309 poller.start();
00310 }
00311 } else if(&pl==&queryServos) {
00312
00313
00314 if(queryServos) {
00315 for(unsigned int i=0; i<NUM_SERVO; i++) {
00316 provideOutput(servos[i]);
00317 servos[i].addPrimitiveListener(this);
00318 }
00319 } else {
00320 for(unsigned int i=0; i<NUM_SERVO; ++i) {
00321 servos[i].removePrimitiveListener(this);
00322 ignoreOutput(servos[i]);
00323 }
00324 }
00325 } else if(&pl==sensorFramerate) {
00326 poller.resetPeriod(1.0/(*sensorFramerate));
00327 } else {
00328
00329
00330 for(unsigned int i=0; i<NUM_SERVO; ++i) {
00331 if(&pl==&servos[i]) {
00332 ignoreOutput(servos[i].getPreviousValue());
00333 provideOutput(servos[i]);
00334 return;
00335 }
00336 }
00337 std::cerr << "Unhandled value change in " << getClassName() << ": " << pl.get() << std::endl;
00338 }
00339 }
00340
00341 void SkewlZoneDriver::setServo(std::ostream& ss, unsigned int servoIdx, float v) {
00342
00343 unsigned int outputIdx = servos[servoIdx];
00344
00345 float outRange = outputRanges[outputIdx][MaxRange]-outputRanges[outputIdx][MinRange];
00346
00347 unsigned int servoRange = maxPW[servoIdx]-minPW[servoIdx];
00348
00349 float cmd = (v-outputRanges[outputIdx][MinRange])/outRange;
00350
00351
00352 #ifdef TGT_HAS_LEDS
00353 if(outputIdx<LEDOffset || outputIdx>=LEDOffset+NumLEDs)
00354 cmd=1-cmd;
00355 #endif
00356
00357 float pw = cmd*servoRange+minPW[servoIdx];
00358 if(pw<0)
00359 pw=0;
00360
00361 unsigned int bpw = static_cast<unsigned int>(pw+0.5);
00362
00363 if(bpw<minPW[servoIdx])
00364 bpw=minPW[servoIdx];
00365 if(bpw>maxPW[servoIdx])
00366 bpw=maxPW[servoIdx];
00367
00368 ss << '#' << servoIdx << " P" << bpw << ' ';
00369 }
00370
00371 float SkewlZoneDriver::getServo(unsigned int servoIdx, unsigned int pw) {
00372 unsigned int outputIdx = servos[servoIdx];
00373
00374 float outRange = outputRanges[outputIdx][MaxRange]-outputRanges[outputIdx][MinRange];
00375
00376 unsigned int servoRange = maxPW[servoIdx]-minPW[servoIdx];
00377
00378 return (pw-minPW[servoIdx])*outRange/servoRange + outputRanges[outputIdx][MinRange];
00379 }
00380
00381 float SkewlZoneDriver::getAnalog(unsigned int , unsigned char s) {
00382 return s*5.f/256;
00383 }
00384
00385 float SkewlZoneDriver::getDigital(unsigned int , unsigned char cur, unsigned char latch) {
00386
00387 if (cur=='1')
00388 return 0;
00389
00390 return (latch=='1') ? 0.5f : 1;
00391 }
00392
00393 void SkewlZoneDriver::simplePrintVec(const char *sPrefix, double fBuf[], size_t uCount)
00394 {
00395 size_t i;
00396
00397
00398 printf("%s:", sPrefix);
00399 for(i=0; i<uCount; ++i)
00400 {
00401 if( (i % 8) == 0 )
00402 {
00403 printf("\n");
00404 }
00405 printf(" %7.3f", fBuf[i]);
00406 }
00407 printf("\n");
00408 }
00409
00410 int SkewlZoneDriver::createSZclient()
00411 {
00412 if( (pClient = bsClientNew(BsBotTypeKHR2, "GeorgeOfThe_eJungle")) == NULL )
00413 {
00414 LOGERROR("Failed to create client\n");
00415 return SK_EC_EXEC;
00416 }
00417 else
00418 {
00419 return SK_EC_OK;
00420 }
00421 }
00422
00423 int SkewlZoneDriver::connectSZserver()
00424 {
00425 if((rc = bsServerConnect(pClient, SKProxyIPAddr, SKProxyIPPort)) < 0)
00426 {
00427 LOGERROR("bsProxy @%s:%d: %s\n",
00428 SKProxyIPAddr, SKProxyIPPort, bsStrError(rc));
00429 return SK_EC_EXEC;
00430 }
00431 else
00432 {
00433 return SK_EC_OK;
00434 }
00435
00436 }
00437
00438 int SkewlZoneDriver::openRCB3()
00439 {
00440 if((h=bsReqProxDevOpenRCB3(pClient, serialPath.c_str(), 115200, RCB3ModelJ)) < 0)
00441 {
00442 LOGERROR("%s: %s\n", serialPath.c_str(), bsStrError(h));
00443 return SK_EC_EXEC;
00444 }
00445 else
00446 {
00447 return SK_EC_OK;
00448 }
00449
00450 }
00451
00452 int SkewlZoneDriver::RCB3EStop()
00453 {
00454 rc = bsBotEStop(pClient);
00455
00456 return rc;
00457 }
00458
00459 int SkewlZoneDriver::convertIndex(int i)
00460 {
00461 switch(i)
00462 {
00463 case 0:
00464 return 1;
00465 case 1:
00466 return 2;
00467 case 2:
00468 return 3;
00469 case 3:
00470 return 5;
00471 case 4:
00472 return 6;
00473 case 5:
00474 return 7;
00475 case 6:
00476 return 10;
00477 case 7:
00478 return 11;
00479 case 8:
00480 return 12;
00481 case 9:
00482 return 13;
00483 case 10:
00484 return 14;
00485 case 11:
00486 return 16;
00487 case 12:
00488 return 17;
00489 case 13:
00490 return 18;
00491 case 14:
00492 return 19;
00493 case 15:
00494 return 20;
00495 case 16:
00496 return 0;
00497 }
00498 }
00499
00500 int SkewlZoneDriver::indexInverted(int i)
00501 {
00502 switch(i)
00503 {
00504 case 0:
00505 return 0;
00506 case 1:
00507 return 0;
00508 case 2:
00509 return 0;
00510 case 3:
00511 return 0;
00512 case 4:
00513 return 0;
00514 case 5:
00515 return 1;
00516 case 6:
00517 return 1;
00518 case 7:
00519 return 1;
00520 case 8:
00521 return 0;
00522 case 9:
00523 return 0;
00524 case 10:
00525 return 1;
00526 case 11:
00527 return 0;
00528 case 12:
00529 return 0;
00530 case 13:
00531 return 1;
00532 case 14:
00533 return 1;
00534 case 15:
00535 return 0;
00536 case 16:
00537 return 0;
00538 case 17:
00539 return 1;
00540 case 18:
00541 return 1;
00542 case 19:
00543 return 0;
00544 case 20:
00545 return 0;
00546 }
00547 }
00548
00549 void SkewlZoneDriver::attachRCB3()
00550 {
00551 bsAttrSetInterface(pClient, BsAttrKeyIFRobotController, h);
00552 }
00553
00554 void SkewlZoneDriver::setSZunits()
00555 {
00556 bsAttrSetUnits(pClient, BsAttrKeyUnitsMotorPos, units_radians);
00557 bsAttrSetUnits(pClient, BsAttrKeyUnitsMotorSpeed, units_percent);
00558
00559
00560 }
00561
00562 void SkewlZoneDriver::printServos()
00563 {
00564 rc = bsBotReadAllMotorPos(pClient, &vecMotorPos);
00565 if( rc == BS_OK )
00566 {
00567 simplePrintVec("Current servo positions (radians)",
00568 vecMotorPos.m_fBuf,
00569 vecMotorPos.m_uCount);
00570 }
00571 }
00572
00573 void SkewlZoneDriver::initMotorVec()
00574 {
00575 vecMotorMove.m_uCount = vecMotorPos.m_uCount;
00576
00577
00578
00579 for(int i=0; i<vecMotorMove.m_uCount; i++) {
00580 vecMotorMove.m_fBufSpeed[i] = 0.0;
00581 vecMotorMove.m_fBufPos[i] = BSBOT_MOTOR_POS_NOOP;
00582 }
00583 }
00584
00585
00586
00587
00588
00589 #endif