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