10 from geometry_msgs.msg
import Twist, TransformStamped, Pose
11 from nav_msgs.msg
import Odometry
12 from std_srvs.srv
import Trigger, TriggerRequest, TriggerResponse
30 rospy.Subscriber(
"/base/twist_controller/command", Twist, self.
twist_callback, queue_size=1)
31 self.
pub_odom = rospy.Publisher(
"/base/odometry_controller/odometry", Odometry, queue_size=1)
32 rospy.Service(
"/base/odometry_controller/reset_odometry", Trigger, self.
reset_odometry)
42 self.
odom.child_frame_id =
"base_footprint"
43 self.
odom.pose.pose.orientation.w = 1
45 rospy.Timer(rospy.Duration(0.1), self.
timer_cb)
47 rospy.loginfo(
"Emulation for base running")
50 self.
odom.pose.pose = Pose()
51 self.
odom.pose.pose.orientation.w = 1
53 return TriggerResponse(
True,
"odometry resetted")
67 if time_since_last_twist < rospy.Duration(0.1):
68 new_pose = copy.deepcopy(self.
odom.pose.pose)
69 yaw = tf.transformations.euler_from_quaternion([self.
odom.pose.pose.orientation.x, self.
odom.pose.pose.orientation.y, self.
odom.pose.pose.orientation.z, self.
odom.pose.pose.orientation.w])[2] + self.
twist.angular.z * dt.to_sec()
70 quat = tf.transformations.quaternion_from_euler(0, 0, yaw)
71 new_pose.orientation.x = quat[0]
72 new_pose.orientation.y = quat[1]
73 new_pose.orientation.z = quat[2]
74 new_pose.orientation.w = quat[3]
75 new_pose.position.x += self.
twist.linear.x * dt.to_sec() * math.cos(yaw) - self.
twist.linear.y * dt.to_sec() * math.sin(yaw)
76 new_pose.position.y += self.
twist.linear.x * dt.to_sec() * math.sin(yaw) + self.
twist.linear.y * dt.to_sec() * math.cos(yaw)
77 self.
odom.pose.pose = new_pose
80 self.
odom.twist.twist.linear.x = self.
twist.linear.x
81 self.
odom.twist.twist.linear.y = self.
twist.linear.y
82 self.
odom.twist.twist.angular.z = self.
twist.angular.z
85 self.
odom.twist.twist = Twist()
88 odom = copy.deepcopy(self.
odom)
89 odom.header.stamp = rospy.Time.now()
94 t_odom = TransformStamped()
95 t_odom.header.stamp = rospy.Time.now()
97 t_odom.child_frame_id =
"base_footprint"
98 t_odom.transform.translation = self.
odom.pose.pose.position
99 t_odom.transform.rotation = self.
odom.pose.pose.orientation
101 transforms = [t_odom]
103 self.
br.sendTransform(transforms)
105 if __name__ ==
'__main__':
106 rospy.init_node(
'emulation_base')
107 parser = argparse.ArgumentParser(conflict_handler=
'resolve',
108 description=
"Tool for emulating base by publishing odometry and propagating base_footprint.")
109 parser.add_argument(
'-o',
'--odom_frame', help=
'odom frame name (default: \'odom_combined\')', default=
'odom_combined')
110 args, unknown = parser.parse_known_args()