def get_directions_info(self): ''' Returns a list of triplets with delta x, delta y, and delta z of the direction the robot can move in. These directions constitute the locations where beams currently exist. Additionally, it returns the "box of locality" to which the robot is restricted containing all of the beams nearby that the robot can detect (though, this should only be used for finding a connection, as the robot itself SHOULD only measure the stresses on its current beam) ''' # Run analysys before deciding to get the next direction if not self.model.GetModelIsLocked() and self.need_data(): errors = helpers.run_analysis(self.model) if errors != '': # pdb.set_trace() pass # Verify that the robot is on its beam and correct if necessary. # This is done so that floating-point arithmethic errors don't add up. (e1, e2) = self.beam.endpoints if not (helpers.on_line (e1,e2,self.location)): self.change_location(helpers.correct(e1,e2,self.location), self.beam) # Obtain all local objects box = self.structure.get_box(self.location) # Debugging if box == {}: # pdb.set_trace() pass # Find the beams and directions (ie, where can he walk?) directions_info = self.get_walkable_directions(box) return { 'box' : box, 'directions' : directions_info }
def move(self, direction, beam): ''' Moves the robot in direction passed in and onto the beam specified ''' length = helpers.length(direction) # The direction is smaller than the determined step, so move exactly by # direction if length < self.step: new_location = helpers.sum_vectors(self.location, direction) self.change_location(new_location, beam) # call do_action again since we still have some distance left, and update # step to reflect how much distance is left to cover self.step = self.step - length # Reset step in preparation for next timestep if helpers.compare(self.step,0): self.step == variables.step_length # We still have steps to go, so run an analysis if necessary elif self.beam is not None: # Run analysis before deciding to get the next direction if not self.model.GetModelIsLocked() and self.need_data(): errors = helpers.run_analysis(self.model) if errors != '': # pdb.set_trace() pass # Get next direction self.next_direction_info = self.get_direction() # Unlock the results so that we can actually move if self.model.GetModelIsLocked(): self.model.SetModelIsLocked(False) # Move self.do_action() # We climbed off else: assert not self.model.GetModelIsLocked() self.do_action() # The direction is larger than the usual step, so move only the step in the # specified direction else: movement = helpers.scale(self.step, helpers.make_unit(direction)) new_location = helpers.sum_vectors(self.location, movement) self.change_location(new_location, beam)
def movable_decide(self): ''' Later classes need direct access to this method ''' # If we're not on a beam, then we will wander on the ground if self.beam is None: # reset steps self.next_direction_info = None # Otherwise, we are not on the ground and we decided not to build, so pick # a direction and store that else: # Before we decide, we need to make sure that we have access to analysis # results. Therefore, check to see if the model is locked. If it is not, # then execute and analysis. if not self.model.GetModelIsLocked() and self.need_data(): errors = helpers.run_analysis(self.model) assert errors == '' self.next_direction_info = self.get_direction()
def run_simulation(self,visualization = False, timesteps = 10, debug = True, comment = ""): ''' Runs the simulation according to the variables passed in. ''' outputfolder = self.folder start_time = strftime("%H:%M:%S") # Make sure the simulation has been started. If not, exit. if not self.started: print("The simulation has not been started. Start it, then run it, or " + "simply Simulation.go()") sys.exit(1) # Make sure that the model is not locked so that we can change properties. # Unlock it if it is if self.SapModel.GetModelIsLocked(): self.SapModel.SetModelIsLocked(False) # Set everything up. if not self.__setup_general(): sys.exit("General Setup Failed.") if not self.__setup_material(): sys.exit("Material Setup Failed.") if not self.__setup_analysis(): sys.exit("Analysis Setup Failed.") # Open files for writing if debugging with open(outputfolder + 'repair_info.txt', 'a') as repair_file, open(outputfolder + "robot_data.txt", 'a') as loc_text, open(outputfolder + "sap_failures.txt", 'a') as sap_failures, open(outputfolder + "run_data.txt", 'a') as run_text, open(outputfolder + "structure.txt", "a") as struct_data: loc_text.write("This file contains information on the robots at each" + " timestep if debugging.\n\n") sap_failures.write("This file contains messages created when SAP 2000 does" + " not complete a function successfully if debugging.\n\n") struct_data.write("This file contains the data about the Pythonic" + " structure.\n\nCurrently unused do to space issues.") run_text.write("This file contains the variables used in the run of the" + " simulation.\n\nTotal timesteps: " + str(timesteps) + "\nStart time of" + " simumation: " + start_time + "\nSeed:" + str(self.seed) + "\n\n") run_text.write("Folder: {}\n\n".format(str(self.folder))) # Write variables self.__push_information(run_text) # Run the simulation! for i in range(timesteps): if visualization: self.Swarm.show() # Add number and new line to structure visualization data self.Structure.visualization_data += "\n" self.Structure.structure_data.append([]) try: self.Structure.color_data += '\n' except MemoryError: self.Structure.color_data = '' # Save to a different filename every now and again try: if i % variables.analysis_timesteps == 0 and i != 0: filename = "tower-" + str(i) + ".sdb" self.SapModel.File.Save(outputfolder + filename) except: print("Simulation ended when saving output.") if debug: swarm_data = self.Swarm.get_information() self.__add_excel(swarm_data) self.__push_data(swarm_data,loc_text,i+1) self.exit(run_text) raise # Run the analysis if there is a structure to analyze and there are \ # robots on it (ie, we actually need the information) if self.Structure.tubes > 0 and self.Swarm.need_data(): try: sap_failures.write(helpers.run_analysis(self.SapModel)) except: if debug: swarm_data = self.Swarm.get_information() self.__add_excel(swarm_data) self.__push_data(swarm_data,loc_text,i+1) self.exit(run_text) raise # Check the structure for stability failed = self.Structure.failed(self.SapProgram) if failed: print(failed) break # Make the decision based on analysis results try: self.Swarm.decide() except: print("Simulation ended at decision.") if debug: swarm_data = self.Swarm.get_information() self.__add_excel(swarm_data) self.__push_data(swarm_data,loc_text,i+1) self.exit(run_text) raise # Make sure that the model has been unlocked, and if not, unlock it if self.SapModel.GetModelIsLocked(): self.SapModel.SetModelIsLocked(False) # Change the model based on decisions made (act on your decisions) try: self.Swarm.act() except: print("Simulation ended at act.") if debug: swarm_data = self.Swarm.get_information() self.__add_excel(swarm_data) self.__push_data(swarm_data,loc_text,i+1) self.exit(run_text) raise # Write out errors on movements errors = self.Swarm.get_errors() if errors != '': sap_failures.write("Errors that occurred in timestep {}. {}\n\n".format( str(i+1),errors)) # Write out repair information repair_data = self.Swarm.get_repair_data() if repair_data != '': repair_file.write("Repairs for begun at timestep {}:\n {}\n".format( str(i+1),repair_data)) # Give a status update if necessary print("Finished timestep {}\r".format(str(i + 1))) # Sort beam data if self.Structure.structure_data[-1] != []: self.Structure.structure_data[-1].sort(key=lambda t: int(t[0])) # Check height of structure and break out if we will reach maximum if self.Structure.height > variables.dim_z - 2* construction.beam['length']: break with open(self.folder + 'random_seed_results.txt', 'a') as rand_tex: rand_tex.write("{},".format(str(random.randint(0,i+1)))) with open(self.folder + 'structure_height.txt', 'a') as str_height: str_height.write("{},\n".format(str(self.Structure.height))) # We run out of mememory is we don't do this every once in a while if i % 100 == 0 and i != 0: # Write out visualization data self.visualization_data() # Write out structure physics self.structure_physics() # We run out of memory for Excel information if we don't clean it out # everynow and again if i % 5000 == 0 and i != 0: self.__push_excel(self.folder + "locations-{}.xlsx".format(str(i))) # This section writes the robots decisions out to a file if debug: swarm_data = self.Swarm.get_information() self.__add_excel(swarm_data) self.__push_data(swarm_data,loc_text,i+1) # END OF LOOOP # Clean up self.exit(run_text)