
Final Deliverables
Raspberry Pi Housing


Wearable Device




Engineering Drawings



Computer Program
************************************************************
*** Program Implementation - STUDENT CODE BEGINS HERE! ***
************************************************************
Below this line is where you should IMPLEMENT each of the
required tasks.
- DO NOT define any functions in this section!
- You can liken this to a main() function where you
would implement your individual functions in your
Lab Mini-Milestones
- PAY ATTENTION TO YOUR INDENTATIONS!!!!
'''
## Start with indentation aligned with this comment
#Variable/object initializations
#LED status guide
#Starting message
print("Red led - Fall detected")
print("Green led (solid) - Standby mode")
print("Green led (flashing) - Charging\n\n\n")
#Initialize files that the program will write to
Start_Up_Routine()
#Account login and password for twilio account
account_sid = "AC7aa58358d003cc3b1b4dd33a53962c8e"
auth_token = "a907c4305a35e1daa00e9b471e91f06b"
#Contacts to call upon medical emergency
priority_contact = "+16479182542" #Dorian's Number
contacts = [priority_contact]
#Initializing the twilio object and its client
Twilio = Twilio_Client(account_sid, auth_token, contacts)
Twilio.Initialize_Client()
#Initializing the sensor object
Sensor = Orientation_Sensor()
#Initializing the button object and the charging button on pin 21 and pin 26 respectively
Push_Button = Button(21)
Charging_Button = Button(26)
#^^ Is meant to simulate what would happen if the watch was charging. The button doesn't actually exist, it's just for demo purposes
#Initializing the buzzer object on pin 18
buzzer = Buzzer(18)
#Initializing the red and green leds on pins 24 and 12 respectively
Red_Led = LED(24)
Green_Led = LED(12)
#Initializing the watch graphical user interface
Watch = Watchface()
#Getting a buffer of data - prevents an index error later on
Read_Data(Sensor,5,0.1)
#Counter to keep count of time, this allows the program to read data from the sensor at set intervals
counter = 0
#Insures that the program runs at a set speed
program_speed_limit = 0.05
Green_Led.on()
while True:
time.sleep(program_speed_limit)
emergency_flag = False
#Read data
if (round(counter,2)%0.75 == 0):
Read_Data(Sensor,5,0.1)
Calculate_Rolling_Average(10)
Calculate_Average_Velocity(2,0.75)
Calculate_Average_Acceleration(2,0.75)
#Flags that determine if a fall has occured
sudden_movement_flag = Detect_Sudden_Movement()
flag_rolling_ank, flag_rolling_wr = Detect_Pos_Diff()
flags = [flag_rolling_ank, flag_rolling_wr, sudden_movement_flag]
#Based on the flags, did a fall happen?
Detect_Fall(flags, Sensor, Watch, Push_Button, Twilio, buzzer, Red_Led, Green_Led)
#Manual help request
if (Push_Button.is_pressed):
emergency_flag = Manual_Alert(Push_Button, Watch, buzzer, Red_Led, Green_Led)
#Manual_Alert has registered as true, help is needed
if (emergency_flag):
Twilio.Call_For_Help()
#Getting a buffer of data - prevents an index error later on
Read_Data(Sensor,10,0.1)
Calculate_Rolling_Average(10)
Calculate_Average_Velocity(2,0.75)
Calculate_Average_Acceleration(2,0.75)
Watch.Rectangle_Transition(Watch.colour_bank["black"])
#Watch is charging
if (Charging_Button.is_pressed):
#Device put to charge, back up files
Archiving_Routine()
#Getting a buffer of data - prevents an index error later on
Read_Data(Sensor,10,0.1)
Calculate_Rolling_Average(10)
Calculate_Average_Velocity(2,0.75)
Calculate_Average_Acceleration(2,0.75)
Watch.Charging(Green_Led, Charging_Button)
#Display the time
Watch.Display_Time()
counter+=program_speed_limit
'''
************************************************************
*** Program Implementation - STUDENT CODE ENDS HERE! ***
************************************************************
'''
except:
(type, value, traceback) = sys.exc_info()
sys.excepthook(type, value, traceback)
sys.exit(1)
def stop(self):
self.is_running = False
print('stopping thread...')
self.terminate()
'''
************************************************************
*** Function Definitions - STUDENT CODE BEGINS HERE! ***
************************************************************
Below this line is where you should DEFINE all functions
- Any output devices that are used in your functions
should be defined here as well
- PAY ATTENTION TO YOUR INDENTATIONS!!!!
'''
#imports
import os
from twilio.rest import Client
import matplotlib.pyplot as plt
import numpy as np
import pygame
import math
from datetime import datetime as dt
class Twilio_Client:
def __init__(self, ID, auth, contacts, your_number="+16145023894"):
self.ID = ID
self.auth = auth
self.contacts = contacts
self.your_number = your_number
def Call_For_Help(self):
for contact in self.contacts:
#Text the priority contact
message = self.client.messages.create(
to=contact,
from_= self.your_number,
body="This is an automated message from Team-13. Your loved one has fallen and needs urgent medical care.")
#The api does one command a second therefore there needs to be a delay
time.sleep(2)
#Call the priority contact
call = self.client.calls.create(
url = 'http://demo.twilio.com/docs/voice.xml',
to=contact,
from_= self.your_number,
)
#Archive and wipe files
Archiving_Routine()
def Initialize_Client(self):
#Creates the twilio client to permit calling/texting
self.client = Client(self.ID, self.auth)
class Watchface:
def __init__(self):
#Initializations
pygame.init()
pygame.display.init()
pygame.font.init()
#Colour bank
self.colour_bank = {"red":(255,0,0),
"blue":(0,0,255),
"green":(0,255,0),
"white":(255,255,255),
"black":(0,0,0),
"yellow":(255,255,0),
"turquoise":(64,224,208),
"magenta":(255,0,255),
"teal":(0,128,128)}
#Default font
self.font_style = pygame.font.match_font("arial")
#Initializing screen
self.length = 640
self.width = 480
self.dimensions = (self.length,self.width)
self.screen = pygame.display.set_mode(self.dimensions)
#Allows the watch to keep track of how many milliseconds have passed since initialization
self.timer = 0
def Automatic_Help_Request(self,message,time=0):
#Get countdown time as integer
time_left = int((60-time)//1)
if (round(time,2)%2==0):
#Shell update within an if statement to limit program lag
Combined_Information()
if time_left < 0:
#Because of floating point errors the time will appear as negative at zero
time_left = 0
time_left = str(time_left)
self.screen.fill(self.colour_bank["red"])
#Message will be written in two lines, initializing variables
line1 = ""
line2 = ""
#Finding desired message
if message == 1:
line1 = "Help sequence"
line2 = "Initialized"
elif message == 2:
line1 = "Help sequence"
line2 = "Aborted"
elif message == 3:
line1 = "Help is"
line2 = "On the way"
elif message == 4:
line1 = "Fall detected"
line2 = "Press button"
time_left = "to cancel" #"to cancel" isn't the time left but should be written in the same spot as "time left" would be written in
#Draw circle
center = (self.length//2,self.width//2)
pygame.draw.circle(self.screen,self.colour_bank["turquoise"],center,abs(int((self.length/3)-20*math.sin(self.timer/500))))
#Write message to screen
self.Text_To_Screen(line1,50,self.colour_bank["black"],self.length/2,3*self.width/8)
self.Text_To_Screen(line2,50,self.colour_bank["black"],self.length/2,4*self.width/8)
self.Text_To_Screen(time_left,50,self.colour_bank["black"],self.length/2,5*self.width/8)
#Update display
self.Update_Screen()
def Charging(self,Green_Led, Charging_Button):
counter = 0
self.Rectangle_Transition(self.colour_bank["teal"])
while Charging_Button.is_pressed:
if (round(counter,2)%1==0):
#Shell update within an if statement to limit program lag
Combined_Information()
#Background
self.screen.fill(self.colour_bank["teal"])
#Draw circle and text
center = (self.length//2,self.width//2)
pygame.draw.circle(self.screen,self.colour_bank["black"],center,abs(int((self.length/3)-20*math.sin(self.timer/500))))
self.Text_To_Screen("Charging",50,self.colour_bank["white"],self.length/2,self.width/2)
self.Update_Screen()
#Flash LED every 3 seconds
if ((self.timer//1000)%6 == 0):
Green_Led.off()
elif ((self.timer//1000)%3 == 0):
Green_Led.on()
time.sleep(0.05)
counter += 0.05
#Charging has stopped
Green_Led.off()
self.Rectangle_Transition(self.colour_bank["black"])
def Display_Time(self):
#Shell update
Combined_Information()
#Fetch current time
time = Get_Current_Time()
#Update screen to have black background with the time and message displayed
self.screen.fill(self.colour_bank["black"])
self.Text_To_Screen(time,100,self.colour_bank["white"],self.length/2,2*self.width/5)
message = "Push button for 10 seconds for EMS"
self.Text_To_Screen(message,20,self.colour_bank["white"],self.length/2,3*self.width/4-10*math.sin(self.timer/500)) #The sin function is for animating the text
self.Update_Screen()
def Manual_Help_Request(self,time,message):
if (round(time,2)%2==0):
#Shell update within an if statement to limit program lag
Combined_Information()
#Get countdown time as integer and cast as string
time_left = int((10-time)//1)
if time_left < 0:
#Because of floating point errors the time will appear as negative at zero
time_left = 0
time_left = str(time_left)
self.screen.fill(self.colour_bank["white"])
#Message will be written in two lines, initializing variables
line1 = ""
line2 = ""
#Finding desired message
if message == 1:
line1 = "Help sequence"
line2 = "Initialized"
elif message == 2:
line1 = "Help sequence"
line2 = "Aborted"
elif message == 3:
line1 = "Help is"
line2 = "On the way"
#Draw circle
center = (self.length//2,self.width//2)
pygame.draw.circle(self.screen,self.colour_bank["turquoise"],center,abs(int((self.length/3)-20*math.sin(self.timer/500))))
#Write message to screen
self.Text_To_Screen(line1,50,self.colour_bank["black"],self.length/2,3*self.width/8)
self.Text_To_Screen(line2,50,self.colour_bank["black"],self.length/2,4*self.width/8)
self.Text_To_Screen(time_left,50,self.colour_bank["black"],self.length/2,5*self.width/8)
#Update display
self.Update_Screen()
def Rectangle_Transition(self,colour):
#General info: this method is the animation between different watch screens
#The dimensions of the drawn on rectangles
final_rect_len = self.length
final_rect_width = self.width//2
#The rectangles will increase in size, starting from zero
curr_rect_width = 0
for i in range(2,10):
#Using the harmonic series to reduce the change in size of rectangles that will be on screen
curr_rect_width += final_rect_width * (1/i)
#Rectangle from top
#Dimensions(left, top, length, width)
dimensions_top = (0,0,self.length,curr_rect_width)
pygame.draw.rect(self.screen,colour,dimensions_top)
#Rectangle from bottom
top_coord = self.width - curr_rect_width
dimensions_bottom = (0,top_coord,self.length,curr_rect_width)
pygame.draw.rect(self.screen, colour,dimensions_bottom)
#Update screen
self.Update_Screen()
time.sleep(0.1)
def Text_To_Screen(self,text,size,colour,x,y):
#Setting the specific font and size for the desired text
text_font = pygame.font.Font(self.font_style,size)
#Pygame can't write directly onto the screen therefore the font must be "rendered" onto a new surface
text_surface = text_font.render(text, True, colour)
#Find how big the new surface is
text_rect = text_surface.get_rect()
#Setting where the middle of the top bar will be placed on the screen
text_rect.center = (x,y)
#Paste the text to the screen
self.screen.blit(text_surface, text_rect)
def Update_Screen(self):
#Updates screen and internal clock
pygame.display.flip()
self.timer = pygame.time.get_ticks()
def Alert_User(Sensor, Watch, Push_Button, Twilio, buzzer, Red_Led, Green_Led):
#Setting initial value to trigger the while loop
acc = -1
#Other variable initalizations
increment = 0.1 #seconds
threshold = 70 #degrees
time_limit = 60 #seconds
message = 4
counter = 0
emergency_flag = True
#Updating the GUI
Watch.Rectangle_Transition(Watch.colour_bank["red"])
Green_Led.off()
Red_Led.on()
#Turn on buzzer to alert the user
buzzer.on()
while acc != 0:
#Waiting to the fall to complete. When fall is finished, acceleration will be zero
#Display that a fall was detected
Watch.Automatic_Help_Request(message)
#Flags
wrist_zero = False
ankle_zero = False
#Continue recording data
time.sleep(0.25)
Read_Data(Sensor,5,0.1)
Calculate_Rolling_Average(10)
Calculate_Average_Velocity(2,0.75)
Calculate_Average_Acceleration(2,0.75)
#read wrist data from acceleration file
accel_file = open('average_acceleration_wr.txt','r')
last_line = accel_file.readlines()[-1].split()
yaw_accel = float(last_line[0])
roll_accel = float(last_line[1])
pitch_accel = float(last_line[2])
yaw_zero = False
roll_zero = False
pitch_zero = False
#Deadzoning - in real life the acceleration values will never be zero so as long as they're within a range we'll be good to continue
if(abs(yaw_accel) < 0.5):
yaw_zero = True
if(abs(roll_accel)<0.5):
roll_zero = True
if(abs(pitch_accel)<0.5):
pitch_zero = True
if (yaw_zero and roll_zero and pitch_zero):
wrist_zero = True
#read ankle data from acceleration file
accel_file = open('average_acceleration_ank.txt','r')
last_line = accel_file.readlines()[-1].split()
yaw_accel = float(last_line[0])
roll_accel = float(last_line[1])
pitch_accel = float(last_line[2])
yaw_zero = False
roll_zero = False
pitch_zero = False
#Deadzoning - in real life the acceleration values will never be zero so as long as they're within a range we'll be good to continue
if(abs(yaw_accel) < 0.5):
yaw_zero = True
if(abs(roll_accel)<0.5):
roll_zero = True
if(abs(pitch_accel)<0.5):
pitch_zero = True
if (yaw_zero and roll_zero and pitch_zero):
ankle_zero = True
if (Push_Button.is_pressed):
emergency_flag = False
message = 2
#Update GUI, let the user know that the sequence has been aborted
Watch.Automatic_Help_Request(message)
#Turn off buzzer and LED
buzzer.off()
Red_Led.off()
Green_Led.on()
#Extra time to read message
time.sleep(2)
Watch.Rectangle_Transition(Watch.colour_bank["black"])
break
if (ankle_zero and wrist_zero):
acc = 0
#Give the user time to read the message
time.sleep(1)
#Read initial position values
reference_wr = open('rolling_average_wr.txt', 'r')
reference_value_wr = reference_wr.readlines()[-1].split()
reference_wr.close()
reference_ank = open('rolling_average_ank.txt', 'r')
reference_value_ank = reference_ank.readlines()[-1].split()
reference_ank.close()
#Split up the values
first_roll_wr = float(reference_value_wr[1])
first_pitch_wr = float(reference_value_wr[2])
first_roll_ank = float(reference_value_ank[1])
first_pitch_ank = float(reference_value_ank[2])
message = 1
while emergency_flag:
time.sleep(increment)
counter += increment
if Push_Button.is_pressed: #The user has cancelled the alert
emergency_flag = False
message = 2
#Turn off buzzer and LED
buzzer.off()
Red_Led.off()
Green_Led.on()
#Update the GUI, let them know that the help sequence has been aborted
Watch.Automatic_Help_Request(message,counter)
#Give user time to read message
time.sleep(2)
Watch.Rectangle_Transition(Watch.colour_bank["black"])
break
else:
#Update GUI, let them know how much time is left until help arrives
Watch.Automatic_Help_Request(message,counter)
#Time limit expired, exit loop and call for help
if counter >= time_limit:
#Turn off buzzer and LED
buzzer.off()
Red_Led.off()
Green_Led.on()
break
if emergency_flag == True:
#Read new position
Read_Data(Sensor,5,0.1)
Calculate_Rolling_Average(5)
#Get current position
reference_new_wr = open('rolling_average_wr.txt', 'r')
ref_new_wr = reference_new_wr.readlines()[-1].split()
reference_new_wr.close()
reference_new_ank = open('rolling_average_ank.txt', 'r')
ref_new_ank = reference_new_ank.readlines()[-1].split()
reference_new_ank.close()
second_roll_wr = float(ref_new_wr[1])
second_pitch_wr = float(ref_new_wr[2])
second_roll_ank = float(ref_new_ank[1])
second_pitch_ank = float(ref_new_ank[2])
#Initializing flags
wrist_unresponsive = False
ankle_unresponsive = False
#Check if both the ankle and wrist have moved drastically from original position in the y and z axis. If so, the user has likely gotten up and is ok
if (abs(first_roll_wr - second_roll_wr)< threshold and abs(first_pitch_wr - second_pitch_wr)<threshold):
wrist_unresponsive = True
if (abs(first_roll_ank - second_roll_ank)< threshold and abs(first_pitch_ank - second_pitch_ank)<threshold):
ankle_unresponsive = True
#If the user has moved both ankle and wrist above the threshold, they are most likely and haven't canceled the alert
if (wrist_unresponsive and ankle_unresponsive):
#Update the GUI
message = 3
Watch.Automatic_Help_Request(message,counter)
#Let user read message
time.sleep(2)
Watch.Rectangle_Transition(Watch.colour_bank["yellow"])
Twilio.Call_For_Help()
#Getting a buffer of data - prevents an index error later on
Read_Data(Sensor,10,0.1)
Calculate_Rolling_Average(10)
Calculate_Average_Velocity(2,0.75)
Calculate_Average_Acceleration(2,0.75)
Watch.Rectangle_Transition(Watch.colour_bank["black"])
else:
#person is okay and up
message = 2
#Update the GUI to notify that the sequence has been aborted
Watch.Automatic_Help_Request(message,counter)
#Give user time to read message
time.sleep(2)
Watch.Rectangle_Transition(Watch.colour_bank["black"])
def Archiving_Routine():
#Move all files to the archive folder
dst_path = "/home/pi/Emulator/Archive/"
src_path = "/home/pi/Emulator/"
current_time = Get_Current_Time_In_Seconds()
file_suffix = current_time + ".txt"
#Rolling average files
file_prefix = "rolling_average"
os.replace(src_path+"rolling_average_wr.txt",dst_path+file_prefix+"_wr_"+file_suffix)
os.replace(src_path+"rolling_average_ank.txt",dst_path+file_prefix+"_ank_"+file_suffix)
#Average velocity files
file_prefix = "average_velocity"
os.replace(src_path+"average_velocity_wr.txt",dst_path+file_prefix+"_wr_"+file_suffix)
os.replace(src_path+"average_velocity_ank.txt",dst_path+file_prefix+"_ank_"+file_suffix)
#Average acceleration files
file_prefix = "average_acceleration"
os.replace(src_path+"average_acceleration_wr.txt",dst_path+file_prefix+"_wr_"+file_suffix)
os.replace(src_path+"average_acceleration_ank.txt",dst_path+file_prefix+"_ank_"+file_suffix)
#wipe files clean
file = open("raw_data_wr.txt",'w')
file.close()
file = open("raw_data_ank.txt",'w')
file.close()
file = open("rolling_average_wr.txt",'w')
file.close()
file = open("rolling_average_ank.txt",'w')
file.close()
file = open("average_velocity_wr.txt",'w')
file.close()
file = open("average_velocity_ank.txt",'w')
file.close()
file = open("average_acceleration_wr.txt",'w')
file.close()
file = open("average_acceleration_ank.txt",'w')
file.close()
def Calculate_Average_Acceleration(data_size,input_interval):
#Average acceleration for wrist
#Initializing variables
yaw_difference = 0
roll_difference = 0
pitch_difference = 0
#Open average velocity file and calculate the average acceleration
with open("average_velocity_wr.txt",'r') as rolling_average_v:
#Calculate the average rate of change by using the current data and the data x lines in the past
all_lines = rolling_average_v.readlines()
last_lines = all_lines[-data_size:]
initial_position = last_lines[0].split()
final_position = last_lines[-1].split()
#Calculate the difference in yaw roll and pitch from the last and first data point
yaw_difference = float(final_position[0]) - float(initial_position[0])
roll_difference = float(final_position[1]) - float(initial_position[1])
pitch_difference = float(final_position[2]) - float(initial_position[2])
#Open a separate file and write the average acceleration
with open("average_acceleration_wr.txt", 'a') as average_acceleration:
#Calculating the average acceleration
ayaw_average = yaw_difference/(data_size*input_interval)
aroll_average = roll_difference/(data_size*input_interval)
apitch_average = pitch_difference/(data_size*input_interval)
#Formatting and writing the string
average = [str(ayaw_average),"\t",str(aroll_average),"\t",str(apitch_average),"\n"]
average_acceleration.writelines(average)
#Average acceleration for ankle
#Initializing variables
yaw_difference = 0
roll_difference = 0
pitch_difference = 0
#Open average velocity file and calculate the average acceleration
with open("average_velocity_ank.txt",'r') as rolling_average_v:
#Calculate the average rate of change by using the current data and the data x lines in the past
all_lines = rolling_average_v.readlines()
last_lines = all_lines[-data_size:]
initial_position = last_lines[0].split()
final_position = last_lines[-1].split()
#Calculate the difference in yaw roll and pitch from the last and first data point
yaw_difference = float(final_position[0]) - float(initial_position[0])
roll_difference = float(final_position[1]) - float(initial_position[1])
pitch_difference = float(final_position[2]) - float(initial_position[2])
#Open a separate file and write the average acceleration
with open("average_acceleration_ank.txt", 'a') as average_acceleration:
#Calculating the average acceleration
ayaw_average = yaw_difference/(data_size*input_interval)
aroll_average = roll_difference/(data_size*input_interval)
apitch_average = pitch_difference/(data_size*input_interval)
#Formatting and writing the string
average = [str(ayaw_average),"\t",str(aroll_average),"\t",str(apitch_average),"\n"]
average_acceleration.writelines(average)
def Calculate_Average_Velocity(data_size,input_interval):
#Average velocity for wrist
#Initializing variables
yaw_difference = 0
roll_difference = 0
pitch_difference = 0
#Open rolling average file and calculate the average velocity
with open("rolling_average_wr.txt",'r') as rolling_average:
#Calculate the average rate of change by using the current data and the data x lines in the past
all_lines = rolling_average.readlines()
last_lines = all_lines[-data_size:]
initial_position = last_lines[0].split()
final_position = last_lines[-1].split()
#Calculate the difference in yaw roll and pitch from the last and first data point
yaw_difference = float(final_position[0]) - float(initial_position[0])
roll_difference = float(final_position[1]) - float(initial_position[1])
pitch_difference = float(final_position[2]) - float(initial_position[2])
#Open a separate file and write the average velocity
with open("average_velocity_wr.txt", 'a') as average_velocity:
#Calculating the average velocity
vyaw_average = yaw_difference/(data_size*input_interval)
vroll_average = roll_difference/(data_size*input_interval)
vpitch_average = pitch_difference/(data_size*input_interval)
#Formatting and writing the string
average = [str(vyaw_average),"\t",str(vroll_average),"\t",str(vpitch_average),"\n"]
average_velocity.writelines(average)
#Average velocity for ankle
#Initializing variables
yaw_difference = 0
roll_difference = 0
pitch_difference = 0
#Open rolling average file and calculate the average velocity
with open("rolling_average_ank.txt",'r') as rolling_average:
#Calculate the average rate of change by using the current data and the data x lines in the past
all_lines = rolling_average.readlines()
last_lines = all_lines[-data_size:]
initial_position = last_lines[0].split()
final_position = last_lines[-1].split()
#Calculate the difference in yaw roll and pitch from the last and first data point
yaw_difference = float(final_position[0]) - float(initial_position[0])
roll_difference = float(final_position[1]) - float(initial_position[1])
pitch_difference = float(final_position[2]) - float(initial_position[2])
#Open a separate file and write the average velocity
with open("average_velocity_ank.txt", 'a') as average_velocity:
#Calculating the average velocity
vyaw_average = yaw_difference/(data_size*input_interval)
vroll_average = roll_difference/(data_size*input_interval)
vpitch_average = pitch_difference/(data_size*input_interval)
#Formatting and writing the string
average = [str(vyaw_average),"\t",str(vroll_average),"\t",str(vpitch_average),"\n"]
average_velocity.writelines(average)
def Calculate_Rolling_Average(data_size):
#Rolling average for wrist
#Initializing variables
yaw_total = 0
roll_total = 0
pitch_total = 0
#Read 10 latest data points for pitch roll and yaw
with open("raw_data_wr.txt",'r') as file1:
all_lines = file1.readlines()
#Retreive the last x lines of data
last_lines = all_lines[-data_size:]
#iterate through each line in the dataset and find the sum
for i in range(len(last_lines)):
line_buffer = last_lines[i]
line_buffer = line_buffer.split()
yaw_total += float(line_buffer[0])
roll_total += float(line_buffer[1])
pitch_total += float(line_buffer[2])
#Calculate the average of the last x data points and write to file
with open("rolling_average_wr.txt",'a') as file2:
yaw_average = round(yaw_total/data_size,2)
roll_average = round(roll_total/data_size,2)
pitch_average = round(pitch_total/data_size,2)
average = [str(yaw_average),"\t",str(roll_average),"\t",str(pitch_average),"\n"]
file2.writelines(average)
#Rolling average for ankle
#Initializing variables
yaw_total = 0
roll_total = 0
pitch_total = 0
#Read 10 latest data points for pitch roll and yaw
with open("raw_data_ank.txt",'r') as file1:
all_lines = file1.readlines()
#Retreive the last x lines of data
last_lines = all_lines[-data_size:]
#iterate through each line in the dataset and find the sum
for i in range(len(last_lines)):
line_buffer = last_lines[i]
line_buffer = line_buffer.split()
yaw_total += float(line_buffer[0])
roll_total += float(line_buffer[1])
pitch_total += float(line_buffer[2])
#Calculate the average of the last x data points and write to file
with open("rolling_average_ank.txt",'a') as file2:
yaw_average = yaw_total/data_size
roll_average = roll_total/data_size
pitch_average = pitch_total/data_size
average = [str(yaw_average),"\t",str(roll_average),"\t",str(pitch_average),"\n"]
file2.writelines(average)
def Combined_Information():
#This function is exclusively to display the current state of all of the output devices and the sensor data
raw_data_file_wr = open("raw_data_wr.txt",'r')
raw_data_file_ank = open("raw_data_ank.txt",'r')
rolling_average_file_wr = open("rolling_average_wr.txt",'r')
rolling_average_file_ank = open("rolling_average_ank.txt",'r')
raw_data_wr = raw_data_file_wr.readlines()[-1]
raw_data_ank = raw_data_file_ank.readlines()[-1]
average_pos_wr = rolling_average_file_wr.readlines()[-1]
average_pos_ank = rolling_average_file_ank.readlines()[-1]
#Determines if the output devices are in the on or off state
red_status = "On" if led6State_var else "Off"
green_status = "On" if led4State_var else "Off"
buzzer_status = "On" if buzzer1State_var else "Off"
#Shell update
print(raw_data_wr.split()[0],raw_data_wr.split()[1],raw_data_wr.split()[2],"\t\t",
raw_data_ank.split()[0],raw_data_ank.split()[1],raw_data_ank.split()[2],"\t",
average_pos_wr.split()[0],average_pos_wr.split()[1],average_pos_wr.split()[2],"\t",
average_pos_ank.split()[0],average_pos_ank.split()[1],average_pos_ank.split()[2],"\t",
buzzer_status,"\t\t",red_status,"\t\t",green_status)
#Writing all this information to a file
processed_information_file = open("Processed_info.txt",'a')
processed_information_file.writelines(["\n",raw_data_wr.split()[0]," ",raw_data_wr.split()[1]," ",raw_data_wr.split()[2],"\t\t",
raw_data_ank.split()[0]," ",raw_data_ank.split()[1]," ",raw_data_ank.split()[2],"\t",
average_pos_wr.split()[0]," ",average_pos_wr.split()[1]," ",average_pos_wr.split()[2],"\t",
average_pos_ank.split()[0]," ",average_pos_ank.split()[1]," ",average_pos_ank.split()[2],"\t",
buzzer_status,"\t\t",red_status,"\t\t",green_status])
def Detect_Fall(flags, Sensor, Watch, Push_Button, Twilio, buzzer, Red_Led, Green_Led):
#If fall has been detected, alert user
if flags[0] == True and flags[1] == True and flags[2] == True:
Alert_User(Sensor, Watch, Push_Button, Twilio, buzzer, Red_Led, Green_Led)
def Detect_Pos_Diff():
#Initialize flags/variables
flag_rolling_wr = False
flag_rolling_ank = False
threshold = 30
#Retreive the last two lines in the rolling_average file and separate into initial and final values for wrist
file_rolling_av_wr = open("rolling_average_wr.txt", 'r')
rolling_av_wr = file_rolling_av_wr.readlines()
last_lines_wr = rolling_av_wr[-2:]
initial_position_wr = last_lines_wr[0].split()
final_position_wr = last_lines_wr[-1].split()
#Retreive the last two lines in the rolling_average file and separate into initial and final values for ankle
file_rolling_av_ank = open("rolling_average_ank.txt", 'r')
rolling_av_ank = file_rolling_av_ank.readlines()
last_lines_ank = rolling_av_ank[-2:]
initial_position_ank = last_lines_ank[0].split()
final_position_ank = last_lines_ank[-1].split()
wrist_roll_difference = abs(float(final_position_wr[1]) - float(initial_position_wr[1]))
wrist_pitch_difference = abs(float(final_position_wr[2]) - float(initial_position_wr[2]))
ankle_roll_difference = abs(float(final_position_ank[1]) - float(initial_position_ank[1]))
ankle_pitch_difference = abs(float(final_position_ank[2]) - float(initial_position_ank[2]))
#Check to see if threshold has been crossed
if wrist_roll_difference >= threshold:
flag_rolling_wr = True
if wrist_pitch_difference >= threshold:
flag_rolling_wr = True
if ankle_roll_difference >= threshold:
flag_rolling_ank = True
if ankle_pitch_difference >= threshold:
flag_rolling_ank = True
else:
pass
return flag_rolling_ank, flag_rolling_wr
def Detect_Sudden_Movement():
#If acceleration is above 7 deg/s^2 the threshold will be crossed
threshold = 7
#Set the flag to false by default
sudden_movement_detected = False
sudden_movement_detected_wr = False
sudden_movement_detected_ank = False
#Read the average acceleration and check to see if the threshold was passed for the wrist
with open("average_acceleration_wr.txt",'r') as accel:
#Isolating the last line
everything = accel.readlines()
average_accel = everything[-1].split()
#Isolating roll and pitch from the string list
roll = float(average_accel[1])
pitch = float(average_accel[2])
#Check to see if the acceleration has passed the threshold
if (abs(pitch) >= threshold):
sudden_movement_detected_wr = True
elif (abs(roll) >= threshold):
sudden_movement_detected_wr = True
#Read the average acceleration and check to see if the threshold was passed for the ankle
with open("average_acceleration_ank.txt",'r') as accel:
#Isolating the last line
everything = accel.readlines()
average_accel = everything[-1].split()
#Isolating roll and pitch from the string list
roll = float(average_accel[1])
pitch = float(average_accel[2])
#Check to see if the acceleration has passed the threshold
if (abs(pitch) >= threshold):
sudden_movement_detected_ank = True
elif (abs(roll) >= threshold):
sudden_movement_detected_ank = True
if (sudden_movement_detected_wr and sudden_movement_detected_ank):
sudden_movement_detected = True
#Return the flag
return sudden_movement_detected
def Get_Current_Time():
return dt.now().strftime("%H:%M")
def Get_Current_Time_In_Seconds():
return dt.now().strftime("%H:%M:%S")
def Manual_Alert(Push_Button, Watch, buzzer, Red_Led, Green_Led):
#If button is pushed to call for help
Green_Led.off()
Red_Led.on()
#Initializing variables
message = 1
time_interval = 0.1
counter = 0
emergency_flag = True
#Updating GUI
Watch.Rectangle_Transition(Watch.colour_bank["white"])
#Turn on buzzer to alert the user
buzzer.on()
while counter < 10:
if Push_Button.is_pressed:
#Show how much time is left before help is called
counter += time_interval
Watch.Manual_Help_Request(counter,message)
else: #Button has been released, help sequence aborted
#Turn off buzzer and LED
buzzer.off()
Red_Led.off()
Green_Led.on()
#Update GUI, show that help sequence has been aborted
message = 2
Watch.Manual_Help_Request(counter,message)
#Time out the program for 1 second
time.sleep(1.5)
emergency_flag = False
Watch.Rectangle_Transition(Watch.colour_bank["black"])
break
time.sleep(time_interval)
if emergency_flag:
#Call for help
message = 3
buzzer.off()
Red_Led.off()
Green_Led.on()
Watch.Manual_Help_Request(10,message)
return emergency_flag
def Read_Data(Sensor,data_size,speed):
#Reads data from orientation sensor and writes in file
file_wr = open("raw_data_wr.txt",'a')
file_ank = open("raw_data_ank.txt",'a')
for i in range(data_size):
time.sleep(speed)
data_tuple = Sensor.euler_angles()
data_str = [str(data_tuple[0]),"\t",str(data_tuple[1]),"\t",str(data_tuple[2]),"\n"]
file_wr.writelines(data_str)
file_ank.writelines(data_str)
file_wr.close()
file_ank.close()
#Yes, it is a bit redundant, the same data is being written to two files
#Our design necessitates two distinct sensors, one for the wrist and one of the ankle
#Because of the limitations of the emulator we can only have one orientation sensor
#If we were able to run two orientation sensors, the data being written to both files would be different
#To showcase how the code would work right now we're just writing the same set of data to both files
def Start_Up_Routine():
#Initialize files
file = open("raw_data_wr.txt",'w')
file.close()
file = open("raw_data_ank.txt",'w')
file.close()
file = open("rolling_average_wr.txt",'w')
file.close()
file = open("rolling_average_ank.txt",'w')
file.close()
file = open("average_velocity_wr.txt",'w')
file.close()
file = open("average_velocity_ank.txt",'w')
file.close()
file = open("average_acceleration_wr.txt",'w')
file.close()
file = open("average_acceleration_ank.txt",'w')
file.close()
#Purely to staisfy the DP-3 project requirements, not actually needed for functionality
file = open("Processed_info.txt",'w')
file.writelines(["|Wr raw pos (x,z,y)|","\t","|Ank raw pos|","\t","|Avg pos Wr|","\t","|Avg pos Ank|","\t","|Buzzer|","\t","|Red LED|","\t","|Green LED|"])
file.close()
#shell header
print("|Wr raw pos (x,z,y)|","\t","|Ank raw pos|","\t",
"|Avg pos Wr|","\t","|Avg pos Ank|","\t",
"|Buzzer|","\t","|Red LED|","\t","|Green LED|")
'''
************************************************************
*** Function Definitions - STUDENT CODE ENDS HERE! ***
************************************************************
'''
if __name__ == "__main__":
global mainObj
mainObj = MainWindow_EXEC()
Emulator




