pendiente por verificar codigo no hay camara ni ruedas aun
This commit is contained in:
parent
040d3f5cf9
commit
fe74bd3822
3
v1.0.0/requirements.txt
Normal file
3
v1.0.0/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
numpy==2.2.0
|
||||||
|
opencv-python==4.10.0.84
|
||||||
|
RPi.GPIO==0.7.1
|
139
v1.0.0/v1.0.0.py
Normal file
139
v1.0.0/v1.0.0.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Configuración de pines GPIO para los motores
|
||||||
|
class MotorController:
|
||||||
|
def __init__(self):
|
||||||
|
# Configurar modo de numeración GPIO
|
||||||
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
|
||||||
|
# Definir pines para los motores
|
||||||
|
self.motor_izq_adelante = 17
|
||||||
|
self.motor_izq_atras = 18
|
||||||
|
self.motor_der_adelante = 22
|
||||||
|
self.motor_der_atras = 23
|
||||||
|
|
||||||
|
# Configurar pines como salida
|
||||||
|
GPIO.setup(self.motor_izq_adelante, GPIO.OUT)
|
||||||
|
GPIO.setup(self.motor_izq_atras, GPIO.OUT)
|
||||||
|
GPIO.setup(self.motor_der_adelante, GPIO.OUT)
|
||||||
|
GPIO.setup(self.motor_der_atras, GPIO.OUT)
|
||||||
|
|
||||||
|
# Inicializar PWM para control de velocidad
|
||||||
|
self.pwm_izq = GPIO.PWM(self.motor_izq_adelante, 100)
|
||||||
|
self.pwm_der = GPIO.PWM(self.motor_der_adelante, 100)
|
||||||
|
self.pwm_izq.start(0)
|
||||||
|
self.pwm_der.start(0)
|
||||||
|
|
||||||
|
def mover(self, velocidad_izq, velocidad_der):
|
||||||
|
"""
|
||||||
|
Control de movimiento de los motores
|
||||||
|
velocidad: -100 a 100 (negativo para reversa)
|
||||||
|
"""
|
||||||
|
# Motor izquierdo
|
||||||
|
if velocidad_izq >= 0:
|
||||||
|
self.pwm_izq.ChangeDutyCycle(velocidad_izq)
|
||||||
|
GPIO.output(self.motor_izq_atras, GPIO.LOW)
|
||||||
|
else:
|
||||||
|
self.pwm_izq.ChangeDutyCycle(-velocidad_izq)
|
||||||
|
GPIO.output(self.motor_izq_atras, GPIO.HIGH)
|
||||||
|
|
||||||
|
# Motor derecho
|
||||||
|
if velocidad_der >= 0:
|
||||||
|
self.pwm_der.ChangeDutyCycle(velocidad_der)
|
||||||
|
GPIO.output(self.motor_der_atras, GPIO.LOW)
|
||||||
|
else:
|
||||||
|
self.pwm_der.ChangeDutyCycle(-velocidad_der)
|
||||||
|
GPIO.output(self.motor_der_atras, GPIO.HIGH)
|
||||||
|
|
||||||
|
def detener(self):
|
||||||
|
"""Detiene ambos motores"""
|
||||||
|
self.pwm_izq.ChangeDutyCycle(0)
|
||||||
|
self.pwm_der.ChangeDutyCycle(0)
|
||||||
|
GPIO.output(self.motor_izq_atras, GPIO.LOW)
|
||||||
|
GPIO.output(self.motor_der_atras, GPIO.LOW)
|
||||||
|
|
||||||
|
def procesar_frame(frame):
|
||||||
|
"""
|
||||||
|
Procesa el frame y detecta la línea negra
|
||||||
|
Retorna: frame procesado y posición de la línea
|
||||||
|
"""
|
||||||
|
# Convertir a escala de grises
|
||||||
|
gris = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||||
|
|
||||||
|
# Aplicar desenfoque para reducir ruido
|
||||||
|
desenfoque = cv2.GaussianBlur(gris, (5, 5), 0)
|
||||||
|
|
||||||
|
# Binarización para detectar la línea negra
|
||||||
|
_, binario = cv2.threshold(desenfoque, 60, 255, cv2.THRESH_BINARY_INV)
|
||||||
|
|
||||||
|
# Región de interés (parte inferior de la imagen)
|
||||||
|
altura = frame.shape[0]
|
||||||
|
roi = binario[int(altura*0.6):altura, :]
|
||||||
|
|
||||||
|
# Encontrar el centro de la línea
|
||||||
|
momentos = cv2.moments(roi)
|
||||||
|
if momentos["m00"] > 0:
|
||||||
|
cx = int(momentos["m10"] / momentos["m00"])
|
||||||
|
return binario, cx
|
||||||
|
else:
|
||||||
|
return binario, None
|
||||||
|
|
||||||
|
def seguidor_linea():
|
||||||
|
# Inicializar cámara
|
||||||
|
camara = cv2.VideoCapture(0)
|
||||||
|
camara.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
|
||||||
|
camara.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
|
||||||
|
|
||||||
|
# Inicializar controlador de motores
|
||||||
|
motores = MotorController()
|
||||||
|
|
||||||
|
# Parámetros de control
|
||||||
|
velocidad_base = 50 # Velocidad base de los motores
|
||||||
|
kp = 0.5 # Constante proporcional para el control
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
ret, frame = camara.read()
|
||||||
|
if not ret:
|
||||||
|
print("Error al capturar frame")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Procesar frame y obtener posición de la línea
|
||||||
|
frame_procesado, centro_linea = procesar_frame(frame)
|
||||||
|
|
||||||
|
if centro_linea is not None:
|
||||||
|
# Calcular error (distancia desde el centro)
|
||||||
|
error = frame.shape[1]/2 - centro_linea
|
||||||
|
|
||||||
|
# Calcular ajuste de velocidad usando control proporcional
|
||||||
|
ajuste = kp * error
|
||||||
|
|
||||||
|
# Aplicar velocidades a los motores
|
||||||
|
velocidad_izq = max(min(velocidad_base + ajuste, 100), -100)
|
||||||
|
velocidad_der = max(min(velocidad_base - ajuste, 100), -100)
|
||||||
|
|
||||||
|
motores.mover(velocidad_izq, velocidad_der)
|
||||||
|
else:
|
||||||
|
# Si no se detecta la línea, detener motores
|
||||||
|
motores.detener()
|
||||||
|
|
||||||
|
# Mostrar frames para debugging
|
||||||
|
cv2.imshow('Video Original', frame)
|
||||||
|
cv2.imshow('Línea Detectada', frame_procesado)
|
||||||
|
|
||||||
|
# Salir con 'q'
|
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||||
|
break
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Limpieza
|
||||||
|
motores.detener()
|
||||||
|
camara.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
GPIO.cleanup()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
seguidor_linea()
|
Loading…
Reference in New Issue
Block a user