game_engine.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import roslib; roslib.load_manifest('pacman_controller')
00004 from visualization_msgs.msg import Marker
00005 from visualization_msgs.msg import MarkerArray
00006 from geometry_msgs.msg import PoseStamped,Point
00007 from std_msgs.msg import String
00008 from collvoid_msgs.msg import PoseTwistWithCovariance
00009 
00010 import commands
00011 
00012 import rospy
00013 import math
00014 
00015 THRESHOLD = 0.20
00016 
00017 EAT_POINTS = 10
00018 EAT_SPECIAL = 50
00019 EAT_CHERRY = 100
00020 EAT_GHOST = 200
00021 
00022 TIME_FLEEING = 20.0
00023 
00024 def dist(a, b):
00025     return math.sqrt(math.pow(a['x'] - b['x'], 2) + math.pow(a['y'] - b['y'], 2))
00026 
00027 class State():
00028     SETUP = -1
00029     INIT = 0
00030     RUNNING = 1
00031     FLEEING = 2
00032     PAUSED = 3
00033     GAME_OVER = 4
00034     STOPPED = 5
00035     WON = 6
00036 
00037 class GameEngine():
00038     def __init__(self):
00039         
00040         self.points = []
00041         self.edges = []
00042         self.initialized = False
00043         self.pacman = {}
00044         self.ghosts = {}
00045 
00046         self.scoreLoc = rospy.get_param('/score_loc')
00047         self.infoLoc = rospy.get_param('/info_loc')
00048         self.power_ups = rospy.get_param('/power_ups')
00049 
00050         self.readMap()
00051 
00052         
00053         self.state = State.STOPPED
00054 
00055         self.score = 0;
00056         self.sendStart = False
00057 
00058         topic = 'pacman_map'
00059         
00060         self.pubMap = rospy.Publisher(topic, MarkerArray)
00061         self.subCommandsRobot= rospy.Subscriber("/commands_robot", String, self.commandsRobotCallback)
00062         self.subCommonPositions = rospy.Subscriber("/position_share", PoseTwistWithCovariance, self.positionShareCallback)
00063 
00064         self.pubPositions = rospy.Publisher('/game_positions', MarkerArray)
00065         
00066         self.pubScore = rospy.Publisher('/score', Marker)
00067 
00068         self.pubInfo = rospy.Publisher('/info', Marker)
00069         self.pubState = rospy.Publisher('/state', String)
00070         
00071 
00072 
00073 
00074     def update(self):
00075         self.publishMap();
00076         self.publishState()
00077         self.publishPositions();
00078         self.publishScore()
00079     
00080         if self.state in [State.GAME_OVER, State.STOPPED, State.PAUSED, State.INIT, State.WON, State.SETUP]:
00081             return;
00082 
00083         self.eatMapPoints();
00084         self.checkGhosts()
00085         if (self.gameWon):
00086             self.state == State.WON
00087 
00088     def gameWon(self):
00089         for point in self.mapPoints:
00090             if not point['eaten']:
00091                 return False
00092         return True
00093             
00094     def publishState(self):
00095         self.pubState.publish(str(self.state));
00096         marker = Marker()
00097         marker.header.frame_id = "/map"
00098         marker.header.stamp = rospy.get_rostime()
00099         marker.type = marker.TEXT_VIEW_FACING
00100         marker.action = marker.ADD
00101         marker.scale.x = 1.0
00102         marker.scale.y = 0.2
00103         marker.scale.z = 0.5
00104         marker.color.a = 1.0
00105         marker.color.r = 1.0
00106         marker.color.g = 0.0
00107         marker.color.b = 0.0
00108         marker.pose.orientation.w = 1.0
00109         marker.pose.position.x = self.infoLoc['x']
00110         marker.pose.position.y = self.infoLoc['y']
00111         marker.pose.position.z = 0.0
00112         marker.id = 0
00113         if (self.state in [State.RUNNING]):
00114             if not self.sendStart:
00115                 marker.text = 'Start'
00116                 self.sendStart = True
00117                 self.timeSend = rospy.get_rostime()
00118             elif (rospy.get_rostime()-self.timeSend).to_sec() > 0.2: 
00119                 #marker.type = marker.SPHERE
00120                 marker.action = marker.DELETE
00121             else:
00122                 marker.text = 'Start'
00123 
00124         if (self.state == State.FLEEING):
00125             timeFleeing = TIME_FLEEING-(rospy.get_rostime()-self.timeStartFleeing).to_sec()
00126             if timeFleeing > 0:
00127                 marker.text = str(timeFleeing)
00128             else:
00129                 marker.action = marker.DELETE
00130                 self.state = State.RUNNING
00131   
00132         if (self.state in [State.GAME_OVER, State.STOPPED, State.SETUP]):
00133             marker.text = 'GAME OVER!'
00134 
00135         if (self.state in [State.INIT]):
00136             marker.text = 'Initializing Game'  
00137 
00138         if (self.state in [State.PAUSED]):
00139             marker.text = 'Game Paused'
00140 
00141         if (self.state in [State.WON]):
00142             marker.text = 'Congratulations, you have won the Game! Now get back to you real job!'
00143 
00144         self.pubInfo.publish(marker)
00145 
00146     def publishScore(self):
00147         marker = Marker()
00148         marker.header.frame_id = "/map"
00149         marker.type = marker.TEXT_VIEW_FACING
00150         marker.action = marker.ADD
00151         marker.scale.x = 0.2
00152         marker.scale.y = 0.2
00153         marker.scale.z = 0.5
00154         marker.color.a = 1.0
00155         marker.color.r = 1.0
00156         marker.color.g = 0.0
00157         marker.color.b = 0.0
00158         marker.pose.orientation.w = 1.0
00159         marker.pose.position.x = self.scoreLoc['x']
00160         marker.pose.position.y = self.scoreLoc['y']
00161         marker.pose.position.z = 0.0
00162         marker.id = 0
00163         marker.text = 'Score: ' + str(self.score)
00164                    
00165         self.pubScore.publish(marker)
00166 
00167     def reset(self):
00168         self.score = 0
00169         self.sendStart = False
00170         for point in self.mapPoints:
00171             point['eaten'] = False
00172         
00173     def checkGhosts(self):
00174         for ghost in self.ghosts:
00175             if (dist(self.pacman, self.ghosts[ghost]) < self.pacman['radius'] + self.ghosts[ghost]['radius'] + 1.5*THRESHOLD):
00176                 if self.state == State.RUNNING and not self.ghosts[ghost]['eaten']:
00177                     self.state = State.GAME_OVER
00178                     return
00179                 elif self.state == State.FLEEING:
00180                     if not self.ghosts[ghost]['eaten']:
00181                         self.score += EAT_GHOST
00182                         self.ghosts[ghost]['eaten'] = True
00183 
00184     def eatMapPoints(self):
00185         for point in self.mapPoints:
00186             if dist(self.pacman, point) < self.pacman['radius'] + THRESHOLD:
00187                 if (not point['eaten']):
00188                     self.score += EAT_POINTS
00189                     point['eaten'] = True
00190                     if (point['powerup']):
00191                         self.state = State.FLEEING
00192                         self.timeStartFleeing = rospy.get_rostime()
00193             
00194                 
00195     def publishPositions(self):
00196         if not self.initialized:
00197             return
00198         nr = 0
00199         markerArray = MarkerArray()
00200         marker = Marker()
00201         marker.header.frame_id = "/map"
00202         marker.type = marker.MESH_RESOURCE
00203         marker.action = marker.ADD
00204         marker.scale.x = 0.2
00205         marker.scale.y = 0.2
00206         marker.scale.z = 0.2
00207 
00208         marker.mesh_use_embedded_materials = True
00209         marker.mesh_resource = "package://pacman_controller/meshes/pacman.dae"
00210      
00211 
00212         marker.color.a = 1.0
00213         marker.color.r = 0.0
00214         marker.color.g = 1.0
00215         marker.color.b = 0.0
00216         marker.pose.orientation = self.pacman['orientation']
00217         marker.pose.position.x = self.pacman['x']
00218         marker.pose.position.y = self.pacman['y']
00219         marker.pose.position.z = 0.0
00220         marker.id = nr
00221         markerArray.markers.append(marker)
00222     
00223         for ghost in self.ghosts:
00224             curGhost = self.ghosts[ghost]
00225             if not curGhost["initialized"]:
00226                 continue
00227             nr += 1
00228             marker = Marker()
00229             marker.header.frame_id = "/map"
00230             marker.type = marker.MESH_RESOURCE
00231             marker.action = marker.ADD
00232             marker.scale.x = 0.3
00233             marker.scale.y = 0.3
00234             marker.scale.z = 0.3
00235             
00236             marker.mesh_use_embedded_materials = True
00237             if curGhost["eaten"]:
00238                 marker.mesh_resource = "package://pacman_controller/meshes/dead.dae"
00239             elif self.state == State.FLEEING:
00240                 marker.mesh_resource = "package://pacman_controller/meshes/ghost_catchable.dae"
00241             else:
00242                 marker.mesh_resource = "package://pacman_controller/meshes/%s.dae"%ghost
00243             marker.color.a = 1.0
00244             marker.color.r = 0.0
00245             marker.color.g = 1.0
00246             marker.color.b = 0.0
00247             marker.pose.orientation = curGhost['orientation']
00248             marker.pose.position.x = curGhost['x']
00249             marker.pose.position.y = curGhost['y']
00250             marker.pose.position.z = 0.0
00251             marker.id = nr
00252             markerArray.markers.append(marker)
00253 
00254 
00255         self.pubPositions.publish(markerArray)
00256         return
00257 
00258     def positionBlocked(self, position, agent):
00259         if not agent == self.pacman:
00260             if (dist(position, self.pacman) < self.pacman['radius'] + THRESHOLD):
00261                 return True
00262         for ghost in self.ghosts:
00263             if self.ghosts[ghost] == agent:
00264                 continue
00265             if (dist(position, self.ghosts[ghost]) < self.ghosts[ghost]['radius'] + THRESHOLD):
00266                 return True
00267        
00268 
00269         return False
00270 
00271     def readMap(self):
00272         vertices = rospy.get_param("/vertices");
00273         edgesRead = rospy.get_param("/edges");
00274         self.points = []
00275         self.edges = []
00276         for i in range(len(vertices)):
00277             #print str(self.vertices['point_%d'%i])
00278             point = {}
00279             point['x'] = vertices['point_%d'%i]['x']
00280             point['y'] = vertices['point_%d'%i]['y']
00281             point['id'] = vertices['point_%d'%i]['id']
00282             point['neighbors'] = []
00283             self.points.append(point)
00284         
00285         for i in range(len(edgesRead)):
00286             #print str(self.edgesRead['edge_%d'%i])
00287             self.addEdge(edgesRead['edge_%d'%i])
00288             self.edges.append(edgesRead['edge_%d'%i])
00289 
00290         self.createMapPoints();
00291 
00292       
00293     def addEdge(self, edge):
00294         if not edge['a'] in self.points[edge['b']]['neighbors']:
00295             self.points[edge['b']]['neighbors'].append(edge['a'])
00296         if not edge['b'] in self.points[edge['a']]['neighbors']:
00297             self.points[edge['a']]['neighbors'].append(edge['b'])
00298 
00299     def commandsRobotCallback(self, msg):
00300         if (msg.data == "Start") and self.state == State.INIT:
00301             self.state = State.RUNNING
00302 
00303         if (msg.data == "Setup"): 
00304             self.state = State.SETUP
00305 
00306             
00307         if (msg.data == "Stop"):
00308             self.state = State.STOPPED
00309 
00310 
00311         if (msg.data == "Init") and self.state in [State.STOPPED, State.GAME_OVER, State.SETUP]:
00312             self.state = State.INIT
00313             self.reset()
00314         
00315         if self.state in [State.STOPPED, State.GAME_OVER]:
00316             return
00317 
00318         if (msg.data == "Pause") and self.state in [State.RUNNING, State.FLEEING]:
00319             self.old_state = self.state
00320             self.state = State.PAUSED
00321 
00322         if (msg.data == "Resume") and self.state == State.PAUSED:
00323             self.state = self.old_state
00324             
00325 
00326     def positionShareCallback(self, msg):
00327         if (msg.robot_id == "pacman"):
00328             self.pacman['x'] = msg.pose.pose.position.x
00329             self.pacman['y'] = msg.pose.pose.position.y
00330             self.pacman['orientation'] = msg.pose.pose.orientation
00331             self.pacman['radius'] = msg.radius
00332             self.initialized = True
00333 
00334         else:
00335             if not msg.robot_id in self.ghosts:
00336                 self.ghosts[msg.robot_id] = {}
00337                 self.ghosts[msg.robot_id]['initialized'] = False
00338               
00339                 self.ghosts[msg.robot_id]['eaten'] = False
00340                 self.ghosts[msg.robot_id]['home'] = self.points[rospy.get_param('/%s/home/'%msg.robot_id)]
00341             self.ghosts[msg.robot_id]['x'] = msg.pose.pose.position.x
00342             self.ghosts[msg.robot_id]['y'] = msg.pose.pose.position.y
00343             self.ghosts[msg.robot_id]['orientation'] = msg.pose.pose.orientation
00344                   
00345             self.ghosts[msg.robot_id]['radius'] = msg.radius
00346             if self.ghosts[msg.robot_id]['eaten'] and dist(self.ghosts[msg.robot_id]['home'], self.ghosts[msg.robot_id]) < self.ghosts[msg.robot_id]['radius'] + THRESHOLD:
00347                 self.ghosts[msg.robot_id]['eaten'] = False
00348             self.ghosts[msg.robot_id]['initialized'] = True
00349 
00350     def createMapPoints(self):
00351         self.mapPoints = [];
00352         for edge in self.edges:
00353 #            print str(edge)
00354             point_a = self.points[edge['a']]
00355             point_b = self.points[edge['b']]
00356             cur_point = {}
00357             cur_point['x'] = point_a['x']
00358             cur_point['y'] = point_a['y']
00359             direction = self.get_dir(point_a, point_b)
00360             while (dist(cur_point, point_b) > 0.2):
00361                 point = {}
00362                 point['x'] = cur_point['x'] + 0.2 * direction[0]
00363                 point['y'] = cur_point['y'] + 0.2 * direction[1]
00364                 point['neighbors'] = [point_a['id'], point_b['id']]
00365                 point['eaten'] = False
00366                 point['powerup'] = False
00367                 cur_point = point
00368                 self.mapPoints.append(point)
00369         for node in self.power_ups['nodes']:
00370             point = self.points[node]
00371             point['eaten'] = False
00372             point['powerup'] = True
00373             self.mapPoints.append(point)
00374             
00375 
00376     def findClosestMapPoint(self,position):
00377        minDist = dist(self.mapPoints[0], position)
00378        minPoint = self.mapPoints[0]
00379        for p in self.mapPoints:
00380            if p["powerup"]:
00381                continue;
00382            distNew = dist(p, position)
00383            if distNew < minDist:
00384                minDist = distNew
00385                minPoint = p
00386        return minPoint
00387         
00388 
00389     def findClosestWP(self, position):
00390         minPoint = self.findClosestMapPoint(position)
00391         distA = dist(minPoint, self.points[minPoint['neighbors'][0]])
00392         distB = dist(minPoint, self.points[minPoint['neighbors'][1]])
00393         if (distA > distB):
00394             return minPoint['neighbors'][1]
00395         else: 
00396             return minPoint['neighbors'][0]
00397         
00398     def publishMap(self):
00399         markerArray = MarkerArray()
00400         marker = Marker()
00401         marker.header.frame_id = "/map"
00402         marker.type = marker.SPHERE_LIST
00403         marker.action = marker.ADD
00404         marker.scale.x = 0.05
00405         marker.scale.y = 0.05
00406         marker.scale.z = 0.05
00407         marker.color.a = 1.0
00408         marker.color.r = 1.0
00409         marker.color.g = 1.0
00410         marker.color.b = 0.0
00411         marker.pose.orientation.w = 1.0
00412         marker.pose.position.x = 0.0
00413         marker.pose.position.y = 0.0
00414         marker.pose.position.z = 0.0
00415         marker.id = 0
00416         for p in self.mapPoints:
00417             if p['eaten']:
00418                 continue
00419             if p['powerup']:
00420                 continue
00421             point = Point()
00422             point.x = p['x']
00423             point.y = p['y']
00424             point.z = 0.15
00425             marker.points.append(point)
00426         markerArray.markers.append(marker)
00427 
00428         marker = Marker()
00429         marker.header.frame_id = "/map"
00430         marker.type = marker.SPHERE_LIST
00431         marker.action = marker.ADD
00432         marker.scale.x = 0.3
00433         marker.scale.y = 0.3
00434         marker.scale.z = 0.3
00435         marker.color.a = 1.0
00436         marker.color.r = 1.0
00437         marker.color.g = 1.0
00438         marker.color.b = 0.0
00439         marker.pose.orientation.w = 1.0
00440         marker.pose.position.x = 0.0
00441         marker.pose.position.y = 0.0
00442         marker.pose.position.z = 0.0
00443         marker.id = 1
00444         for p in self.mapPoints:
00445             if p['eaten']:
00446                 continue
00447             if not p['powerup']:
00448                 continue
00449             point = Point()
00450             point.x = p['x']
00451             point.y = p['y']
00452             point.z = 0.2
00453             marker.points.append(point)
00454         markerArray.markers.append(marker)
00455         
00456         self.pubMap.publish(markerArray)
00457 
00458 
00459 
00460     def publishMarkers(self):
00461         markerArray = MarkerArray()
00462         marker = Marker()
00463         marker.header.frame_id = "/map"
00464         marker.type = marker.SPHERE_LIST
00465         marker.action = marker.ADD
00466         marker.scale.x = 0.2
00467         marker.scale.y = 0.2
00468         marker.scale.z = 0.2
00469         marker.color.a = 1.0
00470         marker.color.r = 0.0
00471         marker.color.g = 1.0
00472         marker.color.b = 0.0
00473         marker.pose.orientation.w = 1.0
00474         marker.pose.position.x = 0.0
00475         marker.pose.position.y = 0.0
00476         marker.pose.position.z = 0.0
00477         marker.id = 0
00478         for p in self.points:
00479             point = Point()
00480             point.x = p['x']
00481             point.y = p['y']
00482             marker.points.append(point)
00483         #markerArray.markers.append(marker)
00484 
00485         for p in self.points:
00486             marker = Marker()
00487             marker.header.frame_id = "/map"
00488             marker.type = marker.TEXT_VIEW_FACING
00489             marker.action = marker.ADD
00490             marker.scale.x = 0.2
00491             marker.scale.y = 0.2
00492             marker.scale.z = 0.2
00493             marker.color.a = 1.0
00494             marker.color.r = 1.0
00495             marker.color.g = 0.0
00496             marker.color.b = 0.0
00497             marker.pose.orientation.w = 1.0
00498             marker.pose.position.x = p['x']
00499             marker.pose.position.y = p['y']
00500             marker.pose.position.z = 0.0
00501             marker.id = p['id']+1
00502             marker.text = 'Node: ' + str(p['id'])
00503             markerArray.markers.append(marker)
00504 
00505 
00506 
00507         
00508         nr = len(self.points)+1
00509         for edge in self.edges:
00510 #            print str(edge)
00511             point_a = self.points[edge['a']]
00512             point_b = self.points[edge['b']]
00513             marker = Marker() 
00514             marker.header.frame_id = "/map"
00515             marker.type = marker.SPHERE_LIST
00516             marker.action = marker.ADD
00517             marker.scale.x = 0.05
00518             marker.scale.y = 0.05
00519             marker.scale.z = 0.05
00520             marker.color.a = 1.0
00521             marker.color.r = 0.0
00522             marker.color.g = 1.0
00523             marker.color.b = 0.0
00524             marker.pose.orientation.w = 1.0
00525             marker.pose.position.x = 0.0
00526             marker.pose.position.y = 0.0
00527             marker.pose.position.z = 0.0
00528             marker.id = nr
00529             cur_point = {}
00530             cur_point['x'] = point_a['x']
00531             cur_point['y'] = point_a['y']
00532             direction = self.get_dir(point_a, point_b)
00533             while (dist(cur_point, point_b) > 0.2):
00534                 point = Point()
00535                 point.x = cur_point['x'] + 0.2 * direction[0]
00536                 point.y = cur_point['y'] + 0.2 * direction[1]
00537                 cur_point['x'] = point.x
00538                 cur_point['y'] = point.y
00539                 marker.points.append(point)
00540             markerArray.markers.append(marker)
00541             nr +=1
00542         self.pubMap.publish(markerArray)
00543 
00544     def get_dir(self, point_a, point_b):
00545         result_x = point_b['x'] - point_a['x']
00546         result_y = point_b['y'] - point_a['y']
00547         dis = dist(point_a,point_b)
00548         return [result_x / dis, result_y / dis]
00549 
00550 
00551     def find_shortest_path(self,start, end, path = [], pathIds = []):
00552         if pathIds == []:
00553             pathIds = pathIds + [-1]
00554         else:
00555             pathIds = pathIds + [start['id']]
00556         path = path + [start]
00557         
00558         if start == end:
00559             return path
00560         shortest = None
00561         for node in start['neighbors']:
00562 #            print str(node)
00563             if node not in pathIds:
00564                 newpath = self.find_shortest_path(self.points[node], end, path, pathIds)
00565                 if newpath:
00566                     if not shortest or len(newpath) < len(shortest):
00567                         shortest = newpath
00568         return shortest
00569 
00570 
00571 
00572 if __name__ == '__main__':
00573     rospy.init_node('game_engine')
00574     gameEngine = GameEngine()
00575     while not rospy.is_shutdown():
00576         gameEngine.update()
00577         rospy.sleep(0.05)
00578 
00579 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


pacman_controller
Author(s): Daniel Claes
autogenerated on Sun Aug 25 2013 10:10:43