Exemplo n.º 1
0
class Crops(dict):
    switch_template = HD.loadTemplates('crops', 'switch*')

    def __init__(self, device, tasklist):
        self.log = MyLogger('Crops', LOG_LEVEL=logging.INFO)
        self.device = device
        self.tasklist = tasklist
        self.data = []
        self.settings = []
        self.updateListData()

    def updateListData(self):
        settings = HD.loadJSON('crops')
        resources = HD.loadJSON('resources')
        count = {}
        if len(resources) and "crops" in resources and len(settings):
            if resources['crops'] != self.data or settings != self.settings:
                self.log.error("Changes found")
                self.log.error(settings)
                self.log.error(self.settings)
                self.log.error(resources['crops'])
                self.log.error(self.data)
                self.data = resources['crops']
                self.settings = settings
                for crop in self.values():
                    crop.enabled = False
                for newcrop in self.data:
                    crop = newcrop['crop']
                    if crop not in count:
                        count[crop] = 0
                    count[crop] += 1
                    name = f"Crop {crop} [{count[crop]}]"
                    if crop in self.settings:
                        if name not in self:
                            self[name] = Crop(self.device, self.tasklist, crop)
                        data = self.settings[crop].copy()
                        data.update(newcrop)
                        data['name'] = name
                        data['log'] = self.log
                        data['enabled'] = True
                        self.log.debug(f"location: {newcrop['location']}")
                        data['position'] = self.device.getPos(
                            newcrop['location'])
                        self.log.debug(f"position: {data['position']}")
                        data['temp_switch'] = self.switch_template
                        data['update'] = self.updateListData
                        for key, value in data.items():
                            setattr(self[name], key, value)
Exemplo n.º 2
0
class Trees(dict):
    def __init__(self, device, tasklist):
        self.log = MyLogger('TREES', LOG_LEVEL=logging.INFO)
        self.device = device
        self.tasklist = tasklist
        self.data = []
        self.settings = []
        self.updateListData()

    def updateListData(self):
        self.log.debug('updating data')
        settings = HD.loadJSON('trees')
        resources = HD.loadJSON('resources')
        count = {}
        if len(resources) and "trees" in resources and len(settings):
            self.log.debug('data is valid')
            if resources['trees'] != self.data or settings != self.settings:
                self.data = resources['trees']
                self.settings = settings
                for fruit in self.values():
                    fruit.enabled = False
                for newfruit in self.data:
                    fruit = newfruit['fruit']
                    self.log.debug(f'fruit: {fruit}')
                    if fruit not in count:
                        count[fruit] = 0
                    count[fruit] += 1
                    self.log.debug(f"amount: {newfruit['amount']}")
                    for i in range(newfruit['amount']):
                        name = f"{fruit} [{count[fruit]}-{i}]"
                        self.log.debug(f"name: {name}")
                        if fruit in self.settings:
                            if name not in self:
                                self[name] = Tree(self.device, self.tasklist,
                                                  fruit)
                            data = self.settings[fruit].copy()
                            data['log'] = self.log
                            data['name'] = name
                            data['enabled'] = True
                            data['position'] = self.device.getPos(
                                newfruit['location'])
                            data['templates'] = HD.loadTemplateMap(
                                'trees', fruit)
                            data['update'] = self.updateListData
                            for key, value in data.items():
                                setattr(self[name], key, value)
Exemplo n.º 3
0
class Shop(HD):
    def __init__(self, device, tasklist):
        HD.__init__(self, device, tasklist, 'money')
        self.log=MyLogger('shop', LOG_LEVEL=logging.DEBUG)
        self.tasklist.addtask(20, f"checking for items to sell", self.image, self.checkItems)
        self.shoplist=Shoplist(self)
        self.position=HD.getPos([-15,0])
        self.slots=4
        self.max_slots=4
        self.atshop=False
        self.temp_shop=self.device.loadTemplates('shop','')

    def add(self, product, min_amount=6,sell=False):
        self.products.append(ShopItem(product, min_amount))

    def checkItems(self):
        self.atshop=False
        wait=10
        if self.max_slots>self.slots:
            self.checkShop()
            self.atshop=True
        try:
            json_data=HD.loadJSON('sell')
            for product,data in data.items():
                wished,scheduled=self.tasklist.getWish(product)

                #check if prodruct needs to be ordered
                if (scheduled-wished<data['maximum']-self.slots*data['amount']) and data['order']:
                    self.log.debug(f'need more {product}')
                    self.tasklist.addWish(product,data['maximum']-(scheduled-wished))

                if -wished>data['minimum']+data['amount']:
                    available=-wished-data['minimum']
                    stocks=int(available/data['amount'])
                    if stocks<self.slots:
                        self.slots-= stocks
                    else:
                        stocks=self.slots
                        self.slots=0
                    if stocks:
                        self.log.debug(f'i can sell some')
                        self.shoplist.add(product,stocks, **data)
                        wait=2
        except Exception as e:
            self.log.error(e)
        finally:
            self.tasklist.addtask(wait, f"checking for items to sell", self.image, self.checkItems)
            self.sellItems()

    def sellItems(self):
        self.log.debug('selling items')
        try:
            if not len(shoplist):
                raise Exception("No items to sell")
            if not self.atshop or self.open_shop():
                raise Exception("Shop is not open")
            spots=self.device.locate_item(self.temp_create, 0.85)
            for product,data in self.shoplist.items():
                if product in self.temp_products:
                    while self.shoplist[product].stock:
                        if not len(spots):
                            raise Exception("No free spot to sell items"):
                        location=spots.pop()
                        self.device.tap(location)
                        location=self.device.locate_item(self.temp_products[product],.85, one=True)
                        if not len(location):
                            raise Exception("Could not find product in list")
                        self.device.tap(location)
                        self.log.debug('item should be selected by now')





            if not len(locations):
                raise



        except Exception as e:
            self.log.error(e)

    def checkShop(self):
        self.log.debug('checking Shop')
        try:
            if not self.open_shop():
                raise Exception("Shop is not open")
            locations=self.device.locate_item(self.temp_sold, 0.85)
            if not len(locations):
                raise Exception("Could not find sold items")
            for location in locations:
                self.device.tap(location)
        except Exception as e:
            self.log.error(e)

    def open_shop(self):
        try:
            self.move_to()
            location = self.device.locate_item(self.temp_shop, .85, one = True)
            if not len(location):
                raise Exception("Could not locate shop")
            self.device.tap(location)
            self.atshop=True
            return True
        except Exception as e:
            self.log.error('OPEN SHOP')
            self.log.error(e)
            return False
Exemplo n.º 4
0
class Adb_Device():
    device = None
    touch = "/dev/input/event6"
    res_x, res_y = [1600, 900]
    max = 32767
    output = ShowOutput()
    lastscreen = None

    def __init__(self):
        self.log = MyLogger('ADB', LOG_LEVEL=logging.INFO)
        client = Client(host='127.0.0.1', port=5037)
        self.log.debug(client.version())
        devices = client.devices()
        if len(devices) == 0:
            self.log.debug("no devices")
            quit()
        self.device = devices[0]
        self.log.debug(f'updating info for {self.device}')
        number = 5
        touch_id = 0
        lines = self.device.shell('getevent -p').split("\n")
        for line in lines:
            if "/dev/input" in line:
                number = line[-1]
            if "Touch" in line:
                touch_id = number
                self.touch = f"sendevent /dev/input/event{number}"
            if "max" in line and "ABS" in line and number == touch_id:
                values = line.split(', ')
                for value in values:
                    if "max" in value:
                        self.max = int(value[4:])
                        self.log.debug(f"found max: {self.max}")

    @staticmethod
    def correct(list1, list2):
        newlist = []
        dx = list2[0][0] - list1[0][0]
        dy = list2[0][1] - list1[0][1]
        for x, y in list1:
            newlist.append([x + dx, y + dy])
        return newlist

    @staticmethod
    def getClosest(list, vector):
        x_target, y_target = vector
        winner = list[0]
        score = 99999
        for loc in list:
            x, y = loc
            newscore = (x_target - x)**2 + (y_target - y)**2
            if newscore < score:
                winner = [x, y]
                score = newscore
        return winner

    @staticmethod
    def checkClose(x1, y1, list, tol_x=30, tol_y=16):
        for location in list:
            x2, y2 = location
            if (isclose(x1, x2, abs_tol=tol_x)
                    and isclose(y1, y2, abs_tol=tol_y)):
                return True
        else:
            return False

    @staticmethod
    def getClose(list, x1, y1, tol_x, tol_y):
        newlist = []
        for vector in list:
            x2, y2 = vector
            if (isclose(x1, x2, abs_tol=tol_x)
                    and isclose(y1, y2, abs_tol=tol_y)):
                newlist.append(vector)
        return newlist

    def release_all(self):
        shellcmd = f"{self.touch} 3 57 -1  && {self.touch} 0 2 0 && {self.touch} 0 0 0"
        self.device.shell(shellcmd)

    def zoom_out(self):
        y = 0.35
        x_c = .5
        dx = 0.25
        steps = []
        for i in range(10):
            x1 = x_c - dx * (10 - i) / 11
            x2 = x_c + dx * (10 - i) / 11
            steps.append(f"{self.touch} 3 57 0")
            steps.append(f"{self.touch} 3 53 {int(x1*self.max)}")
            steps.append(f"{self.touch} 3 54 {int(y*self.max)}")
            steps.append(f"{self.touch} 0 2 0")
            steps.append(f"{self.touch} 3 57 1")
            steps.append(f"{self.touch} 3 53 {int(x2*self.max)}")
            steps.append(f"{self.touch} 3 54 {int(y*self.max)}")
            steps.append(f"{self.touch} 0 2 0")
            steps.append(f"{self.touch} 0 0 0")
        shellcmd = " && ".join(steps)
        self.device.shell(shellcmd)
        self.release_all()
        self.release_all()
        sleep(.1)
        # cmd=f"{self.touch} 3 57 2 && {self.touch} 3 53 {int((x_c-dx)*self.max)} && {self.touch} 3 54 {int(y*self.max)}"
        # self.device.shell(cmd)
        # self.device.shell(f"input swipe {(x_c+dx)*self.res_x} {(y)*self.res_y} {(x_c-dx)*self.res_x} {(y)*self.res_y} 2000")
        # self.release_all()
        # self.release_all()

    def printScreen(self):
        screencap = self.device.screencap()
        screenshot_file = path.join('images', 'screen.png')
        with open(screenshot_file, 'wb') as f:
            f.write(screencap)

    def tap(self, x, y):
        self.device.shell(f'input tap {x} {y}')
        sleep(.3)

    def trace(self, waypoints, size=0, pressure=0):
        eventlist = []
        for waypoint in waypoints:
            x, y = waypoint
            eventlist.append(f"{self.touch} 3 57 0")
            eventlist.append(f"{self.touch} 3 53 {int(x*self.max/self.res_x)}")
            eventlist.append(f"{self.touch} 3 54 {int(y*self.max/self.res_y)}")
            if size:
                eventlist.append(f"{self.touch} 3 48 {size}")
            if pressure:
                eventlist.append(f"{self.touch} 3 58 {pressure}")
            eventlist.append(f"{self.touch} 0 2 0")
            eventlist.append(f"{self.touch} 0 0 0")
        # for event in eventlist:
        #     self.device.shell(event)
        shellcmd = " && ".join(eventlist)
        self.device.shell(shellcmd)
        self.release_all()
        # self.device.shell(shellcmd)

    def move(self, x, y):
        self.log.debug('moving')
        border_x = self.scale_X(500)
        border_y = self.scale_Y(300)
        center_x = self.scale_X(800)
        center_y = self.scale_Y(450)
        while (x or y):
            if x < 0:
                dx = x if x > -border_x else -border_x
            else:
                dx = x if x < border_x else border_x
            if y < 0:
                dy = y if y > -border_y else -border_y
            else:
                dy = y if y < border_y else border_y
            self.swipe(self.res_x / 2 + dx, self.res_y / 2 + dy, center_x,
                       center_y, 500)
            x = x - dx
            y = y - dy

    def swipe(self, x1, y1, x2, y2, speed=300):
        self.device.shell(f'input swipe {x1} {y1} {x2} {y2} {speed}')
        sleep(.3)

    def center(self, x, y):
        self.swipe(x, y, self.res_x / 2, self.res_y / 2, 500)

    def load_screen_img(self):
        screenshot_file = path.join('images', 'screen.png')
        return cv2.imread(screenshot_file)

    @staticmethod
    def show_img(img):
        cv2.imshow('Test', img)
        cv2.waitKey(0)  # waits until a key is pressed
        cv2.destroyAllWindows()  # destroys the window showing image

    def load_screenCap(self):
        screencap = self.device.screencap()
        img_bytes = bytes(screencap)
        self.lastscreen = cv2.imdecode(np.fromstring(img_bytes, np.uint8),
                                       cv2.IMREAD_COLOR)
        # self.show_img(img)
        return self.lastscreen
        # screenshot_file=path.join('images','screen.png')
        # with open(screenshot_file, 'wb') as f:
        #     f.write(screencap)
        # sleep(.1)
        # return cv2.imread(screenshot_file)

    def get_match(self, template, img, threshold, margin):
        loc = []
        if len(template.data):
            result = cv2.matchTemplate(img, template.data,
                                       cv2.TM_CCOEFF_NORMED)
            max = np.max(result)
            # self.log.debug(template.file)
            # self.log.debug(f"offset: {template.offset}")
            # self.log.debug(f"max: {max}")
            if (max >= threshold):
                min = max - margin if (
                    max - margin >= threshold) else threshold
                loc = np.where(result >= min)
        return loc

    def check_present(self, template_dict, threshold=0.75, margin=0.05):
        img = self.load_screenCap()
        list = []
        for name, template in template_dict.items():
            if len(self.get_match(template, img, threshold, margin)):
                list.append(name)
        return list

    #calculate new x or y, if device has an other resolution than 1600:900
    def scale_X(self, x):
        return x * self.res_x / 1600

    def scale_Y(self, y):
        return y * self.res_y / 900

    #calculate a new location based on location and the given vector
    #vector[x,y]=[0,1]=NE  -> -X (screen) and -Y (screen)
    #vector[1] positive = NW  -> dx = positive, dy= negative
    def getPos(self, vector, location=[0, 0], multiplier=1):
        x, y = location
        dx = int(self.scale_X(47) * (vector[0] - vector[1]) * multiplier)
        dy = int(self.scale_Y(23.5) * -(vector[0] + vector[1]) * multiplier)
        return [x + dx, y + dy]

    #get color of pixel on this location
    def getColor(self, location):
        x, y = location
        img = self.lastscreen
        (b, g, r) = img[y, x]
        return [r, g, b]

    def locate_item(self,
                    templates,
                    threshold=0.75,
                    margin=0.05,
                    one=False,
                    offset=[30, 16],
                    last=False):
        result_file = path.join('images', 'result.png')
        img_base = self.lastscreen if last else self.load_screenCap()
        img_result = img_base
        loclist = []
        for template in templates:
            self.log.debug(template)
            loc = self.get_match(template, img_base, threshold, margin)
            if len(loc) and len(loc[0]):
                for pt in zip(*loc[::-1]):  # Switch collumns and rows
                    cv2.rectangle(img_result, pt,
                                  (pt[0] + template.w, pt[1] + template.h),
                                  (0, 0, 255), 2)
                    x, y = np.add(pt, template.offset).astype(int)
                    if not self.checkClose(x, y, loclist, *offset):
                        self.log.debug(f"found on {x},{y} ")
                        self.log.debug(f"point={pt}")
                        cv2.rectangle(img_result, pt,
                                      (pt[0] + template.w, pt[1] + template.h),
                                      (255, 0, 255), 2)
                        loclist.append([x, y])
                for vector in loclist:
                    x, y = vector
                    cv2.circle(img_result, (x, y), 10, (0, 255, 0), -1)
        # cv2.imwrite(result_file, img_result)
        self.output.update(img_result)
        if one and len(loclist):
            target = [self.res_x / 2, self.res_y / 2]
            loclist = self.getClosest(loclist, target)
        return loclist
Exemplo n.º 5
0
class agent():

	def __init__(self, logfile):
		self.log = MyLogger(logfile)
		self.createModel()

	'''
		create model for every traffic light
	'''
	def createModel(self):
		self.model = {}
		for tl in ni.trafficLights:
			dims = util.getDims()	
			self.model[tl] = singleModel(dims)

	def clearRecord(self):
		del self.record
		gc.collect()

	def addRecord(self, step, addEdgeRecord = True, addTrafficLightRecord = True, addVehicleRecord = True):
		self.record['step'] = step
		if addEdgeRecord:
			util.addEdgeRecord(traci, self.record['edge'], step)
		if addTrafficLightRecord:
			util.addTrafficLightRecord(traci, self.record['trafficlight'], step)
		if addVehicleRecord:
			util.addVehicleRecord(traci, self.record['vehicle'], step)

	'''
		self.record record details for the whole network on every step
	'''
	def createRecord(self):
		self.record = {}
		self.record['edge'] = {}
		self.record['trafficlight'] = {}
		self.record['vehicle'] = {}
		# get edge record
		self.record['edge']['speed'],self.record['edge']['number'] ,self.record['edge']['halting'] = util.getEdgeRecord()
		# get tl record
		self.record['trafficlight']['phase'],self.record['trafficlight']['duration'] = util.getTrafficLightRecord()
		# get vehicle record
		self.record['vehicle']['edge'],self.record['vehicle']['waittime'] = util.getVehicleRecord()
		self.record['step'] = -1
		self.record['state'] = util.getStateRecord()

	def getPreProcessData(self, totaldays):

		preData = {}
		for i in ni.trafficLights:
			preData[i] = []
		sumoCmd = ["sumo", "-c", ni.sumocfg, "--ignore-route-errors", "--time-to-teleport", "600"]
		for i in range(totaldays):
			self.log.debug('collecting preprocess data: ' + str(i) + ' days')
			getNewDemand()
			traci.start(sumoCmd)
			self.createRecord()
			step = 0
			while step < 7200:
				self.addRecord(step, addVehicleRecord = False)
				step += 1
				for tl in ni.trafficLights:
					flag = util.adjustFlag(tl, self.record)
					if flag:
						feature = util.getFeature(tl, self.record)
						preData[tl].append(feature)
				traci.simulationStep()
			traci.close()
			#self.clearRecord()
			if (i+1)%10 == 0:
				for tl in ni.trafficLights:
					a = np.array(preData[tl])
					a = np.array(a)
					file = 'preprocess/' +tl 
					np.save(file, a)
				#torch.save(preData, 'preprocess.pt')

	def train(self, totaldays):

		self.loadScaler()
		
		savedays = 4
		starttraindays = 3 
		sumoCmd = ["sumo", "-c", ni.sumocfg, "--ignore-route-errors", "--time-to-teleport", "600"]
		for i in range(totaldays):
			
			getNewDemand()
			self.createRecord()
			self.log.debug('train ' + str(i) + ' epoch')

			traci.start(sumoCmd)
			step = 0
			while step < 7200:
				self.simulation(traci, step)
				step += 1
				if i >= starttraindays:
					for tl in ni.trafficLights:
						self.model[tl].train(tl ,self.log)
			traci.close()
			if (i+1)%savedays == 0:
				savefile = 'model/'+'version'+str(int((i+1)/savedays)) + '_'
				self.log.debug('save model, reward and step in ' + savefile)
				for tl in ni.trafficLights:
					file = savefile + tl
					self.model[tl].save(file)

	def clearRecord(self):
		self.createRecord()

	def simulation(self, traci, step):
		self.addRecord(step)
		for tl in ni.trafficLights:
			self.adjustTrafficLight(traci, tl)
		traci.simulationStep()

	def adjustTrafficLight(self, traci, tl, record = True):
		
		flag = util.adjustFlag(tl, self.record)
		if flag:
			step = self.record['step']
			feature = util.getFeature(tl, self.record)
			feature = self.transform(tl, feature)
			reward = util.getReward(tl, self.record)
			qvalue = self.model[tl].forward(feature)
			action, actionset = util.getAction(tl, qvalue.data, self.record, epsilon = 0.1)
			self.record['state'][tl].append([feature, action, reward, step, actionset])
			self.addexperience(tl)
			self.executeAction(tl, action, step)

	def transform(self, tl, feature):
		feature = self.scaler[tl].transform([feature])
		array = torch.FloatTensor(feature)
		array = torch.squeeze(array)
		array = autograd.Variable(array)
		return array

	def executeAction(self, tl, action, step):
		phase = self.record['trafficlight']['phase'][tl][step]
		if phase == 0 and action == 0:
			traci.trafficlights.setPhaseDuration(tl, ni.actionDuration)
		if phase == 4 and action == 0:
			traci.trafficlights.setPhaseDuration(tl, 0)
		if phase == 0 and action == 1:
			traci.trafficlights.setPhaseDuration(tl, 0)
		if phase == 4 and action == 1:
			traci.trafficlights.setPhaseDuration(tl, ni.actionDuration)

	def addexperience(self, tl):
		if len(self.record['state'][tl]) > 1:
			current = self.record['state'][tl][-1]
			last = self.record['state'][tl][-2]
			laststep = last[3]
			self.model[tl].append([last[0], last[1], current[0], last[2], current[4], laststep])

	def loadScaler(self):
		self.scaler = {}
		for tl in ni.trafficLights:
			file = 'preprocess/'+tl+'.npy'
			data = np.load(file)
			print(np.shape(data))
			self.log.debug('loading pre process scaler : '+ file)
			self.scaler[tl] = prep.StandardScaler().fit(data)

	def evaluation(self):
		pass
class model():

	def __init__(self, loggerfile, modelfile = False):
			
		self.logger = MyLogger(loggerfile)
		self.trafficLights = ni.trafficLights
		self.linkEdges = ni.linkEdges
		if modelfile == False:
			self.model = self.createModel()
		else:
			self.logger.debug(' load model : ' + modelfile)
			self.model = torch.load(modelfile)
		self.actionMap = self.createActionMap()

	def createActionMap(self):

		map = {'inttostr':{},'strtoint':{}}
		tlLen = len(self.trafficLights)
		maxid = 3 ** tlLen
		for i in range(maxid):
			strid = ""
			mx = i
			for j in range(tlLen):
				st = int(mx%3)
				strid += str(st)
				mx = int(mx/3)
			map['inttostr'][i] = strid
			map['strtoint'][strid] = i
		return map

	def createModel(self):
		
		tlNum = len(self.trafficLights)
		dim = 0
		for tl in self.trafficLights:
			dim += len(self.linkEdges[tl]['in'])
		dims = 0
		dims += dim
		if ni.useHalting:
			dims += dim
		if ni.useSpeed:
			dims += dim
		if ni.usePhase:
			dims += tlNum
		self.dims = dims
		self.actions = 3 ** tlNum 
		return QValueMap(dims, dims*2, 3 ** tlNum)

	def save(self, file):
		rewardlist = self.memory.reward
		step = self.memory.step
		torch.save(rewardlist, 'reward/reward.pt')
		torch.save(step, 'reward/step.pts')
		torch.save(self.trainRecord['loss'], 'loss/' + file + '_loss.pt')
		torch.save(self.model, 'model/' + file + '.pt')

	def train(self, totaldays, modellast = ''):

		self.loadPreProcessScaler(ni.preProcessDataFile)

		self.logger.debug(" ----------------------------- train -----------------------------")

		sumoBinary = "sumo"
		sumoCmd = [sumoBinary, "-c", ni.sumocfg, "--ignore-route-errors"]

		targetmodel = deepcopy(self.model)

		optimizer = optim.Adam(self.model.parameters(), lr=0.001)
		gamma = 0.95
		exchange = 500
		exchangeDays = 5
		modellast += str(gamma)
		tua = 0.01
		minibatch = 128

		loss_function = nn.MSELoss(size_average = False)
		totalloss = 0
		evaluationDays = 4

		self.trainCnt = 0
		self.createTrainRecord()

		self.memory = memory(100000, 128)

		for i in range(totaldays):

			self.createRecord()
			getNewDemands(ni.generateTrips, ni.netXml, ni.tripsXml, ni.rouXml)
			traci.start(sumoCmd)
			step = 0

			self.logger.debug("train days : "+str(i))
			while step < 7200:
				flag = self.simulation(traci, step, record = True)
				step += 1
				loss = self.trainModel(targetmodel, optimizer, loss_function, gamma = gamma, minibatch = minibatch)
				if loss > 0:
					totalloss += loss
					self.trainRecord['loss'].append(loss)

				if self.trainCnt>0 and self.trainCnt%exchange == 0 and totalloss > 0:
					self.logger.debug(" --------- soft copy parameters --------- ")
					soft_update(self.model, targetmodel, tua)
					self.logger.debug(" totalloss :" + str(totalloss/exchange))
					totalloss = 0

			traci.close()

			if i > 0 and (i+1)%evaluationDays == 0:
				self.logger.debug(" version: " + str(int((i+1)/evaluationDays)) + " days: " + str(i))
				self.hiddenRecord()
				self.evaluation()
				self.loadRecord()

				self.logger.debug(" --------- save model -----------")
				modelfile = 'version_' + str(int((i+1)/evaluationDays)) + '_' + modellast
				self.save(modelfile)

			self.clearTrainRecord()
			#self.getCsvTrafficLight('csv/test.csv')

	def clearTrainRecord(self):
		self.trainRecord['state'] = []
		self.trainRecord['dataLen'] = 0

	def hiddenRecord(self):
		self.hidden = {}
		self.hidden['trainRecord'] = self.trainRecord
		self.hidden['record'] = self.record

	def loadRecord(self):
		self.record = self.hidden['record']
		self.trainRecord = self.hidden['trainRecord']

	def getMeanWaitTime(self):

		step = self.record['step']
		maxid = self.record['maxid'][step]
		return sum(self.record['vehiclewaittime'][:,step])/(maxid+1)

	def evaluation(self):

		self.loadPreProcessScaler(ni.preProcessDataFile)

		sumoBinary = "sumo"
		sumoCmd = [sumoBinary, "-c", ni.sumocfg, "--ignore-route-errors"]

		getNewDemands(ni.generateTrips, ni.netXml, ni.tripsXml, ni.rouXml)

		self.createRecord()
		self.createTrainRecord()
		step = 0
		traci.start(sumoCmd)
		while step < 7200:
			self.simulation(traci, step, record = False, epsilon = 0)
			step += 1
		traci.close()
		meanwaittime = self.getMeanWaitTime()
		self.getCsvTrafficLight('csv/model.csv')

		self.createRecord()
		step = 0
		traci.start(sumoCmd)
		while step < 7200:
			self.addRecord(traci, step)
			traci.simulationStep()
			step += 1
		traci.close()
		fixmeanwaittime = self.getMeanWaitTime()
		self.getCsvTrafficLight('csv/fix.csv', action = False)

		self.logger.debug(" fix : " + str(fixmeanwaittime) + " model: " + str(meanwaittime))

	def loadPreProcessScaler(self, file):
		data = np.load(file)
		#print(np.shape(data))
		self.logger.debug('loading pre process scaler : '+ file)
		self.scaler = prep.StandardScaler().fit(data)

	def getPreProcessData(self, totaldays, file):

		sumoBinary = "sumo"
		sumoCmd = [sumoBinary, "-c", ni.sumocfg, "--ignore-route-errors"]

		totalfeature = []
		for i in range(totaldays):

			getNewDemands(ni.generateTrips, ni.netXml, ni.tripsXml, ni.rouXml)

			self.logger.debug('collecting days: '+str(i) + ' data')

			traci.start(sumoCmd)
			step = 0
			self.clearRecord()
			while step < 7200:
				self.addRecord(traci, step, getwaittime = False)
				adjustFlag = self.getAdjustFlag()
				if adjustFlag:
					feature = self.getFeatureList()
					totalfeature.append(feature)
				traci.simulationStep()
				step += 1
			traci.close()
			
		tf = np.array(totalfeature)
		np.save(file, tf)

	def getCsvTrafficLight(self, file, action = True):
		lent = len(self.trafficLights)
		if action:
			array = np.zeros((7300,lent*2+1))
		else:
			array = np.zeros((7300,lent*2))
		cols = []
		for tl in self.trafficLights:
			cols.append(tl + 'p')
			cols.append(tl + 'd')
		if action:
			cols.append('action')
		for i in range(7200):
			for j in range(lent):
				tl = self.trafficLights[j]
				array[i,j*2+0] = self.record['phase'][tl][i]
				array[i,j*2+1] = self.record['duration'][tl][i]
			array[i,-1] = -1
		if action:
			for i in range(self.trainRecord['dataLen']):
				d = self.trainRecord['state'][i-1]
				a = d[1]
				step = d[2]
				array[step,lent*2] = a
		dataFrame = DataFrame(array, columns = cols)
		dataFrame.to_csv(file)

	def trainModel(self, targetmodel, optimizer, loss_function, gamma = 0.1, minibatch = 128):

		ln = self.memory.getMemoryLen()
		if ln < 5000:
			return -1

		self.trainCnt += 1

		indexlist = self.memory.sample()
							
		input = torch.FloatTensor(len(indexlist), self.dims)
		inputtarget = torch.FloatTensor(len(indexlist), self.dims)

		target = torch.FloatTensor(len(indexlist), self.actions)
				
		for j in range(len(indexlist)):

			data = indexlist[j]
			s = data[0]
			a = data[1]
			sn = data[2]
			r = data[3]

			input[j,:] = torch.squeeze(s.data)
			inputtarget[j,:] = torch.squeeze(sn.data)

		input = autograd.Variable(input)
		inputtarget = autograd.Variable(inputtarget)

		qs = self.model(input)
		qsn = targetmodel(inputtarget)

		qsdata = torch.squeeze(qs.data)
		qsndata = torch.squeeze(qsn.data)

		target = qsdata.clone()

		for j in range(len(indexlist)):
		
			data = indexlist[j]

			a = data[1]
			r = data[3]
			actionset = data[4]
			target[j,a] = r + gamma*max(torch.index_select(qsndata[j,:],0,torch.LongTensor(actionset)))
			#target[j,a] = r + gamma*max(qsndata[j,:])

		target = autograd.Variable(target)

		loss = loss_function(qs, target)
		loss.backward()

		for param in self.model.parameters():
			param.grad.data.clamp_(-1, 1)

		optimizer.step()
		optimizer.zero_grad()

		return loss.data[0]

	def sample(self, batch):
		lt = []
		num = self.trainRecord['dataLen'] - 1
		for i in range(batch):
			p = random.uniform(0,num)
			lt.append(int(p))
		return lt

	def simulation(self, traci, step, record = False, epsilon = 0.05):
		self.addRecord(traci, step)
		adjustFlag = self.getAdjustFlag()
		flag = False
		if adjustFlag:
			self.adjustTrafficLights(traci, record = record, epsilon = epsilon)
			flag = True
		traci.simulationStep()
		return flag

	def adjustTrafficLights(self, traci, record, epsilon = 0.05):
		feature = self.getFeature()
		#print(feature)
		qvalue = self.model(feature)
		action,actionset = self.getAction(qvalue.data, epsilon)
		self.executeAction(traci,action)
		if record:
			self.trainRecord['dataLen'] += 1
			option = ni.option
			if self.trainRecord['dataLen'] == 1:
				laststep = 0
			else:
				laststep = self.trainRecord['state'][-1][2]
			step = self.record['step']
			reward = self.getReward(infor = [laststep, step, 0.02], options = option)
			self.trainRecord['state'].append([feature, action, step, actionset, reward])

			if self.trainRecord['dataLen'] > 1:
				lastdata = self.trainRecord['state'][-2]
				lastfeature = lastdata[0]
				lastaction = lastdata[1]
				laststep = lastdata[2]
				lastreward = lastdata[4]
				experience = [lastfeature, lastaction, feature, reward, actionset, laststep]
				self.memory.append(experience)

	def getReward(self, infor, options):
		if options == 1:
			laststep = infor[0]
			epsilon = infor[1]
			step = self.record['step']
			assert( step > laststep )
			waittime = epsilon * sum(self.record['vehiclewaittime'][:,step] - self.record['vehiclewaittime'][:,laststep])/(step-laststep)
			return 0-waittime
		if options == 2:
			llstep = infor[0]
			laststep = infor[1]
			step = self.record['step']
			assert( laststep > llstep )
			lastmeanwait = sum(self.record['vehiclewaittime'][:,llstep])/(self.record['maxid'][llstep]+1)
			meanwait = sum(self.record['vehiclewaittime'][:,laststep])/(self.record['maxid'][laststep]+1)
			return lastmeanwait - meanwait
		if options == 3: 
			llstep = infor[0]
			laststep = infor[1]
			epsilon = infor[2]
			assert( laststep > llstep )
			waittime = epsilon * sum(self.record['vehiclewaittime'][:,laststep] - self.record['vehiclewaittime'][:,llstep])/(laststep-llstep)
			return 0-waittime
		if options == 4: 
			llstep = infor[0]
			laststep = infor[1]
			epsilon = infor[2]
			assert( laststep > llstep )
			waittime = sum(self.record['vehiclewaittime'][:,laststep] - self.record['vehiclewaittime'][:,llstep])/(laststep-llstep)/(self.record['currentNum'][llstep]+1)
			return 0-waittime

	def executeAction(self,traci,action):
		straction = self.actionMap['inttostr'][action]
		for i in range(len(straction)):
			inti = int(straction[i])
			#print(i)
			tl = self.trafficLights[i]
			phase = self.record['phase'][tl][-1]
			if inti == 0:
				if phase == 0:
					traci.trafficlights.setPhaseDuration(tl, ni.actionDuration)
				if phase == 4:
					traci.trafficlights.setPhaseDuration(tl, 0)
			if inti == 1:
				if phase == 0:
					traci.trafficlights.setPhaseDuration(tl, 0)
				if phase == 4:
					traci.trafficlights.setPhaseDuration(tl, ni.actionDuration)
			if inti == 2:
				pass

	def getAction(self, qvalue, epsilon):
		nophase = []
		for tl in self.trafficLights:
			phase = self.record['phase'][tl][-1]
			if phase != 0 and phase != 4:
				nophase.append(2)
			else:
				duration = self.record['duration'][tl][-1]
				if duration < 20:
					if phase == 0:
						nophase.append(0)
					else:
						nophase.append(1)
				elif duration > 190:
					if phase == 0:
						nophase.append(1)
					else:
						nophase.append(0)
				else:
					nophase.append(-1)
		actionset = self.getActionSet(nophase)

		#self.logger.DEBUG("")

		action = actionset[0]
		maxvalue = qvalue[action]

		p = random.uniform(0,1)
		if p > epsilon:
			for a in actionset:
				value = qvalue[a]
				if value > maxvalue:
					action = a
					maxvalue = value
			return action,actionset
		else:
			pa = random.uniform(0,len(actionset))
			pa = int(pa)
			return actionset[pa],actionset

	def getActionSet(self, nophase):
		strlist = [""]
		for i in nophase:
			lt = []
			p = i
			if p == -1:
				for j in strlist:
					lt.append(j+"0")
					lt.append(j+"1")
			else:
				for j in strlist:
					lt.append(j+str(p))
			strlist = lt
		actionset = []
		for st in strlist:
			id = self.actionMap['strtoint'][st]
			actionset.append(id)
		return actionset

	def getFeatureList(self):
		featureList = []
		for tl in self.trafficLights:
			for edge in self.linkEdges[tl]['in']:
				featureList.append(self.record['vehicleNum'][edge][-1])
		if ni.useHalting:
			for tl in self.trafficLights:
				for edge in self.linkEdges[tl]['in']:
					featureList.append(self.record['haltingNum'][edge][-1])
		if ni.useSpeed:
			for tl in self.trafficLights:
				for edge in self.linkEdges[tl]['in']:
					featureList.append(self.record['speed'][edge][-1])
		if ni.usePhase:
			for tl in self.trafficLights:
				featureList.append(self.record['phase'][tl][-1])
		return featureList

	def getFeature(self):

		featureList = self.getFeatureList()
		feature = self.scaler.transform([featureList])
		array = torch.FloatTensor(feature)
		array = torch.squeeze(array)
		array = autograd.Variable(array)
		return array

	def getAdjustFlag(self):
		for tl in self.trafficLights:
			phase = self.record['phase'][tl][-1]
			if phase == 0 or phase == 4:
				duration = self.record['duration'][tl][-1]
				if duration > 1 and (duration+1)%self.record['maxduration'] == 0:
					return True
		return False

	def addRecord(self, traci, step, getwaittime = True):

		self.record['step'] = step

		'''
			get states of traffic lights and edge
		'''
		for tl in self.trafficLights:
			phase = traci.trafficlights.getPhase(tl)
			self.record['phase'][tl].append(phase)
			'''
				get duration
			'''
			if step == 0:
				self.record['duration'][tl].append(0)
			else:
				lastPhase = self.record['phase'][tl][-2]
				if phase == lastPhase:
					duration = self.record['duration'][tl][-1] + 1
					self.record['duration'][tl].append(duration)
				else:
					self.record['duration'][tl].append(0)

			for edge in self.linkEdges[tl]['in']:
				#print(edge)
				haltingNum = traci.edge.getLastStepHaltingNumber(edge)
				vehicleNum = traci.edge.getLastStepVehicleNumber(edge)
				speed = traci.edge.getLastStepMeanSpeed(edge)
				self.record['haltingNum'][edge].append(haltingNum)
				self.record['vehicleNum'][edge].append(vehicleNum)
				self.record['speed'][edge].append(speed)

		'''
			get vehicle wait time
		'''
		if getwaittime:
			if step > 0:
				self.record['vehiclewaittime'][:,step] = self.record['vehiclewaittime'][:,step-1]
			idlist = traci.vehicle.getIDList()
			self.record['currentNum'][step] = len(idlist)
			for id in idlist:
				wait = traci.vehicle.getAccumulatedWaitingTime(id)
				intid = int(id)
				self.record['vehiclewaittime'][intid, step] = max(self.record['vehiclewaittime'][intid, step], wait)
				self.record['maxid'][step] = max(self.record['maxid'][step], intid)

	def createTrainRecord(self):

		self.trainRecord = {}
		self.trainRecord['state'] = []
		self.trainRecord['data'] = []
		self.trainRecord['dataLen'] = 0
		self.trainRecord['maxLen'] = 100000
		self.trainRecord['loss'] = []

	def createRecord(self):

		self.record = {}
		self.record['vehicleNum'] = {}
		self.record['haltingNum'] = {}
		self.record['speed'] = {}
		
		self.record['step'] = 0
		self.record['maxduration'] = ni.actionDuration
		self.record['vehiclewaittime'] = np.zeros((5000, 7300))
		self.record['maxid'] = np.zeros(7300)
		self.record['currentNum'] = np.zeros(7300)
		self.record['phase'] = {}
		self.record['duration'] = {}

		for tl in self.trafficLights:
			self.record['phase'][tl] = []
			self.record['duration'][tl] = []
			for edge in self.linkEdges[tl]['in']:
				self.record['vehicleNum'][edge] = []
				self.record['haltingNum'][edge] = []
				self.record['speed'][edge] = []

	def clearRecord(self):
		self.createRecord()
Exemplo n.º 7
0
class Board(HD):
    def __init__(self, device, tasklist):
        HD.__init__(self, device, tasklist, 'board')
        self.device = device
        self.tasklist = tasklist
        self.log = MyLogger('Board', LOG_LEVEL=logging.INFO)
        self.nextcheck = 0.1
        self.image = path.join('images', 'board', 'car_button_C.png')
        self.base_template = HD.loadTemplates('board', 'base')
        self.complete_templates = HD.loadTemplates('board', 'check')
        # self.card_template=HD.loadTemplates('board','pins')
        self.product_templates = {}
        self.car = [1335, 775]
        self.bin = [1175, 780]
        self.cards = []
        for location in [[290, 290], [535, 290], [775, 290], [290, 520],
                         [535, 520], [775, 520], [290, 730], [535, 730],
                         [775, 730]]:
            self.cards.append(Card(tasklist, location))
        self.product_images = []
        self.checkImages()
        self.tasklist.addtask(self.nextcheck, 'board', self.image, self.check)

    def checkImages(self):
        newimages = glob(path.join('images', 'products', '*.png'))
        if newimages != self.product_images:
            self.log.debug('loading new templates')
            for file in newimages:
                filename = path.split(file)[-1]
                product = path.splitext(filename)[0]
                self.log.debug(f"found: {product}")
                self.product_templates[product] = Template(file)
        sleep(.5)
        self.product_images = newimages

    def getCard(self, location):
        list = []
        for card in self.cards:
            list.append(card.location)
        location = self.device.getClosest(list, location)
        idx = list.index(location)
        return self.cards[idx]

    def collect(self, location):
        card = self.getCard(location)
        self.device.tap(*location)
        self.device.tap(*self.car)
        card.reset()

    def checkComplete(self):
        self.log.debug('checking complete')
        checks = self.device.locate_item(self.complete_templates, .85)
        if len(checks):
            self.collect(checks[0])
            self.nextcheck = .3
            return True
        return False

    def check(self):
        self.log.debug('checking board')
        self.checkImages()
        skiplist = HD.loadJSON('skip')
        self.nextcheck = 1
        if self.reset_screen():
            location = self.device.locate_item(self.base_template,
                                               .75,
                                               one=True)
            self.log.debug(location)
            if len(location) and self.open(location):
                if not self.checkComplete():
                    self.log.debug('update board info')
                    for card in self.cards:
                        x, y = card.location
                        self.device.tap(x, y)
                        sleep(.1)
                        products = self.device.check_present(
                            self.product_templates, .93)
                        for product in products:
                            if product in skiplist:
                                self.device.tap(*self.bin)
                                card.reset()
                                break
                            self.log.debug(f'found: {product}')
                            card.add(product)
                    self.nextcheck = 5
                    self.checkComplete()
                self.check_cross()
        self.tasklist.addtask(self.nextcheck, 'board', self.image, self.check)
Exemplo n.º 8
0
class HD():
    # this needs to be placed inside of an update function to be able to change pictures while running
    home = None

    def __init__(self, device, tasklist, item):
        self.log = MyLogger('HD', LOG_LEVEL=logging.INFO)
        self.device = device
        self.tasklist = tasklist
        self.scheduled = False
        file = path.join('images', 'products', f'{item}.png')
        self.image = file if path.isfile(file) else path.join(
            'images', 'no_image.png')
        self.jobs = 0
        self.waiting = 0
        self.loadImages()

    def loadImages(self):
        for name in [
                'home', 'cross', 'info', 'plus', 'grass', 'diamond', 'again',
                'arrows', 'cont'
        ]:
            setattr(self, name, self.loadTemplates('base', name))

    @staticmethod
    def loadJSON(filename):
        file = path.join('data', f'{filename}.json')
        try:
            if path.isfile(file):
                with open(file) as json_file:
                    data = json.load(json_file)
        except Exception as e:
            print(f"ERROR {filename}")
            print(e)
            data = []
            sleep(5)
        finally:
            return data

    @staticmethod
    def loadTemplates(map, name):
        list = []
        filelist = glob(path.join(getcwd(), 'images', map, f'{name}*.png'))
        for file in filelist:
            list.append(Template(file))
        return list

    @staticmethod
    def loadTemplateMap(map, product):
        list = []
        filelist = glob(path.join(getcwd(), 'images', map, product, '*.png'))
        for file in filelist:
            list.append(Template(file))
        return list

    @staticmethod
    def setData(item, data):
        for key, value in data.items():
            setattr(item, key, value)

    @staticmethod
    def getPos(location):
        x, y = location
        pos_x = (47 * x - 47 * y)
        pos_y = int(-23.5 * x - 23.5 * y)
        return [pos_x, pos_y]

    #return time in minutes
    def getWaitTime(self):
        if self.waiting:
            waittime = self.waiting - int(time())
            if waittime > 0:
                return waittime / 60
        return 0

    def setWaittime(self, wait):
        self.waiting = int(time() + wait * 60)

    def move_to(self):
        self.log.debug(f'moving to location: {self.position}')
        pos_x, pos_y = self.position
        self.device.move(pos_x, pos_y)
        sleep(.2)

    def move_from(self):
        pos_x, pos_y = self.position
        self.device.move(-pos_x, -pos_y)

    def onscreen(self, product):
        self.log.debug(f"checking for {product}")
        templates = TemplateLibrary(
            path.join('images', 'products', 'big', '*.png'))
        if product in templates:
            self.log.debug(f"Template is found")
            if len(self.device.locate_item([templates[product]], last=True)):
                return True
        return False

    def check_cross(self):
        locations = self.device.locate_item(self.cross, .45)
        if len(locations):
            x, y = locations[0]
            self.device.tap(x, y)
            return True
        return False

    def check_connection(self):
        locations = self.device.locate_item(self.again, .60)
        if len(locations):
            x, y = locations[0]
            self.device.tap(x, y)
            sleep(1)

    def check_lvl_up(self):
        locations = self.device.locate_item(self.cont, .75)
        if len(locations):
            x, y = locations[0]
            self.device.tap(x, y)
            sleep(1)

    def check_plus(self):
        locations = self.device.locate_item(self.plus, .85)
        if len(locations):
            return True
        return False

    def check_diamond(self):
        locations = self.device.locate_item(self.diamond, .85)
        if len(locations):
            return True
        return False

    def check_moved(self):
        locations = self.device.locate_item(self.arrows, .85)
        if len(locations):
            sleep(.3)
            self.click_green()

    def click_green(self):
        self.log.debug('click on grass')
        location = self.device.locate_item(self.grass, .45, one=True)
        if len(location):
            x, y = location
            self.device.tap(x, y)

    def open(self, location):
        x, y = location
        self.device.tap(x, y)
        sleep(.1)
        if not self.check_open():
            self.device.tap(x, y)
            sleep(.1)
            if not self.check_open():
                self.tasklist.addtask(5, 'board', self.image, self.check)
                return False
        return True

    def check_open(self):
        locations = self.device.locate_item(self.cross, .45)
        if len(locations):
            return True
        return False

    def check_home(self):
        locations = self.device.locate_item(self.home, .85)
        if not len(locations):
            self.log.debug('ohoh')
            return False
        return locations

    def reset_screen(self):
        self.log.debug('cleaning')
        locations = self.check_home()
        count = 0
        while not locations or count >= 3:
            self.check_connection()
            self.check_moved()
            self.check_lvl_up()
            if not self.check_cross():
                for x in range(4):
                    self.device.swipe(200, 150, 1000, 600, 100)
                self.check_cross()
                self.device.zoom_out()
                self.check_cross()
                self.device.swipe(1000, 600, 500, 450, 400)
            locations = self.check_home()
            count += 1
            self.loadImages()
        if not locations:
            return False
        x, y = locations[0]
        self.log.debug(f'home: {x},{y}')
        if not (isclose(x, 800, abs_tol=100) and isclose(y, 550, abs_tol=75)):
            self.device.swipe(x, y, 800, 550, 1000)
        sleep(.1)
        self.log.debug('cleaning done')
        return True

    def tap_and_trace(self, locations, item_x=0, item_y=0):
        self.log.debug('tap and trace')
        x, y = locations[0]
        self.device.tap(x, y)
        waypoints = [[x + item_x, y + item_y]] + locations
        self.device.trace(waypoints, size=50)
        sleep(.5)

    def trace(self, locations, item_x=0, item_y=0):
        self.log.debug('trace')
        x, y = locations[0]
        waypoints = [[x + item_x, y + item_y]] + locations
        self.device.trace(waypoints, size=150)
        sleep(.2)