Trees | Indices | Help |
---|
|
( concrete ) DESCRIPTION: -- The Protocol class provides the functionality needed to send messages using the Dynamixel Protocol as per section 3 of the EX-106 document RESPONSIBILITIES: -- detect modules on the bus and generate NodeAdaptors for each one -- ping modules periodically to ensure that they are still on the Bus?? -- store a queue of pending messages and handle them for during each update for a given timeslice -- act as a abstraction layer for basic Bus functionality? OWNERSHIP: -- owned by the Cluster THEORY: -- The protocol owns a dictionary of the NodeAdaptor of each module It initially checks for modules by performing a scan for all nodes that the user states should be on the Bus and for each module that exists it updates the heartbeat dictionary entry for that node A heartbeat, is a simple indicator of node existing, holding only a timestamp and the error received. Message transmission and reception is based upon the following ideas: - If asked, Dynamixel servos always send a response - Dynamixel servos have no Bus arbitration, therefore the response to a request always follows the request - There are three types of requests - Writes that require an acknowledgement - Reads that require an acknowledgement - Writes that do not require an acknowledgement The aformentioned ideas led to the following decisions: - Messages should be placed in a queue and handled in order of requests - Message that do not require a response should be sent using the "SYNC_WRITE" command as per section 3-5-7 pp. 39 in the EX-106 document and no response should be expected. - Messages that require a response should be sent and listened for. If a response is not found, a number of retries should occur to accomodate for errors A basic representation of the update() algorithm follows: get the allowed timeslice while len queue > 0: pop message from queue if message has timed out: declare message promise as Err if allowed timeslice is used up: append message to front of queue and exit if the message is a broadcast message: if ping: warn that broadcast pings are not allowed outside of scan else: send message through Bus, and continue to next message else: for number of retries remaining in message: if allowed timeslice is used up: append message to front of queue and exit send message through Bus while have not reached timeout or timeslice is used up: read in packet if packet exists: fulfill message promise, and continue to next message sleep so that we don't overwork the OS if no more retries remaining: declare message promise as Err CONSTRAINTS: -- a single write when handled by update must have only a single response -- it is expected that a Dynamixel Bus has been instantiated as shown in the Dynamixel Module Examples
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
Inherited from |
|
|||
Inherited from |
|
Initialize a Dynamixel Protocol INPUTS: bus -- object -- dynamixel bus object used for basic communication with dynamixel servos nodes -- list -- list of expected dynamixel servo IDs ATTRIBUTES: pnas -- dictionary -- dict of NodeAdaptor objects, used for interfacing with Dynamixel Module heartbeats -- dictionary -- dict of node heartbeats. nid : (timestamp, err) requests -- deque object -- queue of pending requests <<< maybe should just be a list? ping_period -- float -- expected ping period
|
Reset the Protocol object INPUTS: ping_rate -- float -- rate at which to ping nodes OUTPUTS: None THEORY OF OPERATION: scan for nodes, add each node to the pollRing and generate a ProtocolNodeAdaptor |
Build a broadcast ping message and then read for responses, and if the get_model flag is set, then get model numbers for all existing nodes INPUTS: timeout -- float -- amount of time allowed to scan retries -- int -- number of times allowed to retry scan get_model -- bool -- flag determining if node model numbers should be read to indicate the servo type OUTPUTS: found -- dict -- map from servo IDs that were discovered to their model numbers, or None if get_model is False THEORY OF OPERATION: Assemble packet as per EX-106 section 3-2 pp. 16, using PING Command as per section 3-5-5 pp. 37 and broadcast ID Send this packet, then read responses and add to set until timeout and number of retries. |
Generate NodeAdaptors for nodes that are not already in pnas INPUTS: nodes -- list -- list of expected nodes THEORY OF OPERATION: Get all node IDs that are in nodes but not in pnas and generate a NodeAdaptors for those nodes
|
Generate NodeAdaptors for given Node ID INPUTS: nid -- int -- ID of node to generate ProtocolNodeAdaptor object for OUTPUTS: pna -- object -- ProtocolNodeAdaptor object for given nid THEORY OF OPERATION: Instantiate ProtocolNodeAdaptor add to pnas dictionary
|
Turn all servos off ... see Bus.off |
Send a memory write command and don't wait for a response INPUTS: addr -- char -- address val -- int -- value pars -- string -- parameters OUTPUTS: msg -- string -- transmitted packet minus SYNC |
Send a memory write command and wait for response, returning it INPUTS: addr -- char -- address val -- int -- value pars -- string -- parameters OUTPUTS: msg -- string -- transmitted packet minus SYNC |
A Protocol level syncronous memory read wrapper around bus.send_cmd_sync INPUTS: nid -- int -- node ID addr -- string hex -- address location to read from length -- int -- number of bytes to read retries -- int -- number of times to retry if there exist protocol errors |
Send a response request by creating an incomplete messsage and appending it to the queue for handling by update INPUTS: nid -- int -- node ID of module cmd -- int -- command value. ie: CMD_PING, CMD_WRITE_DATA, etc ... pars -- string -- parameter string OUTPUTS: promise -- list -- promise of incomplete message, will be fulfilled upon successful read PRECONDITIONS: None? POSTCONDITIONS: None? THEORY OF OPERATION: Create an incomplete message for a given request that holds the packet to be written and has a number of other attributes ( see Request ) Then append to Protocols queue for later handling and return a promise that will be fulfilled by a successful read during Protocol.update() |
Use pollRing to poll all nodes that haven't been seen for self.ping_rate seconds with ping packets. INPUTS: now -- float -- current time |
The update method handles current incomplete message requests and ensures that nodes are pinged to check for their existance INPUTS: None OUTPUTS: num_requests -- int -- length of request queue PRECONDITIONS: instantiation of dynamixel.Bus, dynamixel.Protocol POSTCONDITIONS: No response occurs THEORY OF OPERATION: get the allowed timeslice while timeslice not done: if queue empty --> return pop 1st message on queue if message has timed out: fill promise with ProtocolError(timeout) continue if message ID is BROADCAST_ID: if message cmd not CMD_SYNC_WRITE: bus.send the message fill promise with None else: fill promise with ProtocolError(not CMD_SYNC_WRITE bcast not allowed) continue else: bus.send_cmd_sync the message store reply in promise
|
Process a single incomplete request If it requires a response -- complete it or time-out; if not, complete with a None reply TODO finish comment |
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 on Thu Jan 4 16:46:17 2018 | http://epydoc.sourceforge.net |