Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
dynamixel.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // Library: libdxl
6 //
7 // File: dynamixel.cxx
8 //
9 /*! \file
10  *
11  * \brief Dynamixel SDK interface.
12  *
13  * Based on Robotis Inc. dxl_sdk-1.01
14  *
15  * \author Robotis
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  */
18 /*
19  * This file is a modified version of the file freely provided by Robotis Inc.
20  * No restrictions by Robotis Inc. nor RoadNarrows LLC are made.
21  */
22 ////////////////////////////////////////////////////////////////////////////////
23 
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 #include "rnr/rnrconfig.h"
29 #include "rnr/log.h"
30 
31 #include "Dynamixel/dxl/dxl.h"
32 
33 #include "dxlhal.h"
34 
35 using namespace libdxl;
36 
38 {
40  memset(m_bufStatusPacket, 0, sizeof(m_bufStatusPacket));
41 
43  m_nRxGetLength = 0;
45  m_bBusUsing = false;
46 
47  m_fnEnableTx = NULL;
48  m_fnEnableRx = NULL;
49  m_pTxRxArg = NULL;
50 
51  m_pDxlHal = new dxlhal();
52 }
53 
55 {
56  delete m_pDxlHal;
57 }
58 
59 int dxl::open(const char *deviceName, int baudrate)
60 {
61  if( m_pDxlHal->open(deviceName, baudrate) == 0 )
62  {
63  return 0;
64  }
65 
67  m_bBusUsing = false;
68 
69  return 1;
70 }
71 
72 int dxl::dxl_initialize(int deviceIndex, int baudnum)
73 {
74  float baudrate;
75 
76  baudrate = dxl_baudnum_to_baudrate(baudnum);
77 
78  if( m_pDxlHal->dxl_hal_open(deviceIndex, baudrate) == 0 )
79  {
80  return 0;
81  }
82 
84  m_bBusUsing = false;
85 
86  return 1;
87 }
88 
89 void dxl::close()
90 {
91  m_pDxlHal->close();
92 }
93 
94 int dxl::setBaudRate(int baudrate)
95 {
96  return m_pDxlHal->setBaudRate(baudrate);
97 }
98 
99 int dxl::setHalfDuplexCallbacks(dxl_hdctl_tx_cb_t enable_tx_cb,
100  dxl_hdctl_rx_cb_t enable_rx_cb,
101  void *arg)
102 {
103  m_fnEnableTx = enable_tx_cb;
104  m_fnEnableRx = enable_rx_cb;
105  m_pTxRxArg = arg;
106 
107  return 1;
108 }
109 
111 {
112  return m_pDxlHal->getFd();
113 }
114 
115 void dxl::setTxPacketId(int id)
116 {
117  m_bufInstructionPacket[DXL_ID] = (uint8_t)id;
118 }
119 
120 void dxl::setTxPacketInstruction(int instruction)
121 {
122  m_bufInstructionPacket[DXL_INSTRUCTION] = (uint8_t)instruction;
123 }
124 
125 void dxl::setTxPacketParameter(int index, int value)
126 {
127  m_bufInstructionPacket[DXL_PARAMETER+index] = (uint8_t)value;
128 }
129 
130 void dxl::setTxPacketLength(int length)
131 {
132  m_bufInstructionPacket[DXL_LENGTH] = (uint8_t)length;
133 }
134 
136 {
137  return (unsigned int)m_bufStatusPacket[DXL_ERRBIT];
138 }
139 
140 bool dxl::getRxPacketError(unsigned int errbit)
141 {
142  return m_bufStatusPacket[DXL_ERRBIT] & errbit? true: false;
143 }
144 
146 {
147  return (int)m_bufStatusPacket[DXL_LENGTH];
148 }
149 
151 {
152  return (int)m_bufStatusPacket[DXL_PARAMETER+index];
153 }
154 
155 int dxl::makeWord(int lowbyte, int highbyte)
156 {
157  uint16_t word;
158 
159  word = (uint16_t)highbyte;
160  word = (uint16_t)(word << 8);
161  word = (uint16_t)(word + (uint16_t)lowbyte);
162  return (int)word;
163 }
164 
165 int dxl::getLowByte(int word)
166 {
167  uint16_t temp;
168 
169  temp = (uint16_t)(word & 0xff);
170  return (int)temp;
171 }
172 
173 int dxl::getHighByte(int word)
174 {
175  uint16_t temp;
176 
177  temp = (uint16_t)(word & 0xff00);
178  temp = (uint16_t)(temp >> 8);
179  return (int)temp;
180 }
181 
183 {
184  int txInstLen; ///< length field value in instruction packate
185  int txPktLen; ///< length of packet to transmit
186  int txLen; ///< actual length transmitted
187  int i; ///< working index
188  uint8_t checksum = 0; ///< packet checksum
189 
190  // in use
191  if( m_bBusUsing )
192  {
193  return;
194  }
195 
196  m_bBusUsing = true;
197 
198  txInstLen = (int)m_bufInstructionPacket[DXL_LENGTH];
199 
200  if( txInstLen > (DXL_MAXNUM_TXPARAM+2) )
201  {
203  m_bBusUsing = false;
204  return;
205  }
206 
214  {
216  m_bBusUsing = false;
217  return;
218  }
219 
220  m_bufInstructionPacket[0] = 0xff;
221  m_bufInstructionPacket[1] = 0xff;
222 
223  for( i=0; i<(txInstLen+1); i++ )
224  {
225  checksum += m_bufInstructionPacket[i+2];
226  }
227  m_bufInstructionPacket[txInstLen+3] = (uint8_t)~checksum;
228 
231  {
232  m_pDxlHal->clear();
233  }
234 
235  txPktLen = txInstLen + 4;
236 
237  // enable transmit
238  if( m_fnEnableTx != NULL )
239  {
241  }
242 
243  txLen = (uint8_t)m_pDxlHal->tx((uint8_t*)m_bufInstructionPacket, txPktLen);
244 
245  if( txPktLen != txLen )
246  {
247  LOGERROR("Tx failed.");
249  m_bBusUsing = false;
250  return;
251  }
252 
253  // enable receive
254  if( m_fnEnableRx != NULL )
255  {
256  m_fnEnableRx(m_pTxRxArg, txPktLen);
257  }
258 
260  {
261  m_pDxlHal->setTimeout( m_bufInstructionPacket[DXL_PARAMETER+1] + 6 );
262  }
263  else
264  {
265  m_pDxlHal->setTimeout( 6 );
266  }
267 
269 }
270 
272 {
273  int txPktLen; // transmitted packet length
274  int nRead; // number bytes read
275  int i, j; // working indices
276  uint8_t checksum = 0; // packet checksum
277 
278  // no pending (good) transmission
279  if( !m_bBusUsing )
280  {
281  return;
282  }
283 
284  // no reply on broadcast
286  {
288  m_bBusUsing = false;
289  return;
290  }
291 
292  // fixed packet header size
293  else if( m_nCommStatus == DXL_COMM_TXSUCCESS )
294  {
296  m_nRxGetLength = 0;
297  m_nRxPacketLength = 6;
298  }
299 
300  txPktLen = (int)m_bufInstructionPacket[DXL_LENGTH] + 4;
301 
302  // enable receive if not already done so
303  if( m_fnEnableRx != NULL )
304  {
305  m_fnEnableRx(m_pTxRxArg, txPktLen);
306  }
307 
308  //
309  // Read fixed packet header.
310  //
311  nRead = m_pDxlHal->rx((uint8_t*)&m_bufStatusPacket[m_nRxGetLength],
312  m_nRxPacketLength - m_nRxGetLength);
313 
314  m_nRxGetLength += nRead;
315 
316  // fprintf(stderr, "DBG: read=%d, total=%d\n", nRead, m_nRxGetLength);
317 
318  if( m_nRxGetLength < m_nRxPacketLength )
319  {
320  if( m_pDxlHal->hasTimedOut() )
321  {
322  // nada
323  if( m_nRxGetLength == 0 )
324  {
326  // ping is used to probe the chain for servos - so timeouts are common
328  {
329  // TO MANY ERRORS LOGERROR("Rx Timed out with 0 bytes.");
330  }
331  }
332  else
333  {
335  LOGERROR("Partial packet of %d bytes received.", m_nRxGetLength);
336 #if 0 // debug
337  for(i=0; i<m_nRxGetLength; ++i)
338  {
339  fprintf(stderr, "0x%02x ", m_bufStatusPacket[i]);
340  }
341  fprintf(stderr, "\n");
342 #endif
343  }
344  m_bBusUsing = false;
345  }
346  return;
347  }
348 
349  //
350  // Find packet frame.
351  //
352  for(i=0; i<(m_nRxGetLength-1); ++i)
353  {
354  if( m_bufStatusPacket[i] == 0xff && m_bufStatusPacket[i+1] == 0xff )
355  {
356  break;
357  }
358  else if( i == m_nRxGetLength-2 &&
359  m_bufStatusPacket[m_nRxGetLength-1] == 0xff )
360  {
361  break;
362  }
363  }
364 
365  // frame slipped
366  if( i > 0 )
367  {
368  // copy
369  for( j=0; j<(m_nRxGetLength-i); j++ )
370  {
372  }
373 
374  m_nRxGetLength -= i;
375  }
376 
377  if( m_nRxGetLength < m_nRxPacketLength )
378  {
380  return;
381  }
382 
383  // Check id pairing
385  {
387  m_bBusUsing = false;
388  LOGERROR("Tx/Rx ids mismatch.");
389  return;
390  }
391 
392  // expected packet length
394 
395  //
396  // Read remaining variable length packet component.
397  //
398  if( m_nRxGetLength < m_nRxPacketLength )
399  {
400  nRead = m_pDxlHal->rx((uint8_t*)&m_bufStatusPacket[m_nRxGetLength],
401  m_nRxPacketLength - m_nRxGetLength );
402  m_nRxGetLength += nRead;
403  if( m_nRxGetLength < m_nRxPacketLength )
404  {
406  return;
407  }
408  }
409 
410  //
411  // Validate checksum.
412  //
413  for( i=0; i<(m_bufStatusPacket[DXL_LENGTH]+1); i++ )
414  {
415  checksum += m_bufStatusPacket[i+2];
416  }
417  checksum = (uint8_t)~checksum;
418 
419  if( m_bufStatusPacket[m_bufStatusPacket[DXL_LENGTH]+3] != checksum )
420  {
422  m_bBusUsing = false;
423  LOGERROR("Checksum mismatch.");
424  return;
425  }
426 
428  m_bBusUsing = false;
429 }
430 
432 {
433  txPacket();
434 
436  {
437  return;
438  }
439 
440  do
441  {
442  rxPacket();
443  } while( m_nCommStatus == DXL_COMM_RXWAITING );
444 }
445 
447 {
448  return m_nCommStatus;
449 }
450 
451 void dxl::ping(int id)
452 {
453  while( m_bBusUsing );
454 
455  m_bufInstructionPacket[DXL_ID] = (uint8_t)id;
458 
459  txrxPacket();
460 }
461 
462 int dxl::readByte(int id, int address)
463 {
464  while( m_bBusUsing );
465 
466  m_bufInstructionPacket[DXL_ID] = (uint8_t)id;
468  m_bufInstructionPacket[DXL_PARAMETER] = (uint8_t)address;
471 
472  txrxPacket();
473 
474  return (int)m_bufStatusPacket[DXL_PARAMETER];
475 }
476 
477 void dxl::writeByte( int id, int address, int value )
478 {
479  while( m_bBusUsing );
480 
481  m_bufInstructionPacket[DXL_ID] = (uint8_t)id;
483  m_bufInstructionPacket[DXL_PARAMETER] = (uint8_t)address;
484  m_bufInstructionPacket[DXL_PARAMETER+1] = (uint8_t)value;
486 
487  txrxPacket();
488 }
489 
490 int dxl::readWord( int id, int address )
491 {
492  while( m_bBusUsing );
493 
494  m_bufInstructionPacket[DXL_ID] = (uint8_t)id;
496  m_bufInstructionPacket[DXL_PARAMETER] = (uint8_t)address;
499 
500  txrxPacket();
501 
502  return makeWord((int)m_bufStatusPacket[DXL_PARAMETER], (int)m_bufStatusPacket[DXL_PARAMETER+1]);
503 }
504 
505 void dxl::writeWord( int id, int address, int value )
506 {
507  while( m_bBusUsing );
508 
509  m_bufInstructionPacket[DXL_ID] = (uint8_t)id;
511  m_bufInstructionPacket[DXL_PARAMETER] = (uint8_t)address;
512  m_bufInstructionPacket[DXL_PARAMETER+1] = (uint8_t)getLowByte(value);
513  m_bufInstructionPacket[DXL_PARAMETER+2] = (uint8_t)getHighByte(value);
515 
516  txrxPacket();
517 }
518 
520 {
521  switch( baudnum )
522  {
524  return 2250000.0f;
526  return 2500000.0f;
528  return 3000000.0f;
529  default:
530  return 2000000.0f / (float)(baudnum + 1);
531  }
532 }
Modified dynamixel SDK interface.
void writeWord(int id, int address, int value)
Write word to servo&#39;s control table.
Definition: dynamixel.cxx:505
int getHighByte(int word)
Get high byte from word.
Definition: dynamixel.cxx:173
void * m_pTxRxArg
tx/rx argument passback
Definition: dxl.h:413
#define DXL_MAXNUM_TXPARAM
maximum number of tx parameters
Definition: dxl.h:73
#define DXL_INST_SYNC_WRITE
synchronous write servo(s) data
Definition: dxl.h:85
#define DXL_COMM_TXFAIL
transmit failure error
Definition: dxl.h:110
Dynamixel Hardware Abstraction Layer implementation interface.
int getLowByte(int word)
Get low byte from word.
Definition: dynamixel.cxx:165
#define DXL_BAUDNUM_EXT_2250000
2,250,000 bps at 0.0% tolerance
Definition: dxl.h:54
void setTxPacketParameter(int index, int value)
Set transmit packet parameter value.
Definition: dynamixel.cxx:125
dxl_hdctl_rx_cb_t m_fnEnableRx
enable rx callback
Definition: dxl.h:412
float dxl_baudnum_to_baudrate(int baudnum)
Convert Dynamixel baud number to baud rate.
Definition: dynamixel.cxx:519
int rx(unsigned char *pPacket, int numPacket)
Receive Dynamixel status packet.
Definition: dxlhal.cxx:229
#define DXL_INST_RESET
reset servo defaults
Definition: dxl.h:84
#define DXL_BAUDNUM_EXT_3000000
3,000,000 bps at 0.0% tolerance
Definition: dxl.h:56
int getResult()
Get last transmit/receive result.
Definition: dynamixel.cxx:446
int m_nRxPacketLength
expected received packet length
Definition: dxl.h:405
void close()
Close Dynamixel Bus serial interface.
Definition: dxlhal.cxx:146
#define DXL_COMM_RXSUCCESS
receive success
Definition: dxl.h:109
void txrxPacket()
Transmit instruction packet and receive status response packet.
Definition: dynamixel.cxx:431
#define DXL_INST_ACTION
action
Definition: dxl.h:83
int getRxPacketParameter(int index)
Get receive packet parameter value.
Definition: dynamixel.cxx:150
void setTxPacketId(int id)
Set transmit packet servo id.
Definition: dynamixel.cxx:115
#define DXL_ERRBIT
error bits field packet index
Definition: dxl.h:67
#define DXL_COMM_TXERROR
packed transmit packet format error
Definition: dxl.h:112
void writeByte(int id, int address, int value)
Write byte to servo&#39;s control table.
Definition: dynamixel.cxx:477
#define DXL_COMM_RXWAITING
waiting for complete receive packet
Definition: dxl.h:113
int setHalfDuplexCallbacks(dxl_hdctl_tx_cb_t enable_tx_cb, dxl_hdctl_rx_cb_t enable_rx_cb, void *arg)
Set serial half-duplex callbacks.
Definition: dynamixel.cxx:99
Definition: dxl.h:32
dxl()
Default constructor.
Definition: dynamixel.cxx:37
#define DXL_PARAMETER
start of parameter fields packet index
Definition: dxl.h:68
#define DXL_COMM_RXTIMEOUT
receive timeout error
Definition: dxl.h:114
~dxl()
Destructor.
Definition: dynamixel.cxx:54
void setTxPacketInstruction(int instruction)
Set transmit packet instruction.
Definition: dynamixel.cxx:120
int dxl_hal_open(int deviceIndex, float baudrate)
Open Dynamixel Bus USB serial device by index.
Definition: dxlhal.cxx:86
void rxPacket()
Receive status packet.
Definition: dynamixel.cxx:271
int makeWord(int lowbyte, int highbyte)
Make 16-bit word.
Definition: dynamixel.cxx:155
#define DXL_INSTRUCTION
instruction field packet index
Definition: dxl.h:66
dxl_hdctl_tx_cb_t m_fnEnableTx
enable tx callback
Definition: dxl.h:411
void txPacket()
Transmit a previously packed instruction packet.
Definition: dynamixel.cxx:182
#define DXL_INST_REG_WRITE
register write
Definition: dxl.h:82
int open(const char *deviceName, int baudrate)
Open Dynamixel Bus serial interface.
Definition: dynamixel.cxx:59
unsigned int getRxPacketErrBits()
Get receive packet error bits field.
Definition: dynamixel.cxx:135
#define DXL_INST_READ
read servo control table data
Definition: dxl.h:80
uint8_t m_bufInstructionPacket[(150)+10]
instruction transmit packet buffer
Definition: dxl.h:399
int getRxPacketLength()
Get receive packet length field.
Definition: dynamixel.cxx:145
#define DXL_COMM_RXCORRUPT
receive corrupted packet
Definition: dxl.h:115
#define DXL_COMM_TXSUCCESS
transmit success
Definition: dxl.h:108
uint8_t m_bufStatusPacket[(60)+10]
status receive packet buffer
Definition: dxl.h:401
#define DXL_INST_PING
ping servo
Definition: dxl.h:79
void setTimeout(int NumRcvByte)
Set receive timeout.
Definition: dxlhal.cxx:248
bool hasTimedOut()
Test if receive timeout has expired.
Definition: dxlhal.cxx:260
int open(const char *deviceName, int baudrate)
Open Dynamixel Bus USB serial device by name.
Definition: dxlhal.cxx:60
bool m_bBusUsing
bus is [not] busy
Definition: dxl.h:408
int setBaudRate(int baudrate)
Set Dynamixel Bus serial device baud rate.
Definition: dynamixel.cxx:94
#define DXL_ID
servo id field packet index
Definition: dxl.h:64
int setBaudRate(int baudrate)
Set opened Dynamixel Bus serial interface baud rate.
Definition: dxlhal.cxx:173
void close()
Close the Dynamixel Bus serial interface.
Definition: dynamixel.cxx:89
int getFd()
Get the Dynamixel Bus serial device file descriptor.
Definition: dynamixel.cxx:110
void clear()
Discard any pending recieve data.
Definition: dxlhal.cxx:207
int m_nCommStatus
communication status
Definition: dxl.h:407
void ping(int id)
Ping servo.
Definition: dynamixel.cxx:451
bool getRxPacketError(unsigned int errbit)
Test if error bit is set on received packet.
Definition: dynamixel.cxx:140
#define DXL_INST_WRITE
write servo control table data
Definition: dxl.h:81
int tx(unsigned char *pPacket, int numPacket)
Transmit Dynamixel instruction packet.
Definition: dxlhal.cxx:212
int dxl_initialize(int deviceIndex, int baudnum)
Initialize Dynamixel Bus USB serial interface by index.
Definition: dynamixel.cxx:72
void setTxPacketLength(int length)
Set transmit packet length.
Definition: dynamixel.cxx:130
int readByte(int id, int address)
Read byte from servo&#39;s control table.
Definition: dynamixel.cxx:462
#define DXL_BAUDNUM_EXT_2500000
2,500,000 bps at 0.0% tolerance
Definition: dxl.h:55
int getFd()
Get the Dynamixel Bus serial device file descriptor.
Definition: dxlhal.cxx:168
#define DXL_BROADCAST_ID
broadcast "servo" id
Definition: dxl.h:92
int readWord(int id, int address)
Read word from servo&#39;s control table.
Definition: dynamixel.cxx:490
#define DXL_LENGTH
packet length field packet index
Definition: dxl.h:65
int m_nRxGetLength
current received packet length
Definition: dxl.h:406