00001
00002
00003 import rospy
00004 import tf
00005 import numpy
00006 import scipy.stats
00007 import math
00008 from geometry_msgs.msg import PoseWithCovariance, TwistWithCovariance, Twist, Pose, Point, Quaternion, Vector3
00009
00010
00011 def transform_local_twist_to_global(pose, local_twist):
00012 trans = [pose.position.x, pose.position.y, pose.position.z]
00013 rot = [pose.orientation.x, pose.orientation.y,
00014 pose.orientation.z, pose.orientation.w]
00015 rotation_matrix = tf.transformations.quaternion_matrix(rot)[:3, :3]
00016 global_velocity = numpy.dot(rotation_matrix, numpy.array([[local_twist.linear.x],
00017 [local_twist.linear.y],
00018 [local_twist.linear.z]]))
00019 global_omega = numpy.dot(rotation_matrix, numpy.array([[local_twist.angular.x],
00020 [local_twist.angular.y],
00021 [local_twist.angular.z]]))
00022 return Twist(Vector3(*global_velocity[:, 0]), Vector3(*global_omega[:, 0]))
00023
00024 def transform_local_twist_covariance_to_global(pose, local_twist_with_covariance):
00025 trans = [pose.position.x, pose.position.y, pose.position.z]
00026 rot = [pose.orientation.x, pose.orientation.y,
00027 pose.orientation.z, pose.orientation.w]
00028 rotation_matrix = tf.transformations.quaternion_matrix(rot)[:3, :3]
00029 twist_cov_matrix = numpy.matrix(local_twist_with_covariance).reshape(6, 6)
00030 global_twist_cov_matrix = numpy.zeros((6, 6))
00031 global_twist_cov_matrix[:3, :3] = (rotation_matrix.T).dot(twist_cov_matrix[:3, :3].dot(rotation_matrix))
00032 global_twist_cov_matrix[3:6, 3:6] = (rotation_matrix.T).dot(twist_cov_matrix[3:6, 3:6].dot(rotation_matrix))
00033 return global_twist_cov_matrix.reshape(-1,).tolist()
00034
00035
00036 def update_pose(pose, global_twist, dt):
00037 ret_pose = Pose()
00038
00039 ret_pose.position.x = pose.position.x + global_twist.linear.x * dt
00040 ret_pose.position.y = pose.position.y + global_twist.linear.y * dt
00041 ret_pose.position.z = pose.position.z + global_twist.linear.z * dt
00042 ret_pose.orientation = update_quaternion(pose.orientation, global_twist.angular, dt)
00043 return ret_pose
00044
00045 def update_quaternion(orientation, angular, dt):
00046
00047 quat_vec = numpy.array([[orientation.x],
00048 [orientation.y],
00049 [orientation.z],
00050 [orientation.w]])
00051 skew_omega = numpy.matrix([[0, -angular.z, angular.y, angular.x],
00052 [angular.z, 0, -angular.x, angular.y],
00053 [-angular.y, angular.x, 0, angular.z],
00054 [-angular.x, -angular.y, -angular.z, 0]])
00055 new_quat_vec = quat_vec + 0.5 * numpy.dot(skew_omega, quat_vec) * dt
00056 norm = numpy.linalg.norm(new_quat_vec)
00057 if norm == 0:
00058 rospy.logwarn("norm of quaternion is zero")
00059 else:
00060 new_quat_vec = new_quat_vec / norm
00061 return Quaternion(*numpy.array(new_quat_vec).reshape(-1,).tolist())
00062
00063
00064 def update_twist_covariance(twist, v_sigma, min_sigma = 1e-3):
00065 twist_list = [twist.twist.linear.x, twist.twist.linear.y, twist.twist.linear.z, twist.twist.angular.x, twist.twist.angular.y, twist.twist.angular.z]
00066 if all([abs(x) < 1e-6 for x in twist_list]):
00067 current_sigma = [min_sigma] * 6
00068 else:
00069 current_sigma = v_sigma
00070 return numpy.diag([max(x ** 2, min_sigma ** 2) for x in current_sigma]).reshape(-1,).tolist()
00071
00072 def update_pose_covariance(pose_cov, global_twist_cov, dt):
00073 ret_pose_cov = []
00074
00075 prev_pose_cov_matrix = numpy.matrix(pose_cov).reshape(6, 6)
00076 global_twist_cov_matrix = numpy.matrix(global_twist_cov).reshape(6, 6)
00077
00078
00079 jacobi_pose = numpy.diag([1.0] * 6)
00080 jacobi_twist = numpy.diag([dt] * 6)
00081
00082 pose_cov_matrix = jacobi_pose.dot(prev_pose_cov_matrix.dot(jacobi_pose.T)) + jacobi_twist.dot(global_twist_cov_matrix.dot(jacobi_twist.T))
00083
00084 ret_pose_cov = numpy.array(pose_cov_matrix).reshape(-1,).tolist()
00085 return ret_pose_cov
00086
00087
00088 def broadcast_transform(broadcast, odom, invert_tf):
00089 if not odom or not broadcast:
00090 return
00091 position = [odom.pose.pose.position.x, odom.pose.pose.position.y, odom.pose.pose.position.z]
00092 orientation = [odom.pose.pose.orientation.x, odom.pose.pose.orientation.y, odom.pose.pose.orientation.z, odom.pose.pose.orientation.w]
00093 if invert_tf:
00094 homogeneous_matrix = make_homogeneous_matrix(position, orientation)
00095 homogeneous_matrix_inv = numpy.linalg.inv(homogeneous_matrix)
00096 position = list(homogeneous_matrix_inv[:3, 3])
00097 orientation = list(tf.transformations.quaternion_from_matrix(homogeneous_matrix_inv))
00098 parent_frame = odom.child_frame_id
00099 target_frame = odom.header.frame_id
00100 else:
00101 parent_frame = odom.header.frame_id
00102 target_frame = odom.child_frame_id
00103 broadcast.sendTransform(position, orientation, odom.header.stamp, target_frame, parent_frame)
00104
00105
00106 def make_homogeneous_matrix(trans, rot):
00107 homogeneous_matrix = tf.transformations.quaternion_matrix(rot)
00108 homogeneous_matrix[:3, 3] = numpy.array(trans).reshape(1, 3)
00109 return homogeneous_matrix
00110
00111
00112
00113
00114 def norm_pdf_multivariate(x, mean, cov_inv):
00115 size = len(x)
00116 if size == len(mean) and (size, size) == cov_inv.shape:
00117 inv_det = numpy.linalg.det(cov_inv)
00118 if not inv_det > 0:
00119 rospy.logwarn("Determinant of inverse cov matrix {0} is equal or smaller than zero".format(inv_det))
00120 return 0.0
00121 norm_const = math.pow((2 * numpy.pi), float(size) / 2) * math.pow(1 / inv_det, 1.0 / 2)
00122 if not norm_const > 0 :
00123 rospy.logwarn("Norm const {0} is equal or smaller than zero".format(norm_const))
00124 return 0.0
00125 x_mean = numpy.matrix(x - mean)
00126 exponent = -0.5 * (x_mean * cov_inv * x_mean.T)
00127 if exponent > 0:
00128 rospy.logwarn("Exponent {0} is larger than zero".format(exponent))
00129 exponent = 0
00130 result = math.pow(math.e, exponent)
00131 return result / norm_const
00132 else:
00133 rospy.logwarn("The dimensions of the input don't match")
00134 return 0.0
00135
00136
00137
00138
00139 def transform_quaternion_to_euler(quat, prev_euler = None):
00140
00141 sin_half_pitch = quat[3] * quat[1] - quat[2] * quat[0]
00142 if abs(sin_half_pitch) > 0.499:
00143
00144 ret_euler = list(tf.transformations.euler_from_quaternion(quat))
00145 else:
00146
00147 zero_thre = numpy.finfo(float).eps * 4.0
00148 roll_numerator = 2 * (quat[3] * quat[0] + quat[1] * quat[2])
00149 if abs(roll_numerator) < zero_thre:
00150 roll_numerator = numpy.sign(roll_numerator) * 0.0
00151 yaw_numerator = 2 * (quat[3] * quat[2] + quat[0] * quat[1])
00152 if abs(yaw_numerator) < zero_thre:
00153 yaw_numerator = numpy.sign(yaw_numerator) * 0.0
00154 ret_euler = [numpy.arctan2(roll_numerator, 1 - 2 * (quat[0] ** 2 + quat[1] ** 2)),
00155 numpy.arcsin(2 * sin_half_pitch),
00156 numpy.arctan2(yaw_numerator, 1 - 2 * (quat[1] ** 2 + quat[2] ** 2))]
00157
00158
00159 if prev_euler != None:
00160
00161 for i in range(3):
00162 while abs(prev_euler[i] - ret_euler[i]) > numpy.pi:
00163 ret_euler[i] += numpy.sign(prev_euler[i] - ret_euler[i]) * 2 * numpy.pi
00164 return ret_euler