Go to the documentation of this file.00001
00002 import roslib; roslib.load_manifest('pacman_controller')
00003 import rospy
00004 import commands
00005 import string
00006 import sys
00007 import math
00008 import actionlib
00009 import random
00010 from collvoid_local_planner.srv import InitGuess
00011 from std_msgs.msg import String
00012 from geometry_msgs.msg import PoseWithCovarianceStamped,PoseStamped
00013 from socket import gethostname
00014 from collvoid_msgs.msg import PoseTwistWithCovariance
00015 from move_base_msgs.msg import *
00016
00017 import tf
00018
00019 from pacman_controller import game_engine as GE
00020
00021
00022 class ControllerGhosts():
00023
00024 def __init__(self):
00025 self.initialize()
00026
00027
00028 def initialize(self):
00029 self.move_base_client = actionlib.SimpleActionClient('move_base', MoveBaseAction)
00030 self.move_base_client.wait_for_server()
00031 self.init_guess_srv = rospy.ServiceProxy("init_guess_pub", InitGuess)
00032
00033
00034
00035 self.ghostname = rospy.get_param("~ghostname")
00036 self.home = rospy.get_param("/%s/home"%self.ghostname)
00037
00038
00039 rospy.loginfo("Ghost: %s home %d",self.ghostname, self.home)
00040 self.gameEngine = GE.GameEngine()
00041 self.state = GE.State.STOPPED
00042 self.dead = False
00043 self.headingToWp = False
00044 self.current_wp = None
00045 self.old_wp = self.gameEngine.points[self.home]
00046 self.sleepTime = rospy.get_param('/%s/sleep_time'%self.ghostname)
00047
00048
00049 self.sub_state = rospy.Subscriber("/state", String, self.cb_state)
00050 self.sub_commands_robot = rospy.Subscriber("/commands_robot", String, self.cb_commands_robot)
00051
00052
00053 def update(self):
00054 if not self.gameEngine.initialized or not self.ghostname in self.gameEngine.ghosts or self.state == GE.State.SETUP:
00055 return
00056 me = self.gameEngine.ghosts[self.ghostname]
00057
00058 if self.state == GE.State.RUNNING and self.startTime + self.sleepTime > rospy.get_time():
00059 return
00060
00061
00062 if (self.state == GE.State.STOPPED or self.state == GE.State.PAUSED):
00063 self.move_base_client.cancel_all_goals()
00064 self.current_wp = None
00065 self.headingToWp = False
00066
00067 return
00068
00069 if (self.state in [GE.State.INIT, GE.State.GAME_OVER] or self.dead):
00070 new_wp,end = self.return_home();
00071 self.headingToWp = False
00072 elif (self.state == GE.State.FLEEING):
00073 if GE.dist(self.gameEngine.pacman, me) < self.gameEngine.pacman['radius'] + me['radius'] + 1.5*GE.THRESHOLD:
00074 self.dead = True
00075 new_wp,end = self.return_home();
00076 self.headingToWp = False
00077 else:
00078 new_wp,end = self.newBehavior()
00079
00080 elif self.headingToWp and GE.dist(me, self.gameEngine.points[self.current_wp]) < me['radius'] + GE.THRESHOLD:
00081 self.headingToWp = False
00082 return
00083 elif self.headingToWp:
00084 return
00085 else:
00086 new_wp,end = self.newBehavior()
00087
00088 if not (new_wp == self.current_wp):
00089 self.current_wp = new_wp
00090 self.move_base_client.cancel_all_goals()
00091 self.send_goal(self.current_wp)
00092 else:
00093 nearestWP = self.gameEngine.findClosestWP(me)
00094 if self.state in [GE.State.RUNNING, GE.State.FLEEING] and nearestWP == self.current_wp and self.current_wp == end and GE.dist(me, self.gameEngine.points[self.current_wp]) < me['radius']:
00095 self.headingToWp = True
00096
00097 pm_wp = self.gameEngine.findClosestWP(self.gameEngine.pacman)
00098 if (end == pm_wp):
00099 pm_mp = self.gameEngine.findClosestMapPoint(self.gameEngine.pacman)
00100 if pm_mp['neighbors'][0] == pm_wp:
00101 self.current_wp = pm_mp['neighbors'][1]
00102 else:
00103 self.current_wp = pm_mp['neighbors'][0]
00104
00105 else:
00106 while self.current_wp == end:
00107 print self.ghostname + str(self.current_wp)
00108 self.current_wp = random.choice(self.gameEngine.points[nearestWP]['neighbors'])
00109
00110 self.move_base_client.cancel_all_goals()
00111 self.send_goal(self.current_wp)
00112
00113 def newBehavior(self):
00114 if (self.ghostname == "ghost_red"):
00115 return self.chase_pacman()
00116 if (self.ghostname == "ghost_pink"):
00117 return self.move_random(1.0)
00118 if (self.ghostname == "ghost_blue"):
00119 return self.move_random(0.2)
00120
00121 def send_goal(self,wp):
00122 goal = MoveBaseGoal()
00123 goal.target_pose.pose.position.x = self.gameEngine.points[wp]["x"]
00124 goal.target_pose.pose.position.y = self.gameEngine.points[wp]["y"]
00125
00126 goal.target_pose.pose.orientation.x = 0
00127 goal.target_pose.pose.orientation.y = 0
00128 goal.target_pose.pose.orientation.z = 0
00129 goal.target_pose.pose.orientation.w = 1.0
00130
00131
00132 goal.target_pose.header.frame_id = "/map"
00133
00134 self.move_base_client.send_goal(goal)
00135 return
00136
00137 def cb_state(self,msg):
00138 if self.state == GE.State.INIT and int(msg.data) == GE.State.RUNNING:
00139 self.startTime = rospy.get_time()
00140 if not self.state == GE.State.SETUP and int(msg.data) == GE.State.SETUP:
00141 self.move_base_client.cancel_all_goals()
00142
00143 self.state = int(msg.data)
00144
00145
00146 def flee(self):
00147 my_position = self.gameEngine.ghosts[self.ghostname]
00148 pm_position = self.gameEngine.pacman
00149
00150 my_wp = self.gameEngine.findClosestMapPoint(my_position)
00151 pm_wp = self.gameEngine.findClosestWP(pm_position)
00152 path = self.gameEngine.find_shortest_path(my_wp, pm_wp)
00153
00154 if not (my_wp['neighbors'][0] == path[1]['id']):
00155 return my_wp['neighbors'][0]
00156 else:
00157 return my_wp['neighbors'][1]
00158
00159
00160 def move_random(self, percent):
00161 me = self.gameEngine.ghosts[self.ghostname]
00162
00163 if GE.dist(me, self.old_wp) < me['radius'] + GE.THRESHOLD:
00164 if random.random() <= percent and not self.old_wp['id'] == self.home:
00165 self.old_wp = random.choice(self.gameEngine.points)
00166 else:
00167 self.old_wp = self.gameEngine.points[self.gameEngine.findClosestWP(self.gameEngine.pacman)]
00168
00169 my_wp = self.gameEngine.findClosestMapPoint(me)
00170 path = self.gameEngine.find_shortest_path(my_wp, self.old_wp)
00171
00172
00173 if len(path) == 1:
00174 return path[0]['id'], path[len(path)-1]['id']
00175
00176 index = 1
00177
00178 while index < len(path)-1 and GE.dist(path[index], me) < me['radius'] + GE.THRESHOLD :
00179 index += 1;
00180
00181 while index < len(path)-1 and GE.dist(path[index], self.gameEngine.ghosts[self.ghostname]) < 2 * self.gameEngine.ghosts[self.ghostname]['radius'] + 2.0 * GE.THRESHOLD and self.gameEngine.positionBlocked(path[index], self.gameEngine.ghosts[self.ghostname]):
00182 index +=1;
00183
00184
00185 return path[index]['id'], path[len(path)-1]['id']
00186
00187
00188 def chase_pacman(self):
00189 my_position = self.gameEngine.ghosts[self.ghostname]
00190 pm_position = self.gameEngine.pacman
00191
00192 my_wp = self.gameEngine.findClosestMapPoint(my_position)
00193 pm_wp = self.gameEngine.findClosestWP(pm_position)
00194 path = self.gameEngine.find_shortest_path(my_wp, self.gameEngine.points[pm_wp])
00195
00196 if len(path) == 1:
00197 return path[0]['id'], path[len(path)-1]['id']
00198
00199 index = 1
00200
00201 while index < len(path)-1 and GE.dist(path[index], self.gameEngine.ghosts[self.ghostname]) < self.gameEngine.ghosts[self.ghostname]['radius'] + GE.THRESHOLD :
00202 index += 1;
00203
00204
00205 return path[index]['id'], path[len(path)-1]['id']
00206
00207
00208 def return_home(self):
00209 if GE.dist(self.gameEngine.points[self.home], self.gameEngine.ghosts[self.ghostname]) < self.gameEngine.ghosts[self.ghostname]['radius'] + GE.THRESHOLD:
00210 self.dead = False
00211 my_position = self.gameEngine.ghosts[self.ghostname]
00212 my_wp = self.gameEngine.findClosestMapPoint(my_position)
00213
00214 path = self.gameEngine.find_shortest_path(my_wp,self.gameEngine.points[self.home])
00215
00216 if len(path) == 1:
00217 return path[0]['id'], path[len(path)-1]['id']
00218
00219 index = 1
00220 while index < len(path)-1 and GE.dist(path[index], self.gameEngine.ghosts[self.ghostname]) < self.gameEngine.ghosts[self.ghostname]['radius'] + 1.5 * GE.THRESHOLD :
00221 index += 1;
00222
00223 while index < len(path)-1 and GE.dist(path[index], self.gameEngine.ghosts[self.ghostname]) < 2 * self.gameEngine.ghosts[self.ghostname]['radius'] + 2.0 * GE.THRESHOLD and self.gameEngine.positionBlocked(path[index], self.gameEngine.ghosts[self.ghostname]):
00224 index +=1;
00225
00226 return path[index]['id'], path[len(path)-1]['id']
00227
00228
00229 def cb_commands_robot(self,msg):
00230 if (msg.data == "init Guess"):
00231 self.init_guess_srv(0.1)
00232
00233 if __name__ == '__main__':
00234
00235
00236
00237
00238
00239 rospy.init_node('controller_ghosts')
00240 controller_ghosts = ControllerGhosts()
00241 r = rospy.Rate(10)
00242 while not rospy.is_shutdown():
00243 controller_ghosts.update()
00244 r.sleep()
00245
00246
00247