00001
00002 #ifndef INCLUDED_DynamixelProtocol_h_
00003 #define INCLUDED_DynamixelProtocol_h_
00004
00005 #include "IPC/Thread.h"
00006 #include "Shared/debuget.h"
00007 #include <cstddef>
00008 #include <iostream>
00009 #include <map>
00010 #include <string.h>
00011
00012 #define IS_MXEX(m) (m==MODEL_MX28 || m==MODEL_MX64 || m==MODEL_MX106 || m==MODEL_EX106P)
00013
00014
00015 namespace DynamixelProtocol {
00016
00017 const unsigned int MAX_ID=0xFD;
00018 const unsigned int BROADCAST_ID=0xFE;
00019 const unsigned int INVALID_ID=0xFF;
00020 const unsigned int MARKER_VALUE=0xFF;
00021
00022 extern const char* MODEL_UNKNOWN_NAME;
00023 enum ModelID_t {
00024 MODEL_DX113=113,
00025 MODEL_DX116=116,
00026 MODEL_DX117=117,
00027 MODEL_AX12=12,
00028 MODEL_AX18=18,
00029 MODEL_AXS1=13,
00030 MODEL_RX10=10,
00031 MODEL_RX24=24,
00032 MODEL_RX28=28,
00033 MODEL_RX64=64,
00034 MODEL_MX28=29,
00035 MODEL_MX64=310,
00036 MODEL_MX106=320,
00037 MODEL_EX106P=107,
00038 MODEL_UNKNOWN=static_cast<size_t>(1<<16)
00039 };
00040
00041 extern const std::map<DynamixelProtocol::ModelID_t, const std::string> dynamixelModels;
00042
00043
00044 enum StatusResponseLevel {
00045 RESPOND_NONE=0,
00046 RESPOND_READ=1,
00047 RESPOND_ALL=2
00048 };
00049
00050
00051
00052
00053 inline unsigned char nchecksum(const unsigned char* p, size_t len, size_t off=0) {
00054 const unsigned char* end=p+len;
00055 p+=off;
00056 unsigned char c=0;
00057 while(p!=end) {
00058
00059 c+=*p++;
00060 }
00061 return c;
00062 }
00063
00064 inline unsigned char nchecksum(const struct GenericCmdHeader& p, size_t len);
00065
00066
00067 inline unsigned char nchecksum(const struct GenericResponseHeader& p, size_t len);
00068
00069
00070 template<class T> void updateChecksum(T& cmd) { cmd.checksum=~nchecksum(cmd,sizeof(cmd)-1); }
00071
00072
00073 template<class T> bool validate(const T& msg) {
00074 const unsigned char MARKER=(unsigned char)-1U;
00075 if(msg.markerA!=MARKER || msg.markerB!=MARKER) return false;
00076 if(msg.resplen!=sizeof(msg)-4) return false;
00077 decltype(msg.checksum) chk = ~nchecksum(msg,sizeof(msg)-1);
00078 return chk == msg.checksum;
00079 }
00080
00081 struct GenericCmdHeader {
00082 GenericCmdHeader(unsigned char bytelen, unsigned char instruction)
00083 : markerA(MARKER_VALUE), markerB(MARKER_VALUE), servoid(BROADCAST_ID), cmdlen(bytelen), cmdid(instruction) {}
00084 operator const char*() const { return reinterpret_cast<const char*>(&markerA); }
00085 operator const unsigned char*() const { return &markerA; }
00086 unsigned char markerA;
00087 unsigned char markerB;
00088 unsigned char servoid;
00089 unsigned char cmdlen;
00090 unsigned char cmdid;
00091 };
00092 inline unsigned char nchecksum(const struct GenericCmdHeader& p, size_t len) { return nchecksum(p,len,2); }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 template<class T>
00105 struct SyncWriteHeader : public GenericCmdHeader {
00106 SyncWriteHeader(unsigned char len)
00107 : GenericCmdHeader(sizeof(T)*len+4,0x83), addr(T::ADDRESS), writelen(sizeof(T)-1) {}
00108 unsigned char addr;
00109 unsigned char writelen;
00110 };
00111
00112 struct SyncWriteEntry {
00113 SyncWriteEntry() : servoid() {}
00114 SyncWriteEntry(unsigned char sid) : servoid(sid) {}
00115 operator const char*() const { return reinterpret_cast<const char*>(&servoid); }
00116 operator const unsigned char*() const { return &servoid; }
00117 unsigned char servoid;
00118 };
00119
00120
00121 struct SyncWritePosSpeedEntry : public SyncWriteEntry {
00122 SyncWritePosSpeedEntry() : SyncWriteEntry(), posl(), posh(), speedl(), speedh() {}
00123 SyncWritePosSpeedEntry(unsigned char sid, unsigned short pos, unsigned short speed)
00124 : SyncWriteEntry(sid), posl(pos), posh(pos>>8), speedl(speed), speedh(speed>>8) {}
00125 static const unsigned char ADDRESS=0x1E;
00126 unsigned char posl;
00127 unsigned char posh;
00128 unsigned char speedl;
00129 unsigned char speedh;
00130 };
00131
00132
00133 struct SyncWriteContinuousRotationEntry : public SyncWriteEntry {
00134 SyncWriteContinuousRotationEntry() : SyncWriteEntry(), ccwlimitl(), ccwlimith() {}
00135 SyncWriteContinuousRotationEntry(unsigned char sid, bool enable, ModelID_t model) :
00136 SyncWriteEntry(sid), ccwlimitl(enable?0:0xFF),
00137 ccwlimith(IS_MXEX(model) ? (enable?0:0x0F) : (enable?0:0x03) ) {}
00138 static const unsigned char ADDRESS=0x8;
00139 unsigned char ccwlimitl;
00140 unsigned char ccwlimith;
00141 };
00142
00143
00144 struct SyncWriteLEDEntry : public SyncWriteEntry {
00145 SyncWriteLEDEntry() : SyncWriteEntry(), led() {}
00146 SyncWriteLEDEntry(unsigned char sid, bool enable) : SyncWriteEntry(sid), led(enable?1:0) {}
00147 static const unsigned char ADDRESS=0x19;
00148 unsigned char led;
00149 };
00150
00151 struct SyncWriteComplianceEntry : public SyncWriteEntry {
00152 SyncWriteComplianceEntry() : SyncWriteEntry(), cwmargin(), ccwmargin(), cwslope(), ccwslope() {}
00153 SyncWriteComplianceEntry(unsigned char sid, unsigned char margin, unsigned char slope) : SyncWriteEntry(sid), cwmargin(margin), ccwmargin(margin), cwslope(slope), ccwslope(slope) {}
00154 static const unsigned char ADDRESS=0x1A;
00155 unsigned char cwmargin;
00156 unsigned char ccwmargin;
00157 unsigned char cwslope;
00158 unsigned char ccwslope;
00159 };
00160
00161 struct SyncWritePunchEntry : public SyncWriteEntry {
00162 SyncWritePunchEntry() : SyncWriteEntry(), punchl(), punchh() {}
00163 SyncWritePunchEntry(unsigned char sid, unsigned short punch) : SyncWriteEntry(sid), punchl(punch&0xFF), punchh(punch>>8) {}
00164 static const unsigned char ADDRESS=0x30;
00165 unsigned char punchl;
00166 unsigned char punchh;
00167 };
00168
00169
00170 struct SyncWritePIDEntry : public SyncWriteEntry {
00171 SyncWritePIDEntry() : SyncWriteEntry(), dvalue(), ivalue(), pvalue() {}
00172 SyncWritePIDEntry(unsigned char sid, unsigned char p, unsigned char i, unsigned char d) :
00173 SyncWriteEntry(sid), dvalue(d), ivalue(i), pvalue(p) {}
00174 static const unsigned char ADDRESS=0x1A;
00175 unsigned char dvalue;
00176 unsigned char ivalue;
00177 unsigned char pvalue;
00178 };
00179
00180 struct SyncWriteTorqueEntry : public SyncWriteEntry {
00181 SyncWriteTorqueEntry() : SyncWriteEntry(), maxTorqueL(), maxTorqueH() {}
00182 SyncWriteTorqueEntry(unsigned char sid, unsigned short max) : SyncWriteEntry(sid), maxTorqueL(max), maxTorqueH(max>>8) {}
00183 static const unsigned char ADDRESS=0x22;
00184 unsigned char maxTorqueL;
00185 unsigned char maxTorqueH;
00186 };
00187
00188
00189 struct SyncWriteSoundHoldEntry : public SyncWriteEntry {
00190 SyncWriteSoundHoldEntry() : SyncWriteEntry(), sndMaxHold(0) {}
00191 SyncWriteSoundHoldEntry(unsigned char sid) : SyncWriteEntry(sid), sndMaxHold(0) {}
00192 static const unsigned char ADDRESS=0x24;
00193 unsigned char sndMaxHold;
00194 };
00195
00196
00197
00198
00199
00200
00201 struct SyncWriteSoundCountEntry : public SyncWriteEntry {
00202 SyncWriteSoundCountEntry() : SyncWriteEntry(), sndCount(0) {}
00203 SyncWriteSoundCountEntry(unsigned char sid) : SyncWriteEntry(sid), sndCount(0) {}
00204 static const unsigned char ADDRESS=0x25;
00205 unsigned char sndCount;
00206 };
00207
00208
00209 struct SyncWriteSoundHoldAndCountEntry : public SyncWriteEntry {
00210 SyncWriteSoundHoldAndCountEntry() : SyncWriteEntry(), sndMaxHold(0), sndCount(0) {}
00211 SyncWriteSoundHoldAndCountEntry(unsigned char sid) : SyncWriteEntry(sid), sndMaxHold(0), sndCount(0) {}
00212 static const unsigned char ADDRESS=0x24;
00213 unsigned char sndMaxHold;
00214 unsigned char sndCount;
00215 };
00216
00217 struct WriteHeader : public GenericCmdHeader {
00218 WriteHeader(unsigned char address, unsigned char len)
00219 : GenericCmdHeader(len+3,0x3), addr(address) {}
00220 unsigned char addr;
00221 };
00222
00223
00224 struct BroadcastTorqueCmd : public WriteHeader {
00225
00226 BroadcastTorqueCmd(bool enable)
00227 : WriteHeader(0x18,1), torqueEnable(enable?1:0), checksum() { updateChecksum(*this); }
00228
00229 unsigned char torqueEnable;
00230 char checksum;
00231 };
00232
00233
00234 struct BroadcastTorqueEntry : public WriteHeader {
00235
00236 BroadcastTorqueEntry(unsigned char mtorqL=0xff, unsigned char mtorqH=0x03)
00237 : WriteHeader(0x22,2), maxTorqueL(mtorqL), maxTorqueH(mtorqH), checksum() { updateChecksum(*this); }
00238 unsigned char maxTorqueL;
00239 unsigned char maxTorqueH;
00240 char checksum;
00241 };
00242
00243
00244 struct BroadcastFullComplianceCmd : public WriteHeader {
00245 BroadcastFullComplianceCmd()
00246 : WriteHeader(0x1A,4), cwmargin(0), ccwmargin(0), cwslope(0), ccwslope(0), checksum() { updateChecksum(*this); }
00247 unsigned char cwmargin;
00248 unsigned char ccwmargin;
00249 unsigned char cwslope;
00250 unsigned char ccwslope;
00251 char checksum;
00252 };
00253
00254
00255 struct BroadcastNoPunchCmd : public WriteHeader {
00256 BroadcastNoPunchCmd()
00257 : WriteHeader(0x30,2), punchl(0), punchh(0), checksum() { updateChecksum(*this); }
00258 unsigned char punchl;
00259 unsigned char punchh;
00260 char checksum;
00261 };
00262
00263
00264 struct BroadcastZeroSpeedCmd : public WriteHeader {
00265 BroadcastZeroSpeedCmd()
00266 : WriteHeader(0x20,2), speedl(0), speedh(0), checksum() { updateChecksum(*this); }
00267 unsigned char speedl;
00268 unsigned char speedh;
00269 char checksum;
00270 };
00271
00272
00273 struct BroadcastBaudCmd : public WriteHeader {
00274 BroadcastBaudCmd(unsigned char divisor) : WriteHeader(0x04,1), baudDivisor(divisor), checksum() { updateChecksum(*this); }
00275 unsigned char baudDivisor;
00276 char checksum;
00277 };
00278
00279
00280 struct SetReturnDelayTimeCmd : public WriteHeader {
00281 SetReturnDelayTimeCmd() : WriteHeader(0x05,1), delayTime(0), checksum() { updateChecksum(*this); }
00282 SetReturnDelayTimeCmd(unsigned char delay) : WriteHeader(0x05,1), delayTime(delay), checksum() { updateChecksum(*this); }
00283 SetReturnDelayTimeCmd(unsigned char sid, unsigned char delay) : WriteHeader(0x05,1), delayTime(delay), checksum() { servoid=sid; updateChecksum(*this); }
00284 unsigned char delayTime;
00285 char checksum;
00286 };
00287
00288
00289 struct SetStatusResponseLevelCmd : public WriteHeader {
00290 SetStatusResponseLevelCmd() : WriteHeader(0x10,1), responseLevel(0), checksum() { updateChecksum(*this); }
00291 SetStatusResponseLevelCmd(StatusResponseLevel level) : WriteHeader(0x05,1), responseLevel(level), checksum() { updateChecksum(*this); }
00292 SetStatusResponseLevelCmd(unsigned char sid, StatusResponseLevel level) : WriteHeader(0x05,1), responseLevel(level), checksum() { servoid=sid; updateChecksum(*this); }
00293 unsigned char responseLevel;
00294 char checksum;
00295 };
00296
00297
00298 struct SetServoIDCmd : public WriteHeader {
00299 SetServoIDCmd(unsigned char tgtsid, unsigned char newsid)
00300 : WriteHeader(0x03, 1), newservoid(newsid), checksum() { servoid=tgtsid; updateChecksum(*this); }
00301 unsigned char newservoid;
00302 char checksum;
00303 };
00304
00305
00306 struct SetPosSpeedCmd : public WriteHeader {
00307 SetPosSpeedCmd() : WriteHeader(0x1E,4), posl(), posh(), speedl(), speedh(), checksum() { updateChecksum(*this); }
00308 SetPosSpeedCmd(unsigned char sid, unsigned short pos, unsigned short speed)
00309 : WriteHeader(0x1E,4), posl(pos), posh(pos>>8), speedl(speed), speedh(speed>>8), checksum() { servoid=sid; updateChecksum(*this); }
00310 unsigned char posl;
00311 unsigned char posh;
00312 unsigned char speedl;
00313 unsigned char speedh;
00314 char checksum;
00315 };
00316
00317
00318 struct ClearSoundHoldCmd : public WriteHeader {
00319 ClearSoundHoldCmd() : WriteHeader(0x24,1), sndMaxHold(0), checksum() { updateChecksum(*this); }
00320 ClearSoundHoldCmd(unsigned char sid) : WriteHeader(0x24,1), sndMaxHold(0), checksum() { servoid=sid; updateChecksum(*this); }
00321 unsigned char sndMaxHold;
00322 char checksum;
00323 };
00324
00325
00326
00327
00328
00329
00330 struct ClearSoundCountCmd : public WriteHeader {
00331 ClearSoundCountCmd() : WriteHeader(0x25,1), sndCount(0), checksum() { updateChecksum(*this); }
00332 ClearSoundCountCmd(unsigned char sid) : WriteHeader(0x25,1), sndCount(0), checksum() { servoid=sid; updateChecksum(*this); }
00333 unsigned char sndCount;
00334 char checksum;
00335 };
00336
00337
00338 struct ClearSoundHoldAndCountCmd : public WriteHeader {
00339 ClearSoundHoldAndCountCmd() : WriteHeader(0x24,2), sndMaxHold(0), sndCount(0), checksum() { updateChecksum(*this); }
00340 ClearSoundHoldAndCountCmd(unsigned char sid) : WriteHeader(0x24,2), sndMaxHold(0), sndCount(0), checksum() { servoid=sid; updateChecksum(*this); }
00341 unsigned char sndMaxHold;
00342 unsigned char sndCount;
00343 char checksum;
00344 };
00345
00346
00347 enum ResponseError_t {
00348 VOLTAGE_ERROR=1, ANGLE_ERROR=2, HEAT_ERROR=4,
00349 RANGE_ERROR=8, CHECKSUM_ERROR=16, LOAD_ERROR=32,
00350 INSTRUCTION_ERROR=64
00351 };
00352 extern const char* ResponseErrorNames[9];
00353
00354
00355 struct GenericResponseHeader {
00356 GenericResponseHeader() : markerA(0), markerB(0), servoid(0), resplen(0), error(0) {}
00357 operator char*() { return reinterpret_cast<char*>(&markerA); }
00358 operator const char*() const { return reinterpret_cast<const char*>(&markerA); }
00359 operator const unsigned char*() const { return &markerA; }
00360 unsigned char markerA;
00361 unsigned char markerB;
00362 unsigned char servoid;
00363 unsigned char resplen;
00364 unsigned char error;
00365 };
00366 inline unsigned char nchecksum(const struct GenericResponseHeader& p, size_t len) { return nchecksum(p,len,2); }
00367
00368 const unsigned char RESPONSE_HEADER_LEN = sizeof(GenericResponseHeader)+1;
00369
00370
00371 struct WriteResponse : public GenericResponseHeader {
00372 unsigned char checksum;
00373 WriteResponse() : checksum(0) {}
00374 };
00375
00376 struct ServoSensorsResponse : public GenericResponseHeader {
00377
00378 ServoSensorsResponse() : GenericResponseHeader(), posl(), posh(), speedl(), speedh(),
00379 loadl(), loadh(), voltage(), temp(), checksum() {}
00380
00381
00382 unsigned short getPosition() const { return (static_cast<unsigned short>(posh)<<8) + posl; }
00383
00384 short getSpeed() const { short x = (static_cast<short>(speedh&0x3)<<8) | speedl; return (speedh&4) ? -x : x; }
00385
00386 short getLoad() const { short x = (static_cast<short>(loadh&0x3)<<8) | loadl; return (loadh&4) ? x : -x; }
00387
00388 unsigned char posl;
00389 unsigned char posh;
00390 unsigned char speedl;
00391 unsigned char speedh;
00392 unsigned char loadl;
00393 unsigned char loadh;
00394 unsigned char voltage;
00395 unsigned char temp;
00396 unsigned char checksum;
00397 };
00398
00399
00400 struct AXS1SensorsResponse : public GenericResponseHeader {
00401
00402 AXS1SensorsResponse() : GenericResponseHeader(),
00403 leftIR(), centerIR(), rightIR(), leftLum(), centerLum(), rightLum(),
00404 obsFlag(), lumFlag(), _robotisReserved(), sndData(), sndMaxHold(), sndCount(),
00405
00406 checksum()
00407 {}
00408
00409
00410
00411 unsigned short getDetectedTime() {
00412 return (static_cast<unsigned short>(sndTimeHigh)<<8) + sndTimeLow;
00413 }about:startpage
00414 */
00415
00416 unsigned char leftIR;
00417 unsigned char centerIR;
00418 unsigned char rightIR;
00419 unsigned char leftLum;
00420 unsigned char centerLum;
00421 unsigned char rightLum;
00422 unsigned char obsFlag;
00423 unsigned char lumFlag;
00424 unsigned char _robotisReserved;
00425 unsigned char sndData;
00426 unsigned char sndMaxHold;
00427 unsigned char sndCount;
00428
00429
00430
00431
00432
00433
00434
00435
00436 unsigned char checksum;
00437 };
00438
00439
00440 struct TorqueResponse : public GenericResponseHeader {
00441 unsigned char torqueEnable;
00442 unsigned char checksum;
00443 };
00444
00445
00446 struct ServoInfoResponse : public GenericResponseHeader {
00447 ServoInfoResponse() : GenericResponseHeader(), modell(0), modelh(0), version(0), checksum() {}
00448 unsigned short getModelNumber() const { return (static_cast<unsigned short>(modelh)<<8) | modell; }
00449 const char* getModelString() const {
00450 typedef decltype(dynamixelModels) modelmap_t;
00451 modelmap_t::const_iterator it = dynamixelModels.find((ModelID_t)getModelNumber());
00452 if(it==dynamixelModels.end()) {
00453 return (getModelNumber()==0 && version==0) ? "INVALID RESPONSE" : MODEL_UNKNOWN_NAME;
00454 } else {
00455 return it->second.c_str();
00456 }
00457 }
00458 unsigned char modell;
00459 unsigned char modelh;
00460 unsigned char version;
00461 unsigned char checksum;
00462 };
00463
00464
00465 struct ReadCmd : public GenericCmdHeader {
00466
00467 ReadCmd(unsigned char servoID, unsigned char address, unsigned char len)
00468 : GenericCmdHeader(4,0x2), addr(address), readlen(len), checksum() { servoid=servoID; updateChecksum(*this); }
00469 unsigned char addr;
00470 unsigned char readlen;
00471 unsigned char checksum;
00472 };
00473
00474 struct ReadServoSensorsCmd : public ReadCmd {
00475
00476 ReadServoSensorsCmd(unsigned char servoID) : ReadCmd(servoID,0x24,sizeof(ServoSensorsResponse)-RESPONSE_HEADER_LEN) {}
00477 };
00478
00479 struct ReadAXS1SensorsCmd : public ReadCmd {
00480
00481 ReadAXS1SensorsCmd(unsigned char servoID) : ReadCmd(servoID,0x1A,sizeof(AXS1SensorsResponse)-RESPONSE_HEADER_LEN) {}
00482 };
00483
00484 struct ReadTorqueCmd : public ReadCmd {
00485
00486 ReadTorqueCmd(unsigned char servoID) : ReadCmd(servoID,0x18,sizeof(TorqueResponse)-RESPONSE_HEADER_LEN) {}
00487 };
00488
00489 struct ReadModelCmd : public ReadCmd {
00490
00491 ReadModelCmd(unsigned char servoID) : ReadCmd(servoID,0x00,sizeof(ServoInfoResponse)-RESPONSE_HEADER_LEN) {}
00492 };
00493
00494 void reportErrors(unsigned int servoID, unsigned int offset, unsigned char err);
00495
00496
00497
00498 template<class R> bool readResponse(std::istream& is, R& response, unsigned int offset) {
00499
00500 is.read((char*)&response.markerA,sizeof(response.markerA)*2);
00501 if(!is || is.gcount()!=sizeof(response.markerA)*2) {
00502 Thread::testCurrentCancel();
00503 std::cerr << "Dynamixel protocol bad read! 1" << std::endl;
00504 is.sync();
00505 is.clear();
00506 return false;
00507 }
00508 size_t noiseCnt=0;
00509
00510 while(response.markerA!=DynamixelProtocol::MARKER_VALUE || response.markerB!=DynamixelProtocol::MARKER_VALUE) {
00511
00512 ++noiseCnt;
00513 response.markerA=response.markerB;
00514 try {
00515 is.read((char*)&response.markerB,sizeof(response.markerB));
00516 if(!is || is.gcount()!=sizeof(response.markerB)) {
00517 Thread::testCurrentCancel();
00518 std::cerr << "Dynamixel protocol bad read! 2" << std::endl;
00519 is.sync();
00520 is.clear();
00521 }
00522 } catch(...) {
00523 std::cerr << "Dynamixel protocol couldn't find packet start, skipped " << noiseCnt << " bytes of line noise." << std::endl;
00524 throw;
00525 }
00526 }
00527 if(noiseCnt!=0)
00528 std::cerr << "Dynamixel protocol skipping " << noiseCnt << " bytes of line noise" << std::endl;
00529 const size_t HEADER_SIZE = sizeof(response.servoid)+sizeof(response.resplen)+sizeof(response.error);
00530
00531 is.read((char*)&response.servoid,HEADER_SIZE);
00532 if(!is || (size_t)is.gcount()!=HEADER_SIZE) {
00533 Thread::testCurrentCancel();
00534 std::cerr << "Dynamixel protocol bad read! 3" << std::endl;
00535 is.sync();
00536 is.clear();
00537 return false;
00538 }
00539 if(response.resplen<2) {
00540 std::cerr << "Dynamixel protocol got bad packet, too short! (" << (int)response.resplen << ")" << std::endl;
00541 return false;
00542 }
00543
00544 if(response.resplen != sizeof(R)-sizeof(GenericResponseHeader)+1) {
00545 unsigned char tmpbuf[256];
00546 memcpy(tmpbuf,&response.servoid,HEADER_SIZE);
00547 is.read((char*)tmpbuf+HEADER_SIZE,response.resplen-sizeof(response.error));
00548 if(!is || (size_t)is.gcount()!=response.resplen-sizeof(response.error)) {
00549 Thread::testCurrentCancel();
00550 std::cerr << "Dynamixel protocol bad read! 4" << std::endl;
00551 is.sync();
00552 is.clear();
00553 return false;
00554 }
00555 unsigned char rchksum = tmpbuf[HEADER_SIZE+response.resplen-sizeof(response.error)-1];
00556 unsigned char lchksum = ~nchecksum(tmpbuf,HEADER_SIZE+response.resplen-sizeof(response.error)-1,0);
00557 if( lchksum == rchksum) {
00558 if(response.error==0)
00559 std::cerr << "Dynamixel protocol: invalid response (expected " << (sizeof(R)-sizeof(GenericResponseHeader)+1) << ", length=" << (int)response.resplen << ")" << std::endl;
00560 else
00561 reportErrors(response.servoid,offset,response.error);
00562 } else {
00563 std::cerr << "Dynamixel line noise: sensor checksum failed" << std::endl;
00564 is.sync();
00565 }
00566 return false;
00567 }
00568
00569
00570 is.read((char*)(&response.error+1),response.resplen-sizeof(response.error));
00571 if(!is || (size_t)is.gcount()!=response.resplen-sizeof(response.error)) {
00572 Thread::testCurrentCancel();
00573 std::cerr << "Dynamixel protocol bad read! 5" << std::endl;
00574 is.sync();
00575 is.clear();
00576 return false;
00577 } else if(!validate(response)) {
00578
00579
00580
00581
00582
00583 std::cerr << "Dynamixel line noise: sensor checksum failed" << std::endl;
00584 is.sync();
00585 return false;
00586 }
00587
00588 if(response.error!=0)
00589 reportErrors(response.servoid,offset,response.error);
00590 return true;
00591 }
00592
00593
00594
00595 class PingThread : public Thread {
00596 public:
00597
00598 PingThread(std::istream& is, std::ostream& os, unsigned char servoid, unsigned int outputOffset, ServoSensorsResponse* servoinfo=NULL, AXS1SensorsResponse* servoinfoS1=NULL)
00599 : Thread(), response(), icomm(is), ocomm(os), sid(servoid), output(outputOffset), info(servoinfo), infoS1(servoinfoS1), unknownModelName() { start(); }
00600
00601 ~PingThread() { if(isStarted()) stop().join(); }
00602
00603 static long getTimeout() { return timeout; }
00604 static void setTimeout(long t) { timeout = t; }
00605
00606 ServoInfoResponse response;
00607
00608 protected:
00609 virtual void * run();
00610 virtual void cancelled();
00611 static long timeout;
00612 std::istream& icomm;
00613 std::ostream& ocomm;
00614 unsigned char sid;
00615 unsigned int output;
00616 ServoSensorsResponse* info;
00617 AXS1SensorsResponse* infoS1;
00618 std::string unknownModelName;
00619
00620 private:
00621 PingThread(const PingThread&);
00622 PingThread& operator=(const PingThread&);
00623 };
00624
00625
00626
00627
00628
00629 template<class T> std::ostream& write(std::ostream& os, const T& cmd) { return os.write(cmd,sizeof(cmd)); }
00630
00631 template<class T> std::ostream& write(std::ostream& os, const T& cmd, unsigned char& checksum) { checksum+=nchecksum(cmd,sizeof(cmd)); return os.write(cmd,sizeof(cmd)); }
00632 };
00633
00634
00635
00636
00637
00638
00639 #endif