37 from functools
import partial
40 from std_msgs.msg
import Int32
42 from sensor_msgs.msg
import JointState
49 from behavior_switch_action_msgs.msg
import BehaviorSwitchAction, BehaviorSwitchGoal
51 from trajectory_msgs.msg
import JointTrajectory, JointTrajectoryPoint
52 from control_msgs.msg
import FollowJointTrajectoryAction, FollowJointTrajectoryResult,\
53 FollowJointTrajectoryGoal, JointTolerance
54 from velma_look_at_action_msgs.msg
import LookAtAction, LookAtGoal, LookAtResult
55 import diagnostic_msgs.msg
56 import tf_conversions.posemath
as pm
58 import subsystem_common
60 import xml.dom.minidom
as minidom
66 For joint names that refer to joints that are symmetrical (*left* or *right*), get the name 69 @param joint_name string: name of joint. 71 @return name of the joint symmetrical to joint_name, or None, if such does not exist. 73 if joint_name.startswith(
'left'):
74 return 'right' + joint_name[4:]
75 elif joint_name.startswith(
'right'):
76 return 'left' + joint_name[5:]
81 Get configuration based on the input configuration such that all joint positions are symmetrical. 83 @param q_map Dictionary: configuration {joint_name:joint_position}. 85 @return Dictionary with symmetrical configuration. 88 for joint_name
in q_map:
89 assert not joint_name
in result
90 result[joint_name] = q_map[joint_name]
92 if not sym_joint_name
is None:
93 assert not sym_joint_name
in result
94 result[sym_joint_name] = -q_map[joint_name]
99 Check if two configurations of robot body are close within tolerance. 101 @param q_map1 dictionary: Dictionary {name:position} that maps joint names to their positions. 102 @param q_map2 dictionary: Dictionary {name:position} that maps joint names to their positions. 104 @return True if two configurations are close within tolerance (for every joint), False otherwise. 106 @exception KeyError: Either q_map1 or q_map2 dictionaries does not contain required key, i.e. one 107 of robot body joint names. 109 joint_names = [
'torso_0_joint',
'right_arm_0_joint',
'right_arm_1_joint',
110 'right_arm_2_joint',
'right_arm_3_joint',
'right_arm_4_joint',
'right_arm_5_joint',
111 'right_arm_6_joint',
'left_arm_0_joint',
'left_arm_1_joint',
'left_arm_2_joint',
112 'left_arm_3_joint',
'left_arm_4_joint',
'left_arm_5_joint',
'left_arm_6_joint']
114 for joint_name
in joint_names:
115 if allow_subset
and (
not joint_name
in q_map1
or not joint_name
in q_map2):
117 if abs(q_map1[joint_name] - q_map2[joint_name]) > tolerance:
123 Check if two configurations of robot neck are close within tolerance. 125 @param q1 tuple: 2-tuple of neck joints positions. 126 @param q2 tuple: 2-tuple of neck joints positions. 128 @return True if two configurations are close within tolerance (for every joint), False otherwise. 130 return abs(q1[0]-q2[0]) < tolerance
and abs(q1[1]-q2[1]) < tolerance
134 Check if two configurations of robot hand are close within tolerance. 136 @param current_q tuple: 8-tuple of hand joints positions. 137 @param dest_q tuple: 4-tuple of hand DOFs positions. 139 @return True if two configurations are close within tolerance (for every joint), False otherwise. 141 return abs(current_q[0]-dest_q[3]) < tolerance
and\
142 abs(current_q[1]-dest_q[0]) < tolerance
and\
143 abs(current_q[4]-dest_q[1]) < tolerance
and\
144 abs(current_q[6]-dest_q[2]) < tolerance
148 Split a long trajectory into a number of shorter trajectories. 150 @param joint_trajectory trajectory_msgs.msg.JointTrajectory: A joint trajectory to be splitted. 151 @param max_traj_len int: Maximum number of nodes in the result trajectory. 152 @return Returns list of trajectory_msgs.msg.JointTrajectory -- the input trajectory split 153 into a number of trajectories of length not greater than max_traj_len. 155 assert isinstance(joint_trajectory, JointTrajectory)
156 if len(joint_trajectory.points) > max_traj_len:
160 new_traj = JointTrajectory()
161 new_traj.header = joint_trajectory.header
162 new_traj.joint_names = joint_trajectory.joint_names
163 time_base = rospy.Duration(0.0)
164 for idx
in range(len(joint_trajectory.points)):
165 point = copy.copy( joint_trajectory.points[idx] )
166 point.time_from_start = point.time_from_start - time_base
167 new_traj.points.append( point )
168 if len(new_traj.points) >= max_traj_len:
169 result.append( new_traj )
170 new_traj = JointTrajectory()
171 new_traj.header = joint_trajectory.header
172 new_traj.joint_names = joint_trajectory.joint_names
173 point = copy.copy( joint_trajectory.points[idx] )
174 time_base = point.time_from_start - rospy.Duration(0.5)
175 point.time_from_start = point.time_from_start - time_base
176 new_traj.points.append( point )
178 if len(new_traj.points) > 0:
179 result.append( new_traj )
183 return [joint_trajectory]
187 ROS-based, Python interface class for WUT Velma Robot. 189 This class implements methods that use ROS topics, actions and services 190 to communicate with velma_task_cs_ros_interface subsystem of velma_task 199 This class contains information about geometric object: mesh. 208 This class contains information about single link of robot. 220 'Wr':
'right_arm_7_link',
221 'wrist_right':
'right_arm_7_link',
222 'Wl':
'left_arm_7_link',
223 'wrist_left':
'left_arm_7_link',
224 'Er':
'right_arm_7_link',
225 'El':
'left_arm_7_link',
226 'Wright':
'right_arm_7_link',
227 'Wleft':
'left_arm_7_link',
228 'Gr':
'right_HandGripLink',
229 'grip_right':
'right_HandGripLink',
230 'Gl':
'left_HandGripLink',
231 'grip_left':
'left_HandGripLink',
232 'Pr':
'right_HandPalmLink',
233 'Pl':
'left_HandPalmLink',
234 'Tr':
'right_arm_tool',
235 'Tl':
'left_arm_tool',
236 'Tright':
'right_arm_tool',
237 'Tleft':
'left_arm_tool',
238 'Fr00':
'right_HandFingerOneKnuckleOneLink',
239 'Fr01':
'right_HandFingerOneKnuckleTwoLink',
240 'Fr02':
'right_HandFingerOneKnuckleThreeLink',
241 'Fr10':
'right_HandFingerTwoKnuckleOneLink',
242 'Fr11':
'right_HandFingerTwoKnuckleTwoLink',
243 'Fr12':
'right_HandFingerTwoKnuckleThreeLink',
244 'Fr21':
'right_HandFingerThreeKnuckleTwoLink',
245 'Fr22':
'right_HandFingerThreeKnuckleThreeLink',
246 'Fl00':
'left_HandFingerOneKnuckleOneLink',
247 'Fl01':
'left_HandFingerOneKnuckleTwoLink',
248 'Fl02':
'left_HandFingerOneKnuckleThreeLink',
249 'Fl10':
'left_HandFingerTwoKnuckleOneLink',
250 'Fl11':
'left_HandFingerTwoKnuckleTwoLink',
251 'Fl12':
'left_HandFingerTwoKnuckleThreeLink',
252 'Fl21':
'left_HandFingerThreeKnuckleTwoLink',
253 'Fl22':
'left_HandFingerThreeKnuckleThreeLink',
256 _cartesian_trajectory_result_names = {
257 CartImpResult.SUCCESSFUL:
'SUCCESSFUL',
258 CartImpResult.INVALID_GOAL:
'INVALID_GOAL',
259 CartImpResult.OLD_HEADER_TIMESTAMP:
'OLD_HEADER_TIMESTAMP',
260 CartImpResult.PATH_TOLERANCE_VIOLATED:
'PATH_TOLERANCE_VIOLATED',
261 CartImpResult.GOAL_TOLERANCE_VIOLATED:
'GOAL_TOLERANCE_VIOLATED',
262 CartImpResult.UNKNOWN_ERROR:
'UNKNOWN_ERROR' }
264 _joint_trajectory_result_names = {
265 FollowJointTrajectoryResult.SUCCESSFUL:
"SUCCESSFUL",
266 FollowJointTrajectoryResult.INVALID_GOAL:
"INVALID_GOAL",
267 FollowJointTrajectoryResult.INVALID_JOINTS:
"INVALID_JOINTS",
268 FollowJointTrajectoryResult.OLD_HEADER_TIMESTAMP:
"OLD_HEADER_TIMESTAMP",
269 FollowJointTrajectoryResult.PATH_TOLERANCE_VIOLATED:
"PATH_TOLERANCE_VIOLATED",
270 FollowJointTrajectoryResult.GOAL_TOLERANCE_VIOLATED:
"GOAL_TOLERANCE_VIOLATED" }
272 _look_at_result_names = {
273 LookAtResult.SUCCESSFUL:
'SUCCESSFUL',
274 LookAtResult.OUT_OF_RANGE:
'OUT_OF_RANGE',
275 LookAtResult.WRONG_BEHAVIOUR:
'WRONG_BEHAVIOUR',
276 LookAtResult.MOTION_FAILED:
'MOTION_FAILED' }
278 _moveHand_action_error_codes_names = {
280 -1:
"INVALID_DOF_NAME",
284 -5:
"RESET_IS_ACTIVE"}
286 _core_ve_name =
"/velma_core_ve_body" 287 _core_cs_name =
"/velma_core_cs" 288 _task_cs_name =
"/velma_task_cs_ros_interface" 291 "impedance_joints":[
'torso_0_joint',
'right_arm_0_joint',
'right_arm_1_joint',
292 'right_arm_2_joint',
'right_arm_3_joint',
'right_arm_4_joint',
'right_arm_5_joint',
293 'right_arm_6_joint',
'left_arm_0_joint',
'left_arm_1_joint',
'left_arm_2_joint',
294 'left_arm_3_joint',
'left_arm_4_joint',
'left_arm_5_joint',
'left_arm_6_joint'],
295 "right_arm":[
'right_arm_0_joint',
'right_arm_1_joint',
'right_arm_2_joint',
296 'right_arm_3_joint',
'right_arm_4_joint',
'right_arm_5_joint',
'right_arm_6_joint'],
297 "right_arm_torso":[
'torso_0_joint',
'right_arm_0_joint',
'right_arm_1_joint',
298 'right_arm_2_joint',
'right_arm_3_joint',
'right_arm_4_joint',
'right_arm_5_joint',
299 'right_arm_6_joint'],
300 "left_arm":[
'left_arm_0_joint',
'left_arm_1_joint',
'left_arm_2_joint',
'left_arm_3_joint',
301 'left_arm_4_joint',
'left_arm_5_joint',
'left_arm_6_joint'],
302 "left_arm_torso":[
'torso_0_joint',
'left_arm_0_joint',
'left_arm_1_joint',
303 'left_arm_2_joint',
'left_arm_3_joint',
'left_arm_4_joint',
'left_arm_5_joint',
305 "head":[
"head_pan_joint",
"head_tilt_joint"]
310 Get the newest joint state. 312 @return (rospy.Time, dictionary): A Pair of timestamp of the newest joint state and dictionary 313 (with key=joint_name, value=joint_position), or None if there is no joint state data yet. 323 Get interpolated joint state at a given time. 325 @param time rospy.Time: Time of joint state to be computed. 327 @return dictionary: A dictionary (with key=joint_name, value=joint_position) of interpolated joint positions 328 or None, if time is not within current joint state history. 336 for step
in range(hist_len-1):
344 if time > time1
and time <= time2:
345 factor = (time - time1).to_sec() / (time2 - time1).to_sec()
353 def _jointStatesCallback(self, data):
356 for joint_idx, joint_name
in enumerate(data.name):
357 js_pos[joint_name] = data.position[joint_idx]
364 Get current configuration of a specified hand. 366 @param prefix string: Hand name, can be one of two values ('left' or 'right'). 368 @return An 8-tuple of positions of all joints of the specified hand, 369 or None if there is no valid joint state data. The sequence 370 of joint positions is: FingerOneKnuckleOneJoint, FingerOneKnuckleTwoJoint, 371 FingerOneKnuckleThreeJoint, FingerTwoKnuckleOneJoint, FingerTwoKnuckleTwoJoint, 372 FingerTwoKnuckleThreeJoint, FingerThreeKnuckleTwoJoint, 373 FingerThreeKnuckleThreeJoint. 375 @exception NameError: If prefix is not 'left' or 'right'. 377 if prefix !=
'left' and prefix !=
'right':
378 raise NameError(
'wrong prefix: ' + str(prefix))
382 q = ( js[1][prefix+
'_HandFingerOneKnuckleOneJoint'],
383 js[1][prefix+
'_HandFingerOneKnuckleTwoJoint'],
384 js[1][prefix+
'_HandFingerOneKnuckleThreeJoint'],
385 js[1][prefix+
'_HandFingerTwoKnuckleOneJoint'],
386 js[1][prefix+
'_HandFingerTwoKnuckleTwoJoint'],
387 js[1][prefix+
'_HandFingerTwoKnuckleThreeJoint'],
388 js[1][prefix+
'_HandFingerThreeKnuckleTwoJoint'],
389 js[1][prefix+
'_HandFingerThreeKnuckleThreeJoint'] )
394 Get current configuration of left hand. 396 @return tuple: An 8-tuple of positions of all joints of left hand, 397 or None if there is no valid joint state data. 399 @see getHandCurrentConfiguration 405 Get current configuration of right hand. 407 @return tuple: An 8-tuple of positions of all joints of right hand, 408 or None if there is no valid joint state data. 410 @see getHandCurrentConfiguration 417 Get current configuration of neck. 419 @return tuple: A 2-tuple of positions of neck joints, 420 or None if there is no valid joint state data. 425 q = ( js[1][
"head_pan_joint"],
426 js[1][
"head_tilt_joint"] )
429 def __isActionConnected(self, action_name):
430 self.
dbgPrint(
'__isActionConnected: "{}"'.format(action_name))
439 def __connectAction(self, action_name, action, timeout_s):
440 self.
dbgPrint(
'__connectAction: wait for server "{}"'.format(action_name))
441 is_connected = action.wait_for_server(rospy.Duration(timeout_s))
442 self.
dbgPrint(
'__connectAction: "{}", connected: {}'.format(action_name, is_connected))
446 def __getDiagInfo(self, timeout_s):
448 time_start = time.time()
449 while not rospy.is_shutdown():
452 if len(diag.history) > 0:
458 time_now = time.time()
459 if timeout_s
and (time_now-time_start) > timeout_s:
462 def __isInitialized(self):
476 Wait for the interface until it is initialized. 478 @param timeout_s float: Timeout in seconds. 480 @return True if the interface was succesfully initialized within timeout, False otherwise. 484 self.
dbgPrint(
'Getting ROS parameters')
486 self.
dbgPrint(
'Could not get all ROS parameters')
488 self.
dbgPrint(
'Got all ROS parameters')
490 time_start = time.time()
491 if timeout_s
is None:
497 for action_name, action
in self.
__action_map.iteritems():
498 self.
dbgPrint(
'Running thread for connecting action "{}"'.format(action_name))
500 t = threading.Thread(name=
'action-{}'.format(action_name),
504 threads.append( (action_name, t) )
506 t = threading.Thread(name=
'get-diag-info',
509 threads.append( (
None, t) )
511 for action_name, t
in threads:
512 self.
dbgPrint(
'Joining thread for connecting action "{}"'.format(action_name))
516 self.
dbgPrint(
'Waiting for full initialization')
517 while (time.time()-time_start) < timeout_s:
523 print(
"ERROR: waitForInit: timeout")
526 print(
' is_action_connected({}): information is missing'.format(action_name))
528 print(
' is_action_connected({}): {}'.format(action_name,
533 self.
dbgPrint(
'Failed to initialize')
540 Wait for reception of joint state ROS msg with time stamp greater or equal abs_time 542 @param abs_time rospy.Time: absolute time. 544 @return Returns True. 546 while not rospy.is_shutdown():
548 if (js[0] - abs_time).to_sec() > 0:
555 Gets limits of joints of both arms and torso. 556 Joints of neck and grippers are not included. 557 The joints are used in impedance control (both joint and cartesian). 559 @return dictionary: Returns a dictionary {name:(lower_limit, upper_limit)} that maps joint name to 560 a 2-tupe with lower and upper joint limit. 566 Gets limits of joints of both arms and torso in cart_imp mode. 567 Joints of neck and grippers are not included. 568 The joints are used in impedance control (cart_imp mode). 570 @return dictionary: Returns a dictionary {name:(lower_limit, upper_limit, [lower_limit, upper_limit)])} that maps joint name to 571 a 2-tupe or 4-tupe with lower and upper joint limit. 577 Gets limits of joints of neck. 579 @return dictionary: Returns a dictionary {name:(lower_limit, upper_limit)} that maps joint name to 580 a 2-tupe with lower and upper joint limit. 584 def __tryGetRosParams(self):
590 raise RuntimeError(
"Wrong number of joints")
602 "torso_0_joint": (-1.57, 1.57),
603 "right_arm_0_joint": (-2.96706, 2.96706),
604 "right_arm_1_joint": (-2.0944, 2.0944),
605 "right_arm_2_joint": (-2.96706, 2.96706),
606 "right_arm_3_joint": (-2.0944, 2.0944),
607 "right_arm_4_joint": (-2.96706, 2.96706),
608 "right_arm_5_joint": (-2.0944, 2.0944),
609 "right_arm_6_joint": (-2.96706, 2.96706),
610 "left_arm_0_joint": (-2.96706, 2.96706),
611 "left_arm_1_joint": (-2.0944, 2.0944),
612 "left_arm_2_joint": (-2.96706, 2.96706),
613 "left_arm_3_joint": (-2.0944, 2.0944),
614 "left_arm_4_joint": (-2.96706, 2.96706),
615 "left_arm_5_joint": (-2.0944, 2.0944),
616 "left_arm_6_joint": (-2.96706, 2.96706),
621 joint_names = rospy.get_param(self.
_core_cs_name+
"/JntLimit/joint_names")
622 if not joint_names
is None:
624 for idx, joint_name
in enumerate(joint_names):
626 jnt_limits = rospy.get_param(
'{}/JntLimit/limits_{}'.format(self.
_core_cs_name, idx))
628 for lim
in jnt_limits:
645 "head_pan_joint": (-1.57, 1.57),
646 "head_tilt_joint": (-1, 1.3),
656 self.
dbgPrint(
'Getting ROS parameter: /robot_description')
657 robot_description_xml = rospy.get_param(
"/robot_description")
660 self.
dbgPrint(
'parsing robot_description')
661 dom = minidom.parseString(robot_description_xml)
662 robot = dom.getElementsByTagName(
"robot")
664 raise Exception(
"Could not parse robot_description xml: wrong number of 'robot' elements.")
665 links = robot[0].getElementsByTagName(
"link")
667 name = l.getAttribute(
"name")
669 raise Exception(
"Could not parse robot_description xml: link element has no name.")
671 self.
dbgPrint(
'parsing link "{}"'.format(name))
673 obj_link = self.
Link()
676 visual = l.getElementsByTagName(
"visual")
678 origin = v.getElementsByTagName(
"origin")
680 raise Exception(
"Could not parse robot_description xml: wrong number of origin elements in link " + name)
681 rpy = origin[0].getAttribute(
"rpy").split()
682 xyz = origin[0].getAttribute(
"xyz").split()
683 frame = PyKDL.Frame(PyKDL.Rotation.RPY(float(rpy[0]), float(rpy[1]), float(rpy[2])), PyKDL.Vector(float(xyz[0]), float(xyz[1]), float(xyz[2])))
684 geometry = v.getElementsByTagName(
"geometry")
685 if len(geometry) != 1:
686 raise Exception(
"Could not parse robot_description xml: wrong number of geometry elements in link " + name)
687 mesh = geometry[0].getElementsByTagName(
"mesh")
690 obj_visual.filename = mesh[0].getAttribute(
"filename")
692 obj_visual.origin = frame
693 obj_link.visuals.append( obj_visual )
706 except Exception
as e:
707 self.
dbgPrint(
'Exception on getting ROS parameters: {}'.format(e))
727 print(
'VelmaInterface: {}'.format(s))
732 Initialization of the interface. 735 self.
dbgPrint(
'Running initializer')
747 self.
dbgPrint(
'Creating tf listener')
763 actionlib.SimpleActionClient(
764 "/velma_task_cs_ros_interface/spline_trajectory_action_joint",
765 FollowJointTrajectoryAction),
767 actionlib.SimpleActionClient(
768 "/velma_task_cs_ros_interface/head_spline_trajectory_action_joint",
769 FollowJointTrajectoryAction),
771 actionlib.SimpleActionClient(
772 "/velma_task_cs_ros_interface/relax_action",
773 BehaviorSwitchAction),
775 actionlib.SimpleActionClient(
776 "/velma_task_cs_ros_interface/right_arm/grasped_action",
779 actionlib.SimpleActionClient(
780 "/velma_task_cs_ros_interface/left_arm/grasped_action",
782 'identification_right':
783 actionlib.SimpleActionClient(
784 "/velma_task_cs_ros_interface/right_arm/identification_action",
785 IdentificationAction),
786 'identification_left':
787 actionlib.SimpleActionClient(
788 "/velma_task_cs_ros_interface/left_arm/identification_action",
789 IdentificationAction),
791 actionlib.SimpleActionClient(
792 "/velma_task_cs_ros_interface/motors/hp",
795 actionlib.SimpleActionClient(
796 "/velma_task_cs_ros_interface/motors/ht",
799 actionlib.SimpleActionClient(
800 "/velma_task_cs_ros_interface/motors/t",
803 actionlib.SimpleActionClient(
804 "/velma_task_cs_ros_interface/right_hand/move_hand",
807 actionlib.SimpleActionClient(
808 "/velma_task_cs_ros_interface/left_hand/move_hand",
811 actionlib.SimpleActionClient(
812 "/velma_task_cs_ros_interface/right_arm/cartesian_trajectory",
815 actionlib.SimpleActionClient(
816 "/velma_task_cs_ros_interface/left_arm/cartesian_trajectory",
819 actionlib.SimpleActionClient(
820 '/velma_look_at_action',
830 self.
dbgPrint(
'Creating publisher /velma_task_cs_ros_interface/allow_hands_col_in')
831 self.
__pub_allow_hands_col = rospy.Publisher(
'/velma_task_cs_ros_interface/allow_hands_col_in', Int32, queue_size=10)
839 self.
dbgPrint(
'Creating subscriber /joint_states')
842 subscribed_topics_list = [
843 (
'/right_arm/transformed_wrench', geometry_msgs.msg.Wrench),
844 (
'/left_arm/transformed_wrench', geometry_msgs.msg.Wrench),
845 (
'/right_arm/wrench', geometry_msgs.msg.Wrench),
846 (
'/left_arm/wrench', geometry_msgs.msg.Wrench),
847 (
'/right_arm/ft_sensor/wrench', geometry_msgs.msg.Wrench),
848 (
'/left_arm/ft_sensor/wrench', geometry_msgs.msg.Wrench),
849 (self.
_core_ve_name +
"/diag", diagnostic_msgs.msg.DiagnosticArray),
850 (self.
_core_cs_name +
"/diag", diagnostic_msgs.msg.DiagnosticArray),]
854 for topic_name, topic_type
in subscribed_topics_list:
855 self.
dbgPrint(
'Creating subscriber {}'.format(topic_name))
857 topic_name, topic_type, debug=self.
__debug)
859 self.
dbgPrint(
'Initializer function is done')
863 Class used for subscription for various ROS topics from the VelmaInterface class. 869 print(
'SubscribedTopic({}): {}'.format(self.
__topic_name, s))
872 def __init__(self, topic_name, topic_type, debug=False):
874 self.
__mutex = threading.Lock()
879 def __callback(self, data):
886 Get the newest topic data. 888 @param timeout_s float: timeout in seconds or None for no timeout. Default is None (no 889 timeout, return immediately). 891 @return Returns the newest data read on topic if it is available, or None otherwise. 896 if not timeout_s
is None:
897 end_time = rospy.Time.now() + rospy.Duration(timeout_s)
899 while not rospy.is_shutdown():
902 result = copy.copy( self.
__data )
903 if not result
is None or timeout_s
is None or rospy.Time.now() >= end_time:
911 def _getSubsystemDiag(self, subsystem_name, timeout_s=None):
912 data = self._getTopicData(subsystem_name +
"/diag", timeout_s=timeout_s)
915 for v
in data.status[1].values:
916 if v.key ==
"master_component":
917 mcd = subsystem_common.parseMasterComponentDiag(v.value)
923 This class contains subsystem-specific diagnostic information for velma_core_cs. 927 Initialization of diagnostics data using subsystem-independent diagnostics object. 929 @param parent subsystem_common.SubsystemDiag: subsystem-independent diagnostics object. 930 @exception AssertionError Raised when current state name cannot be obtained or state history is not present. 933 assert (len(parent.history) > 0)
952 return 'safe / safe_st / safe_st_ok' 954 return 'transp / transp_st' 960 Get diagnostic information for core VE. 962 @return Returns object of type subsystem_common.SubsystemDiag, with 963 diagnostic information about subsystem. 969 This class contains subsystem-specific diagnostic information for velma_core_cs. 973 Initialization of diagnostics data using subsystem-independent diagnostics object. 975 @param parent subsystem_common.SubsystemDiag: subsystem-independent diagnostics object. 976 @exception AssertionError Raised when current state name cannot be obtained or state history is not present. 978 assert (len(parent.history) > 0)
994 Information about current state. 995 @return True if the subsystem is in 'idle' state, False otherwise. 1001 Information about current state. 1002 @return True if the subsystem is in 'safe' state, False otherwise. 1008 Information about current state. 1009 @return True if the subsystem is in 'cart_imp' state, False otherwise. 1015 Information about current state. 1016 @return True if the subsystem is in 'jnt_imp' state, False otherwise. 1022 Information about current state. 1023 @return True if the subsystem is in 'relax' state, False otherwise. 1029 Information about reason for entering 'safe' state. 1030 @return True if the subsystem entered 'safe' state due to possibility of self-collision, 1032 @exception AssertionError Raised when current state is not 'safe'. 1033 @exception KeyError Raised when 'inSelfCollision' predicate cannot be obtained. 1036 for pv
in self.
history[0].predicates:
1037 if pv.name ==
"inSelfCollision":
1039 raise KeyError(
"Could not obtain 'inSelfCollision' predicate value.")
1043 Information about reason for entering 'safe' state. 1044 @return True if the subsystem entered 'safe' state just after 'idle' state. 1045 @exception AssertionError Raised when current state is not 'safe' or history contain only one entry. 1049 return (self.
history[1].state_name ==
"idle")
1053 Information about state of head and torso motors. 1054 @return True if all motors are homed and ready to use, False otherwise. 1055 @exception KeyError Raised when 'motorsReady' predicate cannot be obtained. 1058 if pv.name ==
"motorsReady":
1060 raise KeyError(
"Could not obtain current 'motorsReady' predicate value.")
1064 Get diagnostic information for core CS. 1066 @return Returns object of type VelmaInterface.CoreCsDiag, with 1067 diagnostic information about control subsystem. 1072 def _getTopicData(self, topic, timeout_s=None):
1077 Allow self-collisions of hands. 1087 Disallow self-collisions of hands. 1097 Gets right F/T sensor raw reading. 1099 @return PyKDL.Wrench: Returns KDL wrench. 1105 Gets left F/T sensor raw reading. 1107 @return PyKDL.Wrench: Returns KDL wrench. 1113 Gets right F/T sensor transformed reading. 1115 @return PyKDL.Wrench: Returns KDL wrench. 1121 Gets left F/T sensor transformed reading. 1123 @return PyKDL.Wrench: Returns KDL wrench. 1129 Gets estimated wrench for the right end effector. 1131 @return PyKDL.Wrench: Returns KDL wrench. 1137 Gets estimated wrench for the left end effector. 1139 @return PyKDL.Wrench: Returns KDL wrench. 1145 Get Polygon that defines wrist collision constraints for joints 5 and 6 of the left arm. 1147 @return list: Returns wrist collision constraint polygon as [x0, y0, x1, y1, x2, y2, ...]. 1153 Get Polygon that defines wrist collision constraints for joints 5 and 6 of the right arm. 1155 @return list: Returns wrist collision constraint polygon as [x0, y0, x1, y1, x2, y2, ...]. 1160 def _action_right_cart_traj_feedback_cb(self, feedback):
1164 def _wrenchKDLtoROS(self, wrKDL):
1165 return geometry_msgs.msg.Wrench(Vector3( wrKDL.force.x(), wrKDL.force.y(), wrKDL.force.z() ), Vector3( wrKDL.torque.x(), wrKDL.torque.y(), wrKDL.torque.z() ))
1168 def _wrenchROStoKDL(self, wrROS):
1169 return PyKDL.Wrench( PyKDL.Vector(wrROS.force.x, wrROS.force.y, wrROS.force.z), PyKDL.Vector(wrROS.torque.x, wrROS.torque.y, wrROS.torque.z) )
1173 Switches the robot to relax behavior. 1175 goal = BehaviorSwitchGoal()
1183 @param motor string: Name of motor to enable: 'hp', 'ht' or 't' 1185 @exception NameError: Parameter motor has invalid value. 1187 if motor !=
'hp' and motor !=
'ht' and motor !=
't':
1188 raise NameError(motor)
1190 goal.action = MotorGoal.ACTION_ENABLE
1195 Start homing procedure for specified motor. 1197 @param motor string: Name of motor to enable: 'hp' or 'ht' 1199 @exception NameError: Parameter motor has invalid value. 1201 if motor !=
'hp' and motor !=
'ht':
1202 raise NameError(motor)
1204 goal.action = MotorGoal.ACTION_START_HOMING
1209 Wait for an action for a motor to complete. 1211 @param motor string: Name of motor to enable: 'hp', 'ht' or 't' 1212 @param timeout_s float: Timeout in seconds. 1214 @return Returns error code or None if timed out. 1216 @exception NameError: Parameter motor has invalid value. 1218 if motor !=
'hp' and motor !=
'ht' and motor !=
't':
1219 raise NameError(motor)
1221 if not self.
__action_map[motor].wait_for_result(timeout=rospy.Duration(timeout_s)):
1225 error_code = result.error_code
1227 if error_code == MotorResult.ERROR_ALREADY_ENABLED:
1228 print "waitForMotor('" + motor +
"'): ERROR_ALREADY_ENABLED (no error)" 1230 elif error_code == MotorResult.ERROR_HOMING_DONE:
1231 print "waitForMotor('" + motor +
"'): ERROR_HOMING_DONE (no error)" 1234 print "waitForMotor('" + motor +
"'): action failed with error_code=" + str(result.error_code)
1239 Enable all motors and wait. 1241 @param timeout_s float: Timeout in seconds. 1259 Start homing procedure for head pan motor. 1261 @see startHomingMotor 1267 Start homing procedure for head tilt motor. 1269 @see startHomingMotor 1276 Wait for head pan motor. 1278 @param timeout_s float: Timeout in seconds. 1286 Wait for head tilt motor. 1288 @param timeout_s float: Timeout in seconds. 1296 Wait for torso motor. 1298 @param timeout_s float: Timeout in seconds. 1306 Calculate movement time for a given destination pose of end effector tool, given maximum 1307 allowed linear and rotational velocities. 1309 @param side string: side: 'left' or 'right'. 1310 @param T_B_T PyKDL.Frame: destination pose. 1311 @param max_vel_lin float: maximum linear velocity. 1312 @param max_vel_rot float: maximum rotational velocity. 1313 @param current_T_B_T PyKDL.Frame: (optional) current pose. If ommited, the current pose 1314 from tf is considered. 1316 @return Returns float: movement time in seconds. 1318 @exception AssertionError Raised when prefix is neither 'left' nor 'right'. 1320 if current_T_B_T
is None:
1322 current_T_B_T = self.
getTf(
'B',
'Tl', time=
None, timeout_s=0.1)
1323 if current_T_B_T
is None:
1324 current_T_B_T = self.
getTf(
'B',
'Wl', time=
None, timeout_s=0.1)
1325 elif side ==
'right':
1326 current_T_B_T = self.
getTf(
'B',
'Tr', time=
None, timeout_s=0.1)
1327 if current_T_B_T
is None:
1328 current_T_B_T = self.
getTf(
'B',
'Wr', time=
None, timeout_s=0.1)
1330 raise Exception(
'Wrong side: "{}"'.format(side))
1331 twist = PyKDL.diff(current_T_B_T, T_B_T, 1.0)
1332 return max( twist.vel.Norm()/max_vel_lin, twist.rot.Norm()/max_vel_rot )
1334 def moveCartImp(self, prefix, pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=0.01, stamp=None, damping=PyKDL.Wrench(PyKDL.Vector(0.35, 0.35, 0.35),PyKDL.Vector(0.35, 0.35, 0.35)), path_tol=
None):
1336 Execute motion in cartesian impedance mode. 1338 @param prefix string: name of end-effector: 'left' or 'right'. 1339 @param pose_list_T_B_Td list of PyKDL.Frame: Poses of end-effector tool wrt. base frame. This is a path for the end-effector. 1340 @param pose_times list of float: Times of the poses in pose_list_T_B_Td wrt. start_time. 1341 @param tool_list_T_W_T list of PyKDL.Frame: Poses of tool frame wrt. wrist frame. This is a path for the tool of end-effector. 1342 @param tool_times list of float: Times of the tool poses in tool_list_T_W_T wrt. start_time. 1343 @param imp_list list of PyKDL.Wrench: Tool impedance values expressed in tool frame. This is a path for the impedance of end-effector. 1344 @param imp_times list of float: Times of the impedance values in imp_list wrt. start_time. 1345 @param max_wrench PyKDL.Wrench: Maximum allowed wrench during the motion expressed in tool frame. 1346 @param start_time float: Relative start time for the movement. 1347 @param stamp rospy.Time: Absolute start time for the movement. If both start_time and stamp arguments are set, only stamp is taken into account. 1348 @param damping PyKDL.Wrench: Damping for the tool expressed in tool frame. 1349 @param path_tol PyKDL.Twist: Maximum allowed error of tool pose expressed in the tool frame. Error of tool pose is a difference between desired tool equilibrium pose and measured tool pose. 1351 @return Returns True. 1353 @exception AssertionError Raised when prefix is neither 'left' nor 'right'. 1356 assert (prefix==
"left" or prefix==
"right")
1357 assert ((pose_list_T_B_Td ==
None and pose_times ==
None)
or len(pose_list_T_B_Td) == len(pose_times))
1358 assert ((tool_list_T_W_T ==
None and tool_times ==
None)
or len(tool_list_T_W_T) == len(tool_times))
1359 assert ((imp_list ==
None and imp_times ==
None)
or len(imp_list) == len(imp_times))
1361 action_trajectory_goal = CartImpGoal()
1363 stamp = rospy.Time.now() + rospy.Duration(start_time)
1365 action_trajectory_goal.pose_trj.header.stamp = stamp
1366 action_trajectory_goal.tool_trj.header.stamp = stamp
1367 action_trajectory_goal.imp_trj.header.stamp = stamp
1369 if pose_list_T_B_Td !=
None:
1370 for i
in range(len(pose_list_T_B_Td)):
1371 wrist_pose = pm.toMsg(pose_list_T_B_Td[i])
1372 action_trajectory_goal.pose_trj.points.append(CartesianTrajectoryPoint(
1373 rospy.Duration(pose_times[i]),
1377 if tool_list_T_W_T !=
None:
1378 for i
in range(len(tool_list_T_W_T)):
1379 tool_pose = pm.toMsg(tool_list_T_W_T[i])
1380 action_trajectory_goal.tool_trj.points.append(CartesianTrajectoryPoint(
1381 rospy.Duration(tool_times[i]),
1385 if imp_list !=
None:
1386 for i
in range(len(imp_list)):
1387 action_trajectory_goal.imp_trj.points.append(CartesianImpedanceTrajectoryPoint(
1388 rospy.Duration(imp_times[i]),
1391 if path_tol !=
None:
1392 action_trajectory_goal.path_tolerance.position = geometry_msgs.msg.Vector3( path_tol.vel.x(), path_tol.vel.y(), path_tol.vel.z() )
1393 action_trajectory_goal.path_tolerance.rotation = geometry_msgs.msg.Vector3( path_tol.rot.x(), path_tol.rot.y(), path_tol.rot.z() )
1394 action_trajectory_goal.goal_tolerance.position = geometry_msgs.msg.Vector3( path_tol.vel.x(), path_tol.vel.y(), path_tol.vel.z() )
1395 action_trajectory_goal.goal_tolerance.rotation = geometry_msgs.msg.Vector3( path_tol.rot.x(), path_tol.rot.y(), path_tol.rot.z() )
1397 action_trajectory_goal.wrench_constraint = self.
_wrenchKDLtoROS(max_wrench)
1398 self.
__action_map[
'cimp_'+prefix].send_goal(action_trajectory_goal)
1402 def moveCartImpRight(self, pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=0.01, stamp=None, damping=PyKDL.Wrench(PyKDL.Vector(0.35, 0.35, 0.35),PyKDL.Vector(0.35, 0.35, 0.35)), path_tol=
None):
1404 Execute motion in cartesian impedance mode for the right end-effector. 1407 return self.
moveCartImp(
"right", pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=start_time, stamp=stamp, damping=damping, path_tol=path_tol)
1409 def moveCartImpLeft(self, pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=0.01, stamp=None, damping=PyKDL.Wrench(PyKDL.Vector(0.35, 0.35, 0.35),PyKDL.Vector(0.35, 0.35, 0.35)), path_tol=
None):
1411 Execute motion in cartesian impedance mode for the left end-effector. 1414 return self.
moveCartImp(
"left", pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=start_time, stamp=stamp, damping=damping, path_tol=path_tol)
1418 Move right end-effector to current position. Switch core_cs to cart_imp mode. 1419 @return Returns True. 1421 return self.
moveCartImp(side,
None,
None,
None,
None,
None,
None, PyKDL.Wrench(PyKDL.Vector(5,5,5), PyKDL.Vector(5,5,5)), start_time=start_time, stamp=stamp)
1425 Move right end-effector to current position. Switch core_cs to cart_imp mode. 1426 @return Returns True. 1432 Move left end-effector to current position. Switch core_cs to cart_imp mode. 1433 @return Returns True. 1439 Wait for completion of end-effector motion in cartesian impedance mode. 1441 @param prefix string: name of end-effector: 'left' or 'right'. 1442 @param timeout_s float: timeout in seconds. 1444 @return Returns error code. 1446 @exception AssertionError Raised when prefix is neither 'left' nor 'right' 1448 assert (prefix==
"left" or prefix==
"right")
1450 if timeout_s ==
None:
1452 if not self.
__action_map[
'cimp_'+prefix].wait_for_result(timeout=rospy.Duration(timeout_s)):
1454 result = self.
__action_map[
'cimp_'+prefix].get_result()
1455 if result.error_code != 0:
1456 error_str =
"UNKNOWN" 1459 print "waitForEffector(" + prefix +
"): action failed with error_code=" + str(result.error_code) +
" (" + error_str +
")" 1463 return result.error_code
1467 Wait for completion of left end-effector motion in cartesian impedance mode. 1468 @param timeout_s float: Timeout in seconds. 1469 @return Returns error code. 1475 Wait for completion of right end-effector motion in cartesian impedance mode. 1476 @param timeout_s float: Timeout in seconds. 1477 @return Returns error code. 1483 def lookAt(self, point, frame_id='torso_base'):
1485 Execute look at motion of head. 1487 @return Returns True 1494 goal.frame_id = frame_id
1495 goal.target = geometry_msgs.msg.Point(point.x(), point.y(), point.z())
1502 Cancel look at motion of head. 1504 @return Returns True. 1512 Check if look at action is connected. 1514 @return True if look at action is connected, False otherwise. 1521 Wait for completion of look at motion. 1523 @param timeout_s float: timeout in seconds. 1525 @return Returns error code. 1531 if timeout_s ==
None:
1533 if not self.
__action_map[
'look_at'].wait_for_result(timeout=rospy.Duration(timeout_s)):
1536 if result.error_code != 0:
1537 error_str =
"UNKNOWN" 1540 print(
'waitForLookAt(): action failed with error_code={} ({})'.format(
1541 result.error_code, error_str))
1543 return result.error_code
1547 Get maximum number of nodes in single joint trajectory. 1548 @return Maximum number of nodes. 1554 Get maximum number of nodes in single head trajectory. 1555 @return Maximum number of nodes. 1562 Get names of all joints in group. 1563 @param group_name string: name of group. 1564 @return Returns list of names of joints in group. 1566 return VelmaInterface._joint_groups[group_name]
1568 def moveJointTrajAndWait(self, traj, start_time=0.2, stamp=None, position_tol=5.0/180.0 * math.pi, velocity_tol=5.0/180.0*math.pi):
1570 Execute joint space trajectory in joint impedance mode. Trajectories of any length are allowed. 1571 This method blocks the executing thread until trajectory is completed, or error occures. 1572 @param traj trajectory_msgs.msg.JointTrajectory: joint trajectory. 1573 @param start_time float: relative start time. 1574 @param stamp rospy.Time: absolute start time. 1575 @position_tol float: position tolerance. 1576 @velocity_tol float: velocity tolerance. 1577 @return Returns True. 1581 for q_idx, joint_name
in enumerate(traj.joint_names):
1582 q_end_traj[joint_name] = traj.points[-1].positions[q_idx]
1585 for traj_idx, traj_part
in enumerate(traj_list):
1586 print(
'Executing trajectory {}...'.format(traj_idx))
1588 position_tol=position_tol, velocity_tol=velocity_tol):
1591 print(
'VelmaInterface.moveJointTraj(): The trajectory could not be completed')
1596 print(
'VelmaInterface.moveJointTraj(): the goal configuration could not be reached')
1601 def moveJointTraj(self, traj, start_time=0.2, stamp=None, position_tol=5.0/180.0 * math.pi, velocity_tol=5.0/180.0*math.pi):
1603 Execute joint space trajectory in joint impedance mode. Trajectories of length up to 50 nodes are allowed. 1604 This method does not block the executing thread. 1605 @param traj trajectory_msgs.msg.JointTrajectory: joint trajectory. 1606 @param start_time float: relative start time. 1607 @param stamp rospy.Time: absolute start time. 1608 @position_tol float: position tolerance. 1609 @velocity_tol float: velocity tolerance. 1610 @return Returns True. 1611 @exception AssertionError Raised when trajectory has too many nodes. 1615 goal = FollowJointTrajectoryGoal()
1621 for node_idx
in range(len(traj.points)):
1626 if joint_name
in traj.joint_names:
1627 q_idx = traj.joint_names.index(joint_name)
1628 q_dest_all.append(traj.points[node_idx].positions[q_idx])
1629 if len(traj.points[node_idx].velocities) > 0:
1630 vel_dest_all.append(traj.points[node_idx].velocities[q_idx])
1632 vel_dest_all.append(0)
1634 q_dest_all.append(js[1][joint_name])
1635 vel_dest_all.append(0)
1636 goal.trajectory.points.append(JointTrajectoryPoint(q_dest_all, vel_dest_all, [], [], traj.points[node_idx].time_from_start))
1638 for joint_name
in goal.trajectory.joint_names:
1639 goal.path_tolerance.append(JointTolerance(joint_name, position_tol, velocity_tol, 0.0))
1641 goal.trajectory.header.stamp = stamp
1643 goal.trajectory.header.stamp = rospy.Time.now() + rospy.Duration(start_time)
1648 if q_map_start
is None:
1652 q_map_prev = q_map_start
1655 traj_out = JointTrajectory()
1656 traj_out.header = traj_in.header
1657 traj_out.joint_names = traj_in.joint_names
1658 time_from_start = 0.0
1659 for pt_idx
in range(0, len(traj_in.points)):
1661 for joint_idx, joint_name
in enumerate(traj_in.joint_names):
1662 q_map[joint_name] = traj_in.points[pt_idx].positions[joint_idx]
1666 point_out = JointTrajectoryPoint()
1667 point_out.positions = traj_in.points[pt_idx].positions
1668 point_out.velocities = traj_in.points[pt_idx].velocities
1669 point_out.time_from_start = rospy.Duration(time_from_start)
1670 traj_out.points.append( point_out )
1679 for joint_name
in q_dest_map_1:
1680 if not joint_name
in q_dest_map_2:
1682 dist = abs(q_dest_map_1[joint_name] - q_dest_map_2[joint_name])
1683 max_dist = max(max_dist, dist)
1684 return max_dist / max_vel
1686 def moveJoint(self, q_dest_map, time, max_vel=None, start_time=0.2, stamp=None, position_tol=5.0/180.0 * math.pi, velocity_tol=5.0/180.0*math.pi):
1688 Execute simple joint space motion in joint impedance mode. 1689 @param q_dest_map dictionary: dictionary {name:position} of goal configuration 1690 @param start_time float: relative start time. 1691 @param stamp rospy.Time: absolute start time. 1692 @position_tol float: position tolerance. 1693 @velocity_tol float: velocity tolerance. 1694 @return Returns True. 1697 assert not max_vel
is None 1699 print(
'moveJoint calculated time: {}'.format(time))
1700 traj = JointTrajectory()
1701 pt = JointTrajectoryPoint()
1702 for name
in q_dest_map:
1703 traj.joint_names.append(name)
1704 pt.positions.append(q_dest_map[name])
1705 pt.velocities.append(0)
1706 pt.time_from_start = rospy.Duration(time)
1707 traj.points.append(pt)
1708 return self.
moveJointTraj(traj, start_time=start_time, stamp=stamp, position_tol=position_tol, velocity_tol=velocity_tol)
1712 Switch core_cs to jnt_imp mode. 1713 @return Returns True. 1715 traj = JointTrajectory()
1716 return self.
moveJointTraj(traj, start_time=start_time, stamp=stamp)
1720 Wait for joint space movement to complete. 1721 @return Returns error code. 1723 if timeout_s ==
None:
1725 if not self.
__action_map[
'jimp'].wait_for_result(timeout=rospy.Duration(timeout_s)):
1728 if result.error_code != 0:
1729 error_str =
"UNKNOWN" 1732 print "waitForJoint(): action failed with error_code=" + str(result.error_code) +
" (" + error_str +
")" 1736 return result.error_code
1738 def moveHeadTraj(self, traj, start_time=0.2, stamp=None, position_tol=5.0/180.0 * math.pi, velocity_tol=5.0/180.0*math.pi):
1740 Execute head trajectory in joint space. 1741 @param traj trajectory_msgs.msg.JointTrajectory: joint trajectory. 1742 @param start_time float: relative start time. 1743 @param stamp rospy.Time: absolute start time. 1744 @position_tol float: position tolerance. 1745 @velocity_tol float: velocity tolerance. 1746 @return Returns True. 1747 @exception AssertionError Raised when trajectory has too many nodes or not all joints are 1748 included in trajectory. 1752 goal = FollowJointTrajectoryGoal()
1753 goal.trajectory.joint_names = [
"head_pan_joint",
"head_tilt_joint"]
1755 for node_idx
in range(len(traj.points)):
1758 for joint_name
in goal.trajectory.joint_names:
1759 assert (joint_name
in traj.joint_names)
1760 q_idx = traj.joint_names.index(joint_name)
1761 q_dest_all.append(traj.points[node_idx].positions[q_idx])
1762 if len(traj.points[node_idx].velocities) > 0:
1763 vel_dest_all.append(traj.points[node_idx].velocities[q_idx])
1765 vel_dest_all.append(0)
1766 goal.trajectory.points.append(JointTrajectoryPoint(q_dest_all, vel_dest_all, [], [], traj.points[node_idx].time_from_start))
1768 for joint_name
in goal.trajectory.joint_names:
1769 goal.path_tolerance.append(JointTolerance(joint_name, position_tol, velocity_tol, 0))
1771 goal.trajectory.header.stamp = stamp
1773 goal.trajectory.header.stamp = rospy.Time.now() + rospy.Duration(start_time)
1778 def __getHeadMovementTime(self, q_dest, max_vel):
1780 dist1 = abs(q_dest[0] - js[
"head_pan_joint"])
1781 dist2 = abs(q_dest[1] - js[
"head_tilt_joint"])
1782 max_dist = max(dist1, dist2)
1783 return max_dist / max_vel
1785 def moveHead(self, q_dest, time, max_vel=None, start_time=0.2, stamp=None, position_tol=5.0/180.0 * math.pi, velocity_tol=5.0/180.0*math.pi):
1787 Execute simple head motion in joint space. 1788 @param q_dest 2-tuple: goal configuration of head ('head_pan_joint', 'head_tilt_joint') 1789 @param start_time float: relative start time. 1790 @param stamp rospy.Time: absolute start time. 1791 @position_tol float: position tolerance. 1792 @velocity_tol float: velocity tolerance. 1793 @return Returns True. 1794 @exception AssertionError When q_dest has wrong length. 1796 assert (len(q_dest) == 2)
1799 assert not max_vel
is None 1801 print(
'moveHead calculated time: {}'.format(time))
1803 traj = JointTrajectory()
1804 traj.joint_names = [
"head_pan_joint",
"head_tilt_joint"]
1805 pt = JointTrajectoryPoint()
1806 pt.positions = q_dest
1807 pt.velocities = [0.0, 0.0]
1808 pt.time_from_start = rospy.Duration(time)
1809 traj.points.append(pt)
1810 return self.
moveHeadTraj(traj, start_time=start_time, stamp=stamp, position_tol=position_tol, velocity_tol=velocity_tol)
1814 Wait for head movement to complete. 1815 @return Returns error code. 1817 if timeout_s ==
None:
1820 if not self.
__action_map[
'head'].wait_for_result(timeout=rospy.Duration(timeout_s)):
1823 if result.error_code != 0:
1824 print "waitForHead(): action failed with error_code=" + str(result.error_code)
1828 return result.error_code
1830 def moveHand(self, prefix, q, v, t, maxPressure, hold=False):
1832 Executes hand motion with trapezoidal velocity profile. 1834 @param prefix string: name of hand, either 'left' or 'right' 1835 @param q 4-tuple of float: desired configuration for hand DOFs: 1836 [FingerOneKnuckleTwo, FingerTwoKnuckleTwo, FingerThreeKnuckleTwo, Spread] 1837 @param v 4-tuple of float: maximum velocities 1838 @param t 4-tuple of float: maximum current in motors 1839 @param maxPressure float: maximum pressure for tactile sensors 1840 @param hold bool: True if spread joint should hold its position after completion of motion 1841 @exception AssertionError when prefix is neither 'left' nor 'right' 1843 assert (prefix ==
'left' or prefix ==
'right')
1844 action_goal = BHMoveGoal()
1845 action_goal.name = [prefix+
"_HandFingerOneKnuckleTwoJoint", prefix+
"_HandFingerTwoKnuckleTwoJoint",
1846 prefix+
"_HandFingerThreeKnuckleTwoJoint", prefix+
"_HandFingerOneKnuckleOneJoint"]
1850 action_goal.maxPressure = maxPressure
1851 action_goal.reset =
False 1852 action_goal.hold = 1
if hold
else 0
1853 self.
__action_map[
'hand_'+prefix].send_goal(action_goal)
1857 Executes motion with trapezoidal velocity profile for left hand. 1860 self.
moveHand(
"left", q, v, t, maxPressure, hold=hold)
1864 Executes motion with trapezoidal velocity profile for right hand. 1867 self.
moveHand(
"right", q, v, t, maxPressure, hold=hold)
1871 Executes reset command for hand. 1872 @param prefix string: name of hand, either 'left' or 'right' 1873 @exception AssertionError when prefix is neither 'left' nor 'right' 1875 assert (prefix ==
'left' or prefix ==
'right')
1876 action_goal = BHMoveGoal()
1877 action_goal.reset =
True 1878 self.
__action_map[
'hand_'+prefix].send_goal(action_goal)
1882 Executes reset command for left hand. 1889 Executes reset command for right hand. 1896 Wait for completion of hand movement. 1897 @param prefix string: name of hand, either 'left' or 'right' 1898 @exception AssertionError when prefix is neither 'left' nor 'right' 1900 assert (prefix ==
'left' or prefix ==
'right')
1902 if timeout_s ==
None:
1905 if not self.
__action_map[
'hand_'+prefix].wait_for_result(timeout=rospy.Duration(timeout_s)):
1908 result = self.
__action_map[
'hand_'+prefix].get_result()
1909 if result.error_code != 0:
1910 print "waitForHand(" + prefix +
"): action failed with error_code=" + str(result.error_code) +
" (" + self.
_moveHand_action_error_codes_names[result.error_code] +
")" 1911 return result.error_code
1915 Wait for completion of left hand movement. 1922 Wait for completion of right hand movement. 1927 def _getKDLtf(self, base_frame, frame, time=None, timeout_s=1.0):
1929 Lookup tf transform and convert it to PyKDL.Frame. 1930 @param base_frame string: name of base frame 1931 @param frame string: name of target frame 1932 @param time rospy.Time: time at which transform should be interpolated 1933 @param timeout_s float: timeout in seconds 1934 @return PyKDL.Frame transformation from base frame to target frame. 1935 @exception tf2_ros.TransformException when the transform for the specified time 1936 is not avaible during the timeout_s. 1939 time = rospy.Time.now()
1941 self.
_listener.waitForTransform(base_frame, frame, time, rospy.Duration(timeout_s))
1942 pose = self.
_listener.lookupTransform(base_frame, frame, time)
1943 except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException,
1944 tf2_ros.TransformException):
1946 return pm.fromTf(pose)
1950 Lookup transformations for all links. 1952 @param base_frame string: name of base frame 1953 @param time rospy.Time: time at which transform should be interpolated 1954 @param timeout_s float: timeout in seconds 1955 @return dictionary {string:PyKDL.Frame} Returns dictionary that maps link names 1956 to their poses wrt. the base frame. 1957 @exception tf2_ros.TransformException when the transform for the specified time 1958 is not avaible during the timeout_s. 1961 time = rospy.Time.now()
1965 result[l.name] = self.
_getKDLtf(base_frame, l.name, time, timeout_s)
1967 result[l.name] =
None 1970 def getTf(self, frame_from, frame_to, time=None, timeout_s=1.0):
1972 Lookup tf transform and convert it to PyKDL.Frame. Frame names can be the full names 1973 or the following simplified names can be used: 1974 - 'Wo' - world frame ('world') 1975 - 'B' - robot base frame ('torso_base') 1976 - 'Wr' - right wrist ('right_arm_7_link') 1977 - 'Wl' - left wrist ('left_arm_7_link') 1978 - 'Er' - same as 'Wr' 1979 - 'El' - same as 'Wl' 1980 - 'Gr' - right grip frame ('right_HandGripLink') 1981 - 'Gl' - left grip frame ('left_HandGripLink') 1982 - 'Pr' - right palm frame ('right_HandPalmLink') 1983 - 'Pl' - left palm frame ('left_HandPalmLink') 1984 - 'Tr' - right tool frame ('right_arm_tool') 1985 - 'Tl' - left tool frame ('left_arm_tool') 1986 - 'Fr00' - 'right_HandFingerOneKnuckleOneLink' 1987 - 'Fr01' - 'right_HandFingerOneKnuckleTwoLink' 1988 - 'Fr02' - 'right_HandFingerOneKnuckleThreeLink' 1989 - 'Fr10' - 'right_HandFingerTwoKnuckleOneLink' 1990 - 'Fr11' - 'right_HandFingerTwoKnuckleTwoLink' 1991 - 'Fr12' - 'right_HandFingerTwoKnuckleThreeLink' 1992 - 'Fr21' - 'right_HandFingerThreeKnuckleTwoLink' 1993 - 'Fr22' - 'right_HandFingerThreeKnuckleThreeLink' 1994 - 'Fl00' - 'left_HandFingerOneKnuckleOneLink' 1995 - 'Fl01' - 'left_HandFingerOneKnuckleTwoLink' 1996 - 'Fl02' - 'left_HandFingerOneKnuckleThreeLink' 1997 - 'Fl10' - 'left_HandFingerTwoKnuckleOneLink' 1998 - 'Fl11' - 'left_HandFingerTwoKnuckleTwoLink' 1999 - 'Fl12' - 'left_HandFingerTwoKnuckleThreeLink' 2000 - 'Fl21' - 'left_HandFingerThreeKnuckleTwoLink' 2001 - 'Fl22' - 'left_HandFingerThreeKnuckleThreeLink' 2003 @param frame_from string: simplified name of base frame 2004 @param frame_to string: simplified name of target frame 2005 @param time rospy.Time: time at which transform should be interpolated 2006 @param timeout_s float: timeout in seconds 2007 @return PyKDL.Frame transformation from base frame to target frame. 2008 @exception tf2_ros.TransformException when the transform for the specified time 2009 is not avaible during the timeout_s. 2012 time = rospy.Time.now()
2013 if frame_from
in self.
_frames:
2014 frame_from_name = self.
_frames[frame_from]
2016 frame_from_name = frame_from
2019 frame_to_name = self.
_frames[frame_to]
2021 frame_to_name = frame_to
2023 return self.
_getKDLtf( frame_from_name, frame_to_name, time, timeout_s )
2027 Inform control system about grasped object. 2029 @param side string: Hand name, can be one of two values ('left' or 'right'). 2030 @param status bool: True when object is grasped and gravity compensation is active, False 2033 @exception NameError: If side is not 'left' or 'right'. 2035 if side !=
'left' and side !=
'right':
2036 raise NameError(
'wrong side name: ' + str(side))
2038 goal = GraspedGoal()
2040 goal.action = GraspedGoal.ACTION_OBJECT_GRASPED
2041 elif status ==
False:
2042 goal.action = GraspedGoal.ACTION_NOTHING_GRASPED
2046 print "Manipulator:", side,
"--> object_grasped_flag_status:", status
2048 self.
__action_map[
'grasped_'+side].wait_for_result(timeout=rospy.Duration(0))
2049 result = self.
__action_map[
'grasped_'+side].get_result()
2050 error_code = result.error_code
2052 print "setGraspedFlag: action failed (error)" 2056 Make measurement for gravity compensation. This identification action requires four 2057 measurements: two before and two after object is grasped. 2059 @param side string: Hand name, can be one of two values ('left' or 'right'). 2060 @param command_index int: measurement index - one of the following values: 1 - the first 2061 measurement before the object is grasped, 2 - the second measurement before the object 2062 is grasped, 3 - the first measurement after the object is grasped (in the same pose 2063 as for measurement 1), 4 - the second measurement after the object is grasped (in the same 2064 pose as for measurement 2). 2066 @exception NameError: If side is not 'left' or 'right'. 2068 if side !=
'left' and side !=
'right':
2069 raise NameError(
'wrong side name: ' + str(side))
2071 goal = IdentificationGoal()
2072 if command_index == 1:
2073 goal.action = IdentificationGoal.ACTION_FIRST_MEASUREMENT_BEFORE_OBJECT_IS_GRASPED
2074 elif command_index == 2:
2075 goal.action = IdentificationGoal.ACTION_SECOND_MEASUREMENT_BEFORE_OBJECT_IS_GRASPED
2076 elif command_index == 3:
2077 goal.action = IdentificationGoal.ACTION_FIRST_MEASUREMENT_AFTER_OBJECT_IS_GRASPED
2078 elif command_index == 4:
2079 goal.action = IdentificationGoal.ACTION_SECOND_MEASUREMENT_AFTER_OBJECT_IS_GRASPED
2081 self.
__action_map[
'identification_'+side].send_goal(goal)
2083 print "Manipulator:", side,
"--> identification_command:", command_index
2085 self.
__action_map[
'identification_'+side].wait_for_result(timeout=rospy.Duration(0))
2086 result = self.
__action_map[
'identification_'+side].get_result()
2087 error_code = result.error_code
2089 print "sendIdentificationMeasurementCommand: action failed (error)" def waitForHead(self, timeout_s=None)
Wait for head movement to complete.
def startHomingHT(self)
Start homing procedure for head tilt motor.
def moveCartImpRightCurrentPos(self, start_time=0.2, stamp=None)
Move right end-effector to current position.
def enableMotor(self, motor)
Enable motor.
dictionary _cartesian_trajectory_result_names
def moveCartImpLeft(self, pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=0.01, stamp=None, damping=PyKDL.Wrench(PyKDL.Vector(0.35, 0.35, 0.35), PyKDL.Vector(0.35, 0.35, 0.35)), path_tol=None)
Execute motion in cartesian impedance mode for the left end-effector.
def __init__(self, parent)
Initialization of diagnostics data using subsystem-independent diagnostics object.
def getTf(self, frame_from, frame_to, time=None, timeout_s=1.0)
Lookup tf transform and convert it to PyKDL.Frame.
def __getDiagInfo(self, timeout_s)
def waitForJoint(self, timeout_s=None)
Wait for joint space movement to complete.
def resetHandLeft(self)
Executes reset command for left hand.
def waitForHandRight(self)
Wait for completion of right hand movement.
def inStateSafe(self)
Information about current state.
def waitForInit(self, timeout_s=None)
Wait for the interface until it is initialized.
def __isInitialized(self)
def waitForEffectorRight(self, timeout_s=None)
Wait for completion of right end-effector motion in cartesian impedance mode.
def moveHand(self, prefix, q, v, t, maxPressure, hold=False)
Executes hand motion with trapezoidal velocity profile.
def getCartImpMvTime(self, side, T_B_T, max_vel_lin, max_vel_rot, current_T_B_T=None)
Calculate movement time for a given destination pose of end effector tool, given maximum allowed line...
def _jointStatesCallback(self, data)
dictionary _look_at_result_names
def moveCartImpCurrentPos(self, side, start_time=0.2, stamp=None)
Move right end-effector to current position.
def isLookAtConnected(self)
Check if look at action is connected.
def isConfigurationClose(q_map1, q_map2, tolerance=0.1, allow_subset=False)
Check if two configurations of robot body are close within tolerance.
def moveHandLeft(self, q, v, t, maxPressure, hold=False)
Executes motion with trapezoidal velocity profile for left hand.
def inStateIdle(self)
Information about current state.
def waitForT(self, timeout_s=0)
Wait for torso motor.
def __init__(self, parent)
Initialization of diagnostics data using subsystem-independent diagnostics object.
def waitForEffectorLeft(self, timeout_s=None)
Wait for completion of left end-effector motion in cartesian impedance mode.
def getBodyJointLimits(self)
Gets limits of joints of both arms and torso.
def moveCartImp(self, prefix, pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=0.01, stamp=None, damping=PyKDL.Wrench(PyKDL.Vector(0.35, 0.35, 0.35), PyKDL.Vector(0.35, 0.35, 0.35)), path_tol=None)
Execute motion in cartesian impedance mode.
def startHomingMotor(self, motor)
Start homing procedure for specified motor.
def waitForLookAt(self, timeout_s=None)
Wait for completion of look at motion.
def maxJointTrajLen(self)
Get maximum number of nodes in single joint trajectory.
def isHeadConfigurationClose(q1, q2, tolerance=0.1)
Check if two configurations of robot neck are close within tolerance.
dictionary _joint_trajectory_result_names
def allowHandsCollisions(self)
Allow self-collisions of hands.
def getCoreCsDiag(self, timeout_s=None)
Get diagnostic information for core CS.
def getRightWccPolygon(self)
Get Polygon that defines wrist collision constraints for joints 5 and 6 of the right arm...
def lookAt(self, point, frame_id='torso_base')
Execute look at motion of head.
def moveCartImpRight(self, pose_list_T_B_Td, pose_times, tool_list_T_W_T, tool_times, imp_list, imp_times, max_wrench, start_time=0.01, stamp=None, damping=PyKDL.Wrench(PyKDL.Vector(0.35, 0.35, 0.35), PyKDL.Vector(0.35, 0.35, 0.35)), path_tol=None)
Execute motion in cartesian impedance mode for the right end-effector.
def getCurrentStateName(self)
def waitForHand(self, prefix, timeout_s=None)
Wait for completion of hand movement.
def motorsReady(self)
Information about state of head and torso motors.
def getWristWrenchl(self)
Gets estimated wrench for the left end effector.
def getAllLinksTf(self, base_frame, time=None, timeout_s=1.0)
Lookup transformations for all links.
def moveJoint(self, q_dest_map, time, max_vel=None, start_time=0.2, stamp=None, position_tol=5.0/180.0 *math.pi, velocity_tol=5.0/180.0 *math.pi)
Execute simple joint space motion in joint impedance mode.
def inStateRelax(self)
Information about current state.
def moveJointTraj(self, traj, start_time=0.2, stamp=None, position_tol=5.0/180.0 *math.pi, velocity_tol=5.0/180.0 *math.pi)
Execute joint space trajectory in joint impedance mode.
def waitForHP(self, timeout_s=0)
Wait for head pan motor.
def cancelLookAt(self)
Cancel look at motion of head.
def getHandCurrentConfiguration(self, prefix)
Get current configuration of a specified hand.
def isHandConfigurationClose(current_q, dest_q, tolerance=0.1)
Check if two configurations of robot hand are close within tolerance.
_action_right_cart_traj_feedback
def getCurrentStateName(self)
def _wrenchROStoKDL(self, wrROS)
def moveJointTrajAndWait(self, traj, start_time=0.2, stamp=None, position_tol=5.0/180.0 *math.pi, velocity_tol=5.0/180.0 *math.pi)
Execute joint space trajectory in joint impedance mode.
def getJntImpMovementTime(self, q_dest_map, max_vel)
def getHandRightCurrentConfiguration(self)
Get current configuration of right hand.
def waitForEffector(self, prefix, timeout_s=None)
Wait for completion of end-effector motion in cartesian impedance mode.
ROS-based, Python interface class for WUT Velma Robot.
Class used for subscription for various ROS topics from the VelmaInterface class. ...
def moveHandRight(self, q, v, t, maxPressure, hold=False)
Executes motion with trapezoidal velocity profile for right hand.
def getJointStateAtTime(self, time)
Get interpolated joint state at a given time.
def moveHead(self, q_dest, time, max_vel=None, start_time=0.2, stamp=None, position_tol=5.0/180.0 *math.pi, velocity_tol=5.0/180.0 *math.pi)
Execute simple head motion in joint space.
def getData(self, timeout_s=None)
Get the newest topic data.
def __callback(self, data)
def getSymmetricalJointName(joint_name)
For joint names that refer to joints that are symmetrical (left or right), get the name of the anothe...
def __getHeadMovementTime(self, q_dest, max_vel)
def getHeadJointLimits(self)
Gets limits of joints of neck.
def resetHand(self, prefix)
Executes reset command for hand.
def getHeadCurrentConfiguration(self)
Get current configuration of neck.
def switchToRelaxBehavior(self)
Switches the robot to relax behavior.
def inStateJntImp(self)
Information about current state.
def sendIdentificationMeasurementCommand(self, side, command_index)
Make measurement for gravity compensation.
def _getKDLtf(self, base_frame, frame, time=None, timeout_s=1.0)
Lookup tf transform and convert it to PyKDL.Frame.
def getTransformedFTr(self)
Gets right F/T sensor transformed reading.
__action_is_connected_lock
def waitForMotor(self, motor, timeout_s=0)
Wait for an action for a motor to complete.
def moveCartImpLeftCurrentPos(self, start_time=0.2, stamp=None)
Move left end-effector to current position.
def moveHeadTraj(self, traj, start_time=0.2, stamp=None, position_tol=5.0/180.0 *math.pi, velocity_tol=5.0/180.0 *math.pi)
Execute head trajectory in joint space.
def waitForJointState(self, abs_time)
Wait for reception of joint state ROS msg with time stamp greater or equal abs_time.
def __connectAction(self, action_name, action, timeout_s)
def getJointGroup(group_name)
Get names of all joints in group.
def __init__(self, topic_name, topic_type, debug=False)
def getCartImpJointLimits(self)
Gets limits of joints of both arms and torso in cart_imp mode.
dictionary _moveHand_action_error_codes_names
def inStateCartImp(self)
Information about current state.
def setGraspedFlag(self, side, status)
Inform control system about grasped object.
This class contains information about geometric object: mesh.
def resetHandRight(self)
Executes reset command for right hand.
def startHomingHP(self)
Start homing procedure for head pan motor.
def getWristWrenchr(self)
Gets estimated wrench for the right end effector.
This class contains information about single link of robot.
def isSafeReasonIdle(self)
Information about reason for entering 'safe' state.
def getLastJointState(self)
Get the newest joint state.
def getCurrentStateModeName(self)
def __isActionConnected(self, action_name)
def moveJointImpToCurrentPos(self, start_time=0.2, stamp=None)
Switch core_cs to jnt_imp mode.
def enableMotors(self, timeout=0)
Enable all motors and wait.
def calculateJointTrajTime(self, q_map_start, traj_in, max_vel)
def __init__(self, debug=False)
Initialization of the interface.
def getRawFTr(self)
Gets right F/T sensor raw reading.
This class contains subsystem-specific diagnostic information for velma_core_cs.
def maxHeadTrajLen(self)
Get maximum number of nodes in single head trajectory.
def _getSubsystemDiag(self, subsystem_name, timeout_s=None)
def waitForHT(self, timeout_s=0)
Wait for head tilt motor.
def waitForHandLeft(self)
Wait for completion of left hand movement.
def getRawFTl(self)
Gets left F/T sensor raw reading.
def getTransformedFTl(self)
Gets left F/T sensor transformed reading.
def disallowHandsCollisions(self)
Disallow self-collisions of hands.
def getHandLeftCurrentConfiguration(self)
Get current configuration of left hand.
This class contains subsystem-specific diagnostic information for velma_core_cs.
def _wrenchKDLtoROS(self, wrKDL)
def getCoreVeDiag(self, timeout_s=None)
Get diagnostic information for core VE.
def isSafeReasonSelfCol(self)
Information about reason for entering 'safe' state.
def symmetricalConfiguration(q_map)
Get configuration based on the input configuration such that all joint positions are symmetrical...
def getLeftWccPolygon(self)
Get Polygon that defines wrist collision constraints for joints 5 and 6 of the left arm...
def __tryGetRosParams(self)
def splitTrajectory(joint_trajectory, max_traj_len)
Split a long trajectory into a number of shorter trajectories.
def getJntImpMovementTime2(self, q_dest_map_1, q_dest_map_2, max_vel)
def _getTopicData(self, topic, timeout_s=None)