-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Driver profiling sim #30
Open
jinayang15
wants to merge
1
commit into
uw-midsun:main
Choose a base branch
from
jinayang15:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
Names,Average Velocity (km/h),Total Time Elapsed (min),Power Expenditure (W),Percentage of time following recommended speed,Behaviour Score,Emergency Preparedness Score,Enjoyment Score | ||
Raymond,31.39,4.78,145.79,52.5,Moderate,2,4 | ||
Kathryn,27.21,5.51,94.23,81.32,Safe,1,5 | ||
Robert,28.48,5.27,105.87,75.86,Safe,3,1 | ||
Steven,28.07,5.34,100.44,87.78,Safe,2,2 | ||
David,32.47,4.62,155.87,39.74,Reckless,3,4 | ||
Timothy,29.88,5.02,122.29,59.26,Moderate,5,3 | ||
Sandra,31.83,4.71,149.44,48.1,Reckless,1,2 | ||
Jeremy,28.41,5.28,103.15,71.91,Safe,5,2 | ||
David,34.2,4.39,178.49,31.08,Reckless,2,4 | ||
Lisa,25.79,5.82,79.08,89.47,Safe,1,5 | ||
Jesus,28.1,5.34,103.61,80.9,Safe,5,3 | ||
Sheila,30.52,4.92,129.26,43.75,Reckless,5,3 | ||
Kathy,27.03,5.55,88.33,90.43,Safe,1,3 | ||
Amy,27.46,5.46,97.1,70.11,Safe,4,5 | ||
Karyn,29.34,5.11,114.33,82.95,Safe,2,1 | ||
Donna,29.63,5.06,121.32,60.98,Moderate,3,1 | ||
Derrick,29.69,5.05,122.92,56.63,Moderate,2,3 | ||
Chris,29.63,5.06,121.21,56.63,Moderate,5,3 | ||
Lois,30.52,4.92,132.06,51.25,Moderate,1,4 | ||
Brad,29.34,5.11,113.36,53.09,Moderate,5,2 | ||
Matthew,26.81,5.6,90.74,89.58,Safe,1,4 | ||
Russell,31.21,4.81,141.06,46.25,Reckless,4,5 | ||
Jeff,27.78,5.4,96.55,83.7,Safe,1,4 | ||
Len,35.16,4.27,204.7,16.9,Reckless,2,2 | ||
John,29.44,5.1,115.13,67.06,Moderate,1,1 | ||
Elizabeth,30.79,4.87,137.6,46.84,Reckless,4,1 | ||
Emily,26.69,5.62,86.5,86.96,Safe,4,5 | ||
Aaron,29.0,5.17,114.39,68.18,Moderate,3,4 | ||
Arnold,28.94,5.18,113.55,59.04,Moderate,4,1 | ||
Annalee,27.45,5.47,94.39,89.47,Safe,3,1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
import pandas as pd | ||
import matplotlib.pyplot as plt | ||
import simpy | ||
import random | ||
import names | ||
|
||
#simulating driver data | ||
#1 time unit = 1 min | ||
#things to consider: | ||
#stop lights - currently have "crosswalks", how do we consider stoplights? | ||
#speed limits - how to consider speed limits? split up the route into different parts then combining the data? | ||
#picking the best driver? | ||
|
||
class Route: | ||
#distance - set distance in km | ||
#recommended_speed - in km/h | ||
#maxstop - max # of stops | ||
#deltat - time increment in minutes | ||
def __init__(self, route_name, distance, recommended_speed, maxstop, deltat): | ||
self.route_name = route_name | ||
self.distance = distance | ||
self.recommended_speed = recommended_speed | ||
self.maxstop = maxstop | ||
self.deltat = deltat | ||
|
||
class Driver: | ||
#drivers - number of drivers | ||
#inc - speed increment in km/h | ||
drivers = 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great use of static variables :) |
||
inc = 0 | ||
all_velocities = [] | ||
all_times = [] | ||
all_pwr_exp = [] | ||
all_safe_time = [] | ||
all_behaviour_scores = [] | ||
all_eps = [] | ||
all_enjoyment_score = [] | ||
|
||
def __init__(self, env, route, inc): | ||
#driverID - driver number | ||
#driver_stats - array containing name, avg velocity, time elapsed, power expenditure, % of time following | ||
#recommended speed (safe time), behaviour score, emergency preparedness score, enjoyment score | ||
#name - randomly generated name | ||
#mass - weight of person, in kg | ||
#eps - emergency preparedness score from 1 to 5 | ||
#enjoy - enjoyment score from 1 to 5 | ||
#distance_left - distance left to travel in km | ||
self.env = env | ||
self.driverID = self.drivers | ||
self.driver_stats = [] | ||
self.name = names.get_first_name() | ||
self.mass = random.randint(40,100) | ||
self.eps = random.randint(1,5) | ||
self.enjoy = random.randint(1,5) | ||
self.distance_left = route.distance | ||
Driver.inc = inc | ||
|
||
#powerexp - power expenditure calculated by kinetic energy/time in Watts | ||
#time_elapsed - time it took to complete route in minutes | ||
#current_speed - keep track of current speed in km/h | ||
#avg_speed - average speed over time in km/h | ||
#behaviour_score - "Safe" >= 70%, "Moderate" >= 50%, "Reckless" < 50% | ||
#safetime - % time at recommended speed | ||
#stops - number of stops made | ||
self.power_exp = 0 | ||
self.time_elapsed = 0 | ||
self.current_speed = 0 | ||
self.avg_speed = 0 | ||
self.behaviour_score = 0 | ||
self.safetime = 0 | ||
self.stops = 0 | ||
|
||
#speeds - for calculating safe time | ||
self.speeds = [] | ||
self.speedtimes = [] | ||
|
||
def update_values(self, route, time_elapsed): | ||
self.time_elapsed = time_elapsed | ||
#km/(min/60 -> hours) | ||
self.avg_speed = route.distance/(self.time_elapsed/60) | ||
#car weighs ~1000kg | ||
#power exp per hour | ||
self.power_exp = 0.5*(self.mass + 1000)*pow(self.avg_speed/3.6,2)/(self.time_elapsed*60) | ||
|
||
#calculate percentage of time within recommended speed (can be changed) | ||
sum_safe = 0 | ||
for i in range (-2,2): | ||
sum_safe += self.speeds.count(route.recommended_speed+i*Driver.inc) | ||
self.safetime = min(100,round(sum_safe/len(self.speeds),4) * 100) | ||
|
||
#calculate behaviour score (can be changed) | ||
if (self.safetime > 50): | ||
if (self.safetime >= 70): | ||
self.behaviour_score = "Safe" | ||
else: | ||
self.behaviour_score = "Moderate" | ||
else: self.behaviour_score = "Reckless" | ||
|
||
self.driver_stats = [self.name, round(self.avg_speed,2), round(self.time_elapsed,2), round(self.power_exp,2), | ||
round(self.safetime,2), self.behaviour_score, self.eps, self.enjoy] | ||
|
||
Driver.all_velocities.append(self.driver_stats[1]) | ||
Driver.all_times.append(self.driver_stats[2]) | ||
Driver.all_pwr_exp.append(self.driver_stats[3]) | ||
Driver.all_safe_time.append(self.driver_stats[4]) | ||
Driver.all_behaviour_scores.append(self.driver_stats[5]) | ||
Driver.all_eps.append(self.driver_stats[6]) | ||
Driver.all_enjoyment_score.append(self.driver_stats[7]) | ||
return self.driver_stats | ||
|
||
def start_car(self, env, route): | ||
#start car | ||
v0 = 0 | ||
v1 = route.recommended_speed/3.6 | ||
#2.0m/s^2 - average car acceleration | ||
a = 2.0 | ||
t = (v1-v0)/a | ||
d = (pow(v1,2)-pow(v0,2))/(2*a) | ||
self.current_speed = route.recommended_speed | ||
self.speeds.append((d/t)*3.6) | ||
self.distance_left -= d/1000 | ||
|
||
yield self.env.timeout(t/60) | ||
|
||
def stop_car(self, env, route): | ||
#stop car | ||
v0 = self.current_speed/3.6 | ||
v1 = 0 | ||
#2.0m/s^2 - average car acceleration | ||
a = -2.0 | ||
t = (v1-v0)/a | ||
d = (pow(v1,2)-pow(v0,2))/(2*a) | ||
self.current_speed = 0 | ||
self.speeds.append((d/t)*3.6) | ||
self.distance_left -= d/1000 | ||
|
||
yield self.env.timeout(t/60) | ||
|
||
|
||
def move(self, route): | ||
x = random.uniform(0,1) | ||
#40% chance to speed up | ||
if (x >= 0.7): | ||
if (self.current_speed < route.recommended_speed + self.inc*5): | ||
self.current_speed += self.inc | ||
#20% to slow down | ||
elif (x <= 0.3): | ||
if (self.current_speed > route.recommended_speed - self.inc*2): | ||
self.current_speed -= self.inc | ||
#distance remaining calculation | ||
self.distance_left -= (self.current_speed/60)*route.deltat | ||
#keep track of speed based on the set interval | ||
self.speeds.append(self.current_speed) | ||
yield self.env.timeout(route.deltat) | ||
|
||
def drive_route(env, driver, route): | ||
start_time = env.now | ||
|
||
#actually driving | ||
while (driver.distance_left > 0): | ||
#accelerating from stop | ||
if (driver.current_speed == 0): | ||
yield env.process(driver.start_car(env, route)) | ||
#self.speedtime(env.now-start_time) | ||
#drive car | ||
else: | ||
yield env.process(driver.move(route)) | ||
#chance of stopping at crosswalks 50% | ||
if (driver.stops < route.maxstop): | ||
if (random.choice([True, False])): | ||
yield env.process(driver.stop_car(env, route)) | ||
#let the people cross the street | ||
yield env.timeout(random.randint(3,15)/60) | ||
yield env.process(driver.start_car(env, route)) | ||
driver.stops += 1 | ||
|
||
#time spent | ||
time_elapsed = env.now-start_time | ||
#calculate driver stats | ||
driver.update_values(route, time_elapsed) | ||
|
||
def sim_drivers(env, route, num_drivers): | ||
driver_instances =[] | ||
for i in range (num_drivers): | ||
d = Driver(env, route, 3) | ||
env.process(drive_route(env, d, route)) | ||
driver_instances.append(d) | ||
return driver_instances | ||
|
||
|
||
def get_route(): | ||
|
||
route_name = "Ring Road" | ||
distance = 2.5 | ||
recommended_speed = 35 | ||
maxstop = 4 | ||
deltat = 3/60 | ||
num_drivers = 30 | ||
''' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move the triple quotes before the initialization of values. |
||
route_name = input("Input route name: ") | ||
distance = float(input("Input route length in km: ")) | ||
recommended_speed = int(input("Input recommended speed in km/h: ")) | ||
maxstop = int(input("Input # of crosswalks: ")) | ||
deltat = float(input("Input time between speed updates in minutes: ")) | ||
num_drivers = int(input("Input number of drivers to simulate: ")) | ||
''' | ||
params = [route_name, distance, recommended_speed, maxstop, deltat, num_drivers] | ||
return params | ||
|
||
def plot_avg_velocity_vs_time(): | ||
plt.figure(1) | ||
plt.scatter(Driver.all_times, Driver.all_velocities) | ||
plt.xlabel('Total time (min)') | ||
plt.ylabel('Average Velocity (km/h)') | ||
plt.title('Average Velocity vs Time') | ||
|
||
def plot_behaviour_score(): | ||
plt.figure(2) | ||
categories = ["Reckless", "Moderate", "Safe"] | ||
values = [Driver.all_behaviour_scores.count("Reckless"), Driver.all_behaviour_scores.count("Moderate"), Driver.all_behaviour_scores.count("Safe")] | ||
plt.bar(categories, values) | ||
plt.title("Driver Behaviour Scores") | ||
|
||
def main(): | ||
#gets the same data every time | ||
#can delete to randomize | ||
random.seed(100) | ||
#take in route variables | ||
route_name, distance, recommended_speed, maxstop, deltat, num_drivers = get_route() | ||
route = Route(route_name, distance, recommended_speed, maxstop, deltat) | ||
|
||
env = simpy.Environment() | ||
#contains all the drivers | ||
driver_instances = sim_drivers(env,route,num_drivers) | ||
env.run() | ||
|
||
#all the different stats | ||
headings = ["Names", "Average Velocity (km/h)", "Total Time Elapsed (min)", "Power Expenditure (W)", | ||
"Percentage of time following recommended speed", "Behaviour Score", "Emergency Preparedness Score", | ||
"Enjoyment Score"] | ||
|
||
data = [driver.driver_stats for driver in driver_instances] | ||
df = pd.DataFrame(data, columns=headings) | ||
df.to_csv(f"{route_name} Drivers.csv", index=False) | ||
|
||
plot_avg_velocity_vs_time() | ||
plot_behaviour_score() | ||
plt.show() | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pandas | ||
names | ||
simpy | ||
matplotlib |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use triple quotes for documenting multiple lines code logic or field descriptions.
For single line comments the # is fine, and add a space after the
#
and then write the comment.