f.addGoal(370,0) # green flag f.addObstacle(-100,-100) ''' f.setupMap4Ls() #f.setupMapRotatedBoxes() #f.calculateFields() f.fastCalculate() print f.getFast(297, 50), f.getFast(300, 50), f.getFast(303, 50) print f.getFast(-297, 50), f.getFast(-300, 50), f.getFast(-303, 50) f.drawFast(True, True, True) f.goToHome(True) print f.getFast(297, 50), f.getFast(300, 50), f.getFast(303, 50) print f.getFast(-297, 50), f.getFast(-300, 50), f.getFast(-303, 50) f.drawFast(True, True, True) # #f.setupMapRotatedBoxes() #f.fastCalculate() #f.drawFast(True, True, True) #print f.queryPosition(0, 100) #f.visualize(True, True, True) # all fields #f.visualize(True, False, False) # attractive only #f.visualize(False, True, False) # repulsive only #f.visualize(False, False, True) # tangential only
class Agent(object): def __init__(self, bzrc): self.bzrc = bzrc self.field = Field(-400, 400, -400, 400) self.field.setupMap4Ls() #self.field.setupMapRotatedBoxes() self.field.fastCalculate() self.constants = self.bzrc.get_constants() self.commands = [] self.prevError = defaultdict(list) self.vizualize = True self.gotFlag = False self.prevLocation = [0, 0] self.stuckTimer = time.time() self.stuck = False def tickAll(self, step): '''Some time has passed; decide what to do next''' # Get information from the BZRC server mytanks, othertanks, flags, shots = self.bzrc.get_lots_o_stuff() self.mytanks = mytanks self.othertanks = othertanks self.flags = flags self.shots = shots self.enemies = [tank for tank in othertanks if tank.color != self.constants['team']] # Reset my set of commands (we don't want to run old commands) self.commands = [] # Check to see if the flag has been captured for bot in mytanks: if not self.gotFlag and bot.flag is not '-': self.gotFlag = True self.flipFieldToHome() if self.gotFlag and bot.flag is '-': self.gotFlag = False self.flipFieldToEnemy() # Decide what to do with each of my tanks if (time.time() - self.stuckTimer) > 3: if bot.x == self.prevLocation[0] and bot.y == self.prevLocation[1]: print 'stuck' self.stuck = True else: self.stuck = False self.prevLocation = [bot.x, bot.y] self.stuckTimer = time.time() if self.stuck: command = Command(bot.index, 1, 1, True) self.commands.append(command) else: for bot in mytanks: values = self.calculatePD(bot, step) command = Command(bot.index, values[0], values[1], True) self.commands.append(command) # Send the commands to the server results = self.bzrc.do_commands(self.commands) def tickOne(self, step): '''Some time has passed; decide what to do next''' # Get information from the BZRC server mytanks, othertanks, flags, shots = self.bzrc.get_lots_o_stuff() self.mytanks = mytanks self.othertanks = othertanks self.flags = flags self.shots = shots self.enemies = [tank for tank in othertanks if tank.color != self.constants['team']] # Reset my set of commands (we don't want to run old commands) self.commands = [] # Visualize potential field if self.vizualize: self.field.drawFast(True, True, True) self.vizualize = False print 'Done with visualization' # Which tank do you want to control bot = mytanks[0] #print bot.flag # Check to see if the flag has been captured if not self.gotFlag and bot.flag is not '-': print 'set home' self.gotFlag = True self.flipFieldToHome() if self.gotFlag and bot.flag is '-': self.gotFlag = False self.flipFieldToEnemy() # Decide what to do with one tank of my tanks values = self.calculatePD(bot, step) if (time.time() - self.stuckTimer) > 3: if bot.x == self.prevLocation[0] and bot.y == self.prevLocation[1]: print 'stuck' self.stuck = True else: self.stuck = False self.prevLocation = [bot.x, bot.y] self.stuckTimer = time.time() if self.stuck: command = Command(bot.index, 1, 1, True) self.commands.append(command) else: command = Command(bot.index, values[0], values[1], True) self.commands.append(command) # Send the commands to the server results = self.bzrc.do_commands(self.commands) def calculatePD(self, bot, step): # Get the potential field magnitudes in the x and y at the current position pf = self.field.getFast(bot.x, bot.y) # Tune these or set to zero to manipulate the PD controller kProportion = .5 kDerivative = .002 # Calculate values used in the PD controller formula angleReference = numpy.arctan2(pf[1], pf[0]) angle = angleReference - bot.angle errorAtStep = numpy.arctan2(math.sin(angle),math.cos(angle)) errorPrevStep = 0.0 # Previous error is zero if this is the first calculation. # Update the previous error to the last saved error if there is one if bot.index in self.prevError: errorPrevStep = self.prevError[bot.index] # This is the PD formula angularAtStep = (kProportion * errorAtStep) + (kDerivative * ((errorAtStep - errorPrevStep) / step)) #print angularAtStep if angularAtStep > 1: angularAtStep = 1 if angularAtStep < -1: angularAtStep = -1 #print errorAtStep, angularAtStep, pf # Calculates the speed based off the magnitude of the potential field vector speedAtStep = 1 - .7 * math.fabs(angularAtStep) #math.sqrt(pf[0]**2 + pf[1]**2) #print speedAtStep # Save the new error to use in the next iteration self.prevError[bot.index] = errorAtStep return [speedAtStep, angularAtStep] def flipFieldToHome(self): self.field.goToHome(True) #self.field.drawFast(True, True, True) def flipFieldToEnemy(self): self.field.goToHome(False)