Beispiel #1
0
class MotorController():
	
	def __init__(self):
		rospy.init_node('motor_controller',log_level=rospy.INFO)

		# ------ PARAMETRI ------
		# frequenza del loop 
		self.freq = rospy.get_param('/eod/loop_freq/motor_ctrl')
		self.rate = rospy.Rate(self.freq)

		# parametri pid dx
		self.kp_dx = rospy.get_param('/eod/pid_dx/Kp') 
		self.ki_dx = rospy.get_param('/eod/pid_dx/Ki') 
		self.kd_dx = rospy.get_param('/eod/pid_dx/Kd')
		self.vMin_dx = rospy.get_param('/eod/pid_dx/v_min') 
		self.vMax_dx = rospy.get_param('/eod/pid_dx/v_max') 

		# parametri pid sx
		self.kp_sx = rospy.get_param('/eod/pid_sx/Kp') 
		self.ki_sx = rospy.get_param('/eod/pid_sx/Ki') 
		self.kd_sx = rospy.get_param('/eod/pid_sx/Kd')
		self.vMin_sx = rospy.get_param('/eod/pid_sx/v_min') 
		self.vMax_sx = rospy.get_param('/eod/pid_sx/v_max') 

		# ------ VARIABILI ------
		self.old_time = rospy.Time.now()
		self.pid_dx = PID(self.kp_dx, self.ki_dx, self.kd_dx, self.vMin_dx, self.vMax_dx)
		self.pid_sx = PID(self.kp_sx, self.ki_sx, self.kd_sx, self.vMin_sx, self.vMax_sx)
		self.v_dx = 0.0
		self.v_sx = 0.0
		self.ref_dx = 0.0
		self.ref_sx = 0.0

		# ------ TOPIC ------
		rospy.Subscriber('v_target', Wheels_Vel, self.v_target_callback)
		rospy.Subscriber('wheels_velocity', Wheels_Vel, self.wheels_velocity_callback)
		
		# il messaggio Wheels_Vel contiene due valori di tensione
		self.cmd_pub = rospy.Publisher('motor_cmd', Wheels_Vel, queue_size=10)

	def loop(self):

		while not rospy.is_shutdown():

			# calcolo dt e aggiornamento 
			dt = self.calculate_dt()

			# calcolo della legge di controlo
			v_input_dx = self.pid_dx.calculate(self.v_dx, self.ref_dx, dt)
			v_input_sx = self.pid_sx.calculate(self.v_sx, self.ref_sx, dt)

			# controllo tra segno della tensione e direzione di marcia
			v_input_dx = self.saturation(v_input_dx, numpy.sign(self.ref_dx))
			v_input_sx = self.saturation(v_input_sx, numpy.sign(self.ref_sx))

			# normalizzazione input tra [0,1]
			v_input_dx = v_input_dx/self.vMax_dx
			v_input_sx = v_input_sx/self.vMax_sx

			# pubblicazione dei segnali di controllo
			self.publish_motor_cmd(v_input_dx, v_input_sx)

			self.rate.sleep()
			
	def calculate_dt(self):

		current_time = rospy.Time.now()
		dt = (current_time - self.old_time).to_sec()
		self.old_time = current_time
		return dt

	def saturation(self, v_input, sign):
		# se l'input da fornire al motore e' opposto alla direzione di marcia
		# si preferisce fornire una tensione nulla
		if ((sign > 0) and (v_input < 0)) or ((sign < 0) and (v_input > 0)):
			return 0.0
		else:
			return v_input
        
	def publish_motor_cmd(self, v_input_dx, v_input_sx):
		# anche se il messaggio e' di tipo Wheels_Vel stiamo
		# pubblicando il valore di due tensioni
		msg_cmd = Wheels_Vel()
		msg_cmd.right = v_input_dx
		msg_cmd.left = v_input_sx
		self.cmd_pub.publish(msg_cmd)

	def v_target_callback(self, msg):
		self.ref_dx = msg.right
		self.ref_sx = msg.left

	def wheels_velocity_callback(self, msg):
		self.v_dx = msg.right
		self.v_sx = msg.left
Beispiel #2
0
def main():
    #Variables for PID

    kp = 1
    kd = 0.5
    ki = 0

    min = 0
    max = 255

    #Variables for cv2
    center = 320
    source = 2

    red = (0, 0, 255)
    green = (0, 255, 0)
    thinkness = 3
    center_x = (center, 480)
    center_end = (center, 0)
    '''
	base = Base()
	if base.find_arduino() is False:
		print("Cannot connect to arduino")
		return 
	'''

    cam = cv2.VideoCapture(source)
    if cam is None or not cam.isOpened():
        print("Warning: unable to open video source:")
        return

    pid = PID(kp, kd, ki, min, max)

    while True:
        ret, frame = cam.read()
        if not ret:
            break

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        index = get_signature(gray)

        frame = cv2.line(frame, center_x, center_end, green, thinkness)

        if index == None:
            print("Black line is not detected")
            #base.set_motor(ac.MOTOR_L, ac.FORWARD, ac.MINPOWER)
            #base.set_motor(ac.MOTOR_R, ac.FORWARD, ac.MINPOWER)

        else:
            start_point = (index, frame.shape[0])
            end_point = (index, 0)
            frame = cv2.line(frame, start_point, end_point, red, thinkness)
            err = center - index
            if err > 0:
                result = pid.calculate(err)
                print("Left: ", result)
                #base.set_motor(ac.MOTOR_L, ac.FORWARD, ac.MAXPOWER - result)
                #base.set_motor(ac.MOTOR_R, ac.FORWARD, ac.MAXPOWER)
            else:
                result = pid.calculate(-err)
                print("Right:", result)
                #base.set_motor(ac.MOTOR_L, ac.FORWARD, ac.MAXPOWER)
                #base.set_motor(ac.MOTOR_R, ac.FORWARD, ac.MAXPOWER - result)
        cv2.imshow("Video", frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cv2.destroyAllWindows()
Beispiel #3
0
class controller(threading.Thread):
    # Instantiate the motor controller
    def __init__(self, pwm_name, dir_a, dir_b, eqep):
        # Initialize the thread base
        super(controller, self).__init__()
        
        # Create stop event object
        self.stop_event = threading.Event()
        self.stop_confirm = threading.Event()
        
        # Store parameters
        self.pwm = pwm_name
        self.dir_a = dir_a
        self.dir_b = dir_b
        
        # Create a PID controller
        self.pid = PID(0.01, 0.01, 0.0, -100.0, 100.0, 0.0)
        
        # Load the eQEP interface
        self.eqep = eQEP(eqep, eQEP.MODE_RELATIVE)
        self.eqep.set_period(10000000)
        
        # Setup the GPIO
        gpio.setup(self.dir_a, gpio.OUT)
        gpio.setup(self.dir_b, gpio.OUT)
        gpio.output(self.dir_a, gpio.LOW)
        gpio.output(self.dir_b, gpio.LOW)
        
        # Setup the PWM
        pwm.start(self.pwm, 100.0)
    
    # Process of the running thing
    def run(self):
        while (self.stop_event.is_set() == False):
            current = float(self.eqep.poll_position())
            output = self.pid.calculate(current)
            
            # Calculate the output duty cycle 
            duty = 100.0 - abs(output)
                
            # Setup the IO lines correctly
            if(output > 0.0):
                gpio.output(self.dir_a, gpio.HIGH)
                gpio.output(self.dir_b, gpio.LOW)
            else:
                gpio.output(self.dir_a, gpio.LOW)
                gpio.output(self.dir_b, gpio.HIGH)
                
            # Set the pwm
            pwm.set_duty_cycle(self.pwm, duty)
            
            # Log
            #print "Current = " + str(current) + "; Output = " + str(output)
        # Confirm stop
        self.stop_confirm.set()
            
    # Stop the motor
    def stop(self):
        self.stop_event.set()
        self.stop_confirm.wait()
        self.stop_event.clear()
        self.stop_confirm.clear()
        gpio.output(self.dir_a, gpio.LOW)
        gpio.output(self.dir_b, gpio.LOW)
        pwm.set_duty_cycle(self.pwm, 100.0)
Beispiel #4
0
encoder = Encoder(21, 20) #port nums for encoder
pid = PID(0.001, 0, 0, 2000) # p , i , d , setpoint
pid.setMinMax(-0.6, 0.6)
IO.setwarnings(False)

IO.setmode(IO.BCM)

IO.setup(19,IO.OUT)
p = IO.PWM(19,50)
p.start(0)

def setPWM(pwm):
	return (pwm - 7)/3 #7 is mid value, 3 is range / 2
def setSpeed(speed):
	return (speed * 3.0) + 7.0
encoder.start()
while True:
	#print(setSpeed(pid.calculate(encoder.position())))
	print(pid.error(encoder.position()))
	p.ChangeDutyCycle(setSpeed(pid.calculate(encoder.position())))
	if (abs(pid.error(encoder.position())) < 30):
		encoder.stop()
		encoder.join()
		break
#	print("working")
#	for x in range(0, 40):
#		p.ChangeDutyCycle(7 - (x/10.0))
#		print(7 - (x/10.0))
#		time.sleep(0.05)
	
        while self.controlEnabled:
            if self.stopped():
                self.motor.ChangeDutyCycle(0)
                return
            self.motor.ChangeDutyCycle(self.pwmSpeed)

    def stop(self):
        self._stop.set()

    def stopped(self):
        return self._stop.isSet()

    def enableController(self, enable):
        self.controlEnabled = enable

    def setSpeed(self, speed):
        self.speed = speed
        self.pwmSpeed = (self.speed * 3.0) + 7.0


p = PWMMotorControl(19)
p.start()
encoder.start()
while True:
    print(pid.error(encoder.position()))
    p.setSpeed(pid.calculate(encoder.position()))
    if (abs(pid.error(encoder.position())) < 10):
        p.stop()
        encoder.stop()
        break