00001
00002
00003 import rospy
00004 from geometry_msgs.msg import WrenchStamped, PoseStamped
00005 import message_filters
00006 import tf
00007 import numpy
00008 from tf.transformations import *
00009 import diagnostic_updater
00010 from diagnostic_msgs.msg import DiagnosticStatus
00011
00012 g_contact_state = None
00013
00014 def offsetPose(offset):
00015 pose = PoseStamped()
00016 pose.pose.position.x = offset[0]
00017 pose.pose.position.y = offset[1]
00018 pose.pose.position.z = offset[2]
00019 pose.pose.orientation.x = offset[3]
00020 pose.pose.orientation.y = offset[4]
00021 pose.pose.orientation.z = offset[5]
00022 pose.pose.orientation.w = offset[6]
00023 return pose
00024
00025 def publishMidCoords(stamp):
00026 l_pose = computeEndCoords("left", stamp)
00027 r_pose = computeEndCoords("right", stamp)
00028
00029 l_pos = numpy.array((l_pose.pose.position.x,
00030 l_pose.pose.position.y,
00031 l_pose.pose.position.z))
00032 r_pos = numpy.array((r_pose.pose.position.x,
00033 r_pose.pose.position.y,
00034 r_pose.pose.position.z))
00035 l_rot = numpy.array((l_pose.pose.orientation.x,
00036 l_pose.pose.orientation.y,
00037 l_pose.pose.orientation.z,
00038 l_pose.pose.orientation.w))
00039 r_rot = numpy.array((r_pose.pose.orientation.x,
00040 r_pose.pose.orientation.y,
00041 r_pose.pose.orientation.z,
00042 r_pose.pose.orientation.w))
00043 mid_pos = (l_pos + r_pos) / 2.0
00044 mid_rot = quaternion_slerp(l_rot, r_rot, 0.5)
00045 br = tf.TransformBroadcaster()
00046 br.sendTransform(mid_pos, mid_rot,
00047 stamp,
00048 ground_frame,
00049 parent_frame)
00050
00051 def computeEndCoords(leg, stamp):
00052 if leg == "left":
00053 foot_frame_id = lfoot_frame
00054 foot_offset_pose = offsetPose(lfoot_offset)
00055 elif leg == "right":
00056 foot_frame_id = rfoot_frame
00057 foot_offset_pose = offsetPose(rfoot_offset)
00058 else:
00059 raise Exception("unknown leg specified")
00060 foot_offset_pose.header.frame_id = foot_frame_id
00061 foot_offset_pose.header.stamp = stamp
00062 tf_listener.waitForTransform(parent_frame, foot_offset_pose.header.frame_id,
00063 foot_offset_pose.header.stamp,
00064 rospy.Duration(1.0))
00065 pose_stamped = tf_listener.transformPose(parent_frame, foot_offset_pose)
00066 return pose_stamped
00067
00068 def publishSingleCoords(leg, stamp):
00069 pose_stamped = computeEndCoords(leg, stamp)
00070 br = tf.TransformBroadcaster()
00071 br.sendTransform((pose_stamped.pose.position.x,
00072 pose_stamped.pose.position.y,
00073 pose_stamped.pose.position.z),
00074 (pose_stamped.pose.orientation.x,
00075 pose_stamped.pose.orientation.y,
00076 pose_stamped.pose.orientation.z,
00077 pose_stamped.pose.orientation.w),
00078 pose_stamped.header.stamp,
00079 ground_frame,
00080 pose_stamped.header.frame_id)
00081
00082 def callback(lfoot_force_msg, rfoot_force_msg):
00083 global force_thr, g_contact_state
00084 if lfoot_force_msg.wrench.force.z > force_thr:
00085 lfoot_contact = True
00086 else:
00087 lfoot_contact = False
00088 if rfoot_force_msg.wrench.force.z > force_thr:
00089 rfoot_contact = True
00090 else:
00091 rfoot_contact = False
00092 try:
00093 if lfoot_contact and rfoot_contact:
00094 g_contact_state = "both"
00095 publishMidCoords(lfoot_force_msg.header.stamp)
00096 elif lfoot_contact:
00097 g_contact_state = "lleg"
00098 publishSingleCoords("left", lfoot_force_msg.header.stamp)
00099 elif rfoot_contact:
00100 g_contact_state = "rleg"
00101 publishSingleCoords("right", rfoot_force_msg.header.stamp)
00102 else:
00103 g_contact_state = "air"
00104 publishMidCoords(lfoot_force_msg.header.stamp)
00105 updater.update()
00106 except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
00107 rospy.logerr("tf error, ignored")
00108
00109
00110 def contactStateDiagnostic(stats):
00111 if g_contact_state == "both":
00112 stats.summary(DiagnosticStatus.OK,
00113 "BOTH legs on the floor")
00114 elif g_contact_state == "lleg":
00115 stats.summary(DiagnosticStatus.OK,
00116 "LEFT leg on the floor")
00117 elif g_contact_state == "rleg":
00118 stats.summary(DiagnosticStatus.OK,
00119 "RIGHT leg on the floor")
00120 elif g_contact_state == "air":
00121 stats.summary(DiagnosticStatus.WARN,
00122 "robot on the AIR")
00123 else:
00124 stats.summary(DiagnosticStatus.ERROR,
00125 "failed to estimate contact state")
00126 stats.add("contact state", g_contact_state)
00127
00128 if __name__ == "__main__":
00129 rospy.init_node("foot_contact_monitor")
00130 tf_listener = tf.TransformListener()
00131 updater = diagnostic_updater.Updater()
00132 updater.setHardwareID(rospy.get_name())
00133 updater.add('ContactState', contactStateDiagnostic)
00134 force_thr = rospy.get_param('~force_thr', 100)
00135 ground_frame = rospy.get_param('~ground_frame', 'ground')
00136 parent_frame = rospy.get_param('~parent_frame', 'BODY')
00137 lfoot_frame = rospy.get_param('~lfoot_frame_id')
00138 rfoot_frame = rospy.get_param('~rfoot_frame_id')
00139 lfoot_offset = rospy.get_param('~lfoot_endcoords_offset')
00140 rfoot_offset = rospy.get_param('~rfoot_endcoords_offset')
00141 ground_parent_frame = rospy.get_param('')
00142 lfoot_sub = message_filters.Subscriber('/off_lfsensor', WrenchStamped)
00143 rfoot_sub = message_filters.Subscriber('/off_rfsensor', WrenchStamped)
00144 ts = message_filters.TimeSynchronizer([lfoot_sub, rfoot_sub], 100)
00145 ts.registerCallback(callback)
00146 rospy.spin()
00147