Go to the documentation of this file.00001 import re
00002 from threading import Thread
00003 from nav_msgs.msg import Odometry
00004 import rospy
00005 import rostopic
00006 from BAL.Header.Requests.PublishRequest import PublishRequest
00007 from BAL.Header.Requests.closeDiffRequest import CloseDiffRequest
00008 from BAL.Header.Requests.closeDiffSetOdomRequest import CloseDiffSetOdomRequest
00009 from BAL.Header.Response.ParamBuildResponse import DiffDriverCL
00010
00011 __author__ = 'tom1231'
00012 from BAL.Interfaces.Device import Device
00013 from rospy import Subscriber, Service, Publisher
00014 from ric_board.srv._set_odom import set_odom, set_odomResponse
00015 from tf import TransformBroadcaster
00016 from tf.transformations import euler_from_quaternion
00017 from geometry_msgs.msg import Twist, TransformStamped, Quaternion
00018 import math
00019
00020
00021 class RiCDiffCloseLoop(Device):
00022 def __init__(self, param, output):
00023 Device.__init__(self, param.getCloseDiffName(), output)
00024 self._baseLink = param.getCloseDiffBaseLink()
00025 self._odom = param.getCloseDiffOdom()
00026 self._maxAng = param.getCloseDiffMaxAng()
00027 self._maxLin = param.getCloseDiffMaxLin()
00028 self._pub = Publisher("%s/odometry" % self._name, Odometry, queue_size=param.getCloseDiffPubHz())
00029 self._broadCase = TransformBroadcaster()
00030 Subscriber('%s/command' % self._name, Twist, self.diffServiceCallback, queue_size=1)
00031 Service('%s/setOdometry' % self._name, set_odom, self.setOdom)
00032 self._haveRightToPublish = False
00033 self._prevOdom = None
00034 self._firstTimePub = True
00035
00036 def getType(self):
00037 return DiffDriverCL
00038
00039 def diffServiceCallback(self, msg):
00040 Thread(target=self.sendMsg, args=(msg,)).start()
00041
00042 def sendMsg(self, msg):
00043 if msg.angular.z > self._maxAng:
00044 msg.angular.z = self._maxAng
00045 elif msg.angular.z < -self._maxAng:
00046 msg.angular.z = -self._maxAng
00047
00048 if msg.linear.x > self._maxLin:
00049 msg.linear.x = self._maxLin
00050 elif msg.linear.x < -self._maxLin:
00051 msg.linear.x = -self._maxLin
00052
00053 self._output.write(CloseDiffRequest(msg.angular.z, msg.linear.x).dataTosend())
00054
00055 def setOdom(self, req):
00056 self._output.write(CloseDiffSetOdomRequest(req.x, req.y, req.theta).dataTosend())
00057 return set_odomResponse(True)
00058
00059 def publish(self, data):
00060 q = Quaternion()
00061 q.x = 0
00062 q.y = 0
00063 q.z = data[6]
00064 q.w = data[7]
00065 odomMsg = Odometry()
00066 odomMsg.header.frame_id = self._odom
00067 odomMsg.header.stamp = rospy.get_rostime()
00068 odomMsg.child_frame_id = self._baseLink
00069 odomMsg.pose.pose.position.x = data[0]
00070 odomMsg.pose.pose.position.y = data[1]
00071 odomMsg.pose.pose.position.z = 0
00072 odomMsg.pose.pose.orientation = q
00073 if self._firstTimePub:
00074 self._prevOdom = odomMsg
00075 self._firstTimePub = False
00076 return
00077
00078 velocity = Twist()
00079
00080 deltaTime = odomMsg.header.stamp.to_sec() - self._prevOdom.header.stamp.to_sec()
00081 yaw, pitch, roll = euler_from_quaternion(
00082 [odomMsg.pose.pose.orientation.w, odomMsg.pose.pose.orientation.x, odomMsg.pose.pose.orientation.y,
00083 odomMsg.pose.pose.orientation.z])
00084 prevYaw, prevPitch, prevRollprevYaw = euler_from_quaternion(
00085 [self._prevOdom.pose.pose.orientation.w, self._prevOdom.pose.pose.orientation.x,
00086 self._prevOdom.pose.pose.orientation.y, self._prevOdom.pose.pose.orientation.z])
00087 if deltaTime > 0:
00088 velocity.linear.x = (data[8] / deltaTime)
00089
00090 deltaYaw = yaw - prevYaw
00091
00092
00093
00094 if deltaYaw > math.pi: deltaYaw -= 2 * math.pi
00095 elif deltaYaw < -math.pi: deltaYaw += 2 * math.pi
00096
00097 if deltaTime > 0:
00098 velocity.angular.z = -(deltaYaw / deltaTime)
00099
00100
00101
00102 odomMsg.twist.twist = velocity
00103
00104 self._prevOdom = odomMsg
00105
00106 traMsg = TransformStamped()
00107 traMsg.header.frame_id = self._odom
00108 traMsg.header.stamp = rospy.get_rostime()
00109 traMsg.child_frame_id = self._baseLink
00110 traMsg.transform.translation.x = data[0]
00111 traMsg.transform.translation.y = data[1]
00112 traMsg.transform.translation.z = 0
00113 traMsg.transform.rotation = q
00114
00115 self._pub.publish(odomMsg)
00116 self._broadCase.sendTransformMessage(traMsg)
00117
00118 def checkForSubscribers(self):
00119 try:
00120 subCheck = re.search('Subscribers:.*', rostopic.get_info_text(self._pub.name)).group(0).split(': ')[1]
00121 subTfCheck = re.search('Subscribers:.*', rostopic.get_info_text('/tf')).group(0).split(': ')[1]
00122
00123 if not self._haveRightToPublish and (subCheck == '' or subTfCheck == ''):
00124 self._output.write(PublishRequest(DiffDriverCL, 0, True).dataTosend())
00125 self._haveRightToPublish = True
00126
00127 elif self._haveRightToPublish and (subCheck == 'None' and subTfCheck == 'None'):
00128 self._output.write(PublishRequest(DiffDriverCL, 0, False).dataTosend())
00129 self._haveRightToPublish = False
00130 self._firstTimePub = True
00131 except:
00132 pass