mirror of
https://github.com/WallabyLester/RBF-aPID-Controller.git
synced 2026-05-21 03:37:00 +08:00
Cleaning up.
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import tensorflow as tf
|
||||
|
||||
class RBFLayer(tf.keras.layers.Layer):
|
||||
""" RBF Layer using TF Subclassing API.
|
||||
|
||||
...
|
||||
|
||||
Attributes
|
||||
----------
|
||||
n_centers : int
|
||||
The number of RBF centers.
|
||||
input_dim : int
|
||||
The dimensions of the RBF centers.
|
||||
|
||||
Methods
|
||||
-------
|
||||
call(inputs):
|
||||
TF call method to implement forward pass.
|
||||
"""
|
||||
def __init__(self, n_centers, input_dim):
|
||||
""" Constructs RBF centers and standard deviations as trainable weights.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_centers : int
|
||||
The number of RBF centers.
|
||||
input_dim : int
|
||||
The dimensions of the RBF centers.
|
||||
"""
|
||||
super().__init__()
|
||||
self.n_centers = n_centers
|
||||
self.centers = self.add_weight(shape=(n_centers, input_dim),
|
||||
initializer="random_normal",
|
||||
trainable=True,)
|
||||
self.sigmas = self.add_weight(shape=(n_centers,),
|
||||
initializer="ones",
|
||||
trainable=True,)
|
||||
|
||||
def call(self, inputs):
|
||||
""" Find likelihood of inputs under Gaussian distribution given center and
|
||||
standard deviation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
inputs : tensor
|
||||
The points in space to evaluate the Gaussian.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Height of Gaussian curve at inputs.
|
||||
"""
|
||||
distances = tf.norm(tf.expand_dims(inputs, axis=1) - self.centers, axis=2)
|
||||
rbf_output = tf.exp(-tf.square(distances) / (2 * tf.square(self.sigmas)))
|
||||
return rbf_output
|
||||
|
||||
|
||||
class RBFAdaptiveModel(tf.keras.Model):
|
||||
""" RBF Adaptive Model using TF Subclassing API.
|
||||
|
||||
Outputs one control signal adaptation. Determined by output layer
|
||||
number of neurons.
|
||||
|
||||
...
|
||||
|
||||
Attributes
|
||||
----------
|
||||
n_centers : int
|
||||
The number of RBF centers.
|
||||
imput_dim : int
|
||||
The dimensions of the RBF centers.
|
||||
|
||||
Methods
|
||||
-------
|
||||
call(inputs):
|
||||
TF call method to implement forward pass of model.
|
||||
"""
|
||||
def __init__(self, n_centers, input_dim=3):
|
||||
""" Constructs RBF and output layers.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_centers : int
|
||||
The number of RBF centers.
|
||||
input_dim : int
|
||||
The dimensions of the RBF centers. Default of 3 for Kp, Ki, Kd
|
||||
"""
|
||||
super().__init__()
|
||||
self.rbf_layer = RBFLayer(n_centers, input_dim)
|
||||
self.output_layer = tf.keras.layers.Dense(1)
|
||||
|
||||
def call(self, inputs):
|
||||
""" Implement forward pass.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
inputs : tensor
|
||||
The points in space to adapt with.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Adapted control signal.
|
||||
"""
|
||||
rbf_output = self.rbf_layer(inputs)
|
||||
control_signal = self.output_layer(rbf_output)
|
||||
return control_signal
|
||||
|
||||
def train_rbf_adaptive(model, errors, control_signals, epochs=100):
|
||||
""" Training method for the RBF adaptive model.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
model : RBFAdaptiveModel
|
||||
A RBF Adaptive Model instance.
|
||||
errors : ndarray
|
||||
Multi-sample training data, [error, derivative, integral].
|
||||
control_signals : ndarray
|
||||
Control signal target values.
|
||||
epochs : int
|
||||
Number of epochs to train for.
|
||||
"""
|
||||
model.compile(optimizer="adam", loss="mean_squared_error")
|
||||
model.fit(errors, control_signals, epochs=epochs, verbose=1)
|
||||
@@ -0,0 +1,75 @@
|
||||
import tensorflow as tf
|
||||
|
||||
class AdaptivePIDTf:
|
||||
""" PID class implemented for TensorFlow integration.
|
||||
|
||||
...
|
||||
|
||||
Attributes
|
||||
----------
|
||||
Kp : float
|
||||
Proportional gain.
|
||||
Ki : float
|
||||
Integral gain.
|
||||
Kd : float
|
||||
Derivative gain.
|
||||
rbf_model : RBFAdaptiveModel object
|
||||
RBF adaptive model class instance.
|
||||
|
||||
Methods
|
||||
-------
|
||||
update(target, measured_value, dt):
|
||||
Updates the control signal.
|
||||
"""
|
||||
def __init__(self, Kp, Ki, Kd, rbf_model):
|
||||
""" Constructs PID gains, RBF model, and initial PID components.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
Kp : float
|
||||
Proportional gain.
|
||||
Ki : float
|
||||
Integral gain.
|
||||
Kd : float
|
||||
Derivative gain.
|
||||
rbf_model : RBFAdaptiveModel object
|
||||
RBF adaptive model class instance.
|
||||
"""
|
||||
self.Kp = Kp
|
||||
self.Ki = Ki
|
||||
self.Kd = Kd
|
||||
self.rbf_model = rbf_model
|
||||
self.prev_err = 0
|
||||
self.error = 0
|
||||
self.integral = 0
|
||||
self.derivative = 0
|
||||
|
||||
def update(self, target, measured_value, dt):
|
||||
""" Update the control signal according to error and adapt with RBF
|
||||
model predictions.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
target : float
|
||||
Target setpoint.
|
||||
measured_value : float
|
||||
Actual value.
|
||||
dt : float
|
||||
Timestep.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Control signal.
|
||||
"""
|
||||
self.error = target - measured_value
|
||||
self.integral += self.error * dt
|
||||
self.derivative = (self.error - self.prev_err) / dt
|
||||
|
||||
u = (self.Kp * self.error) + (self.Ki * self.integral) + (self.Kd*self.derivative)
|
||||
|
||||
control_signal_adapt = self.rbf_model(tf.constant([[self.error, self.integral, self.derivative]])).numpy().flatten()[0]
|
||||
u += control_signal_adapt
|
||||
|
||||
self.prev_err = self.error
|
||||
return u
|
||||
|
||||
Reference in New Issue
Block a user