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