diff --git a/Manual/6_Module_4.ipynb b/Manual/6_Module_4.ipynb index 98bbc3a..995e1b5 100644 --- a/Manual/6_Module_4.ipynb +++ b/Manual/6_Module_4.ipynb @@ -18,9 +18,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-26T13:39:24.987695Z", + "start_time": "2025-11-26T13:39:24.623022Z" + } + }, "source": [ "# Import necessary libraries\n", "import numpy as np\n", @@ -34,7 +37,9 @@ "# If you are using the simulator, uncomment the next line and comment the real car line\n", "\n", "# Note: After changing the import statement, you need to restart the kernel for changes to take effect." - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "markdown", @@ -116,9 +121,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-26T13:40:00.991214Z", + "start_time": "2025-11-26T13:40:00.934104Z" + } + }, "source": [ "### Student Version ###\n", "# Car parameters, set them to the real values\n", @@ -141,8 +149,8 @@ "# Numerical simulation (Euler's method)\n", "for i in range(1, len(t)):\n", " # TODO: Implement the model without air resistance (c=0) straight from the differential equation\n", - " dv = \n", - " v[i] = \n", + " dv = (F_motor - b * v[i-1])/m\n", + " v[i] = v[i-1] + dv*dt\n", "\n", "# Plotting the results\n", "plt.figure(figsize=(6, 4))\n", @@ -152,7 +160,23 @@ "plt.title('Velocity of the RC Car Over Time')\n", "plt.grid(True)\n", "plt.show()" - ] + ], + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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/Xp4e3tjw4YNRnmaOnXqY+zRv4KDg6FSqfD9998Xux4OAHz33XcwMzMzKjC8vLzQsWNHrF27FuPGjcOGDRsQEhICjUZj6NOwYUNs374dXbp0qdACozxVx32qyTgnhKqEwqMeU6ZMQXx8vNFREADo378/4uLisHXr1iLPTUtLQ35+frHjqlQq9OrVC5s3bzaac5KSkoLIyEh07drVcNj+lVdewd9//42NGzcWGefBv9QeVrjAVFpaWrHbhw4dilOnTuH99983zIF5lOeeew4AihQs8+fPBwD06dPnkWOUFGt6evpjPRf3j1o1bNgQn3/+ObKysopsv3nz5mON6+DggDfeeANbt25FfHw8AGDSpEmwtrbGqFGjkJKSUuQ5Fy5cwKJFi0odd/r06UhNTcWoUaOKfY9s27YNv/32G/DAX+gP/qz3799f4kquZVW/fn2EhoZi+/btWLp0aZHtERER2LFjB0aOHIl69eoZbRswYAD27duH5cuX49atW0anYnD/90Kn02HmzJlFxs3Pzy/xPVmZVcd9qsl4JISqBC8vL3Tu3BmbN28GHihKCr3//vv45ZdfDKtN+vn5ITs7G8ePH8f69etx+fJlODk5FTv2rFmzEB0dja5du+Ktt96CmZkZ/ve//yE3Nxdz5841eo3169ejX79+eP311+Hn54fbt2/jl19+QUREBNq0aVPs+H5+fgCAd955B0FBQUUKjT59+qB27dpYt24dgoODSzzX/aA2bdpg+PDhWLZsGdLS0tCtWzccOHAAq1atQkhICHr06FHGzBaNde3atQgLC0OHDh1gY2ODvn37lvn5SqUS33zzDYKDg9GiRQuEhoaibt26uH79Onbu3Ak7Ozv8+uuvjxXb+PHjsXDhQnzyySdYs2YNGjZsiMjISAwYMADNmjUzWjF17969WLdu3SPvWTJgwAAcP34c//3vf3H06FEMGjTIsGJqVFQUYmJiEBkZCdw/8rJhwwa89NJL6NOnDy5duoSIiAg0b9682ILLFAsWLMDp06fx1ltvISoqynDEY+vWrdi8eTO6deuGefPmFXle//798d577+G9995DrVq1ihx96tatG9544w3MmTMH8fHx6NWrF9RqNc6dO4d169Zh0aJFhsm+VUV13KcaTe7Lc4jKasmSJQJAkXUpCmVmZorw8HDRqFEjYW5uLpycnETnzp3F559/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" + }, + "metadata": {}, + "output_type": "display_data", + "jetTransient": { + "display_id": null + } + } + ], + "execution_count": 6 }, { "cell_type": "markdown", @@ -271,9 +295,12 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "metadata": { + "ExecuteTime": { + "end_time": "2025-11-26T13:39:25.087887Z", + "start_time": "2025-11-26T13:39:25.084439Z" + } + }, "source": [ "### Student Version ###\n", "# Car Parameters\n", @@ -287,7 +314,18 @@ "delta_deg = np.degrees(delta)\n", "\n", "print(f\"Steering Angle: {delta_deg:.2f} degrees\")" - ] + ], + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (3356480960.py, line 7)", + "output_type": "error", + "traceback": [ + " \u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[4]\u001B[39m\u001B[32m, line 7\u001B[39m\n\u001B[31m \u001B[39m\u001B[31mdelta =\u001B[39m\n ^\n\u001B[31mSyntaxError\u001B[39m\u001B[31m:\u001B[39m invalid syntax\n" + ] + } + ], + "execution_count": 4 }, { "cell_type": "markdown", diff --git a/student_code/control.py b/student_code/car.py similarity index 82% rename from student_code/control.py rename to student_code/car.py index d68169b..9e3d368 100644 --- a/student_code/control.py +++ b/student_code/car.py @@ -2,6 +2,10 @@ from serial import Serial class KITT: + current_speed = 150 + current_angle = 150 + beacon_state = False + def __init__(self, port, baudrate=115200): # Initialize the serial connection # self.serial = Serial(port, baudrate, rtscts=True) @@ -39,13 +43,19 @@ class KITT: # Send the motor speed command using send_command # Use the format 'M\n' self.send_command(f"M{speed}\n".encode()) + self.current_speed = speed + def get_speed(self): + return self.current_speed def set_angle(self, angle): # Send the steering angle command using send_command # Use the format 'D\n' self.send_command(f"D{angle}\n".encode()) + self.current_angle = angle + def get_angle(self): + return self.current_angle def stop(self): # Stop the car by setting speed and angle to neutral (150) @@ -63,6 +73,17 @@ class KITT: # Use the command 'A0\n' self.send_command(b"A0\n") + def toggle_beacon(self): + if self.beacon_state: + self.beacon_state = False + self.stop_beacon() + else: + self.beacon_state = True + self.start_beacon() + + def get_beacon_state(self): + return self.beacon_state + def close(self): # Close the serial connection # self.serial.close() diff --git a/student_code/ui.py b/student_code/ui.py new file mode 100644 index 0000000..a8eb96f --- /dev/null +++ b/student_code/ui.py @@ -0,0 +1,168 @@ +import queue +import threading +import time +import tkinter as tk +from car import KITT +import serial.tools.list_ports +from pynput import keyboard + +if __name__ == "__main__": + serial_selector = tk.Tk() + serial_selector.title("Select serial port") + + + ports = list(serial.tools.list_ports.comports()) + length = len(ports) * 25 + serial_selector.geometry(f"600x{length+50}") + selected_port = tk.StringVar() + + for port in ports: + tk.Radiobutton(serial_selector,text = f"{port.device}",variable=selected_port,value= port.device).pack() + + def select_port(): + global selected_port + selected_port = selected_port.get() + serial_selector.destroy() + + button = tk.Button(serial_selector, text="Select serial port", command=select_port) + button.pack() + serial_selector.mainloop() + + car = KITT(f"{selected_port}") + root = tk.Tk() + root.title("Patatje Oorloog") + root.geometry("800x600") + + speed_label = tk.Label(root, text=f"Speed {car.get_speed()}") + speed_label.grid(row = 0, column = 0) + + speed_var = tk.StringVar() + speed_entry = tk.Entry(root, textvariable=speed_var) + speed_entry.grid(row = 0, column = 1) + + def speed_btn(): + global car + car.set_speed(speed_var.get()) + speed_label.config(text = f"Speed {car.get_speed()}") + + speed_set_btn = tk.Button(root, text="Set Speed", command=speed_btn) + speed_set_btn.grid(row = 0, column = 2) + + angle_label = tk.Label(root, text=f"Angle {car.get_angle()}") + angle_label.grid(row = 1, column = 0) + + angle_var = tk.StringVar() + angle_entry = tk.Entry(root, textvariable=angle_var) + angle_entry.grid(row=1, column=1) + + + def angle_btn(): + global car + car.set_angle(angle_var.get()) + angle_label.config(text=f"Speed {car.get_angle()}") + + + angle_set_btn = tk.Button(root, text="Set Angle", command=angle_btn) + angle_set_btn.grid(row=1, column=2) + + beacon_label = tk.Label(root, text=f"Beacon {car.get_beacon_state()}") + beacon_label.grid(row = 2, column = 0) + + def toggle_beacon_btn(): + global car + car.toggle_beacon() + beacon_label.config(text = f"Beacon {car.get_beacon_state()}") + + beacon_toggle = tk.Button(root, text="Toggle Beacon", command=toggle_beacon_btn) + beacon_toggle.grid(row = 2, column = 1) + + def close_btn_func(): + car.stop_beacon() + car.stop() + car.close() + root.destroy() + + close_btn = tk.Button(root, text="Close", command=close_btn_func) + close_btn.grid(row = 10,column = 0) + + # Thread-safe queue for passing keys from listener to Tkinter + key_queue = queue.Queue() + last_key = None + def start_listener(): + """Start pynput listener in a background thread.""" + + def on_press(key): + # Put a string representation of the key into the queue + global last_key + try: + key_queue.put(f"{key.char}") + if True: #not key == last_key : + if key.char == "w": + car.set_speed(165) + speed_label.config(text = f"Speed {car.get_speed()}") + if key.char == "s": + car.set_speed(140) + speed_label.config(text=f"Speed {car.get_speed()}") + if key.char == "a": + car.set_angle(200) + angle_label.config(text=f"Angle {car.get_angle()}") + if key.char == "d": + car.set_angle(100) + angle_label.config(text=f"Angle {car.get_angle()}") + #last_key = key + except AttributeError: + key_queue.put(str(key)) + + def on_release(key): + # Stop listener if ESC is pressed + if key == keyboard.Key.esc: + return False + try : + if key.char == "w": + car.set_speed(150) + speed_label.config(text=f"Speed {car.get_speed()}") + if key.char == "s": + car.set_speed(150) + speed_label.config(text=f"Speed {car.get_speed()}") + if key.char == "a": + car.set_angle(150) + angle_label.config(text=f"Angle {car.get_angle()}") + if key.char == "d": + car.set_angle(150) + angle_label.config(text=f"Angle {car.get_angle()}") + except AttributeError: + pass + return None + + def run_listener(): + with keyboard.Listener(on_press=on_press, + on_release=on_release) as listener: + listener.join() + + # Run listener in its own thread so it does not block Tkinter + t = threading.Thread(target=run_listener, daemon=True) + t.start() + + def poll_queue(): + """Check the queue for new keys and update the label.""" + try: + while True: + k = key_queue.get_nowait() + current = label_var.get() + label_var.set(f"Last key: {k}") + except queue.Empty: + pass + # Schedule next poll + root.after(10, poll_queue) + + label_var = tk.StringVar(value="Press any key (global). ESC stops listener.") + label = tk.Label(root, textvariable=label_var, width=50) + label.grid(row = 9,column = 0) + + start_button = tk.Button(root, text="Start listener", command=start_listener) + start_button.grid(row = 9, column = 1) + + # Start polling the queue + root.after(10, poll_queue) + root.protocol("WM_DELETE_WINDOW", close_btn_func) + root.mainloop() \ No newline at end of file