Quantcast
Viewing all articles
Browse latest Browse all 1234

Python • RPI freezes by running this code

Hello, I am working on an autonomous car powered by arduino mega and raspberry pi 4B 8GB. Arduino communicates with rpi via UART and rpi sends commands like FORWARD, LEFT etc. The arduino reads them and performs the movement according to the command received and also calculates the pwm from the speed measured by the ir encoders connected to the arduino and also sends the distance travelled to the rpi every 100ms. I also use a camera for a simple edge finding algorithm to detect obstacles and ground, then an ultrasonic sensor, the previously mentioned ir encoders on the motors and a compass. All the data is then used to create a simple 2D map (top view) of the searched area, which will in future gradually expand as the car uses some algorithm to find the best path. Now I'm stuck because I can't find a way to "run my script". Every time I run it, after about one second, rpi freezes but doesn't detect any error. I also made a "simulation" to test the mechanism on pc with some random values for the sensors and it works. Any ideas? (temperature on rpi is around 42°C)

Code:

# main.pyimport viewimport serial_busimport compassfrom motion import MotionControllerimport tcpdef main():    motion_controller = MotionController()    while True:        surrounding = view.check_ground()        distance = view.ping()        angle = compass.get_angle()        mileage = serial_bus.read()        direction = motion_controller.gen_map(surrounding, distance, angle, mileage)        serial_bus.write(direction)        if __name__ == "__main__":    main()

Code:

#compass.pyimport RPi.GPIO as GPIOimport smbusimport timeimport mathimport csvbus = smbus.SMBus(1)address = 0x1edef read_byte(adr):    return bus.read_byte_data(address, adr)def read_word(adr):    high = bus.read_byte_data(address, adr)    low = bus.read_byte_data(address, adr+1)    val = (high << 8) + low    return valdef read_word_2c(adr):    val = read_word(adr)    if (val >= 0x8000):        return -((65535 - val) + 1)    else:        return valdef write_byte(adr, value):    bus.write_byte_data(address, adr, value)    def get_angle():    write_byte(0, 0b01110000)    write_byte(1, 0b00100000)    write_byte(2, 0b00000000)     scale = 0.92    x_offset = 38    y_offset = -129.5    x_out = (read_word_2c(3) - x_offset) * scale    y_out = (read_word_2c(7) - y_offset) * scale    z_out = (read_word_2c(5)) * scale            bearing  = math.atan2(y_out, x_out)     if (bearing < 0):        bearing += 2 * math.pi        declination = 5.5    bearing = round((math.degrees(bearing) + declination), 1)    #print("Bearing: ", bearing)    return bearing

Code:

#motion.pyimport tkinter as tkimport mathfrom enum import Enumcommands = ["STOP", "FRWD", "BKWD", "LEFT", "RIHT"]class Commands(Enum):    STOP = 0    FRWD = 1    BKWD = 2    LEFT = 3    RIHT = 4class MotionController:    def __init__(self):        self.width, self.height = 1000, 1000        self.angle_line_startx = self.width / 2        self.angle_line_starty = self.height / 2        self.angle = 0        self.mileage = 0        self.line_length = 20        self.x_factor = self.width / 2        self.y_factor = self.height / 2        self.size_factor = 0.2        self.turn = False        self.cmd_pick = 0        self.polygon_points = []                self.root = tk.Tk()        self.root.title("Map")        self.canvas = tk.Canvas(self.root, width=self.width, height=self.height, bg="black")        self.canvas.pack()    def arr_pos(self, x, y):        image_width = 640 * self.size_factor        image_height = 480 * self.size_factor                x_rot_offset = self.x_factor - image_width / 2        y_rot_offset = self.y_factor - image_height / 2        angle_in_rad_rot = (self.angle + 90) * math.pi / 180        cos_theta = math.cos(angle_in_rad_rot)        sin_theta = math.sin(angle_in_rad_rot)        x_rot = self.size_factor * (x - self.x_factor) * cos_theta - self.size_factor * (y - self.y_factor) * sin_theta + x_rot_offset        y_rot = self.size_factor * (x - self.x_factor) * sin_theta + self.size_factor * (y - self.y_factor) * cos_theta + y_rot_offset        angle_in_rad_transform = self.angle * math.pi / 180        cos_fi = math.cos(angle_in_rad_transform)        sin_fi = math.sin(angle_in_rad_transform)        x_transform_offset = self.mileage * self.size_factor * cos_fi        y_transform_offset = self.mileage * self.size_factor * sin_fi                x_transformed = x_rot + x_transform_offset        y_transformed = y_rot + y_transform_offset        return x_transformed, y_transformed    def gen_map(self, surrounding, distance, angle, mileage):        self.angle = angle        self.mileage = mileage        angle_in_rad = angle * math.pi / 180        cos_theta = math.cos(angle_in_rad)        sin_theta = math.sin(angle_in_rad)        connection_points = [(0, 0),(0, 0)]        angle_line_endx = self.angle_line_startx + self.line_length * cos_theta        angle_line_endy = self.angle_line_starty + self.line_length * sin_theta        self.canvas.delete("angle_line")        self.canvas.create_line(self.angle_line_startx, self.angle_line_starty, angle_line_endx, angle_line_endy, fill="red", tags="angle_line")        if mileage % 500 == 0: #just random val to see if mapping works            self.turn == True                    if self.turn == True:            x_start_rot, y_start_rot = self.arr_pos(surrounding[0][0], surrounding[0][1])            x_end_rot, y_end_rot = self.arr_pos(surrounding[len(surrounding)-2][0], surrounding[len(surrounding)-2][1])            self.x_factor = (x_start_rot + x_end_rot) / 2            self.y_factor = (y_start_rot + y_end_rot) / 2            self.turn = False        self.polygon_points = [self.arr_pos(x, y) for x, y in surrounding]        self.canvas.create_polygon(self.polygon_points, outline="white", fill="white", tags="map_polygon")                if distance < 30:            self.cmd_pick = Commands.STOP.value        else:             if(angle >= angle + 90):                self.cmd_pick = Commands.RIHT.value            else:                self.cmd_pick = Commands.FRWD.value                    direction = commands[self.cmd_pick]        self.root.update()        return direction

Code:

#serial_bus.pyimport serialimport time ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)ser.reset_input_buffer()mileage = 0def write(direction):    ser.write((direction + '\n').encode())            def read():    global mileage    if ser.inWaiting() > 0:        mileage = int(ser.readline().decode('UTF-8').strip())    return mileage

Code:

#view.pyimport osos.environ['QT_QPA_PLATFORM'] = 'xcb'import cv2import numpy as npimport RPi.GPIO as GPIOimport schedimport timecapture = cv2.VideoCapture(0)capture.set(cv2.CAP_PROP_FRAME_WIDTH, 640)capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)last_distance = 0def check_ground():    step_size = 6    fov_width = 173    edge_array = []    _, img = capture.read()    img = cv2.resize(img, (640, 480))    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)    img_gray = cv2.bilateralFilter(img_gray, 10, 25, 50)    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,10))    dilate = cv2.morphologyEx(img_gray, cv2.MORPH_DILATE, kernel)    img_edge = cv2.Canny(dilate, 35, 150)    imagewidth = img_edge.shape[1] - 1    imageheight = img_edge.shape[0] - 1    for j in range(0, imagewidth, step_size):        for i in range(imageheight-5, 0, -1):            if img_edge.item(i, j) == 255:                edge_array.append((j, i))                break        else:            edge_array.append((j, 0))                edge_array.insert(0, (0, imageheight))    edge_array.append((imagewidth, imageheight))        top_left = (0, 0)    bottom_left = (0, imageheight)    top_right = (imagewidth, 0)    bottom_right = (imagewidth, imageheight)    pts1 = np.float32([top_left, bottom_left, top_right, bottom_right])    pts2 = np.float32([[fov_width, 0], [0, imageheight], [(imagewidth - fov_width), 0], [imagewidth, imageheight]])        transform_matrix = cv2.getPerspectiveTransform(pts1, pts2)    transformed_edge_array = []    for point in edge_array:        x, y = point        original_coordinates = np.array([x, y, 1])        transformed_coordinates = np.dot(transform_matrix, original_coordinates)        transformed_x = int(transformed_coordinates[0] / transformed_coordinates[2])        transformed_y = int(transformed_coordinates[1] / transformed_coordinates[2])        transformed_edge_array.append((transformed_x, transformed_y))            cv2.waitKey(1)    return transformed_edge_arraydef ping():    global last_distance    GPIO.setmode(GPIO.BOARD)    TRIG_PIN = 13    ECHO_PIN = 15    GPIO.setup(TRIG_PIN, GPIO.OUT)    GPIO.setup(ECHO_PIN, GPIO.IN)    pulse_start_time = 0    pulse_end_time = 0    try:        GPIO.output(TRIG_PIN, GPIO.LOW)        time.sleep(2E-6)        GPIO.output(TRIG_PIN, GPIO.HIGH)        time.sleep(10E-6)        GPIO.output(TRIG_PIN, GPIO.LOW)        while GPIO.input(ECHO_PIN) == 0:            pulse_start_time = time.time()        while GPIO.input(ECHO_PIN) == 1:            pulse_end_time = time.time()        pulse_duration = pulse_end_time - pulse_start_time        distance = round(pulse_duration * 17150, 2)        if distance > 300 or distance <= 0:            distance = last_distance        else:            last_distance = distance                    #print(distance)        time.sleep(0.1)        return distance            except Exception as e:        print(f"Error in ping function: {e}")

Statistics: Posted by mart1nek — Mon Jan 29, 2024 7:36 pm



Viewing all articles
Browse latest Browse all 1234

Trending Articles