controllers.py
Go to the documentation of this file.
00001 import numpy as np, math
00002 
00003 import roslib; roslib.load_manifest('hrl_generic_arms')
00004 import rospy
00005 from std_msgs.msg import Float64, Float64MultiArray
00006 
00007 ##
00008 # Classic PID controller with maximum integral thresholding to
00009 # prevent windup.
00010 class PIDController(object):
00011     def __init__(self, rate=100., k_p=0., k_i=0., k_d=0., i_max=None, feed_forward=0.,
00012                  init_integ=0., saturation=None, name=None):
00013         self.y = 0.
00014         self.k_p = k_p
00015         self.k_i = k_i
00016         self.k_d = k_d
00017         self.i_max = i_max
00018         self.feed_forward = feed_forward
00019         self.rate = rate
00020         self.saturation = saturation
00021         self.err_last = None
00022         self.integral = init_integ
00023         self.name = name
00024         if self.name is not None:
00025             self.err_pub = rospy.Publisher("/pid_controller/" + name + "_error", Float64)
00026             self.out_pub = rospy.Publisher("/pid_controller/" + name + "_output", Float64)
00027             self.diag_pub = rospy.Publisher("/pid_controller/" + name + "_diag", Float64MultiArray)
00028 
00029     ##
00030     # Updates the controller state and returns the current output.
00031     def update_state(self, err):
00032         last_integral = self.integral
00033         self.integral += err / self.rate
00034         if self.i_max is not None:
00035             self.integral = np.clip(self.integral, -self.i_max, self.i_max)
00036         if self.err_last is None:
00037             self.err_last = err
00038         propr = self.k_p * err
00039         integ = self.k_i * self.integral
00040         deriv = self.k_d * (err - self.err_last) * self.rate
00041         feedf = self.feed_forward
00042         raw_y = propr + integ + deriv + feedf
00043         self.err_last = err
00044         if self.saturation is not None:
00045             self.y = np.clip(raw_y, -self.saturation, self.saturation)
00046             if self.y in [-self.saturation, self.saturation]:
00047                 self.integral = last_integral
00048         if self.name is not None:
00049             self.err_pub.publish(err)
00050             self.out_pub.publish(self.y)
00051             diag_msg = Float64MultiArray()
00052             diag_msg.data = [self.y, propr, integ, deriv, feedf, raw_y, self.saturation]
00053             self.diag_pub.publish(diag_msg)
00054         return self.y
00055 
00056     def reset_controller(self):
00057         self.err_last = None
00058         self.integral = 0


hrl_generic_arms
Author(s): Kelsey Hawkins
autogenerated on Wed Nov 27 2013 11:53:37