Esempio n. 1
0
    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))
Esempio n. 2
0
 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
Esempio n. 3
0
File: show.py Progetto: BafDyce/acsm
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)
Esempio n. 4
0
    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 = ''
Esempio n. 5
0
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)
Esempio n. 6
0
	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()
Esempio n. 7
0
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()
Esempio n. 8
0
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')
Esempio n. 9
0
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()
Esempio n. 10
0
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)