Cannon - Code

From RoboWiki
Jump to: navigation, search

Return back to project page: Avalanche Cannon - Jakub Vojtek

Python code for the Avalanche Cannon:

import cv2
import numpy as np
import pytesseract
from buildhat import Motor, ForceSensor
import time
import re
import serial
import app

motor_aim = None
motor_lift = None
motor_trigger = None
latest_pitch = None
setup_done = False
ammo = 0

# Serial connection to Arduino
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
time.sleep(5)  # Allow time for serial connection to stabilize
ser.reset_input_buffer()  # Clear input buffer


def setup():
    global motor_aim, motor_lift, motor_trigger
    motor_aim = Motor('C')
    motor_lift = Motor('D')
    motor_trigger = Motor('A')


def read_serial():
    global latest_pitch
    while ser.in_waiting > 0:
        latest_pitch = ser.readline().decode('utf-8').rstrip()
        print(latest_pitch)


@app.button_click_signal.connect
def handle_button_click(sender, button_id):
    global setup_done
    if not setup_done:
        setup()
        setup_done = True

    read_serial()

    if button_id in ['cnn-left', 'cnn-right']:
        motor_aim.stop()
    elif button_id in ['lower', 'lift']:
        motor_lift.stop()
        if latest_pitch is not None:
            app.change_label_text('angle', latest_pitch)
    elif button_id == 'cnn-trigger':
        shoot()
    elif button_id == 'load-canvas':
        canvas_setup()
    else:
        print("This button has no onClick function")


@app.button_hold_signal.connect
def handle_button_hold(sender, button_id):
    global setup_done
    if not setup_done:
        setup()
        setup_done = True

    if button_id == 'cnn-left':
        motor_aim.start(10)
    elif button_id == 'cnn-right':
        motor_aim.start(-10)
    elif button_id == 'lower':
        motor_lift.start(-30)
    elif button_id == 'lift':
        motor_lift.start(30)
    else:
        print("This button has no onHold function.")


def pitch_to_y(pitch):
    return 360 - (float(pitch) * 5)


def shoot():
    global ammo
    if ammo < 4:
        motor_trigger.run_for_degrees(360)
        motor_trigger.run_to_position(0)
        ammo += 1
        app.change_label_text('ammo', 3 - ammo)
        print(latest_pitch)
        if latest_pitch is not None:
            y = pitch_to_y(latest_pitch)
            app.draw_rectangle("myCanvas", 15 + (ammo * 100), 360, 25 + (ammo * 100), y)
    else:
        app.change_label_text('ammo', "Out of ammo!!!")


def canvas_setup():
    print("drawing")
    app.draw_line("myCanvas", 20, 360, 380, 360)  # x line
    app.draw_line("myCanvas", 40, 380, 40, 20)  # y line
    app.add_text("myCanvas", 5, 355, "shot")
    app.add_text("myCanvas", 30, 390, "angle")

    # Horizontal scale lines and numbers
    app.draw_line("myCanvas", 120, 355, 120, 365)
    app.draw_line("myCanvas", 220, 355, 220, 365)
    app.draw_line("myCanvas", 320, 355, 320, 365)
    app.add_text("myCanvas", 116, 375, "1")
    app.add_text("myCanvas", 216, 375, "2")
    app.add_text("myCanvas", 316, 375, "3")

    # Vertical scale lines and numbers
    vertical_steps = [310, 260, 210, 160, 110, 60]
    for i, y in enumerate(vertical_steps, start=1):
        app.draw_line("myCanvas", 35, y, 45, y)
        app.add_text("myCanvas", 10, y + 5, str(i * 10))


if __name__ == '__main__':
    app.add_css_file('static/cannon.css')
    modified_img_src = app.set_img_src_to_camera('/video_feed', 0)
    app.run_app("templates/cannon.html")