Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
dynashell_cmd_servo.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // Program: dynashell
6 //
7 // File: dynashell_servo.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-01-12 10:56:06 -0700 (Mon, 12 Jan 2015) $
12  * $Rev: 3845 $
13  *
14  * \brief The Dynamixel Shell Servo 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 #include <cstring>
50 #include <iostream>
51 #include <fstream>
52 #include <string>
53 #include <vector>
54 
55 #include "rnr/rnrconfig.h"
56 #include "rnr/log.h"
57 
58 #include "Dynamixel/Dynamixel.h"
59 #include "Dynamixel/DynaComm.h"
60 #include "Dynamixel/DynaChain.h"
61 
62 #include "dynashell.h"
63 #include "dynashell_cmd.h"
64 #include "dynashell_util.h"
65 
66 using namespace std;
67 
68 /*!
69  * \brief Convert rotation direction to string.
70  *
71  * \param nSpeed Speed.
72  *
73  * \return Short string.
74  */
75 inline const char *rotdirstr(int nSpeed)
76 {
77  if( nSpeed < 0 )
78  {
79  return "(cw)";
80  }
81  else if( nSpeed == 0 )
82  {
83  return "";
84  }
85  else
86  {
87  return "(ccw)";
88  }
89 }
90 
91 
92 // -----------------------------------------------------------------------------
93 // DynaShellCmdMoveTo Class
94 // -----------------------------------------------------------------------------
95 
96 /*!
97  * \brief Determine if servos are moving.
98  */
100 {
101 public:
102 
103  /*
104  * \brief Default constructor.
105  */
107  {
108  m_sCmdName = "moveto";
109  m_sCmdHelpBrief = "Move servos to goal positions.";
110  m_sCmdHelpArgs = "<servo_id> <pos> [<servo_id> <pos> ...]\n"
111  "chain <pos>";
112  m_sCmdHelpDesc = "Move the specified servos to the goal positions. "
113  "If more than one servo is specifed then a synchronous "
114  "move will be automatically performed. "
115  "If the keyword 'chain' is specified, then all servos in "
116  "the chain are synchronously moved.\n"
117  " <servo_id> Servo id [0-253].\n"
118  " <pos> Odometer goal position.";
119  }
120 
121  /*
122  * \brief Default destructor.
123  */
124  virtual ~DynaShellCmdMoveTo() { }
125 
126 protected:
127  /*!
128  * \brief Move servos to goal positions.
129  *
130  * \param shell Dynamixel shell.
131  * \param tup Array of (servo id, goal position) 2-tuples.
132  * \param uCount Number of tuples.
133  */
134  virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
135  {
136  uint_t i;
137  int rc;
138 
139  if( uCount == 1 )
140  {
141  rc = shell.m_pDynaChain->MoveTo(tup[0].m_nServoId, tup[0].m_nVal);
142 
143  if( rc != DYNA_OK )
144  {
145  shell.Error(rc, "Servo %d: move to %d failed.",
146  tup[0].m_nServoId, tup[0].m_nVal);
147  }
148  }
149  else // > 1
150  {
151  DynaPosTuple_T tupPos[uCount];
152 
153  for(i=0; i<uCount; ++i)
154  {
155  tupPos[i].m_nServoId = tup[i].m_nServoId;
156  tupPos[i].m_nPos = tup[i].m_nVal;
157  }
158 
159  rc = shell.m_pDynaChain->SyncMoveTo(tupPos, uCount);
160 
161  if( rc != DYNA_OK )
162  {
163  shell.Error(rc, "Synchronous move of %u servos failed.", uCount);
164  }
165  }
166  }
167 };
168 
169 
170 // -----------------------------------------------------------------------------
171 // DynaShellCmdMoveAtSpeedTo Class
172 // -----------------------------------------------------------------------------
173 
174 /*!
175  * \brief Determine if servos are moving.
176  */
178 {
179 public:
180 
181  /*
182  * \brief Default constructor.
183  */
185  {
186  m_sCmdName = "moveatspeedto";
187  m_sCmdHelpBrief = "Move servos at speeds to goal positions.";
188  m_sCmdHelpArgs = "<servo_id> <speed> <pos> [<servo_id> <speed> "
189  "<pos> ...]\n"
190  "chain <speed> <pos>";
191  m_sCmdHelpDesc = "Move the specified servos to the goal positions at the "
192  "given speeds. "
193  "If more than one servo is specifed then a synchronous "
194  "move will be automatically performed. "
195  "If the keyword 'chain' is specified, then all servos in "
196  "the chain are synchronously moved.\n"
197  " <servo_id> Servo id [0-253].\n"
198  " <speed> Servo goal speed.\n"
199  " <pos> Odometer goal position.";
200  }
201 
202  /*
203  * \brief Default destructor.
204  */
205  virtual ~DynaShellCmdMoveAtSpeedTo() { }
206 
207  /*!
208  * \brief Execute 'write-like' command on servos.
209  *
210  * \param shell Dynamixel shell.
211  * \param argc Command argument count.
212  * \param argv Array of arguments.
213  */
214  void Exec(DynaShell &shell, int argc, char *argv[])
215  {
216  uint_t uNumPairs;
218  int nServoId;
219  int nSpeed;
220  int nPos;
221  int iter;
222  int cnt;
223 
224  TRY( ChkArgCnt(shell, argc) );
225 
226  if( (argc % 3) != 0 )
227  {
228  shell.Error("Unmatched servo_id,speed,pos triplets.");
229  return;
230  }
231 
232  uNumPairs = (uint_t)(argc / 3);
233 
234  if( uNumPairs > DYNA_ID_NUMOF )
235  {
236  shell.Error("%u: Too many servo_id,speed,pos triplets.", uNumPairs);
237  return;
238  }
239 
240  TRY( ChkComm(shell) );
241  TRY( ChkChainNotEmpty(shell) );
242 
243  // full chain of servos
244  if( !strcmp(argv[0], "chain") )
245  {
246  TRY( ChkArgCntEQ(shell, argc, 3) );
247  TRY( ToInt(shell, argv[1], &nSpeed) );
248  TRY( ToInt(shell, argv[2], &nPos) );
249 
250  for(nServoId = shell.m_pDynaChain->IterStartMaster(&iter), cnt=0;
251  nServoId != DYNA_ID_NONE;
252  nServoId = shell.m_pDynaChain->IterNextMaster(&iter), ++cnt)
253  {
254  tup[cnt].m_nServoId = nServoId;
255  tup[cnt].m_nSpeed = nSpeed;
256  tup[cnt].m_nPos = nPos;
257  }
258 
259  uNumPairs = (uint_t)cnt;
260  }
261 
262  // list of servos
263  else
264  {
265  for(iter=0, cnt=0; iter<argc; iter+=3, ++cnt)
266  {
267  TRY( ToInt(shell, argv[iter], &nServoId) );
268  TRY( ToInt(shell, argv[iter+1], &nSpeed) );
269  TRY( ToInt(shell, argv[iter+2], &nPos) );
270  TRY( ChkChainHasServo(shell, nServoId) );
271  TRY( ChkChainIsMasterServo(shell, nServoId) );
272 
273  tup[cnt].m_nServoId = nServoId;
274  tup[cnt].m_nSpeed = nSpeed;
275  tup[cnt].m_nPos = nPos;
276  }
277  }
278 
279  doExec(shell, tup, uNumPairs);
280  }
281 
282 protected:
283  /*!
284  * \brief Move servos to goal positions.
285  *
286  * \param shell Dynamixel shell.
287  * \param tup Array of (servo id, goal position) 2-tuples.
288  * \param uCount Number of tuples.
289  */
290  virtual void doExec(DynaShell &shell,
291  DynaSpeedPosTuple_T tup[],
292  uint_t uCount)
293  {
294  int rc;
295 
296  if( uCount == 1 )
297  {
298  rc = shell.m_pDynaChain->MoveAtSpeedTo(tup[0].m_nServoId,
299  tup[0].m_nSpeed,
300  tup[0].m_nPos);
301 
302  if( rc != DYNA_OK )
303  {
304  shell.Error(rc, "Servo %d: move at speed %d to %d failed.",
305  tup[0].m_nServoId, tup[0].m_nSpeed, tup[0].m_nPos);
306  }
307  }
308  else // > 1
309  {
310  rc = shell.m_pDynaChain->SyncMoveAtSpeedTo(tup, uCount);
311 
312  if( rc != DYNA_OK )
313  {
314  shell.Error(rc, "Synchronous move at speed of %u servos failed.",
315  uCount);
316  }
317  }
318  }
319 };
320 
321 
322 // -----------------------------------------------------------------------------
323 // DynaShellCmdEStop Class
324 // -----------------------------------------------------------------------------
325 
326 /*!
327  * \brief Emergency stop command.
328  */
330 {
331 public:
332 
333  /*
334  * \brief Default constructor.
335  */
337  {
338  m_sCmdName = "estop";
339  m_sCmdHelpBrief = "Emergency stop all servos.";
340  m_sCmdHelpArgs = "";
341  m_sCmdHelpDesc = "";
342  }
343 
344  /*
345  * \brief Default destructor.
346  */
347  virtual ~DynaShellCmdEStop() { }
348 
349  /*!
350  * \brief Emergence stop all servos.
351  *
352  * \param shell Dynamixel shell.
353  * \param argc Command argument count.
354  * \param argv Array of arguments.
355  */
356  void Exec(DynaShell &shell, int argc, char *argv[])
357  {
358  int rc;
359 
360  TRY( ChkComm(shell) );
361  TRY( ChkChain(shell) );
362 
363  rc = shell.m_pDynaChain->EStop();
364 
365  if( rc == DYNA_OK )
366  {
367  shell.Ok();
368  }
369  else
370  {
371  shell.Error(rc, "Emergency stop failed.");
372  }
373  }
374 };
375 
376 
377 // -----------------------------------------------------------------------------
378 // DynaShellCmdStop Class
379 // -----------------------------------------------------------------------------
380 
381 /*!
382  * \brief Stop servo(s) command.
383  */
385 {
386 public:
387 
388  /*
389  * \brief Default constructor.
390  */
392  {
393  m_sCmdName = "stop";
394  m_sCmdHelpBrief = "Stop servo movement.";
395  m_sCmdHelpArgs = "<servo_id [<servo_id ...]\nchain";
396  m_sCmdHelpDesc = "Stop the movement of the specified servos. "
397  "If the keyword 'chain' is specified, then all servos "
398  "in the chain are stopped.\n"
399  " <servo_id> Servo id [0-253].";
400  }
401 
402  /*
403  * \brief Default destructor.
404  */
405  virtual ~DynaShellCmdStop() { }
406 
407 protected:
408  virtual void doExec(DynaShell &shell, DynaServo *pServo)
409  {
410  pServo->Stop();
411  }
412 };
413 
414 
415 // -----------------------------------------------------------------------------
416 // DynaShellCmdFreeze Class
417 // -----------------------------------------------------------------------------
418 
419 /*!
420  * \brief Freeze command.
421  */
423 {
424 public:
425 
426  /*
427  * \brief Default constructor.
428  */
430  {
431  m_sCmdName = "freeze";
432  m_sCmdHelpBrief = "Freeze all servos.";
433  m_sCmdHelpArgs = "";
434  m_sCmdHelpDesc = "Freeze all servos at the current positions. Torque is "
435  "applied to keep the positions.";
436  }
437 
438  /*
439  * \brief Default destructor.
440  */
441  virtual ~DynaShellCmdFreeze() { }
442 
443  /*!
444  * \brief Freeze servos.
445  *
446  * \param shell Dynamixel shell.
447  * \param argc Command argument count.
448  * \param argv Array of arguments.
449  */
450  void Exec(DynaShell &shell, int argc, char *argv[])
451  {
452  int rc;
453 
454  TRY( ChkArgCnt(shell, argc) );
455  TRY( ChkComm(shell) );
456  TRY( ChkChainNotEmpty(shell) );
457 
458  rc = shell.m_pDynaChain->Freeze();
459 
460  if( rc == DYNA_OK )
461  {
462  shell.Ok();
463  }
464  else
465  {
466  shell.Error(rc, "Freeze failed.");
467  }
468  }
469 };
470 
471 
472 // -----------------------------------------------------------------------------
473 // DynaShellCmdRelease Class
474 // -----------------------------------------------------------------------------
475 
476 /*!
477  * \brief Release command.
478  */
480 {
481 public:
482 
483  /*
484  * \brief Default constructor.
485  */
487  {
488  m_sCmdName = "release";
489  m_sCmdHelpBrief = "Release all servos.";
490  m_sCmdHelpArgs = "";
491  m_sCmdHelpDesc = "Release all servos. No torque is applied.";
492  }
493 
494  /*
495  * \brief Default destructor.
496  */
497  virtual ~DynaShellCmdRelease() { }
498 
499  /*!
500  * \brief Release servos.
501  *
502  * \param shell Dynamixel shell.
503  * \param argc Command argument count.
504  * \param argv Array of arguments.
505  */
506  void Exec(DynaShell &shell, int argc, char *argv[])
507  {
508  int rc;
509 
510  TRY( ChkArgCnt(shell, argc) );
511  TRY( ChkComm(shell) );
512  TRY( ChkChainNotEmpty(shell) );
513 
514  rc = shell.m_pDynaChain->Release();
515 
516  if( rc == DYNA_OK )
517  {
518  shell.Ok();
519  }
520  else
521  {
522  shell.Error(rc, "Release failed.");
523  }
524  }
525 };
526 
527 
528 // -----------------------------------------------------------------------------
529 // DynaShellCmdGetOdometer Class
530 // -----------------------------------------------------------------------------
531 
532 /*!
533  * \brief Read servos goal positions.
534  */
536 {
537 public:
538 
539  /*
540  * \brief Default constructor.
541  */
543  {
544  m_sCmdName = "odometer";
545  m_sCmdHelpBrief = "Get servo odometer parameters.";
546  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
547  m_sCmdHelpDesc = "Get the servo odometer zero point, modulo, and reverse "
548  "parameters. If the keyword 'chain' is specified, then "
549  "the odometer settings for all of the servos in the "
550  "chain are read.\n"
551  " <servo_id> Servo id [0-253].";
552  }
553 
554  /*
555  * \brief Default destructor.
556  */
557  virtual ~DynaShellCmdGetOdometer() { }
558 
559 protected:
560 
561  /*!
562  * \brief Determine torque enable state for servo.
563  *
564  * \param shell Dynamixel shell.
565  * \param pServo Pointer to servo.
566  */
567  virtual void doExec(DynaShell &shell, DynaServo *pServo)
568  {
569  int nOdometer;
570  int nOdZeroPt;
571  bool bOdReversed;
572 
573  nOdometer = pServo->GetOdometer();
574  nOdZeroPt = pServo->GetOdometerZeroPt();
575  bOdReversed = pServo->IsOdometerReversed();
576 
577  shell.Response("Servo %3d: odometer %5d, zeropt %4d, reverse: %s\n",
578  pServo->GetServoId(), nOdometer, nOdZeroPt,
579  (bOdReversed? "true": "false"));
580  }
581 };
582 
583 
584 // -----------------------------------------------------------------------------
585 // DynaShellCmdSetOdometer Class
586 // -----------------------------------------------------------------------------
587 
588 /*!
589  * \brief Determine if servos are moving.
590  */
592 {
593 public:
594 
595  /*
596  * \brief Default constructor.
597  */
599  {
600  m_sCmdName = "odometer";
601  m_sCmdHelpBrief = "Set odometer parameters.";
602  m_sCmdHelpArgs = "<servo_id> <zeropt> <modulo> <reverse>";
603  m_sCmdHelpDesc = "Set servo virtual odometer parameters.\n"
604  " <servo_id> Servo id [0-253].\n"
605  " <zeropt> Zero point in encoder units.\n"
606  " <reverse> Odometer is [not] reversed. One of: "
607  "t true 1 f false 0";
608  }
609 
610  /*
611  * \brief Default destructor.
612  */
613  virtual ~DynaShellCmdSetOdometer() { }
614 
615  /*!
616  * \brief Execute 'write-like' command on servos.
617  *
618  * \param shell Dynamixel shell.
619  * \param argc Command argument count.
620  * \param argv Array of arguments.
621  */
622  void Exec(DynaShell &shell, int argc, char *argv[])
623  {
624  int nServoId;
625  int nOdZeroPt;
626  bool bOdReversed;
627  DynaServo *pServo;
628 
629  TRY( ChkArgCnt(shell, argc) );
630 
631  TRY( ChkComm(shell) );
632  TRY( ChkChainNotEmpty(shell) );
633 
634  TRY( ToInt(shell, argv[0], &nServoId) );
635  TRY( ToInt(shell, argv[1], &nOdZeroPt) );
636  TRY( ToBool(shell, argv[2], &bOdReversed) );
637  TRY( ChkChainHasServo(shell, nServoId) );
638  TRY( ChkChainIsMasterServo(shell, nServoId) );
639 
640  pServo = shell.m_pDynaChain->GetServo(nServoId);
641 
642  if( pServo == NULL )
643  {
644  shell.Error("Servo %d: Servo not found.\n");
645  }
646  else
647  {
648  pServo->ResetOdometer(nOdZeroPt, bOdReversed);
649  shell.Ok();
650  }
651  }
652 
653 protected:
654 };
655 
656 
657 // -----------------------------------------------------------------------------
658 // DynaShellCmdCfgWriteServoMode Class
659 // -----------------------------------------------------------------------------
660 
661 /*!
662  * \brief Write EEPROM configuration to put servos into the given modes.
663  *
664  * \par Syntax:
665  * \verbatim
666  * arg_to_uint ::= mode
667  * mode ::= 'c' | 'cont' | 'continuous' | 's' | 'servo'
668  * \endverbatim
669  */
671 {
672 public:
673  /*!
674  * \brief Default constructor.
675  */
677  {
678  m_sCmdName = "mode";
679  m_sCmdHelpBrief = "Configure servo operational modes.";
680  m_sCmdHelpArgs = "<servo_id> <mode> [<servo_id> <mode> ...]\n"
681  "chain <mode>";
682  m_sCmdHelpDesc = "Configure the operational modes of the specified "
683  "servos. The servo configuration is written to the servo "
684  "EEPROM. If the keyword 'chain' is specified, then all "
685  "servos in the chain are configured.\n"
686  " <servo_id> Servo id [0-253].\n"
687  " <mode> Servo mode. One of: continuous servo.";
688  }
689 
690  /*!
691  * \brief Default destructor.
692  */
694 
695 protected:
696  /*!
697  * \brief Execute operation.
698  *
699  * \param shell Dynamixel shell.
700  * \param tup Array of (servo id, mode) 2-tuples.
701  * \param uCount Number of tuples.
702  */
703  virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
704  {
705  DynaServo *pServo;
706  DynaServoSpec_T spec;
707  uint_t i;
708  int rc;
709 
710  for(i=0, rc=DYNA_OK; i<uCount && rc==DYNA_OK; ++i)
711  {
712  pServo = shell.m_pDynaChain->GetServo(tup[i].m_nServoId);
713 
714  switch( tup[i].m_nVal )
715  {
717  rc = pServo->CfgWriteServoModeContinuous();
718  break;
719 
720  case DYNA_MODE_SERVO:
721  default:
722  spec = pServo->GetSpecification();
723  rc = pServo->CfgWriteServoMode(spec.m_uRawPosMin, spec.m_uRawPosMax);
724  break;
725  }
726  }
727 
728  if( rc != DYNA_OK )
729  {
730  shell.Error(rc, "Servo %d: Failed to set mode to %d.",
731  pServo->GetServoId(), tup[i].m_nVal);
732  }
733  }
734 
735  /*!
736  * \brief Convert command argument into servo mode.
737  *
738  * \param shell Dynamixel shell.
739  * \param sArg String argument to convert.
740  * \param [out] pVal Converted argument.
741  *
742  * \return Returns true on success, false otherwise.
743  */
744  virtual bool ArgToInt(DynaShell &shell, const char *sArg, int *pVal)
745  {
746  size_t n = strlen(sArg);
747 
748  if( !strncmp("continuous", sArg, n) )
749  {
750  *pVal = DYNA_MODE_CONTINUOUS;
751  return true;
752  }
753  else if( !strncmp("servo", sArg, n) )
754  {
755  *pVal = DYNA_MODE_SERVO;
756  return true;
757  }
758  else
759  {
760  shell.Error("Argument value \"%s\": Not a servo mode.", sArg);
761  return false;
762  }
763  }
764 };
765 
766 
767 // -----------------------------------------------------------------------------
768 // DynaShellCmdReadTorqueEnable Class
769 // -----------------------------------------------------------------------------
770 
771 /*!
772  * \brief Read servos goal positions.
773  */
775 {
776 public:
777 
778  /*
779  * \brief Default constructor.
780  */
782  {
783  m_sCmdName = "torqueenable";
784  m_sCmdHelpBrief = "Read servo torque enable states.";
785  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
786  m_sCmdHelpDesc = "Read the servo torque enable states for the specified "
787  "servos. If the keyword 'chain' is specified, then the "
788  "torque enable states for all of the servos in the "
789  "chain are read.\n"
790  " <servo_id> Servo id [0-253].";
791  }
792 
793  /*
794  * \brief Default destructor.
795  */
796  virtual ~DynaShellCmdReadTorqueEnable() { }
797 
798 protected:
799 
800  /*!
801  * \brief Determine torque enable state for servo.
802  *
803  * \param shell Dynamixel shell.
804  * \param pServo Pointer to servo.
805  */
806  virtual void doExec(DynaShell &shell, DynaServo *pServo)
807  {
808  bool bTorqueEnable;
809  int rc;
810 
811  rc = pServo->ReadTorqueEnable(&bTorqueEnable);
812 
813  if( rc != DYNA_OK )
814  {
815  shell.Error(rc, "Servo %d: Read torque enable failed.",
816  pServo->GetServoId());
817  return;
818  }
819 
820  shell.Response("Servo %3d: %s\n", pServo->GetServoId(),
821  (bTorqueEnable? "enabled": "disabled"));
822  }
823 };
824 
825 
826 // -----------------------------------------------------------------------------
827 // DynaShellCmdWriteTorqueEnable Class
828 // -----------------------------------------------------------------------------
829 
830 /*!
831  * \brief Determine if servos are moving.
832  */
834 {
835 public:
836 
837  /*
838  * \brief Default constructor.
839  */
841  {
842  m_sCmdName = "torqueenable";
843  m_sCmdHelpBrief = "Enable/disable servo torques.";
844  m_sCmdHelpArgs = "<servo_id> <switch> [<servo_id> <switch> ...]\n"
845  "chain <switch>";
846  m_sCmdHelpDesc = "Enable or disable servo torques for the specified "
847  "servos. If the keyword 'chain' is specified, then all "
848  "servos in the chain are set.\n";
849  " <servo_id> Servo id [0-253].\n"
850  " <switch>: One of: enable e on true 1"
851  "disable d off false 0";
852  }
853 
854  /*
855  * \brief Default destructor.
856  */
857  virtual ~DynaShellCmdWriteTorqueEnable() { }
858 
859 protected:
860  /*!
861  * \brief Enable/disable servos torques.
862  *
863  * \param shell Dynamixel shell.
864  * \param tup Array of (servo id, goal position) 2-tuples.
865  * \param uCount Number of tuples.
866  */
867  virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
868  {
869  uint_t i;
870  DynaServo *pServo;
871  bool state;
872  int rc;
873 
874  for(i=0, rc=DYNA_OK; i<uCount && i==DYNA_OK; ++i)
875  {
876  pServo = shell.m_pDynaChain->GetServo(tup[i].m_nServoId);
877  state = tup[i].m_nVal? true: false;
878 
879  rc = pServo->WriteTorqueEnable(state);
880 
881  if( rc != DYNA_OK )
882  {
883  shell.Error(rc,
884  "Servo %d: Failed to set torque enable state.",
885  pServo->GetServoId());
886  }
887  }
888  }
889 
890  /*!
891  * \brief Convert command argument into enable state.
892  *
893  * \param shell Dynamixel shell.
894  * \param sArg String argument to convert.
895  * \param [out] pVal Converted argument.
896  *
897  * \return Returns true on success, false otherwise.
898  */
899  virtual bool ArgToInt(DynaShell &shell, const char *sArg, int *pVal)
900  {
901  if( !strcmp(sArg, "e") || !strcmp(sArg, "enable") ||
902  !strcmp(sArg, "on") || !strcmp(sArg, "true") ||
903  !strcmp(sArg, "1") )
904  {
905  *pVal = 1;
906  return true;
907  }
908  else if( !strcmp(sArg, "d") || !strcmp(sArg, "disable") ||
909  !strcmp(sArg, "off") || !strcmp(sArg, "false") ||
910  !strcmp(sArg, "0") )
911  {
912  *pVal = 0;
913  return true;
914  }
915  else
916  {
917  shell.Error("Argument value \"%s\": Invalid state.", sArg);
918  return false;
919  }
920  }
921 };
922 
923 
924 // -----------------------------------------------------------------------------
925 // DynaShellCmdReadGoalPos Class
926 // -----------------------------------------------------------------------------
927 
928 /*!
929  * \brief Read servos goal positions.
930  */
932 {
933 public:
934 
935  /*
936  * \brief Default constructor.
937  */
939  {
940  m_sCmdName = "goalpos";
941  m_sCmdHelpBrief = "Read servo goal positions.";
942  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
943  m_sCmdHelpDesc = "Read servo goal positions for all of the specified "
944  "servos. If the keyword 'chain' is specified, then the "
945  "goal positions for all of the servos in the chain are "
946  "read.\n"
947  " <servo_id> Servo id [0-253].";
948  }
949 
950  /*
951  * \brief Default destructor.
952  */
953  virtual ~DynaShellCmdReadGoalPos() { }
954 
955 protected:
956 
957  /*!
958  * \brief Read goal position for servo.
959  *
960  * \param shell Dynamixel shell.
961  * \param pServo Pointer to servo.
962  */
963  virtual void doExec(DynaShell &shell, DynaServo *pServo)
964  {
965  int nGoalPos;
966  int rc;
967 
968  rc = pServo->ReadGoalPos(&nGoalPos);
969 
970  if( rc != DYNA_OK )
971  {
972  shell.Error(rc, "Servo %d: Read goal position failed.",
973  pServo->GetServoId());
974  return;
975  }
976 
977  switch( pServo->GetServoMode() )
978  {
980  shell.Response("Servo %3d: %d (continuous mode)\n",
981  pServo->GetServoId(), nGoalPos);
982  break;
983  case DYNA_MODE_SERVO:
984  default:
985  shell.Response("Servo %3d: %d\n", pServo->GetServoId(), nGoalPos);
986  break;
987  }
988  }
989 };
990 
991 
992 // -----------------------------------------------------------------------------
993 // DynaShellCmdReadGoalSpeed Class
994 // -----------------------------------------------------------------------------
995 
996 /*!
997  * \brief Read servos goal positions.
998  */
1000 {
1001 public:
1002 
1003  /*
1004  * \brief Default constructor.
1005  */
1007  {
1008  m_sCmdName = "goalspeed";
1009  m_sCmdHelpBrief = "Read servo goal speeds.";
1010  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
1011  m_sCmdHelpDesc = "Read the goal rotational speeds for the specified "
1012  "servos. Speeds <0 are clockwise rotations, >0 are "
1013  "conterclockwise. Directions are N/A for servos in "
1014  "servo mode. If the keyword 'chain' is specified, then "
1015  "the goal speeds for all of the servos in the chain are "
1016  "read.\n"
1017  " <servo_id> Servo id [0-253].";
1018  }
1019  /*
1020  * \brief Default destructor.
1021  */
1022  virtual ~DynaShellCmdReadGoalSpeed() { }
1023 
1024 
1025 protected:
1026 
1027  /*!
1028  * \brief Read goal position for servo.
1029  *
1030  * \param shell Dynamixel shell.
1031  * \param pServo Pointer to servo.
1032  */
1033  virtual void doExec(DynaShell &shell, DynaServo *pServo)
1034  {
1035  int nGoalSpeed;
1036  int nSpeed;
1037  int rc;
1038 
1039  rc = pServo->ReadGoalSpeed(&nGoalSpeed);
1040 
1041  if( rc != DYNA_OK )
1042  {
1043  shell.Error(rc, "Servo %d: Read goal speed failed.",
1044  pServo->GetServoId());
1045  return;
1046  }
1047 
1048  if( pServo->GetServoMode() == DYNA_MODE_CONTINUOUS )
1049  {
1050  shell.Response("Servo %3d: %d %s\n",
1051  pServo->GetServoId(), nGoalSpeed, rotdirstr(nGoalSpeed));
1052  }
1053  else
1054  {
1055  shell.Response("Servo %3d: %d\n", pServo->GetServoId(), nGoalSpeed);
1056  }
1057  }
1058 };
1059 
1060 
1061 // -----------------------------------------------------------------------------
1062 // DynaShellCmdWriteGoalSpeed Class
1063 // -----------------------------------------------------------------------------
1064 
1065 /*!
1066  * \brief Determine if servos are moving.
1067  */
1069 {
1070 public:
1071 
1072  /*
1073  * \brief Default constructor.
1074  */
1076  {
1077  m_sCmdName = "goalspeed";
1078  m_sCmdHelpBrief = "Write the servo goal speeds.";
1079  m_sCmdHelpArgs = "<servo_id> <speed> [<servo_id> <speed> ...]\n"
1080  "chain <speed>";
1081  m_sCmdHelpDesc = "Write the goal speeds for the specified servos. "
1082  "Speeds <0 are clockwise rotations, >0 are "
1083  "conterclockwise. Directions are N/A for servos in "
1084  "servo mode. If more than one servo is specifed then a "
1085  "synchronous write will be automatically performed. "
1086  "If the keyword 'chain' is specified, all servos in the "
1087  "chain are synchronously written.\n"
1088  " <servo_id> Servo id [0-253].\n"
1089  " <speed> Servo goal speed.";
1090  }
1091 
1092  /*
1093  * \brief Default destructor.
1094  */
1095  virtual ~DynaShellCmdWriteGoalSpeed() { }
1096 
1097 protected:
1098  /*!
1099  * \brief Write goal speeds.
1100  *
1101  * \param shell Dynamixel shell.
1102  * \param tup Array of (servo id, goal speed) 2-tuples.
1103  * \param uCount Number of tuples.
1104  */
1105  virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
1106  {
1107  DynaServo *pServo;
1108  int nGoalSpeed;
1109  DynaSpeedTuple_T tupSpeed[DYNA_ID_NUMOF];
1110  int i;
1111  int rc;
1112 
1113  if( uCount == 1 )
1114  {
1115  pServo = shell.m_pDynaChain->GetServo(tup[0].m_nServoId);
1116 
1117  nGoalSpeed = tup[0].m_nVal;
1118 
1119  rc = pServo->WriteGoalSpeed(nGoalSpeed);
1120 
1121  if( rc != DYNA_OK )
1122  {
1123  shell.Error(rc,
1124  "Servo %d: Write goal speed %d failed.",
1125  pServo->GetServoId(), nGoalSpeed);
1126  }
1127  }
1128  else // > 1
1129  {
1130  for(i=0; i<(int)uCount; ++i)
1131  {
1132  pServo = shell.m_pDynaChain->GetServo(tup[i].m_nServoId);
1133 
1134  tupSpeed[i].m_nServoId = tup[i].m_nServoId;
1135  tupSpeed[i].m_nSpeed = tup[i].m_nVal;
1136  }
1137 
1138  rc = shell.m_pDynaChain->SyncWriteGoalSpeed(tupSpeed, uCount);
1139 
1140  if( rc != DYNA_OK )
1141  {
1142  shell.Error(rc,
1143  "Synchronous write of goal speeds for %u servos failed.",
1144  uCount);
1145  }
1146  }
1147  }
1148 };
1149 
1150 
1151 // -----------------------------------------------------------------------------
1152 // DynaShellCmdReadMaxTorqueLimit Class
1153 // -----------------------------------------------------------------------------
1154 
1155 /*!
1156  * \brief Read servos on power-up or run-time maximum torque limits.
1157  */
1159 {
1160 public:
1161 
1162  /*
1163  * \brief Default constructor.
1164  */
1166  {
1167  m_sCmdName = "maxtorque";
1168  m_sCmdHelpBrief = "Read maximum torque limits.";
1169  m_sCmdHelpArgs = "<which> <servo_id> [<servo_id> ...]\n<which> chain";
1170  m_sCmdHelpDesc = "Read either the on power-up maximum torque limits "
1171  "or the run-time limits for the specified "
1172  "servos. The power-up limits are read from servo EEPROM "
1173  "configuration. The run-time limits are read from servo "
1174  "state RAM."
1175  "If the keyword 'chain' is specified, then the "
1176  "torque limits for all of the servos in the chain are "
1177  "read.\n"
1178  " <which> Which maximum torque limits. One of: "
1179  "powerup runtime.\n"
1180  " <servo_id> Servo id [0-253].";
1181  }
1182  /*
1183  * \brief Default destructor.
1184  */
1185  virtual ~DynaShellCmdReadMaxTorqueLimit() { }
1186 
1187  /*!
1188  * \brief Execute command on servos.
1189  *
1190  * \param shell Dynamixel shell.
1191  * \param argc Command argument count.
1192  * \param argv Array of arguments.
1193  */
1194  virtual void Exec(DynaShell &shell, int argc, char *argv[])
1195  {
1196  uint_t uAddr;
1197  int nServoId;
1198  int iter;
1199 
1200  TRY( ChkArgCnt(shell, argc) );
1201  TRY( ChkComm(shell) );
1202  TRY( ChkChainNotEmpty(shell) );
1203 
1204  if( !strcmp(argv[0], "powerup") )
1205  {
1207  }
1208  else if( !strcmp(argv[0], "runtime") )
1209  {
1211  }
1212  else
1213  {
1214  shell.Error("%s: Unknown <which> value.", argv[0]);
1215  return;
1216  }
1217 
1218  if( !strcmp(argv[1], "chain") )
1219  {
1220  TRY( ChkArgCntEQ(shell, argc, 2) );
1221 
1222  for(nServoId = shell.m_pDynaChain->IterStart(&iter);
1223  nServoId != DYNA_ID_NONE;
1224  nServoId = shell.m_pDynaChain->IterNext(&iter))
1225  {
1226  doExec(shell, nServoId, uAddr);
1227  }
1228  }
1229 
1230  else
1231  {
1232  for(iter=1; iter<argc; ++iter)
1233  {
1234  TRY( ToInt(shell, argv[iter], &nServoId) );
1235  TRY( ChkChainHasServo(shell, nServoId) );
1236 
1237  doExec(shell, nServoId, uAddr);
1238  }
1239  }
1240  }
1241 
1242  /*!
1243  * \brief Command tab completion generator.
1244  *
1245  * Completes NULL <which> <servo_id> | chain [servo_id [servo_id ...]]
1246  *
1247  * \param shell Dynamixel shell.
1248  * \param sText Partial text string to complete.
1249  * \param uTextLen Length of text.
1250  * \param nState Generator state. If FIRST, then initialize any statics.
1251  * \param sContext Generator context (i.e. canonical command path).
1252  *
1253  * \return
1254  * If a first/next match is made, return allocated completed match.\n
1255  * Otherwise return NULL.
1256  */
1257  virtual char *TabCompletion(DynaShell &shell,
1258  const char *sText,
1259  size_t uTextLen,
1260  int nState,
1261  const char *sContext)
1262  {
1263  int nArgNum;
1264  char buf[16];
1265  int i;
1266 
1267  if( (shell.m_pDynaChain == NULL) ||
1268  (shell.m_pDynaChain->GetNumberInChain() == 0) )
1269  {
1270  return NULL;
1271  }
1272 
1273  // argument number of already (expanded) arguments
1274  nArgNum = ReadLine::wc(sContext) - ReadLine::wc(m_sPubName);
1275 
1276  // <which>
1277  if( nArgNum == 0 )
1278  {
1279  if( nState == ReadLine::FIRST )
1280  {
1281  m_nTabIter = 0;
1282  }
1283 
1284  while( m_nTabIter < 2 )
1285  {
1286  i = m_nTabIter++;
1287 
1288  switch( i )
1289  {
1290  case 0:
1291  if( !strncmp("powerup", sText, uTextLen) )
1292  {
1293  return ReadLine::dupstr("powerup");
1294  }
1295  break;
1296  case 1:
1297  if( !strncmp("runtime", sText, uTextLen) )
1298  {
1299  return ReadLine::dupstr("runtime");
1300  }
1301  break;
1302  }
1303  }
1304  }
1305 
1306  //
1307  // Tab complete servo list
1308  //
1309  else
1310  {
1311  if( nState == ReadLine::FIRST )
1312  {
1313  m_nTabServoId = shell.m_pDynaChain->IterStart(&m_nTabIter);
1314 
1315  if( nArgNum == 1 )
1316  {
1317  m_bTabIncChain = true;
1318  }
1319  else
1320  {
1321  m_bTabIncChain = false;
1322  }
1323  }
1324 
1325  while( m_nTabServoId != DYNA_ID_NONE )
1326  {
1327  snprintf(buf, sizeof(buf), "%d", m_nTabServoId);
1328  buf[sizeof(buf)-1] = 0;
1329 
1330  m_nTabServoId = shell.m_pDynaChain->IterNext(&m_nTabIter);
1331 
1332  if( !strncmp(buf, sText, uTextLen) )
1333  {
1334  return ReadLine::dupstr(buf);
1335  }
1336  }
1337 
1338  if( m_bTabIncChain )
1339  {
1340  m_bTabIncChain = false;
1341  if( !strncmp("chain", sText, uTextLen) )
1342  {
1343  return ReadLine::dupstr("chain");
1344  }
1345  }
1346  }
1347 
1348  // no more matches
1349  return NULL;
1350  }
1351 
1352 protected:
1353  int m_nTabIter; ///< tab completion: iterator
1354  int m_nTabServoId; ///< tab completion: current servo id
1355  bool m_bTabIncChain; ///< tab completion: [do not] include chain keyword
1356 
1357  /*!
1358  * \brief Read goal position for servo.
1359  *
1360  * \param shell Dynamixel shell.
1361  * \param nServoId Servo id.
1362  * \param uAddr Servo read address.
1363  */
1364  virtual void doExec(DynaShell &shell, int nServoId, uint_t uAddr)
1365  {
1366  uint_t uMaxTorqueLimit;
1367  int rc;
1368 
1369  rc = shell.m_pDynaComm->Read16(nServoId, uAddr, &uMaxTorqueLimit);
1370 
1371  if( rc != DYNA_OK )
1372  {
1373  shell.Error(rc, "Servo %d: Read maximum torque limit failed.", nServoId);
1374  return;
1375  }
1376 
1377  shell.Response("Servo %3d: %d\n", nServoId, uMaxTorqueLimit);
1378  }
1379 };
1380 
1381 
1382 // -----------------------------------------------------------------------------
1383 // DynaShellCmdWriteMaxTorqueLimit Class
1384 // -----------------------------------------------------------------------------
1385 
1386 /*!
1387  * \brief Write servos on power-up or run-time maximum torque limits.
1388  */
1390 {
1391 public:
1392 
1393  /*
1394  * \brief Default constructor.
1395  */
1397  {
1398  m_sCmdName = "maxtorque";
1399  m_sCmdHelpBrief = "Write maximum torque limits.";
1400  m_sCmdHelpArgs = "<which> <servo_id> <limit> [<servo_id> <limit> ...]\n"
1401  "<which> chain <limit>";
1402  m_sCmdHelpDesc = "Write either the on power-up maximum torque limits "
1403  "or the run-time limits for the specified "
1404  "servos. The power-up limits are written to servo EEPROM "
1405  "configuration. The run-time limits are written to servo "
1406  "state RAM."
1407  "If the keyword 'chain' is specified, then the "
1408  "torque limits for all of the servos in the chain are "
1409  "written.\n"
1410  " <which> Which maximum torque limits. One of: "
1411  "powerup runtime.\n"
1412  " <servo_id> Servo id [0-253].\n"
1413  " <limit> Servo torque limit.";
1414  }
1415 
1416  /*
1417  * \brief Default destructor.
1418  */
1419  virtual ~DynaShellCmdWriteMaxTorqueLimit() { }
1420 
1421  /*!
1422  * \brief Execute command on servos.
1423  *
1424  * \param shell Dynamixel shell.
1425  * \param argc Command argument count.
1426  * \param argv Array of arguments.
1427  */
1428  void Exec(DynaShell &shell, int argc, char *argv[])
1429  {
1430  uint_t uAddr;
1431  uint_t uNumPairs;
1432  ExecTup_T tup[DYNA_ID_NUMOF];
1433  int nServoId;
1434  int nVal;
1435  int iter;
1436  int cnt;
1437 
1438  TRY( ChkArgCnt(shell, argc) );
1439 
1440  if( ((argc-1) % 2) != 0 )
1441  {
1442  shell.Error("Unmatched servo_id,value pairs.");
1443  return;
1444  }
1445 
1446  if( !strcmp(argv[0], "powerup") )
1447  {
1449  }
1450  else if( !strcmp(argv[0], "runtime") )
1451  {
1453  }
1454  else
1455  {
1456  shell.Error("%s: Unknown <which> value.", argv[0]);
1457  return;
1458  }
1459 
1460  uNumPairs = (uint_t)((argc-1) / 2);
1461 
1462  if( uNumPairs > DYNA_ID_NUMOF )
1463  {
1464  shell.Error("%u: Too many servo_id,value pairs.", uNumPairs);
1465  return;
1466  }
1467 
1468  TRY( ChkComm(shell) );
1469  TRY( ChkChainNotEmpty(shell) );
1470 
1471  // full chain of servos
1472  if( !strcmp(argv[1], "chain") )
1473  {
1474  TRY( ChkArgCntEQ(shell, argc, 3) );
1475  TRY( ToInt(shell, argv[2], &nVal) );
1476 
1477  for(nServoId = shell.m_pDynaChain->IterStart(&iter), cnt=0;
1478  nServoId != DYNA_ID_NONE;
1479  nServoId = shell.m_pDynaChain->IterNext(&iter), ++cnt)
1480  {
1481  tup[cnt].m_nServoId = nServoId;
1482  tup[cnt].m_nVal = nVal;
1483  }
1484 
1485  uNumPairs = (uint_t)cnt;
1486  }
1487 
1488  // list of servos
1489  else
1490  {
1491  for(iter=1, cnt=0; iter<argc-1; iter+=2, ++cnt)
1492  {
1493  TRY( ToInt(shell, argv[iter], &nServoId) );
1494  TRY( ToInt(shell, argv[iter+1], &nVal) );
1495  TRY( ChkChainHasServo(shell, nServoId) );
1496 
1497  tup[cnt].m_nServoId = nServoId;
1498  tup[cnt].m_nVal = nVal;
1499  }
1500  }
1501 
1502  doExec(shell, uAddr, tup, uNumPairs);
1503  }
1504 
1505 
1506  /*!
1507  * \brief Command tab completion generator.
1508  *
1509  * Completes NULL <which> <servo_id> | chain [servo_id [servo_id ...]]
1510  *
1511  * \param shell Dynamixel shell.
1512  * \param sText Partial text string to complete.
1513  * \param uTextLen Length of text.
1514  * \param nState Generator state. If FIRST, then initialize any statics.
1515  * \param sContext Generator context (i.e. canonical command path).
1516  *
1517  * \return
1518  * If a first/next match is made, return allocated completed match.\n
1519  * Otherwise return NULL.
1520  */
1521  virtual char *TabCompletion(DynaShell &shell,
1522  const char *sText,
1523  size_t uTextLen,
1524  int nState,
1525  const char *sContext)
1526  {
1527  int nArgNum;
1528  char buf[16];
1529  int i;
1530 
1531  if( (shell.m_pDynaChain == NULL) ||
1532  (shell.m_pDynaChain->GetNumberInChain() == 0) )
1533  {
1534  return NULL;
1535  }
1536 
1537  // argument number of already (expanded) arguments
1538  nArgNum = ReadLine::wc(sContext) - ReadLine::wc(m_sPubName);
1539 
1540  // <which>
1541  if( nArgNum == 0 )
1542  {
1543  if( nState == ReadLine::FIRST )
1544  {
1545  m_nTabIter = 0;
1546  }
1547 
1548  while( m_nTabIter < 2 )
1549  {
1550  i = m_nTabIter++;
1551 
1552  switch( i )
1553  {
1554  case 0:
1555  if( !strncmp("powerup", sText, uTextLen) )
1556  {
1557  return ReadLine::dupstr("powerup");
1558  }
1559  break;
1560  case 1:
1561  if( !strncmp("runtime", sText, uTextLen) )
1562  {
1563  return ReadLine::dupstr("runtime");
1564  }
1565  break;
1566  }
1567  }
1568  }
1569 
1570  // every even argument is the servo value, which cannot be expanded
1571  else if( !(nArgNum & 0x01) )
1572  {
1573  return NULL;
1574  }
1575 
1576  //
1577  // Tab complete servo list
1578  //
1579  else
1580  {
1581  if( nState == ReadLine::FIRST )
1582  {
1583  m_nTabServoId = shell.m_pDynaChain->IterStart(&m_nTabIter);
1584 
1585  if( nArgNum == 1 )
1586  {
1587  m_bTabIncChain = true;
1588  }
1589  else
1590  {
1591  m_bTabIncChain = false;
1592  }
1593  }
1594 
1595  while( m_nTabServoId != DYNA_ID_NONE )
1596  {
1597  snprintf(buf, sizeof(buf), "%d", m_nTabServoId);
1598  buf[sizeof(buf)-1] = 0;
1599 
1600  m_nTabServoId = shell.m_pDynaChain->IterNext(&m_nTabIter);
1601 
1602  if( !strncmp(buf, sText, uTextLen) )
1603  {
1604  return ReadLine::dupstr(buf);
1605  }
1606  }
1607 
1608  if( m_bTabIncChain )
1609  {
1610  m_bTabIncChain = false;
1611  if( !strncmp("chain", sText, uTextLen) )
1612  {
1613  return ReadLine::dupstr("chain");
1614  }
1615  }
1616  }
1617 
1618  // no more matches
1619  return NULL;
1620  }
1621 
1622 protected:
1623  int m_nTabIter; ///< tab completion: iterator
1624  int m_nTabServoId; ///< tab completion: current servo id
1625  bool m_bTabIncChain; ///< tab completion: [do not] include chain keyword
1626 
1627  /*!
1628  * \brief Move servos to goal positions.
1629  *
1630  * \param shell Dynamixel shell.
1631  * \param uAddr Torque limit address.
1632  * \param tup Array of (servo id, goal position) 2-tuples.
1633  * \param uCount Number of tuples.
1634  */
1635  virtual void doExec(DynaShell &shell,
1636  uint_t uAddr,
1637  ExecTup_T tup[],
1638  uint_t uCount)
1639  {
1640  int nServoId;
1641  uint_t uVal;
1642  uint_t i;
1643  int rc;
1644 
1645  for(i=0, rc=DYNA_OK; i<uCount && rc==DYNA_OK; ++i)
1646  {
1647  nServoId = tup[i].m_nServoId;
1648  uVal = (uint_t)tup[i].m_nVal;
1649 
1650  rc = shell.m_pDynaComm->Write16(nServoId, uAddr, uVal);
1651 
1652  if( rc != DYNA_OK )
1653  {
1654  shell.Error(rc,
1655  "Servo %d: Write maximum torque limit at 0x%02x with %u failed.",
1656  nServoId, uAddr, uVal);
1657  }
1658  }
1659  }
1660 };
1661 
1662 
1663 // -----------------------------------------------------------------------------
1664 // DynaShellCmdGetSoftTorqueTh Class
1665 // -----------------------------------------------------------------------------
1666 
1667 /*!
1668  * \brief Read servos goal positions.
1669  */
1671 {
1672 public:
1673 
1674  /*
1675  * \brief Default constructor.
1676  */
1678  {
1679  m_sCmdName = "torqueth";
1680  m_sCmdHelpBrief = "Get servo soft torque thresholds.";
1681  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
1682  m_sCmdHelpDesc = "Get servo soft torque hysteresis thresholds. When a "
1683  "servo exceeds the over torque limit "
1684  "threshold, it is placed in the over torque limit "
1685  "condition which limits servo actuation. "
1686  "When a servo drops below the clear threshold, the "
1687  "servo torque over limit condition is cleared. "
1688  "If the keyword 'chain' is specified, then "
1689  "the thresholds for all of the servos in the "
1690  "chain are retrieved.\n"
1691  " <servo_id> Servo id [0-253].";
1692  }
1693 
1694  /*
1695  * \brief Default destructor.
1696  */
1697  virtual ~DynaShellCmdGetSoftTorqueTh() { }
1698 
1699 protected:
1700 
1701  /*!
1702  * \brief Determine torque enable state for servo.
1703  *
1704  * \param shell Dynamixel shell.
1705  * \param pServo Pointer to servo.
1706  */
1707  virtual void doExec(DynaShell &shell, DynaServo *pServo)
1708  {
1709  uint_t uOverTorqueTh;
1710  uint_t uClearTorqueTh;
1711 
1712  pServo->GetSoftTorqueThresholds(uOverTorqueTh, uClearTorqueTh);
1713 
1714  shell.Response("Servo %3d: over_th %5d, "
1715  "clear_th %5d\n",
1716  pServo->GetServoId(), uOverTorqueTh, uClearTorqueTh);
1717  }
1718 };
1719 
1720 
1721 // -----------------------------------------------------------------------------
1722 // DynaShellCmdSetSoftTorqueTh Class
1723 // -----------------------------------------------------------------------------
1724 
1725 /*!
1726  * \brief Determine if servos are moving.
1727  */
1729 {
1730 public:
1731 
1732  /*
1733  * \brief Default constructor.
1734  */
1736  {
1737  m_sCmdName = "torqueth";
1738  m_sCmdHelpBrief = "Set servo soft torque thresholds.";
1739  m_sCmdHelpArgs = "<servo_id> <over_th> <clear_th>";
1740  m_sCmdHelpDesc = "Set servo soft torque hysteresis thresholds.\n"
1741  " <servo_id> Servo id [0-253].\n"
1742  " <over_th> Threshold to set the torque over "
1743  "limit condition.\n"
1744  " <clear_th> Theshold to clear the torque over "
1745  "limit condition. The clear\n"
1746  " threshold must be lower "
1747  "than the over threshold.";
1748  }
1749 
1750  /*
1751  * \brief Default destructor.
1752  */
1753  virtual ~DynaShellCmdSetSoftTorqueTh() { }
1754 
1755  /*!
1756  * \brief Execute command on servos.
1757  *
1758  * \param shell Dynamixel shell.
1759  * \param argc Command argument count.
1760  * \param argv Array of arguments.
1761  */
1762  void Exec(DynaShell &shell, int argc, char *argv[])
1763  {
1764  int nServoId;
1765  uint_t uOverTorqueTh;
1766  uint_t uClearTorqueTh;
1767  bool bOdReversed;
1768  DynaServo *pServo;
1769 
1770  TRY( ChkArgCnt(shell, argc) );
1771 
1772  TRY( ChkComm(shell) );
1773  TRY( ChkChainNotEmpty(shell) );
1774 
1775  TRY( ToInt(shell, argv[0], &nServoId) );
1776  TRY( ToUInt(shell, argv[1], &uOverTorqueTh) );
1777  TRY( ToUInt(shell, argv[2], &uClearTorqueTh) );
1778  TRY( ChkChainHasServo(shell, nServoId) );
1779  TRY( ChkChainIsMasterServo(shell, nServoId) );
1780 
1781  pServo = shell.m_pDynaChain->GetServo(nServoId);
1782 
1783  if( pServo == NULL )
1784  {
1785  shell.Error("Servo %d: Servo not found.\n");
1786  }
1787  else
1788  {
1789  pServo->SetSoftTorqueThresholds(uOverTorqueTh, uClearTorqueTh);
1790  shell.Ok();
1791  }
1792  }
1793 
1794 protected:
1795 };
1796 
1797 
1798 // -----------------------------------------------------------------------------
1799 // DynaShellCmdReadCurPos Class
1800 // -----------------------------------------------------------------------------
1801 
1802 /*!
1803  * \brief Read servos current positions.
1804  */
1806 {
1807 public:
1808 
1809  /*
1810  * \brief Default constructor.
1811  */
1813  {
1814  m_sCmdName = "curpos";
1815  m_sCmdHelpBrief = "Read current odometer positions.";
1816  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
1817  m_sCmdHelpDesc = "Read the current odometer positions for the "
1818  "specified servos. If the keyword 'chain' is specified, "
1819  "then the current positions for all of the servos in "
1820  "the chain are read.\n"
1821  " <servo_id> Servo id [0-253].";
1822  }
1823 
1824  /*
1825  * \brief Default destructor.
1826  */
1827  virtual ~DynaShellCmdReadCurPos() { }
1828 
1829 protected:
1830 
1831  /*!
1832  * \brief Read current position for servo.
1833  *
1834  * \param shell Dynamixel shell.
1835  * \param pServo Pointer to servo.
1836  */
1837  virtual void doExec(DynaShell &shell, DynaServo *pServo)
1838  {
1839  int nCurPos;
1840  int rc;
1841 
1842  rc = pServo->ReadCurPos(&nCurPos);
1843 
1844  if( rc != DYNA_OK )
1845  {
1846  shell.Error(rc, "Servo %d: Read current position failed.",
1847  pServo->GetServoId());
1848  return;
1849  }
1850 
1851  switch( pServo->GetServoMode() )
1852  {
1853  case DYNA_MODE_CONTINUOUS:
1854  shell.Response("Servo %3d: %d (continuous mode)\n",
1855  pServo->GetServoId(), nCurPos);
1856  break;
1857  case DYNA_MODE_SERVO:
1858  default:
1859  shell.Response("Servo %3d: %d\n", pServo->GetServoId(), nCurPos);
1860  break;
1861  }
1862  }
1863 };
1864 
1865 
1866 // -----------------------------------------------------------------------------
1867 // DynaShellCmdReadCurSpeed Class
1868 // -----------------------------------------------------------------------------
1869 
1870 /*!
1871  * \brief Read servos current positions.
1872  */
1874 {
1875 public:
1876 
1877  /*
1878  * \brief Default constructor.
1879  */
1881  {
1882  m_sCmdName = "curspeed";
1883  m_sCmdHelpBrief = "Read the current speeds.";
1884  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
1885  m_sCmdHelpDesc = "Read the current speeds for the specified servos. "
1886  "Speeds <0 are clockwise rotations, >0 are "
1887  "conterclockwise. If the keyword 'chain' is specified, "
1888  "then the current speeds for all of the servos in the "
1889  "chain are read.\n"
1890  " <servo_id> Servo id [0-253].";
1891  }
1892 
1893  /*
1894  * \brief Default destructor.
1895  */
1896  virtual ~DynaShellCmdReadCurSpeed() { }
1897 
1898 protected:
1899 
1900  /*!
1901  * \brief Read current position for servo.
1902  *
1903  * \param shell Dynamixel shell.
1904  * \param pServo Pointer to servo.
1905  */
1906  virtual void doExec(DynaShell &shell, DynaServo *pServo)
1907  {
1908  int nCurSpeed;
1909  int rc;
1910 
1911  rc = pServo->ReadCurSpeed(&nCurSpeed);
1912 
1913  if( rc != DYNA_OK )
1914  {
1915  shell.Error(rc, "Servo %d: Read current speed failed.",
1916  pServo->GetServoId());
1917  return;
1918  }
1919 
1920  shell.Response("Servo %3d: %d %s\n",
1921  pServo->GetServoId(), nCurSpeed, rotdirstr(nCurSpeed));
1922  }
1923 };
1924 
1925 
1926 // -----------------------------------------------------------------------------
1927 // DynaShellCmdReadDynamics Class
1928 // -----------------------------------------------------------------------------
1929 
1930 /*!
1931  * \brief Read servos goal positions.
1932  */
1934 {
1935 public:
1936 
1937  /*
1938  * \brief Default constructor.
1939  */
1941  {
1942  m_sCmdName = "dynamics";
1943  m_sCmdHelpBrief = "Read the current servo dynamics.";
1944  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
1945  m_sCmdHelpDesc = "Read the current dynamics for the specified servos. "
1946  "Dynamics are position, speed, and torque. "
1947  "If the keyword 'chain' is specified, then the dynamics "
1948  "for all of the servos in the chain are read.\n"
1949  " <servo_id> Servo id [0-253].";
1950  }
1951  /*
1952  * \brief Default destructor.
1953  */
1954  virtual ~DynaShellCmdReadDynamics() { }
1955 
1956 
1957 protected:
1958 
1959  /*!
1960  * \brief Read dynamics for servo.
1961  *
1962  * \param shell Dynamixel shell.
1963  * \param pServo Pointer to servo.
1964  */
1965  virtual void doExec(DynaShell &shell, DynaServo *pServo)
1966  {
1967  int nCurPos;
1968  int nCurSpeed;
1969  int nCurLoad;
1970  int rc;
1971 
1972  rc = pServo->ReadDynamics(&nCurPos, &nCurSpeed, &nCurLoad);
1973 
1974  if( rc != DYNA_OK )
1975  {
1976  shell.Error(rc, "Servo %d: Failed to read the dynamics.",
1977  pServo->GetServoId());
1978  return;
1979  }
1980 
1981  shell.Response("Servo %3d: pos %5d, speed %5d, load %5d\n",
1982  pServo->GetServoId(), nCurPos, nCurSpeed, nCurLoad);
1983  }
1984 };
1985 
1986 
1987 // -----------------------------------------------------------------------------
1988 // DynaShellCmdReadHealth Class
1989 // -----------------------------------------------------------------------------
1990 
1991 /*!
1992  * \brief Read servos goal positions.
1993  */
1995 {
1996 public:
1997 
1998  /*
1999  * \brief Default constructor.
2000  */
2002  {
2003  m_sCmdName = "health";
2004  m_sCmdHelpBrief = "Read the current servo health.";
2005  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
2006  m_sCmdHelpDesc = "Read the current health of the specified servos. "
2007  "Servo health is the combined state of servo alarms, "
2008  "torque, temperature, and voltage. "
2009  "If the keyword 'chain' is specified, then the health "
2010  "for all of the servos in the chain are read.\n"
2011  " <servo_id> Servo id [0-253].";
2012  }
2013  /*
2014  * \brief Default destructor.
2015  */
2016  virtual ~DynaShellCmdReadHealth() { }
2017 
2018 
2019 protected:
2020 
2021  /*!
2022  * \brief Read dynamics for servo.
2023  *
2024  * \param shell Dynamixel shell.
2025  * \param pServo Pointer to servo.
2026  */
2027  virtual void doExec(DynaShell &shell, DynaServo *pServo)
2028  {
2029  uint_t uAlarms;
2030  string strAlarms;
2031  int nCurLoad;
2032  uint_t uCurVolt;
2033  uint_t uCurTemp;
2034  int rc;
2035 
2036  rc = pServo->ReadHealth(&uAlarms, &nCurLoad, &uCurVolt, &uCurTemp);
2037 
2038  if( rc != DYNA_OK )
2039  {
2040  shell.Error(rc, "Servo %d: Failed to read the health.",
2041  pServo->GetServoId());
2042  return;
2043  }
2044 
2045  strAlarms = DynaComm::GetAlarmsString(uAlarms);
2046 
2047  shell.Response("Servo %3d: load %5d, voltage %3u, temperature %3u, "
2048  "alarms(0x%02x) %s\n",
2049  pServo->GetServoId(), nCurLoad, uCurVolt, uCurTemp, uAlarms,
2050  strAlarms.c_str());
2051  }
2052 };
2053 
2054 
2055 // -----------------------------------------------------------------------------
2056 // DynaShellCmdReadIsMoving Class
2057 // -----------------------------------------------------------------------------
2058 
2059 /*!
2060  * \brief Determine if servos are moving.
2061  */
2063 {
2064 public:
2065 
2066  /*
2067  * \brief Default constructor.
2068  */
2070  {
2071  m_sCmdName = "ismoving";
2072  m_sCmdHelpBrief = "Check if servos are moving.";
2073  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
2074  m_sCmdHelpDesc = "Determine if the specified servos are moving. "
2075  "The determination is made by reading the servos states. "
2076  "If the keyword 'chain' is specified, then all servos "
2077  "in the chain are checked.\n"
2078  " <servo_id> Servo id [0-253].";
2079  }
2080 
2081  /*
2082  * \brief Default destructor.
2083  */
2084  virtual ~DynaShellCmdReadIsMoving() { }
2085 
2086 protected:
2087 
2088  /*!
2089  * \brief Determine if servo is moving.
2090  *
2091  * \param shell Dynamixel shell.
2092  * \param pServo Pointer to servo.
2093  */
2094  virtual void doExec(DynaShell &shell, DynaServo *pServo)
2095  {
2096  bool bIsMoving;
2097  int rc;
2098 
2099  rc = pServo->ReadIsMoving(&bIsMoving);
2100 
2101  if( rc != DYNA_OK )
2102  {
2103  shell.Error(rc, "Servo %d: Read motion state failed.",
2104  pServo->GetServoId());
2105  return;
2106  }
2107 
2108  shell.Response("Servo %3d: %s\n", pServo->GetServoId(),
2109  (bIsMoving? "moving": "stopped"));
2110  }
2111 };
2112 
2113 
2114 // -----------------------------------------------------------------------------
2115 // DynaShellCmdClearAlarms Class
2116 // -----------------------------------------------------------------------------
2117 
2118 /*!
2119  * \brief Determine if servos are moving.
2120  */
2122 {
2123 public:
2124 
2125  /*
2126  * \brief Default constructor.
2127  */
2129  {
2130  m_sCmdName = "alarms";
2131  m_sCmdHelpBrief = "Clear servo alarms (if possible).";
2132  m_sCmdHelpArgs = "<servo_id> [servo_id...]\nchain";
2133  m_sCmdHelpDesc = "Clear all clearable alarms raised by serovs. "
2134  "If the keyword 'chain' is specified, then all servos "
2135  "alarms in the chain are cleared.\n"
2136  " <servo_id> Servo id [0-253].";
2137  }
2138 
2139  /*
2140  * \brief Default destructor.
2141  */
2142  virtual ~DynaShellCmdClearAlarms() { }
2143 
2144 protected:
2145 
2146  /*!
2147  * \brief Determine if servo is moving.
2148  *
2149  * \param shell Dynamixel shell.
2150  * \param pServo Pointer to servo.
2151  */
2152  virtual void doExec(DynaShell &shell, DynaServo *pServo)
2153  {
2154  uint_t uAlarms;
2155  int rc;
2156 
2157  uAlarms = pServo->GetAlarms();
2158 
2159  if( uAlarms == DYNA_ALARM_NONE )
2160  {
2161  shell.Response("Servo %3d: %s.\n", pServo->GetServoId(), "No alarms");
2162  }
2163  else if( uAlarms & DYNA_ALARM_LOAD )
2164  {
2165  pServo->Stop();
2166  rc = pServo->ReloadMaxTorqueLimit();
2167  if( rc != DYNA_OK )
2168  {
2169  shell.Error(rc, "Servo %3d: Failed to reload maximum torque limit.",
2170  pServo->GetServoId());
2171  }
2172  else if( uAlarms == DYNA_ALARM_LOAD )
2173  {
2174  shell.Response("Servo %3d: %s.\n", pServo->GetServoId(),
2175  "Over-load alarm cleared");
2176  }
2177  else
2178  {
2179  shell.Response("Servo %3d: %s.\n", pServo->GetServoId(),
2180  "Over-load alarm cleared, but other unclearable alarms are present");
2181  }
2182  }
2183  else
2184  {
2185  shell.Response("Servo %3d: %s.\n", pServo->GetServoId(),
2186  "Alarms present, but not clearable");
2187  }
2188  }
2189 };
2190 
2191 
2192 // -----------------------------------------------------------------------------
2193 // DynaShellCmdReadByte Class
2194 // -----------------------------------------------------------------------------
2195 
2196 /*!
2197  * \brief Read servo byte value at address.
2198  */
2200 {
2201 public:
2202 
2203  /*
2204  * \brief Default constructor.
2205  */
2207  {
2208  m_sCmdName = "byte";
2209  m_sCmdHelpBrief = "Read a byte from the servo control table.";
2210  m_sCmdHelpArgs = "<addr> <servo_id> [servo_id...]\n<addr> chain";
2211  m_sCmdHelpDesc = "Read an 8-bit byte at the address for the specified "
2212  "servos. If the keyword 'chain' is specified, then"
2213  "the byte value at <addr> is read for all servos in the "
2214  "chain.\n"
2215  " <addr> Servo memory address.\n"
2216  " <servo_id> Servo id [0-253]."
2217  "\n\n"
2218  "Caution: This is a low-level function that bypasses all "
2219  "state consistency checks.";
2220  }
2221 
2222  /*
2223  * \brief Default destructor.
2224  */
2225  virtual ~DynaShellCmdReadByte() { }
2226 
2227  /*!
2228  * \brief Execute read byte command on servos.
2229  *
2230  * \param shell Dynamixel shell.
2231  * \param argc Command argument count.
2232  * \param argv Array of arguments.
2233  */
2234  virtual void Exec(DynaShell &shell, int argc, char *argv[])
2235  {
2236  uint_t uAddr;
2237  int nServoId;
2238  int iter;
2239 
2240  TRY( ChkArgCnt(shell, argc) );
2241  TRY( ChkComm(shell) );
2242  TRY( ChkChainNotEmpty(shell) );
2243 
2244  TRY( ToInt(shell, argv[0], (int *)&uAddr) );
2245 
2246  if( !strcmp(argv[1], "chain") )
2247  {
2248  TRY( ChkArgCntEQ(shell, argc, 2) );
2249 
2250  for(nServoId = shell.m_pDynaChain->IterStart(&iter);
2251  nServoId != DYNA_ID_NONE;
2252  nServoId = shell.m_pDynaChain->IterNext(&iter))
2253  {
2254  doExec(shell, nServoId, uAddr);
2255  }
2256  }
2257 
2258  else
2259  {
2260  for(iter=1; iter<argc; ++iter)
2261  {
2262  TRY( ToInt(shell, argv[iter], &nServoId) );
2263  TRY( ChkChainHasServo(shell, nServoId) );
2264 
2265  doExec(shell, nServoId, uAddr);
2266  }
2267  }
2268  }
2269 
2270  /*!
2271  * \brief Command tab completion generator.
2272  *
2273  * Completes NULL <servo_id> | chain [servo_id [servo_id ...]]
2274  *
2275  * \param shell Dynamixel shell.
2276  * \param sText Partial text string to complete.
2277  * \param uTextLen Length of text.
2278  * \param nState Generator state. If FIRST, then initialize any statics.
2279  * \param sContext Generator context (i.e. canonical command path).
2280  *
2281  * \return
2282  * If a first/next match is made, return allocated completed match.\n
2283  * Otherwise return NULL.
2284  */
2285  virtual char *TabCompletion(DynaShell &shell,
2286  const char *sText,
2287  size_t uTextLen,
2288  int nState,
2289  const char *sContext)
2290  {
2291  int nArgNum;
2292 
2293  char buf[16];
2294 
2295  if( (shell.m_pDynaChain == NULL) ||
2296  (shell.m_pDynaChain->GetNumberInChain() == 0) )
2297  {
2298  return NULL;
2299  }
2300 
2301  // argument number of already (expanded) arguments
2302  nArgNum = ReadLine::wc(sContext) - ReadLine::wc(m_sPubName);
2303 
2304  // <addr> cannot complete adrress
2305  if( nArgNum == 0 )
2306  {
2307  return NULL;
2308  }
2309 
2310  //
2311  // New command to complete - initialize.
2312  //
2313  if( nState == ReadLine::FIRST )
2314  {
2315  m_nTabServoId = shell.m_pDynaChain->IterStart(&m_nTabIter);
2316 
2317  if( nArgNum == 1 )
2318  {
2319  m_bTabIncChain = true;
2320  }
2321  else
2322  {
2323  m_bTabIncChain = false;
2324  }
2325  }
2326 
2327  while( m_nTabServoId != DYNA_ID_NONE )
2328  {
2329  snprintf(buf, sizeof(buf), "%d", m_nTabServoId);
2330  buf[sizeof(buf)-1] = 0;
2331 
2332  m_nTabServoId = shell.m_pDynaChain->IterNext(&m_nTabIter);
2333 
2334  if( !strncmp(buf, sText, uTextLen) )
2335  {
2336  return ReadLine::dupstr(buf);
2337  }
2338  }
2339 
2340  if( m_bTabIncChain )
2341  {
2342  m_bTabIncChain = false;
2343  if( !strncmp("chain", sText, uTextLen) )
2344  {
2345  return ReadLine::dupstr("chain");
2346  }
2347  }
2348 
2349  // no more matches
2350  return NULL;
2351  }
2352 
2353 protected:
2354  int m_nTabIter; ///< tab completion: servo id iterator
2355  int m_nTabServoId; ///< tab completion: current servo id
2356  bool m_bTabIncChain; ///< tab completion: [do not] include chain keyword
2357 
2358  /*!
2359  * \brief Read byte.
2360  *
2361  * \param shell Dynamixel shell.
2362  * \param nServoId Servo id.
2363  * \param uAddr Servo read address.
2364  */
2365  virtual void doExec(DynaShell &shell, int nServoId, uint_t uAddr)
2366  {
2367  uint_t uVal;
2368  int rc;
2369 
2370  rc = shell.m_pDynaComm->Read8(nServoId, uAddr, &uVal);
2371 
2372  if( rc != DYNA_OK )
2373  {
2374  shell.Error(rc, "Servo %d: Failed to read byte at 0x%02x.",
2375  nServoId, uAddr);
2376  return;
2377  }
2378 
2379  shell.Response("Servo %3d: 0x%02x.\n", nServoId, uVal);
2380  }
2381 };
2382 
2383 
2384 // -----------------------------------------------------------------------------
2385 // DynaShellCmdWriteByte Class
2386 // -----------------------------------------------------------------------------
2387 
2388 /*!
2389  * \brief Write byte value to servo at address.
2390  */
2392 {
2393 public:
2394 
2395  /*
2396  * \brief Default constructor.
2397  */
2399  {
2400  m_sCmdName = "byte";
2401  m_sCmdHelpBrief = "Write a byte to the servo control table.";
2402  m_sCmdHelpArgs = "<addr> <servo_id> <val> [<servo_id> <val> ...]\n"
2403  "<addr> chain <val> ";
2404  m_sCmdHelpDesc = "Write an 8-bit byte to the address for the specified "
2405  "servos. "
2406  "If the keyword 'chain' is specified, then "
2407  "the byte value is written to <addr> for all servos in "
2408  "the chain.\n"
2409  "If more than 1 servo is specified, a synchronous write "
2410  "is performed.\n"
2411  " <addr> Servo memory address.\n"
2412  " <servo_id> Servo id [0-253].\n"
2413  " <val> New servo value."
2414  "\n\n"
2415  "Caution: This is a low-level function that bypasses all "
2416  "state consistency checks.";
2417  }
2418 
2419  /*
2420  * \brief Default destructor.
2421  */
2422  virtual ~DynaShellCmdWriteByte() { }
2423 
2424  /*!
2425  * \brief Execute write byte command on servos.
2426  *
2427  * \param shell Dynamixel shell.
2428  * \param argc Command argument count.
2429  * \param argv Array of arguments.
2430  */
2431  virtual void Exec(DynaShell &shell, int argc, char *argv[])
2432  {
2434  uint_t uAddr;
2435  uint_t uVal;
2436  int nServoId;
2437  int iter;
2438  int cnt;
2439  uint_t uNumPairs;
2440 
2441  TRY( ChkArgCnt(shell, argc) );
2442  TRY( ChkComm(shell) );
2443  TRY( ChkChainNotEmpty(shell) );
2444 
2445  TRY( ToInt(shell, argv[0], (int *)&uAddr) );
2446 
2447  cnt = argc - 1; // less address
2448 
2449  if( (cnt % 2) != 0 )
2450  {
2451  shell.Error("Unmatched servo_id,value pairs.");
2452  return;
2453  }
2454 
2455  uNumPairs = (uint_t)(cnt / 2);
2456 
2457  if( uNumPairs > DYNA_ID_NUMOF )
2458  {
2459  shell.Error("%u: Too many servo_id,value pairs.", uNumPairs);
2460  return;
2461  }
2462 
2463  if( !strcmp(argv[1], "chain") )
2464  {
2465  TRY( ChkArgCntEQ(shell, argc, 3) );
2466 
2467  TRY( ToInt(shell, argv[2], (int *)&uVal) );
2468 
2469  for(nServoId = shell.m_pDynaChain->IterStart(&iter), cnt=0;
2470  nServoId != DYNA_ID_NONE;
2471  nServoId = shell.m_pDynaChain->IterNext(&iter), ++cnt)
2472  {
2473  tup[cnt].m_nServoId = nServoId;
2474  tup[cnt].m_uVal = uVal;
2475  }
2476  }
2477 
2478  else
2479  {
2480  for(iter=1, cnt=0; iter<argc; iter+=2, ++cnt)
2481  {
2482  TRY( ToInt(shell, argv[iter], &nServoId) );
2483  TRY( ChkChainHasServo(shell, nServoId) );
2484  TRY( ToInt(shell, argv[iter+1], (int *)&uVal) );
2485 
2486  tup[cnt].m_nServoId = nServoId;
2487  tup[cnt].m_uVal = uVal;
2488  }
2489  }
2490 
2491  doExec(shell, uAddr, tup, (uint_t)cnt);
2492  }
2493 
2494  /*!
2495  * \brief Command tab completion generator.
2496  *
2497  * Completes NULL <servo_id> | chain [servo_id [servo_id ...]]
2498  *
2499  * \param shell Dynamixel shell.
2500  * \param sText Partial text string to complete.
2501  * \param uTextLen Length of text.
2502  * \param nState Generator state. If FIRST, then initialize any statics.
2503  * \param sContext Generator context (i.e. canonical command path).
2504  *
2505  * \return
2506  * If a first/next match is made, return allocated completed match.\n
2507  * Otherwise return NULL.
2508  */
2509  virtual char *TabCompletion(DynaShell &shell,
2510  const char *sText,
2511  size_t uTextLen,
2512  int nState,
2513  const char *sContext)
2514  {
2515  int nArgNum;
2516 
2517  char buf[16];
2518 
2519  if( (shell.m_pDynaChain == NULL) ||
2520  (shell.m_pDynaChain->GetNumberInChain() == 0) )
2521  {
2522  return NULL;
2523  }
2524 
2525  // argument number of already (expanded) arguments
2526  nArgNum = ReadLine::wc(sContext) - ReadLine::wc(m_sPubName);
2527 
2528  // cannot complete adrress
2529  if( nArgNum == 0 )
2530  {
2531  return NULL;
2532  }
2533 
2534  // every even argument is the servo value, which cannot be expanded
2535  else if( (nArgNum & 0x01) == 0 )
2536  {
2537  return NULL;
2538  }
2539 
2540  // New command argument to complete - initialize.
2541  //
2542  if( nState == ReadLine::FIRST )
2543  {
2544  m_nTabServoId = shell.m_pDynaChain->IterStart(&m_nTabIter);
2545 
2546  if( nArgNum == 1 )
2547  {
2548  m_bTabIncChain = true;
2549  }
2550  else
2551  {
2552  m_bTabIncChain = false;
2553  }
2554  }
2555 
2556  while( m_nTabServoId != DYNA_ID_NONE )
2557  {
2558  snprintf(buf, sizeof(buf), "%d", m_nTabServoId);
2559  buf[sizeof(buf)-1] = 0;
2560 
2561  m_nTabServoId = shell.m_pDynaChain->IterNext(&m_nTabIter);
2562 
2563  if( !strncmp(buf, sText, uTextLen) )
2564  {
2565  return ReadLine::dupstr(buf);
2566  }
2567  }
2568 
2569  if( m_bTabIncChain )
2570  {
2571  m_bTabIncChain = false;
2572  if( !strncmp("chain", sText, uTextLen) )
2573  {
2574  return ReadLine::dupstr("chain");
2575  }
2576  }
2577 
2578  // no more matches
2579  return NULL;
2580  }
2581 
2582 protected:
2583  int m_nTabIter; ///< tab completion: servo id iterator
2584  int m_nTabServoId; ///< tab completion: current servo id
2585  bool m_bTabIncChain; ///< tab completion: [do not] include chain keyword
2586 
2587  /*!
2588  * \brief Write byte.
2589  *
2590  * \param shell Dynamixel shell.
2591  * \param uAddr Write address.
2592  * \param tup Array of (servo id, value) 2-tuples.
2593  * \param uCount Number of tuples.
2594  */
2595  virtual void doExec(DynaShell &shell,
2596  uint_t uAddr,
2597  DynaSyncWriteTuple_T tup[],
2598  uint_t uCount)
2599  {
2600  int rc;
2601 
2602  if( uCount == 1 )
2603  {
2604  rc = shell.m_pDynaComm->Write8(tup[0].m_nServoId, uAddr, tup[0].m_uVal);
2605 
2606  if( rc != DYNA_OK )
2607  {
2608  shell.Error(rc,
2609  "Servo %d: Failed to write byte 0x%02x to 0x%02x.",
2610  tup[0].m_nServoId, tup[0].m_uVal, uAddr);
2611  return;
2612  }
2613  }
2614  else
2615  {
2616  rc = shell.m_pDynaComm->SyncWrite(uAddr, 1, tup, uCount);
2617 
2618  if( rc != DYNA_OK )
2619  {
2620  shell.Error(rc,
2621  "Failed to syncwrite to 0x%02x for %u servos.",
2622  uAddr, uCount);
2623  return;
2624  }
2625  }
2626 
2627  shell.Ok();
2628  }
2629 };
2630 
2631 
2632 // -----------------------------------------------------------------------------
2633 // DynaShellCmdReadWord Class
2634 // -----------------------------------------------------------------------------
2635 
2636 /*!
2637  * \brief Read servo byte value at address.
2638  */
2640 {
2641 public:
2642 
2643  /*
2644  * \brief Default constructor.
2645  */
2647  {
2648  m_sCmdName = "word";
2649  m_sCmdHelpBrief = "Read a word from the servo control table.";
2650  m_sCmdHelpArgs = "<addr> <servo_id> [servo_id...]\n<addr> chain";
2651  m_sCmdHelpDesc = "Read a 16-bit word at the address for the specified "
2652  "servos.\n"
2653  "If the keyword 'chain' is specified, then"
2654  "the word value at <addr> is read for all servos in the "
2655  "chain.\n"
2656  " <addr> Servo memory address.\n"
2657  " <servo_id> Servo id [0-253]."
2658  "\n\n"
2659  "Caution: This is a low-level function that bypasses all "
2660  "state consistency checks.";
2661  }
2662 
2663  /*
2664  * \brief Default destructor.
2665  */
2666  virtual ~DynaShellCmdReadWord() { }
2667 
2668 protected:
2669 
2670  /*!
2671  * \brief Read word.
2672  *
2673  * \param shell Dynamixel shell.
2674  * \param nServoId Servo id.
2675  * \param uAddr Servo read address.
2676  */
2677  virtual void doExec(DynaShell &shell, int nServoId, uint_t uAddr)
2678  {
2679  uint_t uVal;
2680  int rc;
2681 
2682  rc = shell.m_pDynaComm->Read16(nServoId, uAddr, &uVal);
2683 
2684  if( rc != DYNA_OK )
2685  {
2686  shell.Error(rc, "Servo %d: Failed to read byte at 0x%02x.",
2687  nServoId, uAddr);
2688  return;
2689  }
2690 
2691  shell.Response("Servo %3d: 0x%04x.\n", nServoId, uVal);
2692  }
2693 };
2694 
2695 
2696 // -----------------------------------------------------------------------------
2697 // DynaShellCmdWriteWord Class
2698 // -----------------------------------------------------------------------------
2699 
2700 /*!
2701  * \brief Write byte value to servo at address.
2702  */
2704 {
2705 public:
2706 
2707  /*
2708  * \brief Default constructor.
2709  */
2711  {
2712  m_sCmdName = "word";
2713  m_sCmdHelpBrief = "Write a word to the servo control table.";
2714  m_sCmdHelpArgs = "<addr> <servo_id> <val> [<servo_id> <val> ...]\n"
2715  "<addr> chain <val> ";
2716  m_sCmdHelpDesc = "Write a 16-bit word to the address for the specified "
2717  "servos. "
2718  "If the keyword 'chain' is specified, then "
2719  "the word <val> is written to <addr> for all servos in "
2720  "the chain.\n"
2721  "If more than 1 servo is specified, a synchronous write "
2722  "is performed.\n"
2723  " <addr> Servo memory address.\n"
2724  " <servo_id> Servo id [0-253].\n"
2725  " <val> New servo value."
2726  "\n\n"
2727  "Caution: This is a low-level function that bypasses all "
2728  "state consistency checks.";
2729  }
2730 
2731  /*
2732  * \brief Default destructor.
2733  */
2734  virtual ~DynaShellCmdWriteWord() { }
2735 
2736 protected:
2737  /*!
2738  * \brief Write word.
2739  *
2740  * \param shell Dynamixel shell.
2741  * \param uAddr Write address.
2742  * \param tup Array of (servo id, value) 2-tuples.
2743  * \param uCount Number of tuples.
2744  */
2745  virtual void doExec(DynaShell &shell,
2746  uint_t uAddr,
2747  DynaSyncWriteTuple_T tup[],
2748  uint_t uCount)
2749  {
2750  int rc;
2751 
2752  if( uCount == 1 )
2753  {
2754  rc = shell.m_pDynaComm->Write16(tup[0].m_nServoId, uAddr, tup[0].m_uVal);
2755 
2756  if( rc != DYNA_OK )
2757  {
2758  shell.Error(rc,
2759  "Servo %d: Failed to write word 0x%04x to 0x%02x.",
2760  tup[0].m_nServoId, tup[0].m_uVal, uAddr);
2761  return;
2762  }
2763  }
2764  else
2765  {
2766  rc = shell.m_pDynaComm->SyncWrite(uAddr, 2, tup, uCount);
2767 
2768  if( rc != DYNA_OK )
2769  {
2770  shell.Error(rc,
2771  "Failed to syncwrite to 0x%02x for %u servos.",
2772  uAddr, uCount);
2773  return;
2774  }
2775  }
2776 
2777  shell.Ok();
2778  }
2779 };
2780 
2781 
2782 // -----------------------------------------------------------------------------
2783 // DynaShellCmdDump Class
2784 // -----------------------------------------------------------------------------
2785 
2786 /*!
2787  * \brief Read servo byte value at address.
2788  */
2790 {
2791 public:
2792  /*
2793  * \brief Default constructor.
2794  */
2796  {
2797  m_sCmdName = "tables";
2798  m_sCmdHelpBrief = "Dump servo EEPROM and RAM control tables.";
2799  m_sCmdHelpArgs = "<servo_id> [servo_id...]\n"
2800  "chain";
2801  m_sCmdHelpDesc = "Dump servo control tables "
2802  "for the specified "
2803  "servos. If the keyword 'chain' is specified, then "
2804  "the memory is dumped for all servos in the "
2805  "chain.\n"
2806  " <servo_id> Servo id [0-253].";
2807  }
2808 
2809  /*
2810  * \brief Default destructor.
2811  */
2812  virtual ~DynaShellCmdDump() { }
2813 
2814 protected:
2815  /*!
2816  * \brief Read byte.
2817  *
2818  * \param shell Dynamixel shell.
2819  * \param pServo Pointer to servo.
2820  */
2821  virtual void doExec(DynaShell &shell, DynaServo *pServo)
2822  {
2823  uint_t uAddr;
2824  uint_t uVal;
2825  int rc;
2826 
2827  shell.Response("\n");
2828  shell.Response( "-------------------------"
2829  " Servo %d Control Tables "
2830  "-------------------------\n",
2831  pServo->GetServoId());
2832  pServo->Dump();
2833  }
2834 };
2835 
2836 
2837 // -----------------------------------------------------------------------------
2838 // Public Interface.
2839 // -----------------------------------------------------------------------------
2840 
2841 /*!
2842  * \brief Publish shell servo commands to shell.
2843  *
2844  * \brief shell Dynamixel shell.
2845  */
2847 {
2848  shell.PublishCommand(NULL, new DynaShellCmdMoveTo());
2849  shell.PublishCommand(NULL, new DynaShellCmdMoveAtSpeedTo());
2850  shell.PublishCommand(NULL, new DynaShellCmdEStop());
2851  shell.PublishCommand(NULL, new DynaShellCmdStop());
2852  shell.PublishCommand(NULL, new DynaShellCmdFreeze());
2853  shell.PublishCommand(NULL, new DynaShellCmdRelease());
2854 
2855  shell.PublishCommand("get", new DynaShellCmdGetOdometer());
2856  shell.PublishCommand("set", new DynaShellCmdSetOdometer());
2857 
2858  shell.PublishCommand("write", new DynaShellCmdCfgWriteServoMode());
2859 
2860  shell.PublishCommand("read", new DynaShellCmdReadTorqueEnable());
2861  shell.PublishCommand("write", new DynaShellCmdWriteTorqueEnable());
2862 
2863  shell.PublishCommand("read", new DynaShellCmdReadGoalPos());
2864  //shell.PublishCommand("read", new DynaShellCmdWriteGoalPos());
2865 
2866  shell.PublishCommand("read", new DynaShellCmdReadGoalSpeed());
2867  shell.PublishCommand("write", new DynaShellCmdWriteGoalSpeed());
2868 
2869  shell.PublishCommand("read", new DynaShellCmdReadMaxTorqueLimit());
2870  shell.PublishCommand("write", new DynaShellCmdWriteMaxTorqueLimit());
2871 
2872  shell.PublishCommand("get", new DynaShellCmdGetSoftTorqueTh());
2873  shell.PublishCommand("set", new DynaShellCmdSetSoftTorqueTh());
2874 
2875  shell.PublishCommand("read", new DynaShellCmdReadCurPos());
2876  shell.PublishCommand("read", new DynaShellCmdReadCurSpeed());
2877 
2878  shell.PublishCommand("read", new DynaShellCmdReadDynamics());
2879  shell.PublishCommand("read", new DynaShellCmdReadHealth());
2880  shell.PublishCommand("clear", new DynaShellCmdClearAlarms());
2881 
2882  shell.PublishCommand("read", new DynaShellCmdReadIsMoving());
2883 
2884  shell.PublishCommand("read", new DynaShellCmdReadByte());
2885  shell.PublishCommand("write", new DynaShellCmdWriteByte());
2886 
2887  shell.PublishCommand("read", new DynaShellCmdReadWord());
2888  shell.PublishCommand("write", new DynaShellCmdWriteWord());
2889 
2890  shell.PublishCommand("dump", new DynaShellCmdDump());
2891 }
RoadNarrows Dynamixel Bus Communications Abstract Base Class Interface.
bool m_bTabIncChain
tab completion: [do not] include chain keyword
virtual bool ArgToInt(DynaShell &shell, const char *sArg, int *pVal)
Convert command argument into enable state.
void Exec(DynaShell &shell, int argc, char *argv[])
Execute &#39;write-like&#39; command on servos.
Read servo byte value at address.
Write servos on power-up or run-time maximum torque limits.
virtual uint_t GetServoMode() const
Get the servo operational mode.
Definition: DynaServo.h:165
Determine if servos are moving.
int m_nTabIter
tab completion: iterator
Synchronous Write Speed Tuple Structure.
Definition: DynaTypes.h:314
bool m_bTabIncChain
tab completion: [do not] include chain keyword
Synchronous Write Speed-Position Tuple Structure.
Definition: DynaTypes.h:324
virtual int SyncWriteGoalSpeed(DynaSpeedTuple_T tuplesSpeed[], uint_t uCount)
Synchronous write new goal speed for servos.
Definition: DynaChain.cxx:940
Dynamixel Servo Specification Structure.
Definition: DynaTypes.h:81
void Exec(DynaShell &shell, int argc, char *argv[])
Execute command on servos.
void Exec(DynaShell &shell, int argc, char *argv[])
Emergence stop all servos.
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
virtual void doExec(DynaShell &shell, uint_t uAddr, ExecTup_T tup[], uint_t uCount)
Move servos to goal positions.
Determine if servos are moving.
virtual int SyncMoveTo(DynaPosTuple_T tuplesPos[], uint_t uCount)
Synchronous move servos to new goal positions in tuple list.
Definition: DynaChain.cxx:513
virtual int Freeze()
Freeze all servos at current position.
Definition: DynaChain.cxx:751
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Determine if servo is moving.
virtual void doExec(DynaShell &shell, int nServoId, uint_t uAddr)
Read byte.
#define DYNA_MODE_SERVO
servo mode with limited rotation
Definition: Dynamixel.h:170
int m_nServoId
servo id
virtual void doExec(DynaShell &shell, DynaSpeedPosTuple_T tup[], uint_t uCount)
Move servos to goal positions.
Dynamixel shell utilities.
virtual int MoveAtSpeedTo(int nServoId, int nGoalSpeed, int nGoalOdPos)
Move at speed to the goal postition.
Definition: DynaChain.cxx:559
DynaComm * m_pDynaComm
dynamixel bus communication
Definition: dynashell.h:359
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Read goal position for servo.
Read servo byte value at address.
uint_t m_uRawPosMin
minimum raw position value (servo mode)
Definition: DynaTypes.h:101
void Exec(DynaShell &shell, int argc, char *argv[])
Execute &#39;write-like&#39; command on servos.
#define DYNA_ALARM_LOAD
operating load (torque) out of rnge
Definition: Dynamixel.h:652
#define DYNA_ALARM_NONE
no alarms
Definition: Dynamixel.h:646
virtual void Exec(DynaShell &shell, int argc, char *argv[])
Execute write byte command on servos.
virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
Move servos to goal positions.
virtual int Read8(int nServoId, uint_t uAddr, byte_t *pVal)=0
Read an 8-bit value from Dynamixel servo control table.
int m_nServoId
servo id
Definition: DynaTypes.h:296
Read servos current positions.
Determine if servos are moving.
RoadNarrows Dynamixel Servo Chain Container Base Class Interface.
virtual int MoveTo(int nServoId, int nGoalOdPos)
Move to the goal postition.
Definition: DynaChain.cxx:480
static const int FIRST
first state
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Read dynamics for servo.
void Exec(DynaShell &shell, int argc, char *argv[])
Execute command on servos.
virtual int Read16(int nServoId, uint_t uAddr, ushort_t *pVal)=0
Read a 16-bit value from Dynamixel servo control table.
static char * dupstr(const string &str)
Duplicate string.
virtual void SetSoftTorqueThresholds(uint_t uOverTorqueTh, uint_t uClearTorqueTh)
Set soft torque thresholds.
Definition: DynaServo.h:528
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Read byte.
Dynamixel shell command abstract base class.
Definition: dynashell_cmd.h:80
Read servos goal positions.
virtual void doExec(DynaShell &shell, int nServoId, uint_t uAddr)
Read goal position for servo.
virtual int IterStartMaster(int *pIter)
Start iteration master servos over of entire servo chain.
Definition: DynaChain.cxx:1036
virtual bool ArgToInt(DynaShell &shell, const char *sArg, int *pVal)
Convert command argument into servo mode.
#define DYNA_ID_NUMOF
number of unique servo id&#39;s
Definition: Dynamixel.h:148
const char * rotdirstr(int nSpeed)
Convert rotation direction to string.
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 char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
Dynamixel Servo Abstract Base Class.
Definition: DynaServo.h:78
int m_nSpeed
speed
Definition: DynaTypes.h:327
Read servos goal positions.
Execute 2-tuple structure type.
bool m_bTabIncChain
tab completion: [do not] include chain keyword
virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
Enable/disable servos torques.
int m_nTabIter
tab completion: iterator
virtual int Write8(int nServoId, uint_t uAddr, byte_t byVal)=0
Write an 8-bit value to Dynamixel servo control table.
Read servos current positions.
Determine if servos are moving.
Determine if servos are moving.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
static int wc(const string &str)
Count the words in the string.
Read servos goal positions.
void Response(const char *sFmt,...)
Print formatted success response.
Definition: dynashell.cxx:763
virtual int Write16(int nServoId, uint_t uAddr, ushort_t uhVal)=0
Write a 16-bit value to Dynamixel servo control table.
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Read goal position for servo.
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Derived class specific execution function.
int m_nTabIter
tab completion: servo id iterator
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Determine torque enable state for servo.
virtual void Ok()
Print standard ok success response.
Definition: dynashell.h:425
int m_nPos
position
Definition: DynaTypes.h:328
virtual void Exec(DynaShell &shell, int argc, char *argv[])
Execute command on servos.
void PublishShellServoCommands(DynaShell &shell)
Publish shell servo commands to shell.
uint_t m_uVal
write value
Definition: DynaTypes.h:297
int m_nTabServoId
tab completion: current servo id
virtual int Release()
Release all servos from any applied torque.
Definition: DynaChain.cxx:770
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Determine if servo is moving.
#define DYNA_ADDR_LIM_TORQUE_MAX_LSB
current torque limit lsb (RW)
Definition: Dynamixel.h:965
Emergency stop command.
virtual void doExec(DynaShell &shell, uint_t uAddr, DynaSyncWriteTuple_T tup[], uint_t uCount)
Write byte.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
Read servos goal positions.
int m_nTabServoId
tab completion: current servo id
Determine if servos are moving.
#define DYNA_ADDR_LIM_TORQUE_MAX_ON_LSB
maximum torque lsb (RW)
Definition: Dynamixel.h:589
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
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Read current position for servo.
#define DYNA_MODE_CONTINUOUS
continuous mode with/without position
Definition: Dynamixel.h:171
int GetOdometerZeroPt()
Get the virtual odometer zero point.
Definition: DynaServo.h:324
Read servos goal positions.
Determine if servos are moving.
virtual void doExec(DynaShell &shell, uint_t uAddr, DynaSyncWriteTuple_T tup[], uint_t uCount)
Write word.
int m_nVal
value
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
bool IsOdometerReversed()
Test if the virtual odometer is reversed.
Definition: DynaServo.h:334
virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
Execute operation.
int m_nSpeed
speed
Definition: DynaTypes.h:317
virtual void doExec(DynaShell &shell, int nServoId, uint_t uAddr)
Read word.
int m_nServoId
servo id
Definition: DynaTypes.h:306
virtual const DynaServoSpec_T & GetSpecification() const
Get servo specification.
Definition: DynaServo.h:185
DynaShellCmdCfgWriteServoMode()
Default constructor.
Dynamixel chain input command abstract base class.
int m_nServoId
servo id
Definition: DynaTypes.h:316
int m_nPos
position
Definition: DynaTypes.h:307
virtual uint_t GetAlarms() const
Get the current servo alarms.
Definition: DynaServo.h:435
virtual int SyncWrite(uint_t uAddr, uint_t uValSize, DynaSyncWriteTuple_T tuples[], uint_t uCount)=0
Synchronous Write 8/16-bit values to a list of Dynamixel servos.
#define TRY(boolexpr,...)
Try boolean expression.
Definition: dynashell_cmd.h:89
Write byte value to servo at address.
virtual void Exec(DynaShell &shell, int argc, char *argv[])
Execute read byte command on servos.
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Read current position for servo.
void PublishCommand(const char *sParent, DynaShellCmd *pNewCmd)
Publish new command to shell.
Definition: dynashell.cxx:192
RoadNarrows Dynamixel Top-Level Package Header File.
int m_nServoId
servo id
Definition: DynaTypes.h:326
Read servo byte value at address.
The dynashell Command Class Interface.
virtual uint_t GetServoId() const
Get servo id.
Definition: DynaServo.h:155
Dynamixel chain output command abstract base class.
uint_t m_uRawPosMax
maximum raw position value (servo mode)
Definition: DynaTypes.h:102
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Determine torque enable state for servo.
virtual ~DynaShellCmdCfgWriteServoMode()
Default destructor.
#define DYNA_ID_NONE
no servo id
Definition: Dynamixel.h:145
Read servos goal positions.
int m_nTabServoId
tab completion: current servo id
virtual int EStop()
Emergency stop all servos.
Definition: DynaChain.cxx:714
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
void Exec(DynaShell &shell, int argc, char *argv[])
Freeze servos.
Write EEPROM configuration to put servos into the given modes.
virtual int IterNext(int *pIter)
Next iteration over of entire servo chain.
Definition: DynaChain.cxx:1020
virtual int ResetOdometer(int nEncZeroPt, bool bIsReverse)
Reset the servo&#39;s virtual odometer.
Definition: DynaServo.cxx:188
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
int m_nTabIter
tab completion: servo id iterator
Write byte value to servo at address.
Position Tuple Structure.
Definition: DynaTypes.h:304
virtual void doExec(DynaShell &shell, ExecTup_T tup[], uint_t uCount)
Write goal speeds.
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Determine torque enable state for servo.
void Exec(DynaShell &shell, int argc, char *argv[])
Release servos.
Read servos goal positions.
virtual int SyncMoveAtSpeedTo(DynaSpeedPosTuple_T tuplesSpeedPos[], uint_t uCount)
Synchronous move servos to new goal positions at the given speeds.
Definition: DynaChain.cxx:596
The simple dynashell declarations.
virtual void doExec(DynaShell &shell, DynaServo *pServo)
Read dynamics for servo.
int GetOdometer()
Get the current virtual odometer value.
Definition: DynaServo.h:304
int m_nTabServoId
tab completion: current servo id
virtual void GetSoftTorqueThresholds(uint_t &uOverTorqueTh, uint_t &uClearTorqueTh)
Get soft torque thresholds.
Definition: DynaServo.h:546
bool m_bTabIncChain
tab completion: [do not] include chain keyword
Determine if servos are moving.
Read servos on power-up or run-time maximum torque limits.
Stop servo(s) command.