Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
DynaCommBotSense.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // Library: libDynamixel
6 //
7 // File: DynaCommBotSense.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-03-04 12:38:36 -0700 (Wed, 04 Mar 2015) $
12  * $Rev: 3873 $
13  *
14  * \brief RoadNarrows Dynamixel bus communication over BotSense IP proxy
15  * interface class.
16  *
17  * \author Robin Knight (robin.knight@roadnarrows.com)
18  *
19  * \copyright
20  * \h_copy 2011-2017. RoadNarrows LLC.\n
21  * http://www.roadnarrows.com\n
22  * All Rights Reserved
23  */
24 /*
25  * @EulaBegin@
26  *
27  * Unless otherwise stated explicitly, all materials contained are copyrighted
28  * and may not be used without RoadNarrows LLC's written consent,
29  * except as provided in these terms and conditions or in the copyright
30  * notice (documents and software) or other proprietary notice provided with
31  * the relevant materials.
32  *
33  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY
34  * MEMBERS/EMPLOYEES/CONTRACTORS OF ROADNARROWS OR DISTRIBUTORS OF THIS SOFTWARE
35  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
36  * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
37  * DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN
38  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40  * THE AUTHORS AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
41  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
42  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
43  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
44  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
45  *
46  * @EulaEnd@
47  */
48 ////////////////////////////////////////////////////////////////////////////////
49 
50 #include <unistd.h>
51 #include <ctype.h>
52 #include <pthread.h>
53 
54 #include "rnr/rnrconfig.h"
55 #include "rnr/uri.h"
56 #include "rnr/shm.h"
57 #include "rnr/log.h"
58 
59 #include "botsense/BotSense.h"
60 #include "botsense/libBotSense.h"
61 #include "botsense/bsDyna.h"
62 
63 #include "Dynamixel/Dynamixel.h"
64 #include "Dynamixel/DynaError.h"
65 #include "Dynamixel/DynaComm.h"
67 
68 #include "DynaLibInternal.h"
69 
70 
71 // ---------------------------------------------------------------------------
72 // Private Interface
73 // ---------------------------------------------------------------------------
74 
75 // ---------------------------------------------------------------------------
76 // DynaCommBotSense Class
77 // ---------------------------------------------------------------------------
78 
80 {
81  m_sSerialDevName = NULL;
82  m_sBsProxyHostName = newstr("localhost");
83  m_nBsProxyIPPort = BSPROXY_LISTEN_PORT_DFT;
84  m_pBsClient = bsClientNew("Dynamixel");
85  m_hndBsVConn = BSPROXY_VCONN_UNDEF;
86  m_bBsTrace = false;
87 }
88 
89 DynaCommBotSense::DynaCommBotSense(const char *sSerialDevName,
90  int nBaudRate,
91  const char *sBsProxyHostName,
92  int nBsProxyIPPort) : DynaComm()
93 {
94  Uri_T uri;
95 
96  // fill in URI structure
97  uri.m_sScheme = (char *)BSPROXY_URI_SCHEME;
98  uri.m_sUserInfo = NULL;
99  uri.m_sHostName = (char *)sBsProxyHostName;
100  uri.m_nPortNum = nBsProxyIPPort;
101  uri.m_sPath = (char *)sSerialDevName;
102  uri.m_sQuery = NULL;
103 
104  m_sDevUri = UriStrNew(&uri);
105  m_nBaudRate = nBaudRate;
106 
107  m_sSerialDevName = newstr(sSerialDevName);
108  m_sBsProxyHostName = newstr(sBsProxyHostName);
109  m_nBsProxyIPPort = nBsProxyIPPort;
110  m_pBsClient = bsClientNew("Dynamixel");
111  m_hndBsVConn = BSPROXY_VCONN_UNDEF;
112  m_bBsTrace = false;
113 
114  Open();
115 }
116 
118 {
119  Close();
120 
121  bsClientDelete(m_pBsClient);
122 
123  if( m_sBsProxyHostName != NULL )
124  {
125  delete[] m_sBsProxyHostName;
126  }
127 
128  if( m_sSerialDevName != NULL )
129  {
130  delete[] m_sSerialDevName;
131  }
132 }
133 
134 int DynaCommBotSense::Open(const char *sSerialDevName,
135  int nBaudRate,
136  const char *sBsProxyHostName,
137  int nBsProxyIPPort)
138 {
139  // close if open
140  Close();
141 
142  if( m_sSerialDevName != NULL )
143  {
144  delete[] m_sSerialDevName;
145  }
146 
147  if( m_sBsProxyHostName != NULL )
148  {
149  delete[] m_sBsProxyHostName;
150  }
151 
152  m_sSerialDevName = newstr(sSerialDevName);
153  m_nBaudRate = nBaudRate;
154  m_sBsProxyHostName = newstr(sBsProxyHostName);
155  m_nBsProxyIPPort = nBsProxyIPPort;
156  m_hndBsVConn = BSPROXY_VCONN_UNDEF;
157 
158  // (re)open
159  return Open();
160 }
161 
163 {
164  int nSerialIndex;
165  int nBaudNum;
166  int rc;
167 
168  // close if open
169  Close();
170 
171  // check proxied serial device name
172  if( (m_sSerialDevName == NULL) || (*m_sSerialDevName == 0) )
173  {
174  rc = -DYNA_ECODE_BAD_VAL;
175  DYNA_LOG_ERROR(rc, "Unspecified serial device.");
176  }
177 
178  // check proxy server host name
179  else if( (m_sBsProxyHostName == NULL) || (*m_sBsProxyHostName == 0) )
180  {
181  rc = -DYNA_ECODE_BOTSENSE;
182  DYNA_LOG_ERROR(rc, "Unspecified BotSense server host name.");
183  }
184 
185  // connect to bsProxy server
186  else if((rc =
187  bsServerConnect(m_pBsClient, m_sBsProxyHostName, m_nBsProxyIPPort)) < 0)
188  {
189  LOGERROR("bsProxy server %s:%d: %s.",
190  m_sBsProxyHostName, m_nBsProxyIPPort, bsStrError(rc));
191  rc = -DYNA_ECODE_BOTSENSE;
192  }
193 
194  // open proxied serial device
195  else if( (m_hndBsVConn = bsDynaOpen(m_pBsClient,
197  m_nBaudRate,
198  m_bBsTrace)) < 0 )
199  {
200  rc = m_hndBsVConn;
201  m_hndBsVConn = BSPROXY_VCONN_UNDEF;
202  DYNA_LOG_ERROR(rc, "Failed to open %s@%d on bsProxy server %s:%d.",
204  }
205 
206  // success
207  else
208  {
209  m_bIsOpen = true;
210  rc = DYNA_OK;
211  LOGDIAG3("Dynamixel bus communication opened on %s@%d "
212  "via bsProxy server %s:%d.",
214  }
215 
216  return rc;
217 }
218 
220 {
221  if( m_bIsOpen )
222  {
223  bsDynaClose(m_pBsClient, m_hndBsVConn);
224  bsServerDisconnect(m_pBsClient);
225  m_hndBsVConn = BSPROXY_VCONN_UNDEF;
226  m_bIsOpen = false;
227  }
228  return DYNA_OK;
229 }
230 
231 int DynaCommBotSense::SetBaudRate(int nNewBaudRate)
232 {
233  int rc; // return code
234 
235  if( m_bIsOpen )
236  {
237  rc = bsDynaSetBaudRate(m_pBsClient, m_hndBsVConn, nNewBaudRate);
238 
239  DYNA_TRY_RC(rc, "SetBaudRate(%d)", nNewBaudRate);
240  }
241 
242  m_nBaudRate = nNewBaudRate;
243 
244  return DYNA_OK;
245 }
246 
248  HalfDuplexTxFunc_T fnEnableTx,
249  HalfDuplexRxFunc_T fnEnableRx)
250 {
251  int rc; // return code
252 
253  if( m_bIsOpen )
254  {
255  // Note: do not know how got generalize this for non-builtin signal support.
256  rc = bsDynaSetHalfDuplexCtl(m_pBsClient, m_hndBsVConn, nSignal);
257 
258  DYNA_TRY_RC(rc, "SetHalfDuplexCtl(%d)", nSignal);
259  }
260 
261  return DYNA_OK;
262 }
263 
265 {
266  m_bBsTrace = bEnabled;
267 
268  return DYNA_OK;
269 }
270 
271 int DynaCommBotSense::Read8(int nServoId, uint_t uAddr, byte_t *pVal)
272 {
273  int rc;
274 
275  DYNA_TRY_COMM(*this);
276 
277  shm_mutex_lock(&m_mutexComm);
278 
279  rc = bsDynaRead8(m_pBsClient, m_hndBsVConn,
280  nServoId, uAddr, pVal, &m_uAlarms);
281 
282  shm_mutex_unlock(&m_mutexComm);
283 
284  if( rc == BS_OK )
285  {
286  rc = DYNA_OK;
287  }
288  else
289  {
290  rc = -DYNA_ECODE_BOTSENSE;
291  DYNA_LOG_ERROR(rc, "Read8(%d, 0x%02x)", nServoId, uAddr);
292  }
293 
294  return rc;
295 }
296 
297 int DynaCommBotSense::Write8(int nServoId, uint_t uAddr, byte_t byVal)
298 {
299  int rc;
300 
301  DYNA_TRY_COMM(*this);
302 
303  shm_mutex_lock(&m_mutexComm);
304 
305  rc = bsDynaWrite8(m_pBsClient, m_hndBsVConn,
306  nServoId, uAddr, byVal, &m_uAlarms);
307 
308  shm_mutex_unlock(&m_mutexComm);
309 
310  if( rc == BS_OK )
311  {
312  rc = DYNA_OK;
313  }
314  else
315  {
316  rc = -DYNA_ECODE_BOTSENSE;
317  DYNA_LOG_ERROR(rc, "Write8(%d, 0x%02x, 0x%02x)", nServoId, uAddr, byVal);
318  }
319 
320  return rc;
321 }
322 
323 int DynaCommBotSense::Read16(int nServoId, uint_t uAddr, ushort_t *pVal)
324 {
325  int rc;
326 
327  DYNA_TRY_COMM(*this);
328 
329  shm_mutex_lock(&m_mutexComm);
330 
331  rc = bsDynaRead16(m_pBsClient, m_hndBsVConn,
332  nServoId, uAddr, pVal, &m_uAlarms);
333 
334  shm_mutex_unlock(&m_mutexComm);
335 
336  if( rc == BS_OK )
337  {
338  rc = DYNA_OK;
339  }
340  else
341  {
342  rc = -DYNA_ECODE_BOTSENSE;
343  DYNA_LOG_ERROR(rc, "Read16(%d, 0x%02x)", nServoId, uAddr);
344  }
345 
346  return rc;
347 }
348 
349 int DynaCommBotSense::Write16(int nServoId, uint_t uAddr, ushort_t huVal)
350 {
351  int rc;
352 
353  DYNA_TRY_COMM(*this);
354 
355  shm_mutex_lock(&m_mutexComm);
356 
357  rc = bsDynaWrite16(m_pBsClient, m_hndBsVConn,
358  nServoId, uAddr, huVal, &m_uAlarms);
359 
360  shm_mutex_unlock(&m_mutexComm);
361 
362  if( rc == BS_OK )
363  {
364  rc = DYNA_OK;
365  }
366  else
367  {
368  rc = -DYNA_ECODE_BOTSENSE;
369  DYNA_LOG_ERROR(rc, "Write16(%d, 0x%02x, 0x%04x)", nServoId, uAddr, huVal);
370  }
371 
372  return rc;
373 }
374 
376  uint_t uValSize,
377  DynaSyncWriteTuple_T tuples[],
378  uint_t uCount)
379 {
380  int rc;
381 
382  DYNA_TRY_COMM(*this);
383 
384  shm_mutex_lock(&m_mutexComm);
385 
386  rc = bsDynaSyncWrite(m_pBsClient, m_hndBsVConn,
387  uAddr, uValSize, tuples, uCount);
388 
389  shm_mutex_unlock(&m_mutexComm);
390 
391  if( rc == BS_OK )
392  {
393  rc = DYNA_OK;
394  }
395  else
396  {
397  rc = -DYNA_ECODE_BOTSENSE;
398  DYNA_LOG_ERROR(rc, "SyncWrite(0x%02x, %d, tuples, %d)",
399  uAddr, uValSize, uCount);
400  }
401 
402  return rc;
403 }
404 
405 bool DynaCommBotSense::Ping(int nServoId)
406 {
407  bool_t bPong;
408  int rc;
409 
410  DYNA_TRY_COMM(*this);
411 
412  shm_mutex_lock(&m_mutexComm);
413 
414  rc = bsDynaPing(m_pBsClient, m_hndBsVConn, nServoId, &bPong);
415 
416  shm_mutex_unlock(&m_mutexComm);
417 
418  if( rc == BS_OK )
419  {
420  return bPong? true: false;
421  }
422  else
423  {
424  rc = -DYNA_ECODE_BOTSENSE;
425  DYNA_LOG_ERROR(rc, "Ping(%d)", nServoId);
426  return false;
427  }
428 }
429 
430 int DynaCommBotSense::Reset(int nServoId)
431 {
432  int rc;
433 
434  DYNA_TRY_COMM(*this);
435 
436  shm_mutex_lock(&m_mutexComm);
437 
438  rc = bsDynaReset(m_pBsClient, m_hndBsVConn, nServoId);
439 
440  shm_mutex_unlock(&m_mutexComm);
441 
442  if( rc == BS_OK )
443  {
444  rc = DYNA_OK;
445  }
446  else
447  {
448  rc = -DYNA_ECODE_BOTSENSE;
449  DYNA_LOG_ERROR(rc, "Reset(%d)", nServoId);
450  }
451 
452  return rc;
453 }
454 
uint_t m_uAlarms
servo alarms from last I/O operation
Definition: DynaComm.h:503
RoadNarrows Dynamixel Bus Communications Abstract Base Class Interface.
char * newstr(const char *s)
Allocate new duplicated string.
virtual int SetMsgTracing(bool bEnabled)
char * m_sDevUri
dynamixel bus device URI
Definition: DynaComm.h:499
bsProxy client library Dynamixel interface.
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
#define DYNA_ECODE_BOTSENSE
BotSense proxy error.
Definition: Dynamixel.h:100
int m_nBaudRate
baud rate
Definition: DynaComm.h:500
char * m_sSerialDevName
proxied serial device name
virtual int Read8(int nServoId, uint_t uAddr, byte_t *pVal)
Read an 8-bit value from Dynamixel servo control table.
virtual bool Ping(int nServoId)
Ping the servo.
shm_mutex_t m_mutexComm
synchonization mutex
Definition: DynaComm.h:504
BsClient_P m_pBsClient
BotSense client.
bool m_bIsOpen
dynamixel bus communication is [not] open
Definition: DynaComm.h:501
BsVConnHnd_T m_hndBsVConn
virtual connection to proxied device
#define DYNA_LOG_ERROR(ecode, efmt,...)
Log Error.
virtual int SetBaudRate(int nNewBaudRate)
virtual ~DynaCommBotSense()
Destructor.
char * m_sBsProxyHostName
BotSense proxy server domain/IP address.
int m_nBsProxyIPPort
BotSense proxy server IP port number.
void(* HalfDuplexRxFunc_T)(void *pArg, size_t uNumTxBytes)
Half-duplex control receive function type.
Definition: DynaComm.h:87
virtual int Reset(int nServoId)
Reset a servo back to default values.
void(* HalfDuplexTxFunc_T)(void *pArg)
Half-duplex control transmit function type.
Definition: DynaComm.h:84
The libDynamixel internal declarations.
virtual int Open()
(Re)Open serial communication to dynamixel bus.
bool m_bBsTrace
do [not] trace messaging
virtual int Write8(int nServoId, uint_t uAddr, byte_t byVal)
Write an 8-bit value to Dynamixel servo control table.
DynaCommBotSense()
Default constructor.
RoadNarrows Dynamixel Top-Level Package Header File.
virtual int Close()
Close serial communication to dynamixel bus and connection to BotSense proxy server.
RoadNarrows Botsene IP Proxied Dynamixel Bus Communication Class Interface.
virtual int SyncWrite(uint_t uAddr, uint_t uValSize, DynaSyncWriteTuple_T tuples[], uint_t uCount)
Synchronous Write 8/16-bit values to a list of Dynamixel servos.
virtual int Read16(int nServoId, uint_t uAddr, ushort_t *pVal)
Read a 16-bit value from Dynamixel servo control table.
#define DYNA_ECODE_BAD_VAL
bad value
Definition: Dynamixel.h:85
virtual int SetHalfDuplexCtl(int nSignal, HalfDuplexTxFunc_T fnEnableTx=NULL, HalfDuplexRxFunc_T fnEnableRx=NULL)
#define DYNA_TRY_RC(rc, fmt,...)
Test if Dynamixel return code is not an error.
virtual int Write16(int nServoId, uint_t uAddr, ushort_t uhVal)
Write a 16-bit value to Dynamixel servo control table.
RoadNarrows Dynamixel Library Error and Logging Routines.
Dynamixel Bus Communications Abstract Base Class.
Definition: DynaComm.h:80
#define DYNA_TRY_COMM(comm)
Test if bus communication is available exception macro.