Go to the documentation of this file.00001
00002
00003 import roslib; roslib.load_manifest('thymio_navigation_driver')
00004 import rospy
00005 from asebaros.msg import AsebaAnonymousEvent
00006 from asebaros.msg import AsebaEvent
00007 from asebaros.srv import LoadScripts
00008 from asebaros.srv import GetNodeList
00009 from geometry_msgs.msg import Quaternion
00010 from geometry_msgs.msg import Twist
00011 from nav_msgs.msg import Odometry
00012 from tf.broadcaster import TransformBroadcaster
00013 from math import sin,cos,atan2
00014 import time
00015
00016 BASE_WIDTH = 95
00017 MAX_SPEED = 500
00018 SPEED_COEF = 2.93
00019
00020 class ThymioDriver():
00021
00022 def __init__(self):
00023 rospy.init_node('thymio')
00024
00025 self.x = 0
00026 self.y = 0
00027 self.th = 0
00028 self.then = rospy.Time.now()
00029 self.odom = Odometry(header=rospy.Header(frame_id='odom'),child_frame_id='base_link')
00030
00031
00032 rospy.wait_for_service('/aseba/load_script')
00033 load_script = rospy.ServiceProxy('/aseba/load_script',LoadScripts)
00034 script_filename = roslib.packages.get_pkg_dir('thymio_navigation_driver') + '/aseba/thymio_ros.aesl'
00035 load_script(script_filename)
00036
00037
00038 rospy.Subscriber("cmd_vel", Twist, self.on_cmd_vel)
00039 rospy.Subscriber('/aseba/events/odometry', AsebaEvent, self.on_aseba_odometry_event)
00040 self.aseba_pub = rospy.Publisher('/aseba/events/set_speed', AsebaEvent)
00041 self.odom_pub = rospy.Publisher('odom',Odometry)
00042 self.odom_broadcaster = TransformBroadcaster()
00043
00044
00045 def set_speed(self,values):
00046 self.aseba_pub.publish(AsebaEvent(rospy.get_rostime(),0,values))
00047
00048
00049 def shutdown(self):
00050 self.set_speed([0,0])
00051
00052
00053 def on_aseba_odometry_event(self,data):
00054 now = data.stamp
00055 dt = (now-self.then).to_sec()
00056 self.then = now
00057 dsl = (data.data[0]*dt)/SPEED_COEF
00058 dsr = (data.data[1]*dt)/SPEED_COEF
00059 ds = ((dsl+dsr)/2.0)/1000.0
00060 dth = atan2(dsr-dsl,BASE_WIDTH)
00061
00062 self.x += ds*cos(self.th+dth/2.0)
00063 self.y += ds*sin(self.th+dth/2.0)
00064 self.th+= dth
00065
00066
00067 quaternion = Quaternion()
00068 quaternion.z = sin(self.th/2.0)
00069 quaternion.w = cos(self.th/2.0)
00070
00071
00072 self.odom.header.stamp = rospy.Time.now()
00073 self.odom.pose.pose.position.x = self.x
00074 self.odom.pose.pose.position.y = self.y
00075 self.odom.pose.pose.position.z = 0
00076 self.odom.pose.pose.orientation = quaternion
00077 self.odom.twist.twist.linear.x = ds/dt
00078 self.odom.twist.twist.angular.z = dth/dt
00079
00080
00081 self.odom_broadcaster.sendTransform((self.x,self.y,0),(quaternion.x,quaternion.y,quaternion.z,quaternion.w),self.then,"base_link","odom")
00082 self.odom_pub.publish(self.odom)
00083
00084
00085 def on_cmd_vel(self,data):
00086 x = data.linear.x * 1000.0
00087 x = x * SPEED_COEF
00088 th = data.angular.z * (BASE_WIDTH/2)
00089 th = th * SPEED_COEF
00090 k = max(abs(x-th),abs(x+th))
00091
00092 if k > MAX_SPEED:
00093 x = x*MAX_SPEED/k; th = th*MAX_SPEED/k
00094 self.set_speed([int(x-th),int(x+th)])
00095
00096
00097 def control_loop(self):
00098 rospy.on_shutdown(self.shutdown)
00099 while not rospy.is_shutdown():
00100 rospy.spin()
00101
00102 def main():
00103 try:
00104 robot = ThymioDriver()
00105 robot.control_loop()
00106 except rospy.ROSInterruptException:
00107 pass
00108
00109 if __name__ == '__main__':
00110 main()
00111