51 #include <sys/types.h> 61 #include "rnr/rnrconfig.h" 94 m_sCmdName =
"create";
95 m_sCmdHelpBrief =
"Create a new dynamixel chain interface.";
96 m_sCmdHelpArgs =
"<uri> <baudrate>";
97 m_sCmdHelpDesc =
"Create a new, empty dynamixel chain interface. " 98 "A connection is opened to the (proxied) dynamixel bus " 99 "as specifed by the <uri> and at the specified " 100 "<baudrate>. The created dynamixel chain is empty. " 101 "Use scan to populate the chain.\n" 103 "[botsense://[<hostname>][:<port>]]/<device>\n" 104 " <baudrate> Baud rate. One of:\n" 105 " 9600 19200 57600 115200 200000 250000 " 106 "400000 500000 1000000\n" 107 " 2250000 2500000 3000000";
122 TRY( ChkArgCnt(shell, argc) );
126 TRY( ToInt(shell, argv[1], &nBaudRate) );
130 shell.
Error(
"Dynamixel interface already created. Try destroying first.");
134 shell.
m_pDynaComm = CommNew(shell, sUri, nBaudRate);
186 const char *sContext)
210 snprintf(buf,
sizeof(buf),
"%d", nBaudRate);
211 buf[
sizeof(buf)-1] = 0;
213 if( !strncmp(buf, sText, uTextLen) )
239 if( pDynaComm == NULL )
241 shell.
Error(
"Failed to create %s@%d.", sUri, nBaudRate);
244 else if( !pDynaComm->
IsOpen() )
246 shell.
Error(
"Failed to open %s@%d.", sUri, nBaudRate);
272 m_sCmdName =
"destroy";
273 m_sCmdHelpBrief =
"Destroy the dynamixel interface.";
275 m_sCmdHelpDesc =
"Destroy the existing dynamixel interface. Any existing " 276 "dynamixel bus communication is closed.";
288 TRY( ChkArgCnt(shell, argc) );
292 shell.
Error(
"Dynamixel interface not created.");
334 m_sCmdHelpBrief =
"Scan for servos.";
336 m_sCmdHelpDesc =
"Scan the dynamixel bus for all servos and add to the " 337 "chain. The chain is cleared of existing servos prior to " 353 TRY( ChkArgCnt(shell, argc) );
354 TRY( ChkComm(shell) );
355 TRY( ChkChain(shell) );
380 shell.
Response(
"Added %d servos to chain.\n", nNumServos);
402 m_sCmdHelpBrief =
"Ping a servo.";
403 m_sCmdHelpArgs =
"<servo_id>";
404 m_sCmdHelpDesc =
"Ping a servo. The servo does not have to be present " 405 "in the dynamixel chain.\n" 406 " <servo_id> Servo id [0-253].";
421 TRY( ChkArgCnt(shell, argc) );
422 TRY( ToInt(shell, argv[0], &nServoId) );
423 TRY( ChkComm(shell) );
427 shell.
Response(
"Servo %d: %s.\n", nServoId,
428 (bPong?
"present":
"no response"));
450 m_sCmdHelpBrief =
"List servo information.";
452 m_sCmdHelpDesc =
"List information about all servos in the dynamixel " 453 "chain. Per each servo, the servo id, model number " 454 "firmware version, mode, and linkage, if any, are " 471 TRY( ChkArgCnt(shell, argc) );
472 TRY( ChkComm(shell) );
473 TRY( ChkChain(shell) );
480 shell.
Response(
"Servo %3d: %7s, model 0x%04x, fwver 0x%02x",
489 shell.
Response(
", continuous mode");
493 shell.
Response(
", linked master of %d",
498 shell.
Response(
", linked slave of %d",
523 m_sCmdHelpBrief =
"Link two servos in a master-slave configuration.";
524 m_sCmdHelpArgs =
"<master_id> <slave_id> <dir>";
525 m_sCmdHelpDesc =
"Link two servos in a master-slave configuration. " 526 "The servos may operate in the same forward rotation " 527 "direction or in opposite reverse directions. Once " 528 "linked, all commands that modify servo state " 529 "(e.g. move and write) are only supported on the master " 530 "servo to preserve synchronization.\n" 531 " <master_id> Master servo id.\n" 532 " <slave_id> Slave servo id.\n" 533 " <dir> One of: forward reverse.";
550 TRY( ChkArgCnt(shell, argc) );
552 TRY( ToInt(shell, argv[0], &nServoIdMaster) );
553 TRY( ToInt(shell, argv[1], &nServoIdSlave) );
555 if( !strncmp(
"forward", argv[2], strlen(argv[2])) )
559 else if( !strncmp(
"reverse", argv[2], strlen(argv[2])) )
569 TRY( ChkComm(shell) );
570 TRY( ChkChain(shell) );
571 TRY( ChkChainHasServo(shell, nServoIdMaster) );
572 TRY( ChkChainHasServo(shell, nServoIdSlave) );
580 shell.
Error(rc,
"Cannot link servos %d and %d.",
581 nServoIdMaster, nServoIdSlave);
608 const char *sContext)
611 static const char *keywordsDir[] = {
"forward",
"reverse"};
641 nServoId = m_nTabServoId;
650 snprintf(buf,
sizeof(buf),
"%d", nServoId);
651 buf[
sizeof(buf)-1] = 0;
653 if( !strncmp(buf, sText, uTextLen) )
661 else if( nArgNum == 2 )
663 while( m_nTabIndex < arraysize(keywordsDir) )
665 s = keywordsDir[m_nTabIndex++];
667 if( !strncmp(s, sText, uTextLen) )
702 m_sCmdName =
"unlink";
703 m_sCmdHelpBrief =
"Unlink two servos.";
704 m_sCmdHelpArgs =
"<master_id>";
705 m_sCmdHelpDesc =
"Unlink two servos previously linked in a master-slave " 707 " <master_id> Master servo id.";
722 TRY( ChkArgCnt(shell, argc) );
724 TRY( ToInt(shell, argv[0], &nServoId) );
726 TRY( ChkComm(shell) );
727 TRY( ChkChain(shell) );
728 TRY( ChkChainHasServo(shell, nServoId) );
734 shell.
Error(rc,
"Cannot unlink servo %d.", nServoId);
761 const char *sContext)
790 nServoId = m_nTabServoId;
799 snprintf(buf,
sizeof(buf),
"%d", nServoId);
800 buf[
sizeof(buf)-1] = 0;
802 if( !strncmp(buf, sText, uTextLen) )
834 m_sCmdName =
"megascan";
835 m_sCmdHelpBrief =
"Exhaustive scan for all connected servos.";
836 m_sCmdHelpArgs =
"<uri>";
837 m_sCmdHelpDesc =
"Scan the interface at all supported baud rates for " 838 "connected servos. The scan does not effect the " 839 "current dynamixel chain.\n" 840 " <uri> [botsense://[<hostname>][:<port>]]/<device>." 842 "Note: The servos may respond to a different baudrate " 843 "other the what is saved\n" 862 static int baudTbl[] =
864 1000000, 500000, 400000, 250000, 200000, 115200, 57600, 19200, 9600
875 TRY( ChkArgCnt(shell, argc) );
879 shell.
Response(
"Mega Scan on Interface %s.\n", sUri);
881 for(i=0; i<arraysize(baudTbl); ++i)
883 shell.
Response(
"%8d baudrate\n", baudTbl[i]);
885 pComm = CommNew(shell, sUri, baudTbl[i]);
894 if( pComm->
Ping(nServoId) )
900 shell.
Response(
"%4d:0x%04x", nServoId, uModelNum);
916 shell.
Response(
" %d servos found @%d baudrate\n", cnt, baudTbl[i]);
942 const char *sContext)
963 if( pDynaComm == NULL )
965 shell.
Error(
"Failed to create %s@%d.", sUri, nBaudRate);
968 else if( !pDynaComm->
IsOpen() )
970 shell.
Error(
"Failed to open %s@%d.", sUri, nBaudRate);
995 m_sCmdName =
"start";
996 m_sCmdHelpBrief =
"Start the dynamixel background thread.";
997 m_sCmdHelpArgs =
"[<hz>]";
998 m_sCmdHelpDesc =
"Start the background thread with the given or default " 999 "control and monitor execute hertz.\n" 1000 " <hz> Execute hertz.\n" 1024 TRY( ChkArgCnt(shell, argc) );
1026 TRY( ChkComm(shell) );
1027 TRY( ChkChainNotEmpty(shell) );
1036 shell.
Error(
"Background thread already running. " 1037 "Try stopping first.");
1043 TRY( ToDouble(shell, argv[0], &val) );
1055 shell.
Response(
"Background thread started.\n");
1077 const char *sContext)
1091 if( nArgNum > m_nArgCntMax )
1105 while( m_nTabIndex < 2 )
1109 if( m_nTabIndex == 1 )
1111 if( !strncmp(m_strTDefault.c_str(), sText, uTextLen) )
1134 buf[
sizeof(buf)-1] = 0;
1135 m_strTDefault = buf;
1155 m_sCmdName =
"stop";
1156 m_sCmdHelpBrief =
"Stop the dynamixel background thread.";
1157 m_sCmdHelpArgs =
"";
1158 m_sCmdHelpDesc =
"The dynamixel background thread stopped. The thread is " 1159 "not destroyed, simply blocked, and can be resumed.";
1176 TRY( ChkArgCnt(shell, argc) );
1178 TRY( ChkComm(shell) );
1179 TRY( ChkChainNotEmpty(shell) );
1189 shell.
Error(
"Background thread not running.");
1193 shell.
Response(
"Background thread stopped.\n");
1216 m_sCmdHelpBrief =
"Get the state of the dynamixel background thread.";
1217 m_sCmdHelpArgs =
"";
1218 m_sCmdHelpDesc =
"The dynamixel background thread state includes its " 1219 "operational state plus any task time periods.";
1238 TRY( ChkArgCnt(shell, argc) );
1240 TRY( ChkComm(shell) );
1241 TRY( ChkChainNotEmpty(shell) );
1265 shell.
Response(
"Background Thread: %s, Hz %lf.\n",
1288 m_sCmdName =
"halfduplex";
1289 m_sCmdHelpBrief =
"Set/unset sofware half-duplex control.";
1290 m_sCmdHelpArgs =
"none\n" 1291 "modem {rts | cts}\n" 1293 m_sCmdHelpDesc =
"Dynamixel 3-wire serial interface is a half-duplex " 1294 "channel. Software can control the channel direction by " 1295 "toggling between transmit and receive using a signal.\n" 1296 " Signaling types:\n" 1297 " none Disable software half-duplex control.\n" 1298 " modem Use built-in modem signal. Signals:\n" 1299 " rts - request to send.\n" 1300 " cts - clear to send.\n" 1301 " <gpio> Use GPIO signal (future).\n" 1302 " <number> - GPIO pin number. If negative,\n" 1303 " then transmit is active low.";
1318 TRY( ChkArgCnt(shell, argc) );
1319 TRY( ChkComm(shell) );
1321 if( !strncmp(
"none", argv[0], strlen(argv[0])) )
1325 else if( !strncmp(
"modem", argv[0], strlen(argv[0])) )
1327 TRY( ChkArgCntEQ(shell, argc, 2) );
1328 if( !strncmp(
"cts", argv[1], strlen(argv[1])) )
1332 else if( !strncmp(
"rts", argv[1], strlen(argv[1])) )
1342 else if( !strncmp(
"gpio", argv[0], strlen(argv[0])) )
1344 TRY( ChkArgCntEQ(shell, argc, 2) );
1345 TRY( ToInt(shell, argv[1], &nSignal) );
1357 shell.
Error(rc,
"Failed to set half-duplex %s signal control.", argv[0]);
1384 const char *sContext)
1386 static const char *keywordsSigType[] = {
"gpio",
"modem",
"none"};
1387 static const char *keywordsSigModem[] = {
"cts",
"rts"};
1388 static char cSigType =
'\0';
1409 while( m_nTabIndex < arraysize(keywordsSigType) )
1411 s = keywordsSigType[m_nTabIndex++];
1413 if( !strncmp(s, sText, uTextLen) )
1421 else if( nArgNum == 1 )
1424 if( cSigType ==
'm' )
1426 while( m_nTabIndex < arraysize(keywordsSigModem) )
1428 s = keywordsSigModem[m_nTabIndex++];
1430 if( !strncmp(s, sText, uTextLen) )
1437 else if( cSigType ==
'g' )
1441 else if( cSigType ==
'n' )
RoadNarrows Dynamixel Bus Communications Abstract Base Class Interface.
virtual uint_t GetServoMode() const
Get the servo operational mode.
virtual void RegisterChainAgent(DynaChain *pChain)
Register the Dynamixel chain for control and monitoring.
#define DYNA_OK
not an error, success
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
BgThreadState
Background thread states.
zombie instance - no thread exists
#define DYNA_MODEL_NUM_GENERIC
generic, base model
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
int GetLinkedMateId(int nServoId) const
Get linked mate.
void Exec(DynaShell &shell, int argc, char *argv[])
List servo chain info.
#define DYNA_MODE_SERVO
servo mode with limited rotation
Dynamixel shell utilities.
DynaComm * m_pDynaComm
dynamixel bus communication
static int BaudRateAt(int nIndex)
Get the baud rate associated with the given index.
virtual bool IsOpen()
Test if Dynamixel Bus is open.
int m_nTabIndex
tab completion: keyword index
thread created and ready to run
Link <master_id> <slaf_id> <dir> command.
void Exec(DynaShell &shell, int argc, char *argv[])
Execute background thread stop.
void Exec(DynaShell &shell, int argc, char *argv[])
Create dynamixel interface.
void SetTabTDefaults()
Set tab completion time period default strings.
void Exec(DynaShell &shell, int argc, char *argv[])
Link two servo together.
static int ReadModelNumber(DynaComm &comm, int nServoId, uint_t *pModelNum)
Read the servo model number from the servo's EEPROM.
BgThreadState GetCurrentState()
Get current background thread state.
Start the background thread.
bool IsUnlinked(int nServoId) const
Test if this servo is unlinked.
#define DELOBJ(p)
Delete an allocated object convenience macro.
int m_nTabServoId
tab completion: current servo id
RoadNarrows Dynamixel Servo Chain Container Base Class Interface.
static const int FIRST
first state
not a signal, but a value to clear signal
bool IsLinkedMaster(int nServoId) const
Test if this servo is a linked master.
#define DYNA_ID_MIN
minimum servo id
virtual uint_t GetFirmwareVersion() const
Get servo firmware version.
static char * dupstr(const string &str)
Duplicate string.
virtual bool Ping(int nServoId)=0
Ping the servo.
Dynamixel shell command abstract base class.
DynaComm * CommNew(DynaShell &shell, const char *sUri, int nBaudRate)
Create a new open dynamixel bus object.
virtual int IterStartMaster(int *pIter)
Start iteration master servos over of entire servo chain.
#define DYNA_ID_NUMOF
number of unique servo id's
static const double HZ_EXEC_DFT
default exec hertz
virtual int IterNextMaster(int *pIter)
Next iteration of master servos over of entire servo chain.
virtual uint_t GetNumberInChain() const
Get the number of servos currently in chain.
virtual int LinkServos(int nServoIdMaster, int nServoIdSlave, bool bIsReversed)
Software link two unlinked servos in a master-slave configuration.
virtual int Run()
Run the background thread control and monitoring tasks.
double getHz()
Get control and monitoring hetrz rate.
Start the background thread.
Dynamixel Servo Abstract Base Class.
Dynamixel background thread class declarations.
virtual int AddNewServosByScan()
Scan and add all discovered and created servos to the Dynamixel chain.
virtual int Stop()
Stop control and monitoring tasks.
virtual void UnregisterAgent()
Unregister any chain or servo from control and monitoring.
DynaComm * CommNew(DynaShell &shell, const char *sUri, int nBaudRate)
Create a new open dynamixel bus object.
static DynaComm * New(const char *sUri, int nBaudRate)
Archetype constructor to create a new Dynamixel bus communication derived instance.
Set halfduplex control command.
static int wc(const string &str)
Count the words in the string.
void Response(const char *sFmt,...)
Print formatted success response.
virtual void Ok()
Print standard ok success response.
Start the background thread.
void PublishShellInterfaceCommands(DynaShell &shell)
Publish shell dynamixel interface commands to shell.
virtual int SetHalfDuplexCtl(int nSignal, HalfDuplexTxFunc_T fnEnableTx=NULL, HalfDuplexRxFunc_T fnEnableRx=NULL)=0
string m_strTDefault
default time period value
int m_nTabServoId
tab completion: current servo id
void Exec(DynaShell &shell, int argc, char *argv[])
Scan interface at all supported baudrates for connected servos.
void Exec(DynaShell &shell, int argc, char *argv[])
Scan for all connected servos and add to chain.
void Exec(DynaShell &shell, int argc, char *argv[])
Ping a servo.
int m_nTabIter
tab completion: servo id iterator
RoadNarrows Dynamixel Bus Communication over Serial Interface Class Interface.
virtual int IterStart(int *pIter)
Start iteration over of entire servo chain.
virtual DynaServo * GetServo(int nServoId)
Dynamixel Chain Container Base Class.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
int m_nTabIndex
tab completion: index
void Exec(DynaShell &shell, int argc, char *argv[])
Execute background thread get state.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
DynaBgThread * m_pDynaBgThread
dynamixel chain
RoadNarrows Dynamixel Archetype Servo Abstract Base Class.
bool IsLinkedSlave(int nServoId) const
Test if this servo is a linked slave.
void Exec(DynaShell &shell, int argc, char *argv[])
Set software half-duplex control signal.
#define TRY(boolexpr,...)
Try boolean expression.
void PublishCommand(const char *sParent, DynaShellCmd *pNewCmd)
Publish new command to shell.
RoadNarrows Dynamixel Top-Level Package Header File.
virtual uint_t GetModelNumber() const
Get servo model number.
The dynashell Command Class Interface.
void Exec(DynaShell &shell, int argc, char *argv[])
Destroy dynamixel interface.
#define DYNA_ID_NONE
no servo id
void setHz(double fHz)
Set new control and monitoring execution hertz rate.
void Exec(DynaShell &shell, int argc, char *argv[])
Execute background thread start.
virtual int UnlinkServos(int nServoIdMaster)
Unlink two software linked servos.
virtual int IterNext(int *pIter)
Next iteration over of entire servo chain.
#define DYNA_ECODE_BAD_VAL
bad value
DynaChain * m_pDynaChain
dynamixel chain
void Error(int rc, const char *sFmt,...)
Raise error on dynamixel error code.
virtual const char * GetModelName() const
Get servo model name string.
static char * FileCompletionGenerator(const char *sText, int nState)
File name tab completion generator.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
int m_nTabIndex
tab completion: keyword index
int m_nTabIter
tab completion: baud rate iterator
The simple dynashell declarations.
virtual char * TabCompletion(DynaShell &shell, const char *sText, size_t uTextLen, int nState, const char *sContext)
Command tab completion generator.
int m_nTabIter
tab completion: servo id iterator
void Exec(DynaShell &shell, int argc, char *argv[])
Unlink two servo.
Dynamixel Bus Communications Abstract Base Class.