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.