00001
00002
00003 """
00004 listen to /move_base/TrajectoryPlannerROS/local_plan
00005 use rotate and movedistance commands to get there, repeat
00006 subscribe to odo so moves relative to current pos
00007 assumes robot is stopped before running this
00008
00009 rosmsg show nav_msgs/Path
00010 rosmsg show nav_msgs/Odometry
00011 rosmsg show geometry_msgs/PoseStamped << is in map frame!!!
00012
00013 consider polling telnet and broadcasting odom from here, to only update odom between moves
00014 /move_base/status 3 = goal reached, 1= accepted (read last in list)
00015 rosmsg show actionlib_msgs/GoalStatusArray
00016
00017 adding initial pose to goal pose:
00018 1st test, initial poseth -90deg: solution would be just ot add initial pose to goal pose
00019 gth = gth + ith
00020 180 = 180 + (-90)
00021 if dth > math.pi:
00022 dth = -math.pi*2 + dth
00023 elif dth < -math.pi:
00024 dth = math.pi*2 + dth
00025 ^^ works but not if odom gets whacked - need to use odom/map tf and ADD to goal pose diff
00026 """
00027
00028 import rospy, tf
00029 import oculusprimesocket
00030 from nav_msgs.msg import Odometry
00031 import math
00032 from nav_msgs.msg import Path
00033 from geometry_msgs.msg import PoseStamped
00034 from actionlib_msgs.msg import GoalStatusArray
00035
00036 listentime = 1.5
00037 nextmove = 0
00038 odomx = 0
00039 odomy = 0
00040 odomth = 0
00041 targetx = 0
00042 targety = 0
00043 targetth = 0
00044 followpath = False
00045 goalth = 0
00046 minturn = math.radians(6)
00047 lastpath = 0
00048 goalpose = False
00049 goalseek = False
00050 linearspeed = 150
00051 secondspermeter = 3.2
00052 turnspeed = 100
00053 secondspertwopi = 3.8
00054 initth = 0
00055
00056 tfth = 0
00057
00058 def pathCallback(data):
00059 global targetx, targety, targetth, followpath, lastpath, goalpose
00060 lastpath = rospy.get_time()
00061 goalpose = False
00062 followpath = True
00063 p = data.poses[len(data.poses)-1]
00064 targetx = p.pose.position.x
00065 targety = p.pose.position.y
00066 quaternion = ( p.pose.orientation.x, p.pose.orientation.y,
00067 p.pose.orientation.z, p.pose.orientation.w )
00068 targetth = tf.transformations.euler_from_quaternion(quaternion)[2]
00069
00070 def odomCallback(data):
00071 global odomx, odomy, odomth
00072 odomx = data.pose.pose.position.x
00073 odomy = data.pose.pose.position.y
00074 quaternion = ( data.pose.pose.orientation.x, data.pose.pose.orientation.y,
00075 data.pose.pose.orientation.z, data.pose.pose.orientation.w )
00076 odomth = tf.transformations.euler_from_quaternion(quaternion)[2]
00077
00078 def goalCallback(data):
00079 global goalth, followpath, lastpath, goalpose, odomx, odomy, odomth, targetx, targety, targetth
00080 goalpose = False
00081 followpath = True
00082 lastpath = 0
00083 targetx = odomx
00084 targety = odomy
00085
00086 if goalpose:
00087 targetth = goalth
00088 else:
00089 targetth = odomth
00090
00091
00092
00093
00094
00095
00096 quaternion = ( data.pose.orientation.x, data.pose.orientation.y,
00097 data.pose.orientation.z, data.pose.orientation.w )
00098 goalth = tf.transformations.euler_from_quaternion(quaternion)[2]
00099
00100
00101
00102
00103
00104
00105 def goalStatusCallback(data):
00106 global goalseek
00107 goalseek = False
00108 if len(data.status_list) == 0:
00109 return
00110 status = data.status_list[len(data.status_list)-1]
00111 if status.status == 1:
00112 goalseek = True
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 def move(ox, oy, oth, tx, ty, tth, gth):
00132 global followpath, goalpose, tfth
00133
00134
00135
00136
00137 distance = 0
00138 if followpath:
00139 dx = tx - ox
00140 dy = ty - oy
00141 distance = math.sqrt( pow(dx,2) + pow(dy,2) )
00142
00143 if distance > 0:
00144 th = math.acos(dx/distance)
00145 if dy <0:
00146 th = -th
00147 elif goalpose:
00148 th = gth - tfth
00149 else:
00150 th = tth
00151
00152
00153
00154
00155
00156 dth = th - oth
00157 if dth > math.pi:
00158 dth = -math.pi*2 + dth
00159 elif dth < -math.pi:
00160 dth = math.pi*2 + dth
00161
00162
00163 if distance > 0 and distance < 0.05:
00164 distance = 0.05
00165
00166
00167 if dth < minturn*0.3 and dth > -minturn*0.3:
00168 dth = 0
00169 elif dth >= minturn*0.3 and dth < minturn:
00170 dth = minturn
00171 elif dth <= -minturn*0.3 and dth > -minturn:
00172 dth = -minturn
00173
00174
00175 if dth > 0:
00176 oculusprimesocket.sendString("speed "+str(turnspeed) )
00177 oculusprimesocket.sendString("move left")
00178 rospy.sleep(dth/(2.0*math.pi) * secondspertwopi)
00179 oculusprimesocket.sendString("move stop")
00180 oculusprimesocket.waitForReplySearch("<state> direction stop")
00181 elif dth < 0:
00182 oculusprimesocket.sendString("speed "+str(turnspeed) )
00183 oculusprimesocket.sendString("move right")
00184 rospy.sleep(-dth/(2.0*math.pi) * secondspertwopi)
00185 oculusprimesocket.sendString("move stop")
00186 oculusprimesocket.waitForReplySearch("<state> direction stop")
00187
00188 if distance > 0:
00189 oculusprimesocket.sendString("speed "+str(linearspeed) )
00190 oculusprimesocket.sendString("move forward")
00191 rospy.sleep(distance*secondspermeter)
00192 oculusprimesocket.sendString("move stop")
00193 oculusprimesocket.waitForReplySearch("<state> direction stop")
00194
00195 def cleanup():
00196 oculusprimesocket.sendString("odometrystop")
00197 oculusprimesocket.sendString("state stopbetweenmoves false")
00198 oculusprimesocket.sendString("move stop")
00199
00200
00201
00202
00203 rospy.init_node('base_controller', anonymous=False)
00204 rospy.Subscriber("move_base/TrajectoryPlannerROS/local_plan", Path, pathCallback)
00205 rospy.Subscriber("odom", Odometry, odomCallback)
00206 rospy.Subscriber("move_base_simple/goal", PoseStamped, goalCallback)
00207 rospy.Subscriber("move_base/status", GoalStatusArray, goalStatusCallback)
00208
00209
00210 rospy.on_shutdown(cleanup)
00211 listener = tf.TransformListener()
00212
00213 while not rospy.is_shutdown():
00214 t = rospy.get_time()
00215
00216 if t >= nextmove and goalseek:
00217 move(odomx, odomy, odomth, targetx, targety, targetth, goalth)
00218 nextmove = t + listentime
00219
00220 followpath = False
00221
00222 if t - lastpath > 3:
00223 goalpose = True
00224
00225 try:
00226 (trans,rot) = listener.lookupTransform('/map', '/odom', rospy.Time(0))
00227 except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
00228 continue
00229 quaternion = (rot[0], rot[1], rot[2], rot[3])
00230 tfth = tf.transformations.euler_from_quaternion(quaternion)[2]
00231
00232 cleanup()