00001 #include "Dynamixel.h"
00002 #include "Shared/MarkScope.h"
00003 #include "Shared/debuget.h"
00004 #include "Shared/WorldState.h"
00005 #include "Shared/TimeET.h"
00006 #include "IPC/CallbackThread.h"
00007 #include <algorithm>
00008
00009 using namespace std;
00010 using namespace DynamixelProtocol;
00011
00012 INSTANTIATE_NAMEDENUMERATION_STATICS(SensorOffset_t);
00013 enum SeenState { LED_UNSEEN, LED_SAME, LED_DIFF };
00014
00015 unsigned int DynamixelDriver::VOLTAGE_SENSOR_OFFSET = capabilities.findSensorOffset("PowerVoltage");
00016 unsigned int DynamixelDriver::TEMP_SENSOR_OFFSET = capabilities.findSensorOffset("PowerThermo");
00017
00018 const std::string DynamixelDriver::autoRegisterDynamixelDriver = DeviceDriver::getRegistry().registerType<DynamixelDriver>("Dynamixel");
00019
00020 void DynamixelDriver::motionStarting() {
00021 ASSERTRET(!motionActive,"DynamixelDriver::motionStarting, but motionActive is true");
00022 MotionHook::motionStarting();
00023
00024 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00025 if(comm==NULL) {
00026 if(commName.size()>0)
00027 std::cerr << "DynamixelDriver \"" << instanceName << "\": initialization failed, CommPort \"" << commName << "\" not found" << std::endl;
00028 } else if(!comm->open() || !comm->isWriteable()) {
00029 std::cerr << "DynamixelDriver \"" << instanceName << "\": initialization failed, CommPort disconnected" << std::endl;
00030 } else {
00031 bool restartComm=false;
00032 if(commThread.isStarted()) {
00033 commThread.stop().join();
00034 restartComm=true;
00035 }
00036 MarkScope autolock(*comm);
00037 std::ostream os(&comm->getWriteStreambuf());
00038
00039 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it)
00040 it->second->punch = it->second->margin = it->second->slope = 0;
00041 write(os, BroadcastFullComplianceCmd()).flush();
00042 write(os, BroadcastNoPunchCmd()).flush();
00043 write(os, BroadcastZeroSpeedCmd()).flush();
00044
00045 write(os, BroadcastTorqueCmd(true)).flush();
00046
00047 if(!sensorsActive)
00048 pingServos();
00049
00050 if(restartComm)
00051 commThread.start();
00052 }
00053
00054 motionActive=true;
00055 commName.addPrimitiveListener(this);
00056 }
00057
00058 bool DynamixelDriver::isConnected() {
00059 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00060 return (comm!=NULL && comm->isReadable() && comm->isWriteable());
00061 }
00062
00063 void DynamixelDriver::motionStopping() {
00064 ASSERTRET(motionActive,"DynamixelDriver::motionStopping, but motionActive is false");
00065 motionActive=false;
00066 if(!sensorsActive) {
00067 if(commThread.isStarted())
00068 commThread.stop().join();
00069
00070 commName.removePrimitiveListener(this);
00071 }
00072 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00073 if(comm!=NULL) {
00074 sendZeroTorqueCmd(*comm);
00075 comm->close();
00076 }
00077 MotionHook::motionStopping();
00078 }
00079
00080 void DynamixelDriver::motionCheck(const float outputs[][NumOutputs]) {
00081 float * buf = commThread.getWriteBuffer();
00082 for(unsigned int i=NumOutputs; i!=0; ) {
00083 --i;
00084 buf[i] = outputs[NumFrames-1][i];
00085 }
00086 commThread.setWriteBufferTimestamp(buf);
00087 }
00088
00089 void DynamixelDriver::updatePIDs(const std::vector<MotionHook::PIDUpdate>& pids) {
00090 MarkScope autolock(commThread.pidLock);
00091 for(std::vector<MotionHook::PIDUpdate>::const_iterator it=pids.begin(); it!=pids.end(); ++it)
00092 commThread.pidValues[it->idx]=*it;
00093 commThread.dirtyPIDs+=pids.size();
00094 }
00095
00096 void DynamixelDriver::registerSource() {
00097 ASSERTRET(!sensorsActive,"DynamixelDriver::registerSource, but sensorsActive is true");
00098 sensorsActive=true;
00099 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00100 if(comm!=NULL)
00101 comm->open();
00102 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00103 if(it->second->detected) {
00104 provideOutput(it->second->output);
00105 provideOutput(it->second->freeSpinOutput);
00106 }
00107 it->second->output.addPrimitiveListener(this);
00108 it->second->freeSpinOutput.addPrimitiveListener(this);
00109 it->second->detected.addPrimitiveListener(this);
00110 }
00111 if(!motionActive && comm!=NULL && comm->isWriteable())
00112 pingServos();
00113 commName.addPrimitiveListener(this);
00114 commLatency.addPrimitiveListener(this);
00115 numPoll.addPrimitiveListener(this);
00116 responseTime.addPrimitiveListener(this);
00117 plistValueChanged(numPoll);
00118 }
00119
00120 void DynamixelDriver::deregisterSource() {
00121 ASSERTRET(sensorsActive,"DynamixelDriver::deregisterSource, but sensorsActive is false");
00122 sensorsActive=false;
00123 if(!motionActive) {
00124 if(commThread.isStarted())
00125 commThread.stop().join();
00126
00127 commName.removePrimitiveListener(this);
00128 }
00129 commLatency.removePrimitiveListener(this);
00130 numPoll.removePrimitiveListener(this);
00131 responseTime.removePrimitiveListener(this);
00132 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00133 if(comm!=NULL)
00134 comm->close();
00135 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00136 it->second->detected.removePrimitiveListener(this);
00137 it->second->freeSpinOutput.removePrimitiveListener(this);
00138 it->second->output.removePrimitiveListener(this);
00139 if(it->second->detected)
00140 ignoreOutput(it->second->output);
00141 }
00142 }
00143
00144 void DynamixelDriver::doUnfreeze() {
00145 MarkScope sl(commThread.getStartLock());
00146 if(!commThread.isStarted()) {
00147 commThread.start();
00148 }
00149 }
00150
00151 void DynamixelDriver::doFreeze() {
00152 MarkScope sl(commThread.getStartLock());
00153 if(commThread.isStarted()) {
00154 commThread.stop().join();
00155 ASSERT(!commThread.isStarted(),"DynamixelDriver::CommThread ended, but still running?");
00156 }
00157 }
00158
00159 unsigned int DynamixelDriver::nextTimestamp() {
00160 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00161 if(comm==NULL || !comm->isReadable() || !comm->isWriteable())
00162 return -1U;
00163 return commThread.nextTimestamp();
00164 }
00165
00166 bool DynamixelDriver::advance() {
00167 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00168 if(comm==NULL || !comm->isReadable() || !comm->isWriteable())
00169 return false;
00170
00171 if(!commThread.isStarted()) {
00172
00173 pingServos(true);
00174 }
00175 static unsigned int lockeduptest=0;
00176 if(!commThread.takeUpdate()) {
00177 if(++lockeduptest==8)
00178 std::cerr << "WARNING: DynamixelDriver appears to be locked up, not getting new sensor readings" << std::endl;
00179 return false;
00180 }
00181 if(lockeduptest>=8)
00182 std::cerr << "DynamixelDriver has gotten unwedged, sending sensor updates again." << std::endl;
00183 lockeduptest=0;
00184
00185 return true;
00186 }
00187
00188 void DynamixelDriver::plistValueChanged(const plist::PrimitiveBase& pl) {
00189 if(&pl==&commName) {
00190
00191
00192 if(commThread.isStarted())
00193 commThread.stop().join();
00194
00195 CommPort * comm = CommPort::getRegistry().getInstance(commName.getPreviousValue());
00196 if(comm!=NULL) {
00197
00198 if(sensorsActive)
00199 comm->close();
00200 if(motionActive) {
00201 sendZeroTorqueCmd(*comm);
00202 comm->close();
00203 }
00204 }
00205 bool motionWasActive=motionActive, sensorsWereActive=sensorsActive;
00206 sensorsActive=motionActive=false;
00207
00208
00209 if(motionWasActive)
00210 motionStarting();
00211 if(sensorsWereActive)
00212 registerSource();
00213
00214 if(getTimeScale()>0)
00215 commThread.start();
00216 } else if(&pl==&commLatency || &pl==&numPoll || &pl==&responseTime) {
00217 if(numPoll==0) {
00218 std::cerr << "NumPoll must be at least 1, remove " << instanceName << " from the Sensors.Sources list if you want to disable sensor polling." << std::endl;
00219 numPoll=1;
00220 } else if(numPoll>1 && (numPoll * responseTime)/1000 > commLatency) {
00221 std::cerr << "WARNING: NumPoll * ResponseTime (" << numPoll << "·" << responseTime << "µs=" << (numPoll*responseTime/1000) << "ms) exceeds BufferLatency (" << commLatency << "ms)\n"
00222 "You may be missing synchronization with buffer flushes" << std::endl;
00223 }
00224 } else {
00225
00226
00227 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00228 if(&pl==&it->second->detected) {
00229 if(it->second->detected) {
00230 provideOutput(it->second->output);
00231 provideOutput(it->second->freeSpinOutput);
00232 } else {
00233 ignoreOutput(it->second->freeSpinOutput);
00234 ignoreOutput(it->second->output);
00235 }
00236 return;
00237 } else if(it->second->detected) {
00238 if(&pl==&it->second->output) {
00239 ignoreOutput(it->second->output.getPreviousValue());
00240 provideOutput(it->second->output);
00241 return;
00242 } else if(&pl==&it->second->freeSpinOutput) {
00243 ignoreOutput(it->second->freeSpinOutput.getPreviousValue());
00244 provideOutput(it->second->freeSpinOutput);
00245 return;
00246 }
00247 } else if(&pl==&it->second->output || &pl==&it->second->freeSpinOutput) {
00248 return;
00249 }
00250 }
00251 std::cerr << "Unhandled value change in " << getClassName() << ": " << pl.get() << std::endl;
00252 }
00253 }
00254
00255 void DynamixelDriver::processDriverMessage(const DriverMessaging::Message& d) {
00256 if(d.CLASS_NAME==DriverMessaging::LoadPrediction::NAME) {
00257 const DriverMessaging::LoadPrediction& loads = dynamic_cast<const DriverMessaging::LoadPrediction&>(d);
00258 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00259 plist::DictionaryOf<plist::Primitive<float> >::const_iterator dit = loads.loads.findEntry(it->second->output.get());
00260 if(dit!=loads.loads.end())
00261 it->second->predictedLoad=*dit->second;
00262 }
00263 } else if(d.CLASS_NAME==DriverMessaging::SensorPriority::NAME) {
00264 const DriverMessaging::SensorPriority& pri = dynamic_cast<const DriverMessaging::SensorPriority&>(d);
00265 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00266 plist::DictionaryOf<plist::Primitive<float> >::const_iterator dit = pri.outputs.findEntry(it->second->output.get());
00267 if(dit!=pri.outputs.end())
00268 it->second->sensorPriority=*dit->second;
00269 }
00270 }
00271 }
00272
00273 void DynamixelDriver::pingServos(bool detectedOnly) {
00274 if(!detectedOnly)
00275 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it)
00276 it->second->detected=false;
00277
00278 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00279 if(comm==NULL)
00280 return;
00281
00282 bool restartComm=false;
00283 if(commThread.isStarted()) {
00284 commThread.stop().join();
00285 restartComm=true;
00286 }
00287
00288 MarkScope autolock(comm->getLock());
00289 if(!comm->isWriteable() || !comm->isReadable()) {
00290 std::cerr << "DynamixelDriver \"" << instanceName << "\": cannot ping servos, CommPort disconnected." << std::endl;
00291 ASSERT(!restartComm,"How was the comm thread still running? Not restarting it...");
00292 return;
00293 }
00294 std::istream is(&comm->getReadStreambuf());
00295 std::ostream os(&comm->getWriteStreambuf());
00296 if(!is || !os) {
00297 std::cerr << "DynamixelDriver \"" << instanceName << "\": cannot ping servos, CommPort gave bad iostreams." << std::endl;
00298 ASSERT(!restartComm,"How was the comm thread still running? Not restarting it...");
00299 return;
00300 }
00301
00302
00303
00304 is.exceptions(ios_base::badbit);
00305
00306 MarkScope writeLock(getSensorWriteLock());
00307 ServoSensorsResponse servoSensors;
00308 AXS1SensorsResponse axs1Sensors;
00309 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00310 if( (it->second->getModel()==MODEL_UNKNOWN && !it->second->hasSensorOffset() && it->second->output==UNUSED)
00311 || ( it->second->getModel()==MODEL_AXS1 && !it->second->hasSensorOffset() )
00312 || ( it->second->getModel()!=MODEL_UNKNOWN && it->second->getModel()!=MODEL_AXS1 && it->second->output==UNUSED ))
00313 continue;
00314 if(!detectedOnly) {
00315 it->second->setModel(MODEL_UNKNOWN);
00316 it->second->detected=false;
00317 } else if(!it->second->detected) {
00318 continue;
00319 }
00320 unsigned int servoid = it->second->servoID;
00321 PingThread ping(is, os, servoid, it->second->output, &servoSensors, &axs1Sensors);
00322 const char* model = static_cast<const char*>(ping.join());
00323 is.clear();
00324 os.clear();
00325 if(model==Thread::CANCELLED || model==NULL) {
00326 unsigned int idx = it->second->output;
00327 if(static_cast<unsigned int>(idx)<NumOutputs) {
00328 cerr << "Warning: Dynamixel servo " << it->first
00329 << " (mapped to output offset " << outputNames[idx] << ")"
00330 << " was disconnected or not found" << endl;
00331 } else if(idx!=UNUSED) {
00332 cerr << "Warning: Dynamixel servo " << it->first
00333 << " (mapped to invalid output " << idx << "))"
00334 << " was disconnected or not found" << endl;
00335 } else if(servoid>=NumOutputs+START_SERVO_ID && (it->second->leftIRDistOffset!=-1 || it->second->centerIRDistOffset!=-1 || it->second->rightIRDistOffset!=-1
00336 || it->second->leftLuminosityOffset!=-1 || it->second->centerLuminosityOffset!=-1 || it->second->rightLuminosityOffset!=-1
00337 || it->second->micVolumeOffset!=-1 || it->second->micSpikeCountOffset!=-1))
00338 {
00339 cerr << "Warning: Dynamixel sensor module " << it->first
00340 << " was disconnected or not found" << endl;
00341 }
00342 it->second->sensorActivation=0;
00343 continue;
00344 }
00345 it->second->setModelName(model);
00346 for(std::map<DynamixelProtocol::ModelID_t, const std::string>::const_iterator nit=DynamixelProtocol::dynamixelModels.begin(); nit!=DynamixelProtocol::dynamixelModels.end(); ++nit) {
00347 if(nit->second==model) {
00348 it->second->setModel(nit->first);
00349 break;
00350 }
00351 }
00352
00353 it->second->detected=true;
00354 if(it->second->sensorActivation==0)
00355 it->second->sensorActivation=1;
00356 if(it->second->getModel()==MODEL_AXS1) {
00357 provideValues(*it->second,axs1Sensors);
00358 } else if(it->second->getModel()!=MODEL_UNKNOWN) {
00359 it->second->lastCmd=servoSensors.getPosition();
00360 provideValues(*it->second,servoSensors);
00361 }
00362 }
00363
00364 if(restartComm)
00365 commThread.start();
00366 }
00367
00368 void DynamixelDriver::sendZeroTorqueCmd(CommPort& comm) {
00369 if(!comm.isWriteable()) {
00370 std::cerr << "DynamixelDriver \"" << instanceName << "\": unable to send shutdown, CommPort disconnected" << std::endl;
00371 } else {
00372 MarkScope autolock(comm);
00373 std::ostream os(&comm.getWriteStreambuf());
00374
00375
00376 write(os, BroadcastTorqueCmd(false)).flush();
00377 }
00378 }
00379
00380
00381 static bool sensorActivationCompare(const DynamixelDriver::ServoInfo* a, const DynamixelDriver::ServoInfo* b) { return a->sensorActivation > b->sensorActivation; }
00382
00383
00384 Thread& DynamixelDriver::CommThread::stop() {
00385
00386 if(getCurrent()!=&failsafe) {
00387
00388 failsafe.restartFlag=false;
00389 failsafe.stop().join();
00390 }
00391
00392 if(isStarted())
00393 Thread::stop();
00394 return *this;
00395 }
00396
00397 void DynamixelDriver::CommThread::waitForUpdate() {
00398 if(!isStarted()) {
00399 if(!updated)
00400 std::cerr << "DynamixelDriver::CommThread::waitForUpdate: thread not running!" << std::endl;
00401 return;
00402 }
00403 if(updated)
00404 return;
00405 join();
00406 ASSERT(!failsafe.isStarted(),"DynamixelDriver::CommThread ended, but failsafe still running?");
00407 }
00408
00409 float * DynamixelDriver::CommThread::getWriteBuffer() {
00410 float * bufs[3];
00411 if(timestampBufA<timestampBufB) {
00412 if(timestampBufA<timestampBufC) {
00413 bufs[0]=outputBufA;
00414 if(timestampBufB<timestampBufC) {
00415 bufs[1]=outputBufB;
00416 bufs[2]=outputBufC;
00417 } else {
00418 bufs[1]=outputBufC;
00419 bufs[2]=outputBufB;
00420 }
00421 } else {
00422 bufs[0]=outputBufC;
00423 bufs[1]=outputBufA;
00424 bufs[2]=outputBufB;
00425 }
00426 } else if(timestampBufB<timestampBufC) {
00427 bufs[0]=outputBufB;
00428 if(timestampBufA<timestampBufC) {
00429 bufs[1]=outputBufA;
00430 bufs[2]=outputBufC;
00431 } else {
00432 bufs[1]=outputBufC;
00433 bufs[2]=outputBufA;
00434 }
00435 } else {
00436 bufs[0]=outputBufC;
00437 bufs[1]=outputBufB;
00438 bufs[2]=outputBufA;
00439 }
00440 return (bufs[0]==curBuf) ? bufs[1] : bufs[0];
00441 }
00442
00443 void DynamixelDriver::CommThread::setWriteBufferTimestamp(float * buf) {
00444 if(buf==outputBufA)
00445 timestampBufA=get_time();
00446 else if(buf==outputBufB)
00447 timestampBufB=get_time();
00448 else if(buf==outputBufC)
00449 timestampBufC=get_time();
00450 else
00451 std::cerr << "DynamixelDriver::CommThread::setWriteBufferTimestamp was passed a unknown buffer" << std::endl;
00452 }
00453
00454 bool DynamixelDriver::CommThread::launched() {
00455 isFirstCheck=true;
00456 if(!failsafe.isRunning())
00457 failsafe.start();
00458 return true;
00459 }
00460
00461 void DynamixelDriver::CommThread::cancelled() {
00462 if(!failsafe.isEngaged()) {
00463 ASSERT(!failsafe.isStarted(),"Failsafe is still running! How was CommThread cancelled?");
00464 if(responsePending) {
00465
00466 CallbackThread cb(std::mem_fun(&CommThread::clearBuffer), this, true);
00467 usleep(50*1000);
00468 if(cb.isStarted())
00469 cb.stop().join();
00470 }
00471 } else {
00472 if(servoPollQueue.empty())
00473 return;
00474 ServoInfo* cur=NULL;
00475
00476 for(std::vector<ServoInfo*>::const_iterator it=servoPollQueue.begin(); it!=servoPollQueue.end(); ++it) {
00477 cur=*it;
00478 if(cur->sensorActivation>0)
00479 break;
00480 }
00481 cur->sensorActivation=0;
00482
00483 if(++(cur->failures) >= 20) {
00484
00485 std::cerr << "DynamixelDriver: too many failures on #" << cur->servoID << ", disabling 'Detected' flag" << std::endl;
00486 cur->detected=false;
00487 cur->sensorActivation=0;
00488 }
00489 }
00490 }
00491
00492 void DynamixelDriver::CommThread::clearBuffer() {
00493 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00494 if(comm==NULL || !comm->isReadable() || !comm->isWriteable())
00495 return;
00496
00497 MarkScope autolock(comm->getLock());
00498 std::istream is(&comm->getReadStreambuf());
00499
00500
00501
00502 is.exceptions(ios_base::badbit);
00503
00504 while(is) {
00505 is.get();
00506 Thread::testCurrentCancel();
00507 }
00508 }
00509
00510 unsigned int DynamixelDriver::CommThread::runloop() {
00511 testCancel();
00512
00513 failsafe.progressFlag=true;
00514
00515
00516 if(servoPollQueue.empty())
00517 return FrameTime*NumFrames*1000;
00518
00519
00520 CommPort * comm = CommPort::getRegistry().getInstance(commName);
00521 if(comm==NULL || !comm->isReadable() || !comm->isWriteable())
00522 return FrameTime*NumFrames*1000;
00523
00524 MarkScope autolock(comm->getLock());
00525 std::ostream os(&comm->getWriteStreambuf());
00526 std::istream is(&comm->getReadStreambuf());
00527
00528
00529
00530 os.exceptions(ios_base::badbit);
00531 is.exceptions(ios_base::badbit);
00532
00533 if(!driver.sensorsActive && continuousUpdates)
00534 updateCommands(is,os);
00535
00536 unsigned int NUM_AVAIL_POLL = std::min<unsigned int>(driver.numPoll,servoPollQueue.size());
00537 std::partial_sort(servoPollQueue.begin(),servoPollQueue.begin()+NUM_AVAIL_POLL,servoPollQueue.end(),sensorActivationCompare);
00538
00539 for(unsigned int i=0; driver.sensorsActive && i<NUM_AVAIL_POLL; ++i) {
00540 failsafe.progressFlag=true;
00541 if(servoPollQueue[i]->sensorActivation<=0) {
00542 NUM_AVAIL_POLL=i;
00543 break;
00544 }
00545 if(i>0) {
00546
00547 struct timespec st, rt;
00548 st.tv_sec = 0;
00549 st.tv_nsec = driver.responseTime*1000;
00550 while(nanosleep(&st,&rt)!=0) {
00551 testCancel();
00552 st=rt;
00553 }
00554 }
00555 failsafe.progressFlag=true;
00556 if(continuousUpdates)
00557 updateCommands(is,os);
00558
00559
00560
00561
00562
00563 if(servoPollQueue[i]->getModel()==MODEL_AXS1) {
00564
00565 write(os, ReadAXS1SensorsCmd(servoPollQueue[i]->servoID)).flush();
00566 responsePending=true;
00567 } else if(servoPollQueue[i]->getModel()!=MODEL_UNKNOWN) {
00568
00569 write(os, ReadServoSensorsCmd(servoPollQueue[i]->servoID)).flush();
00570 responsePending=true;
00571 } else {
00572 std::cerr << "Dynamixel Driver, attempting to poll unknown model '" << servoPollQueue[i]->getModelName() << "' (" << servoPollQueue[i]->getModel() << ") at servo ID " << servoPollQueue[i]->servoID << " (ignoring)" << std::endl;
00573
00574 std::vector<ServoInfo*>::iterator it=servoPollQueue.begin();
00575 std::advance(it,i);
00576 servoPollQueue.erase(it);
00577 --i;
00578 os.flush();
00579 }
00580 if(!os) {
00581 std::cerr << "DynamixelDriver " << driver.instanceName << " unable to send sensor poll request, lost comm?" << std::endl;
00582 return false;
00583 }
00584 }
00585
00586
00587
00588
00589 lastSensorTime=get_time();
00590
00591 ServoSensorsResponse servoresponse;
00592 AXS1SensorsResponse axs1response;
00593 for(unsigned int i=0; driver.sensorsActive && i<NUM_AVAIL_POLL; ++i) {
00594 failsafe.progressFlag=true;
00595
00596
00597
00598 if(servoPollQueue[i]->getModel()==MODEL_AXS1) {
00599 readResponse(axs1response, is, *servoPollQueue[i]);
00600
00601
00602
00603 unsigned char checksum = 0;
00604 if(axs1response.sndCount>0) {
00605 write(os, SyncWriteHeader<SyncWriteSoundHoldAndCountEntry>(1), checksum);
00606 write(os, SyncWriteSoundHoldAndCountEntry(servoPollQueue[i]->servoID), checksum);
00607 } else {
00608 write(os, SyncWriteHeader<SyncWriteSoundHoldEntry>(1), checksum);
00609 write(os, SyncWriteSoundHoldEntry(servoPollQueue[i]->servoID), checksum);
00610 }
00611 os.put(~checksum);
00612
00613
00614 } else if(servoPollQueue[i]->getModel()!=MODEL_UNKNOWN) {
00615 readResponse(servoresponse, is, *servoPollQueue[i]);
00616 }
00617
00618 if(i==0)
00619 lastSensorTime=get_time();
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 }
00633 responsePending=false;
00634
00635
00636
00637
00638 const float actInc = (driver.numPoll>servoPollQueue.size()) ? 20 : 20.f*driver.numPoll/servoPollQueue.size();
00639 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00640 ServoInfo * s = it->second;
00641 if(s->detected) {
00642 if(s->sensorPriority>=0) {
00643 s->sensorActivation += s->sensorPriority;
00644 } else {
00645
00646 s->sensorActivation += actInc + s->recentCmdMotion;
00647 }
00648 }
00649
00650
00651 }
00652
00653
00654
00655 updated=true;
00656
00657
00658 if(!continuousUpdates) {
00659 failsafe.stop();
00660 return -1U;
00661 }
00662
00663 return (driver.sensorsActive && NUM_AVAIL_POLL>0) ? 0 : FrameTime*NumFrames*1000;
00664 }
00665
00666 void DynamixelDriver::provideValues(const ServoInfo& info, const DynamixelProtocol::ServoSensorsResponse& response) {
00667 MarkScope writeLock(getSensorWriteLock());
00668
00669 if(info.freeSpinOutput<NumOutputs) {
00670 float x=response.getSpeed();
00671 if(info.invertRotation)
00672 x = info.maxTic - x;
00673 unsigned int idx=info.freeSpinOutput;
00674 float outputValue = x * info.repSpeedSlope;
00675 setOutputValue(idx,outputValue);
00676 if(idx-PIDJointOffset<NumPIDJoints) {
00677 float dutyValue = (info.curRotationMode!=ServoInfo::CONTINUOUS) ? 0 : response.getLoad() / 1023.f;
00678 setPIDDutyValue(idx-PIDJointOffset, (info.invertRotation) ? -dutyValue : dutyValue);
00679 }
00680 }
00681 if(info.output<NumOutputs && info.output!=info.freeSpinOutput) {
00682 float x = response.getPosition();
00683 if(info.invertRotation)
00684 x=info.maxTic-x;
00685 x = x/info.maxTic*info.maxAngle;
00686 x -= info.zeroAngle + info.maxAngle/2;
00687 unsigned int idx=info.output;
00688 setOutputValue(idx,x);
00689 if(idx-PIDJointOffset<NumPIDJoints) {
00690 float dutyValue = (info.curRotationMode!=ServoInfo::POSITION) ? 0 : response.getLoad() / 1023.f;
00691 setPIDDutyValue(idx-PIDJointOffset, (info.invertRotation) ? -dutyValue : dutyValue);
00692 }
00693 }
00694 ASSERT(info.output!=info.freeSpinOutput || info.curRotationMode==ServoInfo::CONTINUOUS,"Permanent free-spin, but curRotationMode not CONTINUOUS");
00695
00696 if(VOLTAGE_SENSOR_OFFSET<NumSensors)
00697 setSensorValue(VOLTAGE_SENSOR_OFFSET, response.voltage/10.f);
00698 if(TEMP_SENSOR_OFFSET<NumSensors)
00699 setSensorValue(TEMP_SENSOR_OFFSET, response.temp);
00700 }
00701
00702
00703
00704
00705 void DynamixelDriver::provideValues(ServoInfo& info, const DynamixelProtocol::AXS1SensorsResponse& response) {
00706 if(info.leftIRDistOffset!=-1)
00707 setSensorValue(info.leftIRDistOffset, response.leftIR/255.f);
00708 if(info.centerIRDistOffset!=-1)
00709 setSensorValue(info.centerIRDistOffset, response.centerIR/255.f);
00710 if(info.rightIRDistOffset!=-1)
00711 setSensorValue(info.rightIRDistOffset, response.rightIR/255.f);
00712
00713 if(info.leftLuminosityOffset!=-1)
00714 setSensorValue(info.leftLuminosityOffset, response.leftLum/255.f);
00715 if(info.centerLuminosityOffset!=-1)
00716 setSensorValue(info.centerLuminosityOffset, response.centerLum/255.f);
00717 if(info.rightLuminosityOffset!=-1)
00718 setSensorValue(info.rightLuminosityOffset, response.rightLum/255.f);
00719
00720 if(info.micVolumeOffset!=-1 && response.sndMaxHold>0)
00721 setSensorValue(info.micVolumeOffset, std::abs(response.sndMaxHold-127)/128.f);
00722 if(info.micSpikeCountOffset!=-1) {
00723 if(info.micSpikeFrameNumber != getSensorFrameNumber()) {
00724
00725 setSensorValue(info.micSpikeCountOffset, response.sndCount);
00726 info.micSpikeFrameNumber = getSensorFrameNumber();
00727 } else if(response.sndCount>0) {
00728
00729 setSensorValue(info.micSpikeCountOffset, getSensorValue(info.micSpikeCountOffset) + response.sndCount);
00730 }
00731 }
00732
00733
00734
00735
00736
00737
00738
00739 }
00740
00741 void DynamixelDriver::CommThread::updateCommands(std::istream& is, std::ostream& os) {
00742 if(timestampBufA>timestampBufB) {
00743 if(timestampBufA>timestampBufC) {
00744 if(curBuf == outputBufA)
00745 return;
00746 curBuf = outputBufA;
00747 } else {
00748 if(curBuf == outputBufC)
00749 return;
00750 curBuf = outputBufC;
00751 }
00752 } else if(timestampBufB>timestampBufC) {
00753 if(curBuf == outputBufB)
00754 return;
00755 curBuf = outputBufB;
00756 } else {
00757 if(timestampBufC==0)
00758 return;
00759 if(curBuf == outputBufC)
00760 return;
00761 curBuf = outputBufC;
00762 }
00763
00764 float period = NumFrames*FrameTime;
00765 if(getTimeScale()>0)
00766 period /= ::getTimeScale();
00767
00768 std::vector<SyncWritePosSpeedEntry> packets;
00769 packets.reserve(servos.size());
00770
00771 std::vector<SyncWriteContinuousRotationEntry> modes;
00772 modes.reserve(servos.size());
00773
00774 typedef std::vector<std::pair<std::string,ServoInfo::RotationMode> > modeUpdates_t;
00775 modeUpdates_t modeUpdates;
00776 modeUpdates.reserve(servos.size());
00777
00778 std::vector<SyncWriteLEDEntry> leds;
00779 std::vector<SeenState> seenLEDs(NumLEDs,LED_UNSEEN);
00780 leds.reserve(servos.size());
00781
00782 std::vector<SyncWriteComplianceEntry> compliances;
00783 compliances.reserve(servos.size());
00784
00785 std::vector<SyncWritePunchEntry> punches;
00786 punches.reserve(servos.size());
00787
00788 std::vector<SyncWritePIDEntry> pidentries;
00789 pidentries.reserve(servos.size());
00790
00791 std::vector<SyncWriteTorqueEntry> torqueToggles;
00792 torqueToggles.reserve(servos.size());
00793
00794 const bool havePIDUpdates = (dirtyPIDs>0);
00795 if(havePIDUpdates)
00796 pidLock.lock();
00797
00798 for(servo_iterator it=servos.begin(); it!=servos.end(); ++it) {
00799 if(!it->second->detected || it->second->getModel()==MODEL_AXS1)
00800 continue;
00801 unsigned int servoid = it->second->servoID;
00802
00803 unsigned int ledidx = it->second->led;
00804 #ifndef TGT_HAS_LEDS
00805 if(ledidx!=UNUSED)
00806 std::cerr << "Warning: Dynamixel driver mapping servo " << it->first << " to invalid led output index " << ledidx << std::endl;
00807 #else
00808 unsigned int ledsubidx = ledidx - LEDOffset;
00809 if(ledidx>=NumOutputs) {
00810 if(ledidx!=UNUSED)
00811 std::cerr << "Warning: Dynamixel driver mapping servo " << it->first << " to invalid led output index " << ledidx << std::endl;
00812 } else if(static_cast<unsigned int>(ledsubidx)>=NumLEDs) {
00813 std::cerr << "Warning: Dynamixel driver mapping servo " << it->first << " to invalid led index " << ledsubidx << std::endl;
00814 } else if(lastOutputs[ledidx]!=curBuf[ledidx] || lastLEDState[ledsubidx]==LED_UNKNOWN || (curBuf[ledidx]>0 && curBuf[ledidx]<1)) {
00815 if(seenLEDs[ledsubidx]==LED_UNSEEN) {
00816
00817
00818 LedState cur = calcLEDValue(ledsubidx,curBuf[ledidx]) ? LED_ON : LED_OFF;
00819 seenLEDs[ledsubidx] = (cur==lastLEDState[ledsubidx]) ? LED_SAME : LED_DIFF;
00820 lastLEDState[ledsubidx]=cur;
00821 }
00822 if(seenLEDs[ledsubidx]==LED_DIFF) {
00823
00824 leds.push_back(SyncWriteLEDEntry(servoid,lastLEDState[ledsubidx]==LED_ON));
00825 }
00826 }
00827 #endif
00828
00829 unsigned int idx = it->second->freeSpinOutput;
00830 ServoInfo::RotationMode rm = ServoInfo::CONTINUOUS;
00831 if(it->second->output!=it->second->freeSpinOutput) {
00832 if(it->second->freeSpinOutput>=NumOutputs) {
00833 if(it->second->freeSpinOutput!=UNUSED)
00834 std::cerr << "Warning: Dynamixel driver mapping servo " << it->first << " to invalid free spin output index " << it->second->freeSpinOutput << std::endl;
00835 idx = it->second->output;
00836 rm = ServoInfo::POSITION;
00837 } else if(curBuf[it->second->freeSpinOutput]==0) {
00838 idx = it->second->output;
00839 rm = ServoInfo::POSITION;
00840 }
00841 }
00842 if(idx>=NumOutputs) {
00843 if(idx!=UNUSED)
00844 std::cerr << "Warning: Dynamixel driver mapping servo " << it->first << " to invalid output index " << idx << std::endl;
00845 continue;
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 {
00865
00866 float speed;
00867 if(rm==ServoInfo::CONTINUOUS) {
00868
00869 speed = curBuf[idx];
00870 } else if(lastOutputs[idx]!=curBuf[idx]) {
00871
00872 speed = (curBuf[idx] - lastOutputs[idx]) / (period/1000);
00873 } else {
00874
00875 speed = .35f;
00876 }
00877 unsigned short oldLastCmd = it->second->lastCmd;
00878 DynamixelProtocol::SyncWritePosSpeedEntry packet = setServo(it, rm, curBuf[idx], speed);
00879
00880 if(isFirstCheck || oldLastCmd!=it->second->lastCmd || rm!=it->second->curRotationMode) {
00881 packets.push_back(packet);
00882 }
00883 }
00884
00885 if(rm!=it->second->curRotationMode) {
00886 modes.push_back(SyncWriteContinuousRotationEntry(servoid,rm==ServoInfo::CONTINUOUS,it->second->getModel()));
00887 modeUpdates.push_back(std::make_pair(it->first,rm));
00888 }
00889
00890 if(havePIDUpdates) {
00891 if(it->second->slope!=pidValues[idx].pids[DYNAMIXEL_SLOPE] || it->second->margin!=pidValues[idx].pids[DYNAMIXEL_MARGIN]) {
00892 if(it->second->slope!=pidValues[idx].pids[DYNAMIXEL_SLOPE]) {
00893 it->second->slope = pidValues[idx].pids[DYNAMIXEL_SLOPE];
00894 unsigned short torque = (it->second->slope>0) ? 0x3FF : 0;
00895
00896
00897
00898 torqueToggles.push_back(SyncWriteTorqueEntry(servoid,torque));
00899 }
00900 it->second->margin = pidValues[idx].pids[DYNAMIXEL_MARGIN];
00901
00902
00903 if ( it->second->margin > 0 && it->second->margin < 1 )
00904 it->second->margin = 1;
00905
00906
00907
00908
00909
00910
00911 compliances.push_back(SyncWriteComplianceEntry(servoid,(unsigned char)it->second->margin,(unsigned char)it->second->slope));
00912 }
00913 if(it->second->punch!=pidValues[idx].pids[DYNAMIXEL_PUNCH]) {
00914 it->second->punch = pidValues[idx].pids[DYNAMIXEL_PUNCH];
00915
00916 punches.push_back(SyncWritePunchEntry(servoid,(unsigned short)it->second->punch));
00917 }
00918 }
00919 }
00920
00921 if(havePIDUpdates) {
00922 dirtyPIDs=0;
00923 pidLock.unlock();
00924 }
00925
00926
00927 if(packets.size()>0 || modes.size()>0 || leds.size()>0 || compliances.size()>0 || punches.size()>0) {
00928
00929 writeSyncEntries(os,modes);
00930
00931 writeSyncEntries(os,packets);
00932
00933 writeSyncEntries(os,leds);
00934
00935 writeSyncEntries(os,torqueToggles);
00936 writeSyncEntries(os,compliances);
00937 writeSyncEntries(os,punches);
00938
00939 os.flush();
00940 if(os) {
00941 for(modeUpdates_t::const_iterator it=modeUpdates.begin(); it!=modeUpdates.end(); ++it) {
00942
00943 servos[it->first].curRotationMode=it->second;
00944 }
00945 } else {
00946 std::cerr << "WARNING: DynamixelDriver couldn't write update, bad output stream" << std::endl;
00947 }
00948 }
00949 memcpy(lastOutputs,curBuf,sizeof(lastOutputs));
00950 isFirstCheck=false;
00951 }
00952
00953 DynamixelProtocol::SyncWritePosSpeedEntry DynamixelDriver::CommThread::setServo(const servo_iterator& servo, ServoInfo::RotationMode rm, float v, float speed) {
00954 const int MAX_CMD = servo->second->maxTic;
00955 const int MIN_CMD = 0;
00956 const int MAX_SPDCMD = 1023;
00957 unsigned int servoIdx = servo->second->servoID;
00958 if(servoIdx>255)
00959 throw std::runtime_error("DynamixelDriver::setServo, bad servo index!");
00960
00961
00962 float outRange = servo->second->maxAngle;
00963
00964 unsigned int servoRange = MAX_CMD - MIN_CMD;
00965
00966 float cmd = (v+servo->second->zeroAngle+outRange/2)/outRange;
00967
00968 float pw = cmd*servoRange;
00969
00970 pw -= servo->second->predictedLoad*driver.loadCompensation;
00971
00972
00973 int bpw = static_cast<int>(pw+0.5);
00974
00975 if(bpw<MIN_CMD)
00976 bpw = MIN_CMD;
00977 else if(bpw>MAX_CMD)
00978 bpw = MAX_CMD;
00979 if(servo->second->invertRotation)
00980 bpw = MAX_CMD - (bpw-MIN_CMD);
00981
00982
00983 int bpwSpeed;
00984 if(rm==ServoInfo::CONTINUOUS) {
00985 if(speed>0)
00986 speed = speed*servo->second->cmdSpeedSlopeP + servo->second->cmdSpeedOffsetP;
00987 else if(speed<0)
00988 speed = speed*servo->second->cmdSpeedSlopeN + servo->second->cmdSpeedOffsetN;
00989 bpwSpeed = static_cast<int>(speed/outRange*servoRange+.5f);
00990 if(bpwSpeed<-MAX_SPDCMD)
00991 bpwSpeed=-MAX_SPDCMD;
00992 if(bpwSpeed>MAX_SPDCMD)
00993 bpwSpeed=MAX_SPDCMD;
00994 if(servo->second->invertRotation)
00995 bpwSpeed=-bpwSpeed;
00996
00997 if(bpwSpeed<0)
00998 bpwSpeed = -bpwSpeed + 1024;
00999 } else {
01000 bpwSpeed = 0;
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 }
01011
01012
01013
01014 const float GAMMA = 0.9f;
01015 float motion = std::abs(servo->second->lastCmd-bpw);
01016 servo->second->recentCmdMotion*=GAMMA;
01017 if(motion>servo->second->recentCmdMotion)
01018 servo->second->recentCmdMotion=motion;
01019
01020 servo->second->lastCmd = bpw;
01021 return SyncWritePosSpeedEntry(servoIdx,bpw,bpwSpeed);
01022 }
01023
01024
01025
01026
01027