Skip to content

Commit 68d3103

Browse files
committed
added Proper initialization sequences, Detailed Logging and Debuging messages
1 parent 4c1aec2 commit 68d3103

File tree

5 files changed

+111
-96
lines changed

5 files changed

+111
-96
lines changed

L1/L1_motor.py

Lines changed: 26 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,31 @@
11
import gpiozero
2-
import logging
32
from gpiozero.pins.pigpio import PiGPIOFactory
4-
from gpiozero import Device
5-
6-
# Configure logging for debugging
7-
logging.basicConfig(level=logging.DEBUG)
3+
from utils.constants import MOTOR_PINS, PWM_FREQUENCY
4+
import logging
85

9-
# Set the pin factory to pigpio (optional, for sharing GPIO pins between processes)
10-
Device.pin_factory = PiGPIOFactory()
6+
logger = logging.getLogger(__name__)
117

128
class MotorController:
13-
def __init__(self, pins):
14-
"""
15-
Initialize the MotorController with a list of GPIO pins.
16-
Each pin should be unique to avoid conflicts.
17-
"""
18-
# Ensure that no pin conflicts exist and that each pin is used once
19-
if len(set(pins)) != len(pins):
20-
raise ValueError("Pins must be unique. Duplicate pins found.")
21-
22-
logging.debug(f"Initializing MotorController with pins: {pins}")
23-
24-
try:
25-
# Initialize PWMOutputDevice for each motor
26-
self.motor_a = gpiozero.PWMOutputDevice(pins[0])
27-
self.motor_b = gpiozero.PWMOutputDevice(pins[1])
28-
self.motor_c = gpiozero.PWMOutputDevice(pins[2])
29-
self.motor_d = gpiozero.PWMOutputDevice(pins[3])
30-
31-
logging.debug("MotorController initialized successfully.")
32-
except gpiozero.GPIOPinInUse as e:
33-
logging.error(f"GPIO pin conflict detected: {e}")
34-
raise
35-
except Exception as e:
36-
logging.error(f"An error occurred while initializing motors: {e}")
37-
raise
38-
39-
def set_speed(self, duty_cycle):
40-
"""
41-
Set the speed of all motors using a list of duty cycles.
42-
:param duty_cycle: List of duty cycles for each motor (e.g., [0.5, 0.5, 0.5, 0.5])
43-
"""
44-
if len(duty_cycle) != 4:
45-
raise ValueError("Duty cycle list must contain exactly 4 values.")
46-
47-
try:
48-
# Set the duty cycle for each motor
49-
self.motor_a.value = duty_cycle[0]
50-
self.motor_b.value = duty_cycle[1]
51-
self.motor_c.value = duty_cycle[2]
52-
self.motor_d.value = duty_cycle[3]
53-
54-
logging.debug(f"Motor speeds set to: {duty_cycle}")
55-
except Exception as e:
56-
logging.error(f"An error occurred while setting motor speeds: {e}")
57-
raise
9+
def __init__(self):
10+
"""Initialize with pigpio for hardware PWM"""
11+
gpiozero.Device.pin_factory = PiGPIOFactory()
12+
self.motors = [
13+
gpiozero.PWMOutputDevice(
14+
pin=pin,
15+
frequency=PWM_FREQUENCY,
16+
initial_value=0
17+
) for pin in MOTOR_PINS
18+
]
19+
logger.info(f"Motors ready on pins: {MOTOR_PINS}")
20+
21+
def set_speed(self, speeds):
22+
"""Set speeds between -1.0 (full reverse) and 1.0 (full forward)"""
23+
for motor, speed in zip(self.motors, speeds):
24+
motor.value = max(-1.0, min(1.0, speed))
25+
logger.debug(f"Motor speeds set: {speeds}")
26+
27+
def stop(self):
28+
"""Emergency stop all motors"""
29+
for motor in self.motors:
30+
motor.value = 0
31+
logger.warning("Motors forcefully stopped")

L2/L2_kinematics.py

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,46 @@
1+
from utils.constants import WHEELBASE
12
import numpy as np
23
import logging
34

4-
# Configure logging for debugging
5-
logging.basicConfig(level=logging.DEBUG)
5+
logger = logging.getLogger(__name__)
66

77
class Kinematics:
8-
def __init__(self, wheelbase):
8+
def __init__(self, wheelbase=WHEELBASE):
9+
"""Initialize with wheelbase from constants.py"""
910
self.wheelbase = wheelbase
11+
logger.info(f"Kinematics initialized with wheelbase: {self.wheelbase}m")
1012

11-
def compute_chassis_movement(self, phiL, phiR):
13+
def compute_chassis_speeds(self, phi_l, phi_r):
1214
"""
13-
Compute chassis movement based on wheel speeds.
15+
Convert wheel speeds to chassis movement
16+
phi_l, phi_r: left/right wheel speeds in rad/s
17+
Returns: (x_dot, theta_dot) in m/s and rad/s
1418
"""
15-
try:
16-
x_dot = (phiL + phiR) / 2
17-
theta_dot = (phiR - phiL) / self.wheelbase
18-
logging.debug(f"Chassis movement: x_dot={x_dot}, theta_dot={theta_dot}")
19-
return x_dot, theta_dot
20-
except Exception as e:
21-
logging.error(f"An error occurred while computing chassis movement: {e}")
22-
raise
19+
x_dot = (phi_l + phi_r) / 2
20+
theta_dot = (phi_r - phi_l) / self.wheelbase
21+
logger.debug(f"Computed chassis speeds: x_dot={x_dot:.2f}m/s, theta_dot={theta_dot:.2f}rad/s")
22+
return x_dot, theta_dot
23+
24+
def compute_wheel_speeds(self, x_dot, theta_dot):
25+
"""
26+
Convert chassis commands to wheel speeds
27+
x_dot: desired forward speed (m/s)
28+
theta_dot: desired angular speed (rad/s)
29+
Returns: [left_speed, right_speed] in rad/s
30+
"""
31+
phi_l = x_dot - (theta_dot * self.wheelbase) / 2
32+
phi_r = x_dot + (theta_dot * self.wheelbase) / 2
33+
logger.debug(f"Computed wheel speeds: left={phi_l:.2f}rad/s, right={phi_r:.2f}rad/s")
34+
return [phi_l, phi_r]
35+
36+
def compute_motor_commands(self, x_dot, theta_dot):
37+
"""
38+
Directly compute motor duty cycles (-1 to 1)
39+
Returns: [left_duty, right_duty, left_duty, right_duty]
40+
"""
41+
phi_l, phi_r = self.compute_wheel_speeds(x_dot, theta_dot)
42+
# Scale to motor duty cycles (assuming MAX_SPEED from constants)
43+
from utils.constants import MAX_SPEED
44+
left_duty = phi_l / MAX_SPEED
45+
right_duty = phi_r / MAX_SPEED
46+
return [left_duty, right_duty, left_duty, right_duty]

L3/L3_drive_mt.py

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,48 @@
1-
import threading
21
from L1.L1_motor import MotorController
32
from L2.L2_kinematics import Kinematics
3+
from utils.constants import WHEELBASE
44
import logging
5+
import time
56

6-
# Configure logging for debugging
7-
logging.basicConfig(level=logging.DEBUG)
7+
logger = logging.getLogger(__name__)
88

99
class DriveController:
1010
def __init__(self):
11-
self.motor_controller = MotorController([17, 18, 22, 23])
12-
self.kinematics = Kinematics(0.405) # Wheelbase in meters
11+
self.motor = MotorController()
12+
self.kinematics = Kinematics(WHEELBASE)
13+
self._running = False
1314

14-
def drive(self, x_dot, theta_dot):
15-
"""
16-
Drive the robot based on desired x_dot and theta_dot.
17-
"""
15+
# safety variables
16+
self._last_update = 0
17+
self._command_timeout = 0.5 # seconds
18+
19+
logger.info("Drive controller initialized")
20+
21+
def driving_thread(self):
22+
"""Main control loop with safety checks"""
23+
self._running = True
1824
try:
19-
phiL = x_dot - theta_dot * self.kinematics.wheelbase / 2
20-
phiR = x_dot + theta_dot * self.kinematics.wheelbase / 2
21-
self.motor_controller.set_speed([phiL, phiR, phiL, phiR])
22-
logging.debug(f"Driving with x_dot={x_dot}, theta_dot={theta_dot}")
25+
while self._running:
26+
# Auto-stop if no recent commands
27+
if time.time() - self._last_update > self._command_timeout:
28+
self.motor.stop()
29+
time.sleep(0.1)
30+
continue
31+
32+
# Get commands from L2 systems
33+
x_dot, theta_dot = self._get_commands() # Implement your logic
34+
35+
# Convert to wheel speeds
36+
speeds = self.kinematics.compute_wheel_speeds(x_dot, theta_dot)
37+
38+
# Drive motors
39+
self.motor.set_speed(speeds)
40+
2341
except Exception as e:
24-
logging.error(f"An error occurred while driving: {e}")
42+
logger.error(f"Control error: {e}", exc_info=True)
2543
raise
26-
27-
# Multithreading example
28-
drive_controller = DriveController()
29-
30-
def driving_thread():
31-
while True:
32-
# Get x_dot and theta_dot from gamepad or autonomous logic
33-
x_dot, theta_dot = 0.5, 0.1 # Example values
34-
drive_controller.drive(x_dot, theta_dot)
35-
36-
thread = threading.Thread(target=driving_thread)
37-
thread.start()
44+
finally:
45+
self.motor.stop()
46+
47+
def stop(self):
48+
self._running = False

utils/constants.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
# Constants for the SCUTTLE robot
2-
WHEELBASE = 0.405 # Wheelbase in meters
3-
MAX_SPEED = 1.0 # Maximum speed in m/s
2+
WHEELBASE = 0.405 # Distance between wheels in meters
3+
MAX_SPEED = 0.5 # Maximum speed in m/s
4+
5+
# Motor Configuration
6+
MOTOR_PINS = [17, 18, 22, 23] # GPIO pins for motors 1-4
7+
PWM_FREQUENCY = 1000 # PWM frequency in Hz

utils/logger.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import csv
22
from datetime import datetime
3-
3+
import logging
44
class Logger:
55
def __init__(self, filename="log.csv"):
66
self.filename = filename
@@ -10,7 +10,9 @@ def log_data(self, data):
1010
writer = csv.writer(file)
1111
writer.writerow([datetime.now()] + data)
1212

13-
import logging
1413

1514
def setup_logger():
16-
logging.basicConfig(level=logging.DEBUG)
15+
logging.basicConfig(
16+
level=logging.INFO,
17+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
18+
)

0 commit comments

Comments
 (0)