Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
DynaComm.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // Library: libDynamixel
6 //
7 // File: DynaComm.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-01-12 10:56:06 -0700 (Mon, 12 Jan 2015) $
12  * $Rev: 3845 $
13  *
14  * \brief RoadNarrows Dynamixel bus communications abstract class base class.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  *
18  * \copyright
19  * \h_copy 2011-2017. RoadNarrows LLC.\n
20  * http://www.roadnarrows.com\n
21  * All Rights Reserved
22  */
23 /*
24  * @EulaBegin@
25  *
26  * Unless otherwise stated explicitly, all materials contained are copyrighted
27  * and may not be used without RoadNarrows LLC's written consent,
28  * except as provided in these terms and conditions or in the copyright
29  * notice (documents and software) or other proprietary notice provided with
30  * the relevant materials.
31  *
32  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY
33  * MEMBERS/EMPLOYEES/CONTRACTORS OF ROADNARROWS OR DISTRIBUTORS OF THIS SOFTWARE
34  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
35  * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
36  * DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN
37  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  * THE AUTHORS AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
40  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
42  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
43  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
44  *
45  * @EulaEnd@
46  */
47 ////////////////////////////////////////////////////////////////////////////////
48 
49 #include <unistd.h>
50 #include <string.h>
51 #include <pthread.h>
52 
53 #include <string>
54 
55 #include "rnr/rnrconfig.h"
56 #include "rnr/uri.h"
57 #include "rnr/shm.h"
58 #include "rnr/log.h"
59 
60 #include "botsense/BotSense.h"
61 
62 #include "Dynamixel/Dynamixel.h"
63 #include "Dynamixel/DynaError.h"
64 
65 #include "Dynamixel/DynaComm.h"
68 
69 #include "DynaLibInternal.h"
70 
71 using namespace std;
72 
73 
74 // ---------------------------------------------------------------------------
75 // Private Interface
76 // ---------------------------------------------------------------------------
77 
78 /*!
79  * \brief Dynamixel Bus Communication Status String Table.
80  */
81 static const char *DynaBusStatusStrTbl[] =
82 {
83  "Transmit packet success", ///< [COMM_TXSUCCESS]
84  "Receive packet success", ///< [COMM_RXSUCCESS]
85  "Transmit packet failure", ///< [COMM_TXFAIL]
86  "Receive packet failure", ///< [COMM_RXFAIL]
87  "Transmit error", ///< [COMM_TXERROR]
88  "Waiting to receive packet", ///< [COMM_RXWAITING]
89  "Timed out waiting to receive packet", ///< [COMM_RXTIMEOUT]
90  "Received packet corrupted", ///< [COMM_RXCORRUPT]
91  "Unknown communication status" ///< [?]
92 };
93 
94 /*!
95  * \brief Dynamixel Servo Alarms String Table.
96  */
97 static const char *DynaServoAlarmStrTbl[] =
98 {
99  "Input voltage out of range", ///< DYNA_ALARM_VOLTAGE
100  "Angle position out of range", ///< DYNA_ALARM_ANGLE
101  "Over-temperature", ///< DYNA_ALARM_TEMP
102  "Command out of range", ///< DYNA_ALARM_CMD_RANGE
103  "Checksum", ///< DYNA_ALARM_CHECKSUM
104  "Load out of torque range", ///< DYNA_ALARM_LOAD
105  "Instruction code" ///< DYNA_ALARM_INSTRUCTION
106 };
107 
108 /*!
109  * \brief Dynamixel Servo Alarms Short String Table.
110  */
111 static const char *DynaServoAlarmShortStrTbl[] =
112 {
113  "VOLT", ///< DYNA_ALARM_VOLTAGE
114  "POS", ///< DYNA_ALARM_ANGLE
115  "TEMP", ///< DYNA_ALARM_TEMP
116  "CMD", ///< DYNA_ALARM_CMD_RANGE
117  "CS", ///< DYNA_ALARM_CHECKSUM
118  "TORQ", ///< DYNA_ALARM_LOAD
119  "INST" ///< DYNA_ALARM_INSTRUCTION
120 };
121 
122 /*!
123  * \brief Baud rate to baud number enumeration map.
124  */
125 static const int DynaBaudMap[DYNA_BAUDNUM_NUMOF][2] =
126 {
127  {1000000, DYNA_BAUDNUM_1000000},
128  {500000, DYNA_BAUDNUM_500000},
129  {400000, DYNA_BAUDNUM_400000},
130  {250000, DYNA_BAUDNUM_250000},
131  {200000, DYNA_BAUDNUM_200000},
132  {115200, DYNA_BAUDNUM_115200},
133  {57600, DYNA_BAUDNUM_57600},
134  {19200, DYNA_BAUDNUM_19200},
135  {9600, DYNA_BAUDNUM_9600},
136  {2250000, DYNA_BAUDNUM_EXT_2250000},
137  {2500000, DYNA_BAUDNUM_EXT_2500000},
138  {3000000, DYNA_BAUDNUM_EXT_3000000}
139 };
140 
141 
142 // ---------------------------------------------------------------------------
143 // DynaComm Class
144 // ---------------------------------------------------------------------------
145 
146 /*! \brief Shared memory mutex key: roaddyna */
147 const key_t DynaComm::ShmKey = 0x70add12a;
148 
150 {
151  m_sDevUri = NULL;
152  m_nBaudRate = 0;
153  m_bIsOpen = false;
154  m_uAlarms = DYNA_ALARM_NONE;
155 
156  shm_mutex_init(ShmKey, &m_mutexComm);
157 }
158 
159 DynaComm::DynaComm(const char *sUri, int nBaudRate)
160 {
161  m_sDevUri = newstr(sUri);
162  m_nBaudRate = nBaudRate;
163  m_bIsOpen = false;
164  m_uAlarms = DYNA_ALARM_NONE;
165 
166  shm_mutex_init(ShmKey, &m_mutexComm);
167 }
168 
170 {
171  if( m_sDevUri != NULL )
172  {
173  delete[] m_sDevUri;
174  }
175 
176  shm_mutex_destroy(&m_mutexComm);
177 }
178 
179 DynaComm *DynaComm::New(const char *sUri, int nBaudRate)
180 {
181  Uri_T *pUri; // parsed URI
182  const char *sHostName; // parsed/default hostname
183  int nPortNum; // parsed/default IP port number
184  DynaComm *pDynaComm; // new derived Dynamixel bus communication object
185  int rc; // return code
186 
187  pUri = NULL;
188  pDynaComm = NULL;
189 
190  //
191  // No uri string.
192  //
193  if( sUri == NULL )
194  {
195  DYNA_LOG_ERROR(DYNA_ECODE_BAD_VAL, "No URI specified.");
196  }
197 
198  //
199  // Bad baud rate.
200  //
201  else if( (rc = DynaComm::BaudRateToNum(nBaudRate)) < 0 )
202  {
203  DYNA_LOG_ERROR(rc, "%d: Unsupported baudrate.", nBaudRate);
204  }
205 
206  //
207  // Bad uri parse.
208  //
209  else if( (pUri = UriParseNew(sUri)) == NULL )
210  {
211  DYNA_LOG_ERROR(DYNA_ECODE_BAD_VAL, "Failed to parse URI \"%s\".", sUri);
212  }
213 
214  //
215  // Required device path in uri not specified.
216  //
217  else if( pUri->m_sPath == NULL )
218  {
220  "URI \"%s\" does not specify device path.", sUri);
221  }
222 
223  //
224  // Direct connect serial Dynamixel bus.
225  //
226  else if( pUri->m_sScheme == NULL )
227  {
228  pDynaComm = new DynaCommSerial(pUri->m_sPath, nBaudRate);
229  }
230 
231  //
232  // BotSense proxied Dynamixel bus.
233  //
234  else if( !strcasecmp(pUri->m_sScheme, BSPROXY_URI_SCHEME) )
235  {
236  sHostName = pUri->m_sHostName;
237  nPortNum = pUri->m_nPortNum;
238 
239  if( sHostName == NULL )
240  {
241  sHostName = BSPROXY_URI_HOSTNAME_DFT;
242  }
243 
244  if( nPortNum == URI_PORT_NONE )
245  {
246  nPortNum = BSPROXY_LISTEN_PORT_DFT;
247  }
248 
249  pDynaComm = new DynaCommBotSense(pUri->m_sPath, nBaudRate,
250  sHostName, nPortNum);
251  }
252 
253  //
254  // File scheme is also direct connect, but only locally.
255  //
256  else if( !strcasecmp(pUri->m_sScheme, URI_SCHEME_FILE) )
257  {
258  if( (pUri->m_sHostName == NULL) ||
259  !strcasecmp(pUri->m_sHostName, URI_LOCAL_HOST) )
260  {
261  pDynaComm = new DynaCommSerial(pUri->m_sPath, nBaudRate);
262  }
263  else
264  {
266  "URI \"%s\" remote file device access not supported - "
267  "use botsense proxy services.", sUri);
268  }
269  }
270 
271  //
272  // Bad scheme.
273  //
274  else
275  {
276  DYNA_LOG_ERROR(DYNA_ECODE_BAD_VAL, "URI \"%s\" unknown scheme.", sUri);
277  }
278 
279  if( pUri != NULL )
280  {
281  UriDelete(pUri);
282  }
283 
284  //
285  // Final checks
286  //
287  if( (pDynaComm != NULL) && !pDynaComm->IsOpen() )
288  {
290  "Failed to open the device \"%s\" at %d baud.", sUri, nBaudRate);
291  delete pDynaComm;
292  pDynaComm = NULL;
293  }
294 
295  return pDynaComm;
296 }
297 
298 const char *DynaComm::GetBusStatusString(uint_t uBusStatus)
299 {
300  if( uBusStatus < 0 )
301  {
302  uBusStatus = -uBusStatus;
303  }
304 
305  if( uBusStatus >= arraysize(DynaBusStatusStrTbl) )
306  {
307  uBusStatus = arraysize(DynaBusStatusStrTbl) - 1;
308  }
309  return DynaBusStatusStrTbl[uBusStatus];
310 }
311 
312 string DynaComm::GetAlarmsString(const uint_t uAlarms,
313  const string &strSep)
314 {
315  string strAlarms;
316  size_t i;
317  uint_t bit;
318 
319  if( uAlarms == DYNA_ALARM_NONE )
320  {
321  return "OK";
322  }
323 
324  for(i=0, bit=0x01; i<arraysize(DynaServoAlarmStrTbl); ++i, bit<<=1)
325  {
326  if( !strAlarms.empty() )
327  {
328  strAlarms += strSep;
329  }
330 
331  if( bit & uAlarms )
332  {
333  strAlarms += DynaServoAlarmStrTbl[i];
334  }
335  }
336 
337  return strAlarms;
338 }
339 
340 string DynaComm::GetAlarmsShortString(const uint_t uAlarms,
341  const string &strSep)
342 {
343  string strAlarms;
344  size_t i;
345  uint_t bit;
346 
347  if( uAlarms == DYNA_ALARM_NONE )
348  {
349  return "OK";
350  }
351 
352  for(i=0, bit=0x01; i<arraysize(DynaServoAlarmShortStrTbl); ++i, bit<<=1)
353  {
354  if( !strAlarms.empty() )
355  {
356  strAlarms += strSep;
357  }
358 
359  if( bit & uAlarms )
360  {
361  strAlarms += DynaServoAlarmShortStrTbl[i];
362  }
363  }
364 
365  return strAlarms;
366 }
367 
368 int DynaComm::BaudRateToNum(int nBaudRate)
369 {
370  int i;
371 
372  for(i=0; i<arraysize(DynaBaudMap); ++i)
373  {
374  if( DynaBaudMap[i][0] == nBaudRate )
375  {
376  return DynaBaudMap[i][1];
377  }
378  }
379  return -DYNA_ECODE_BAD_VAL;
380 }
381 
382 int DynaComm::BaudNumToRate(int nBaudNum)
383 {
384  int i;
385 
386  for(i=0; i<arraysize(DynaBaudMap); ++i)
387  {
388  if( DynaBaudMap[i][1] == nBaudNum )
389  {
390  return DynaBaudMap[i][0];
391  }
392  }
393  return -DYNA_ECODE_BAD_VAL;
394 }
395 
396 int DynaComm::BaudRateAt(int nIndex)
397 {
398  if( (nIndex >= 0) && (nIndex < arraysize(DynaBaudMap)) )
399  {
400  return DynaBaudMap[nIndex][0];
401  }
402  else
403  {
404  return 0;
405  }
406 }
407 
408 int DynaComm::BaudNumAt(int nIndex)
409 {
410  if( (nIndex >= 0) && (nIndex < arraysize(DynaBaudMap)) )
411  {
412  return DynaBaudMap[nIndex][1];
413  }
414  else
415  {
416  return 0;
417  }
418 }
419 
420 int DynaComm::vSyncWrite(uint_t uAddr, uint_t uValSize, uint_t uCount, ...)
421 {
423  va_list ap;
424  int i;
425 
426  va_start(ap, uCount);
427 
428  for(i=0; i<uCount && i<DYNA_ID_NUMOF; ++i)
429  {
430  tuples[i].m_nServoId = va_arg(ap, int);
431  tuples[i].m_uVal = va_arg(ap, uint_t);
432  }
433 
434  va_end(ap);
435 
436  return SyncWrite(uAddr, uValSize, tuples, (uint_t)i);
437 }
RoadNarrows Dynamixel Bus Communications Abstract Base Class Interface.
static int BaudNumToRate(int nBaudRate)
Map baud number to Dynamixel baud rate.
Definition: DynaComm.cxx:382
char * newstr(const char *s)
Allocate new duplicated string.
Dynamixel Serial Bus Communications Class.
static const char * DynaServoAlarmStrTbl[]
Dynamixel Servo Alarms String Table.
Definition: DynaComm.cxx:97
#define DYNA_BAUDNUM_9600
9,600 bps at -0.160% tolerance
Definition: Dynamixel.h:409
virtual int vSyncWrite(uint_t uAddr, uint_t uValSize, uint_t uCount,...)
Synchronous write 8/16-bit values to a list of Dynamixel servos.
Definition: DynaComm.cxx:420
static int BaudNumAt(int nIndex)
Get the baud number associated with the given index.
Definition: DynaComm.cxx:408
virtual ~DynaComm()
Destructor.
Definition: DynaComm.cxx:169
static int BaudRateAt(int nIndex)
Get the baud rate associated with the given index.
Definition: DynaComm.cxx:396
virtual bool IsOpen()
Test if Dynamixel Bus is open.
Definition: DynaComm.h:383
#define DYNA_BAUDNUM_1000000
1,000,000 bps at 0.0% tolerance
Definition: Dynamixel.h:401
#define DYNA_BAUDNUM_500000
500,000 bps at 0.0% tolerance
Definition: Dynamixel.h:402
#define DYNA_ALARM_NONE
no alarms
Definition: Dynamixel.h:646
#define DYNA_BAUDNUM_200000
200,000 bps at 0.0% tolerance
Definition: Dynamixel.h:405
static const key_t ShmKey
shared memory key
Definition: DynaComm.h:497
static const char * GetBusStatusString(uint_t uBusStatus)
Get the string describing the Dynamixel servo communication status.
Definition: DynaComm.cxx:298
int m_nServoId
servo id
Definition: DynaTypes.h:296
#define DYNA_BAUDNUM_EXT_3000000
3,000,000 bps at 0.0% tolerance
Definition: Dynamixel.h:414
static std::string GetAlarmsShortString(const uint_t uAlarms, const std::string &strSep=",")
Get a formatted servo alarms short string associated with the alarms.
Definition: DynaComm.cxx:340
#define DYNA_ID_NUMOF
number of unique servo id&#39;s
Definition: Dynamixel.h:148
#define DYNA_ECODE_BAD_DEV
no or bad serial device
Definition: Dynamixel.h:87
#define DYNA_LOG_ERROR(ecode, efmt,...)
Log Error.
static const char * DynaBusStatusStrTbl[]
Dynamixel Bus Communication Status String Table.
Definition: DynaComm.cxx:81
static DynaComm * New(const char *sUri, int nBaudRate)
Archetype constructor to create a new Dynamixel bus communication derived instance.
Definition: DynaComm.cxx:179
static const int DynaBaudMap[DYNA_BAUDNUM_NUMOF][2]
Baud rate to baud number enumeration map.
Definition: DynaComm.cxx:125
The libDynamixel internal declarations.
#define DYNA_BAUDNUM_19200
19,200 bps at -0.160% tolerance
Definition: Dynamixel.h:408
uint_t m_uVal
write value
Definition: DynaTypes.h:297
#define DYNA_BAUDNUM_57600
57,600 bps at 0.794 % tolerance
Definition: Dynamixel.h:407
#define DYNA_BAUDNUM_EXT_2500000
2,500,000 bps at 0.0% tolerance
Definition: Dynamixel.h:413
RoadNarrows Dynamixel Bus Communication over Serial Interface Class Interface.
#define DYNA_BAUDNUM_115200
115,200 bps at -2.124% tolerance
Definition: Dynamixel.h:406
static std::string GetAlarmsString(const uint_t uAlarms, const std::string &strSep="; ")
Get a formatted servo alarms string associated with the alarms.
Definition: DynaComm.cxx:312
BotSense IP Proxied Dynamixel Bus Communications Class.
RoadNarrows Dynamixel Top-Level Package Header File.
#define DYNA_BAUDNUM_NUMOF
number of supported bit rates
Definition: Dynamixel.h:416
RoadNarrows Botsene IP Proxied Dynamixel Bus Communication Class Interface.
#define DYNA_ECODE_BAD_VAL
bad value
Definition: Dynamixel.h:85
static const char * DynaServoAlarmShortStrTbl[]
Dynamixel Servo Alarms Short String Table.
Definition: DynaComm.cxx:111
RoadNarrows Dynamixel Library Error and Logging Routines.
#define DYNA_BAUDNUM_250000
250,000 bps at 0.0% tolerance
Definition: Dynamixel.h:404
static int BaudRateToNum(int nBaudRate)
Map baud rate to Dynamixel baud number.
Definition: DynaComm.cxx:368
#define DYNA_BAUDNUM_400000
500,000 bps at 0.0% tolerance
Definition: Dynamixel.h:403
Dynamixel Bus Communications Abstract Base Class.
Definition: DynaComm.h:80
#define DYNA_BAUDNUM_EXT_2250000
2,250,000 bps at 0.0% tolerance
Definition: Dynamixel.h:412