Servo Design ************ :mod:`openqlab` helps with designing a standard servo circuit. Here's an example: >>> %pylab notebook >>> from openqlab.analysis import servo_design >>> S = servo_design.ServoDesign() >>> S.integrator(1e3).notch(22e3, 100).lowpass(10e3, Q=1.0).gain(10) zeros poles gain ------------------ ------------------------- ---------------------------------- ------- Gain [] [] 3.16228 Int 1kHz [-1000.] [-1.] 1 Notch 22kHz, Q=100 [ 0.+22000.j -0.-22000.j] [-110.+21999.725j -110.-21999.725j] 1 LP2 10kHz, Q=1 [] [-5000.+8660.254j -5000.-8660.254j] 1e+08 As you can see, the servo keeps track of the individual filters that are added, labelling them with a shorthand notation. It also displays poles, zeros and gain for the individual filters, but you can just ignore that if you don't know what that means. A list of available filters can be found on the >>> %pylab notebook >>> from openqlab.analysis import servo_design >>> S = servo_design.ServoDesign() >>> S.integrator(1e3).notch(22e3, 100).lowpass(10e3, Q=1.0).gain(10) zeros poles gain ------------------ ------------------------- ---------------------------------- ------- Gain [] [] 3.16228 Int 1kHz [-1000.] [-1.] 1 Notch 22kHz, Q=100 [ 0.+22000.j -0.-22000.j] [-110.+21999.725j -110.-21999.725j] 1 LP2 10kHz, Q=1 [] [-5000.+8660.254j -5000.-8660.254j] 1e+08 As you can see, the servo keeps track of the individual filters that are added, labelling them with a shorthand notation. It also displays poles, zeros and gain for the individual filters, but you can just ignore that if you don't know what that means. A list of available filters can be found on the >>> %pylab notebook >>> from openqlab.analysis import servo_design >>> S = servo_design.ServoDesign() >>> S.integrator(1e3).notch(22e3, 100).lowpass(10e3, Q=1.0).gain(10) zeros poles gain ------------------ ------------------------- ---------------------------------- ------- Gain [] [] 3.16228 Int 1kHz [-1000.] [-1.] 1 Notch 22kHz, Q=100 [ 0.+22000.j -0.-22000.j] [-110.+21999.725j -110.-21999.725j] 1 LP2 10kHz, Q=1 [] [-5000.+8660.254j -5000.-8660.254j] 1e+08 As you can see, the servo keeps track of the individual filters that are added, labelling them with a shorthand notation. It also displays poles, zeros and gain for the individual filters, but you can just ignore that if you don't know what that means. A list of available filters can be found on the :class:`openqlab.analysis.servo_design.ServoDesign` page. To get a graph of how this servo's response looks like in the frequency domain, simply say: >>> S.plot() which will result in an image similar to this one: .. image:: _static/servo.png :width: 400 The servo can be applied to the measured transfer function of the system that is to be controlled (the *plant*): >>> plant = io.read(['Amplitude.txt', 'Phase.txt']) >>> S = servo_design.ServoDesign() >>> S.plant = plant >>> S.integrator(100).notch(15.3e3, 5).integrator(4e3).lowpass(5e3, Q=0.5).notch(8.05e3, 10).gain(35) zeros poles gain ------------------- ------------------------- ------------------------------------- -------- Gain [] [] 56.2341 Int 100Hz [-100] [-0.1] 1 Notch 15.3kHz, Q=5 [ 0.+15300.j -0.-15300.j] [-1530.+15223.308j -1530.-15223.308j] 1 Int 4kHz [-4000.] [-4.] 1 LP2 5kHz, Q=0.5 [] [-5000. -5000.] 2.5e+07 Notch 8.05kHz, Q=10 [ 0.+8050.j -0.-8050.j] [-402.5+8039.931j -402.5-8039.931j] 1 >>> S.plot() which will show you the transfer function of the servo by its own (blue), and the combined open-loop gain of servo and plant (orange): .. image:: _static/servo_and_tf.png :width: 400 The grey dashed lines indicate unity gain (0dB) and a phase lag of 135deg, respectively, and can be used to hand-optimize phase and gain margin of the combined system.