Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
DynaServoGeneric.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // Library: libDynamixel
6 //
7 // File: DynaServoGeneric.cxx
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-03-13 13:28:02 -0600 (Fri, 13 Mar 2015) $
12  * $Rev: 3890 $
13  *
14  * \brief Generic Dynamixel servo base class.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  *
18  * \copyright
19  * \h_copy 2011-2017. RoadNarrows LLC.\n
20  * http://www.roadnarrows.com\n
21  * All Rights Reserved
22  */
23 /*
24  * @EulaBegin@
25  *
26  * Unless otherwise stated explicitly, all materials contained are copyrighted
27  * and may not be used without RoadNarrows LLC's written consent,
28  * except as provided in these terms and conditions or in the copyright
29  * notice (documents and software) or other proprietary notice provided with
30  * the relevant materials.
31  *
32  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY
33  * MEMBERS/EMPLOYEES/CONTRACTORS OF ROADNARROWS OR DISTRIBUTORS OF THIS SOFTWARE
34  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
35  * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
36  * DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN
37  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  * THE AUTHORS AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
40  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
41  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
42  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
43  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
44  *
45  * @EulaEnd@
46  */
47 ////////////////////////////////////////////////////////////////////////////////
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <libgen.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <iostream>
55 
56 #include "rnr/rnrconfig.h"
57 #include "rnr/log.h"
58 #include "rnr/new.h"
59 #include "rnr/units.h"
60 
61 #include "Dynamixel/Dynamixel.h"
62 #include "Dynamixel/DynaTypes.h"
63 #include "Dynamixel/MX.h"
64 
65 #include "Dynamixel/DynaError.h"
66 #include "Dynamixel/DynaComm.h"
67 #include "Dynamixel/DynaServo.h"
69 #include "Dynamixel/DynaOlio.h"
70 
71 #include "DynaLibInternal.h"
72 
73 using namespace std;
74 
75 
76 // ---------------------------------------------------------------------------
77 // Private Interface
78 // ---------------------------------------------------------------------------
79 
80 /*!
81  * \brief Generic Servo EEPROM Control Table Information.
82  */
84 {
85  {0x00, "Model Number", 2, 0xffff, false, NULL},
86  {0x02, "Firmware Version", 1, 0xff, false, "%u"},
87  {0x03, "Servo Id", 1, 0xff, false, "%u"},
88  {0x04, "Baud Rate", 1, 0xff, false, "%u"},
89  {0x05, "Return Delay Time", 1, 0xff, false, "%u"},
90  {0x06, "CW Angle Limit", 2, 0x3ff, false, "%u"},
91  {0x08, "CCW Angle Limit", 2, 0x3ff, false, "%u"},
92  {0x0b, "Highest Temperature Limit", 1, 0xff, false, "%u"},
93  {0x0c, "Lowest Voltage Limit", 1, 0xff, false, "%u"},
94  {0x0d, "Highest Voltage Limit", 1, 0xff, false, "%u"},
95  {0x0e, "Maximum Torque", 2, 0x3ff, false, "%u"},
96  {0x10, "Status Return Level", 1, 0xff, false, "%u"},
97  {0x11, "Alarm LED", 1, 0xff, false, "%u"},
98  {0x12, "Alarm Shutdown", 1, 0xff, false, NULL}
99 };
100 
101 /*!
102  * \brief Generic Servo RAM Control Table Information.
103  */
105 {
106  {0x18, "Torque Enable", 1, 0xff, false, "%u"},
107  {0x19, "LED", 1, 0xff, false, "%u"},
108  {0x1a, "CW Compliance Margin", 1, 0xff, false, "%u"},
109  {0x1b, "CCW Compliance Margin", 1, 0xff, false, "%u"},
110  {0x1c, "CW Compliance Slope", 1, 0xff, false, "%u"},
111  {0x1d, "CCW Compliance Slope", 1, 0xff, false, "%u"},
112  {0x1e, "Goal Position", 2, 0x3ff, false, "%u"},
113  {0x20, "Goal Speed", 2, 0x7ff, true, "%d"},
114  {0x22, "Torque Limit", 2, 0x3ff, false, "%u"},
115  {0x24, "Current Position", 2, 0x3ff, false, "%u"},
116  {0x26, "Current Speed", 2, 0x7ff, true, "%d"},
117  {0x28, "Current Load", 2, 0x7ff, true, "%d"},
118  {0x2a, "Current Voltage", 1, 0xff, false, "%u"},
119  {0x2b, "Current Temperature", 1, 0xff, false, "%u"},
120  {0x2c, "Registered", 1, 0xff, false, "%u"},
121  {0x2e, "Moving", 1, 0xff, false, "%u"},
122  {0x2f, "Lock", 1, 0xff, false, "%u"},
123  {0x30, "Punch", 2, 0x3ff, false, "%u"}
124 };
125 
126 // ---------------------------------------------------------------------------
127 // DynaServoGeneric Class
128 // ---------------------------------------------------------------------------
129 
130 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
131 // Constructors and Destructors
132 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
133 
135  int nServoId,
136  uint_t uModelNum,
137  uint_t uFwVer) :
138  DynaServo(comm, nServoId, uModelNum, uFwVer)
139 {
140  Init();
141  SyncData();
142  CheckData();
143 }
144 
146 {
147  //Stop();
148 }
149 
150 
151 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
152 // Servo Proxy Agent Functions
153 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
154 
156 {
157  int rc;
158 
160  DYNA_TRY_IS_MASTER(this);
163 
164  m_state.m_od.m_nOdGoalPos = nGoalOdPos;
165  rc = m_pAgent->m_fnWriteGoalPos(m_nServoId, nGoalOdPos, m_pAgentArg);
166 
167  return rc;
168 }
169 
171 {
172  int rc;
173 
175  DYNA_TRY_IS_MASTER(this);
178 
179  DYNA_TRY_EXPR( (iabs(nGoalSpeed) <= DYNA_SPEED_MAX_RAW),
181  "Goal speed %d: Out of range.", nGoalSpeed);
182 
184 
185  return rc;
186 }
187 
188 int DynaServoGeneric::AgentWriteGoalSpeedPos(int nGoalSpeed, int nGoalOdPos)
189 {
190  int rc;
191 
193  DYNA_TRY_IS_MASTER(this);
196 
197  DYNA_TRY_EXPR( (iabs(nGoalSpeed) <= DYNA_SPEED_MAX_RAW),
199  "Goal speed %d: Out of range.", nGoalSpeed);
200 
201  m_state.m_od.m_nOdGoalPos = nGoalOdPos;
202 
204  nGoalSpeed, nGoalOdPos,
205  m_pAgentArg);
206 
207  return rc;
208 }
209 
210 
211 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
212 // Servo Move Functions
213 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
214 
215 int DynaServoGeneric::MoveTo(int nGoalOdPos)
216 {
217  int rc;
218 
220  DYNA_TRY_IS_MASTER(this);
222 
223  if( HasAgent() )
224  {
225  rc = AgentWriteGoalPos(nGoalOdPos);
226  }
227  else
228  {
229  rc = WriteGoalPos(nGoalOdPos);
230  }
231 
232  return rc;
233 }
234 
235 int DynaServoGeneric::MoveAtSpeedTo(int nGoalSpeed, int nGoalOdPos)
236 {
237  int rc; // return code
238 
240  DYNA_TRY_IS_MASTER(this);
242 
243  if( HasAgent() )
244  {
245  rc = AgentWriteGoalSpeedPos(nGoalSpeed, nGoalOdPos);
246  }
247  else if( (rc = WriteGoalSpeed(nGoalSpeed)) == DYNA_OK )
248  {
249  rc = WriteGoalPos(nGoalOdPos);
250  }
251 
252  return rc;
253 }
254 
255 int DynaServoGeneric::MoveAtSpeed(int nGoalSpeed)
256 {
258  DYNA_TRY_IS_MASTER(this);
260 
261  return WriteGoalSpeed(nGoalSpeed);
262 }
263 
265 {
266  int nMaxTries = 3;
267  int nTries;
268  int rc;
269 
271  DYNA_TRY_IS_MASTER(this);
272 
273  Stop();
274 
275  for(nTries=0; nTries<nMaxTries; ++nTries)
276  {
277  if( (rc = WriteTorqueEnable(false)) == DYNA_OK )
278  {
279  break;
280  }
281  }
282  return rc;
283 }
284 
286 {
287  int nCurPos; // current position
288  int rc; // return code
289 
291  DYNA_TRY_IS_MASTER(this);
292 
293  if( HasAgent() )
294  {
296  }
297 
298  else
299  {
300  switch( GetServoMode() )
301  {
302  //
303  // In continuous mode: Set the goal speed to zero.
304  //
307  break;
308 
309  //
310  // In servo mode: Set the goal position to the current position (a 0 speed
311  // value sets the speed to the default maximum).
312  //
313  case DYNA_MODE_SERVO:
314  default:
315  if( (rc = ReadCurPos(&nCurPos)) == DYNA_OK )
316  {
317  rc = WriteGoalPos(nCurPos);
318  }
319  break;
320  }
321  }
322 
323  return rc;
324 }
325 
327 {
328  int rc_tmp; // temporary return code
329  int rc; // return code
330 
332  DYNA_TRY_IS_MASTER(this);
333 
334  rc = WriteTorqueEnable(true);
335 
336  rc_tmp = Stop();
337 
338  if( rc == DYNA_OK )
339  {
340  rc = rc_tmp;
341  }
342 
343  return rc;
344 }
345 
347 {
349  DYNA_TRY_IS_MASTER(this);
350 
351  Stop();
352 
353  return WriteTorqueEnable(false);
354 }
355 
356 
357 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
358 // Servo Read/Write Functions
359 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
360 
361 int DynaServoGeneric::CfgReadRotationLimits(uint_t *pCwLim, uint_t *pCcwLim)
362 {
363  uint_t uVal1, uVal2; // working values
364  int rc; // return code
365 
367 
368  // Clockwise limit
370 
371  // Counter-clockwise limit
372  if( rc == DYNA_OK )
373  {
375  }
376 
377  // Update configuration and state.
378  if( rc == DYNA_OK )
379  {
380  m_cfg.m_uLimCw = *pCwLim;
381  m_cfg.m_uLimCcw = *pCcwLim;
382 
383  SetServoMode();
384 
385  if( IsLinkedMaster() )
386  {
387  rc = m_link.m_pServoMate->CfgReadRotationLimits(&uVal1, &uVal2);
388  }
389  }
390 
391  return rc;
392 }
393 
394 int DynaServoGeneric::CfgWriteRotationLimits(uint_t uCwLim, uint_t uCcwLim)
395 {
396  int rc; // return code
397 
399  DYNA_TRY_IS_MASTER(this);
400 
401  DYNA_TRY_EXPR(((uCwLim >= m_spec.m_uRawPosMin) &&
402  (uCwLim <= m_spec.m_uRawPosMax)),
404  "Clockwise limit %u: Out of range.", uCwLim);
405 
406  DYNA_TRY_EXPR(((uCcwLim >= m_spec.m_uRawPosMin) &&
407  (uCcwLim <= m_spec.m_uRawPosMax)),
409  "Counterclockwise limit %u: Out of range.", uCcwLim);
410 
411  DYNA_TRY_EXPR((uCcwLim >= uCwLim), DYNA_ECODE_BAD_VAL,
412  "Counterclockwise limit %u: Smaller than clockwise limit %u.",
413  uCcwLim, uCwLim);
414 
415  //
416  // Linked pair
417  //
418  if( IsLinkedMaster() )
419  {
420  // Clockwise limit
422  m_nServoId, uCwLim,
423  m_link.m_pServoMate->GetServoId(), uCwLim);
424 
425  // Counter-clockwise limit
426  if( rc == DYNA_OK )
427  {
428  m_cfg.m_uLimCw = uCwLim;
429  m_link.m_pServoMate->m_cfg.m_uLimCw = uCwLim;
430 
432  m_nServoId, uCcwLim,
433  m_link.m_pServoMate->GetServoId(), uCcwLim);
434 
435  if( rc == DYNA_OK )
436  {
437  m_cfg.m_uLimCcw = uCcwLim;
438  m_link.m_pServoMate->m_cfg.m_uLimCcw = uCcwLim;
439  }
440  }
441  }
442 
443  //
444  // Solitary servo
445  //
446  else
447  {
448  // Clockwise limit
450 
451  // Counter-clockwise limit
452  if( rc == DYNA_OK )
453  {
454  m_cfg.m_uLimCw = uCwLim;
456  }
457 
458  // Update configuration and state.
459  if( rc == DYNA_OK )
460  {
461  m_cfg.m_uLimCcw = uCcwLim;
462  SetServoMode();
463  }
464  }
465 
466  return rc;
467 }
468 
470 {
471  uint_t uVal; // working value
472  int rc; // return code
473 
475 
477 
478  if( rc == DYNA_OK )
479  {
480  m_cfg.m_uLimTemp = *pTempLim;
481 
482  if( IsLinkedMaster() )
483  {
484  rc = m_link.m_pServoMate->CfgReadTemperatureLimit(&uVal);
485  }
486  }
487 
488  return rc;
489 }
490 
492 {
493  int rc; // return code
494 
496  DYNA_TRY_IS_MASTER(this);
497 
498  DYNA_TRY_EXPR(((uTempLim >= m_spec.m_uRawTempMin) &&
499  (uTempLim <= m_spec.m_uRawTempMax)),
501  "Temperature limit %u: Out of range.", uTempLim);
502 
503  //
504  // Linked pair
505  //
506  if( IsLinkedMaster() )
507  {
509  m_nServoId, uTempLim,
510  m_link.m_pServoMate->GetServoId(), uTempLim);
511 
512  if( rc == DYNA_OK )
513  {
514  m_cfg.m_uLimTemp = uTempLim;
515  m_link.m_pServoMate->m_cfg.m_uLimTemp = uTempLim;
516  }
517  }
518 
519  //
520  // Solitary servo
521  //
522  else
523  {
525 
526  if( rc == DYNA_OK )
527  {
528  m_cfg.m_uLimTemp = uTempLim;
529  }
530  }
531 
532  return rc;
533 }
534 
536  uint_t *pMaxVoltLim)
537 {
538  uint_t uVal1, uVal2; // working values
539  int rc; // return code
540 
542 
543  rc = m_comm.Read8(m_nServoId, DYNA_ADDR_LIM_VOLT_MIN, pMinVoltLim);
544 
545  if( rc == DYNA_OK )
546  {
547  rc = m_comm.Read8(m_nServoId, DYNA_ADDR_LIM_VOLT_MAX, pMaxVoltLim);
548  }
549 
550  if( rc == DYNA_OK )
551  {
552  m_cfg.m_uLimVoltMin = *pMinVoltLim;
553  m_cfg.m_uLimVoltMax = *pMaxVoltLim;
554 
555  if( IsLinkedMaster() )
556  {
557  rc = m_link.m_pServoMate->CfgReadVoltageLimits(&uVal1, &uVal2);
558  }
559  }
560 
561  return rc;
562 }
563 
565  uint_t uMaxVoltLim)
566 {
567  int rc; // return code
568 
570  DYNA_TRY_IS_MASTER(this);
571 
572  DYNA_TRY_EXPR(((uMinVoltLim >= m_spec.m_uRawVoltMin) &&
573  (uMinVoltLim <= m_spec.m_uRawVoltMax)),
575  "Minimum voltage limit %u: Out of range.", uMinVoltLim);
576 
577  DYNA_TRY_EXPR(((uMaxVoltLim >= m_spec.m_uRawVoltMin) &&
578  (uMaxVoltLim <= m_spec.m_uRawVoltMax)),
580  "Maximum voltage limit %u: Out of range.", uMaxVoltLim);
581 
582  DYNA_TRY_EXPR((uMinVoltLim <= uMaxVoltLim), DYNA_ECODE_BAD_VAL,
583  "Maximum voltage limit %u: Smaller than minimum voltage limit %u.",
584  uMaxVoltLim, uMinVoltLim);
585 
586  //
587  // Linked pair
588  //
589  if( IsLinkedMaster() )
590  {
592  m_nServoId, uMinVoltLim,
593  m_link.m_pServoMate->GetServoId(), uMinVoltLim);
594 
595  if( rc == DYNA_OK )
596  {
597  m_cfg.m_uLimVoltMin = uMinVoltLim;
598  m_link.m_pServoMate->m_cfg.m_uLimVoltMin = uMinVoltLim;
599 
601  m_nServoId, uMaxVoltLim,
602  m_link.m_pServoMate->GetServoId(), uMaxVoltLim);
603  }
604 
605  if( rc == DYNA_OK )
606  {
607  m_cfg.m_uLimVoltMax = uMaxVoltLim;
608  m_link.m_pServoMate->m_cfg.m_uLimVoltMax = uMaxVoltLim;
609  }
610  }
611 
612  //
613  // Solitary servo
614  //
615  else
616  {
617  rc = m_comm.Write8(m_nServoId, DYNA_ADDR_LIM_VOLT_MIN, uMinVoltLim);
618 
619  if( rc == DYNA_OK )
620  {
621  m_cfg.m_uLimVoltMin = uMinVoltLim;
622  rc = m_comm.Write8(m_nServoId, DYNA_ADDR_LIM_VOLT_MAX, uMaxVoltLim);
623  }
624 
625  if( rc == DYNA_OK )
626  {
627  m_cfg.m_uLimVoltMax = uMaxVoltLim;
628  }
629  }
630 
631  return rc;
632 }
633 
634 int DynaServoGeneric::CfgReadMaxTorqueLimit(uint_t *pMaxTorqueLim)
635 {
636  uint_t uVal; // working value
637  int rc; // return code
638 
640 
642  pMaxTorqueLim);
643 
644  if( rc == DYNA_OK )
645  {
646  m_cfg.m_uLimTorqueMax = *pMaxTorqueLim;
647 
648  if( IsLinkedMaster() )
649  {
650  rc = m_link.m_pServoMate->CfgReadMaxTorqueLimit(&uVal);
651  }
652  }
653 
654  return rc;
655 }
656 
658 {
659  int rc; // return code
660 
662  DYNA_TRY_IS_MASTER(this);
663 
664  DYNA_TRY_EXPR(((uMaxTorqueLim >= m_spec.m_uRawTorqueMin) &&
665  (uMaxTorqueLim <= m_spec.m_uRawTorqueMax)),
667  "Maximum torque limit %u: Out of range.", uMaxTorqueLim);
668 
669  //
670  // Linked pair
671  //
672  if( IsLinkedMaster() )
673  {
675  m_nServoId, uMaxTorqueLim,
676  m_link.m_pServoMate->GetServoId(), uMaxTorqueLim);
677 
678  if( rc == DYNA_OK )
679  {
680  m_cfg.m_uLimTorqueMax = uMaxTorqueLim;
681  m_link.m_pServoMate->m_cfg.m_uLimTorqueMax = uMaxTorqueLim;
682  }
683  }
684 
685  //
686  // Solitary servo
687  //
688  else
689  {
691  uMaxTorqueLim);
692 
693  if( rc == DYNA_OK )
694  {
695  m_cfg.m_uLimTorqueMax = uMaxTorqueLim;
696  }
697  }
698 
699  return rc;
700 }
701 
703 {
704  uint_t uVal; // working value
705  int rc; // return code
706 
708 
709  rc = m_comm.Read8(m_nServoId, DYNA_ADDR_ALARM_SHUTDOWN, pAlarmMask);
710 
711  if( rc == DYNA_OK )
712  {
713  m_cfg.m_uAlarmShutdown = *pAlarmMask;
714 
715  if( IsLinkedMaster() )
716  {
717  rc = m_link.m_pServoMate->CfgReadAlarmShutdownMask(&uVal);
718  }
719  }
720 
721  return rc;
722 }
723 
725 {
726  int rc; // return code
727 
729  DYNA_TRY_IS_MASTER(this);
730 
731  uAlarmMask &= DYNA_ADDR_ALARM_SHUTDOWN_MASK;
732 
733  //
734  // Linked pair
735  //
736  if( IsLinkedMaster() )
737  {
739  m_nServoId, uAlarmMask,
740  m_link.m_pServoMate->GetServoId(), uAlarmMask);
741 
742  if( rc == DYNA_OK )
743  {
744  m_cfg.m_uAlarmShutdown = uAlarmMask;
746  }
747  }
748 
749  //
750  // Solitary servo
751  //
752  else
753  {
755 
756  if( rc == DYNA_OK )
757  {
758  m_cfg.m_uAlarmShutdown = uAlarmMask;
759  }
760  }
761 
762  return rc;
763 }
764 
765 int DynaServoGeneric::CfgReadServoMode(uint_t *pServoMode)
766 {
767  uint_t uCwLim; // clockwise limit
768  uint_t uCcwLim; // counterclockwise limit
769  int rc; // return limit
770 
772 
773  // mode set here
774  rc = CfgReadRotationLimits(&uCwLim, &uCcwLim);
775 
776  *pServoMode = m_cfg.m_uServoMode;
777 
778  if( rc == DYNA_OK )
779  {
780  if( IsLinkedMaster() )
781  {
782  rc = m_link.m_pServoMate->CfgReadRotationLimits(&uCwLim, &uCcwLim);
783  }
784  }
785 
786  return rc;
787 }
788 
789 int DynaServoGeneric::CfgWriteServoMode(uint_t uCwLim, uint_t uCcwLim)
790 {
792  DYNA_TRY_IS_MASTER(this);
793 
794  return CfgWriteRotationLimits(uCwLim, uCcwLim);
795 }
796 
798 {
800  DYNA_TRY_IS_MASTER(this);
802 
804 }
805 
807 {
808  uint_t uVal; // working value
809  bool bVal; // working boolean
810  int rc; // return code
811 
813 
815 
816  if( rc == DYNA_OK )
817  {
818  *pState = uVal==DYNA_TORQUE_EN_OFF? false: true;
819 
820  m_state.m_bTorqueEnabled = *pState;
821 
822  if( IsLinkedMaster() )
823  {
824  rc = m_link.m_pServoMate->ReadTorqueEnable(&bVal);
825  }
826  }
827 
828  return rc;
829 }
830 
832 {
833  uint_t uVal; // working value
834  int rc; // return code
835 
837  DYNA_TRY_IS_MASTER(this);
838 
839  uVal = bState? DYNA_TORQUE_EN_ON: DYNA_TORQUE_EN_OFF;
840 
841  //
842  // Linked pair
843  //
844  if( IsLinkedMaster() )
845  {
847  m_nServoId, uVal,
848  m_link.m_pServoMate->GetServoId(),uVal);
849 
850  if( rc == DYNA_OK )
851  {
852  m_state.m_bTorqueEnabled = bState;
854  }
855  }
856 
857  //
858  // Solitary servo
859  //
860  else
861  {
863 
864  if( rc == DYNA_OK )
865  {
866  m_state.m_bTorqueEnabled = bState;
867  }
868  }
869 
870  return rc;
871 }
872 
873 int DynaServoGeneric::ReadLed(bool *pState)
874 {
875  uint_t uVal; // working value
876  bool bVal; // working boolean
877  int rc; // return code
878 
880 
881  rc = m_comm.Read8(m_nServoId, DYNA_ADDR_LED, &uVal);
882 
883  if( rc == DYNA_OK )
884  {
885  *pState = uVal==DYNA_LED_OFF? false: true;
886 
887  m_state.m_bLed = *pState;
888 
889  if( IsLinkedMaster() )
890  {
891  rc = m_link.m_pServoMate->ReadLed(&bVal);
892  }
893  }
894 
895  return rc;
896 }
897 
899 {
900  uint_t uVal; // working value
901  int rc; // return code
902 
904  DYNA_TRY_IS_MASTER(this);
905 
906  uVal = bState? DYNA_LED_ON: DYNA_LED_OFF;
907 
908  //
909  // Linked pair
910  //
911  if( IsLinkedMaster() )
912  {
913  rc = m_comm.vSyncWrite(DYNA_ADDR_LED, 1, 2,
914  m_nServoId, uVal,
915  m_link.m_pServoMate->GetServoId(), uVal);
916 
917  if( rc == DYNA_OK )
918  {
919  m_state.m_bLed = bState;
920  m_link.m_pServoMate->m_state.m_bLed = bState;
921  }
922  }
923 
924  //
925  // Solitary servo
926  //
927  else
928  {
929  rc = m_comm.Write8(m_nServoId, DYNA_ADDR_LED, uVal);
930 
931  if( rc == DYNA_OK )
932  {
933  m_state.m_bLed = bState;
934  }
935  }
936 
937  return rc;
938 }
939 
941 {
942  int rc; // return code
943 
945 
946  switch( m_spec.m_uCtlMethodUsed )
947  {
949  return ReadCtlMethodCompliance(pCtlMethod);
950  case DYNA_CTL_METHOD_PID:
951  return ReadCtlMethodPid(pCtlMethod);
952  default:
953  rc = -DYNA_ECODE_INTERNAL;
954  DYNA_LOG_ERROR(rc, "Servo %d: Unknown control method %u.",
956  return rc;
957  }
958 }
959 
961 {
962  int rc; // return code
963 
965  DYNA_TRY_IS_MASTER(this);
966 
967  switch( m_spec.m_uCtlMethodUsed )
968  {
970  return WriteCtlMethodCompliance(ctlMethod);
971  case DYNA_CTL_METHOD_PID:
972  return WriteCtlMethodPid(ctlMethod);
973  default:
974  rc = -DYNA_ECODE_INTERNAL;
975  DYNA_LOG_ERROR(rc, "Servo %d: Unknown control method %u.",
977  return rc;
978  }
979 }
980 
982 {
983  uint_t uVal; // working value
984  int nValMate; // working mate's value
985  int rc; // return code
986 
988 
990  {
991  *pGoalPos = m_state.m_od.m_nOdGoalPos;
992  rc = DYNA_OK;
993  }
994  else
995  {
997 
998  if( rc == DYNA_OK )
999  {
1000  m_state.m_uGoalPos = uVal;
1001  *pGoalPos = uVal;
1002 
1003  if( IsLinkedMaster() )
1004  {
1005  rc = m_link.m_pServoMate->ReadGoalPos(&nValMate);
1006  }
1007  }
1008  }
1009 
1010  return rc;
1011 }
1012 
1014 {
1015  int nEncPos; // encoder position
1016  int rc; // return code
1017 
1019  DYNA_TRY_IS_MASTER(this);
1020 
1021  nEncPos = OdometerToEncoder(nGoalOdPos);
1022 
1024  {
1025  DYNA_TRY_EXPR(((nEncPos >= m_spec.m_uRawPosMin) &&
1026  (nEncPos <= m_spec.m_uRawPosMax)),
1028  "Servo %d: Goal odometer position %d (encoder=%d): Out of range.",
1029  m_nServoId, nGoalOdPos, nEncPos);
1030  }
1031 
1032  //
1033  // Linked pair
1034  //
1035  if( IsLinkedMaster() )
1036  {
1037  int nGoalOdPosMate; // mate's calculated goal odometer position
1038  int nEncGoalPosMate; // mate's calculated goal encoder position
1039 
1040  if( (rc = CalcMatesGoalPos(nGoalOdPos, &nGoalOdPosMate)) == DYNA_OK )
1041  {
1042  nEncGoalPosMate = m_link.m_pServoMate->OdometerToEncoder(nGoalOdPosMate);
1044  m_nServoId, (uint_t)nEncPos,
1045  m_link.m_pServoMate->GetServoId(), // RDK FIX ME
1046  (uint_t)nEncGoalPosMate);
1047 
1048  if( rc == DYNA_OK )
1049  {
1050  m_state.m_uGoalPos = (uint_t)nEncPos;
1051  m_link.m_pServoMate->m_state.m_uGoalPos = (uint_t)nEncGoalPosMate;
1052  }
1053  }
1054  }
1055 
1056  //
1057  // Solitary servo
1058  //
1059  else
1060  {
1061  rc = m_comm.Write16(m_nServoId, DYNA_ADDR_GOAL_POS_LSB, (uint_t)nEncPos);
1062 
1063  if( rc == DYNA_OK )
1064  {
1065  m_state.m_uGoalPos = (uint_t)nEncPos;
1066  }
1067  }
1068 
1069  return rc;
1070 }
1071 
1073 {
1074  uint_t uVal; // working value
1075  int nVal; // working value
1076  int rc; // return code
1077 
1079 
1081 
1082  if( rc == DYNA_OK )
1083  {
1085  *pGoalSpeed = m_state.m_nGoalSpeed;
1086 
1087  if( IsLinkedMaster() )
1088  {
1089  rc = m_link.m_pServoMate->ReadGoalSpeed(&nVal);
1090  }
1091  }
1092 
1093  return rc;
1094 }
1095 
1097 {
1098  int nGoalSpeedMate; // mate's calculated speed
1099  uint_t uVal1, uVal2; // working values
1100  int rc; // return code
1101 
1103  DYNA_TRY_IS_MASTER(this);
1104 
1105  DYNA_TRY_EXPR( (iabs(nGoalSpeed) <= DYNA_SPEED_MAX_RAW),
1107  "Goal speed %d: Out of range.", nGoalSpeed);
1108 
1109  uVal1 = PackGoalSpeed(nGoalSpeed);
1110 
1111  //
1112  // Linked pair
1113  //
1114  if( IsLinkedMaster() )
1115  {
1116  nGoalSpeedMate = CalcMatesGoalSpeed(nGoalSpeed);
1117 
1118  uVal2 = PackGoalSpeed(nGoalSpeedMate);
1119 
1121  m_nServoId, uVal1,
1122  m_link.m_pServoMate->GetServoId(), uVal2);
1123 
1124  if( rc == DYNA_OK )
1125  {
1126  m_state.m_nGoalSpeed = nGoalSpeed;
1127  m_link.m_pServoMate->m_state.m_nGoalSpeed = nGoalSpeedMate;
1128  }
1129  }
1130 
1131  //
1132  // Solitary servo
1133  //
1134  else
1135  {
1137 
1138  if( rc == DYNA_OK )
1139  {
1140  m_state.m_nGoalSpeed = nGoalSpeed;
1141  }
1142  }
1143 
1144  return rc;
1145 }
1146 
1147 int DynaServoGeneric::ReadMaxTorqueLimit(uint_t *pMaxTorqueLim)
1148 {
1149  uint_t uVal; // working value
1150  int rc; // return code
1151 
1153 
1154  rc = m_comm.Read16(m_nServoId, DYNA_ADDR_LIM_TORQUE_MAX_LSB, pMaxTorqueLim);
1155 
1156  if( rc == DYNA_OK )
1157  {
1158  m_state.m_uLimTorqueMax = *pMaxTorqueLim;
1159 
1160  if( IsLinkedMaster() )
1161  {
1162  rc = m_link.m_pServoMate->ReadMaxTorqueLimit(&uVal);
1163  }
1164  }
1165 
1166  return rc;
1167 }
1168 
1169 int DynaServoGeneric::WriteMaxTorqueLimit(uint_t uMaxTorqueLim)
1170 {
1171  int rc; // return code
1172 
1174  DYNA_TRY_IS_MASTER(this);
1175 
1176  DYNA_TRY_EXPR(((uMaxTorqueLim >= m_spec.m_uRawTorqueMin) &&
1177  (uMaxTorqueLim <= m_spec.m_uRawTorqueMax)),
1179  "Maximum torque limit %u: Out of range.", uMaxTorqueLim);
1180 
1181  //
1182  // Linked pair
1183  //
1184  if( IsLinkedMaster() )
1185  {
1187  m_nServoId, uMaxTorqueLim,
1188  m_link.m_pServoMate->GetServoId(), uMaxTorqueLim);
1189 
1190  if( rc == DYNA_OK )
1191  {
1192  m_state.m_uLimTorqueMax = uMaxTorqueLim;
1193  m_link.m_pServoMate->m_state.m_uLimTorqueMax = uMaxTorqueLim;
1194  }
1195  }
1196 
1197  //
1198  // Solitary servo
1199  //
1200  else
1201  {
1203  uMaxTorqueLim);
1204 
1205  if( rc == DYNA_OK )
1206  {
1207  m_state.m_uLimTorqueMax = uMaxTorqueLim;
1208  }
1209  }
1210 
1211  return rc;
1212 }
1213 
1215 {
1217  DYNA_TRY_IS_MASTER(this);
1218 
1220 }
1221 
1222 int DynaServoGeneric::ReadCurPos(int *pCurOdPos)
1223 {
1224  uint_t uVal; // working value
1225  int nVal; // working value
1226  int rc; // return code
1227 
1230 
1232 
1233  if( rc == DYNA_OK )
1234  {
1235  m_state.m_uCurPos = uVal;
1236 
1237  UpdateOdometer((int)uVal);
1238 
1239  *pCurOdPos = GetOdometer();
1240 
1241  if( IsLinkedMaster() )
1242  {
1243  rc = m_link.m_pServoMate->ReadCurPos(&nVal);
1244  }
1245  }
1246 
1247  return rc;
1248 }
1249 
1251 {
1252  uint_t uVal; // working value
1253  int nVal; // working value
1254  int rc; // return code
1255 
1257 
1259 
1260  if( rc == DYNA_OK )
1261  {
1262 
1264  *pCurSpeed = m_state.m_nCurSpeed;
1265 
1266  if( IsLinkedMaster() )
1267  {
1268  rc = m_link.m_pServoMate->ReadCurSpeed(&nVal);
1269  }
1270  }
1271 
1272  return rc;
1273 }
1274 
1276 {
1277  uint_t uVal; // working value
1278  int nVal; // working value
1279  int rc; // return code
1280 
1282 
1284 
1285  if( rc == DYNA_OK )
1286  {
1288  *pCurLoad = m_state.m_nCurLoad;
1289 
1290  if( IsLinkedMaster() )
1291  {
1292  rc = m_link.m_pServoMate->ReadCurLoad(&nVal);
1293  }
1294  }
1295 
1296  return rc;
1297 }
1298 
1300  int *pCurSpeed,
1301  int *pCurLoad)
1302 {
1303  int rc, rc_tmp; // return codes
1304 
1306 
1307  rc = ReadCurPos(pCurPos);
1308 
1309  rc_tmp = ReadCurSpeed(pCurSpeed);
1310 
1311  if( rc == DYNA_OK )
1312  {
1313  rc = rc_tmp;
1314  }
1315 
1316  rc_tmp = ReadCurLoad(pCurLoad);
1317 
1318  if( rc == DYNA_OK )
1319  {
1320  rc = rc_tmp;
1321  }
1322 
1323  return rc;
1324 }
1325 
1326 int DynaServoGeneric::ReadHealth(uint_t *pAlarms,
1327  int *pCurLoad,
1328  uint_t *pCurVolt,
1329  uint_t *pCurTemp)
1330 {
1331  uint_t uVal1; // working value
1332  int nVal2; // woking value
1333  uint_t uVal3, uVal4; // working values
1334  int rc, rc_tmp; // return codes
1335 
1337 
1338  rc = ReadCurLoad(pCurLoad);
1339 
1340  rc_tmp = m_comm.Read8(m_nServoId, DYNA_ADDR_CUR_VOLT, pCurVolt);
1341 
1342  if( rc_tmp == DYNA_OK )
1343  {
1344  m_state.m_uCurVolt = *pCurVolt;
1345  }
1346  else if( rc == DYNA_OK )
1347  {
1348  rc = rc_tmp;
1349  }
1350 
1351  rc_tmp = m_comm.Read8(m_nServoId, DYNA_ADDR_CUR_TEMP_C, pCurTemp);
1352 
1353  if( rc_tmp == DYNA_OK )
1354  {
1355  m_state.m_uCurTemp = *pCurTemp;
1356  }
1357  else if( rc == DYNA_OK )
1358  {
1359  rc = rc_tmp;
1360  }
1361 
1362  if( rc == DYNA_OK )
1363  {
1364  if( IsLinkedMaster() )
1365  {
1366  rc = m_link.m_pServoMate->ReadHealth(&uVal1, &nVal2, &uVal3, &uVal4);
1367  }
1368  }
1369 
1371  *pAlarms = m_state.m_uAlarms;
1372 
1373  return rc;
1374 }
1375 
1377 {
1378  uint_t uVal; // working value
1379  bool bVal; // working boolean
1380  int rc; // return code
1381 
1383 
1385 
1386  if( rc == DYNA_OK )
1387  {
1388  *pState = uVal==DYNA_IS_NOT_MOVING? false: true;
1389 
1390  m_state.m_bIsMoving = *pState;
1391 
1392  if( IsLinkedMaster() )
1393  {
1394  rc = m_link.m_pServoMate->ReadIsMoving(&bVal);
1395  }
1396  }
1397 
1398  return rc;
1399 }
1400 
1401 int DynaServoGeneric::Read(uint_t uAddr, uint_t *pVal)
1402 {
1404  DYNA_TRY_ADDR(uAddr);
1405 
1406  switch( uAddr )
1407  {
1409  case DYNA_ADDR_LIM_CW_LSB:
1410  case DYNA_ADDR_LIM_CCW_LSB:
1415  case DYNA_ADDR_CUR_POS_LSB:
1418  return m_comm.Read16(m_nServoId, uAddr, pVal);
1419 
1420  case DYNA_ADDR_FWVER:
1421  case DYNA_ADDR_ID:
1422  case DYNA_ADDR_BAUD_RATE:
1423  case DYNA_ADDR_T_RET_DELAY:
1427  case DYNA_ADDR_SRL:
1428  case DYNA_ADDR_ALARM_LED:
1430  case DYNA_ADDR_TORQUE_EN:
1431  case DYNA_ADDR_LED:
1436  case DYNA_ADDR_CUR_VOLT:
1437  case DYNA_ADDR_CUR_TEMP_C:
1438  case DYNA_ADDR_REG_INSTR:
1439  case DYNA_ADDR_IS_MOVING:
1440  case DYNA_ADDR_EEPROM_LOCK:
1441  case DYNA_ADDR_PUNCH_LSB:
1442  default:
1443  return m_comm.Read8(m_nServoId, uAddr, pVal);
1444  }
1445 }
1446 
1447 int DynaServoGeneric::Write(uint_t uAddr, uint_t uVal)
1448 {
1450  DYNA_TRY_ADDR(uAddr);
1451 
1452  switch( uAddr )
1453  {
1455  case DYNA_ADDR_LIM_CW_LSB:
1456  case DYNA_ADDR_LIM_CCW_LSB:
1461  case DYNA_ADDR_CUR_POS_LSB:
1464  return m_comm.Write16(m_nServoId, uAddr, uVal);
1465 
1466  case DYNA_ADDR_FWVER:
1467  case DYNA_ADDR_ID:
1468  case DYNA_ADDR_BAUD_RATE:
1469  case DYNA_ADDR_T_RET_DELAY:
1473  case DYNA_ADDR_SRL:
1474  case DYNA_ADDR_ALARM_LED:
1476  case DYNA_ADDR_TORQUE_EN:
1477  case DYNA_ADDR_LED:
1482  case DYNA_ADDR_CUR_VOLT:
1483  case DYNA_ADDR_CUR_TEMP_C:
1484  case DYNA_ADDR_REG_INSTR:
1485  case DYNA_ADDR_IS_MOVING:
1486  case DYNA_ADDR_EEPROM_LOCK:
1487  case DYNA_ADDR_PUNCH_LSB:
1488  default:
1489  return m_comm.Write8(m_nServoId, uAddr, uVal);
1490  }
1491 }
1492 
1494 {
1496  return m_comm.Ping(m_nServoId);
1497 }
1498 
1500 {
1501  int rc;
1502 
1504 
1505  if( (rc = m_comm.Reset(m_nServoId)) == DYNA_OK )
1506  {
1507  SyncData();
1508  CheckData();
1509  }
1510 }
1511 
1513 {
1514  int rc;
1515 
1516  rc = SyncCfg();
1517  rc = SyncState();
1518 
1519  return rc;
1520 }
1521 
1523 {
1524  uint_t uVal1;
1525  uint_t uVal2;
1526 
1528 
1530  {
1531  m_cfg.m_uTRetDelay = uVal1;
1532  }
1533 
1534  CfgReadRotationLimits(&uVal1, &uVal2);
1535  CfgReadTemperatureLimit(&uVal1);
1536  CfgReadVoltageLimits(&uVal1, &uVal2);
1537  CfgReadMaxTorqueLimit(&uVal1);
1538 
1539  if( m_comm.Read8(m_nServoId, DYNA_ADDR_SRL, &uVal1) == DYNA_OK )
1540  {
1541  m_cfg.m_uSrl = uVal1;
1542  }
1543 
1545  {
1546  m_cfg.m_uAlarmLed = uVal1;
1547  }
1548 
1549  CfgReadAlarmShutdownMask(&uVal1);
1550 
1551  return DYNA_OK;
1552 }
1553 
1555 {
1556  bool bState;
1557  uint_t uVal1, uVal3, uVal4, uVal5;
1558  int nVal2;
1559 
1561 
1562  ReadTorqueEnable(&bState);
1563  ReadLed(&bState);
1565  ReadGoalPos(&nVal2);
1566  ReadGoalSpeed(&nVal2);
1567  ReadMaxTorqueLimit(&uVal1);
1568  ReadCurPos(&nVal2);
1569  ReadCurSpeed(&nVal2);
1570  ReadHealth(&uVal1, &nVal2, &uVal3, &uVal4);
1571  ReadIsMoving(&bState);
1572 
1573  // reset odometer to align with encoder (odometer is also enabled)
1574  ResetOdometer(0, false);
1575 
1576  // log any servo alarms
1578 
1579  return DYNA_OK;
1580 }
1581 
1583 {
1584  DumpCtlTbl("EEPROM",
1585  GenericEEPROMCtlTblInfo, arraysize(GenericEEPROMCtlTblInfo));
1586 
1587  printf("\n");
1588 
1589  DumpCtlTbl("RAM", GenericRAMCtlTblInfo, arraysize(GenericRAMCtlTblInfo));
1590 }
1591 
1592 
1593 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1594 // Protected Interface
1595 // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1596 
1598 {
1599  InitSpec();
1600  InitCfg();
1601  InitState();
1602 }
1603 
1604 
1606 {
1607  //
1608  // Fixed servo specification.
1609  //
1610  if( m_spec.m_sModelName != NULL )
1611  {
1612  delete[] m_spec.m_sModelName;
1613  }
1614 
1615  // physical and fixed features
1616  m_spec.m_sModelName = newstr("Generic");
1617  m_spec.m_fWeight = 100.0;
1618  m_spec.m_fWidth = 40.0;
1619  m_spec.m_fHeight = 50.0;
1620  m_spec.m_fDepth = 40.0;
1621  m_spec.m_fResolution = 0.29;
1622  m_spec.m_fGearRedectionRatio = 193.0;
1623  m_spec.m_fStallTorque = 40.0;
1624  m_spec.m_fMaxSpeed = 85.0;
1625  m_spec.m_fAngleMin = 0.0;
1626  m_spec.m_fAngleMax = 300.0;
1628  m_spec.m_bHas360Pos = false;
1629  m_spec.m_fTempMin = -5.0;
1630  m_spec.m_fTempMax = 80.0;
1631  m_spec.m_fVoltMin = 12.0;
1632  m_spec.m_fVoltMax = 18.5;
1633 
1634  // raw units
1646 }
1647 
1649 {
1650  //
1651  // Configuration defaults.
1652  //
1653  // Keep in 'natural' units (i.e. mostly in raw units), and convert to current
1654  // operational units when needed.
1655  //
1667 }
1668 
1670 {
1671  //
1672  // State defaults.
1673  //
1674  // Keep in 'natural' units (i.e. mostly in raw units), and convert to current
1675  // operational units when needed.
1676  //
1678  m_state.m_bTorqueEnabled = DYNA_TORQUE_EN_DFT;
1680 
1681  switch( m_spec.m_uCtlMethodUsed )
1682  {
1684  m_state.m_ctlMethod.m_params.m_comp.m_uCwMargin =
1686  m_state.m_ctlMethod.m_params.m_comp.m_uCwSlope =
1688  m_state.m_ctlMethod.m_params.m_comp.m_uCcwMargin =
1690  m_state.m_ctlMethod.m_params.m_comp.m_uCcwSlope =
1692  break;
1693  case DYNA_CTL_METHOD_PID:
1694  m_state.m_ctlMethod.m_params.m_pid.m_uPGain = DYNA_P_GAIN_DFT;
1695  m_state.m_ctlMethod.m_params.m_pid.m_uIGain = DYNA_I_GAIN_DFT;
1696  m_state.m_ctlMethod.m_params.m_pid.m_uDGain = DYNA_D_GAIN_DFT;
1697  break;
1698  default:
1700  "Servo %d: Unknown control method %u.",
1702  break;
1703  }
1704 
1705  m_state.m_uGoalPos = 0;
1706  m_state.m_nGoalSpeed = 0;
1710  m_state.m_bOverTorqueCond = false;
1711  m_state.m_uCurPos = 0;
1712  m_state.m_nCurSpeed = 0;
1713  m_state.m_nCurLoad = 0;
1714  m_state.m_uCurVolt = 0;
1715  m_state.m_uCurTemp = 0;
1716  m_state.m_bIsMoving = false;
1717  m_state.m_od.m_bOdEnabled = false;
1718 }
1719 
1721 {
1722  /*! \todo TODO check synchronized data for consistencies */
1723 }
1724 
1725 int DynaServoGeneric::CalcMatesGoalPos(int nGoalOdPos, int *pGoalOdPosMate)
1726 {
1727  DynaServo *pServoMate;
1728  int nEncPos;
1729  int nGoalOdPosMate;
1730  uint_t uVal;
1731  int nVal;
1732  int delta;
1733  int rc;
1734 
1735  // linked mate
1736  pServoMate = m_link.m_pServoMate;
1737 
1738  // read latest current positions for master and mate
1739  rc = ReadCurPos(&nVal);
1740 
1741  DYNA_TRY_RC(rc, "Servo %d: Failed.", m_nServoId);
1742 
1743  // mates rotate in reverse directions to each other
1744  if( m_link.m_bRotReversed )
1745  {
1746  delta = GetOdometer() - nGoalOdPos;
1747 
1748  nGoalOdPosMate = pServoMate->GetOdometer() + delta;
1749 
1750  nEncPos = OdometerToEncoder(nGoalOdPosMate);
1751 
1752  DYNA_TRY_EXPR(((nEncPos >= m_spec.m_uRawPosMin) &&
1753  (nEncPos <= m_spec.m_uRawPosMax)),
1755  "Mate servo %d: Goal odometer position %d (encoder=%d): Out of range.",
1756  m_nServoId, nGoalOdPosMate, nEncPos);
1757  }
1758 
1759  // same rotation direction
1760  else
1761  {
1762  nGoalOdPosMate = nGoalOdPos;
1763  }
1764 
1765  if( rc == DYNA_OK )
1766  {
1767  *pGoalOdPosMate = nGoalOdPosMate;
1768  }
1769 
1770  return rc;
1771 }
1772 
1774 {
1775  DynaServoCtlMethod_T *pVal; // working value
1776  int rc; // return code
1777 
1779 
1781  &(pCtlMethod->m_params.m_comp.m_uCwMargin));
1782 
1783  if( rc == DYNA_OK )
1784  {
1786  &(pCtlMethod->m_params.m_comp.m_uCcwMargin));
1787  }
1788 
1789  if( rc == DYNA_OK )
1790  {
1792  &(pCtlMethod->m_params.m_comp.m_uCwSlope));
1793  }
1794 
1795  if( rc == DYNA_OK )
1796  {
1798  &(pCtlMethod->m_params.m_comp.m_uCcwSlope));
1799  }
1800 
1801  if( rc == DYNA_OK )
1802  {
1803  m_state.m_ctlMethod = *pCtlMethod;
1804 
1805  if( IsLinkedMaster() )
1806  {
1807  rc = m_link.m_pServoMate->ReadControlMethod(pVal);
1808  }
1809  }
1810 
1811  return rc;
1812 }
1813 
1815 {
1816  uint_t uCwMargin; // new cw margin
1817  uint_t uCcwMargin; // new ccw margin
1818  uint_t uCwSlope; // new cw slope
1819  uint_t uCcwSlope; // new ccw slope
1820  DynaServo *pServoMate; // servo mate
1821  int rc; // return code
1822 
1824  DYNA_TRY_IS_MASTER(this);
1825 
1826  uCwMargin = ctlMethod.m_params.m_comp.m_uCwMargin;
1827  uCcwMargin = ctlMethod.m_params.m_comp.m_uCcwMargin;
1828  uCwSlope = ctlMethod.m_params.m_comp.m_uCwSlope;
1829  uCcwSlope = ctlMethod.m_params.m_comp.m_uCcwSlope;
1830 
1833  "Control method %u.", ctlMethod.m_uCtlMethod);
1834 
1835  DYNA_TRY_EXPR(((uCwMargin >= DYNA_COMP_MARGIN_MIN_RAW) &&
1836  (uCwMargin <= DYNA_COMP_MARGIN_MAX_RAW)),
1838  "CW compliance margin %u: Out of range.",
1839  uCwMargin);
1840 
1841  DYNA_TRY_EXPR(((uCcwMargin >= DYNA_COMP_MARGIN_MIN_RAW) &&
1842  (uCcwMargin <= DYNA_COMP_MARGIN_MAX_RAW)),
1844  "CCW compliance margin %u: Out of range.",
1845  uCcwMargin);
1846 
1849  "CW compliance slope 0x%02x: Unknown value.",
1850  uCwSlope);
1851 
1852  DYNA_TRY_EXPR(ChkComplianceSlope(uCcwSlope),
1854  "CCW compliance slope 0x%02x: Unknown value.",
1855  uCcwSlope);
1856 
1857  //
1858  // Linked pair
1859  //
1860  if( IsLinkedMaster() )
1861  {
1862  pServoMate = m_link.m_pServoMate;
1863 
1865  m_nServoId, uCwMargin,
1866  m_link.m_pServoMate->GetServoId(), uCwMargin);
1867 
1868  if( rc == DYNA_OK )
1869  {
1870  m_state.m_ctlMethod.m_params.m_comp.m_uCwMargin = uCwMargin;
1871  pServoMate->m_state.m_ctlMethod.m_params.m_comp.m_uCwMargin = uCwMargin;
1872 
1874  m_nServoId, uCcwMargin,
1875  m_link.m_pServoMate->GetServoId(), uCcwMargin);
1876  }
1877 
1878  if( rc == DYNA_OK )
1879  {
1880  m_state.m_ctlMethod.m_params.m_comp.m_uCcwMargin = uCcwMargin;
1881  pServoMate->m_state.m_ctlMethod.m_params.m_comp.m_uCcwMargin = uCcwMargin;
1882 
1884  m_nServoId, uCwSlope,
1885  m_link.m_pServoMate->GetServoId(), uCwSlope);
1886  }
1887 
1888  if( rc == DYNA_OK )
1889  {
1890  m_state.m_ctlMethod.m_params.m_comp.m_uCwSlope = uCwSlope;
1891  pServoMate->m_state.m_ctlMethod.m_params.m_comp.m_uCwSlope = uCwSlope;
1892 
1894  m_nServoId, uCcwSlope,
1895  m_link.m_pServoMate->GetServoId(), uCcwSlope);
1896  }
1897 
1898  if( rc == DYNA_OK )
1899  {
1900  m_state.m_ctlMethod.m_params.m_comp.m_uCcwSlope = uCcwSlope;
1901  pServoMate->m_state.m_ctlMethod.m_params.m_comp.m_uCcwSlope = uCcwSlope;
1902  }
1903  }
1904 
1905  //
1906  // Solitary servo
1907  //
1908  else
1909  {
1911 
1912  if( rc == DYNA_OK )
1913  {
1914  m_state.m_ctlMethod.m_params.m_comp.m_uCwMargin = uCwMargin;
1916  }
1917 
1918  if( rc == DYNA_OK )
1919  {
1920  m_state.m_ctlMethod.m_params.m_comp.m_uCcwMargin = uCcwMargin;
1922  }
1923 
1924  if( rc == DYNA_OK )
1925  {
1926  m_state.m_ctlMethod.m_params.m_comp.m_uCwSlope = uCwSlope;
1928  }
1929 
1930  if( rc == DYNA_OK )
1931  {
1932  m_state.m_ctlMethod.m_params.m_comp.m_uCcwSlope = uCcwSlope;
1933  }
1934  }
1935 
1936  return rc;
1937 }
1938 
1940 {
1941  DynaServoCtlMethod_T *pVal; // working value
1942  int rc; // return code
1943 
1944  pCtlMethod->m_uCtlMethod = DYNA_CTL_METHOD_PID;
1945 
1947  &(pCtlMethod->m_params.m_pid.m_uPGain));
1948 
1949  if( rc == DYNA_OK )
1950  {
1952  &(pCtlMethod->m_params.m_pid.m_uIGain));
1953  }
1954 
1955  if( rc == DYNA_OK )
1956  {
1958  &(pCtlMethod->m_params.m_pid.m_uDGain));
1959  }
1960 
1961  if( rc == DYNA_OK )
1962  {
1963  m_state.m_ctlMethod = *pCtlMethod;
1964 
1965  if( IsLinkedMaster() )
1966  {
1967  rc = m_link.m_pServoMate->ReadControlMethod(pVal);
1968  }
1969  }
1970 
1971  return rc;
1972 }
1973 
1975 {
1976  uint_t uPGain; // new p gain
1977  uint_t uIGain; // new i gain
1978  uint_t uDGain; // new d gain
1979  DynaServo *pServoMate; // servo mate
1980  int rc; // return code
1981 
1983  DYNA_TRY_IS_MASTER(this);
1984 
1985  uPGain = ctlMethod.m_params.m_pid.m_uPGain;
1986  uIGain = ctlMethod.m_params.m_pid.m_uIGain;
1987  uDGain = ctlMethod.m_params.m_pid.m_uDGain;
1988 
1991  "Control method %u.", ctlMethod.m_uCtlMethod);
1992 
1993  DYNA_TRY_EXPR(((uPGain >= DYNA_P_GAIN_MIN_RAW) &&
1994  (uPGain <= DYNA_P_GAIN_MAX_RAW)),
1996  "P-Gain %u: Out of range.", uPGain);
1997 
1998  DYNA_TRY_EXPR(((uIGain >= DYNA_I_GAIN_MIN_RAW) &&
1999  (uIGain <= DYNA_I_GAIN_MAX_RAW)),
2001  "I-Gain %u: Out of range.", uIGain);
2002 
2003  DYNA_TRY_EXPR(((uDGain >= DYNA_D_GAIN_MIN_RAW) &&
2004  (uDGain <= DYNA_D_GAIN_MAX_RAW)),
2006  "D-Gain %u: Out of range.", uDGain);
2007 
2008  //
2009  // Linked pair
2010  //
2011  if( IsLinkedMaster() )
2012  {
2013  pServoMate = m_link.m_pServoMate;
2014 
2015  rc = m_comm.vSyncWrite(DYNA_ADDR_P_GAIN, 1, 2,
2016  m_nServoId, uPGain,
2017  m_link.m_pServoMate->GetServoId(), uPGain);
2018 
2019  if( rc == DYNA_OK )
2020  {
2021  m_state.m_ctlMethod.m_params.m_pid.m_uPGain = uPGain;
2022  pServoMate->m_state.m_ctlMethod.m_params.m_pid.m_uPGain = uPGain;
2023 
2024  rc = m_comm.vSyncWrite(DYNA_ADDR_I_GAIN, 1, 2,
2025  m_nServoId, uIGain,
2026  m_link.m_pServoMate->GetServoId(), uIGain);
2027  }
2028 
2029  if( rc == DYNA_OK )
2030  {
2031  m_state.m_ctlMethod.m_params.m_pid.m_uIGain = uIGain;
2032  pServoMate->m_state.m_ctlMethod.m_params.m_pid.m_uIGain = uIGain;
2033 
2034  rc = m_comm.vSyncWrite(DYNA_ADDR_D_GAIN, 1, 2,
2035  m_nServoId, uDGain,
2036  m_link.m_pServoMate->GetServoId(), uDGain);
2037  }
2038 
2039  if( rc == DYNA_OK )
2040  {
2041  m_state.m_ctlMethod.m_params.m_pid.m_uDGain = uDGain;
2042  pServoMate->m_state.m_ctlMethod.m_params.m_pid.m_uDGain = uDGain;
2043  }
2044  }
2045 
2046  //
2047  // Solitary servo
2048  //
2049  else
2050  {
2051  rc = m_comm.Write8(m_nServoId, DYNA_ADDR_P_GAIN, uPGain);
2052 
2053  if( rc == DYNA_OK )
2054  {
2055  m_state.m_ctlMethod.m_params.m_pid.m_uPGain = uPGain;
2056  rc = m_comm.Write8(m_nServoId, DYNA_ADDR_I_GAIN, uIGain);
2057  }
2058 
2059  if( rc == DYNA_OK )
2060  {
2061  m_state.m_ctlMethod.m_params.m_pid.m_uIGain = uIGain;
2062  rc = m_comm.Write8(m_nServoId, DYNA_ADDR_D_GAIN, uDGain);
2063  }
2064 
2065  if( rc == DYNA_OK )
2066  {
2067  m_state.m_ctlMethod.m_params.m_pid.m_uDGain = uDGain;
2068  }
2069  }
2070 
2071  return rc;
2072 }
2073 
2075 {
2076  switch( uVal )
2077  {
2085  return true;
2086  default:
2087  return false;
2088  }
2089 }
2090 
2091 uint_t DynaServoGeneric::PackGoalSpeed(int nGoalSpeed)
2092 {
2094  {
2095  return (uint_t)( (iabs(nGoalSpeed) & DYNA_GOAL_SPEED_MAG_MASK) |
2097  }
2098  else
2099  {
2100  return (uint_t)iabs(nGoalSpeed);
2101  }
2102 }
2103 
2105 {
2106  int nSpeed;
2107 
2108  nSpeed = (int)(uVal & DYNA_GOAL_SPEED_MAG_MASK);
2109 
2111  {
2113  {
2114  nSpeed = -nSpeed;
2115  }
2116  }
2117 
2118  return nSpeed;
2119 }
2120 
2122 {
2123  int nSpeed;
2124 
2125  nSpeed = (int)(uVal & DYNA_CUR_SPEED_MAG_MASK);
2126 
2128  {
2129  nSpeed = -nSpeed;
2130  }
2131 
2132  return nSpeed;
2133 }
2134 
2136 {
2137  int nLoad;
2138 
2139  nLoad = (int)(uVal & DYNA_CUR_LOAD_MAG_MASK);
2140 
2142  {
2143  nLoad = -nLoad;
2144  }
2145 
2146  return nLoad;
2147 }
2148 
2150 {
2154  {
2156  }
2157 
2158  else
2159  {
2161  }
2162 }
RoadNarrows Dynamixel Bus Communications Abstract Base Class Interface.
#define DYNA_ADDR_ALARM_LED
alarm LED (RW)
Definition: Dynamixel.h:627
#define DYNA_GOAL_SPEED_DIR_MASK
speed direction field mask
Definition: Dynamixel.h:948
#define DYNA_LIM_TEMP_DFT_C
80C default maximum limit
Definition: Dynamixel.h:509
uint_t m_uLimTemp
maximum temperature limit
Definition: DynaTypes.h:129
virtual int UpdateOdometer(int nEncCurPos)
Update the odometer from the current servo position and rotation direction.
Definition: DynaServo.cxx:207
#define DYNA_P_GAIN_MAX_RAW
maximum value
Definition: Dynamixel.h:840
char * newstr(const char *s)
Allocate new duplicated string.
#define DYNA_P_GAIN_MIN_RAW
minimum value
Definition: Dynamixel.h:839
virtual int ReadHealth(uint_t *pAlarms, int *pCurLoad, uint_t *pCurVolt, uint_t *pCurTemp)
Read from the servo state memory the current servo health.
virtual int WriteGoalPos(int nGoalOdPos)
Write to the servo state memory to set the new goal position.
uint_t m_uLimVoltMin
minimum voltage limit
Definition: DynaTypes.h:130
virtual uint_t GetServoMode() const
Get the servo operational mode.
Definition: DynaServo.h:165
#define DYNA_TORQUE_MAX_RAW
maximum raw torque
Definition: Dynamixel.h:282
double m_fMaxSpeed
max no-load speed (rpm) at optimal power
Definition: DynaTypes.h:91
void DumpCtlTbl(const char *sTblName, const DynaCtlTblEntry_T tblInfo[], size_t uSize)
Dump the servo control tabl values to stdout.
Definition: DynaServo.cxx:422
bool IsLinkedMaster() const
Test if this servo is a linked master.
Definition: DynaServo.h:236
#define DYNA_CUR_SPEED_MAG_MASK
speed magnitude field mask
Definition: Dynamixel.h:1014
#define DYNA_ADDR_CUR_POS_LSB
current position lsb (R)
Definition: Dynamixel.h:985
#define DYNA_CTL_METHOD_COMPLIANCE
compliance control method
Definition: Dynamixel.h:216
#define DYNA_OK
not an error, success
Definition: Dynamixel.h:78
virtual void Dump()
Dump contents of the servo EEPROM and RAM control tables.
#define DYNA_TORQUE_EN_OFF
disable power drive to the motor
Definition: Dynamixel.h:676
virtual int CfgReadAlarmShutdownMask(uint_t *pAlarmMask)
Read from the servo configuration EEPROM the current servo shutdown on alarms mask.
#define DYNA_ADDR_ALARM_SHUTDOWN
alarm shutdown (RW)
Definition: Dynamixel.h:642
RoadNarrows MX Series Dynamixel Declarations.
virtual int MoveTo(int nGoalOdPos)
Move to the goal postition.
virtual int ReadGoalSpeed(int *pGoalSpeed)
Read from the servo state memory the current goal speed and direction.
#define DYNA_ADDR_CW_COMP_SLOPE
clockwise compliance slope
Definition: Dynamixel.h:781
#define DYNA_ADDR_GOAL_SPEED_LSB
goal speed lsb (RW)
Definition: Dynamixel.h:940
uint_t m_uRawVoltMin
minimum raw voltage value
Definition: DynaTypes.h:110
#define DYNA_ADDR_MODEL_NUM_LSB
model number lsb (R)
Definition: Dynamixel.h:353
#define DYNA_CUR_LOAD_MAG_MASK
load magnitude field mask
Definition: Dynamixel.h:1037
virtual int CfgReadServoMode(uint_t *pServoMode)
Read from the servo configuration EEPROM to determine the servo operational mode. ...
#define DYNA_LIM_TORQUE_MAX_ON_DFT_RAW
default maximum raw torque
Definition: Dynamixel.h:594
#define DYNA_MODE_SERVO
servo mode with limited rotation
Definition: Dynamixel.h:170
virtual int WriteCtlMethodCompliance(DynaServoCtlMethod_T &ctlMethod)
Write to the servo state memory the new compliance control method parameters.
#define DYNA_D_GAIN_DFT
default value
Definition: Dynamixel.h:885
#define DYNA_LED_OFF
LED off.
Definition: Dynamixel.h:693
#define DYNA_ADDR_LIM_CW_LSB
clockwise angle limit lsb (RW)
Definition: Dynamixel.h:464
virtual int vSyncWrite(uint_t uAddr, uint_t uValSize, uint_t uCount,...)
Synchronous write 8/16-bit values to a list of Dynamixel servos.
Definition: DynaComm.cxx:420
#define DYNA_ADDR_EEPROM_LOCK
lock the EEPROM (RW)
Definition: Dynamixel.h:1128
#define DYNA_POS_MIN_RAW
minimum raw angular position
Definition: Dynamixel.h:244
#define DYNA_TEMP_MIN_RAW
minimum raw temperature
Definition: Dynamixel.h:295
virtual int UnpackCurSpeed(uint_t uVal)
Unpack current speed from the control table value.
virtual int Reset(int nServoId)=0
Reset a servo back to default values.
double m_fHeight
height (mm)
Definition: DynaTypes.h:86
int m_nOdGoalPos
odometer goal position
Definition: DynaTypes.h:183
uint_t m_uRawPosMin
minimum raw position value (servo mode)
Definition: DynaTypes.h:101
#define DYNA_ADDR_CW_COMP_MARGIN
clockwise compliance margin (RW)
Definition: Dynamixel.h:733
virtual int ReadCurLoad(int *pCurLoad)
Read from the servo state memory the current load.
DynaAgent_T * m_pAgent
servo agent
Definition: DynaServo.h:841
uint_t m_uRawSpeedMax
maximum raw speed magnitude value
Definition: DynaTypes.h:105
#define DYNA_SRL_RET_DFT
return status packet default
Definition: Dynamixel.h:613
#define DYNA_COMP_SLOPE_TORQUE_2
compliance torque level 2
Definition: Dynamixel.h:786
#define DYNA_TRY_EXPR(expr, ecode, efmt,...)
Test if the servo is in the required mode(s) exception macro.
#define DYNA_COMP_MARGIN_DFT_RAW
default raw position difference
Definition: Dynamixel.h:739
#define DYNA_VOLT_MAX_RAW
maximum raw temperature
Definition: Dynamixel.h:309
double m_fVoltMax
maximum operational voltage (V)
Definition: DynaTypes.h:99
#define DYNA_ALARM_NONE
no alarms
Definition: Dynamixel.h:646
int m_nCurLoad
current load
Definition: DynaTypes.h:208
DynaServoCfg_T m_cfg
servo shadowed EEPROM configuration
Definition: DynaServo.h:838
uint_t m_uCtlMethod
Dynamixel Internal Position Control Methods
Definition: DynaTypes.h:148
uint_t m_uRawSpeedMin
minimum raw speed magnitude value
Definition: DynaTypes.h:104
virtual int Reset()
Reset this servo back to default values.
virtual int Read8(int nServoId, uint_t uAddr, byte_t *pVal)=0
Read an 8-bit value from Dynamixel servo control table.
#define DYNA_CCW_POS_CONT_MODE
continuous mode (with cw limit)
Definition: Dynamixel.h:488
virtual int CfgWriteAlarmShutdownMask(uint_t uAlarmMask)
Write to the servo configuration EEPROM the new servo shutdown on alarms mask.
uint_t m_uLimTorqueMax
on power-up maximum torque limit
Definition: DynaTypes.h:132
int(* m_fnWriteGoalPos)(int nServoId, int nGoalPos, void *pUsrArg)
Definition: DynaTypes.h:233
Generic Dynamixel Servo Base Class Interface.
#define DYNA_P_GAIN_DFT
default value
Definition: Dynamixel.h:841
#define DYNA_TRY_ADDR(addr)
Test if servo address is valid.
INLINE_IN_H int iabs(int a)
Return absolute value of a.
Definition: DynaOlio.h:91
#define DYNA_SPEED_MIN_RAW
minimum raw value
Definition: Dynamixel.h:265
virtual int Read16(int nServoId, uint_t uAddr, ushort_t *pVal)=0
Read a 16-bit value from Dynamixel servo control table.
virtual int MoveAtSpeed(int nGoalSpeed)
Move at speed.
double m_fDepth
depth (mm)
Definition: DynaTypes.h:87
void Init()
Initialize servo class instance.
virtual bool HasAgent()
Tests if servo has a registered agent.
Definition: DynaServo.h:604
virtual bool ChkComplianceSlope(uint_t uVal)
Check validity of compliance slope discrete values.
virtual bool Ping(int nServoId)=0
Ping the servo.
#define DYNA_ADDR_LIM_VOLT_MIN
lowest voltage limit (RW)
Definition: Dynamixel.h:524
uint_t m_uLimTorqueMax
maximum torque limit
Definition: DynaTypes.h:202
#define DYNA_TRY_IS_MASTER(pservo)
Test if the servo is a master servo.
uint_t m_uAlarmShutdown
alarm shutdown mask enable causes
Definition: DynaTypes.h:135
int(* m_fnWriteGoalSpeedPos)(int nServoId, int nGoalSpeed, int nGoalPos, void *pUsrArg)
Definition: DynaTypes.h:239
static DynaCtlTblEntry_T GenericRAMCtlTblInfo[]
Generic Servo RAM Control Table Information.
#define DYNA_ECODE_NOT_SUPP
feature/function not supported
Definition: Dynamixel.h:97
#define DYNA_IS_NOT_MOVING
not moving
Definition: Dynamixel.h:1114
virtual int WriteGoalSpeed(int nGoalSpeed)
Write to the servo state memory the new goal speed and direction.
#define DYNA_ADDR_CUR_SPEED_LSB
current speed lsb (R)
Definition: Dynamixel.h:1009
Miscellaneous collection of useful utilities.
uint_t m_uCtlMethodUsed
Dynamixel Internal Position Control Methods
Definition: DynaTypes.h:100
virtual ~DynaServoGeneric()
Destructor.
double m_fVoltMin
minimum operational voltage (V)
Definition: DynaTypes.h:98
double m_fAngleMin
min rotation angle in servo mode (deg)
Definition: DynaTypes.h:92
virtual int AgentWriteGoalPos(int nGoalOdPos)
Agent write to the servo state memory to set the new goal position.
#define DYNA_D_GAIN_MAX_RAW
maximum value
Definition: Dynamixel.h:884
#define DYNA_D_GAIN_MIN_RAW
minimum value
Definition: Dynamixel.h:883
Dynamixel Servo Abstract Base Class.
Definition: DynaServo.h:78
double m_fGearRedectionRatio
gear reduction ratio
Definition: DynaTypes.h:89
virtual int ReadGoalPos(int *pGoalPos)
Read from the servo state memory the current goal position.
virtual int CfgWriteVoltageLimits(uint_t uMinVoltLim, uint_t uMaxVoltLim)
Write to the servo configuration EEPROM the new voltage limits.
double m_fWeight
weight (grams)
Definition: DynaTypes.h:84
#define DYNA_I_GAIN_DFT
default value
Definition: Dynamixel.h:863
virtual int CalcMatesGoalPos(int nGoalOdPos, int *pGoalOdPosMate)
Calculate the linked mate&#39;s goal position given this servo&#39;s goal position.
#define DYNA_ADDR_CUR_TEMP_C
current temperature C (R)
Definition: Dynamixel.h:1076
uint_t m_uCurVolt
current voltage
Definition: DynaTypes.h:209
#define DYNA_LOG_ERROR(ecode, efmt,...)
Log Error.
void * m_pAgentArg
servo agent callback argument
Definition: DynaServo.h:842
uint_t m_uSupportedModes
Dynamixel Operational Modes
Definition: DynaTypes.h:94
#define DYNA_POS_MODULO
servo position modulo [0-max]
Definition: Dynamixel.h:246
uint_t m_uRawPosModulo
raw position modulo
Definition: DynaTypes.h:103
#define DYNA_COMP_SLOPE_TORQUE_6
compliance torque level 6
Definition: Dynamixel.h:790
#define DYNA_T_RET_DELAY_DFT_RAW
raw default
Definition: Dynamixel.h:440
virtual int Write8(int nServoId, uint_t uAddr, byte_t byVal)=0
Write an 8-bit value to Dynamixel servo control table.
virtual int Release()
Release servo from any applied torque.
virtual int CfgReadRotationLimits(uint_t *pCwLim, uint_t *pCcwLim)
Read from the servo configuration EEPROM the current rotation limits.
int m_nCurSpeed
current speed (raw)
Definition: DynaTypes.h:207
bool_t m_bTorqueEnabled
torque [not] enabled
Definition: DynaTypes.h:197
virtual int Freeze()
Freeze servo at current position.
virtual int ReadCurPos(int *pCurOdPos)
Read from the servo state memory the current servo position.
virtual int EStop()
Emergency stop servo.
bool_t m_bLed
led on/off
Definition: DynaTypes.h:198
virtual int WriteTorqueEnable(bool bState)
Write to the servo state memory to set the new torque enable value.
Dynamixel Control Method Structure.
Definition: DynaTypes.h:146
virtual int ReadCtlMethodPid(DynaServoCtlMethod_T *pCtlMethod)
Read from the servo state memory the current PID control method parameters.
virtual uint_t GetAlarms()
Get current alarms.
Definition: DynaComm.h:393
#define DYNA_COMP_MARGIN_MAX_RAW
max position difference (loosest)
Definition: Dynamixel.h:738
virtual int WriteLed(bool bState)
Write to the servo state memory to turn on or off the servo LED.
virtual int Write16(int nServoId, uint_t uAddr, ushort_t uhVal)=0
Write a 16-bit value to Dynamixel servo control table.
#define DYNA_COMP_SLOPE_TORQUE_4
compliance torque level 4
Definition: Dynamixel.h:788
DynaServoGeneric(DynaComm &comm)
Bare-bones initialization constructor.
Servo Control Table Entry.
Definition: DynaTypes.h:369
double m_fResolution
resolution (degrees)
Definition: DynaTypes.h:88
#define DYNA_COMP_SLOPE_TORQUE_1
compliance torque level 1
Definition: Dynamixel.h:785
#define DYNA_TORQUE_MIN_RAW
minimum raw torque
Definition: Dynamixel.h:281
#define DYNA_LOG_SERVO_ALARMS(id, alarms)
Log servo alarms.
uint_t m_uRawTorqueMin
minimum raw torque value
Definition: DynaTypes.h:106
bool m_bOverTorqueCond
over torque condition state
Definition: DynaTypes.h:205
uint_t m_uTRetDelay
response return delay time (raw or )
Definition: DynaTypes.h:126
#define DYNA_TRY_SERVO_HAS_MODE(pservo, mode)
Test if the servo has one of the required modes exception macro.
The libDynamixel internal declarations.
virtual int SyncState()
Synchronize the shadowed state data to the servo control table RAM state.
char * m_sModelName
model name
Definition: DynaTypes.h:83
#define DYNA_CUR_LOAD_DIR_MASK
load direction field mask
Definition: Dynamixel.h:1042
uint_t m_uClearTorqueTh
clear over torque cond. threshold
Definition: DynaTypes.h:204
void SetServoMode()
Set the servo mode given the servo capabilites and the current rotation limits.
uint_t m_uLimVoltMax
maximum voltage limit
Definition: DynaTypes.h:131
#define DYNA_COMP_SLOPE_TORQUE_3
compliance torque level 3
Definition: Dynamixel.h:787
#define DYNA_ADDR_LIM_TORQUE_MAX_LSB
current torque limit lsb (RW)
Definition: Dynamixel.h:965
virtual int MoveAtSpeedTo(int nGoalSpeed, int nGoalOdPos)
Move at speed to the goal postition.
uint_t m_uRawTempMin
minimum raw temperature value
Definition: DynaTypes.h:108
uint_t m_uLimCcw
counterclockwise angle limit
Definition: DynaTypes.h:128
double m_fTempMin
minimum operational temperature (C)
Definition: DynaTypes.h:96
int(* m_fnWriteGoalSpeed)(int nServoId, int nGoalSpeed, void *pUsrArg)
Definition: DynaTypes.h:236
#define DYNA_ADDR_IS_MOVING
is [not] moving (to goal position)
Definition: Dynamixel.h:1110
void InitCfg()
Initialize servo configuration data.
uint_t m_uRawTorqueMax
maximum raw torque value
Definition: DynaTypes.h:107
uint_t m_uOverTorqueTh
set over torque cond. threshold
Definition: DynaTypes.h:203
uint_t m_uAlarms
current servo alarms and errors
Definition: DynaTypes.h:196
#define DYNA_GOAL_SPEED_MAG_MASK
speed magnitude field mask
Definition: Dynamixel.h:945
#define DYNA_ADDR_LIM_TORQUE_MAX_ON_LSB
maximum torque lsb (RW)
Definition: Dynamixel.h:589
#define DYNA_GOAL_SPEED_DIR_CW
clockwise direction
Definition: Dynamixel.h:951
virtual int CfgWriteMaxTorqueLimit(uint_t uMaxTorqueLim)
Write to the servo configuration EEPROM the new on power-up maximum torque limit. ...
#define DYNA_ADDR_CUR_VOLT
current voltage (R)
Definition: Dynamixel.h:1061
void InitState()
Initialize servo state data.
#define DYNA_MODE_CONTINUOUS
continuous mode with/without position
Definition: Dynamixel.h:171
#define DYNA_COMP_SLOPE_TORQUE_DFT
default compliance torque level
Definition: Dynamixel.h:793
#define DYNA_ADDR_LED
LED on/off (RW)
Definition: Dynamixel.h:689
#define DYNA_ADDR_BAUD_RATE
baud rate enumeration (RW)
Definition: Dynamixel.h:396
RoadNarrows Dynamixel Fundatmental Types.
#define DYNA_TEMP_MAX_RAW
maximum raw temperature
Definition: Dynamixel.h:296
#define DYNA_COMP_SLOPE_TORQUE_7
compliance torque level 7
Definition: Dynamixel.h:791
#define DYNA_ADDR_I_GAIN
Igain (RW)
Definition: Dynamixel.h:857
bool m_bOdEnabled
odometer mapping [not] enabled
Definition: DynaTypes.h:181
virtual int ReadIsMoving(bool *pState)
Read from the servo state memory to test if the servo is currently moving.
virtual int ReadMaxTorqueLimit(uint_t *pMaxTorqueLim)
Read from the servo state memory the current maximum torque limit.
#define DYNA_I_GAIN_MAX_RAW
maximum value
Definition: Dynamixel.h:862
int m_nGoalSpeed
goal speed (raw)
Definition: DynaTypes.h:201
#define DYNA_LIM_VOLT_MIN_DFT_RAW
default minimum raw limit
Definition: Dynamixel.h:532
#define DYNA_GOAL_SPEED_DIR_CCW
counterclockwise direction
Definition: Dynamixel.h:950
virtual int CfgReadTemperatureLimit(uint_t *pTempLim)
Read from the servo configuration EEPROM the current maximum temperature limit.
#define DYNA_ALARM_LED_DFT
alarm LED default mask
Definition: Dynamixel.h:631
#define DYNA_CTL_METHOD_PID
pid control method
Definition: Dynamixel.h:217
CrossLink_T m_link
servo cross linkage
Definition: DynaServo.h:840
DynaServoOdometer_T m_od
servo virtual odometer
Definition: DynaTypes.h:212
RoadNarrows Dynamixel Archetype Servo Abstract Base Class.
uint_t m_uCurPos
current position (encoder ticks)
Definition: DynaTypes.h:206
#define DYNA_TRY_SERVO_HAS_POS_CTL(pservo)
Test if the servo has positiion control.
virtual void CheckData()
Check data for consitencies.
bool_t m_uAlarmLed
alarm led enable
Definition: DynaTypes.h:134
#define DYNA_I_GAIN_MIN_RAW
minimum value
Definition: Dynamixel.h:861
virtual int AgentWriteGoalSpeed(int nGoalSpeed)
Agent write to the servo state memory to set the new goal speed.
#define DYNA_VOLT_MIN_RAW
minimum raw temperature
Definition: Dynamixel.h:308
#define DYNA_ADDR_ALARM_SHUTDOWN_MASK
valid data mask
Definition: Dynamixel.h:644
#define DYNA_POS_MAX_RAW
maximum raw angular position
Definition: Dynamixel.h:245
int m_nServoId
servo id
Definition: DynaServo.h:836
virtual int ReadCtlMethodCompliance(DynaServoCtlMethod_T *pCtlMethod)
Read from the servo state memory the current compliance control method parameters.
virtual int ReadTorqueEnable(bool *pState)
Read from the servo state memory the current torque enable value.
virtual int SyncCfg()
Synchronize the shadowed configuration to the servo control table EEPROM configuration.
virtual int UnpackGoalSpeed(uint_t uVal)
Unpack goal speed from the control table value.
virtual int WriteControlMethod(DynaServoCtlMethod_T &ctlMethod)
Write to the servo state memory the new control method parameters.
double m_fTempMax
maximum operational temperature (C)
Definition: DynaTypes.h:97
#define DYNA_ADDR_ID
dynamixel id (RW)
Definition: Dynamixel.h:380
int OdometerToEncoder(int nOdPos)
Convert virtual odometer units to servo encoder units.
Definition: DynaServo.h:367
virtual int SyncData()
Synchronize the shadowed configuration and state data to the servo control table. ...
RoadNarrows Dynamixel Top-Level Package Header File.
#define DYNA_ADDR_LIM_CCW_LSB
counterclockwise angle limit lsb (RW)
Definition: Dynamixel.h:483
virtual bool Ping()
Ping this servo.
uint_t m_uLimCw
clockwise angle limit (deg
Definition: DynaTypes.h:127
#define DYNA_ADDR_SRL
status return level (RW)
Definition: Dynamixel.h:606
virtual uint_t PackGoalSpeed(int nGoalSpeed)
Pack the goal speed into the control table value.
#define DYNA_ADDR_PUNCH_LSB
punch lsb (not used)
Definition: Dynamixel.h:1147
#define DYNA_ECODE_INTERNAL
internal error (bug)
Definition: Dynamixel.h:82
#define DYNA_CUR_SPEED_DIR_CW
clockwise direction
Definition: Dynamixel.h:1020
virtual uint_t GetServoId() const
Get servo id.
Definition: DynaServo.h:155
virtual int Read(uint_t uAddr, uint_t *pVal)
#define DYNA_LED_ON
LED on.
Definition: Dynamixel.h:694
virtual int AgentWriteGoalSpeedPos(int nGoalSpeed, int nGoalOdPos)
Agent write to the servo state memory to set the new goal position and speed.
DynaComm & m_comm
attached Dynamixel bus comm. object
Definition: DynaServo.h:835
virtual int ReloadMaxTorqueLimit()
Reload the maximum torque limit from the configuration.
uint_t m_uRawPosMax
maximum raw position value (servo mode)
Definition: DynaTypes.h:102
uint_t m_uServoMode
servo mode Dynamixel Operational Modes
Definition: DynaTypes.h:136
virtual int CfgReadMaxTorqueLimit(uint_t *pMaxTorqueLim)
Read from the servo configuration EEPROM the current on power-up maximum torque limit.
virtual int ReadLed(bool *pState)
Read from the servo state memory the current LED on/off value.
DynaServoState_T m_state
servo shadowed RAM state
Definition: DynaServo.h:839
virtual int WriteMaxTorqueLimit(uint_t uMaxTorqueLim)
Write to the servo state memory to set the new maximum torque limit.
DynaServoSpec_T m_spec
servo specification
Definition: DynaServo.h:837
union DynaServoCtlMethod_T::@2 m_params
parameters to control methods
uint_t m_uGoalPos
goal position (encoder ticks)
Definition: DynaTypes.h:200
struct DynaServoCtlMethod_T::@2::@3 m_comp
compliance control method parameters
#define DYNA_TORQUE_EN_ON
enable power drive to the motor
Definition: Dynamixel.h:677
#define DYNA_CUR_SPEED_DIR_MASK
speed direction field mask
Definition: Dynamixel.h:1017
#define DYNA_ADDR_T_RET_DELAY
return delay time (RW)
Definition: Dynamixel.h:434
static DynaCtlTblEntry_T GenericEEPROMCtlTblInfo[]
Generic Servo EEPROM Control Table Information.
virtual int ReadDynamics(int *pCurPos, int *pCurSpeed, int *pCurLoad)
Read from the servo state memory the current servo dynamics.
#define DYNA_ADDR_D_GAIN
Dgain (RW)
Definition: Dynamixel.h:879
virtual int Stop()
Stop servo.
#define DYNA_ADDR_LIM_TEMP_MAX
maximum temperature limit (RW)
Definition: Dynamixel.h:503
uint_t m_uRawTempMax
maximum raw temperature value
Definition: DynaTypes.h:109
#define DYNA_ADDR_CUR_LOAD_LSB
current load lsb (R)
Definition: Dynamixel.h:1032
double m_fStallTorque
max stall torque (kgf) at optimal power
Definition: DynaTypes.h:90
#define DYNA_TRY_SERVO_HAS_AGENT(pservo)
Test if the servo has a proxy agent.
#define DYNA_SPEED_MAX_RAW
maximum raw value
Definition: Dynamixel.h:266
virtual int ResetOdometer(int nEncZeroPt, bool bIsReverse)
Reset the servo&#39;s virtual odometer.
Definition: DynaServo.cxx:188
#define DYNA_ADDR_GOAL_POS_LSB
goal position lsb (RW)
Definition: Dynamixel.h:909
virtual int Write(uint_t uAddr, uint_t uVal)
#define DYNA_ECODE_BAD_VAL
bad value
Definition: Dynamixel.h:85
virtual int UnpackCurLoad(uint_t uVal)
Unpack current load estimate from the control table value.
virtual int CfgWriteTemperatureLimit(uint_t uTempLim)
Write to the servo configuration EEPROM the new maximum temperature limit.
DynaServoCtlMethod_T m_ctlMethod
position control method
Definition: DynaTypes.h:199
#define DYNA_CW_POS_CONT_MODE
continuous mode (with ccw limit)
Definition: Dynamixel.h:469
#define DYNA_CUR_LOAD_DIR_CW
clockwise direction
Definition: Dynamixel.h:1045
bool_t m_bIsMoving
servo is [not] moving
Definition: DynaTypes.h:211
double m_fWidth
width (mm)
Definition: DynaTypes.h:85
uint_t m_uSrl
status return level
Definition: DynaTypes.h:133
#define DYNA_ALARM_DFT
alarm shutdown default
Definition: Dynamixel.h:655
#define DYNA_ADDR_TORQUE_EN
torque enable (RW)
Definition: Dynamixel.h:672
double m_fAngleMax
max rotation angle in servo mode (deg)
Definition: DynaTypes.h:93
#define DYNA_ADDR_REG_INSTR
registered instruction (RW)
Definition: Dynamixel.h:1092
virtual int CfgWriteServoModeContinuous()
Write to the servo configuration EEPROM to set the servo operational mode to the full/continuous mode...
#define DYNA_TRY_SERVO_IN_MODE(pservo, mode)
Test if the servo is in the given mode.
bool m_bHas360Pos
does [not] have full 360 position info
Definition: DynaTypes.h:95
#define DYNA_ADDR_P_GAIN
Pgain (RW)
Definition: Dynamixel.h:835
virtual int CfgWriteRotationLimits(uint_t uCwLim, uint_t uCcwLim)
Write to the servo configuration EEPROM the new rotation limits.
#define DYNA_ADDR_LIM_VOLT_MAX
highest voltage limit (RW)
Definition: Dynamixel.h:555
#define DYNA_TRY_RC(rc, fmt,...)
Test if Dynamixel return code is not an error.
#define DYNA_COMP_SLOPE_TORQUE_5
compliance torque level 5
Definition: Dynamixel.h:789
uint_t m_uCurTemp
current temperature
Definition: DynaTypes.h:210
#define DYNA_ADDR_FWVER
firmware version (R)
Definition: Dynamixel.h:367
virtual int ReadCurSpeed(int *pCurSpeed)
Read from the servo state memory the current speed and direction.
virtual int CfgWriteServoMode(uint_t uCwLim, uint_t uCcwLim)
Write to the servo configuration EEPROM to set the servo operational mode.
virtual int ReadControlMethod(DynaServoCtlMethod_T *pCtlMethod)
Read from the servo state memory the current control method parameters.
uint_t m_uRawVoltMax
maximum raw voltage value
Definition: DynaTypes.h:111
RoadNarrows Dynamixel Library Error and Logging Routines.
int GetOdometer()
Get the current virtual odometer value.
Definition: DynaServo.h:304
#define DYNA_ADDR_CCW_COMP_MARGIN
counterclockwise compliance margin
Definition: Dynamixel.h:766
#define DYNA_LIM_VOLT_MAX_DFT_RAW
default maximum raw limit
Definition: Dynamixel.h:563
virtual int WriteCtlMethodPid(DynaServoCtlMethod_T &ctlMethod)
Write to the servo state memory the new PID control method parameters.
#define DYNA_SPEED_CONT_STOP
continuous mode: stop
Definition: Dynamixel.h:261
#define DYNA_COMP_MARGIN_MIN_RAW
min position difference (tightest)
Definition: Dynamixel.h:737
void InitSpec()
Initialize servo fixed specification data.
#define DYNA_ADDR_CCW_COMP_SLOPE
counterclockwise compliance slope
Definition: Dynamixel.h:810
Dynamixel Bus Communications Abstract Base Class.
Definition: DynaComm.h:80
virtual int CalcMatesGoalSpeed(int nGoalSpeed)
Calculate the linked mate&#39;s speed speed given this servo&#39;s goal speed.
#define DYNA_TRY_COMM(comm)
Test if bus communication is available exception macro.
virtual int CfgReadVoltageLimits(uint_t *pMinVoltLim, uint_t *pMaxVoltLim)
Read from the servo configuration EEPROM the current voltage limits.