Source code for cpsim.models.linear.motor_speed

# Ref: https://ctms.engin.umich.edu/CTMS/index.php?example=MotorSpeed&section=ControlPID

import numpy as np

from cpsim import Simulator
from cpsim.controllers.PID import PID

# system dynamics
J = 0.01   # moment of inertia of the rotor
b = 0.1    # motor viscous friction constant
Ke = 0.01  # electromotive force constant
Kt = 0.01  # motor torque constant
R = 1      # electric resistance
L = 0.5    # electric inductance

A = [[-b / J, Kt / J], [-Ke / L, -R / L]]
B = [[0], [1 / L]]
C = [[1, 0]]

x_0 = np.array([0.0, 0.0])

# utils parameters
P = 19
I = 37
D = 0.1

control_limit = {
    'lo': np.array([0]),
    'up': np.array([60])
}


[docs] class Controller: def __init__(self, dt): self.dt = dt self.pid = PID(P, I, D, current_time=-dt) self.pid.setWindup(100) self.pid.setSampleTime(dt) self.set_control_limit(control_limit['lo'], control_limit['up'])
[docs] def update(self, ref: np.ndarray, feedback_value: np.ndarray, current_time) -> np.ndarray: self.pid.set_reference(ref[0]) cin = self.pid.update(feedback_value[0], current_time) return np.array([cin])
[docs] def set_control_limit(self, control_lo, control_up): self.control_lo = control_lo self.control_up = control_up self.pid.set_control_limit(self.control_lo[0], self.control_up[0])
[docs] def clear(self): self.pid.clear(current_time=-self.dt)
[docs] class MotorSpeed(Simulator): """ States: (2,) x[0]: the rotational speed of the shaft x[1]: electric current Control Input: (1,) u[0]: voltage source Output: (1,) y[0]: the rotational speed of the shaft Output Feedback Controller: PID """ def __init__(self, name, dt, max_index, noise=None): super().__init__('Motor Speed ' + name, dt, max_index) self.linear(A, B, C) controller = Controller(dt) settings = { 'init_state': x_0, 'feedback_type': 'output', 'controller': controller } if noise: settings['noise'] = noise self.sim_init(settings)
if __name__ == "__main__": max_index = 500 dt = 0.02 ref = [np.array([5])] * 201 + [np.array([4])] * 200 + [np.array([5])] * 100 noise = { 'process': { 'type': 'white', 'param': {'C': np.eye(2) * 0.1} } } motor_speed = MotorSpeed('test', dt, max_index, noise) for i in range(0, max_index + 1): assert motor_speed.cur_index == i motor_speed.update_current_ref(ref[i]) # attack here motor_speed.evolve() # print results import matplotlib.pyplot as plt t_arr = np.linspace(0, 10, max_index + 1) ref = [x[0] for x in motor_speed.refs[:max_index + 1]] y_arr = [x[0] for x in motor_speed.outputs[:max_index + 1]] plt.plot(t_arr, y_arr, t_arr, ref) plt.show() u_arr = [x[0] for x in motor_speed.inputs[:max_index + 1]] plt.plot(t_arr, u_arr) plt.show()