Nathan HsiaoJerry JiangSamuel BartonBarret Glass
Published

Dogo Mobile (ELEC 424 Final)

This is an automous RC car with lane keeping that is able to self drive a given course.

ExpertFull instructions provided217
Dogo Mobile (ELEC 424 Final)

Things used in this project

Hardware components

Power Supply Accessory, Battery Pack
Power Supply Accessory, Battery Pack
×1
Compute Module 4
Raspberry Pi Compute Module 4
×1
Raspberry Pi Web Camera
×1
Webcam, Logitech® HD Pro
Webcam, Logitech® HD Pro
×1
USB WiFi Adapter
×1

Software apps and online services

OpenCV
OpenCV

Story

Read more

Schematics

Car Picture

Code

Camera.py

Python
This came from the instructables from Raja: “Autonomous Lane-Keeping Car Using Raspberry
Pi 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

Python
This was referenced from the user Raja's instructables: https://www.instructables.com/Autonomous-Lane-Keeping-Car-Using-Raspberry-Pi-and/
import 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

Python
This came from the instructables from Raja: “Autonomous Lane-Keeping Car Using Raspberry
Pi 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

Python
This came from the instructables from Raja: “Autonomous Lane-Keeping Car Using Raspberry
Pi 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]

initialize_car.py

Python
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)

gpiod_driver.c

C/C++
#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");

Github Repostory

Credits

Nathan Hsiao
1 project • 3 followers
Jerry Jiang
0 projects • 1 follower
Samuel Barton
0 projects • 1 follower
Barret Glass
0 projects • 1 follower
Thanks to Jerry Jiang, Barret Glass, and Sam Barton.

Comments