def __init__(self, threshold, generation_limit, N_pop, mutation_variance, obstacle_courses): # Intialise Class for Genetic Algorithm self.threshold = threshold # Threshold on fitness value self.generation_limit = generation_limit # Number of generations before algorithm ends self.N_pop = N_pop # Population Size self.parents_in_new_gen = 0.25 # Percentage of parents transfered to the new generation self.mutation_variance = mutation_variance # Variance of the normal distribution for mutation # Create Folder name for data storage date_time = str(datetime.datetime.now())[:-10] temp_list = list(date_time) temp_list[10] = '_' self.folder_name = './data/data_' + ''.join(temp_list) if not os.path.exists(self.folder_name): os.makedirs(self.folder_name) # Find the range of angles for the lasers self.angle_ranges = [] for i in range(12): self.angle_ranges.append((np.pi / 6) + i * (np.pi / 6)) self.parameter_limits = [ [0, 3], #z_sat [0, 3], #x_sat [1, 10], #z_lim [1, 10], #x_lim [0, 3], #z_norm [0, 3], #x_norm [0, 1], #z_up [2, 5], #max_vel [0, len(self.angle_ranges) - 1], #angle range choice (index) [2, 20], #number of lasers [1, 5] ] #stabiliser_choice # Find the Range of the parameters self.parameter_ranges = [] for i in range(len(self.parameter_limits)): self.parameter_ranges.append(self.parameter_limits[i][1] - self.parameter_limits[i][0]) # Intialise Population self.population = self.initialisePopulation() self.universal_best_fitness = -100000. # Load in the drone presets self.preset = Presets() self.preset.loadDefault() # Set parameters and courses self.safe_vel = 1. self.obstacle_courses = obstacle_courses self.simulation_time = 30.0 # Load stabiliser controllers self.stabilisers = [] for i in range(5): self.stabilisers.append(self.loadStabiliser(i + 1))
def __init__(self): self.__channel_users = {} self.__user_ids = {} self.__bracket = TourneyTree() self.__last_post = None self.participants = Participants() self.presets = Presets() self.is_joinable = False
def execute_arguments(args): if args.element == 'presets': presets = Presets() presets.display( args.preset_type ) elif args.element == 'servers': slist = ServerList() slist.display() else: print "Invalid argument!" sys.exit(1)
def __init__(self): # Patient/ acquistion information self.name = '' self.modality = '' self.original_orientation = '' self.window = '' self.level = '' # Masks (vtkImageData) self.mask_dict = {} # Surfaces are (vtkPolyData) self.surface_dict = {} self.last_surface_index = -1 # Measurements self.measurement_dict = {} # TODO: Future ++ self.annotation_dict = {} # InVesalius related data # So we can find bugs and reproduce user-related problems self.invesalius_version = version.get_svn_revision() self.presets = Presets() self.threshold_modes = self.presets.thresh_ct self.threshold_range = '' self.raycasting_preset = ''
import numpy as np import time import matplotlib.pyplot as plt import pickle import os from drone import TrainingDrone from environment import Environment, Obstacle, Course from render import Renderer, DataStream from presets import Presets import neat # Load Presets preset = Presets() preset.loadDefault() # Initialise objects drone = TrainingDrone(preset.drone_dict) # Generate obstacles/load empty course course = Course() obstacles = course.emptyCourse() environment = Environment(preset.lasers, obstacles, preset.max_laser_length, preset.safe_vel, preset.safe_angle) # Initialise None lists in environment and drone environment.update(drone, False) drone.recieveLaserDistances(environment.laser_distances)
def __init__(self): wx.Frame.__init__(self, None, -1, DEFAULT_TITLE) self.settings = Settings(cmdFolder) self.materialSize = "" self.CreateStatusBar() self.SetStatusText("") self.images = Images(os.path.join(cmdFolder, "images")) ico = wx.Icon(os.path.join(cmdFolder, "images", "shapeoko.png"), wx.BITMAP_TYPE_PNG) self.SetIcon(ico) self.cnc = None self.material = None self.toolList = None self.pGrid = None self.objListBox = None self.bScrollUp = self.bScrollDown = None self.bMoveUp = self.bMoveDown = None self.fsWidth = self.fsHeight = self.fsThick = None self.bAdd = self.bDel = self.bRender = self.bNew = self.bLoad = self.bSave = self.bSaveAs = None self.setCnc() self.objectTypes = { "Rectangle": Rectangle, "Circle": Circle, "Arc": Arc, "Path": Path, "Polygon": Polygon, "Linear Drill": LinearDrill, "Circular Drill": CircularDrill, "Rectangular Drill": RectangularDrill, "Carve Grid": CarveGrid, "Carve Diamond": CarveDiamond } self.rawObjectTypes = { "Rectangle": Rectangle, "Circle": Circle, "Arc": Arc, "Path": Path, "Polygon": Polygon, "LinearDrill": LinearDrill, "CircularDrill": CircularDrill, "RectangularDrill": RectangularDrill, "CarveGrid": CarveGrid, "CarveDiamond": CarveDiamond } self.presets = Presets(cmdFolder) self.presetList = self.presets.getPresetList() self.fileMenu = None self.setMenu() self.t = 0 self.seq = 1 self.objList = [] self.modified = False self.currentFile = None szLeft = self.listAndButtonSizer() szRight = self.propertySizer() sz = wx.BoxSizer(wx.HORIZONTAL) sz.Add(szLeft) sz.Add(szRight, 1, wx.EXPAND) self.Bind(wx.EVT_CLOSE, self.onClose) self.SetSizer(sz) self.Layout() self.Fit() self.Show() self.msgTimer = 0 self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) self.startTimer()
class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, DEFAULT_TITLE) self.settings = Settings(cmdFolder) self.materialSize = "" self.CreateStatusBar() self.SetStatusText("") self.images = Images(os.path.join(cmdFolder, "images")) ico = wx.Icon(os.path.join(cmdFolder, "images", "shapeoko.png"), wx.BITMAP_TYPE_PNG) self.SetIcon(ico) self.cnc = None self.material = None self.toolList = None self.pGrid = None self.objListBox = None self.bScrollUp = self.bScrollDown = None self.bMoveUp = self.bMoveDown = None self.fsWidth = self.fsHeight = self.fsThick = None self.bAdd = self.bDel = self.bRender = self.bNew = self.bLoad = self.bSave = self.bSaveAs = None self.setCnc() self.objectTypes = { "Rectangle": Rectangle, "Circle": Circle, "Arc": Arc, "Path": Path, "Polygon": Polygon, "Linear Drill": LinearDrill, "Circular Drill": CircularDrill, "Rectangular Drill": RectangularDrill, "Carve Grid": CarveGrid, "Carve Diamond": CarveDiamond } self.rawObjectTypes = { "Rectangle": Rectangle, "Circle": Circle, "Arc": Arc, "Path": Path, "Polygon": Polygon, "LinearDrill": LinearDrill, "CircularDrill": CircularDrill, "RectangularDrill": RectangularDrill, "CarveGrid": CarveGrid, "CarveDiamond": CarveDiamond } self.presets = Presets(cmdFolder) self.presetList = self.presets.getPresetList() self.fileMenu = None self.setMenu() self.t = 0 self.seq = 1 self.objList = [] self.modified = False self.currentFile = None szLeft = self.listAndButtonSizer() szRight = self.propertySizer() sz = wx.BoxSizer(wx.HORIZONTAL) sz.Add(szLeft) sz.Add(szRight, 1, wx.EXPAND) self.Bind(wx.EVT_CLOSE, self.onClose) self.SetSizer(sz) self.Layout() self.Fit() self.Show() self.msgTimer = 0 self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) self.startTimer() def startTimer(self): self.timer.Start(1000) def stopTimer(self): self.timer.Stop() def OnTimer(self, _): if self.msgTimer > 0: self.msgTimer -= 1 if self.msgTimer <= 0: self.SetStatusText("") def setMenu(self): menuBar = wx.MenuBar() menu1 = wx.Menu() menu1.Append(MENU_FILE_NEW, "&New", "Create a new model file") menu1.Append(MENU_FILE_OPEN, "&Open", "Open an existing model file") menu1.Append(MENU_FILE_SAVE, "&Save", "Save the current model") menu1.Append(MENU_FILE_SAVEAS, "Sa&ve as", "Save the current model to a specified file") menu1.AppendSeparator() menu1.Append(MENU_FILE_SAVEEACH, "Save &each object", "Saves each object to a different specified file") menu1.AppendSeparator() menu1.Append(MENU_FILE_RENDER, "&Render", "Render the current model and create a G Code file") menu1.AppendSeparator() menu1.Append(MENU_FILE_EXIT, "E&xit", "Exit the application") menuBar.Append(menu1, "&File") self.fileMenu = menu1 self.fileMenu.Enable(MENU_FILE_SAVE, False) self.fileMenu.Enable(MENU_FILE_SAVEAS, False) self.fileMenu.Enable(MENU_FILE_SAVEEACH, False) self.fileMenu.Enable(MENU_FILE_RENDER, False) menu2 = wx.Menu() addOffset = 0 for ot in list(self.objectTypes.keys()): menu2.Append(MENU_ADD_BASE + addOffset, ot, "Add an object or type %s" % ot) self.Bind(wx.EVT_MENU, lambda evt, text=ot: self.onMenuAddObject(evt, text), id=MENU_ADD_BASE + addOffset) addOffset += 1 presetOffset = 0 presetCatOffset = 0 if len(self.presetList) > 0: menu2.AppendSeparator() presetMenu = wx.Menu() for cat in list(self.presetList.keys()): catMenu = wx.Menu() for lbl in list(self.presetList[cat].keys()): catMenu.Append(MENU_PRESET_BASE + presetOffset, lbl, "Add preset for %s: %s" % (cat, lbl)) self.Bind(wx.EVT_MENU, lambda evt, text=self.presetList[cat][lbl]: self.onMenuAddPreset(evt, text), id=MENU_PRESET_BASE + presetOffset) presetOffset += 1 presetMenu.AppendSubMenu(catMenu, cat) presetCatOffset += 1 menu2.AppendSubMenu(presetMenu, "Preset") menuBar.Append(menu2, "&Add") menu3 = wx.Menu() menu3.Append(MENU_SHAPEOKO_PROPERTIES, "&Properties", "Set shapeoko properties") menuBar.Append(menu3, "&Shapeoko") self.SetMenuBar(menuBar) self.Bind(wx.EVT_MENU, self.onBNew, id=MENU_FILE_NEW) self.Bind(wx.EVT_MENU, self.onBLoad, id=MENU_FILE_OPEN) self.Bind(wx.EVT_MENU, self.onBSave, id=MENU_FILE_SAVE) self.Bind(wx.EVT_MENU, self.onBSaveAs, id=MENU_FILE_SAVEAS) self.Bind(wx.EVT_MENU, self.onSaveEachObject, id=MENU_FILE_SAVEEACH) self.Bind(wx.EVT_MENU, self.onBRender, id=MENU_FILE_RENDER) self.Bind(wx.EVT_MENU, self.onClose, id=MENU_FILE_EXIT) self.Bind(wx.EVT_MENU, self.onShapeokoProperties, id=MENU_SHAPEOKO_PROPERTIES) def setTitle(self): t = DEFAULT_TITLE if self.currentFile is not None: t += " - %s" % self.currentFile if self.modified: t += " *" self.SetTitle(t) def setCnc(self): self.cnc = Shapeoko() self.loadTools() self.cnc.setTool(self.toolList[0]) self.material = Material({}) self.cnc.setMaterial(self.material) def loadTools(self): fn = os.path.join(cmdFolder, 'tools.json') try: with open(fn) as jfp: self.toolList = json.load(jfp) except (FileNotFoundError, PermissionError): print("Unable to open tools json file \"%s\"" % fn) self.toolList = [] return def setModified(self, flag=True): self.modified = flag self.bSave.Enable(flag) self.bSaveAs.Enable(len(self.objList) > 0) self.fileMenu.Enable(MENU_FILE_SAVE, flag) self.fileMenu.Enable(MENU_FILE_SAVEAS, flag) self.fileMenu.Enable(MENU_FILE_SAVEEACH, flag) self.setTitle() def warnIfModified(self): if not self.modified: return True dlg = wx.MessageDialog(self, 'Are you sure you want to continue?', 'Discard Changes?', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) rc = dlg.ShowModal() dlg.Destroy() if rc == wx.ID_NO: return False return True def message(self, text, duration=10): self.SetStatusText(text) self.msgTimer = duration def propertySizer(self): sz = wx.BoxSizer(wx.HORIZONTAL) sz.AddSpacer(20) self.pGrid = PropertiesGrid(self, self.images) sz.Add(self.pGrid, 1, wx.EXPAND) sz.AddSpacer(20) szProp = wx.BoxSizer(wx.VERTICAL) szProp.AddSpacer(20) szProp.Add(sz, 1, wx.EXPAND) szProp.AddSpacer(20) return szProp def listAndButtonSizer(self): sz = wx.BoxSizer(wx.VERTICAL) sz.AddSpacer(20) sz.Add(wx.StaticText(self, wx.ID_ANY, "Object List:")) hsz = wx.BoxSizer(wx.HORIZONTAL) self.objListBox = wx.ListBox(self, wx.ID_ANY, size=(200, 200)) self.Bind(wx.EVT_LISTBOX, self.onLbProp, self.objListBox) hsz.Add(self.objListBox, 1, wx.ALIGN_CENTER_HORIZONTAL) hsz.AddSpacer(10) vsz = wx.BoxSizer(wx.VERTICAL) bhsz = wx.BoxSizer(wx.HORIZONTAL) self.bScrollUp = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("scrollup"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBScrollUp, self.bScrollUp) self.bScrollUp.SetToolTip("Move the selection cursor up 1 line") self.bScrollUp.Enable(False) bhsz.Add(self.bScrollUp) bhsz.AddSpacer(20) self.bMoveUp = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("moveup"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBMoveUp, self.bMoveUp) self.bMoveUp.SetToolTip("Move the selected object up 1 line") self.bMoveUp.Enable(False) bhsz.Add(self.bMoveUp) vsz.Add(bhsz) vsz.AddSpacer(20) bhsz = wx.BoxSizer(wx.HORIZONTAL) self.bScrollDown = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("scrolldown"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBScrollDown, self.bScrollDown) self.bScrollDown.SetToolTip("Move the selection cursor down 1 line") self.bScrollDown.Enable(False) bhsz.Add(self.bScrollDown) bhsz.AddSpacer(20) self.bMoveDown = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("movedown"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBMoveDown, self.bMoveDown) self.bMoveDown.SetToolTip("Move the selected object down 1 line") self.bMoveDown.Enable(False) bhsz.Add(self.bMoveDown) vsz.Add(bhsz) hsz.Add(vsz) sz.Add(hsz) sz.AddSpacer(10) vsz = wx.BoxSizer(wx.VERTICAL) vsz.AddSpacer(5) box = wx.StaticBox(self, wx.ID_ANY, " Material Dimensions ") vbsizer = wx.StaticBoxSizer(box, wx.VERTICAL) bsizer = wx.BoxSizer(wx.HORIZONTAL) bsizer.AddSpacer(SBMARGIN) bsizer.Add(wx.StaticText(self, wx.ID_ANY, "Wd:"), 0, wx.TOP, 9) self.fsWidth = FS.FloatSpin(self, wx.ID_ANY, size=SPDIM, min_val=0, max_val=400, increment=0.1, value=self.material.getWidth(), agwStyle=FS.FS_RIGHT) self.fsWidth.SetFormat("%f") self.fsWidth.SetDigits(1) bsizer.Add(self.fsWidth, 0, wx.TOP+wx.BOTTOM, 5) self.fsWidth.Bind(FS.EVT_FLOATSPIN, self.onFSMaterialWidth) bsizer.AddSpacer(SBMARGIN) bsizer.Add(wx.StaticText(self, wx.ID_ANY, "Ht:"), 0, wx.TOP, 9) self.fsHeight = FS.FloatSpin(self, wx.ID_ANY, size=SPDIM, min_val=0, max_val=400, increment=0.1, value=self.material.getHeight(), agwStyle=FS.FS_RIGHT) self.fsHeight.SetFormat("%f") self.fsHeight.SetDigits(1) bsizer.Add(self.fsHeight, 0, wx.TOP+wx.BOTTOM, 5) self.fsHeight.Bind(FS.EVT_FLOATSPIN, self.onFSMaterialHeight) bsizer.AddSpacer(SBMARGIN) bsizer.Add(wx.StaticText(self, wx.ID_ANY, "Thk:"), 0, wx.TOP, 9) self.fsThick = FS.FloatSpin(self, wx.ID_ANY, size=SPDIM, min_val=0, max_val=50, increment=0.1, value=self.material.getThickness(), agwStyle=FS.FS_RIGHT) self.fsThick.SetFormat("%f") self.fsThick.SetDigits(1) bsizer.Add(self.fsThick, 0, wx.TOP+wx.BOTTOM, 5) self.fsThick.Bind(FS.EVT_FLOATSPIN, self.onFSMaterialThick) bsizer.AddSpacer(SBMARGIN) vbsizer.AddSpacer(SBMARGIN) vbsizer.Add(bsizer) vbsizer.AddSpacer(SBMARGIN) vsz.Add(vbsizer) sz.Add(vsz) sz.AddSpacer(10) bsz = wx.BoxSizer(wx.HORIZONTAL) self.bAdd = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("add"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBAdd, self.bAdd) self.bAdd.SetToolTip("Add a new object to the bottom of the list") bsz.Add(self.bAdd) bsz.AddSpacer(10) self.bDel = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("delete"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBDel, self.bDel) self.bDel.SetToolTip("Delete the selected object") self.bDel.Enable(False) bsz.Add(self.bDel) bsz.AddSpacer(10) self.bRender = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("render"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBRender, self.bRender) self.bRender.SetToolTip("Render the G Code and save to file") self.bRender.Enable(False) bsz.Add(self.bRender) bsz.AddSpacer(10) self.bNew = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("new"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBNew, self.bNew) self.bNew.SetToolTip("Create a new empty model") bsz.Add(self.bNew) bsz.AddSpacer(10) self.bLoad = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("open"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBLoad, self.bLoad) self.bLoad.SetToolTip("Load a model from file") bsz.Add(self.bLoad) bsz.AddSpacer(10) self.bSave = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("save"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBSave, self.bSave) self.bSave.SetToolTip("Save the model to the current file") self.bSave.Enable(False) bsz.Add(self.bSave) bsz.AddSpacer(10) self.bSaveAs = wx.BitmapButton(self, wx.ID_ANY, self.images.getByName("saveas"), size=BTNDIM) self.Bind(wx.EVT_BUTTON, self.onBSaveAs, self.bSaveAs) self.bSaveAs.SetToolTip("Save the model to a named file") self.bSaveAs.Enable(False) bsz.Add(self.bSaveAs) sz.AddSpacer(10) sz.Add(bsz, 0, wx.ALIGN_CENTER_HORIZONTAL) sz.AddSpacer(20) hsz = wx.BoxSizer(wx.HORIZONTAL) hsz.AddSpacer(20) hsz.Add(sz) return hsz def onLbProp(self, _): self.showObjectProperties() self.updateScrollButtons() def showObjectProperties(self): ox = self.objListBox.GetSelection() if ox == wx.NOT_FOUND: self.pGrid.clearProperties() else: self.pGrid.setProperties(self.objList[ox]) def onClose(self, _): if not self.warnIfModified(): return self.Destroy() def onBScrollUp(self, _): ox = self.objListBox.GetSelection() self.objListBox.SetSelection(ox-1) self.showObjectProperties() self.updateScrollButtons() def onBScrollDown(self, _): ox = self.objListBox.GetSelection() self.objListBox.SetSelection(ox+1) self.showObjectProperties() self.updateScrollButtons() def onBMoveUp(self, _): ox = self.objListBox.GetSelection() sobj = self.objList[ox] self.objList[ox] = self.objList[ox-1] self.objList[ox-1] = sobj self.rebuildObjectListBox() self.objListBox.SetSelection(ox-1) self.updateScrollButtons() def onBMoveDown(self, _): ox = self.objListBox.GetSelection() sobj = self.objList[ox] self.objList[ox] = self.objList[ox+1] self.objList[ox+1] = sobj self.rebuildObjectListBox() self.objListBox.SetSelection(ox+1) self.updateScrollButtons() def updateScrollButtons(self): l = len(self.objList) ox = self.objListBox.GetSelection() if l <= 1 or ox == wx.NOT_FOUND: self.bScrollUp.Enable(False) self.bScrollDown.Enable(False) self.bMoveUp.Enable(False) self.bMoveDown.Enable(False) return self.bScrollUp.Enable(not(ox == 0)) self.bMoveUp.Enable(not(ox == 0)) self.bScrollDown.Enable(not (ox == (l-1))) self.bMoveDown.Enable(not (ox == (l-1))) def onMenuAddObject(self, _, objType): self.doObjectAddType(objType) def onMenuAddPreset(self, _, fn): path = os.path.join(cmdFolder, "presets", fn) try: with open(path, 'r') as f: j = json.load(f) obj = self.makeCncObject(j) self.doObjectAdd(obj) except IOError: self.message("Cannot read preset file '%s'." % path) def onFSMaterialWidth(self, _): nw = self.fsWidth.GetValue() self.material.setWidth(nw) def onFSMaterialHeight(self, _): nh = self.fsHeight.GetValue() self.material.setHeight(nh) def onFSMaterialThick(self, _): nt = self.fsThick.GetValue() self.material.setThickness(nt) def onBAdd(self, _): dlg = wx.SingleChoiceDialog( self, 'Choose the type of object to add', 'Add New Object', list(self.objectTypes.keys()), wx.OK | wx.CANCEL ) rc = dlg.ShowModal() objType = None if rc == wx.ID_OK: objType = dlg.GetStringSelection() dlg.Destroy() if rc != wx.ID_OK: return self.doObjectAddType(objType) def doObjectAddType(self, objType): obj = self.objectTypes[objType](self, {}) el = obj.getErrors() if not el is None: for e in el: print(e) self.doObjectAdd(obj) def doObjectAdd(self, obj): self.setModified() self.pGrid.setProperties(obj) self.objListBox.Append(obj.getTitle()) self.objList.append(obj) self.objListBox.SetSelection(len(self.objList)-1) self.bDel.Enable(True) self.bRender.Enable(True) self.fileMenu.Enable(MENU_FILE_RENDER, True) self.updateScrollButtons() def updateLabel(self): ox = self.objListBox.GetSelection() if ox == wx.NOT_FOUND: return self.rebuildObjectListBox() def rebuildObjectListBox(self): self.objListBox.Clear() for obj in self.objList: self.objListBox.Append(obj.getTitle()) def onBDel(self, _): ox = self.objListBox.GetSelection() if ox == wx.NOT_FOUND: return ot = self.objList[ox].getTitle() dlg = wx.MessageDialog(self, "Are you sure you want to delete\n\n \"%s\"?" % ot, 'Confirm Object Deletion', wx.ICON_QUESTION | wx.YES_NO ) rc = dlg.ShowModal() dlg.Destroy() if rc != wx.ID_YES: return self.setModified() del(self.objList[ox]) self.rebuildObjectListBox() if ox >= len(self.objList): ox = len(self.objList)-1 if ox >= 0: self.objListBox.SetSelection(ox) else: self.bDel.Enable(False) self.bSave.Enable(False) self.bSaveAs.Enable(False) self.bRender.Enable(False) self.fileMenu.Enable(MENU_FILE_SAVE, False) self.fileMenu.Enable(MENU_FILE_SAVEAS, False) self.fileMenu.Enable(MENU_FILE_SAVEEACH, False) self.fileMenu.Enable(MENU_FILE_RENDER, False) self.showObjectProperties() self.updateScrollButtons() def onBRender(self, _): dlg = RenderDlg(self, self.objList, self.cnc, self.toolList, self.images, self.settings) dlg.ShowModal() dlg.Destroy() def onBSave(self, evt): if self.currentFile is None: return self.onBSaveAs(evt) self.saveFile(self.currentFile) def saveFile(self, fn): j = [o.toJson() for o in self.objList] j.append(self.material.toJson()) try: with open(fn, 'w') as f: f.write(json.dumps(j, indent=2)) self.message("Model saved to file '%s'" % fn) except IOError: self.message("Cannot write current model file '%s'." % fn) self.setModified(False) def onBSaveAs(self, _): skey = "modeldir" sdir = self.settings.setting(skey) with wx.FileDialog(self, "Save Model file", wildcard="JSON files (*.json)|*.json", defaultDir=sdir, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog: if fileDialog.ShowModal() == wx.ID_CANCEL: return # the user changed their mind self.currentFile = fileDialog.GetPath() ndir = os.path.dirname(self.currentFile) if ndir != sdir: self.settings.setSetting(skey, ndir) self.saveFile(self.currentFile) def onSaveEachObject(self, _): skey = "objectdir" sdir = self.settings.setting(skey) for o in self.objList: lbl = o.getLabel() with wx.FileDialog(self, "Save Object '%s' to file" % lbl, wildcard="JSON files (*.json)|*.json", defaultDir = sdir, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog: if fileDialog.ShowModal() == wx.ID_CANCEL: continue # the user changed their mind # save the current object in the file fn = fileDialog.GetPath() ndir = os.path.dirname(fn) if ndir != sdir: self.settings.setSetting(skey, ndir) j = o.toJson() try: with open(fn, 'w') as f: f.write(json.dumps(j, indent=2)) self.message("Object '%s' saved to file '%s'" % (lbl, fn)) except IOError: self.message("Cannot write current object '%s' to file '%s'." % (lbl, fn)) def onBLoad(self, evt): if not self.warnIfModified(): return skey = "modeldir" sdir = self.settings.setting(skey) with wx.FileDialog(self, "Open Model file", wildcard="JSON files (*.json)|*.json", defaultDir=sdir, style=wx.FD_OPEN) as fileDialog: if fileDialog.ShowModal() == wx.ID_CANCEL: return # the user changed their mind # load the current contents in the file fn = fileDialog.GetPath() ndir = os.path.dirname(fn) if ndir != sdir: self.settings.setSetting(skey, ndir) try: with open(fn, 'r') as f: j = json.load(f) self.currentFile = fn except IOError: self.message("Cannot read from input model file '%s'." % fn) return self.onBNew(evt) self.objList = [] self.objListBox.Clear() for o in j: obj = self.makeCncObject(o) if obj is None: continue self.pGrid.setProperties(obj) self.objListBox.Append(obj.getTitle()) self.objList.append(obj) self.objListBox.SetSelection(len(self.objList)-1) if len(self.objList) > 0: self.bDel.Enable(True) else: self.bDel.Enable(False) self.bRender.Enable(True) self.fileMenu.Enable(MENU_FILE_RENDER, False) self.updateScrollButtons() self.setModified(False) def makeCncObject(self, o): k = list(o.keys())[0] params = o[k] if k == "Material": self.material = Material(params) self.fsWidth.SetValue(self.material.getWidth()) self.fsHeight.SetValue(self.material.getHeight()) self.fsThick.SetValue(self.material.getThickness()) self.cnc.setMaterial(self.material) return None if k not in self.rawObjectTypes.keys(): print("Unknown object type: (%s)" % k) return None obj = self.rawObjectTypes[k](self, params) el = obj.getErrors() if not el is None: print("errors in makecncobject") for e in el: print(e) return obj def onBNew(self, _): if not self.warnIfModified(): return self.objList = [] self.objListBox.Clear() self.pGrid.clearProperties() self.currentFile = None self.updateScrollButtons() self.setModified(False) def onShapeokoProperties(self, _): dlg = ShapeokoDlg(self, self.cnc, self.images) dlg.ShowModal() dlg.Destroy()
import numpy as np import time import matplotlib.pyplot as plt import pickle import os import random from drone import TrainingDrone from environment import Environment, Obstacle, Course from presets import Presets import neat # Load Presets preset = Presets() preset.loadDefault() def loadStabiliser(N): # Load stabiliser network local_dir = os.path.dirname(__file__) folder_paths = [ 'first_stabiliser', 'second_stabiliser', 'third_stabiliser', 'fourth_stabiliser', 'fifth_stabiliser' ] with open(folder_paths[N - 1] + '/winner', 'rb') as f: stabiliser = pickle.load(f) config_path_stabilise = os.path.join( local_dir, folder_paths[N - 1] + '/config-nn')
class Tourney: ''' This class provides methods to manage the tournament tree bracket. ''' def __init__(self): self.__channel_users = {} self.__user_ids = {} self.__bracket = TourneyTree() self.__last_post = None self.participants = Participants() self.presets = Presets() self.is_joinable = False def set_last_post(self, last_post): self.__last_post = last_post def get_last_post(self): return self.__last_post def add_channel_user(self, player): self.__channel_users[player.get_user()] = player self.__user_ids[player.get_handle()] = player.get_user() # def remove_channel_user(self, player_id): # player = self.__channel_users[player_id] # user_id = player.get_user() # handle =player.get_handle() # del self.__channel_users[user_id] # del self.__user_ids[handle] def singles(self): self.__last_post = None number_of_slots = 0 number_of_presets = len(self.presets.get_all()) is_random = number_of_presets == 0 if is_random: if self.is_joinable: number_of_slots = len(self.participants.get_handles()) else: number_of_slots = len(self.__channel_users) else: number_of_slots = number_of_presets if number_of_slots < 2: return "There are not enough players." response = "" team = None slots = [] if is_random: users = {} if self.is_joinable: for participant in self.participants.get_handles(): user_id = self.__user_ids[participant] users[user_id] = participant else: users = self.__channel_users for key in users: del(team) team = PlayerTeam() team.add_player(self.__channel_users[key]) slots.append(team) response = "Singles bracket randomly generated." else: for handle in self.presets.get_all(): if handle == "-bye-": del(team) team = PlayerTeam() slots.append(team) else: del(team) team = PlayerTeam() user_id = self.__user_ids[handle] player = self.__channel_users[user_id] team.add_player(player) slots.append(team) slots = self.__get_order_preset(slots) response = "Singles bracket generated from presets." self.__bracket.generate(slots, is_random) return response def doubles(self, user): self.__last_post = None number_of_slots = 0 number_of_presets = len(self.presets.get_all()) is_random = number_of_presets == 0 if is_random: number_of_players = len(self.__channel_users) number_of_slots = number_of_players / 2 else: number_of_players = number_of_presets number_of_slots = number_of_players / 2 is_odd = number_of_players % 2 == 1 if number_of_slots < 2: return "There are not enough players." if is_odd and is_preset: return "There is an odd number of presets." response = "" team = None slots = [] i = 0 if is_random: players = [] if self.is_joinable: users = {} for participant in self.participants.get_handles(): user_id = self.__user_ids[participant] users[user_id] = participant for key in users: if not is_odd or key != user: players.append(self.__channel_users[key]) else: for key in self.__channel_users: if not is_odd or key != user: players.append(self.__channel_users[key]) for x in range(len(players)): rand_int = random.choice(range(len(players))) random_player = players[rand_int] del players[rand_int] if i % 2 == 0: del(team) team = PlayerTeam() team.add_player(random_player) else: team.add_player(random_player) slots.append(team) i += 1 response = "Doubles bracket randomly generated." else: for handle in self.presets.get_all(): user_id = self.__user_ids[handle] player = self.__channel_users[user_id] if handle == "-bye-": del(team) team = PlayerTeam() slots.append(team) elif player.get_handle() == handle: if i % 2 == 0: del(team) team = PlayerTeam() team.add_player(player) else: team.add_player(player) slots.append(team) i += 1 slots = self.__get_order_preset(slots) response = "Doubles bracket generated from presets." self.__bracket.generate(slots, is_random) return response def reset(self, handle): ''' ''' response = "" if handle in self.__user_ids: user_id = self.__user_ids[handle] player = self.__channel_users[user_id] games = self.__bracket.get_round_matches() match = games[player.get_match_id()] response = match.reset_game(user_id) if response == "": response = "Player not found in tournament." return response def next(self): ''' Advance the bracket to the next round if all the games are complete. ''' response = "" games = self.__bracket.get_round_matches() if len(games) == 0: response = "The tournament has not started." elif self.is_round_complete(): self.__last_post = None response = self.__bracket.advance() else: response = "The matches are not all complete." return response def help(self, key): # call the readmedocs app pass def win(self, user): ''' Report a win if the game is not already complete and also check for a champion. ''' games = self.__bracket.get_round_matches() if len(games) == 0: return "The tournament has not started." if user == None or user not in self.__channel_users: return "Player not found in tournament." response = "" player = self.__channel_users[user] match_id = player.get_match_id() if match_id != None: match = games[match_id] response = match.add_win(user) else: response = "Player is not in the tournament." return response def loss(self, user): ''' Report a loss if the game is not already complete ''' games = self.__bracket.get_round_matches() if len(games) == 0: return "The tournament has not started." if user == None or user not in self.__channel_users: return "Player not found in tournament." response = "" player = self.__channel_users[user] match_id = player.get_match_id() if match_id != None: match = games[match_id] response = match.add_loss(user) else: response = "Player is not in the tournament." return response def clear_users(self): self.__channel_users.clear() self.__user_ids.clear() return "Players have been cleared." def destroy(self): self.clear_users() self.__bracket.destroy() self.__last_post = None self.participants.clear_users() self.presets.clear_users() self.is_joinable = False return "Games have been destroyed" def __get_order_preset(self, presets): ''' Flip everyother postion in the list to feed it to tree generator. ''' response = presets size = len(response) i = 0 j = 1 while j < size: response[i], response[j] = response[j], response[i] i += 2 j += 2 response.reverse() return response def get_printed(self): ''' Loop through the list and print each game. ''' games = self.__bracket.get_round_matches() string = "" number_of_games = len(games) if number_of_games == 0: return "The tournament has not started." champion = False if number_of_games == 1 and self.is_round_complete(): champion = True champ = "" for match in games: if champion: winner = match.get_winner() name = winner.get_player_names() if name == "": name = winner.get_handle() if winner.is_single_player(): champ = "\n" + name + " is the tournament champion!\n" else: champ = "\n" + name + " are the tournament champions!\n" champ += "Grand Prize: :tada: :champagne: :cookie:\n" match_number = match.get_match_number() if number_of_games == 1: if champion: string = "%s\n*Match: %d* _Finals_ :trophy:\n" % (string, match_number) else: string = "%s\n*Match: %d* _Finals_ :trophy:\n" % (string, match_number) else: string = "%s\n*Match: %d*\n" % (string, match_number) string = "%s%s\n" % (string, match.get_score()) return champ + string def is_round_complete(self): ''' Check if all the matches in the current round are complete. ''' response = True games = self.__bracket.get_round_matches() for match in games: if match.is_complete() == False: response = False return response def add_participant(self, user_id): response = "" if user_id in self.__channel_users: player = self.__channel_users[user_id] response = self.participants.add_user(player.get_handle(), self.get_channel_users()) else: response = "Player not found." return response def boot_participant(self, user_id): response = "" if user_id in self.__channel_users: player = self.__channel_users[user_id] response = self.participants.boot_user(player.get_handle(), self.get_channel_users()) else: response = "Player not found." return response def list_players(self): number_of_players = self.participants.get_count() response = "\n*Registered Players ({})*:\n".format(number_of_players) if number_of_players == 0: response += "None" for handle in self.participants.get_handles(): user_id = self.__user_ids[handle] player = self.__channel_users[user_id] response += player.get_handle_and_name() + "\n" return response def get_user(self, user_id): response = None user_upper = user_id.upper() if user_upper in self.__channel_users: response = self.__channel_users[user_upper] return response def get_user_id(self, handle): response = None if handle in self.__user_ids: response = self.__user_ids[handle] return response def get_channel_users(self): users = [] for user_id in self.__channel_users: users.append(self.__channel_users[user_id]) return users # To-Do: May not need this after creating messanger app, can get matches from db def get_round_matches(self): return self.__bracket.get_round_matches()
class GeneticAlgorithm(object): def __init__(self, threshold, generation_limit, N_pop, mutation_variance, obstacle_courses): # Intialise Class for Genetic Algorithm self.threshold = threshold # Threshold on fitness value self.generation_limit = generation_limit # Number of generations before algorithm ends self.N_pop = N_pop # Population Size self.parents_in_new_gen = 0.25 # Percentage of parents transfered to the new generation self.mutation_variance = mutation_variance # Variance of the normal distribution for mutation # Create Folder name for data storage date_time = str(datetime.datetime.now())[:-10] temp_list = list(date_time) temp_list[10] = '_' self.folder_name = './data/data_' + ''.join(temp_list) if not os.path.exists(self.folder_name): os.makedirs(self.folder_name) # Find the range of angles for the lasers self.angle_ranges = [] for i in range(12): self.angle_ranges.append((np.pi / 6) + i * (np.pi / 6)) self.parameter_limits = [ [0, 3], #z_sat [0, 3], #x_sat [1, 10], #z_lim [1, 10], #x_lim [0, 3], #z_norm [0, 3], #x_norm [0, 1], #z_up [2, 5], #max_vel [0, len(self.angle_ranges) - 1], #angle range choice (index) [2, 20], #number of lasers [1, 5] ] #stabiliser_choice # Find the Range of the parameters self.parameter_ranges = [] for i in range(len(self.parameter_limits)): self.parameter_ranges.append(self.parameter_limits[i][1] - self.parameter_limits[i][0]) # Intialise Population self.population = self.initialisePopulation() self.universal_best_fitness = -100000. # Load in the drone presets self.preset = Presets() self.preset.loadDefault() # Set parameters and courses self.safe_vel = 1. self.obstacle_courses = obstacle_courses self.simulation_time = 30.0 # Load stabiliser controllers self.stabilisers = [] for i in range(5): self.stabilisers.append(self.loadStabiliser(i + 1)) def initialisePopulation(self): # Intialise the population of genomes randomly population = [] for _ in range(self.N_pop): genome = [] for i in range(len(self.parameter_limits)): if i <= 7: genome.append( random.uniform(self.parameter_limits[i][0], self.parameter_limits[i][1])) else: genome.append( random.randint(self.parameter_limits[i][0], self.parameter_limits[i][1])) population.append(genome) return population def decodeGenome(self, genome): # Given the genome create the genome, environment and stabiliser objects # Drone preset_copy = self.preset preset_copy.drone_dict["laser_range"] = self.angle_ranges[genome[8]] preset_copy.drone_dict["lasers"] = genome[9] drone = AvoiderDrone(preset_copy.drone_dict, genome[0], genome[1], genome[2], genome[3], genome[4], genome[5], genome[6], self.safe_vel, genome[7]) # Environment # Load with first obstacle course environment = Environment(genome[9], self.obstacle_courses[0], preset_copy.max_laser_length, self.safe_vel, preset_copy.safe_angle) # Stabiliser stabiliser = self.stabilisers[genome[10] - 1] return drone, environment, stabiliser, preset_copy def crossover(self): # Crossover genomes in the current population and select genomes to transfer to next genome pool # Find child population crossover_population = [] # Normalise the fitnesses normalised_fitnesses = self.normaliseFitness() for _ in range( int(len(self.population) * (1 - self.parents_in_new_gen))): # Select Parent based on fitness parent_1, parent_2 = np.random.choice(len(self.population), 2, replace=False, p=normalised_fitnesses) # Find the relative fitnesses of the two parents parent_1_proportion = normalised_fitnesses[parent_1] / ( normalised_fitnesses[parent_1] + normalised_fitnesses[parent_2]) assert (parent_1_proportion < 1. and parent_1_proportion > 0.) # Get the genomes of the parents parent_1 = self.population[parent_1] parent_2 = self.population[parent_2] child = [] # Use averages to find the resultant genome of the chile and add to crossover population for i in range(len(parent_1)): if i <= 7: # all the continuous variables child.append(parent_1[i] * parent_1_proportion + parent_2[i] * (1 - parent_1_proportion)) else: #integer variables child.append( round(parent_1[i] * parent_1_proportion + parent_2[i] * (1 - parent_1_proportion))) crossover_population.append(child) # Add previous generation to new generation parents_to_new = np.random.choice( len(self.population), int(len(self.population) * self.parents_in_new_gen) - 1, replace=False, p=normalised_fitnesses) for idx in parents_to_new: crossover_population.append(self.population[idx]) return crossover_population def mutation(self, population): # Mutate crossover population using normal distribution mutated_population = [] p_range = 0.25 # percentage of the range that the first standard deviation represents # For every genome for n in range(len(population)): genome = population[n] # For every genome type for i in range(len(genome)): if i <= 7: # all the continuous variables new_value = genome[i] + p_range * ( self.parameter_ranges[i] / 2) * np.random.normal(scale=self.mutation_variance) while (new_value < self.parameter_limits[i][0]) or ( new_value > self.parameter_limits[i][1] ): # If not in parameter limits redo mutation new_value = genome[i] + p_range * ( self.parameter_ranges[i] / 2) * np.random.normal(scale=self.mutation_variance) genome[i] = float(new_value) else: # integer variables new_value = round( genome[i] + p_range * (self.parameter_ranges[i] / 2) * np.random.normal(scale=self.mutation_variance)) while (new_value < self.parameter_limits[i][0]) or ( new_value > self.parameter_limits[i][1]): new_value = round( genome[i] + p_range * (self.parameter_ranges[i] / 2) * np.random.normal(scale=self.mutation_variance)) genome[i] = int(new_value) mutated_population.append(genome) return mutated_population def normaliseFitness(self): # Normalise the fitnesses to rank genomes original_fitnesses = np.array(self.cummu_fitnesses) original_fitnesses -= np.min(original_fitnesses) if sum(original_fitnesses) == 0.: # If all the same return list of uniform probability return [1 / len(original_fitnesses)] * len(original_fitnesses) original_fitnesses += 0.0001 # To avoid probability of 0 normalised_fitnesses = original_fitnesses / np.sum(original_fitnesses) if sum( normalised_fitnesses > 0. ) == 1: # If there is only 1 one and all other zeros then just mix everything up anyways return [1 / len(original_fitnesses)] * len(original_fitnesses) return list(normalised_fitnesses) def newGeneration(self): print("\n Producing New Generation") print("\n Performing Crossover") crossover_population = self.crossover() print("\n Performing Mutation") new_population = self.mutation(crossover_population) new_population.append(self.readBestGenome()) # Add best genome to population to avoid losing knowledge print("Last Genome: " + str(new_population[-1])) print(len(new_population)) return new_population def run(self): # Run the main algorithm self.generation_count = 0 while self.generation_count <= self.generation_limit: print("Running Generation " + str(self.generation_count)) print("----------------------------------------------") self.fitnesses = [] self.cummu_fitnesses = [] start = time.time() pool = multiprocessing.Pool(multiprocessing.cpu_count()) # Run simulations in parallel self.fitnesses = pool.map(self.runOneGenome, self.population.copy()) # Seperate the fitness scores from all the fitness information for i in range(len(self.fitnesses)): self.cummu_fitnesses.append(self.fitnesses[i][0]) # Write data for generation to file self.writeData(self.population.copy(), self.fitnesses.copy()) # If best genome so far store it! if max(self.cummu_fitnesses) > self.universal_best_fitness: print("CHANGING BEST RUN") self.universal_best_generation = self.generation_count self.universal_best_fitness = max(self.cummu_fitnesses) self.writeBestGenome( self.population[self.cummu_fitnesses.index( max(self.cummu_fitnesses))]) print("Best Historical fitness: " + str(self.universal_best_fitness)) print("Best Historical Genome: " + str(self.readBestGenome())) assert (self.runOneGenome( self.readBestGenome())[0] == self.universal_best_fitness) print("Best Fitness is: " + str(max(self.cummu_fitnesses))) print("Average Fitness is: " + str(sum(self.cummu_fitnesses) / len(self.cummu_fitnesses))) if max(self.cummu_fitnesses) >= self.threshold: print("Achieved Threshold Fitness Value!") self.closeAlgorithm() break self.generation_count += 1 # Generate new population self.population = self.newGeneration() print("Time Taken: " + str(time.time() - start)) # If loop done but not reached best fitness if self.universal_best_fitness < self.threshold: print("Reached Maximum ammount of Generations!") self.closeAlgorithm() def runOneGenome(self, genome): # Decode Genome drone, environment, stabiliser, preset_copy = self.decodeGenome(genome) fitnesses = [] information = [] # For each obstacle course for c in range(len(self.obstacle_courses)): # Reset all object parameters for new run environment.resetEnv(self.obstacle_courses[c]) drone.resetParams(preset_copy.drone_dict) environment.update(drone, False) drone.recieveLaserDistances(environment.laser_distances) collision = False total_t = 0 # Run simulation of course while not collision and total_t < self.simulation_time: delta_z_dot, delta_x_dot = drone.findDeltaVelocities() # create list of inputs # Convert theta to positive-negative representation about positive x-axis theta_raw = drone.theta_pos if theta_raw < np.pi: theta_input = theta_raw else: theta_input = theta_raw - 2 * np.pi inputs_stabilise = [ drone.vel[0][0] + delta_x_dot, drone.vel[1][0] + delta_z_dot, theta_input, drone.theta_vel ] # inputs are laser lengths + state information # Input to the stabiliser network action = stabiliser.activate(inputs_stabilise) # Simulate drone dynamics and laser calculations drone.update(action[0] * drone.input_limit, action[1] * drone.input_limit) # Check that drone has not left the course if abs(drone.pos[0][0]) > 10.: environment.fitness -= 2000 break # Update Dynamics, Environment and Fitness environment.update(drone, False) drone.recieveLaserDistances(environment.laser_distances) # Update time and check for any collisions total_t += self.preset.dt collision = environment.collision or environment.touchdown # Penalise z position environment.fitness -= 16 * drone.pos[1][0] fitnesses.append(environment.fitness) # Form list of relavent information (fitness, energy, z_pos, z_vel, theta) at the end of the run information.append([ environment.fitness, environment.energy, drone.pos[1][0], drone.vel[1][0], drone.theta_pos ]) # Return the worse fitness information min_fitness = min(fitnesses) idx = fitnesses.index(min_fitness) return information[idx] def loadStabiliser(self, N): # Load stabiliser network from folder local_dir = os.path.dirname(__file__) folder_paths = [ 'first_stabiliser', 'second_stabiliser', 'third_stabiliser', 'fourth_stabiliser', 'fifth_stabiliser' ] with open(folder_paths[N - 1] + '/winner', 'rb') as f: stabiliser = pickle.load(f) config_path_stabilise = os.path.join( local_dir, folder_paths[N - 1] + '/config-nn') config_stabilise = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path_stabilise) return neat.nn.FeedForwardNetwork.create(stabiliser, config_stabilise) def writeData(self, population, fitnesses): # Write generation data to file # Convert information to numpy arrays pop_np = np.array(population) fit_np = np.array(fitnesses) # Concatenate array and save as txt file full_array = np.concatenate((pop_np, fit_np), axis=1) np.savetxt( self.folder_name + '/generation_' + str(self.generation_count) + '.txt', full_array) def writeBestGenome(self, genome): # Update the file containting the best genome in array format gen_np = np.array(genome.copy()) np.savetxt(self.folder_name + '/best_genome.txt', gen_np) def readBestGenome(self): # Read genome array from txt file return_list = list(np.loadtxt(self.folder_name + '/best_genome.txt')) return_list[8] = int(return_list[8]) return_list[9] = int(return_list[9]) return_list[10] = int(return_list[10]) return return_list def closeAlgorithm(self): # Pickle this object with open(self.folder_name + '/algorithm_pickle', 'wb') as f: pickle.dump(self, f)