Exemple #1
0
  def start(self, visualization = False, robots = 10, comment = "", 
    model="C:\\SAP 2000\\template.sdb"):
    '''
    This starts up the SAP 2000 Program and hides it. 
      visualization = should we display the simulation as it occurs?
      robots = number of robots in simulation
      comment = a comment attached to the name of the folder
      model = location of a file which contains a starting model
    '''
    outputfolder = ''
    if self.started:
      print("Simulation has already been started")
    else:
      outputfolder = ('C:\SAP 2000\\' +strftime("%b-%d") + "\\" + 
        strftime("%H_%M_%S") + comment + "\\")
      outputfilename = "tower.sdb"
      self.SapProgram, self.SapModel = commandline.run(model,
        outputfolder + outputfilename)
      self.SapProgram.hide()
      self.started = True

    # Make python structure and start up the colony
    self.Structure = Structure(visualization)
    self.Swarm = SmartSwarm(robots, self.Structure, self.SapProgram)

    # If we started with a previous model, we have to add all of the beams 
    # to our own model in python
    if model != "":
      ret = self.Structure.load_model(self.SapProgram)
      assert ret == 0

    self.folder = outputfolder
Exemple #2
0
class Simulation:
  def __init__(self,seed = None,template="C:\\SAP 2000\\template.sdb"):
    self.SapProgram = None
    self.SapModel = None
    self.Structure = None
    self.Swarm = None
    self.started = False
    self.folder = None
    self.run = False

    # Keeps track of the excel data since we can only write it in one go
    self.excel = {}
    self.excel['headers'] = []
    self.excel['data'] = [[]]

    # Seed the simulation
    self.seed = seed
    random.seed(seed)

    # Stores the template
    self.template = template

  def __setup_general(self):
    '''
    Function to setup the general settigns for the SAP2000 program
    '''
    # switch to default units HERE
    ret = self.SapModel.SetPresentUnits(UNITS[variables.program_units])
    if ret:
      return False

    if not self.__setup_case("DEAD"):
      print("Failure setting up DEAD case.")
      return False

    return True

  def __setup_wind(self,name=variables.wind_case):
    '''
    We initalize the wind based on the information in variables.python
    '''
    # Add loadpattern and case
    if not helpers.addloadpattern(self.SapModel,name,'LTYPE_WIND'):
      return False

    # Make static non-linear
    if not self.__setup_case(name):
      return False

  def __setup_case(self, name):
    # Initialize Non-linear
    ret = self.SapModel.LoadCases.StaticNonlinear.SetCase(name)
    if ret:
      return False
    # Set options (P-delta)
    ret = self.SapModel.LoadCases.StaticNonlinear.SetGeometricNonlinearity(name,
      1)
    if ret:
      return False

    ret,load_types,loads,scales = self.SapModel.LoadCases.StaticNonlinear.SetLoads(
      name,1,["Load"],[name],[1])

    if ret:
      return False

    return True

  def __setup_analysis(self):
    '''
    Funtion to set up the analysis model to the correct values
    '''
    # Set the degrees of Freedom
    DOF = (True,True,True,True,True,True)
    ret, DOF = self.SapModel.Analyze.SetActiveDOF(DOF)
    if ret:
      print("Failure with DOF.")
      return False

    # Set the cases to be analyzed (all cases)
    ret = self.SapModel.Analyze.SetRunCaseFlag("",False,True)
    if ret:
      print("Failure with run flag.")
      return False

    # Set the cases to be analyzed (all cases)
    ret = self.SapModel.Analyze.SetRunCaseFlag(variables.robot_load_case,True,
      False)
    if ret:
      print("Failure with run flag.")
      return False

    # Set the cases to be analyzed (all cases)
    ret = self.SapModel.Analyze.SetRunCaseFlag("DEAD",True,False)
    if ret:
      print("Failure with run flag.")
      return False

    # Set the cases to be analyzed (all cases)
    ret = self.SapModel.Analyze.SetRunCaseFlag("Wind",True,False)
    if ret:
      print("Failure with setting the wind case to be analyzed.")

    # Set Solver Options (Multithreaded, Auto, 64bit, robot_load_case)
    ret = self.SapModel.Analyze.SetSolverOption_1(2,0,False,
      variables.robot_load_case)
    if ret:
      print("Failure with solver options")
      return False

    return True

  def __setup_material(self):
    '''
    Sets up our beam materials
    '''
    # Defining our Scaffold Tube Material Property
    ret, name = self.SapModel.PropMaterial.AddQuick(variables.material_property,
      MATERIAL_TYPES[variables.material_type],
      STEEL_SUBTYPES[variables.material_subtype],PLACEHOLDER,PLACEHOLDER,
      PLACEHOLDER,PLACEHOLDER,PLACEHOLDER,variables.material_property)
    if ret or name != variables.material_property:
      return False

    # Defining the Frame Section. This is the Scaffold Tube
    ret = self.SapModel.PropFrame.SetPipe(variables.frame_property_name,
      variables.material_property,variables.outside_diameter,
      variables.wall_thickness)
    if ret:
      return False

    return True

  def __push_information(self,file_obj):
    '''
    Writes out the data from variables and construction
    '''
    # Pull the names of all the variables and use that to get their attributes 
    # and store them in a list of names, values
    variables_text = 'variables', ([(constant, getattr(variables, constant)) for
     constant in dir(variables) if '__' not in constant and '.' not in constant])
    construction_text = 'construction', ([(constant, getattr(construction,
      constant)) for constant in dir(construction) if '__' not in constant 
      and '.' not in constant])
    
    # Cycle through both modules and store information the data
    data = ''
    for name, file_data in variables_text, construction_text:
      data += 'Data from the file {}.\n\n'.format(name)
      for var_name, value in file_data:
        data += var_name + ' : ' + str(value) + '\n'
      data += '\n\n'

    # Write out the data and you are now done
    file_obj.write(data)

  def __push_data(self,data,file_obj,i):
    '''
    Writes a set of data to a data file in specified format
    '''
    to_write = "Data for Timestep: {}\n\n\n".format(str(i))
    for name, state in data.items():
      to_write += "{} = \n\n".format(name)
      for key, temp_data in state.items():
        to_write += "{} : {}\n".format(str(key),str(temp_data))
      to_write += "\n"
    file_obj.write(to_write + "\n")

  def __add_excel(self,data):
    '''
    Stores timestep data in the simulation
    '''
    timestep = []
    for name, state in data.items():

      # Add names to headers if not already there
      if name not in self.excel['headers']:
        self.excel['headers'].append(name)
        self.excel['headers'].append("{}-height".format(name))
        self.excel['headers'].append("{}-measured moment".format(name))

      # Add the location to a list
      timestep.append(state['location'])
      timestep.append(state['location'][2])
      timestep.append(state['read_moment'])

    # Add the location list to a list of rows
    self.excel['data'].append(timestep)


  def __push_excel(self,file_name):
    '''
    Writes a set of data to an excel file
    '''
    # Open work book
    workbook = Workbook(file_name)
    worksheet = workbook.add_worksheet()

    # start at top left corner and write headers
    row, col = 0, 0
    for header in self.excel['headers']:
      worksheet.write(row,col, str(header))
      col += 1

    # start in second row and write data
    row, col = 1, 0
    for row_data in self.excel['data']:
      for cell_data in row_data:
        worksheet.write(row, col, str(cell_data))
        col += 1
      row += 1
      col = 0

    workbook.close()

    # Empty memory (this usually happens every 4000 timesteps)
    self.excel['header'] = []
    self.excel['data'] = [[]]


  def reset(self, comment = ""):
    '''
    Allows us to reset everything without exiting the SAP program
    '''
    if self.started:
      # Resetting the SAP Program (this saves the previous file)
      self.SapProgram.reset(template=self.template)

      # Creating new SAP Files
      outputfolder = ('C:\SAP 2000\\' +strftime("%b-%d") + "\\" + 
        strftime("%H_%M_%S") + comment + "\\")
      outputfilename = "tower.sdb"
      outputfile = outputfolder + outputfilename

      # Create directory if necessary
      path = os.path.dirname(outputfile)
      helpers.path_exists(path)

      # Save to the new file
      ret = self.SapModel.File.Save(outputfolder + outputfilename)
      assert ret == 0

      # Reset the structure and the swarm
      self.Structure.reset()
      self.Swarm.reset()

      self.folder = outputfolder
      self.run = False

    else:
      print("The simulation is not started. Cannot reset.")

  def start(self, visualization = False, robots = 10, comment = "", 
    model="C:\\SAP 2000\\template.sdb"):
    '''
    This starts up the SAP 2000 Program and hides it. 
      visualization = should we display the simulation as it occurs?
      robots = number of robots in simulation
      comment = a comment attached to the name of the folder
      model = location of a file which contains a starting model
    '''
    outputfolder = ''
    if self.started:
      print("Simulation has already been started")
    else:
      outputfolder = ('C:\SAP 2000\\' +strftime("%b-%d") + "\\" + 
        strftime("%H_%M_%S") + comment + "\\")
      outputfilename = "tower.sdb"
      self.SapProgram, self.SapModel = commandline.run(model,
        outputfolder + outputfilename)
      self.SapProgram.hide()
      self.started = True

    # Make python structure and start up the colony
    self.Structure = Structure(visualization)
    self.Swarm = SmartSwarm(robots, self.Structure, self.SapProgram)

    # If we started with a previous model, we have to add all of the beams 
    # to our own model in python
    if model != "":
      ret = self.Structure.load_model(self.SapProgram)
      assert ret == 0

    self.folder = outputfolder

  def stop(self):
    '''
    This stops the simulation gracefully
    '''
    if self.started:
      ret = self.SapProgram.exit()
      assert ret == 0
      self.started = False
      self.run = False
      self.folder = None
    else:
      print("No simulation started. Use Simulation.Start() to begin.")

  def go(self,visualization = False, robots = 10, timesteps = 10, debug = True, 
    comment = ""):
    '''
    Direct accesss
    '''
    outputfolder = ""
    if not self.started:
      outputfolder = self.start(visualization,robots,comment)
    self.folder = outputfolder
    self.run_simulation(visualization,timesteps,debug,comment)
    self.stop()

    # Run visualization
    self.run_visualization()

  def run_visualization(self,fullscreen=True,inverse_speed=.25):
    '''
    Displays the visualization if an outputfolder exist and the simulation has
    been run.
    '''
    if self.run:
      window = Visualization(self.folder)
      window.load_data()
      window.run(fullscreen,inverse_speed)
    else:
      print("The visualization cannot be started becase simulation has not run.")

  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)

  def exit(self,run_text):

    # Sort beam data
    if self.Structure.structure_data[-1] != []:
      self.Structure.structure_data[-1].sort(key=lambda t: int(t[0]))

    # Finish up run_data (add ending time and maximum height)
    run_data = ("\n\nStop time : " + strftime("%H:%M:%S") + 
      ".\n\n Total beams" + " on structure: " + str(self.Structure.tubes) 
      + ".")
    run_data += "\n\n Maximum height of structure : " +  str(
      self.Structure.height) + "."

    # Write out simulation data
    run_text.write(run_data)

    # Write out locations to excel
    self.__push_excel(self.folder + "locations-end.xlsx")

    # Write out visualization data
    self.visualization_data()

    # Write out structure moments
    self.structure_physics()

    self.run = True

  def visualization_data(self):
    '''
    Writes out the data for the visualization currently stored and clears the
    buffers
    '''
    # Write data
    with open(self.folder + 'structure_color_data.txt','a') as c_struct, open(self.folder + 'swarm_color_data.txt', 'a') as c_swarm, open(self.folder + 'swarm_visualization.txt', 'a') as v_swarm, open(self.folder + 'structure_visualization.txt','a') as v_struct:
      v_swarm.write(self.Swarm.visualization_data)
      c_swarm.write(self.Swarm.color_data)
      v_struct.write(self.Structure.visualization_data)
      c_struct.write(self.Structure.color_data)

    # Clear buffers
    self.Swarm.visualization_data = ''
    self.Swarm.color_data = ''
    self.Structure.visualization_data = ''
    self.Structure.color_data = ''

  def structure_physics(self):
    '''
    Writes out the physical data for the structure and clears the buffer.
    '''
    # Write data
    with open(self.folder + 'structure_physics.txt',"a") as struct_phys:
      for timestep in self.Structure.structure_data:
        for beam,moment in timestep:
          struct_phys.write("{},{},".format(beam,str(moment)))
        struct_phys.write("\n")

    # Clear buffers
    self.Structure.structure_data = []