Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 1 | ||||
![]() |
| × | 1 | |||
| × | 1 | ||||
Software apps and online services | ||||||
![]() |
| |||||
Story:
This project involves creating an autonomous car which features lane keeping. This is a commercial RC car. We integrated an Raspberry Pi control its motor movements. Our team comprised of Nathan Hsiao, Barret Glass, Sam Barton, and Jerry Jiang. We followed a tutorial by User raja_961, with his article "Autonomous Lane-Keeping Car Using Raspberry Pi and OpenCV”. Instructables" URL= https://www.instructables.com/Autonomous-Lane-Keeping-Car-Using-Raspberry-Pi-and/. In addition, we also used the Nicomobile for reference for the lane keeping code and the openCV: https://www.hackster.io/team-youngerwoods/the-nicomobile-83caa9.
Setting Resolution and Gain Parameters
For this section, we used our reference code provided by the Nicomobile. We used their proportional and derivative gain values. The selected value was k_p =0.2 and k_d=k_p=0.2*0.1. The values were computed through trial and error.
In addition, the resolution had a standard value of 320x240 (same as the Nicomobile). We had no issues with the default resolution, and we were able to grasp all the pixels with a resolution of 320x240.
Detect Red Stop Sign
For detecting the red stop sign, we first needed to obtain the HSV values of a red stop sign. We used the following line:
left_lower_red = np.array([145, 135, 140], dtype="uint8")
left_upper_red = np.array([175, 150, 200], dtype="uint8")
right_lower_red = np.array([150, 145, 160], dtype="uint8")
right_upper_red = np.array([170, 150, 180], dtype="uint8")
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
Next, when the car is approaching the stop sign, we also needed to measure the amount of pixels that the Raspberry Pi was reading. As it was approaching the stop sign, the number of pixels will increase. We want the car to stop before it hits the red stop sign.
left_mask = cv2.inRange(frame, left_lower_red, left_upper_red)
right_mask = cv2.inRange(frame, right_lower_red, right_upper_red)
mask = cv2.bitwise_or(left_mask, right_mask)
num_red_px = cv2.countNonZero(mask)
We found that the average HSV values were (125.98791666666666, 107.065, 163.78041666666667). If the number of pixels were higher than a preset threshold (a value we defined), we will stop the car.
Plots
The figure down below demonstrates the throttle/speed PWM, error and steering voltage values over the entire course (this is in frame number for an entire run of the track). We can see that over the frames 400-600, the steering values are much in fluctuation.
Next, we have a plot of the error, proportional response, and derivative
response. The x-axis represents the frame number for the
entire run of the track. As shown, with frames of 400-600, we obtain a high error. To define these values, the proportional response is proportional gain times the error. The derivative response is the derivative gain times the derivative
of the error. As mentioned earlier, the derivative gain and the proportional gain were predefined values used from the Nicomobile.
Picture of the Vehicle
Video Demo
Camera.py
PythonPi and OpenCV”. Instructables. URL "https://www.instructables.com/Autonomous-Lane-Keeping-Car-Using-Raspberry-Pi-and/"
'''
ELEC 424 Final Project - Autonomous Lanekeeping RC Car
Team YoungerWoods (ft. The NicoMobile)
GitHub Repo:
https://github.com/nicorossirice/comp424-FinalProject/tree/main
Hackster Webpage:
https://www.hackster.io/team-youngerwoods/the-nicomobile-83caa9
Used the following reference code:
https://www.instructables.com/Autonomous-Lane-Keeping-Car-Using-Raspberry-Pi-and/
https://www.hackster.io/really-bad-idea/autonomous-path-following-car-6c4992
'''
import math
import signal
import time
import cv2
import matplotlib.pyplot as plt
import numpy as np
from pwm_control import PWMControl
# from pwm_control import PWMControl
''' BLUE LINE DETECTION '''
def detect_edges(frame):
# filter for blue lane lines
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
#cv2.imshow("HSV",hsv)
lower_blue = np.array([70, 80, 0], dtype = "uint8")
upper_blue = np.array([150, 255, 255], dtype="uint8")
mask = cv2.inRange(hsv,lower_blue,upper_blue)
#cv2.imshow("mask",mask)
# detect edges
edges = cv2.Canny(mask, 50, 100)
cv2.imshow("edges",edges)
return edges
def region_of_interest(edges):
height, width = edges.shape
mask = np.zeros_like(edges)
# only focus lower half of the screen
polygon = np.array([[
(0, height),
(0, height/2),
(width , height/2),
(width , height),
]], np.int32)
cv2.fillPoly(mask, polygon, 255)
cropped_edges = cv2.bitwise_and(edges, mask)
# cv2.imshow("roi",cropped_edges)
return cropped_edges
def detect_line_segments(cropped_edges):
rho = 1
theta = np.pi / 180
min_threshold = 10
line_segments = cv2.HoughLinesP(cropped_edges, rho, theta, min_threshold,
np.array([]), minLineLength=5, maxLineGap=150)
return line_segments
def average_slope_intercept(frame, line_segments):
lane_lines = []
if line_segments is None:
print("no line segments detected")
return lane_lines
height, width,_ = frame.shape
left_fit = []
right_fit = []
boundary = 1/3
left_region_boundary = width * (1 - boundary)
right_region_boundary = width * boundary
for line_segment in line_segments:
for x1, y1, x2, y2 in line_segment:
if x1 == x2:
print("skipping vertical lines (slope = infinity")
continue
fit = np.polyfit((x1, x2), (y1, y2), 1)
slope = (y2 - y1) / (x2 - x1)
intercept = y1 - (slope * x1)
if slope < 0:
if x1 < left_region_boundary and x2 < left_region_boundary:
left_fit.append((slope, intercept))
else:
if x1 > right_region_boundary and x2 > right_region_boundary:
right_fit.append((slope, intercept))
left_fit_average = np.average(left_fit, axis=0)
if len(left_fit) > 0:
lane_lines.append(make_points(frame, left_fit_average))
right_fit_average = np.average(right_fit, axis=0)
if len(right_fit) > 0:
lane_lines.append(make_points(frame, right_fit_average))
return lane_lines
def make_points(frame, line):
height, width, _ = frame.shape
slope, intercept = line
y1 = height # bottom of the frame
y2 = int(y1 / 2) # make points from middle of the frame down
if slope == 0:
slope = 0.1
x1 = int((y1 - intercept) / slope)
x2 = int((y2 - intercept) / slope)
return [[x1, y1, x2, y2]]
def display_lines(frame, lines, line_color=(0, 255, 0), line_width=6):
line_image = np.zeros_like(frame)
if lines is not None:
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(line_image, (x1, y1), (x2, y2), line_color, line_width)
line_image = cv2.addWeighted(frame, 0.8, line_image, 1, 1)
return line_image
def display_heading_line(frame, steering_angle, line_color=(0, 0, 255), line_width=5 ):
heading_image = np.zeros_like(frame)
height, width, _ = frame.shape
steering_angle_radian = steering_angle / 180.0 * math.pi
x1 = int(width / 2)
y1 = height
x2 = int(x1 - height / 2 / math.tan(steering_angle_radian))
y2 = int(height / 2)
cv2.line(heading_image, (x1, y1), (x2, y2), line_color, line_width)
heading_image = cv2.addWeighted(frame, 0.8, heading_image, 1, 1)
return heading_image
def get_steering_angle(frame, lane_lines):
height,width,_ = frame.shape
if len(lane_lines) == 2:
_, _, left_x2, _ = lane_lines[0][0]
_, _, right_x2, _ = lane_lines[1][0]
mid = int(width / 2)
x_offset = (left_x2 + right_x2) / 2 - mid
y_offset = int(height / 2)
elif len(lane_lines) == 1:
x1, _, x2, _ = lane_lines[0][0]
x_offset = x2 - x1
y_offset = int(height / 2)
elif len(lane_lines) == 0:
x_offset = 0
y_offset = int(height / 2)
angle_to_mid_radian = math.atan(x_offset / y_offset)
angle_to_mid_deg = int(angle_to_mid_radian * 180.0 / math.pi)
steering_angle = angle_to_mid_deg + 90
return steering_angle
''' STOP SIGN DETECTION '''
# currently for [145, 135, 140] - [175, 150, 200]
# background redpx values could be <1000
# detection could be between 1000-25000
def check_for_stop_sign(frame):
# Range of red in HSV
left_lower_red = np.array([145, 135, 140], dtype="uint8")
left_upper_red = np.array([175, 150, 200], dtype="uint8")
right_lower_red = np.array([150, 145, 160], dtype="uint8")
right_upper_red = np.array([170, 150, 180], dtype="uint8")
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Right orientation for HSV function
left_lower_red = np.flip(left_lower_red)
left_upper_red = np.flip(left_upper_red)
right_lower_red = np.flip(right_lower_red)
right_upper_red = np.flip(right_upper_red)
# Create mask for 'red' detection
left_mask = cv2.inRange(frame, left_lower_red, left_upper_red)
right_mask = cv2.inRange(frame, right_lower_red, right_upper_red)
mask = cv2.bitwise_or(left_mask, right_mask)
num_red_px = cv2.countNonZero(mask)
'''
Average HSV value for red construction paper:
125.98791666666666
107.065
163.78041666666667
'''
# TESTING:
center = frame[:, :, :]
# center[:110, :, :] = 0
# center[130:, :, :] = 0
# center[:, :110, :] = 0
# center[:, 230:, :] = 0
# center = center[110:130, 110:230, :]
# print(np.mean(center[:,:,0]))
# print(np.mean(center[:,:,1]))
# print(np.mean(center[:,:,2]))
# print(np.average(center[110:130, 110:230, :], axis=1))
# cv2.imshow("center", center)
# print(frame.shape)
# Filter out non red pixels and get count of number of red pixels
# mask = cv2.inRange(frame, lower_red, upper_red, axis=2)
# num_red_px = cv2.countNonZero(mask)
# cv2.imshow("Mask", mask)
# cv2.imshow("Mask", cv2.bitwise_and(frame, frame, mask=mask))
# cv2.imshow("mask", mask)
return num_red_px
''' CAMERA WORK '''
video = cv2.VideoCapture(0)
video.set(cv2.CAP_PROP_FRAME_WIDTH,320)
video.set(cv2.CAP_PROP_FRAME_HEIGHT,240)
time.sleep(2)
''' CONSTANTS (for PD algorithm) '''
speed = 8
lastTime = 0
lastError = 0
''' BEGIN MAIN CODE '''
# Set up signal handler so ctrl+c triggers the handler
# This means the shutdown code will actually run
done = False
def stop(signum, stackframe):
global done
done = True
signal.signal(signal.SIGINT, stop)
show_camera = True
''' SETTING P AND D VALUES '''
kp = 0.2 # change for testing purposes
kd = kp * 0.1
stop_timing = 0
stop_state = 0
''' PLOTTING DATA '''
error_data = []
steering_pwm_data = []
throttle_pwm_data = []
proportional_resp_data = []
derivative_resp_data = []
''' MAIN FUNCTION '''
num_stopped = 0
pwm = PWMControl()
pwm.set_throttle(int(65535 / 2))
throttle_pwm_data.append(int(65535/2))
flag = True
skip_frames = 0
while not done:
ret,frame = video.read()
# Detect lanes
edges = detect_edges(frame)
roi = region_of_interest(edges)
line_segments = detect_line_segments(roi)
lane_lines = average_slope_intercept(frame,line_segments)
lane_lines_image = display_lines(frame,lane_lines)
steering_angle = get_steering_angle(frame, lane_lines)
heading_image = display_heading_line(lane_lines_image,steering_angle)
if show_camera:
cv2.imshow("heading line",heading_image)
if flag:
pwm.set_throttle(int(65535 / 1.8))
throttle_pwm_data.append(int(65535/1.8))
flag = False
# Stop sign detection (x2)
red_px = check_for_stop_sign(frame)
print(f"{red_px=}")
print(f"{stop_state=}")
# TODO: adjust values of picture detection
# Need this to stop twice
if num_stopped == 1 and skip_frames == 0 and red_px > 4000:
print(f'Stopping! {num_stopped}')
break
if num_stopped == 0 and red_px > 4000:
num_stopped = 1
print(f'First stop! {num_stopped}')
pwm.set_throttle(int(65535 / 2))
throttle_pwm_data.append(int(65535/2))
time.sleep(3)
skip_frames = 200
pwm.set_throttle(int(65535 / 1.8))
throttle_pwm_data.append(int(65535/1.8))
continue
if skip_frames > 0:
skip_frames -= 1
speed: int
try:
with open("speed", 'r') as file:
speed = int(file.read().strip())
except IOError as e:
print(f"Error reading speed file! Throttle disabled: {e}")
pwm.set_throttle(int(65535 / 2))
except ValueError as e:
print(f"File does not contain a valid number! Throttle disabled: {e}")
pwm.set_throttle(int(65535 / 2))
# TODO: tweak this to desired speed:
speed_threshold = 300000
if speed > speed_threshold:
pwm.set_throttle(int(65535 / 1.9))
throttle_pwm_data.append(int(65535 / 1.9))
# elif speed < speed_threshold - 60000:
# pwm.set_throttle(int(65535 / 1.8))
else:
pwm.set_throttle(int(65535 / 1.8))
throttle_pwm_data.append(int(65535 / 1.8))
''' CALCULATE DERIVATIVE FROM PD ALGORITHM '''
now = time.time()
dt = now - lastTime
deviation = steering_angle - 90
error = -deviation
base_turn = 7.5
proportional = kp * error
derivative = kd * (error - lastError) / dt
error_data.append(error)
proportional_resp_data.append(proportional)
derivative_resp_data.append(derivative)
''' DETERMINE TURN AMOUNT (WITH PWM CONTROL) '''
turn_amt = base_turn + proportional + derivative
print(f"Steering angle: {steering_angle}")
print(f"Turn amt: {turn_amt}")
#max((7-turn_amt)/7.0, 1) *
# lower voltage is more left
# higher voltage is more right
if turn_amt < 6.8:
turn_amt = int(65535 / 1.4) # 1.3
elif turn_amt < 7.4:
# right
turn_amt = int(65535 / 1.5)
elif turn_amt < 8:
# neutral
turn_amt = int(65535 / 2)
elif turn_amt < 11.5:
turn_amt = int(65525 / 2.2)
else:
# left
turn_amt = int(65535 / 2.8)
turn_amt = int(turn_amt)
steering_pwm_data.append(turn_amt)
# 7.6, 9
"""
if turn_amt > 9
turn_amt = 9
if turn_amt < 6:
turn_amt = 6
turn_amt = turn_amt *-1 +9
turn_amt = turn_amt * (2/3) + 1 #value between 1 and 3
turn_amt = int(65525 / turn_amt) #actual output value
"""
print(f"Adjusted turn: {turn_amt}")
steering_pwm_data.append(pwm.set_steering(turn_amt))
lastError = error
lastTime = time.time()
key = cv2.waitKey(1)
if key == 27:
break
''' SHUTDOWN PROTOCOL '''
video.release()
pwm.shutdown()
with open("data.py", 'w') as data:
data.write(f"{error_data=}")
data.write("\n")
data.write(f"{throttle_pwm_data=}")
data.write("\n")
data.write(f"{steering_pwm_data=}")
data.write("\n")
data.write(f"{proportional_resp_data=}")
data.write("\n")
data.write(f"{derivative_resp_data=}")
pwm_control.py
Pythonimport board
import time
import adafruit_mcp4728
class PWMControl:
''' initialization '''
def __init__(self):
MCP4728_DEFAULT_ADDRESS = 0x60
MCP4728A4_DEFAULT_ADDRESS = 0x64
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
# use for MCP4728 variant
#mcp4728 = adafruit_mcp4728.MCP4728(i2c, adafruit_mcp4728.MCP4728_DEFAULT_ADDRESS)
# use for MCP4728A4 variant
self.mcp4728 = adafruit_mcp4728.MCP4728(i2c, adafruit_mcp4728.MCP4728A4_DEFAULT_ADDRESS)
#neutral values set at beginning
self.mcp4728.channel_a.value = int(65535 / 2)
self.mcp4728.channel_b.value = int(65535 / 2)
''' gets the speed of the RC car '''
def get_speed(self):
pass
# TODO: get speed
''' set throttle value given PWM percent '''
def set_throttle_direct(self, percent):
self.cur_throttle = percent
# TODO: set throttle (duty cycle)
'''
with open('/dev/bone/pwm/1/a/duty_cycle', 'w') as throttle:
# print(self.percent_to_period(percent))
throttle.write(self.percent_to_period(percent))
'''
''' set throttle value given rotational period for constant speed '''
def set_throttle(self, rot_period: int):
self.mcp4728.channel_b.value = rot_period
pass
'''
# if vehicle was previously stopped
if rot_period == 0:
print("rot_period 0")
self.jumped = False
self.set_throttle_direct(7.9)
return 7.9
# if vehicle was not previously stopped
cur_rot_period = self.get_speed()
print(cur_rot_period)
diff = abs(cur_rot_period - rot_period)
jump = 0
if cur_rot_period == 1000000 and not self.jumped:
print("Jumped")
self.jumped = True
jump = 0.05
delta = 0.001
# Speed is changed based on throttle error
if diff < 1:
pass
elif rot_period > cur_rot_period:
self.set_throttle_direct(self.cur_throttle - (jump + self.diff_to_delta(diff)))
print(f"Decreasing: {self.cur_throttle}")
return self.cur_throttle
elif rot_period < cur_rot_period:
self.set_throttle_direct(self.cur_throttle + (jump + self.diff_to_delta(diff)))
print(f"Increasing: {self.cur_throttle}")
return self.cur_throttle
'''
''' detect throttle error '''
def diff_to_delta(self, diff):
if diff < 30:
return -0.0005
elif diff < 25:
return 0.0001
elif diff < 400:
return 0.0001
else:
return 0.0003
''' set steering '''
def set_steering(self, percent: int):
self.mcp4728.channel_a.value = percent
'''
with open('/dev/bone/pwm/1/b/duty_cycle', 'w') as steering:
steering.write(self.percent_to_period(percent))
return percent
'''
''' shutdown '''
def shutdown(self):
print("Shutting down PWM...")
self.mcp4728.channel_b.value = int(65535 / 2)
'''
# Center steering and stop motor
self.set_throttle_direct(7.5)
self.set_steering(7.5)
time.sleep(0.2)
# Shut down throttle
with open('/dev/bone/pwm/1/a/enable', 'w') as filetowrite:
filetowrite.write('1')
# Shut down steering
with open('/dev/bone/pwm/1/b/enable', 'w') as filetowrite:
filetowrite.write('0')
# Close speed file
self.speed.close()
# self.last_rot.close()
'''
def percent_to_period(self, percent: float):
return str(int(percent * 200000))
plot.py
PythonPi and OpenCV”. Instructables. URL "https://www.instructables.com/Autonomous-Lane-Keeping-Car-Using-Raspberry-Pi-and/"
import matplotlib.pyplot as plt
import numpy as np
from data import error_data, throttle_pwm_data, steering_pwm_data, proportional_resp_data, derivative_resp_data
# Plots relevant values throughout the run of the RC car
frames = np.arange(len(throttle_pwm_data))
plt.figure(figsize=(10, 10))
plt.plot(frames, throttle_pwm_data, label="throttle values")
plt.plot(frames, error_data, label="error")
plt.plot(frames, steering_pwm_data, label="steering values")
plt.legend()
plt.show()
# Plots relevant values throughout the run of the RC car
frames = np.arange(len(throttle_pwm_data))
plt.figure(figsize=(10, 10))
plt.plot(frames, proportional_resp_data, label="proportional response")
plt.plot(frames, error_data, label="error")
plt.plot(frames, derivative_resp_data, label="derivative response")
plt.legend()
plt.show()
datapy
PythonPi and OpenCV”. Instructables. URL "https://www.instructables.com/Autonomous-Lane-Keeping-Car-Using-Raspberry-Pi-and/"
error_data=[-32, -31, -31, -32, -32, -30, -31, -32, -32, -30, -31, -30, -30, -30, -30, -31, -30, -30, -28, -28, -30, -29, -27, -27, -27, -27, -28, -26, -33, -28, -23, -25, -25, -23, -23, -18, 0, 0, 0, 0, 0, 0, 0, -45, 0, -45, 0, -45, 0, 0, -46, -46, -45, -45, 0, -43, -44, -43, 0, 0, -45, -42, -44, -43, -43, -43, -43, -41, -41, -41, -43, -41, -40, -40, -41, -40, -41, -39, -38, -38, -38, -39, -38, -35, -37, -36, -34, -38, -34, -35, -35, -36, -34, -34, -34, -34, -33, -34, -33, -32, -34, -32, -32, -30, -33, -30, -30, -30, -31, -33, -29, -30, -29, -30, -30, -28, -27, -27, -26, -26, -25, -25, -26, -27, -25, -25, -26, -25, -25, -25, -24, -24, -25, -24, -24, -25, -23, -25, -24, -23, -25, -24, -26, -23, -23, -23, -21, -22, -22, -19, -19, -20, -20, -19, -20, -20, -20, -20, -20, -20, -20, -19, -20, -19, -20, -19, -18, -20, -20, -18, -18, -20, -19, -18, -18, -19, -18, -18, -19, -18, -18, -18, -16, -14, 0, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -14, -15, -16, -17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, -13, 0, -12, 0, 0, 0, -14, -14, -14, -14, -12, -13, -14, -14, -14, -12, -13, -13, -13, -13, -14, -12, -12, -13, -12, -12, -12, -13, -13, -11, 0, 0, -12, 0, 0, -12, 0, 0, -12, -13, -14, -13, -14, -12, -13, -13, -12, -12, -11, -12, 0, -10, 0, 0, -10, 0, -12, 0, 0, 0, 0, -13, -13, -12, -13, -14, -13, -13, -13, -13, -13, -13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -14, 0, 12, 16, 19, 15, 11, 15, 17, 14, 17, -26, 14, 14, -23, -22, -23, -22, -18, -21, -22, -23, 12, 12, 11, 11, 11, 11, 9, 10, 10, 11, 9, 10, 9, 9, 10, 9, 9, 11, 11, 12, 11, 10, 11, 10, 10, 10, 9, 10, 9, 9, 9, 9, 8, 9, 9, 10, 13, 9, 8, 10, 11, 8, 8, 6, 8, 5, 7, 5, 14, 5, 8, 8, 12, 4, 11, 8, 6, 4, 7, 5, 65, 19, 11, 45, 45, 0, 52, 51, 51, 50, 51, 51, 51, 50, 49, 50, 49, 50, 50, 48, 50, 48, 48, 48, 47, 48, 46, 47, 47, 46, 46, 45, 45, 45, 46, 45, 45, 45, 44, 44, 38, 38, 38, 39, 37, 37, 38, 38, 38, 36, 37, 35, 37, 35, 35, 36, 35, 35, 34, 34, 35, 34, 33, 32, 33, 33, 32, 32, 33, 30, 31, 34, 32, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 34, 0, 0, 0, 32, 30, 0, 31, 0, 31, 0, 0, 28, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 45, 0, 0, 45, 45, 0, 44, 0, 42, 0, 41, 39, 38, 0, 0, 0, 0, 0, 34, 0, 0, 33, 27, 28, 24, 25, 23, 24, 23, 23, 22, 21, 20, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 18, 15, 16, 0, 0, 15, 0, 0, 0, 12, 12, 11, 10, 10, 11, 10, 10, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 7, 7, 6, 7, 5, 6, 6, 5, 6, 5, 5, 6, 5, 5, 3, 3, 1, 1, 2, 1, 2, 3, 2, 2, 2, 1, 2, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 37, 45, 40, 39, -8, 0, 0, 0, -3, -1, -3, 0, -4, 0, 40, 0, 40, 18, 43, 40, 39, 36, 36, 37, 35, 35, 36, 33, 34, 32, 32, 25, 26, 0, 11, 10, 13, 8, 8, 7, 7, 8, 6, 6, 7, 6, 6, 5, 5, 6, 6, 4, 4, 5, 5, 6, 4, 5, 4, 3, 3, 4, 4, 2, 3, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 16, 0, 0, 0, 0, 0, 18, 17, 0, 0, 0, 14, 0, 0, 0, 16, 16, 15, 15, 16, 15, 16, 15, 15, 15, 15, 15, 14, 15, 14, 15, 14, 14, 14, 14, 13, 14, 14, 14, 13, 14, 12, 13, 13, 13, 12, 12, 13, 11, 13, 10, 0, 0, 11, 0, 12, 0, 0, 11, 0, 8, 0, 9, 0, 0, 0, 10, 0, 12, 8, 0, 0, 0, 0, 0, 0, 0, 9, 9, 10, 9, 9, 9]
throttle_pwm_data=[32767, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 34492, 34492, 36408, 34492, 36408, 34492, 34492, 36408, 34492, 34492, 34492, 36408, 36408, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 36408, 34492, 34492, 36408, 34492, 34492, 36408, 34492, 36408, 36408, 34492, 34492, 34492, 36408, 36408, 36408, 34492, 36408, 36408, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 36408, 36408, 36408, 36408, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 36408, 34492, 34492, 36408, 36408, 34492, 36408, 34492, 36408, 34492, 36408, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 34492, 36408, 34492, 34492, 36408, 36408, 36408, 36408, 36408, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 32767, 36408, 36408, 34492, 34492, 36408, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 36408, 34492, 36408, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 36408, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 36408, 36408, 36408, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 36408, 36408, 36408, 36408, 34492, 34492, 36408, 34492, 34492, 36408, 36408, 36408, 36408, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 36408, 34492, 34492, 36408, 36408, 34492, 36408, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 36408, 34492, 34492, 36408, 36408, 36408, 34492, 36408, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 34492, 34492, 36408, 34492, 34492, 36408, 36408, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 36408, 36408, 36408, 34492, 36408, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 34492, 36408, 34492, 34492, 34492, 34492, 34492, 36408, 36408, 34492, 34492, 34492, 34492, 36408, 34492, 34492]
steering_pwm_data=[46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 43690, None, 23405, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 46810, None, 23405, None, 46810, None, 23405, None, 46810, None, 23405, None, 32767, None, 46810, None, 46810, None, 46810, None, 46810, None, 23405, None, 46810, None, 46810, None, 46810, None, 23405, None, 32767, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 43690, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 43690, None, 23405, None, 46810, None, 23405, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 46810, None, 46810, None, 46810, None, 46810, None, 23405, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 46810, None, 23405, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 46810, None, 23405, None, 46810, None, 23405, None, 32767, None, 32767, None, 46810, None, 46810, None, 46810, None, 46810, None, 43690, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 23405, None, 32767, None, 46810, None, 23405, None, 32767, None, 46810, None, 23405, None, 32767, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 43690, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 23405, None, 46810, None, 23405, None, 32767, None, 46810, None, 23405, None, 46810, None, 23405, None, 32767, None, 32767, None, 32767, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 23405, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 46810, None, 23405, None, 23405, None, 23405, None, 23405, None, 29784, None, 43690, None, 23405, None, 23405, None, 29784, None, 23405, None, 46810, None, 23405, None, 29784, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 46810, None, 23405, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 23405, None, 46810, None, 29784, None, 29784, None, 29784, None, 43690, None, 29784, None, 32767, None, 29784, None, 46810, None, 29784, None, 43690, None, 23405, None, 46810, None, 29784, None, 29784, None, 23405, None, 46810, None, 23405, None, 43690, None, 32767, None, 43690, None, 29784, None, 43690, None, 23405, None, 46810, None, 29784, None, 23405, None, 23405, None, 46810, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 29784, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 46810, None, 32767, None, 32767, None, 32767, None, 23405, None, 46810, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 46810, None, 32767, None, 32767, None, 23405, None, 23405, None, 46810, None, 23405, None, 46810, None, 23405, None, 46810, None, 32767, None, 23405, None, 46810, None, 32767, None, 23405, None, 46810, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 23405, None, 46810, None, 32767, None, 23405, None, 23405, None, 46810, None, 23405, None, 46810, None, 23405, None, 46810, None, 23405, None, 23405, None, 23405, None, 46810, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 46810, None, 32767, None, 23405, None, 32767, None, 23405, None, 32767, None, 23405, None, 29784, None, 23405, None, 29784, None, 23405, None, 29784, None, 29784, None, 29784, None, 46810, None, 32767, None, 23405, None, 46810, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 46810, None, 23405, None, 29784, None, 29784, None, 46810, None, 32767, None, 29784, None, 46810, None, 32767, None, 32767, None, 23405, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 43690, None, 29784, None, 29784, None, 32767, None, 29784, None, 32767, None, 29784, None, 29784, None, 32767, None, 29784, None, 46810, None, 29784, None, 46810, None, 32767, None, 29784, None, 46810, None, 29784, None, 29784, None, 43690, None, 32767, None, 32767, None, 43690, None, 29784, None, 46810, None, 29784, None, 32767, None, 43690, None, 32767, None, 32767, None, 32767, None, 29784, None, 32767, None, 43690, None, 32767, None, 32767, None, 32767, None, 32767, None, 29784, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 23405, None, 29784, None, 23405, None, 46810, None, 23405, None, 32767, None, 32767, None, 46810, None, 29784, None, 46810, None, 29784, None, 46810, None, 29784, None, 23405, None, 46810, None, 23405, None, 46810, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 23405, None, 46810, None, 23405, None, 46810, None, 23405, None, 29784, None, 23405, None, 46810, None, 29784, None, 29784, None, 29784, None, 29784, None, 43690, None, 29784, None, 29784, None, 29784, None, 29784, None, 32767, None, 29784, None, 29784, None, 29784, None, 43690, None, 29784, None, 29784, None, 29784, None, 29784, None, 43690, None, 29784, None, 32767, None, 32767, None, 29784, None, 29784, None, 29784, None, 43690, None, 29784, None, 46810, None, 46810, None, 29784, None, 46810, None, 32767, None, 29784, None, 46810, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 46810, None, 23405, None, 46810, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 29784, None, 46810, None, 32767, None, 32767, None, 23405, None, 46810, None, 32767, None, 32767, None, 23405, None, 29784, None, 29784, None, 29784, None, 23405, None, 29784, None, 23405, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None, 32767, None, 23405, None, 46810, None, 46810, None, 32767, None, 23405, None, 46810, None, 23405, None, 46810, None, 32767, None, 23405, None, 46810, None, 23405, None, 46810, None, 23405, None, 46810, None, 32767, None, 32767, None, 23405, None, 46810, None, 23405, None, 46810, None, 46810, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 32767, None, 23405, None, 29784, None, 29784, None, 29784, None, 29784, None, 29784, None]
proportional_resp_data=[-6.4, -6.2, -6.2, -6.4, -6.4, -6.0, -6.2, -6.4, -6.4, -6.0, -6.2, -6.0, -6.0, -6.0, -6.0, -6.2, -6.0, -6.0, -5.6000000000000005, -5.6000000000000005, -6.0, -5.800000000000001, -5.4, -5.4, -5.4, -5.4, -5.6000000000000005, -5.2, -6.6000000000000005, -5.6000000000000005, -4.6000000000000005, -5.0, -5.0, -4.6000000000000005, -4.6000000000000005, -3.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.0, 0.0, -9.0, 0.0, -9.0, 0.0, 0.0, -9.200000000000001, -9.200000000000001, -9.0, -9.0, 0.0, -8.6, -8.8, -8.6, 0.0, 0.0, -9.0, -8.4, -8.8, -8.6, -8.6, -8.6, -8.6, -8.200000000000001, -8.200000000000001, -8.200000000000001, -8.6, -8.200000000000001, -8.0, -8.0, -8.200000000000001, -8.0, -8.200000000000001, -7.800000000000001, -7.6000000000000005, -7.6000000000000005, -7.6000000000000005, -7.800000000000001, -7.6000000000000005, -7.0, -7.4, -7.2, -6.800000000000001, -7.6000000000000005, -6.800000000000001, -7.0, -7.0, -7.2, -6.800000000000001, -6.800000000000001, -6.800000000000001, -6.800000000000001, -6.6000000000000005, -6.800000000000001, -6.6000000000000005, -6.4, -6.800000000000001, -6.4, -6.4, -6.0, -6.6000000000000005, -6.0, -6.0, -6.0, -6.2, -6.6000000000000005, -5.800000000000001, -6.0, -5.800000000000001, -6.0, -6.0, -5.6000000000000005, -5.4, -5.4, -5.2, -5.2, -5.0, -5.0, -5.2, -5.4, -5.0, -5.0, -5.2, -5.0, -5.0, -5.0, -4.800000000000001, -4.800000000000001, -5.0, -4.800000000000001, -4.800000000000001, -5.0, -4.6000000000000005, -5.0, -4.800000000000001, -4.6000000000000005, -5.0, -4.800000000000001, -5.2, -4.6000000000000005, -4.6000000000000005, -4.6000000000000005, -4.2, -4.4, -4.4, -3.8000000000000003, -3.8000000000000003, -4.0, -4.0, -3.8000000000000003, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -3.8000000000000003, -4.0, -3.8000000000000003, -4.0, -3.8000000000000003, -3.6, -4.0, -4.0, -3.6, -3.6, -4.0, -3.8000000000000003, -3.6, -3.6, -3.8000000000000003, -3.6, -3.6, -3.8000000000000003, -3.6, -3.6, -3.6, -3.2, -2.8000000000000003, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.8000000000000003, -3.0, -3.2, -3.4000000000000004, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.6, 0.0, -2.4000000000000004, 0.0, 0.0, 0.0, -2.8000000000000003, -2.8000000000000003, -2.8000000000000003, -2.8000000000000003, -2.4000000000000004, -2.6, -2.8000000000000003, -2.8000000000000003, -2.8000000000000003, -2.4000000000000004, -2.6, -2.6, -2.6, -2.6, -2.8000000000000003, -2.4000000000000004, -2.4000000000000004, -2.6, -2.4000000000000004, -2.4000000000000004, -2.4000000000000004, -2.6, -2.6, -2.2, 0.0, 0.0, -2.4000000000000004, 0.0, 0.0, -2.4000000000000004, 0.0, 0.0, -2.4000000000000004, -2.6, -2.8000000000000003, -2.6, -2.8000000000000003, -2.4000000000000004, -2.6, -2.6, -2.4000000000000004, -2.4000000000000004, -2.2, -2.4000000000000004, 0.0, -2.0, 0.0, 0.0, -2.0, 0.0, -2.4000000000000004, 0.0, 0.0, 0.0, 0.0, -2.6, -2.6, -2.4000000000000004, -2.6, -2.8000000000000003, -2.6, -2.6, -2.6, -2.6, -2.6, -2.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.8000000000000003, 0.0, 2.4000000000000004, 3.2, 3.8000000000000003, 3.0, 2.2, 3.0, 3.4000000000000004, 2.8000000000000003, 3.4000000000000004, -5.2, 2.8000000000000003, 2.8000000000000003, -4.6000000000000005, -4.4, -4.6000000000000005, -4.4, -3.6, -4.2, -4.4, -4.6000000000000005, 2.4000000000000004, 2.4000000000000004, 2.2, 2.2, 2.2, 2.2, 1.8, 2.0, 2.0, 2.2, 1.8, 2.0, 1.8, 1.8, 2.0, 1.8, 1.8, 2.2, 2.2, 2.4000000000000004, 2.2, 2.0, 2.2, 2.0, 2.0, 2.0, 1.8, 2.0, 1.8, 1.8, 1.8, 1.8, 1.6, 1.8, 1.8, 2.0, 2.6, 1.8, 1.6, 2.0, 2.2, 1.6, 1.6, 1.2000000000000002, 1.6, 1.0, 1.4000000000000001, 1.0, 2.8000000000000003, 1.0, 1.6, 1.6, 2.4000000000000004, 0.8, 2.2, 1.6, 1.2000000000000002, 0.8, 1.4000000000000001, 1.0, 13.0, 3.8000000000000003, 2.2, 9.0, 9.0, 0.0, 10.4, 10.200000000000001, 10.200000000000001, 10.0, 10.200000000000001, 10.200000000000001, 10.200000000000001, 10.0, 9.8, 10.0, 9.8, 10.0, 10.0, 9.600000000000001, 10.0, 9.600000000000001, 9.600000000000001, 9.600000000000001, 9.4, 9.600000000000001, 9.200000000000001, 9.4, 9.4, 9.200000000000001, 9.200000000000001, 9.0, 9.0, 9.0, 9.200000000000001, 9.0, 9.0, 9.0, 8.8, 8.8, 7.6000000000000005, 7.6000000000000005, 7.6000000000000005, 7.800000000000001, 7.4, 7.4, 7.6000000000000005, 7.6000000000000005, 7.6000000000000005, 7.2, 7.4, 7.0, 7.4, 7.0, 7.0, 7.2, 7.0, 7.0, 6.800000000000001, 6.800000000000001, 7.0, 6.800000000000001, 6.6000000000000005, 6.4, 6.6000000000000005, 6.6000000000000005, 6.4, 6.4, 6.6000000000000005, 6.0, 6.2, 6.800000000000001, 6.4, 0.0, 0.0, 0.0, 0.0, 7.4, 0.0, 0.0, 0.0, 0.0, 0.0, 6.800000000000001, 0.0, 0.0, 0.0, 6.4, 6.0, 0.0, 6.2, 0.0, 6.2, 0.0, 0.0, 5.6000000000000005, 0.0, 0.0, 5.6000000000000005, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.6, 9.0, 0.0, 0.0, 9.0, 9.0, 0.0, 8.8, 0.0, 8.4, 0.0, 8.200000000000001, 7.800000000000001, 7.6000000000000005, 0.0, 0.0, 0.0, 0.0, 0.0, 6.800000000000001, 0.0, 0.0, 6.6000000000000005, 5.4, 5.6000000000000005, 4.800000000000001, 5.0, 4.6000000000000005, 4.800000000000001, 4.6000000000000005, 4.6000000000000005, 4.4, 4.2, 4.0, 0.0, 0.0, 3.8000000000000003, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.6, 0.0, 3.6, 3.0, 3.2, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 2.4000000000000004, 2.4000000000000004, 2.2, 2.0, 2.0, 2.2, 2.0, 2.0, 1.8, 1.6, 1.6, 1.6, 1.6, 1.6, 1.6, 1.6, 1.6, 1.6, 1.4000000000000001, 1.2000000000000002, 1.4000000000000001, 1.4000000000000001, 1.2000000000000002, 1.4000000000000001, 1.0, 1.2000000000000002, 1.2000000000000002, 1.0, 1.2000000000000002, 1.0, 1.0, 1.2000000000000002, 1.0, 1.0, 0.6000000000000001, 0.6000000000000001, 0.2, 0.2, 0.4, 0.2, 0.4, 0.6000000000000001, 0.4, 0.4, 0.4, 0.2, 0.4, 0.0, 0.2, 0.2, 0.0, 0.0, 0.0, 0.0, 0.2, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.4, 9.0, 8.0, 7.800000000000001, -1.6, 0.0, 0.0, 0.0, -0.6000000000000001, -0.2, -0.6000000000000001, 0.0, -0.8, 0.0, 8.0, 0.0, 8.0, 3.6, 8.6, 8.0, 7.800000000000001, 7.2, 7.2, 7.4, 7.0, 7.0, 7.2, 6.6000000000000005, 6.800000000000001, 6.4, 6.4, 5.0, 5.2, 0.0, 2.2, 2.0, 2.6, 1.6, 1.6, 1.4000000000000001, 1.4000000000000001, 1.6, 1.2000000000000002, 1.2000000000000002, 1.4000000000000001, 1.2000000000000002, 1.2000000000000002, 1.0, 1.0, 1.2000000000000002, 1.2000000000000002, 0.8, 0.8, 1.0, 1.0, 1.2000000000000002, 0.8, 1.0, 0.8, 0.6000000000000001, 0.6000000000000001, 0.8, 0.8, 0.4, 0.6000000000000001, 0.2, 0.0, 0.2, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.6, 0.0, 3.2, 0.0, 0.0, 0.0, 0.0, 0.0, 3.6, 3.4000000000000004, 0.0, 0.0, 0.0, 2.8000000000000003, 0.0, 0.0, 0.0, 3.2, 3.2, 3.0, 3.0, 3.2, 3.0, 3.2, 3.0, 3.0, 3.0, 3.0, 3.0, 2.8000000000000003, 3.0, 2.8000000000000003, 3.0, 2.8000000000000003, 2.8000000000000003, 2.8000000000000003, 2.8000000000000003, 2.6, 2.8000000000000003, 2.8000000000000003, 2.8000000000000003, 2.6, 2.8000000000000003, 2.4000000000000004, 2.6, 2.6, 2.6, 2.4000000000000004, 2.4000000000000004, 2.6, 2.2, 2.6, 2.0, 0.0, 0.0, 2.2, 0.0, 2.4000000000000004, 0.0, 0.0, 2.2, 0.0, 1.6, 0.0, 1.8, 0.0, 0.0, 0.0, 2.0, 0.0, 2.4000000000000004, 1.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.8, 1.8, 2.0, 1.8, 1.8, 1.8]
derivative_resp_data=[-3.7602794444971183e-10, 0.3270106500756265, 0.0, -0.5741925061946419, 0.0, 1.7615354570462614, -0.7475411705995582, -0.8453445930285289, 0.0, 1.7365740961174196, -0.9393212026202342, 0.9708475203981253, 0.0, 0.0, 0.0, -0.8474625448300249, 0.477069997042699, 0.0, 1.3159839357429721, 0.0, -0.15283066958775332, 0.9182127454629043, 1.8257934486886498, 0.0, 0.0, 0.0, -0.9968992358610529, 1.9459064232526855, -6.338610736298968, 3.2005371995421603, 3.0522231439840493, -1.1589516585844353, 0.0, 1.0617550343640438, 0.0, 3.137711148016818, 7.184214372716202, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -29.025432512648596, 24.732672462932513, -2.154828375730169, 40.52337122797978, -43.4547836397334, 43.80016708437762, 0.0, -31.820623093035152, 0.0, 0.5453522298790795, 0.0, 45.24003307726418, -44.062658832439574, -0.6356547041707081, 0.6742278448456013, 23.459143996201902, 0.0, -24.796684030400773, 1.9392038466873183, -1.1992720254476574, 0.5779785995300992, 0.0, 0.0, 0.0, 1.3221858302466707, 0.0, 0.0, -1.133159256232397, 1.2886320414151193, 0.6279932324185121, 0.0, -0.6265064416146982, 0.5644257243207602, -0.6448955618595141, 1.2671900420704398, 0.5552721880957425, 0.0, 0.0, -1.044879737927083, 0.5186316733129309, 1.5082903206472882, -1.2709723263865218, 0.9416197649488703, 2.1172927472582947, -3.824084791156192, 3.884154280687133, -0.7282599598913073, 0.0, -0.5637278066744622, 1.3067792438427868, 0.0, 0.0, 0.0, 0.5965826286705878, -0.6143295080886716, 0.5512184672400992, 0.6504158234669273, -1.2699140886967977, 1.1233338689806633, 0.0, 1.128570486818827, -1.8855606671361997, 1.9126309309377783, 0.0, 0.0, -0.5598190129800795, -1.2722927820666436, 1.851667218506501, -0.8456172820838501, 0.027261107251097944, -0.6665878389116685, 0.0, 1.436380883888975, 0.7490698027449616, 0.0, 1.0940901502504177, 0.0, 1.0813406208105603, 0.0, -0.7662228717573988, -0.6285390598072861, 1.1503140919718342, 0.0, -0.5581948483174853, 0.645664937423993, 0.0, 0.0, 0.6321483044461191, 0.0, -0.6382130113588814, 0.6342225515249574, 0.0, -0.6090617875553621, 1.1706286719044365, -1.2596358612819187, 0.6429924422437187, 0.5527475916237268, -1.2777383781149092, 0.5563881169205872, -1.28939462176349, 1.9084102284102287, 0.0, 0.0, 1.1279028148466863, -0.5911425249286496, 0.0, 3.1954167301538936, 0.0, -1.0689801587807273, 0.0, 1.0718348154962694, -1.0684219374888557, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5612836056579283, -0.640317540284107, 0.5599909211676981, -0.6349906892949603, 0.6276314391530434, 0.5747038995916802, -1.2460333469493856, 0.0, 1.3091653661277236, 0.0, -1.1264412515106756, 0.6431403336604515, 0.6371901253323207, 0.0, -0.6195198109375578, 0.5631450053705694, 0.0, -0.6380916448609506, 0.030645611817505976, 0.0, 0.0, 2.1574528059256215, 2.1017759069953903, 15.131746637117972, -15.846498331339339, 16.165097636176775, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -9.062397234375846, -0.5630429500560453, -0.6480992629448215, -0.6133144214951564, 9.794391208791211, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -16.661474291918807, 17.12496699647509, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -7.3657839137600325, 6.437804631832486, -0.7256377307731402, 12.50615547079798, 0.0, 0.0, -9.339279994274309, 0.0, 0.0, 0.0, 2.27954401554369, -1.0839675401871094, -0.7087546997642726, 0.0, 0.0, 1.1210744856434554, -0.6602032094820599, 0.0, 0.0, 0.0, -0.5183528597557963, 1.2847047292330314, 0.0, -0.7301679926187701, 0.5904975362522878, 0.0, 0.0, -0.5600507400706356, 0.0, 1.3346817075305089, 6.406007053400351, 0.0, -6.858060375661702, 7.709881437455961, 0.0, -0.3862720062501416, 12.172986673761098, 0.0, -9.475797876346112, -0.5525873812629278, -0.5666829696683106, 0.7543305217344389, -1.052324907482908, 2.196459421599047, -1.0567925621708787, 0.0, 0.5456892502845992, 0.0, 0.5016270002631139, -0.756050579975305, 7.943506833748936, -5.5620366134240395, 6.506377928937634, 0.0, -6.370981780069721, 6.416006730658918, -6.851385478206421, 8.37311773219544, 0.0, 0.0, 0.0, -7.192448489645168, 0.0, 0.5727145987943006, -0.6225404458693266, -0.6468748216750593, 0.5632055000537116, 0.0, 0.0, 0.0, 0.0, 0.0, 10.892119856172595, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -7.64233407734706, 9.19321095603028, 6.708113712998628, 2.554426224516208, 1.8463283003917774, -2.2990518605814363, -2.5603320743199425, 2.249288232849348, 1.273799711487359, -1.8858432624432357, 1.6945884032402516, -26.482302361094803, 22.773316320643954, 0.0, -23.50657729913132, 0.5356915335198029, -0.6632883687831107, 0.6408850111925191, 0.13070877257496163, -1.5458312755684962, -0.522944685838253, -0.9138116298830041, 35.69880842371481, 0.0, -1.0352855221099142, 0.0, 0.0, 0.0, -1.1482435392028036, 0.6359052730525487, 0.0, 0.5451395892903562, -1.285127883017105, 0.5582245646257147, -0.6143160114828052, 0.0, 0.571022633674824, -0.6339110261390001, 0.0, 1.2977526125666197, 0.0, 0.5522163414698371, -0.6564215567362846, -0.5536157968374648, 0.6339014455955809, -0.6481994220099836, 0.0, 0.0, -0.6817179868509806, 0.5510772424485292, -0.6273826547401802, 0.0, 0.0, 0.0, -0.9810548967323932, 0.9924997633696169, 0.0, 0.9223419718743473, 2.9167959758458033, -3.1705074976614105, -0.6467501387775243, 1.1177656966208296, 0.6329639550588929, -1.8702167790072908, 0.0, -1.2748644376899698, 1.1188390951771237, -1.9129944052541965, 1.2520310447761196, -1.1460629824441562, 5.505620442214575, -5.055408597830455, 1.9346123214587725, 0.0, 2.179212989121611, -5.146464209573767, 4.005583781276433, -1.947728743247218, -1.2403953954323994, -1.088623746058113, 2.017963739585756, -1.2681574650783094, 33.399458512501994, -28.96401363097294, -0.2276770710278992, 19.00568892561323, 0.0, -46.36468550794061, 55.320492574602746, -1.0901233252329408, 0.0, -0.970342163100058, 1.0369876628674564, 0.0, 0.0, -0.5518639518436894, -0.6436683675426819, 0.6190032320429759, -0.5606009249111178, 0.6542508403721816, 0.0, -1.2916082344065163, 1.2716948638651389, -1.1111842898301159, 0.0, 0.0, -0.6357944201487052, 0.6146581083853573, -1.1396171663791115, 0.6446527212086748, 0.0, -0.6238553069966684, 0.0, -0.5516280660222267, 0.0, 0.0, 0.5531412293773986, -0.6527591627110731, 0.0, 0.0, -0.7426504360143421, 0.0, -6.11644910012274, 0.0, 0.0, 1.0038422784658652, -2.220001323223903, 0.0, 0.6443952127087528, 0.0, 0.0, -1.2850786647670698, 0.5727224190784399, -1.2662145374682074, 1.109068769707747, -1.2850294502868438, 0.0, 0.5420783333010231, -0.6569664883660828, 0.0, -0.6414731094814601, 0.0, 0.5687924546212734, -0.6367161550839483, -0.6315866825279707, -0.5424288550200779, 0.6528861734832861, 0.0, -0.618323394782814, 0.0, 0.5510120861797163, -0.1003935986366226, 0.6351685861178628, 1.9370097212921702, -1.2378420493448237, -33.833132428378775, 0.0, 0.0, 0.0, 38.03564814587878, -38.94628152684017, 0.0, 0.0, 0.0, 0.0, 22.17138308457712, -18.902903044080517, 0.0, 0.0, 18.13348753318517, -1.2448129873791525, -17.538381768764378, 18.822696661744697, -20.317112364642096, 17.13257884507692, -19.96965527833453, 0.0, 15.833003525470344, -15.670853726882124, 0.0, 18.858674888396443, -19.993107310969435, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.394995316177692, 1.240982595252713, -25.13616332727382, 0.0, 24.790007486504596, 0.0, -30.47374004020247, 24.236094370719602, -28.597010281322397, 25.744524124425485, -24.354472156168782, 25.911441529675898, -1.127569275023355, -0.6298179306409594, -24.76014851408243, 0.0, 0.0, 0.0, 0.0, 0.9356048144110858, -21.66594541214364, 0.0, 21.062311326855923, -5.359733353211157, 1.111265250970366, -4.603118458056109, 1.072643437120389, -2.1782085870454284, 1.061849113924051, -0.6288641832779832, 0.0, -0.6445932779049933, -0.56685145892179, -0.633069045408922, -12.738577416023814, 0.0, 11.618655333542307, -12.298398265391947, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.106418392958739, -12.044137578967522, 11.042808331383107, -1.6413171848402437, 0.6575277869225102, -9.094635957690459, 0.0, 0.5189144249156548, -7.9390462730450375, 0.0, 0.0, 13.184625338904246, 0.0, -1.031073526881192, -1.1347457558336154, 0.0, 0.9092060739407999, -0.6363828641222302, 0.0, -0.6398047470864605, -0.5569865942486074, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.6463564565466973, -0.6234055930024303, 0.5710265207210152, 0.0, -0.5568350061069514, 0.6643179118425013, -1.245580055533283, 0.5553824763972935, 0.0, -0.5615203057747791, 0.6232157025898576, -0.6456549983067025, 0.0, 0.584164902506964, -0.5294835574070569, 0.0, -1.8928859454153648, 0.0, -1.9352669219766534, 0.0, 1.009447299069807, -0.9416620455081218, 1.0024147985277951, 0.8270015970976203, -0.533344862445401, 0.0, 0.0, -0.5681875939798698, 0.6554214457605402, -1.1368757157474607, 0.6167096499095736, 0.0, -0.5701183922576086, 0.0, 0.0, 0.0, 0.6406598593216586, 0.0, -0.6482895916411637, 0.0, 0.0, 0.0, 0.0, 0.6288358983200775, 0.0, -0.0342296878991236, 0.0, 0.0, 0.0, 0.0, 0.0, 37.039332673007394, 7.7795652829138815, -4.279203395364023, -0.5539887202652192, -28.484855070369626, 4.846665125953317, 0.0, 0.0, -1.8241920612369165, 1.2623654846015517, -1.1782993995153985, 1.8777522925511678, -2.5297179605099482, 2.2277245023967285, 25.508725036300476, -25.984799931852155, 22.368577466384906, -13.77768805805238, 14.214799400812025, -1.9224640958259491, -0.6475389436956758, -1.674339434342628, 0.0, 0.5633681439345607, -1.243180342931666, 0.0, 0.5905349487156023, -0.10482545352758489, 0.5781180135353063, -1.1654324555249138, 0.0, -7.436803404298434, 1.095977005487327, -28.068904418104843, 11.186166565644323, -1.0187149189386122, 2.996787653615319, -5.044383508923848, 0.0, -0.6908411707542044, 0.0, 0.5528022300276119, -1.329035774264077, 0.0, 0.635211873390883, -0.6089954626302226, 0.0, -0.7159836807155905, 0.0, 0.578644409188108, 0.0, -1.0681770488463305, 0.0, 0.6021021805601414, 0.0, 0.6278334281351976, -1.1841459042080154, 0.6379315117455152, -0.644910435598198, -0.5797681924679832, 0.0, 0.03293221080897523, 0.0, -1.0875370135089586, 0.6892291512611948, -1.8513811520635626, -0.9887096317948236, 0.8795210585361253, -0.9552917596683826, 0.0, 0.9221189170175113, -0.7195642439890547, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.718410503958296, -11.985913619152706, 8.809076219292088, -10.600041699573529, 0.0, 0.0, 0.0, 0.0, 11.43000545025132, -0.6515828556337483, -9.71095436871387, 0.0, 0.0, 10.353293309707052, -8.465889476795319, 0.0, 0.0, 14.55313338971657, 0.0, -0.8443490689481632, 0.0, 1.066100019063354, -1.0595288797948799, 1.0516257145722598, -1.0421278340269584, 0.0, 0.0, 0.0, 0.0, -0.645208054517206, 0.6254600764992284, -0.5487592320020934, 0.654511180812384, -0.6373983146793105, 0.0, 0.0, 0.0, -0.6288641832779832, 0.6240502298730863, 0.0, 0.0, -0.4437102234258633, 0.679091048920479, -1.4529250381044758, 0.6521654085067677, 0.0, 0.0, -0.6295626852789975, 0.0, 0.5125537231995015, -1.997834645200472, 2.2341619836471627, -3.2287057374525308, -11.201239150754443, 0.0, 11.446910223170537, -10.776857620032002, 6.855725017196642, -7.542355691422408, 0.0, 6.918543333358326, -6.872067622416683, 4.7027935529082, -5.209223532334061, 6.063810449379544, -5.0619843643141635, 0.0, 0.0, 5.655597206116341, -7.131229597388467, 6.882301591642511, -2.5297942504730964, -4.391251635868713, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.743654912701131, 0.0, 0.03679477085423213, -0.9255475869982569, 0.0, 0.0]
steering_pwm_data = [element for element in steering_pwm_data if element is not None]
throttle_pwm_data = throttle_pwm_data[0:len(throttle_pwm_data)-4]
import board
import time
import adafruit_mcp4728
MCP4728_DEFAULT_ADDRESS = 0x60
MCP4728A4_DEFAULT_ADDRESS = 0x64
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
# use for MCP4728 variant
#mcp4728 = adafruit_mcp4728.MCP4728(i2c, adafruit_mcp4728.MCP4728_DEFAULT_ADDRESS)
# use for MCP4728A4 variant
mcp4728 = adafruit_mcp4728.MCP4728(i2c, adafruit_mcp4728.MCP4728A4_DEFAULT_ADDRESS)
#neutral values set at beginning
mcp4728.channel_a.value = int(65535 / 2)
mcp4728.channel_b.value = int(65535 / 2)
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/timekeeping.h>
#include <linux/sysfs.h>
#define FILENAME "/dev/encoder_speed"
unsigned int irq_number;
struct gpio_desc *encoder_desc;
ktime_t last_change;
s64 speedOut;
int stopped;
/**
* @brief Shows the speed in the sysfs file
*/
static ssize_t speed_show(struct device *dev, struct device_attribute *attr, char *buf) {
if(stopped) {
return sprintf(buf, "%d\n", 0);
}
stopped = 1;
return sprintf(buf, "%lld\n", speedOut);
}
/**
* @brief The sysfs attribute
*/
static DEVICE_ATTR(speed, 0444, speed_show, NULL);
/**
* @brief Interrupt service routine is called, when interrupt is triggered
*/
static irq_handler_t gpiod_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs) {
printk("encoder_gpiod_irq: Interrupt was triggered and ISR was called!\n");
printk("encoder_gpiod_irq: This means that the encoder triggered\n");
ktime_t now;
ktime_t diff;
s64 timeDiff;
now = ktime_get_real();
diff = ktime_sub(now, last_change);
timeDiff = ktime_to_ns(diff);
last_change = now;
speedOut = timeDiff;
stopped = 0;
return (irq_handler_t) IRQ_HANDLED; // Return value denoting that the interrupt has been dealt with.
}
/**
* @brief This function is called, when the module is loaded into the kernel
*/
static int setup_encoder(struct platform_device *pdev) {
printk("Setting up encoder\n");
speedOut = 0.0;
/* Setup the gpio */
if((encoder_desc = devm_gpiod_get(&pdev->dev, "encoder", GPIOD_IN)) == NULL) {
printk("Error occurred setting up encoder! Aborting...\n");
return -1;
}
//gpiod_set_debounce(encoder_desc 5000);
last_change = ktime_get_real();
stopped = 1;
/* Setup the interrupt */
irq_number = gpiod_to_irq(encoder_desc);
if(request_irq(irq_number, (irq_handler_t) gpiod_irq_handler, IRQF_TRIGGER_FALLING, "encoder_gpiod_irq", NULL) != 0){
printk("Error!\nCan not request interrupt nr.: %d\n", irq_number);
// Free the encoder if it fails
devm_gpiod_put(&pdev->dev, encoder_desc);
return -1;
}
printk("Done!\n");
printk("GPIO 24 is mapped to IRQ Nr.: %d\n", irq_number);
return 0;
}
/**
* @brief This function is called, when the module is removed from the kernel
*/
static void remove_encoder(struct platform_device *pdev) {
printk("Removing encoder\n");
free_irq(irq_number, NULL); // Free the interrupt
devm_gpiod_put(&pdev->dev, encoder_desc); // Free the encoder
}
/**
* Checks if there are gpiod pins registered to the functions
* 'encoder' (in other words, did your overlay work)
*/
static int gpiods_exist(struct platform_device *pdev) {
int b_c;
if((b_c = gpiod_count(&pdev->dev, "encoder")) == -ENOENT) {
printk("No gpio associated with encoder!\n");
}
if(b_c < 0) {
return 0;
}
return 1;
}
/**
* Driver probe function
*/
static int gpiod_probe(struct platform_device *pdev)
{
printk("Begininng speed encoder driver setup...\n");
// Check if the overlay worked properly
if(!gpiods_exist(pdev)) {
return -1;
}
int err;
err = sysfs_create_file(&pdev->dev.kobj, &dev_attr_speed.attr);
if (err) {
printk("Error creating sysfs speed file.");
return -1;
}
// Set up the encoder and error handle
if(setup_encoder(pdev) < -1) {
printk("Error setting up encoder!\n");
return -1;
}
printk("Encoder setup complete!\n");
return 0;
}
/**
* Driver remove function
*/
static int gpiod_remove(struct platform_device *pdev)
{
// Free the encoder
remove_encoder(pdev);
printk("Removed encoder!\n");
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_speed.attr);
return 0;
}
// Driver configuration:
/**
* Match table
*/
static struct of_device_id matchy_match[] = {
{ .compatible = "two-compatible"},
{/* leave alone - keep this here (end node) */},
};
/**
* Platform driver object
*/
static struct platform_driver gpio_encoder_driver = {
.probe = gpiod_probe,
.remove = gpiod_remove,
.driver = {
.name = "final-project",
.owner = THIS_MODULE,
.of_match_table = matchy_match,
},
};
module_platform_driver(gpio_encoder_driver);
MODULE_DESCRIPTION("Comp 424 Project 2");
MODULE_AUTHOR("Barret Glass (bmg7)");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:final-project");










Comments