Gripper Cuff Control - Code Walkthrough

From sdk-wiki
Revision as of 15:11, 29 July 2014 by Sdkuser (talk | contribs) (Protected "Gripper Cuff Control - Code Walkthrough": Setting Permissions for (almost all) Pages - editable and moveable by all logged in users ([Edit=Allow only autoconfirmed users] (indefinite) [Move=Allow only autoconfirmed users] (indefinite)))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Introduction

This program demonstrates the usage of gripper interface to control the close and open actions of the grippers. The main() function creates an instance of the GripperConnect class which connects the gripper buttons to various callback functions.
Interfaces -

  • DigitalIO.state_changed()
  • Gripper.calibrated()
  • Gripper.calibrate()
  • Gripper.type()
  • Gripper.on_type_changed
  • Gripper.close()
  • Gripper.open()
  • Gripper.ready()

Code Walkthrough

Now, let's break down the code.

30 import argparse
31 import sys
32 
33 import rospy
34 
35 from baxter_interface import (
36     DigitalIO,
37     Gripper,
38     Navigator,
39     CHECK_VERSION,
40 )

The interfaces for the grippers, the navigator buttons, and the lights are imported. The CHECK_VERSION is imported to check if the software running on the robot would be compatible with this local version. It is not necessary to check the version in custom programs.

43 class GripperConnect(object):
44     """
45     Connects wrist button presses to gripper open/close commands.
46 
47     Uses the DigitalIO Signal feature to make callbacks to connected
48     action functions when the button values change.
49     """
50 
51     def __init__(self, arm, lights=True):
52         """
53         @type arm: str
54         @param arm: arm of gripper to control {left, right}
55         @type lights: bool
56         @param lights: if lights should activate on cuff grasp
57         """
58         self._arm = arm
59         # inputs
60         self._close_io = DigitalIO('%s_upper_button' % (arm,))  # 'dash' btn
61         self._open_io = DigitalIO('%s_lower_button' % (arm,))   # 'circle' btn
62         self._light_io = DigitalIO('%s_lower_cuff' % (arm,))    # cuff squeeze
63         # outputs
64         self._gripper = Gripper('%s' % (arm,), CHECK_VERSION)
65         self._nav = Navigator('%s' % (arm,))

Instances of the cuff squeeze, grasp, and open buttons are created. Also, interfaces for the gripper and the navigator are created.

67         # connect callback fns to signals
68         if self._gripper.type() != 'custom':
69             if not (self._gripper.calibrated() or
70                     self._gripper.calibrate() == True):
71                 rospy.logwarn("%s (%s) calibration failed.",
72                               self._gripper.name.capitalize(),
73                               self._gripper.type())
74         else:
75             msg = (("%s (%s) not capable of gripper commands."
76                    " Running cuff-light connection only.") %
77                    (self._gripper.name.capitalize(), self._gripper.type()))
78             rospy.logwarn(msg)

The method calibrated() returns true if the grippers were already in a calibrated state. calibrate() method performs the actual calibration for the grippers. type() method returns the gripper types like "electric", "vacuum" or "custom" and the name returns the component id of the gripper. The grippers are verified not to be custom grippers and then calibrated if they were not already calibrated.

33         self._gripper.on_type_changed.connect(self._check_calibration)
34         self._open_io.state_changed.connect(self._open_action)
35         self._close_io.state_changed.connect(self._close_action)
36 
37         if lights:
38             self._light_io.state_changed.connect(self._light_action)
39 
40         rospy.loginfo("%s Cuff Control initialized...",
41                       self._gripper.name.capitalize())

The on_type_changed method is invoked whenever a new type of gripper is connected. This event is connected to the _check_calibration() function. Similarly on the state changed event (On/Off) for the gripper open/close buttons and the light, the functions _open_action, _close_action and _light_actions() are triggered respectively.

90     def _open_action(self, value):
91         if value and self._is_grippable():
92             rospy.logdebug("gripper open triggered")
93             self._gripper.open()

The open() method opens the gripper when the button sends a True value.

95     def _close_action(self, value):
96         if value and self._is_grippable():
97             rospy.logdebug("gripper close triggered")
98             self._gripper.close()

The open() method closes the gripper when the button sends a True value.

100     def _light_action(self, value):
101         if value:
102             rospy.logdebug("cuff grasp triggered")
103         else:
104             rospy.logdebug("cuff release triggered")
105         self._nav.inner_led = value
106         self._nav.outer_led = value

This method assigns the boolean value that was signalled to the light I/O interface, through to the navigator's LEDs.

108     def _check_calibration(self, value):
109         if self._gripper.calibrated():
110             return True
111         elif value == 'electric':
112             rospy.loginfo("calibrating %s...",
113                           self._gripper.name.capitalize())
114             return (self._gripper.calibrate() == True)
115         else:
116             return False

This method is invoked when the gripper type is changed. This method checks if the grippers are already calibrated and calibrates them if not.

118     def _is_grippable(self):
119         return (self._gripper.calibrated() and self._gripper.ready())

The ready() method returns a bool describing if the gripper ready, i.e. is calibrated, not busy (as in resetting or rebooting), and not moving. This method indicates if the gripper is already calibrated and ready to be used.

122 def main():
123     """RSDK Gripper Button Control Example
124 
125     Connects cuff buttons to gripper open/close commands:
126         'Circle' Button    - open gripper
127         'Dash' Button      - close gripper
128         Cuff 'Squeeze'     - turn on Nav lights
129 
130     Run this example in the background or in another terminal
131     to be able to easily control the grippers by hand while
132     using the robot. Can be run in parallel with other code.
133     """
134     arg_fmt = argparse.RawDescriptionHelpFormatter
135     parser = argparse.ArgumentParser(formatter_class=arg_fmt,
136                                      description=main.__doc__)
137     parser.add_argument('-g', '--gripper', dest='gripper', default='both',
138                         choices=['both', 'left', 'right'],
139                         help='gripper limb to control (default: both)')
140     parser.add_argument('-n', '--no-lights', dest='lights',
141                         action='store_false',
142                         help='do not trigger lights on cuff grasp')
143     parser.add_argument('-v', '--verbose', dest='verbosity',
144                         action='store_const', const=rospy.DEBUG,
145                         default=rospy.INFO,
146                         help='print debug statements')
147     args = parser.parse_args(rospy.myargv()[1:])

The side of the gripper and the option of using the navigator lights are parsed from the command line arguments, as entered by the user.

149     rospy.init_node('rsdk_gripper_cuff_control_%s' % (args.gripper,),
150                     log_level=args.verbosity)
151 
152     arms = (args.gripper,) if args.gripper != 'both' else ('left', 'right')
153     grip_ctrls = [GripperConnect(arm, args.lights) for arm in arms]
154 
155     print("Press cuff buttons to control grippers. Spinning...")
156     rospy.spin()
157     print("Gripper Button Control Finished.")
158     return 0
159 
160 if __name__ == '__main__':
161     sys.exit(main())

The node is initialized and an instance of the GripperConnect is created for either of the side, or both the sides as desired by the user.