def animate(self, obstacles): forward_list = list(linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES/2)) backward_list = list(linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES/2)) #print forward_list anim_points = forward_list + backward_list gp = GnuplotProcess(persist=False) gp.write(self.gnuplot_header(-WORLDSIZE / 4, WORLDSIZE / 4)) gp.write(self.draw_obstacles(obstacles))
class KalmanViz(object): def __init__(self, world_size): self.gp = GnuplotProcess(persist=False) self.gp.write(self.gnuplot_header(-world_size / 2, world_size / 2)) def gnuplot_header(self, minimum, maximum): '''Return a string that has all of the gnuplot sets and unsets.''' s = '' s += 'set xrange [%s: %s]\n' % (minimum, maximum) s += 'set yrange [%s: %s]\n' % (minimum, maximum) s += 'set pm3d\n' s += 'set view map\n' # The key is just clutter. Get rid of it: s += 'unset key\n' # Make sure the figure is square since the world is square: s += 'set size square\n' # Add a pretty title (optional): s += "set title 'Kalman Filter Output'\n" # set what color scheme to use s += 'set palette model XYZ functions gray**0.35, gray**0.5, gray**0.8\n' # How fine the plotting should be, at some processing cost: s += 'set isosamples 100\n' return s def draw_noise(self, sigma_x, sigma_y, rho, mu_x, mu_y): # set up the values and plot them s = '' s += 'sigma_x = %s\n' % sigma_x s += 'sigma_y = %s\n' % sigma_y s += 'rho = %s\n' % rho s += 'mu_x = %s\n' % mu_x s += 'mu_y = %s\n' % mu_y piece_1 = '1.0 / (2.0 * pi * sigma_x * sigma_y * sqrt(1 - rho**2))' piece_2 = '-1.0 / (2.0 * (1.0 - rho**2))' piece_3 = '(x - mu_x)**2 / sigma_x**2' piece_4 = '(y - mu_y)**2 / sigma_y**2' piece_5 = '(2.0 * rho * (x - mu_x) * (y - mu_y)) / (sigma_x * sigma_y)' s += 'splot %s * exp(%s * (%s + %s - %s)) with pm3d\n' % (piece_1, piece_2, piece_3, piece_4, piece_5) return s def update_values(self, sigma_x, sigma_y, rho, mu_x, mu_y): self.gp.write(self.draw_noise(sigma_x, sigma_y, rho, mu_x, mu_y)) self.gp.flush() def destroy(self): self.gp.write('exit') self.gp.flush()
class GnuPlotter(object): def __init__(self): self.gnuprocess = GnuplotProcess(persist=False) self.gnuprocess.write(self.plot_file_base()) def plot_file_base(self): header = '' header += "set xrange [-400.0: 400.0]\n" header += "set yrange [-400.0: 400.0]\n" header += "set pm3d\n" header += "set view map\n" header += "unset key\n" header += "set size square\n\n" header += "set palette model RGB functions 1-gray, 1-gray, 1-gray\n" header += "set isosamples 100\n" return header def plot(self,rho,sigma_x,sigma_y, x, y): # print rho # print sigma_x # print sigma_y # print x # print y plot = '' plot += "sigma_x = %f\n" % sigma_x plot += "sigma_y = %f\n" % sigma_y plot += "mu_x = %f\n" % x plot += "mu_y = %f\n" % y plot += "rho = %f\n" % rho plot += "splot 1.0/(2.0 * pi * sigma_x * sigma_y * sqrt(1 - rho**2) ) \\\n" plot += "* exp(-1.0/2.0 * ((x-mu_x)**2 / sigma_x**2 + (y-mu_y)**2 / sigma_y**2 \\\n" plot += "- 2.0*rho*x*y/(sigma_x*sigma_y) ) ) with pm3d\n\n" self.gnuprocess.write(plot) self.gnuprocess.flush() def remove(self): self.gnuprocess.write('exit') self.gnuprocess.flush()
def plot(caller, func): gp = GnuplotProcess(persist=True) forward_list = list(linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES/2)) backward_list = list(linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES/2)) anim_points = forward_list + backward_list gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2)) gp.write(draw_obstacles(caller.obstacles)) gp.write(draw_bases(caller.bases)) field_function = func() #caller.generate_field_function(1) #field_function = generate_field_function(scale) gp.write(plot_field(field_function))
def __init__(self, bzrc): self.bzrc = bzrc self.constants = self.bzrc.get_constants() self.commands = [] self.tanks = {} self.bases = bzrc.get_bases() for base in self.bases: if base.color == self.constants['team']: self.base = base self.WORLDSIZE = int(self.constants['worldsize']) self.gp = GnuplotProcess(persist=False) self.gp.write(gnuplot_header(-self.WORLDSIZE / 2, self.WORLDSIZE / 2))
def __init__(self, WS, OB): """Initialize variables""" self.worldSize=WS self.obstacles=OB self.counter=0 self.step=1000 try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) self.gp = GnuplotProcess(persist=True) self.gp.write(self.draw_obstacles(self.obstacles))
def visualize(self): time.sleep(1) forward_list = list( linspace(self.ANIMATION_MIN, self.ANIMATION_MAX, self.ANIMATION_FRAMES / 2)) backward_list = list( linspace(self.ANIMATION_MAX, self.ANIMATION_MIN, self.ANIMATION_FRAMES / 2)) anim_points = forward_list + backward_list lastTime = time.time() gp = GnuplotProcess(persist=False) gp.write(self.gnuplot_header(-self.WORLDSIZE / 2, self.WORLDSIZE / 2)) gp.write(self.draw_obstacles(self.OBSTACLES)) for scale in cycle(anim_points): self.mytanks, self.othertanks, self.flags, shots = self.BZRC.get_lots_o_stuff( ) field_function = self.generate_field_function(scale) gp.write(self.plot_field(field_function))
def animate_changing_field(self): ######################################################################## # Animate a changing field, if the Python Gnuplot library is present try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) forward_list = list(linspace(self.ANIMATION_MIN, self.ANIMATION_MAX, self.ANIMATION_FRAMES/2)) backward_list = list(linspace(self.ANIMATION_MAX, self.ANIMATION_MIN, self.ANIMATION_FRAMES/2)) anim_points = forward_list + backward_list gp = GnuplotProcess(persist=False) gp.write(self.gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2)) gp.write(self.draw_obstacles(self.obstacles)) for scale in cycle(anim_points): field_function = self.generate_field_function() gp.write(self.plot_field(field_function))
class ANIMATION: def __init__(self, WS, OB): """Initialize variables""" self.worldSize=WS self.obstacles=OB self.counter=0 self.step=1000 try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) self.gp = GnuplotProcess(persist=True) self.gp.write(self.draw_obstacles(self.obstacles)) def animate(self,orderedVisits, color): self.gp.write(self.gnuplot_header(-self.worldSize / 2, self.worldSize / 2)) self.gp.write(self.draw_nodes(orderedVisits,color)) def animateTuples(self,orderedVisits, color): self.gp.write(self.gnuplot_header(-self.worldSize / 2, self.worldSize / 2)) self.gp.write(self.draw_node_tuples(orderedVisits,color)) def draw_nodes(self,nodes,color): '''Return a string which tells Gnuplot to draw all of the obstacles.''' #s = 'unset arrow\n' s = '' last_point = nodes[0] for cur_point in nodes[1:-1]: s += self.draw_line_pause(last_point, cur_point, color) last_point = cur_point self.counter = self.step s+= self.draw_line_pause(last_point, nodes[-1], color) return s def draw_node_tuples(self,nodes,color): '''Return a string which tells Gnuplot to draw all of the obstacles.''' #s = 'unset arrow\n' s = '' for cur_point in nodes: s += self.draw_line_pause(cur_point[0], cur_point[1], color) return s def gnuplot_header(self,minimum, maximum): '''Return a string that has all of the gnuplot sets and unsets.''' s = '' s += 'set xrange [%s: %s]\n' % (minimum, maximum) s += 'set yrange [%s: %s]\n' % (minimum, maximum) # The key is just clutter. Get rid of it: s += 'unset key\n' # Make sure the figure is square since the world is square: s += 'set size square\n' # Add a pretty title (optional): #s += "set title 'Potential Fields'\n" return s def draw_obstacles(self,obstacles): '''Return a string which tells Gnuplot to draw all of the obstacles.''' s = 'unset arrow\n' brown=3 for obs in obstacles: last_point = obs[0] for cur_point in obs[1:]: s += self.draw_line(last_point, cur_point, brown) last_point = cur_point s += self.draw_line(last_point, obs[0], brown) return s def draw_line(self,p1, p2,color): '''Return a string to tell Gnuplot to draw a line from point p1 to point p2 in the form of a set command.''' x1 = p1[0] y1 = p1[1] x2 = p2[0] y2 = p2[1] s='set arrow from %s, %s to %s, %s nohead lt %d\n' % (x1, y1, x2, y2 ,color) return s def draw_line_pause(self, p1, p2, color): '''Return a string to tell Gnuplot to draw a line from point p1 to point p2 in the form of a set command.''' x1 = p1[0] y1 = p1[1] x2 = p2[0] y2 = p2[1] s='set arrow from %s, %s to %s, %s nohead lt %d\n' % (x1, y1, x2, y2 ,color) if self.counter % self.step == 0: s+="\nplot '-' with lines\n0 0 0 0\ne\npause %f\n" % (0) self.counter = 0 self.counter += 1 return s
# Plot the potential fields to a file outfile = open(FILENAME, 'w') print >>outfile, gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2, 70, 100, 0, 300, 100) ######################################################################## # Animate a changing field, if the Python Gnuplot library is present try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) forward_list = list(linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES/2)) backward_list = list(linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES/2)) anim_points = forward_list + backward_list track_enemy_field_gen.vector_at(0,0) sigma_x, sigma_y, x, y = track_enemy_field_gen.get_sigma_t() gp = GnuplotProcess(persist=False) gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2, sigma_x, sigma_y, 0, x, y)) for scale in cycle(anim_points): track_enemy_field_gen.vector_at(0,0) sigma_x, sigma_y, x, y = track_enemy_field_gen.get_sigma_t() gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2, sigma_x, sigma_y, 0, x, y))
print >> sys.stderr, '%s: incorrect number of arguments' % execname print >> sys.stderr, 'usage: %s hostname port' % sys.argv[0] sys.exit(-1) x = 0 for f in flags: if f.color == flagColor: FLAG_INT = x x += 1 forward_list = list( linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES / 2)) backward_list = list( linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES / 2)) anim_points = forward_list + backward_list lastTime = time.time() gp = GnuplotProcess(persist=False) gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2)) gp.write(draw_obstacles(OBSTACLES)) for scale in cycle(anim_points): # if ((time.time() - lastTime) > 1): # print 'hello world' # lastTime = time.time() time.sleep(.3) mytanks, othertanks, flags, shots = BZRC.get_lots_o_stuff() f = flags[FLAG_INT] # print 'hello world' field_function = generate_field_function(scale) gp.write(plot_field(field_function)) # vim: et sw=4 sts=4
def display(flags, bases, obstacles, field_function): try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) gp = GnuplotProcess(persist=True) gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2)) gp.write(unset_arrow()) gp.write(draw_flags(flags)) gp.write(draw_bases(bases)) gp.write(draw_obstacles(obstacles)) gp.write(plot_field(field_function))
from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) #forward_list = list(linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES/2)) #backward_list = list(linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES/2)) #anim_points = forward_list + backward_list plotter = PFieldPlotter() agent = Agent(plotter) agent.update() headers = plotter.gnuplot_header(-plotter.WORLDSIZE / 2, plotter.WORLDSIZE / 2) vectors = plotter.plot_field(agent) gp = GnuplotProcess(persist=True) gp.write(headers) gp.write(vectors) # animate #for scale in cycle(anim_points): # field_function = generate_field_function(scale) # gp.write(plot_field(field_function)) outfile = open('fields.gpi', 'w') print >>outfile, headers print >>outfile, vectors # vim: et sw=4 sts=4
class Agent(object): """Class handles all command and control logic for a teams tanks.""" def __init__(self, bzrc): self.bzrc = bzrc self.constants = self.bzrc.get_constants() self.commands = [] self.tanks = {} self.bases = bzrc.get_bases() for base in self.bases: if base.color == self.constants['team']: self.base = base self.WORLDSIZE = int(self.constants['worldsize']) self.gp = GnuplotProcess(persist=False) self.gp.write(gnuplot_header(-self.WORLDSIZE / 2, self.WORLDSIZE / 2)) def tick(self, time_diff): """Some time has passed; decide what to do next.""" mytanks, othertanks, flags, shots = self.bzrc.get_lots_o_stuff() self.mytanks = mytanks self.othertanks = othertanks self.flags = flags self.shots = shots self.obstacles = self.bzrc.get_obstacles() self.enemies = [tank for tank in othertanks if tank.color != self.constants['team']] self.commands = [] for tank in mytanks: if tank.index == 0: self.behave(tank, time_diff) else: self.behave(tank, time_diff) results = self.bzrc.do_commands(self.commands) def closest_flag(self, flags, tank, flags_captured): closest_dist = sys.maxint chosen_flag = flags[0] for flag in flags: distance = compute_distance(flag.x, tank.x, flag.y, tank.y) if distance < closest_dist and not flags_captured.__contains__(flag.color): closest_dist = distance chosen_flag = flag return chosen_flag # def get_obstacle_center_and_radius(self, obstacle): # x_total = 0 # y_total = 0 # for index, value in obstacle: # if index % 2 == 0: # x_total += value # else: # y_total += value # x_average = x_total / len(obstacle) / 2 # y_average = y_total / len(obstacle) / 2 # current_x = None # total_distance_from_center = 0 # for index, value in obstacle: # if index % 2 == 0: # current_x = value # else: # total_distance_from_center += compute_distance(current_x, x_average, value, y_average) # average_radius = total_distance_from_center / len(obstacle) / 2 # return x_average, y_average, average_radius def behave(self, tank, time_diff, plot=False): """Create a behavior command based on potential fields. Plot the potential field if plot is True. """ bag_o_fields = [] # avoid enemies for enemy in self.enemies: if enemy.status == self.constants['tankalive']: bag_o_fields.append(make_circle_repulsion_function(enemy.x, enemy.y, int(self.constants['tanklength']), int(self.constants['tanklength'])*5, 2)) #avoid obstacles #~ for obstacle in self.obstacles: #~ # x, y, r = self.get_obstacle_center_and_radius(obstacle) #~ current_x = None #~ for index, value in obstacle: #~ if index % 2 == 0: #~ current_x = value #~ else: #~ bag_o_fields.append(make_circle_repulsion_function(current_x, value, 10, 20, 20)) # avoid shots for shot in self.shots: bag_o_fields.append(make_circle_repulsion_function(shot.x, shot.y, int(self.constants['tanklength']), int(self.constants['tanklength'])*3, 2)) enemy_flags = [] for flag in self.flags: if flag.color != self.constants['team']: enemy_flags.append(flag) else: our_flag = flag #if another tank on your team has a flag, that tank becomes a tangential field #also, make sure that any flag that a teammate is carrying is no longer attractive flags_captured = [] for my_tank in self.mytanks: if my_tank != tank and my_tank.flag != "-": bag_o_fields.append(make_tangential_function(my_tank.x, my_tank.y, int(self.constants['tanklength']), 80, 1, 20)) flags_captured.append(my_tank.flag) #if an enemy tank has captured our flag, they become a priority public_enemy = None for other_tank in self.othertanks: if other_tank.flag == self.constants['team']: public_enemy = other_tank if tank.flag != "-": goal = self.base cr = (self.base.corner1_x - self.base.corner2_x) / 2 goal.x = self.base.corner1_x + cr goal.y = self.base.corner1_y + cr cs = 10 a = 3 elif public_enemy is not None: goal1 = public_enemy goal2 = self.closest_flag(enemy_flags, tank, flags_captured) dist_goal1 = compute_distance(goal1.x, tank.x, goal1.y, tank.y) dist_goal2 = compute_distance(goal2.x, tank.x, goal2.y, tank.y) if dist_goal1 < dist_goal2: goal = goal1 cr = int(self.constants['tanklength']) cs = 20 a = 3 else: goal = goal2 cr = 2 cs = 20 a = 2 else: goal = self.closest_flag(enemy_flags, tank, flags_captured) cr = 2 cs = 20 a = 2 bag_o_fields.append(make_circle_attraction_function(goal.x, goal.y, cr, cs, a)) def pfield_function(x, y): dx = 0 dy = 0 for field_function in bag_o_fields: newdx, newdy = field_function(x, y) dx += newdx dy += newdy return dx, dy dx, dy = pfield_function(tank.x, tank.y) self.move_to_position(tank, tank.x + dx, tank.y + dy) if plot: self.gp.write(plot_field(pfield_function)) def attack_enemies(self, tank): """Find the closest enemy and chase it, shooting as you go.""" best_enemy = None best_dist = 2 * float(self.constants['worldsize']) for enemy in self.enemies: if enemy.status != 'alive': continue dist = math.sqrt((enemy.x - tank.x)**2 + (enemy.y - tank.y)**2) if dist < best_dist: best_dist = dist best_enemy = enemy if best_enemy is None: command = Command(tank.index, 0, 0, False) self.commands.append(command) else: self.move_to_position(tank, best_enemy.x, best_enemy.y) def move_to_position(self, tank, target_x, target_y): """Set command to move to given coordinates.""" target_angle = math.atan2(target_y - tank.y, target_x - tank.x) relative_angle = self.normalize_angle(target_angle - tank.angle) command = Command(tank.index, 1, 2 * relative_angle, True) self.commands.append(command) def normalize_angle(self, angle): """Make any angle be between +/- pi.""" angle -= 2 * math.pi * int (angle / (2 * math.pi)) if angle <= -math.pi: angle += 2 * math.pi elif angle > math.pi: angle -= 2 * math.pi return angle
def __init__(self, world_size): self.gp = GnuplotProcess(persist=False) self.gp.write(self.gnuplot_header(-world_size / 2, world_size / 2))
outfile = open(FILENAME, 'w') print >>outfile, gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2) print >>outfile, draw_obstacles(OBSTACLES) field_function = generate_field_function(150) print >>outfile, plot_field(field_function) ######################################################################## # Animate a changing field, if the Python Gnuplot library is present try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) forward_list = list(linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES/2)) backward_list = list(linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES/2)) anim_points = forward_list + backward_list gp = GnuplotProcess(persist=False) gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2)) gp.write(draw_obstacles(OBSTACLES)) for scale in cycle(anim_points): field_function = generate_field_function(scale) gp.write(plot_field(field_function)) # vim: et sw=4 sts=4
def __init__(self): self.gnuprocess = GnuplotProcess(persist=False) self.gnuprocess.write(self.plot_file_base())
######################################################################## # Animate a changing field, if the Python Gnuplot library is present try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) #this for loop populates the list of fieldGenerators -Josh for obs in OBSTACLES: obsRadiusAndCenter(obs) forward_list = list(linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES/2)) backward_list = list(linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES/2)) anim_points = forward_list + backward_list gp = GnuplotProcess(persist=True)#this starts the GP process and makes it a persistent file so it doesn't close automatically gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2))#sets up the initialization gp.write(draw_obstacles(OBSTACLES,FLAGS))#draws the obstacles and now flags -josh gp.write(plot_field(generate_fields))
def plot(obstacleList): ######################################################################## # Constants # Output file: FILENAME = 'fields.gpi' # Size of the world (one of the "constants" in bzflag): WORLDSIZE = 800 # How many samples to take along each dimension: SAMPLES = 25 # Change spacing by changing the relative length of the vectors. It looks # like scaling by 0.75 is pretty good, but this is adjustable: VEC_LEN = 0.75 * WORLDSIZE / SAMPLES # Animation parameters: ANIMATION_MIN = 0 ANIMATION_MAX = 500 ANIMATION_FRAMES = 50 ######################################################################## # Field and Obstacle Definitions def generate_field_function(scale): def function(x, y): '''User-defined field function.''' sqnorm = (x**2 + y**2) if sqnorm == 0.0: return 0, 0 else: return x * scale / sqnorm, y * scale / sqnorm return function OBSTACLES = obstacleList ######################################################################## # Helper Functions def gpi_point(x, y, vec_x, vec_y): '''Create the centered gpi data point (4-tuple) for a position and vector. The vectors are expected to be less than 1 in magnitude, and larger values will be scaled down.''' r = (vec_x**2 + vec_y**2)**0.5 if r > 1: vec_x /= r vec_y /= r return (x - vec_x * VEC_LEN / 2, y - vec_y * VEC_LEN / 2, vec_x * VEC_LEN, vec_y * VEC_LEN) def gnuplot_header(minimum, maximum): '''Return a string that has all of the gnuplot sets and unsets.''' s = '' s += 'set terminal png\n' s += "set output 'fields.png'\n" s += 'set xrange [%s: %s]\n' % (minimum, maximum) s += 'set yrange [%s: %s]\n' % (minimum, maximum) # The key is just clutter. Get rid of it: s += 'unset key\n' # Make sure the figure is square since the world is square: s += 'set size square\n' # Add a pretty title (optional): #s += "set title 'Potential Fields'\n" return s def draw_line(p1, p2): '''Return a string to tell Gnuplot to draw a line from point p1 to point p2 in the form of a set command.''' x1, y1 = p1 x2, y2 = p2 return 'set arrow from %s, %s to %s, %s nohead lt 3\n' % (x1, y1, x2, y2) def draw_obstacles(obstacles): '''Return a string which tells Gnuplot to draw all of the obstacles.''' s = 'unset arrow\n' for obs in obstacles: last_point = obs[0] for cur_point in obs[1:]: s += draw_line(last_point, cur_point) last_point = cur_point s += draw_line(last_point, obs[0]) return s def plot_field(function): '''Return a Gnuplot command to plot a field.''' s = "plot '-' with vectors head\n" separation = WORLDSIZE / SAMPLES end = WORLDSIZE / 2 - separation / 2 start = -end points = ((x, y) for x in linspace(start, end, SAMPLES) for y in linspace(start, end, SAMPLES)) for x, y in points: f_x, f_y = function(x, y) plotvalues = gpi_point(x, y, f_x, f_y) if plotvalues is not None: x1, y1, x2, y2 = plotvalues s += '%s %s %s %s\n' % (x1, y1, x2, y2) s += 'e\n' return s ######################################################################## # Plot the potential fields to a file outfile = open(FILENAME, 'w') print >> outfile, gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2) print >> outfile, draw_obstacles(OBSTACLES) #field_function = generate_field_function(150) #print >>outfile, plot_field(field_function) ######################################################################## # Animate a changing field, if the Python Gnuplot library is present try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) forward_list = list( linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES / 2)) backward_list = list( linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES / 2)) anim_points = forward_list + backward_list gp = GnuplotProcess(persist=False) gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2)) gp.write(draw_obstacles(OBSTACLES)) for scale in cycle(anim_points): field_function = generate_field_function(scale) gp.write(plot_field(field_function))
def plot(obstacleList): ######################################################################## # Constants # Output file: FILENAME = 'fields.gpi' # Size of the world (one of the "constants" in bzflag): WORLDSIZE = 800 # How many samples to take along each dimension: SAMPLES = 25 # Change spacing by changing the relative length of the vectors. It looks # like scaling by 0.75 is pretty good, but this is adjustable: VEC_LEN = 0.75 * WORLDSIZE / SAMPLES # Animation parameters: ANIMATION_MIN = 0 ANIMATION_MAX = 500 ANIMATION_FRAMES = 50 ######################################################################## # Field and Obstacle Definitions def generate_field_function(scale): def function(x, y): '''User-defined field function.''' sqnorm = (x**2 + y**2) if sqnorm == 0.0: return 0, 0 else: return x*scale/sqnorm, y*scale/sqnorm return function OBSTACLES = obstacleList ######################################################################## # Helper Functions def gpi_point(x, y, vec_x, vec_y): '''Create the centered gpi data point (4-tuple) for a position and vector. The vectors are expected to be less than 1 in magnitude, and larger values will be scaled down.''' r = (vec_x ** 2 + vec_y ** 2) ** 0.5 if r > 1: vec_x /= r vec_y /= r return (x - vec_x * VEC_LEN / 2, y - vec_y * VEC_LEN / 2, vec_x * VEC_LEN, vec_y * VEC_LEN) def gnuplot_header(minimum, maximum): '''Return a string that has all of the gnuplot sets and unsets.''' s = '' s += 'set terminal png\n' s += "set output 'fields.png'\n" s += 'set xrange [%s: %s]\n' % (minimum, maximum) s += 'set yrange [%s: %s]\n' % (minimum, maximum) # The key is just clutter. Get rid of it: s += 'unset key\n' # Make sure the figure is square since the world is square: s += 'set size square\n' # Add a pretty title (optional): #s += "set title 'Potential Fields'\n" return s def draw_line(p1, p2): '''Return a string to tell Gnuplot to draw a line from point p1 to point p2 in the form of a set command.''' x1, y1 = p1 x2, y2 = p2 return 'set arrow from %s, %s to %s, %s nohead lt 3\n' % (x1, y1, x2, y2) def draw_obstacles(obstacles): '''Return a string which tells Gnuplot to draw all of the obstacles.''' s = 'unset arrow\n' for obs in obstacles: last_point = obs[0] for cur_point in obs[1:]: s += draw_line(last_point, cur_point) last_point = cur_point s += draw_line(last_point, obs[0]) return s def plot_field(function): '''Return a Gnuplot command to plot a field.''' s = "plot '-' with vectors head\n" separation = WORLDSIZE / SAMPLES end = WORLDSIZE / 2 - separation / 2 start = -end points = ((x, y) for x in linspace(start, end, SAMPLES) for y in linspace(start, end, SAMPLES)) for x, y in points: f_x, f_y = function(x, y) plotvalues = gpi_point(x, y, f_x, f_y) if plotvalues is not None: x1, y1, x2, y2 = plotvalues s += '%s %s %s %s\n' % (x1, y1, x2, y2) s += 'e\n' return s ######################################################################## # Plot the potential fields to a file outfile = open(FILENAME, 'w') print >>outfile, gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2) print >>outfile, draw_obstacles(OBSTACLES) #field_function = generate_field_function(150) #print >>outfile, plot_field(field_function) ######################################################################## # Animate a changing field, if the Python Gnuplot library is present try: from Gnuplot import GnuplotProcess except ImportError: print "Sorry. You don't have the Gnuplot module installed." import sys sys.exit(-1) forward_list = list(linspace(ANIMATION_MIN, ANIMATION_MAX, ANIMATION_FRAMES/2)) backward_list = list(linspace(ANIMATION_MAX, ANIMATION_MIN, ANIMATION_FRAMES/2)) anim_points = forward_list + backward_list gp = GnuplotProcess(persist=False) gp.write(gnuplot_header(-WORLDSIZE / 2, WORLDSIZE / 2)) gp.write(draw_obstacles(OBSTACLES)) for scale in cycle(anim_points): field_function = generate_field_function(scale) gp.write(plot_field(field_function))