Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
dynashell_cmd_if.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // Program: dynashell
6 //
7 // File: dynashell_if.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-07-04 11:47:16 -0600 (Sat, 04 Jul 2015) $
12  * $Rev: 4023 $
13  *
14  * \brief The Dynamixel Shell Interface Derived Commands.
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 
50 #include <sys/time.h>
51 #include <sys/types.h>
52 #include <stdio.h>
53 #include <unistd.h>
54 #include <ctype.h>
55 
56 #include <cstring>
57 #include <iostream>
58 #include <fstream>
59 #include <string>
60 
61 #include "rnr/rnrconfig.h"
62 #include "rnr/log.h"
63 
64 #include "Dynamixel/Dynamixel.h"
65 #include "Dynamixel/DynaComm.h"
67 #include "Dynamixel/DynaServo.h"
68 #include "Dynamixel/DynaChain.h"
69 #include "Dynamixel/DynaBgThread.h"
70 
71 #include "dynashell.h"
72 #include "dynashell_cmd.h"
73 #include "dynashell_util.h"
74 
75 using namespace std;
76 
77 
78 // -----------------------------------------------------------------------------
79 // DynaShellCmdCreate Class
80 // -----------------------------------------------------------------------------
81 
82 /*!
83  * \brief Create command.
84  */
86 {
87 public:
88 
89  /*
90  * \brief Default constructor.
91  */
93  {
94  m_sCmdName = "create";
95  m_sCmdHelpBrief = "Create a new dynamixel chain interface.";
96  m_sCmdHelpArgs = "<uri> <baudrate>";
97  m_sCmdHelpDesc = "Create a new, empty dynamixel chain interface. "
98  "A connection is opened to the (proxied) dynamixel bus "
99  "as specifed by the <uri> and at the specified "
100  "<baudrate>. The created dynamixel chain is empty. "
101  "Use scan to populate the chain.\n"
102  " <uri> "
103  "[botsense://[<hostname>][:<port>]]/<device>\n"
104  " <baudrate> Baud rate. One of:\n"
105  " 9600 19200 57600 115200 200000 250000 "
106  "400000 500000 1000000\n"
107  " 2250000 2500000 3000000";
108  }
109 
110  /*!
111  * \brief Create dynamixel interface.
112  *
113  * \param shell Dynamixel shell.
114  * \param argc Command argument count.
115  * \param argv Array of arguments.
116  */
117  void Exec(DynaShell &shell, int argc, char *argv[])
118  {
119  char *sUri;
120  int nBaudRate;
121 
122  TRY( ChkArgCnt(shell, argc) );
123 
124  sUri = argv[0];
125 
126  TRY( ToInt(shell, argv[1], &nBaudRate) );
127 
128  if( shell.m_pDynaChain != NULL )
129  {
130  shell.Error("Dynamixel interface already created. Try destroying first.");
131  return;
132  }
133 
134  shell.m_pDynaComm = CommNew(shell, sUri, nBaudRate);
135 
136  TRY( shell.m_pDynaComm != NULL );
137 
138  shell.m_pDynaChain = new DynaChain(*shell.m_pDynaComm);
139 
140  // create background thread and register chain - leave in ready state
141  if( shell.m_pDynaBgThread == NULL )
142  {
143  shell.m_pDynaBgThread = new DynaBgThread();
145  }
146 
147  // register new chain with background thread - leave in ready state
148  else
149  {
150  switch( shell.m_pDynaBgThread->GetCurrentState() )
151  {
154  shell.m_pDynaBgThread->Stop();
155  break;
156  default:
157  break;
158  }
159 
162  }
163 
164  shell.Ok();
165  }
166 
167  /*!
168  * \brief Command tab completion generator.
169  *
170  * Completes <device> <baudrate>
171  *
172  * \param shell Dynamixel shell.
173  * \param sText Partial text string to complete.
174  * \param uTextLen Length of text.
175  * \param nState Generator state. If FIRST, then initialize any statics.
176  * \param sContext Generator context (i.e. canonical command path).
177  *
178  * \return
179  * If a first/next match is made, return allocated completed match.\n
180  * Otherwise return NULL.
181  */
182  virtual char *TabCompletion(DynaShell &shell,
183  const char *sText,
184  size_t uTextLen,
185  int nState,
186  const char *sContext)
187  {
188  int nBaudRate;
189  char buf[32];
190 
191  // <device>
192  if( ReadLine::wc(sContext) == ReadLine::wc(m_sPubName) )
193  {
194  return ReadLine::FileCompletionGenerator(sText, nState);
195  }
196 
197  //
198  // New command to complete - initialize.
199  //
200  if( nState == ReadLine::FIRST )
201  {
202  m_nTabIter = 0;
203  }
204 
205  // <baudrate>
206  while( (nBaudRate = DynaComm::BaudRateAt(m_nTabIter)) != 0 )
207  {
208  m_nTabIter++;
209 
210  snprintf(buf, sizeof(buf), "%d", nBaudRate);
211  buf[sizeof(buf)-1] = 0;
212 
213  if( !strncmp(buf, sText, uTextLen) )
214  {
215  return ReadLine::dupstr(buf);
216  }
217  }
218 
219  // no more matches
220  return NULL;
221  }
222 
223 protected:
224  int m_nTabIter; ///< tab completion: baud rate iterator
225 
226  /*!
227  * \brief Create a new open dynamixel bus object.
228  *
229  * \param shell Dynamixel shell.
230  * \param sUri Dynamixel bus [proxied] device Uniform Resource Id.
231  * \param nBaudRate Device and servo baudrate.
232  *
233  * \return Returns new DynaComm object on success, NULL on failure.
234  */
235  DynaComm *CommNew(DynaShell &shell, const char *sUri, int nBaudRate)
236  {
237  DynaComm *pDynaComm = DynaComm::New(sUri, nBaudRate);
238 
239  if( pDynaComm == NULL )
240  {
241  shell.Error("Failed to create %s@%d.", sUri, nBaudRate);
242  }
243 
244  else if( !pDynaComm->IsOpen() )
245  {
246  shell.Error("Failed to open %s@%d.", sUri, nBaudRate);
247  delete pDynaComm;
248  pDynaComm = NULL;
249  }
250 
251  return pDynaComm;
252  }
253 };
254 
255 
256 // -----------------------------------------------------------------------------
257 // DynaShellCmdDestroy Class
258 // -----------------------------------------------------------------------------
259 
260 /*!
261  * \brief Destroy command.
262  */
264 {
265 public:
266 
267  /*
268  * \brief Default constructor.
269  */
271  {
272  m_sCmdName = "destroy";
273  m_sCmdHelpBrief = "Destroy the dynamixel interface.";
274  m_sCmdHelpArgs = "";
275  m_sCmdHelpDesc = "Destroy the existing dynamixel interface. Any existing "
276  "dynamixel bus communication is closed.";
277  }
278 
279  /*!
280  * \brief Destroy dynamixel interface.
281  *
282  * \param shell Dynamixel shell.
283  * \param argc Command argument count.
284  * \param argv Array of arguments.
285  */
286  void Exec(DynaShell &shell, int argc, char *argv[])
287  {
288  TRY( ChkArgCnt(shell, argc) );
289 
290  if( shell.m_pDynaChain == NULL )
291  {
292  shell.Error("Dynamixel interface not created.");
293  }
294  else
295  {
296  switch( shell.m_pDynaBgThread->GetCurrentState() )
297  {
300  shell.m_pDynaBgThread->Stop();
301  break;
302  default:
303  break;
304  }
305 
307 
308  DELOBJ(shell.m_pDynaChain);
309  DELOBJ(shell.m_pDynaComm);
310 
311  shell.Ok();
312  }
313  }
314 };
315 
316 
317 // -----------------------------------------------------------------------------
318 // DynaShellCmdScan Class
319 // -----------------------------------------------------------------------------
320 
321 /*!
322  * \brief Scan command.
323  */
325 {
326 public:
327 
328  /*
329  * \brief Default constructor.
330  */
332  {
333  m_sCmdName = "scan";
334  m_sCmdHelpBrief = "Scan for servos.";
335  m_sCmdHelpArgs = "";
336  m_sCmdHelpDesc = "Scan the dynamixel bus for all servos and add to the "
337  "chain. The chain is cleared of existing servos prior to "
338  "the scan.";
339  }
340 
341  /*!
342  * \brief Scan for all connected servos and add to chain.
343  *
344  * \param shell Dynamixel shell.
345  * \param argc Command argument count.
346  * \param argv Array of arguments.
347  */
348  void Exec(DynaShell &shell, int argc, char *argv[])
349  {
350  DynaBgThread::BgThreadState eOldState;
351  int nNumServos;
352 
353  TRY( ChkArgCnt(shell, argc) );
354  TRY( ChkComm(shell) );
355  TRY( ChkChain(shell) );
356 
357  switch( (eOldState = shell.m_pDynaBgThread->GetCurrentState()) )
358  {
361  shell.m_pDynaBgThread->Stop();
362  break;
363  default:
364  break;
365  }
366 
368 
370 
372 
373  nNumServos = shell.m_pDynaChain->GetNumberInChain();
374 
375  if( (eOldState == DynaBgThread::BgThreadStateRunning) && (nNumServos > 0) )
376  {
377  shell.m_pDynaBgThread->Run();
378  }
379 
380  shell.Response("Added %d servos to chain.\n", nNumServos);
381  }
382 };
383 
384 
385 // -----------------------------------------------------------------------------
386 // DynaShellCmdPing Class
387 // -----------------------------------------------------------------------------
388 
389 /*!
390  * \brief Ping command.
391  */
393 {
394 public:
395 
396  /*
397  * \brief Default constructor.
398  */
400  {
401  m_sCmdName = "ping";
402  m_sCmdHelpBrief = "Ping a servo.";
403  m_sCmdHelpArgs = "<servo_id>";
404  m_sCmdHelpDesc = "Ping a servo. The servo does not have to be present "
405  "in the dynamixel chain.\n"
406  " <servo_id> Servo id [0-253].";
407  }
408 
409  /*!
410  * \brief Ping a servo.
411  *
412  * \param shell Dynamixel shell.
413  * \param argc Command argument count.
414  * \param argv Array of arguments.
415  */
416  void Exec(DynaShell &shell, int argc, char *argv[])
417  {
418  int nServoId;
419  bool bPong;
420 
421  TRY( ChkArgCnt(shell, argc) );
422  TRY( ToInt(shell, argv[0], &nServoId) );
423  TRY( ChkComm(shell) );
424 
425  bPong = shell.m_pDynaComm->Ping(nServoId);
426 
427  shell.Response("Servo %d: %s.\n", nServoId,
428  (bPong? "present": "no response"));
429  }
430 };
431 
432 
433 // -----------------------------------------------------------------------------
434 // DynaShellCmdList Class
435 // -----------------------------------------------------------------------------
436 
437 /*!
438  * \brief List command.
439  */
441 {
442 public:
443 
444  /*
445  * \brief Default constructor.
446  */
448  {
449  m_sCmdName = "list";
450  m_sCmdHelpBrief = "List servo information.";
451  m_sCmdHelpArgs = "";
452  m_sCmdHelpDesc = "List information about all servos in the dynamixel "
453  "chain. Per each servo, the servo id, model number "
454  "firmware version, mode, and linkage, if any, are "
455  "printed.";
456  }
457 
458  /*!
459  * \brief List servo chain info.
460  *
461  * \param shell Dynamixel shell.
462  * \param argc Command argument count.
463  * \param argv Array of arguments.
464  */
465  void Exec(DynaShell &shell, int argc, char *argv[])
466  {
467  int nServoId;
468  const DynaServo *pServo;
469  int iter;
470 
471  TRY( ChkArgCnt(shell, argc) );
472  TRY( ChkComm(shell) );
473  TRY( ChkChain(shell) );
474 
475  for(nServoId = shell.m_pDynaChain->IterStart(&iter);
476  nServoId != DYNA_ID_NONE;
477  nServoId = shell.m_pDynaChain->IterNext(&iter))
478  {
479  pServo = shell.m_pDynaChain->GetServo(nServoId);
480  shell.Response("Servo %3d: %7s, model 0x%04x, fwver 0x%02x",
481  nServoId, pServo->GetModelName(),
482  pServo->GetModelNumber(), pServo->GetFirmwareVersion());
483  if( pServo->GetServoMode() == DYNA_MODE_SERVO )
484  {
485  shell.Response(", servo mode");
486  }
487  else
488  {
489  shell.Response(", continuous mode");
490  }
491  if( shell.m_pDynaChain->IsLinkedMaster(nServoId) )
492  {
493  shell.Response(", linked master of %d",
494  shell.m_pDynaChain->GetLinkedMateId(nServoId));
495  }
496  else if( shell.m_pDynaChain->IsLinkedSlave(nServoId) )
497  {
498  shell.Response(", linked slave of %d",
499  shell.m_pDynaChain->GetLinkedMateId(nServoId));
500  }
501  shell.Response("\n");
502  }
503  }
504 };
505 
506 
507 // -----------------------------------------------------------------------------
508 // DynaShellCmdLink Class
509 // -----------------------------------------------------------------------------
510 
511 /*!
512  * \brief Link <master_id> <slaf_id> <dir> command.
513  */
515 {
516 public:
517  /*
518  * \brief Default constructor.
519  */
521  {
522  m_sCmdName = "link";
523  m_sCmdHelpBrief = "Link two servos in a master-slave configuration.";
524  m_sCmdHelpArgs = "<master_id> <slave_id> <dir>";
525  m_sCmdHelpDesc = "Link two servos in a master-slave configuration. "
526  "The servos may operate in the same forward rotation "
527  "direction or in opposite reverse directions. Once "
528  "linked, all commands that modify servo state "
529  "(e.g. move and write) are only supported on the master "
530  "servo to preserve synchronization.\n"
531  " <master_id> Master servo id.\n"
532  " <slave_id> Slave servo id.\n"
533  " <dir> One of: forward reverse.";
534  }
535 
536  /*!
537  * \brief Link two servo together.
538  *
539  * \param shell Dynamixel shell.
540  * \param argc Command argument count.
541  * \param argv Array of arguments.
542  */
543  void Exec(DynaShell &shell, int argc, char *argv[])
544  {
545  int nServoIdMaster;
546  int nServoIdSlave;
547  bool bIsReversed;
548  int rc;
549 
550  TRY( ChkArgCnt(shell, argc) );
551 
552  TRY( ToInt(shell, argv[0], &nServoIdMaster) );
553  TRY( ToInt(shell, argv[1], &nServoIdSlave) );
554 
555  if( !strncmp("forward", argv[2], strlen(argv[2])) )
556  {
557  bIsReversed = false;
558  }
559  else if( !strncmp("reverse", argv[2], strlen(argv[2])) )
560  {
561  bIsReversed = true;
562  }
563  else
564  {
565  shell.Error(-DYNA_ECODE_BAD_VAL, "Unknown linkage <dir> '%s'", argv[2]);
566  return;
567  }
568 
569  TRY( ChkComm(shell) );
570  TRY( ChkChain(shell) );
571  TRY( ChkChainHasServo(shell, nServoIdMaster) );
572  TRY( ChkChainHasServo(shell, nServoIdSlave) );
573 
574  rc = shell.m_pDynaChain->LinkServos(nServoIdMaster,
575  nServoIdSlave,
576  bIsReversed);
577 
578  if( rc != DYNA_OK )
579  {
580  shell.Error(rc, "Cannot link servos %d and %d.",
581  nServoIdMaster, nServoIdSlave);
582  }
583  else
584  {
585  shell.Ok();
586  }
587  }
588 
589  /*!
590  * \brief Command tab completion generator.
591  *
592  * Completes <master_id> <slave_id> <dir>
593  *
594  * \param shell Dynamixel shell.
595  * \param sText Partial text string to complete.
596  * \param uTextLen Length of text.
597  * \param nState Generator state. If FIRST, then initialize any statics.
598  * \param sContext Generator context (i.e. canonical command path).
599  *
600  * \return
601  * If a first/next match is made, return allocated completed match.\n
602  * Otherwise return NULL.
603  */
604  virtual char *TabCompletion(DynaShell &shell,
605  const char *sText,
606  size_t uTextLen,
607  int nState,
608  const char *sContext)
609  {
610  // direction keyword table
611  static const char *keywordsDir[] = {"forward", "reverse"};
612 
613  int nArgNum;
614  int nServoId;
615  const char *s;
616  char buf[16];
617 
618  if( (shell.m_pDynaChain == NULL) ||
619  (shell.m_pDynaChain->GetNumberInChain() == 0) )
620  {
621  return NULL;
622  }
623 
624  // argument number of already (expanded) arguments
625  nArgNum = ReadLine::wc(sContext) - ReadLine::wc(m_sPubName);
626 
627  //
628  // New command argument to complete - initialize.
629  //
630  if( nState == ReadLine::FIRST )
631  {
632  m_nTabServoId = shell.m_pDynaChain->IterStart(&m_nTabIter);
633  m_nTabIndex = 0;
634  }
635 
636  // <master_id> or <slave_id>
637  if( nArgNum < 2 )
638  {
639  while( m_nTabServoId != DYNA_ID_NONE )
640  {
641  nServoId = m_nTabServoId;
642 
643  m_nTabServoId = shell.m_pDynaChain->IterNext(&m_nTabIter);
644 
645  if( !shell.m_pDynaChain->IsUnlinked(m_nTabServoId) )
646  {
647  continue;
648  }
649 
650  snprintf(buf, sizeof(buf), "%d", nServoId);
651  buf[sizeof(buf)-1] = 0;
652 
653  if( !strncmp(buf, sText, uTextLen) )
654  {
655  return ReadLine::dupstr(buf);
656  }
657  }
658  }
659 
660  // <dir>
661  else if( nArgNum == 2 )
662  {
663  while( m_nTabIndex < arraysize(keywordsDir) )
664  {
665  s = keywordsDir[m_nTabIndex++];
666 
667  if( !strncmp(s, sText, uTextLen) )
668  {
669  return ReadLine::dupstr(s);
670  }
671  }
672  }
673 
674  // no more matches
675  return NULL;
676  }
677 
678 protected:
679  int m_nTabIter; ///< tab completion: servo id iterator
680  int m_nTabServoId; ///< tab completion: current servo id
681  int m_nTabIndex; ///< tab completion: keyword index
682 };
683 
684 
685 
686 // -----------------------------------------------------------------------------
687 // DynaShellCmdUnlink Class
688 // -----------------------------------------------------------------------------
689 
690 /*!
691  * \brief List command.
692  */
694 {
695 public:
696 
697  /*
698  * \brief Default constructor.
699  */
701  {
702  m_sCmdName = "unlink";
703  m_sCmdHelpBrief = "Unlink two servos.";
704  m_sCmdHelpArgs = "<master_id>";
705  m_sCmdHelpDesc = "Unlink two servos previously linked in a master-slave "
706  "configuration.\n"
707  " <master_id> Master servo id.";
708  }
709 
710  /*!
711  * \brief Unlink two servo.
712  *
713  * \param shell Dynamixel shell.
714  * \param argc Command argument count.
715  * \param argv Array of arguments.
716  */
717  void Exec(DynaShell &shell, int argc, char *argv[])
718  {
719  int nServoId;
720  int rc;
721 
722  TRY( ChkArgCnt(shell, argc) );
723 
724  TRY( ToInt(shell, argv[0], &nServoId) );
725 
726  TRY( ChkComm(shell) );
727  TRY( ChkChain(shell) );
728  TRY( ChkChainHasServo(shell, nServoId) );
729 
730  rc = shell.m_pDynaChain->UnlinkServos(nServoId);
731 
732  if( rc != DYNA_OK )
733  {
734  shell.Error(rc, "Cannot unlink servo %d.", nServoId);
735  }
736  else
737  {
738  shell.Ok();
739  }
740  }
741 
742  /*!
743  * \brief Command tab completion generator.
744  *
745  * Completes <master_id>
746  *
747  * \param shell Dynamixel shell.
748  * \param sText Partial text string to complete.
749  * \param uTextLen Length of text.
750  * \param nState Generator state. If FIRST, then initialize any statics.
751  * \param sContext Generator context (i.e. canonical command path).
752  *
753  * \return
754  * If a first/next match is made, return allocated completed match.\n
755  * Otherwise return NULL.
756  */
757  virtual char *TabCompletion(DynaShell &shell,
758  const char *sText,
759  size_t uTextLen,
760  int nState,
761  const char *sContext)
762  {
763  int nServoId;
764  const char *s;
765  char buf[16];
766 
767  if( (shell.m_pDynaChain == NULL) ||
768  (shell.m_pDynaChain->GetNumberInChain() == 0) )
769  {
770  return NULL;
771  }
772 
773  // argument number of already (expanded) arguments
774  else if( (ReadLine::wc(sContext) - ReadLine::wc(m_sPubName)) > 0 )
775  {
776  return NULL;
777  }
778 
779  //
780  // New command argument to complete - initialize.
781  //
782  if( nState == ReadLine::FIRST )
783  {
784  m_nTabServoId = shell.m_pDynaChain->IterStartMaster(&m_nTabIter);
785  }
786 
787  // <master_id>
788  while( m_nTabServoId != DYNA_ID_NONE )
789  {
790  nServoId = m_nTabServoId;
791 
792  m_nTabServoId = shell.m_pDynaChain->IterNextMaster(&m_nTabIter);
793 
794  if( !shell.m_pDynaChain->IsLinkedMaster(m_nTabServoId) )
795  {
796  continue;
797  }
798 
799  snprintf(buf, sizeof(buf), "%d", nServoId);
800  buf[sizeof(buf)-1] = 0;
801 
802  if( !strncmp(buf, sText, uTextLen) )
803  {
804  return ReadLine::dupstr(buf);
805  }
806  }
807 
808  // no more matches
809  return NULL;
810  }
811 
812 protected:
813  int m_nTabIter; ///< tab completion: servo id iterator
814  int m_nTabServoId; ///< tab completion: current servo id
815 };
816 
817 
818 // -----------------------------------------------------------------------------
819 // DynaShellCmdMegaScan Class
820 // -----------------------------------------------------------------------------
821 
822 /*!
823  * \brief MegaScan command.
824  */
826 {
827 public:
828 
829  /*
830  * \brief Default constructor.
831  */
833  {
834  m_sCmdName = "megascan";
835  m_sCmdHelpBrief = "Exhaustive scan for all connected servos.";
836  m_sCmdHelpArgs = "<uri>";
837  m_sCmdHelpDesc = "Scan the interface at all supported baud rates for "
838  "connected servos. The scan does not effect the "
839  "current dynamixel chain.\n"
840  " <uri> [botsense://[<hostname>][:<port>]]/<device>."
841  "\n\n"
842  "Note: The servos may respond to a different baudrate "
843  "other the what is saved\n"
844  " in the EEPROM.";
845  }
846 
847  /*
848  * \brief Default destructor.
849  */
850  virtual ~DynaShellCmdMegaScan() { }
851 
852  /*!
853  * \brief Scan interface at all supported baudrates for connected
854  * servos.
855  *
856  * \param shell Dynamixel shell.
857  * \param argc Command argument count.
858  * \param argv Array of arguments.
859  */
860  void Exec(DynaShell &shell, int argc, char *argv[])
861  {
862  static int baudTbl[] =
863  {
864  1000000, 500000, 400000, 250000, 200000, 115200, 57600, 19200, 9600
865  };
866 
867  char *sUri;
868  DynaComm *pComm;
869  int nBaudRate;
870  int i;
871  int nServoId;
872  uint_t cnt;
873  uint_t uModelNum;
874 
875  TRY( ChkArgCnt(shell, argc) );
876 
877  sUri = argv[0];
878 
879  shell.Response("Mega Scan on Interface %s.\n", sUri);
880 
881  for(i=0; i<arraysize(baudTbl); ++i)
882  {
883  shell.Response("%8d baudrate\n", baudTbl[i]);
884 
885  pComm = CommNew(shell, sUri, baudTbl[i]);
886 
887  if( pComm == NULL )
888  {
889  continue;
890  }
891 
892  for(nServoId=DYNA_ID_MIN, cnt=0; nServoId<DYNA_ID_NUMOF; ++nServoId)
893  {
894  if( pComm->Ping(nServoId) )
895  {
896  if( DynaServo::ReadModelNumber(*pComm, nServoId, &uModelNum) < 0 )
897  {
898  uModelNum = DYNA_MODEL_NUM_GENERIC;
899  }
900  shell.Response("%4d:0x%04x", nServoId, uModelNum);
901  fflush(stdout);
902  ++cnt;
903  if( (cnt % 5) == 0 )
904  {
905  shell.Response("\n");
906  }
907  }
908  }
909 
910  if( cnt > 0 )
911  {
912  if( (cnt % 5) != 0 )
913  {
914  shell.Response("\n");
915  }
916  shell.Response(" %d servos found @%d baudrate\n", cnt, baudTbl[i]);
917  }
918 
919  delete pComm;
920  }
921  }
922 
923  /*!
924  * \brief Command tab completion generator.
925  *
926  * Completes <device>
927  *
928  * \param shell Dynamixel shell.
929  * \param sText Partial text string to complete.
930  * \param uTextLen Length of text.
931  * \param nState Generator state. If FIRST, then initialize any statics.
932  * \param sContext Generator context (i.e. canonical command path).
933  *
934  * \return
935  * If a first/next match is made, return allocated completed match.\n
936  * Otherwise return NULL.
937  */
938  virtual char *TabCompletion(DynaShell &shell,
939  const char *sText,
940  size_t uTextLen,
941  int nState,
942  const char *sContext)
943  {
944  // <device>
945  return ReadLine::FileCompletionGenerator(sText, nState);
946  }
947 
948 protected:
949 
950  /*!
951  * \brief Create a new open dynamixel bus object.
952  *
953  * \param shell Dynamixel shell.
954  * \param sUri Dynamixel bus [proxied] device Uniform Resource Id.
955  * \param nBaudRate Device and servo baudrate.
956  *
957  * \return Returns new DynaComm object on success, NULL on failure.
958  */
959  DynaComm *CommNew(DynaShell &shell, const char *sUri, int nBaudRate)
960  {
961  DynaComm *pDynaComm = DynaComm::New(sUri, nBaudRate);
962 
963  if( pDynaComm == NULL )
964  {
965  shell.Error("Failed to create %s@%d.", sUri, nBaudRate);
966  }
967 
968  else if( !pDynaComm->IsOpen() )
969  {
970  shell.Error("Failed to open %s@%d.", sUri, nBaudRate);
971  delete pDynaComm;
972  pDynaComm = NULL;
973  }
974 
975  return pDynaComm;
976  }
977 };
978 
979 
980 // -----------------------------------------------------------------------------
981 // DynaShellCmdBgStart Class
982 // -----------------------------------------------------------------------------
983 
984 /*!
985  * \brief Start the background thread.
986  */
988 {
989 public:
990  /*
991  * \brief Default constructor.
992  */
994  {
995  m_sCmdName = "start";
996  m_sCmdHelpBrief = "Start the dynamixel background thread.";
997  m_sCmdHelpArgs = "[<hz>]";
998  m_sCmdHelpDesc = "Start the background thread with the given or default "
999  "control and monitor execute hertz.\n"
1000  " <hz> Execute hertz.\n"
1001  " Default: 50.0\n";
1002 
1003  SetTabTDefaults();
1004  }
1005 
1006  /*
1007  * \brief Default destructor.
1008  */
1009  virtual ~DynaShellCmdBgtStart() { }
1010 
1011  /*!
1012  * \brief Execute background thread start.
1013  *
1014  * \param shell Dynamixel shell.
1015  * \param argc Command argument count.
1016  * \param argv Array of arguments.
1017  */
1018  void Exec(DynaShell &shell, int argc, char *argv[])
1019  {
1020  int i;
1021  double val;
1022  double fHz;
1023 
1024  TRY( ChkArgCnt(shell, argc) );
1025 
1026  TRY( ChkComm(shell) );
1027  TRY( ChkChainNotEmpty(shell) );
1028 
1029  switch( shell.m_pDynaBgThread->GetCurrentState() )
1030  {
1033  break;
1035  default:
1036  shell.Error("Background thread already running. "
1037  "Try stopping first.");
1038  return;
1039  }
1040 
1041  if( argc > 0 )
1042  {
1043  TRY( ToDouble(shell, argv[0], &val) );
1044  fHz = val;
1045  }
1046  else
1047  {
1048  fHz = shell.m_pDynaBgThread->getHz();
1049  }
1050 
1051  shell.m_pDynaBgThread->setHz(fHz);
1052 
1053  shell.m_pDynaBgThread->Run();
1054 
1055  shell.Response("Background thread started.\n");
1056  }
1057 
1058  /*!
1059  * \brief Command tab completion generator.
1060  *
1061  * Completes t_posctl_dft|notask t_dynamics_dft|notask t_health_dft|notask
1062  *
1063  * \param shell Dynamixel shell.
1064  * \param sText Partial text string to complete.
1065  * \param uTextLen Length of text.
1066  * \param nState Generator state. If FIRST, then initialize any statics.
1067  * \param sContext Generator context (i.e. canonical command path).
1068  *
1069  * \return
1070  * If a first/next match is made, return allocated completed match.\n
1071  * Otherwise return NULL.
1072  */
1073  virtual char *TabCompletion(DynaShell &shell,
1074  const char *sText,
1075  size_t uTextLen,
1076  int nState,
1077  const char *sContext)
1078  {
1079  int nArgNum;
1080  char buf[16];
1081 
1082  if( (shell.m_pDynaChain == NULL) ||
1083  (shell.m_pDynaChain->GetNumberInChain() == 0) )
1084  {
1085  return NULL;
1086  }
1087 
1088  // argument number of already (expanded) arguments
1089  nArgNum = ReadLine::wc(sContext) - ReadLine::wc(m_sPubName);
1090 
1091  if( nArgNum > m_nArgCntMax )
1092  {
1093  return NULL;
1094  }
1095 
1096  //
1097  // New command to complete - initialize.
1098  //
1099  if( nState == ReadLine::FIRST )
1100  {
1101  m_nTabIndex = 0;
1102  }
1103 
1104  // can only expand default keyword
1105  while( m_nTabIndex < 2 )
1106  {
1107  ++m_nTabIndex;
1108 
1109  if( m_nTabIndex == 1 )
1110  {
1111  if( !strncmp(m_strTDefault.c_str(), sText, uTextLen) )
1112  {
1113  return ReadLine::dupstr(m_strTDefault);
1114  }
1115  }
1116  }
1117 
1118  // no more matches
1119  return NULL;
1120  }
1121 
1122 protected:
1123  int m_nTabIndex; ///< tab completion: index
1124  string m_strTDefault; ///< default time period value
1125 
1126  /*!
1127  * \brief Set tab completion time period default strings.
1128  */
1130  {
1131  char buf[32];
1132 
1133  snprintf(buf, sizeof(buf), "%lf", DynaBgThread::HZ_EXEC_DFT);
1134  buf[sizeof(buf)-1] = 0;
1135  m_strTDefault = buf;
1136  }
1137 };
1138 
1139 
1140 // -----------------------------------------------------------------------------
1141 // DynaShellCmdBgtStop Class
1142 // -----------------------------------------------------------------------------
1143 
1144 /*!
1145  * \brief Start the background thread.
1146  */
1148 {
1149 public:
1150  /*
1151  * \brief Default constructor.
1152  */
1154  {
1155  m_sCmdName = "stop";
1156  m_sCmdHelpBrief = "Stop the dynamixel background thread.";
1157  m_sCmdHelpArgs = "";
1158  m_sCmdHelpDesc = "The dynamixel background thread stopped. The thread is "
1159  "not destroyed, simply blocked, and can be resumed.";
1160  }
1161 
1162  /*
1163  * \brief Default destructor.
1164  */
1165  virtual ~DynaShellCmdBgtStop() { }
1166 
1167  /*!
1168  * \brief Execute background thread stop.
1169  *
1170  * \param shell Dynamixel shell.
1171  * \param argc Command argument count.
1172  * \param argv Array of arguments.
1173  */
1174  void Exec(DynaShell &shell, int argc, char *argv[])
1175  {
1176  TRY( ChkArgCnt(shell, argc) );
1177 
1178  TRY( ChkComm(shell) );
1179  TRY( ChkChainNotEmpty(shell) );
1180 
1181  switch( shell.m_pDynaBgThread->GetCurrentState() )
1182  {
1184  shell.m_pDynaBgThread->Stop();
1185  break;
1188  default:
1189  shell.Error("Background thread not running.");
1190  return;
1191  }
1192 
1193  shell.Response("Background thread stopped.\n");
1194  }
1195 
1196 protected:
1197 };
1198 
1199 
1200 // -----------------------------------------------------------------------------
1201 // DynaShellCmdBgtState Class
1202 // -----------------------------------------------------------------------------
1203 
1204 /*!
1205  * \brief Start the background thread.
1206  */
1208 {
1209 public:
1210  /*
1211  * \brief Default constructor.
1212  */
1214  {
1215  m_sCmdName = "get";
1216  m_sCmdHelpBrief = "Get the state of the dynamixel background thread.";
1217  m_sCmdHelpArgs = "";
1218  m_sCmdHelpDesc = "The dynamixel background thread state includes its "
1219  "operational state plus any task time periods.";
1220  }
1221 
1222  /*
1223  * \brief Default destructor.
1224  */
1225  virtual ~DynaShellCmdBgtGetState() { }
1226 
1227  /*!
1228  * \brief Execute background thread get state.
1229  *
1230  * \param shell Dynamixel shell.
1231  * \param argc Command argument count.
1232  * \param argv Array of arguments.
1233  */
1234  void Exec(DynaShell &shell, int argc, char *argv[])
1235  {
1236  const char *sState;
1237 
1238  TRY( ChkArgCnt(shell, argc) );
1239 
1240  TRY( ChkComm(shell) );
1241  TRY( ChkChainNotEmpty(shell) );
1242 
1243  switch( shell.m_pDynaBgThread->GetCurrentState() )
1244  {
1246  sState = "Zombie";
1247  break;
1249  sState = "Stopped";
1250  break;
1252  sState = "Running";
1253  break;
1255  sState = "Paused";
1256  break;
1258  sState = "Exiting";
1259  break;
1260  default:
1261  sState = "Unknown";
1262  break;
1263  }
1264 
1265  shell.Response("Background Thread: %s, Hz %lf.\n",
1266  sState, shell.m_pDynaBgThread->getHz());
1267  }
1268 
1269 protected:
1270 };
1271 
1272 
1273 // -----------------------------------------------------------------------------
1274 // DynaShellCmdSetHalfDuplexCtl Class
1275 // -----------------------------------------------------------------------------
1276 
1277 /*!
1278  * \brief Set halfduplex control command.
1279  */
1281 {
1282 public:
1283  /*
1284  * \brief Default constructor.
1285  */
1287  {
1288  m_sCmdName = "halfduplex";
1289  m_sCmdHelpBrief = "Set/unset sofware half-duplex control.";
1290  m_sCmdHelpArgs = "none\n"
1291  "modem {rts | cts}\n"
1292  "gpio <number>";
1293  m_sCmdHelpDesc = "Dynamixel 3-wire serial interface is a half-duplex "
1294  "channel. Software can control the channel direction by "
1295  "toggling between transmit and receive using a signal.\n"
1296  " Signaling types:\n"
1297  " none Disable software half-duplex control.\n"
1298  " modem Use built-in modem signal. Signals:\n"
1299  " rts - request to send.\n"
1300  " cts - clear to send.\n"
1301  " <gpio> Use GPIO signal (future).\n"
1302  " <number> - GPIO pin number. If negative,\n"
1303  " then transmit is active low.";
1304  }
1305 
1306  /*!
1307  * \brief Set software half-duplex control signal.
1308  *
1309  * \param shell Dynamixel shell.
1310  * \param argc Command argument count.
1311  * \param argv Array of arguments.
1312  */
1313  void Exec(DynaShell &shell, int argc, char *argv[])
1314  {
1315  int nSignal;
1316  int rc;
1317 
1318  TRY( ChkArgCnt(shell, argc) );
1319  TRY( ChkComm(shell) );
1320 
1321  if( !strncmp("none", argv[0], strlen(argv[0])) )
1322  {
1324  }
1325  else if( !strncmp("modem", argv[0], strlen(argv[0])) )
1326  {
1327  TRY( ChkArgCntEQ(shell, argc, 2) );
1328  if( !strncmp("cts", argv[1], strlen(argv[1])) )
1329  {
1331  }
1332  else if( !strncmp("rts", argv[1], strlen(argv[1])) )
1333  {
1335  }
1336  else
1337  {
1338  shell.Error(-DYNA_ECODE_BAD_VAL, "Unknown modem signal '%s'", argv[1]);
1339  return;
1340  }
1341  }
1342  else if( !strncmp("gpio", argv[0], strlen(argv[0])) )
1343  {
1344  TRY( ChkArgCntEQ(shell, argc, 2) );
1345  TRY( ToInt(shell, argv[1], &nSignal) );
1346  }
1347  else
1348  {
1349  shell.Error(-DYNA_ECODE_BAD_VAL, "Unknown signal type '%s'", argv[0]);
1350  return;
1351  }
1352 
1353  rc = shell.m_pDynaComm->SetHalfDuplexCtl(nSignal);
1354 
1355  if( rc != DYNA_OK )
1356  {
1357  shell.Error(rc, "Failed to set half-duplex %s signal control.", argv[0]);
1358  }
1359  else
1360  {
1361  shell.Ok();
1362  }
1363  }
1364 
1365  /*!
1366  * \brief Command tab completion generator.
1367  *
1368  * Completes none | modem sig | gpio number
1369  *
1370  * \param shell Dynamixel shell.
1371  * \param sText Partial text string to complete.
1372  * \param uTextLen Length of text.
1373  * \param nState Generator state. If FIRST, then initialize any statics.
1374  * \param sContext Generator context (i.e. canonical command path).
1375  *
1376  * \return
1377  * If a first/next match is made, return allocated completed match.\n
1378  * Otherwise return NULL.
1379  */
1380  virtual char *TabCompletion(DynaShell &shell,
1381  const char *sText,
1382  size_t uTextLen,
1383  int nState,
1384  const char *sContext)
1385  {
1386  static const char *keywordsSigType[] = {"gpio", "modem", "none"};
1387  static const char *keywordsSigModem[] = {"cts", "rts"};
1388  static char cSigType = '\0';
1389 
1390  int nArgNum;
1391  int nServoId;
1392  const char *s;
1393  char buf[16];
1394 
1395  // argument number of already (expanded) arguments
1396  nArgNum = ReadLine::wc(sContext) - ReadLine::wc(m_sPubName);
1397 
1398  //
1399  // New command argument to complete - initialize.
1400  //
1401  if( nState == ReadLine::FIRST )
1402  {
1403  m_nTabIndex = 0;
1404  }
1405 
1406  // gpio | modem | none
1407  if( nArgNum == 0 )
1408  {
1409  while( m_nTabIndex < arraysize(keywordsSigType) )
1410  {
1411  s = keywordsSigType[m_nTabIndex++];
1412 
1413  if( !strncmp(s, sText, uTextLen) )
1414  {
1415  cSigType = *s;
1416  return ReadLine::dupstr(s);
1417  }
1418  }
1419  }
1420 
1421  else if( nArgNum == 1 )
1422  {
1423  // rts | cts
1424  if( cSigType == 'm' )
1425  {
1426  while( m_nTabIndex < arraysize(keywordsSigModem) )
1427  {
1428  s = keywordsSigModem[m_nTabIndex++];
1429 
1430  if( !strncmp(s, sText, uTextLen) )
1431  {
1432  return ReadLine::dupstr(s);
1433  }
1434  }
1435  }
1436  // NUM
1437  else if( cSigType == 'g' )
1438  {
1439  }
1440  //
1441  else if( cSigType == 'n' )
1442  {
1443  }
1444  }
1445 
1446  // no more matches
1447  return NULL;
1448  }
1449 
1450 protected:
1451  int m_nTabIndex; ///< tab completion: keyword index
1452 };
1453 
1454 
1455 // -----------------------------------------------------------------------------
1456 // Public Interface.
1457 // -----------------------------------------------------------------------------
1458 
1459 /*!
1460  * \brief Publish shell dynamixel interface commands to shell.
1461  *
1462  * The dynamixel interface command set contains the top-level dynamixel
1463  * library semantic fundamentals.
1464  *
1465  * \brief shell Dynamixel shell.
1466  */
1468 {
1469  shell.PublishCommand(NULL, new DynaShellCmdCreate());
1470  shell.PublishCommand(NULL, new DynaShellCmdDestroy());
1471  shell.PublishCommand(NULL, new DynaShellCmdScan());
1472  shell.PublishCommand(NULL, new DynaShellCmdPing());
1473  shell.PublishCommand(NULL, new DynaShellCmdList());
1474  shell.PublishCommand(NULL, new DynaShellCmdLink());
1475  shell.PublishCommand(NULL, new DynaShellCmdUnlink());
1476  shell.PublishCommand(NULL, new DynaShellCmdMegaScan());
1477  shell.PublishCommand("bg", new DynaShellCmdBgtStart());
1478  shell.PublishCommand("bg", new DynaShellCmdBgtStop());
1479  shell.PublishCommand("bg", new DynaShellCmdBgtGetState());
1480  shell.PublishCommand("set", new DynaShellCmdSetHalfDuplexCtl());
1481 }
RoadNarrows Dynamixel Bus Communications Abstract Base Class Interface.
virtual uint_t GetServoMode() const
Get the servo operational mode.
Definition: DynaServo.h:165
Destroy command.
virtual void RegisterChainAgent(DynaChain *pChain)
Register the Dynamixel chain for control and monitoring.
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
BgThreadState
Background thread states.
Definition: DynaBgThread.h:251
zombie instance - no thread exists
Definition: DynaBgThread.h:253
#define DYNA_MODEL_NUM_GENERIC
generic, base model
Definition: Dynamixel.h:119
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
int GetLinkedMateId(int nServoId) const
Get linked mate.
Definition: DynaChain.h:238
void Exec(DynaShell &shell, int argc, char *argv[])
List servo chain info.
#define DYNA_MODE_SERVO
servo mode with limited rotation
Definition: Dynamixel.h:170
Dynamixel shell utilities.
DynaComm * m_pDynaComm
dynamixel bus communication
Definition: dynashell.h:359
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
thread created and ready to run
Definition: DynaBgThread.h:254
void Exec(DynaShell &shell, int argc, char *argv[])
Execute background thread stop.
void Exec(DynaShell &shell, int argc, char *argv[])
Create dynamixel interface.
void SetTabTDefaults()
Set tab completion time period default strings.
static int ReadModelNumber(DynaComm &comm, int nServoId, uint_t *pModelNum)
Read the servo model number from the servo&#39;s EEPROM.
Definition: DynaServo.cxx:256
BgThreadState GetCurrentState()
Get current background thread state.
Definition: DynaBgThread.h:415
Start the background thread.
bool IsUnlinked(int nServoId) const
Test if this servo is unlinked.
Definition: DynaChain.h:224
#define DELOBJ(p)
Delete an allocated object convenience macro.
RoadNarrows Dynamixel Servo Chain Container Base Class Interface.
static const int FIRST
first state
not a signal, but a value to clear signal
Create command.
bool IsLinkedMaster(int nServoId) const
Test if this servo is a linked master.
Definition: DynaChain.h:196
#define DYNA_ID_MIN
minimum servo id
Definition: Dynamixel.h:146
virtual uint_t GetFirmwareVersion() const
Get servo firmware version.
Definition: DynaServo.h:135
static char * dupstr(const string &str)
Duplicate string.
virtual bool Ping(int nServoId)=0
Ping the servo.
Dynamixel shell command abstract base class.
Definition: dynashell_cmd.h:80
DynaComm * CommNew(DynaShell &shell, const char *sUri, int nBaudRate)
Create a new open dynamixel bus object.
virtual int IterStartMaster(int *pIter)
Start iteration master servos over of entire servo chain.
Definition: DynaChain.cxx:1036
#define DYNA_ID_NUMOF
number of unique servo id&#39;s
Definition: Dynamixel.h:148
static const double HZ_EXEC_DFT
default exec hertz
Definition: DynaBgThread.h:244
virtual int IterNextMaster(int *pIter)
Next iteration of master servos over of entire servo chain.
Definition: DynaChain.cxx:1058
virtual uint_t GetNumberInChain() const
Get the number of servos currently in chain.
Definition: DynaChain.h:140
virtual int LinkServos(int nServoIdMaster, int nServoIdSlave, bool bIsReversed)
Software link two unlinked servos in a master-slave configuration.
Definition: DynaChain.cxx:105
virtual int Run()
Run the background thread control and monitoring tasks.
MegaScan command.
double getHz()
Get control and monitoring hetrz rate.
Definition: DynaBgThread.h:457
Start the background thread.
Dynamixel Servo Abstract Base Class.
Definition: DynaServo.h:78
Dynamixel background thread class declarations.
virtual int AddNewServosByScan()
Scan and add all discovered and created servos to the Dynamixel chain.
Definition: DynaChain.cxx:229
virtual int Stop()
Stop control and monitoring tasks.
virtual void UnregisterAgent()
Unregister any chain or servo from control and monitoring.
DynaComm * CommNew(DynaShell &shell, const char *sUri, int nBaudRate)
Create a new open dynamixel bus object.
static DynaComm * New(const char *sUri, int nBaudRate)
Archetype constructor to create a new Dynamixel bus communication derived instance.
Definition: DynaComm.cxx:179
Set halfduplex control command.
static int wc(const string &str)
Count the words in the string.
void Response(const char *sFmt,...)
Print formatted success response.
Definition: dynashell.cxx:763
virtual void Ok()
Print standard ok success response.
Definition: dynashell.h:425
Start the background thread.
void PublishShellInterfaceCommands(DynaShell &shell)
Publish shell dynamixel interface commands to shell.
virtual int SetHalfDuplexCtl(int nSignal, HalfDuplexTxFunc_T fnEnableTx=NULL, HalfDuplexRxFunc_T fnEnableRx=NULL)=0
string m_strTDefault
default time period value
void Exec(DynaShell &shell, int argc, char *argv[])
Scan interface at all supported baudrates for connected servos.
void Exec(DynaShell &shell, int argc, char *argv[])
Scan for all connected servos and add to chain.
void Exec(DynaShell &shell, int argc, char *argv[])
Ping a servo.
RoadNarrows Dynamixel Bus Communication over Serial Interface Class Interface.
virtual int IterStart(int *pIter)
Start iteration over of entire servo chain.
Definition: DynaChain.cxx:1008
virtual DynaServo * GetServo(int nServoId)
Definition: DynaChain.h:129
Dynamixel Chain Container Base Class.
Definition: DynaChain.h:75
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
int m_nTabIndex
tab completion: index
void Exec(DynaShell &shell, int argc, char *argv[])
Execute background thread get state.
DynaBgThread * m_pDynaBgThread
dynamixel chain
Definition: dynashell.h:361
RoadNarrows Dynamixel Archetype Servo Abstract Base Class.
bool IsLinkedSlave(int nServoId) const
Test if this servo is a linked slave.
Definition: DynaChain.h:211
void Exec(DynaShell &shell, int argc, char *argv[])
Set software half-duplex control signal.
#define TRY(boolexpr,...)
Try boolean expression.
Definition: dynashell_cmd.h:89
void PublishCommand(const char *sParent, DynaShellCmd *pNewCmd)
Publish new command to shell.
Definition: dynashell.cxx:192
RoadNarrows Dynamixel Top-Level Package Header File.
virtual uint_t GetModelNumber() const
Get servo model number.
Definition: DynaServo.h:125
The dynashell Command Class Interface.
void Exec(DynaShell &shell, int argc, char *argv[])
Destroy dynamixel interface.
#define DYNA_ID_NONE
no servo id
Definition: Dynamixel.h:145
void setHz(double fHz)
Set new control and monitoring execution hertz rate.
void Exec(DynaShell &shell, int argc, char *argv[])
Execute background thread start.
virtual int UnlinkServos(int nServoIdMaster)
Unlink two software linked servos.
Definition: DynaChain.cxx:146
virtual int IterNext(int *pIter)
Next iteration over of entire servo chain.
Definition: DynaChain.cxx:1020
#define DYNA_ECODE_BAD_VAL
bad value
Definition: Dynamixel.h:85
DynaChain * m_pDynaChain
dynamixel chain
Definition: dynashell.h:360
void Error(int rc, const char *sFmt,...)
Raise error on dynamixel error code.
Definition: dynashell.cxx:808
virtual const char * GetModelName() const
Get servo model name string.
Definition: DynaServo.h:145
static char * FileCompletionGenerator(const char *sText, int nState)
File name tab completion generator.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
int m_nTabIndex
tab completion: keyword index
int m_nTabIter
tab completion: baud rate iterator
The simple dynashell declarations.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
Dynamixel Bus Communications Abstract Base Class.
Definition: DynaComm.h:80