# LAG # NO. OF VEHICLES IN SIGNAL CLASS # stops not used # DISTRIBUTION # BUS TOUCHING ON TURNS # Distribution using python class # *** IMAGE XY COOD IS TOP LEFT import random import math import time import threading from vehicle_detection import VehicleDetector import pygame import sys import os # dynamic path resolution SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PROJECT_ROOT = os.path.dirname(SCRIPT_DIR) # ensure local modules in api/ can be imported even if run from project root if SCRIPT_DIR not in sys.path: sys.path.append(SCRIPT_DIR) detector = VehicleDetector() # Default values of signal times defaultRed = 150 defaultYellow = 5 defaultGreen = 20 defaultMinimum = 10 defaultMaximum = 60 signals = [] noOfSignals = 4 simTime = 300 # change this to change time of simulation timeElapsed = 0 currentGreen = 0 # Indicates which signal is green nextGreen = (currentGreen+1)%noOfSignals currentYellow = 0 # Indicates whether yellow signal is on or off # Average times for vehicles to pass the intersection carTime = 2 bikeTime = 1 rickshawTime = 2.25 busTime = 2.5 truckTime = 2.5 # Count of cars at a traffic signal noOfCars = 0 noOfBikes = 0 noOfBuses =0 noOfTrucks = 0 noOfRickshaws = 0 noOfLanes = 2 # Red signal time at which cars will be detected at a signal detectionTime = 5 speeds = {'car':2.25, 'bus':1.8, 'truck':1.8, 'rickshaw':2, 'bike':2.5} # average speeds of vehicles # Coordinates of start x = {'right':[0,0,0], 'down':[755,727,697], 'left':[1400,1400,1400], 'up':[602,627,657]} y = {'right':[348,370,398], 'down':[0,0,0], 'left':[498,466,436], 'up':[800,800,800]} vehicles = {'right': {0:[], 1:[], 2:[], 'crossed':0}, 'down': {0:[], 1:[], 2:[], 'crossed':0}, 'left': {0:[], 1:[], 2:[], 'crossed':0}, 'up': {0:[], 1:[], 2:[], 'crossed':0}} vehicleTypes = {0:'car', 1:'bus', 2:'truck', 3:'rickshaw', 4:'bike'} directionNumbers = {0:'right', 1:'down', 2:'left', 3:'up'} # Coordinates of signal image, timer, and vehicle count signalCoods = [(530,230),(810,230),(810,570),(530,570)] signalTimerCoods = [(530,210),(810,210),(810,550),(530,550)] vehicleCountCoods = [(480,210),(880,210),(880,550),(480,550)] vehicleCountTexts = ["0", "0", "0", "0"] # Coordinates of stop lines stopLines = {'right': 590, 'down': 330, 'left': 800, 'up': 535} defaultStop = {'right': 580, 'down': 320, 'left': 810, 'up': 545} stops = {'right': [580,580,580], 'down': [320,320,320], 'left': [810,810,810], 'up': [545,545,545]} mid = {'right': {'x':705, 'y':445}, 'down': {'x':695, 'y':450}, 'left': {'x':695, 'y':425}, 'up': {'x':695, 'y':400}} rotationAngle = 3 # Gap between vehicles gap = 15 # stopping gap gap2 = 15 # moving gap pygame.init() simulation = pygame.sprite.Group() class TrafficSignal: def __init__(self, red, yellow, green, minimum, maximum): self.red = red self.yellow = yellow self.green = green self.minimum = minimum self.maximum = maximum self.signalText = "30" self.totalGreenTime = 0 class Vehicle(pygame.sprite.Sprite): def __init__(self, lane, vehicleClass, direction_number, direction, will_turn): pygame.sprite.Sprite.__init__(self) self.lane = lane self.vehicleClass = vehicleClass self.speed = speeds[vehicleClass] self.direction_number = direction_number self.direction = direction self.x = x[direction][lane] self.y = y[direction][lane] self.crossed = 0 self.willTurn = will_turn self.turned = 0 self.rotateAngle = 0 vehicles[direction][lane].append(self) # self.stop = stops[direction][lane] self.index = len(vehicles[direction][lane]) - 1 path = os.path.join(PROJECT_ROOT, "images", direction, vehicleClass + ".png") self.originalImage = pygame.image.load(path) self.currentImage = pygame.image.load(path) if(direction=='right'): if(len(vehicles[direction][lane])>1 and vehicles[direction][lane][self.index-1].crossed==0): # if more than 1 vehicle in the lane of vehicle before it has crossed stop line self.stop = vehicles[direction][lane][self.index-1].stop - vehicles[direction][lane][self.index-1].currentImage.get_rect().width - gap # setting stop coordinate as: stop coordinate of next vehicle - width of next vehicle - gap else: self.stop = defaultStop[direction] # Set new starting and stopping coordinate temp = self.currentImage.get_rect().width + gap x[direction][lane] -= temp stops[direction][lane] -= temp elif(direction=='left'): if(len(vehicles[direction][lane])>1 and vehicles[direction][lane][self.index-1].crossed==0): self.stop = vehicles[direction][lane][self.index-1].stop + vehicles[direction][lane][self.index-1].currentImage.get_rect().width + gap else: self.stop = defaultStop[direction] temp = self.currentImage.get_rect().width + gap x[direction][lane] += temp stops[direction][lane] += temp elif(direction=='down'): if(len(vehicles[direction][lane])>1 and vehicles[direction][lane][self.index-1].crossed==0): self.stop = vehicles[direction][lane][self.index-1].stop - vehicles[direction][lane][self.index-1].currentImage.get_rect().height - gap else: self.stop = defaultStop[direction] temp = self.currentImage.get_rect().height + gap y[direction][lane] -= temp stops[direction][lane] -= temp elif(direction=='up'): if(len(vehicles[direction][lane])>1 and vehicles[direction][lane][self.index-1].crossed==0): self.stop = vehicles[direction][lane][self.index-1].stop + vehicles[direction][lane][self.index-1].currentImage.get_rect().height + gap else: self.stop = defaultStop[direction] temp = self.currentImage.get_rect().height + gap y[direction][lane] += temp stops[direction][lane] += temp simulation.add(self) def render(self, screen): screen.blit(self.currentImage, (self.x, self.y)) def move(self): if(self.direction=='right'): if(self.crossed==0 and self.x+self.currentImage.get_rect().width>stopLines[self.direction]): # if the image has crossed stop line now self.crossed = 1 vehicles[self.direction]['crossed'] += 1 if(self.willTurn==1): if(self.crossed==0 or self.x+self.currentImage.get_rect().widthstopLines[self.direction]): self.crossed = 1 vehicles[self.direction]['crossed'] += 1 if(self.willTurn==1): if(self.crossed==0 or self.y+self.currentImage.get_rect().height(vehicles[self.direction][self.lane][self.index-1].x + vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().width + gap2) or self.y<(vehicles[self.direction][self.lane][self.index-1].y - gap2)): self.x -= self.speed else: if((self.y+self.currentImage.get_rect().height<=self.stop or self.crossed == 1 or (currentGreen==1 and currentYellow==0)) and (self.index==0 or self.y+self.currentImage.get_rect().height<(vehicles[self.direction][self.lane][self.index-1].y - gap2) or (vehicles[self.direction][self.lane][self.index-1].turned==1))): self.y += self.speed elif(self.direction=='left'): if(self.crossed==0 and self.xmid[self.direction]['x']): if((self.x>=self.stop or (currentGreen==2 and currentYellow==0) or self.crossed==1) and (self.index==0 or self.x>(vehicles[self.direction][self.lane][self.index-1].x + vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().width + gap2) or vehicles[self.direction][self.lane][self.index-1].turned==1)): self.x -= self.speed else: if(self.turned==0): self.rotateAngle += rotationAngle self.currentImage = pygame.transform.rotate(self.originalImage, -self.rotateAngle) self.x -= 1.8 self.y -= 2.5 if(self.rotateAngle==90): self.turned = 1 # path = "images/" + directionNumbers[((self.direction_number+1)%noOfSignals)] + "/" + self.vehicleClass + ".png" # self.x = mid[self.direction]['x'] # self.y = mid[self.direction]['y'] # self.currentImage = pygame.image.load(path) else: if(self.index==0 or self.y>(vehicles[self.direction][self.lane][self.index-1].y + vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().height + gap2) or self.x>(vehicles[self.direction][self.lane][self.index-1].x + gap2)): self.y -= self.speed else: if((self.x>=self.stop or self.crossed == 1 or (currentGreen==2 and currentYellow==0)) and (self.index==0 or self.x>(vehicles[self.direction][self.lane][self.index-1].x + vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().width + gap2) or (vehicles[self.direction][self.lane][self.index-1].turned==1))): # (if the image has not reached its stop coordinate or has crossed stop line or has green signal) and (it is either the first vehicle in that lane or it is has enough gap to the next vehicle in that lane) self.x -= self.speed # move the vehicle # if((self.x>=self.stop or self.crossed == 1 or (currentGreen==2 and currentYellow==0)) and (self.index==0 or self.x>(vehicles[self.direction][self.lane][self.index-1].x + vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().width + gap2))): # self.x -= self.speed elif(self.direction=='up'): if(self.crossed==0 and self.ymid[self.direction]['y']): if((self.y>=self.stop or (currentGreen==3 and currentYellow==0) or self.crossed == 1) and (self.index==0 or self.y>(vehicles[self.direction][self.lane][self.index-1].y + vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().height + gap2) or vehicles[self.direction][self.lane][self.index-1].turned==1)): self.y -= self.speed else: if(self.turned==0): self.rotateAngle += rotationAngle self.currentImage = pygame.transform.rotate(self.originalImage, -self.rotateAngle) self.x += 1 self.y -= 1 if(self.rotateAngle==90): self.turned = 1 else: if(self.index==0 or self.x<(vehicles[self.direction][self.lane][self.index-1].x - vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().width - gap2) or self.y>(vehicles[self.direction][self.lane][self.index-1].y + gap2)): self.x += self.speed else: if((self.y>=self.stop or self.crossed == 1 or (currentGreen==3 and currentYellow==0)) and (self.index==0 or self.y>(vehicles[self.direction][self.lane][self.index-1].y + vehicles[self.direction][self.lane][self.index-1].currentImage.get_rect().height + gap2) or (vehicles[self.direction][self.lane][self.index-1].turned==1))): self.y -= self.speed # Initialization of signals with default values def initialize(): ts1 = TrafficSignal(0, defaultYellow, defaultGreen, defaultMinimum, defaultMaximum) signals.append(ts1) ts2 = TrafficSignal(ts1.red+ts1.yellow+ts1.green, defaultYellow, defaultGreen, defaultMinimum, defaultMaximum) signals.append(ts2) ts3 = TrafficSignal(defaultRed, defaultYellow, defaultGreen, defaultMinimum, defaultMaximum) signals.append(ts3) ts4 = TrafficSignal(defaultRed, defaultYellow, defaultGreen, defaultMinimum, defaultMaximum) signals.append(ts4) repeat() # Set time according to formula def setTime(): global noOfCars, noOfBikes, noOfBuses, noOfTrucks, noOfRickshaws, noOfLanes global carTime, busTime, truckTime, rickshawTime, bikeTime # processed_img, vehicle_count = detector.detect('frame.jpg') # Example usage # greenTime = math.ceil(((noOfCars*carTime) + (noOfRickshaws*rickshawTime) + (noOfBuses*busTime) + (noOfBikes*bikeTime))/(noOfLanes+1)) # if(greenTimedefaultMaximum): # greenTime = defaultMaximum # greenTime = len(vehicles[currentGreen][0])+len(vehicles[currentGreen][1])+len(vehicles[currentGreen][2]) # noOfVehicles = len(vehicles[directionNumbers[nextGreen]][1])+len(vehicles[directionNumbers[nextGreen]][2])-vehicles[directionNumbers[nextGreen]]['crossed'] # print("no. of vehicles = ",noOfVehicles) noOfCars, noOfBuses, noOfTrucks, noOfRickshaws, noOfBikes = 0,0,0,0,0 for j in range(len(vehicles[directionNumbers[nextGreen]][0])): vehicle = vehicles[directionNumbers[nextGreen]][0][j] if(vehicle.crossed==0): vclass = vehicle.vehicleClass # print(vclass) noOfBikes += 1 for i in range(1,3): for j in range(len(vehicles[directionNumbers[nextGreen]][i])): vehicle = vehicles[directionNumbers[nextGreen]][i][j] if(vehicle.crossed==0): vclass = vehicle.vehicleClass # print(vclass) if(vclass=='car'): noOfCars += 1 elif(vclass=='bus'): noOfBuses += 1 elif(vclass=='truck'): noOfTrucks += 1 elif(vclass=='rickshaw'): noOfRickshaws += 1 # print(noOfCars) greenTime = math.ceil(((noOfCars*carTime) + (noOfRickshaws*rickshawTime) + (noOfBuses*busTime) + (noOfTrucks*truckTime)+ (noOfBikes*bikeTime))/(noOfLanes+1)) # greenTime = math.ceil((noOfVehicles)/noOfLanes) print('Green Time: ',greenTime) if(greenTimedefaultMaximum): greenTime = defaultMaximum # greenTime = random.randint(15,50) signals[(currentGreen+1)%(noOfSignals)].green = greenTime def repeat(): global currentGreen, currentYellow, nextGreen while(signals[currentGreen].green>0): # while the timer of current green signal is not zero printStatus() updateValues() if(signals[(currentGreen+1)%(noOfSignals)].red==detectionTime): # set time of next green signal thread = threading.Thread(name="detection",target=setTime, args=()) thread.daemon = True thread.start() # setTime() time.sleep(1) currentYellow = 1 # set yellow signal on vehicleCountTexts[currentGreen] = "0" # reset stop coordinates of lanes and vehicles for i in range(0,3): stops[directionNumbers[currentGreen]][i] = defaultStop[directionNumbers[currentGreen]] for vehicle in vehicles[directionNumbers[currentGreen]][i]: vehicle.stop = defaultStop[directionNumbers[currentGreen]] while(signals[currentGreen].yellow>0): # while the timer of current yellow signal is not zero printStatus() updateValues() time.sleep(1) currentYellow = 0 # set yellow signal off # reset all signal times of current signal to default times signals[currentGreen].green = defaultGreen signals[currentGreen].yellow = defaultYellow signals[currentGreen].red = defaultRed currentGreen = nextGreen # set next signal as green signal nextGreen = (currentGreen+1)%noOfSignals # set next green signal signals[nextGreen].red = signals[currentGreen].yellow+signals[currentGreen].green # set the red time of next to next signal as (yellow time + green time) of next signal repeat() # Print the signal timers on cmd def printStatus(): for i in range(0, noOfSignals): if(i==currentGreen): if(currentYellow==0): print("GREEN TS",i+1,"-> r:",signals[i].red," y:",signals[i].yellow," g:",signals[i].green) else: print("YELLOW TS",i+1,"-> r:",signals[i].red," y:",signals[i].yellow," g:",signals[i].green) else: print("RED TS",i+1,"-> r:",signals[i].red," y:",signals[i].yellow," g:",signals[i].green) print() # Update values of the signal timers after every second def updateValues(): for i in range(0, noOfSignals): if(i==currentGreen): if(currentYellow==0): signals[i].green-=1 signals[i].totalGreenTime+=1 else: signals[i].yellow-=1 else: signals[i].red-=1 # Generating vehicles in the simulation def generateVehicles(): while(True): vehicle_type = random.randint(0,4) if(vehicle_type==4): lane_number = 0 else: lane_number = random.randint(0,1) + 1 will_turn = 0 if(lane_number==2): temp = random.randint(0,4) if(temp<=2): will_turn = 1 elif(temp>2): will_turn = 0 temp = random.randint(0,999) direction_number = 0 a = [400,800,900,1000] if(temp