diff options
author | Sunil Shetye | 2025-03-17 15:51:20 +0530 |
---|---|---|
committer | Sunil Shetye | 2025-03-17 15:51:20 +0530 |
commit | 9dae2503fef590a973bd2f949de1bf2b9132ea81 (patch) | |
tree | 0f34256b928e2ad0be8a4898c2b1f8e887d04d53 | |
parent | af35c90573c9e91428b195913565697118150ddf (diff) | |
download | Common-Interface-Project-9dae2503fef590a973bd2f949de1bf2b9132ea81.tar.gz Common-Interface-Project-9dae2503fef590a973bd2f949de1bf2b9132ea81.tar.bz2 Common-Interface-Project-9dae2503fef590a973bd2f949de1bf2b9132ea81.zip |
add script_dump column from xcos_on_cloud
-rw-r--r-- | blocks/saveAPI/fixtures/saveAPI.yaml | 24595 |
1 files changed, 24284 insertions, 311 deletions
diff --git a/blocks/saveAPI/fixtures/saveAPI.yaml b/blocks/saveAPI/fixtures/saveAPI.yaml index 3a0e7e64..cacb8790 100644 --- a/blocks/saveAPI/fixtures/saveAPI.yaml +++ b/blocks/saveAPI/fixtures/saveAPI.yaml @@ -69,13 +69,13 @@ fields: category_name: Power Systems - model: saveAPI.gallery - pk: 622 + pk: 1 fields: save_id: gallery0 name: ch5_1 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 5) Analysis Methods, 5.1) The branch current method' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="ch51.scos"><!--Xcos - 1.0 - scilab-5.5.2 @@ -1054,14 +1054,15 @@ x="300.0" y="190.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-5c1d823d:130d68ab7d2:-7f7c" parent="-5c1d823d:130d68ab7d2:-7f7b"/></XcosDiagram> media: gallery0.png + script_dump: '' - model: saveAPI.gallery - pk: 623 + pk: 2 fields: save_id: gallery1 name: ch5_6 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 5) Analysis Methods, 5.6) Network reduction' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ch5_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -2727,14 +2728,15 @@ scilabClass="ScilabList"><mxPoint x="630.0" y="450.0"/><mxPoint x="630.0" y="410.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="331568f2:130d6f18fe2:-8000" parent="331568f2:130d6f18fe2:-7fff"/></XcosDiagram> media: gallery1.png + script_dump: '' - model: saveAPI.gallery - pk: 624 + pk: 3 fields: save_id: gallery2 name: ch5_7 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 5) Analysis Methods, 5.7) Superposition' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ch5_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -3634,14 +3636,15 @@ x="844.0" y="90.0"/><mxPoint as="targetPoint" x="880.0" y="90.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="331568f2:130d6f18fe2:-7db5" parent="331568f2:130d6f18fe2:-7db4"/></XcosDiagram> media: gallery2.png + script_dump: '' - model: saveAPI.gallery - pk: 625 + pk: 4 fields: save_id: gallery3 name: ch6_11 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 6) Amplifiers and Operational Amplifiers, 6.11) Noninverting circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="ch611"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -4342,14 +4345,15 @@ x="640.0" y="200.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-55de3cf2:130fe0d1e6e:-7e33" parent="-55de3cf2:130fe0d1e6e:-7e32"/></XcosDiagram> media: gallery3.png + script_dump: '' - model: saveAPI.gallery - pk: 626 + pk: 5 fields: save_id: gallery4 name: ch6_15 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 6) Amplifiers and Operational Amplifiers, 6.15) Circuits containing several Op amps' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ch6_15"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -5502,14 +5506,15 @@ x="584.0" y="180.0"/><mxPoint as="targetPoint" x="610.0" y="180.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-1e985524:130d9355380:-8000" parent="-1e985524:130d9355380:-7fff"/></XcosDiagram> media: gallery4.png + script_dump: '' - model: saveAPI.gallery - pk: 627 + pk: 6 fields: save_id: gallery5 name: ch6_9 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 6) Amplifiers and Operational Amplifiers, 6.9) Analysis of circuits containing ideal op amps' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ch6_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -7439,14 +7444,15 @@ scilabClass="ScilabList"><mxPoint x="740.0" y="170.0"/><mxPoint x="740.0" y="130.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="5678f95b:130d8f27016:-8000" parent="5678f95b:130d8f27016:-7fff"/></XcosDiagram> media: gallery5.png + script_dump: '' - model: saveAPI.gallery - pk: 628 + pk: 7 fields: save_id: gallery6 name: ch8_2 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.2) Capacitor Discharge in a Resistor' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.05" title="ch8_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -7976,14 +7982,15 @@ scilabClass="ScilabList"><mxPoint x="120.0" y="110.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-1e985524:130d9355380:-7dc3" parent="-1e985524:130d9355380:-7dc2"/></XcosDiagram> media: gallery6.png + script_dump: '' - model: saveAPI.gallery - pk: 629 + pk: 8 fields: save_id: gallery7 name: ch8_3 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.3) Establishing a DC Voltage across a Capacitor' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.1" title="ch8_3"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -8549,14 +8556,15 @@ x="430.0" y="84.0"/><mxPoint as="targetPoint" x="430.0" y="150.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-1e985524:130d9355380:-7d28" parent="-1e985524:130d9355380:-7d27"/></XcosDiagram> media: gallery7.png + script_dump: '' - model: saveAPI.gallery - pk: 630 + pk: 9 fields: save_id: gallery8 name: ch8_4 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.4) The Source free RL Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.1" title="ch8_4"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -9606,14 +9614,15 @@ x="-8.0" y="6.0"/></ExplicitInputPort></root></mxGraphModel><mxCell as="defaultParent" id="-1e985524:130d9355380:-7b0d" parent="-1e985524:130d9355380:-7b0c"/></XcosDiagram> media: gallery8.png + script_dump: '' - model: saveAPI.gallery - pk: 631 + pk: 10 fields: save_id: gallery9 name: ch8_5 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.5) Complex first order RL and RC Circuits' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="ch8_5"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -10534,14 +10543,15 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="40.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="-5c3e5c92:130db8fddce:-8000" parent="-5c3e5c92:130db8fddce:-7fff"/></XcosDiagram> media: gallery9.png + script_dump: '' - model: saveAPI.gallery - pk: 632 + pk: 11 fields: save_id: gallery10 name: ch8_6 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.6) Complex first order RL and RC Circuits' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ch8_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -12375,14 +12385,15 @@ x="210.0" y="190.0"/><mxPoint x="210.0" y="190.0"/><mxPoint x="160.0" y="190.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="31befcfe:130dc407023:-8000" parent="31befcfe:130dc407023:-7fff"/></XcosDiagram> media: gallery10.png + script_dump: '' - model: saveAPI.gallery - pk: 633 + pk: 12 fields: save_id: gallery11 name: ch8_7 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.7) DC Steady state in Inductors and Capacitors' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="ch8_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -13548,14 +13559,15 @@ as="defaultParent" id="31befcfe:130dc407023:-7d8a" parent="31befcfe:130dc407023:-7d89"/><mxPoint as="origin" x="-6.0" y="-6.0"/></XcosDiagram> media: gallery11.png + script_dump: '' - model: saveAPI.gallery - pk: 634 + pk: 13 fields: save_id: gallery12 name: ch8_8 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.8) DC Steady state in Inductors and Capacitors' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" title="ch8_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 2040--><mxGraphModel @@ -14320,14 +14332,15 @@ as="targetPoint" x="360.0" y="360.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="4cf3be04:130e07e353b:-8000" parent="4cf3be04:130e07e353b:-7fff"/></XcosDiagram> media: gallery12.png + script_dump: '' - model: saveAPI.gallery - pk: 635 + pk: 14 fields: save_id: gallery13 name: ch8_9 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 8) First order Circuits, 8.9) Transitions at Switching Time' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="ch8_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -15602,14 +15615,15 @@ x="400.0" y="370.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery13.png + script_dump: '' - model: saveAPI.gallery - pk: 636 + pk: 15 fields: save_id: gallery14 name: ch9_1 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 9) Higher order circuits and Complex frequency, 9.1) Series RLC Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" cellsLocked="1" finalIntegrationTime="0.05" title="ch9_1"><!--Xcos - 1.0 - scilab-5.5.2 @@ -16106,14 +16120,15 @@ x="400.0" y="290.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="5f267dc3:130e0981282:-8000" parent="5f267dc3:130e0981282:-7fff"/></XcosDiagram> media: gallery14.png + script_dump: '' - model: saveAPI.gallery - pk: 637 + pk: 16 fields: save_id: gallery15 name: ch9_2 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 9) Higher order circuits and Complex frequency, 9.2) Series RLC Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.05" title="ch9_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -16612,14 +16627,15 @@ as="geometry" height="8.0" width="8.0" x="40.0" y="16.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="5f267dc3:130e0981282:-7ebc" parent="5f267dc3:130e0981282:-7ebb"/></XcosDiagram> media: gallery15.png + script_dump: '' - model: saveAPI.gallery - pk: 638 + pk: 17 fields: save_id: gallery16 name: ch9_5 description: 'Electric Circuits (Author: M. Navhi And J. A. Edminister), 9) Higher order circuits and Complex frequency, 9.5) Parallel RLC circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 154 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ch9_5"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -17181,14 +17197,15 @@ x="380.0" y="240.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="5f267dc3:130e0981282:-7d6d" parent="5f267dc3:130e0981282:-7d6c"/></XcosDiagram> media: gallery16.png + script_dump: '' - model: saveAPI.gallery - pk: 639 + pk: 18 fields: save_id: gallery17 name: example3_27 description: 'Basic Electronics (Author: D. De), 3) Diode Circuits, 3.27) Find currents and voltages' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 181 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex3_27"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -17910,14 +17927,53 @@ y="20.0"/><mxPoint x="240.0" y="20.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-3721ad33:1314dc6b131:-8000" parent="-3721ad33:1314dc6b131:-7fff"/></XcosDiagram> media: gallery17.png + script_dump: '// Find currents and voltages + + // Basic Electronics + + // By Debashis De + + // First Edition, 2010 + + // Dorling Kindersley Pvt. Ltd. India + + // Example 3-27 in page 179 + + + // Given data + + //Diode acts as short circuited.Both diodes are forward biased + + V1=0; // Voltage at junction 1 in V + + V2=0; // Voltage at junction 2 in V + + + //Calculation + + I1=(20-V1)/(20*10^3); + + I2=(V2-(-10))/(20*10^3); + + + printf("I1 = %0.0e A\n",I1); + + printf("I2 = %0.1e A",I2); + + + // Result + + // I1 = 1 mA + + // I2 = 0.5 mA' - model: saveAPI.gallery - pk: 640 + pk: 19 fields: save_id: gallery18 name: example3_28 description: 'Basic Electronics (Author: D. De), 3) Diode Circuits, 3.28) Find voltage across diode' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 181 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" title="example3_28"><!--Xcos - 1.0 - scilab-5.5.2 - 20200302--><mxGraphModel @@ -18473,14 +18529,44 @@ y="470.0"/><mxPoint x="510.0" y="200.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-3721ad33:1314dc6b131:-7f87" parent="-3721ad33:1314dc6b131:-7f86"/></XcosDiagram> media: gallery18.png + script_dump: '// Find voltage across diode + + // Basic Electronics + + // By Debashis De + + // First Edition, 2010 + + // Dorling Kindersley Pvt. Ltd. India + + // Example 3-28 in page 180 + + + // Given data + + I=0.1075; // Cirremt across diode in A + + Rd=1; // Internal resistance of diode in ohm + + + // Calculation + + Vd=I*Rd; + + printf("Voltage across diode = %0.4f V",Vd); + + + // Result + + // Voltage across diode = 0.1075 V' - model: saveAPI.gallery - pk: 641 + pk: 20 fields: save_id: gallery19 name: example3_30 description: 'Basic Electronics (Author: D. De), 3) Diode Circuits, 3.30) Calculate R Il max' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:07+00:00 book: 181 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex3_30"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -19120,14 +19206,52 @@ x="780.0" y="130.0"/><mxPoint as="targetPoint" x="780.0" y="180.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-3721ad33:1314dc6b131:-7f5d" parent="-3721ad33:1314dc6b131:-7f5c"/></XcosDiagram> media: gallery19.png + script_dump: '// Calculate R,I_l(max) + + // Basic Electronics + + // By Debashis De + + // First Edition, 2010 + + // Dorling Kindersley Pvt. Ltd. India + + // Example 3-30 in page 181 + + + // Given data + + V_0=50; // Zener diode voltage in V + + I_L=0; // Load current in A + + + // Calculation + + R=(150)/(40*10^-3); + + printf("(a)R = %0.2e ohm\n",R); + + printf("I_L = I_max when Id = Id_min = 10mA\n"); + + I_Lmax=40-10; + + printf("(b)Maximum load current = %0.0f mA",I_Lmax); + + + // Result + + // (a) R = 3.75 K-ohms + + // (b) I_Lmax = 30 mA' - model: saveAPI.gallery - pk: 642 + pk: 21 fields: save_id: gallery20 name: example3_8 description: 'Basic Electronics (Author: D. De), 3) Diode Circuits, 3.8) Calculate the dc load current' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 181 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" title="Ex3_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 1216--><mxGraphModel @@ -19793,14 +19917,71 @@ x="870.0" y="200.0"/><mxPoint x="740.0" y="200.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-2d85d470:1314777ee15:-7f7e" parent="-2d85d470:1314777ee15:-7f7d"/></XcosDiagram> media: gallery20.png + script_dump: '// Calculate the dc load current + + // Basic Electronics + + // By Debashis De + + // First Edition, 2010 + + // Dorling Kindersley Pvt. Ltd. India + + // Example 3-8 in page 157 + + + // Given data + + Vm=280; // Supply voltage in V + + Rl=2000; // Load resistance in ohms + + Rf=500; // Internal resistance of the diodes in ohms + + + // Calculation + + Idc=(2*Vm)/(%pi*2500); + + Idc_t=Idc/2; + + printf("(a)I_dc = %0.2e A\n(b)I_dc(tube) = %0.2e A\n",Idc,Idc_t); + + printf("(c)Voltage across conducting diode is sinusoidal with a peak value 0.2 + Vm\n"); + + V_rms=0.905*(280*sqrt(2)); + + Pdc=Idc^2*Rl; + + R=(Rf/Rl)*100; + + printf("Rms voltage V_rms = %0.0f V\n",V_rms); + + printf("(d)DC output power = %0.1f W\n",Pdc); + + printf("(e)Percentage regulation = %0.0f percent",R); + + + // Result + + // (a) Idc = 71 mA, + + // (b) Idc_tube = 35.7 mA, + + // (c) V_rms = 358 V, + + // (d) P_dc = 10.167W, + + // (e) Percentage regulation = 25%' - model: saveAPI.gallery - pk: 643 + pk: 22 fields: save_id: gallery21 name: Ex10_1 description: 'Digital Control (Author: K. M. Moudgalya), 10) Special Cases of Pole Placement Control, 10.1) Effect of delay in control performance' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="stb_disc"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -22203,14 +22384,1082 @@ as="geometry" height="40.0" width="40.0" x="40.0" y="320.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-7476484f:145f8cd2a3c:-7be9" parent="-7476484f:145f8cd2a3c:-7be8"/></XcosDiagram> media: gallery21.png + script_dump: '// Effect of delay in control performance + + // 10.1 + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // Pole placement controller using internal model principle, as discussed in + Sec. 9.4. + + // 9.8 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im(B,A,k,phi,Delta) + + // Calculates 2-DOF pole placement controller. + + + function [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + dphi = length(phi)-1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + endfunction; + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + Ts = 1; B = 0.63; A = [1 -0.37]; + + k = 5; + + if k<=0, k = 1; end + + [zk,dzk] = zpowk(k); + + + // Desired transfer function + + phi = [1 -0.5]; + + delta = 1; // internal model of step introduced + + + // Controller design + + [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,delta); + + + // simulation parameters for stb_disc.xcos + + // y1: 0 to 1; u1: 0 to 1.2 + + st = 1.0; // desired change in setpoint + + t_init = 0; // simulation start time + + t_final = 20; // simulation end time + + + // simulation parameters for stb_disc.xcos + + N_var = 0; C = 0; D = 1; N = 1; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 644 + pk: 23 fields: save_id: gallery22 name: Ex10_2 description: 'Digital Control (Author: K. M. Moudgalya), 10) Special Cases of Pole Placement Control, 10.2) Smith predictor for paper machine control' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="smith_disc"><!--Xcos - 1.0 - scilab-5.5.2 @@ -24769,14 +26018,1114 @@ as="geometry" height="30.0" width="40.0" x="550.0" y="380.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-5d8a58f8:147c67c0236:-7ffb" parent="-5d8a58f8:147c67c0236:-7ffa"/></XcosDiagram> media: gallery22.png + script_dump: '// Smith predictor for paper machine control in Example 10.2 on + page 385. + + // 10.2 + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + function [C,degC] = poladd(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= cB | rA ~= rB + + error(''poladd: Inconsistent dimensions''); + + end + + + degC = max(degA,degB); + + if degC >= degA + + A = [A zeros(rA,(degC-degA)*cA)]; + + end + + if degC >= degB + + B = [B zeros(rB,(degC-degB)*cB)]; + + end + + C = A+B; + + endfunction; + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // Pole placement controller using internal model principle, as discussed in + Sec. 9.4. + + // 9.8 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im(B,A,k,phi,Delta) + + // Calculates 2-DOF pole placement controller. + + + function [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + dphi = length(phi)-1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + endfunction; + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + Ts = 1; B = 0.63; A = [1 -0.37]; k = 3; + + Bd = convol(B,[0 1]); + + kd = k - 1; + + [zkd,dzkd] = zpowk(kd); + + [mzkd,dmzkd] = poladd(1,0,-zkd,dzkd); + + + // Desired transfer function + + phi = [1 -0.5]; delta = 1; + + + // Controller design + + [Rc,Sc,Tc,gamm] = pp_im(B,A,1,phi,delta); + + + // simulation parameters for smith_disc.xcos + + st = 1.0; // desired change in setpoint + + t_init = 0; // simulation start time + + t_final = 20; // simulation end time + + + // simulation parameters for smith_disc.xcos + + N_var = 0; C = 0; D = 1; N = 1; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bdp,Ap] = cosfil_ip(Bd,A); // Bd/Ad + + [zkdp1,zkdp2] = cosfil_ip(zkd,1); // zkd/1 + + [mzkdp1,mzkdp2] = cosfil_ip(mzkd,1); // mzkd/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 645 + pk: 24 fields: save_id: gallery23 name: Ex11_4 description: 'Digital Control (Author: K. M. Moudgalya), 11) Minimum Variance Control, 11.4) 1st control problem by MacGregor' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1000.0" title="stb_disc"><!--Xcos - 1.0 - scilab-5.5.2 @@ -27179,14 +29528,1299 @@ as="geometry" height="40.0" width="40.0" x="40.0" y="320.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-7476484f:145f8cd2a3c:-7be9" parent="-7476484f:145f8cd2a3c:-7be8"/></XcosDiagram> media: gallery23.png + script_dump: '// MacGregor''s first control problem, discussed in Example 11.4 + on page 213. + + // 11.4 + + // Minimum variance control law design, given by Eq. 11.40 on page 413. + + // 11.5 + + + // function [S,dS,R,dR] = mv(A,dA,B,dB,C,dC,k,int) + + // implements the minimum variance controller + + // if int>=1, integrated noise is assumed; otherwise, + + // it is not integrated noise + + + function [S,dS,R,dR] = mv(A,dA,B,dB,C,dC,k,int1) + + zk = zeros(1,k+1); zk(k+1) = 1; + + if int1>=1, [A,dA] = polmul([1 -1],1,A,dA); end + + [Fk,dFk,Ek,dEk] = xdync(zk,k,A,dA,C,dC); + + + [Gk,dGk] = polmul(Ek,dEk,B,dB); + + S = Fk; dS = dFk; R = Gk; dR = dGk; + + endfunction; + + // Calculation of closed loop transfer functions + + // 11.6 + + + // function [Nu,dNu,Du,dDu,Ny,dNy,Dy,dDy,yvar,uvar] = ... + + // cl(A,dA,B,dB,C,dC,k,S,dS,R,dR,int) + + // int>=1 means integrated noise and control law: + + // delta u = - (S/R)y + + // Evaluates the closed loop transfer function and + + // variances of input and output + + + function [Nu,dNu,Du,dDu,Ny,dNy,Dy,dDy,yvar,uvar] = ... + + cl(A,dA,B,dB,C,dC,k,S,dS,R,dR,int1) + + [zk,dzk] = zpowk(k); + + + [BS,dBS] = polmul(B,dB,S,dS); + + [zBS,dzBS] = polmul(zk,dzk,BS,dBS); + + [RA,dRA] = polmul(R,dR,A,dA); + + if int1>=1, [RA,dRA] = polmul(RA,dRA,[1 -1],1); end + + + [D,dD] = poladd(RA,dRA,zBS,dzBS); + + + [Ny,dNy] = polmul(C,dC,R,dR); + + [Nu,dNu] = polmul(C,dC,S,dS); + + + [Nu,dNu,Du,dDu,uvar] = tfvar(Nu,dNu,D,dD); + + [Ny,dNy,Dy,dDy,yvar] = tfvar(Ny,dNy,D,dD); + + + endfunction; + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + function [C,degC] = poladd(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= cB | rA ~= rB + + error(''poladd: Inconsistent dimensions''); + + end + + + degC = max(degA,degB); + + if degC >= degA + + A = [A zeros(rA,(degC-degA)*cA)]; + + end + + if degC >= degB + + B = [B zeros(rB,(degC-degB)*cB)]; + + end + + C = A+B; + + endfunction; + + // Cancellation of common factors and determination of covariance + + // 11.7 + + + // function [N,dN,D,dD,yvar] = tfvar(N,dN,D,dD) + + // N and D polynomials in z^{-1} form; discrete case + + + function [N,dN,D,dD,yvar] = tfvar(N,dN,D,dD) + + + [N,dN,D,dD] = l2r(N,dN,D,dD); + + N = N/D(1); D = D/D(1); + + LN = length(N); LD = length(D); + + D1 = D; + + if LD<LN, D1 = [D zeros(1,LN-LD)]; dD1 = dD+LN-LD; end + + H = tf(N,D1,1);//TS=1 (sampling time) has been taken constant in tfvar + + yvar = covar_m(H,1); + + endfunction; + + // function [Rnum,Rnumdeg,Rden,Rdendeg] = l2r(N,degN,D,degD) + + // given Numerator and Denominator polynomial matrices in left form, + + // not necessarily coprime, finds right coprime factorisation. + + + function [Rnum,Rnumdeg,Rden,Rdendeg] = l2r(N,degN,D,degD) + + + [N,degN] = transp(N,degN); + + [D,degD] = transp(D,degD); + + + [Rnum,Rnumdeg,Rden,Rdendeg] = left_prm(N,degN,D,degD); + + [Rnum,Rnumdeg] = transp(Rnum,Rnumdeg); + + [Rden,Rdendeg] = transp(Rden,Rdendeg); + + endfunction; + + // function [P,degP] = transp(Q,degQ) + + // MATLAB FUNCTION transp TO TRANSPOSE + + // A POLYNOMIAL MATRIX + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = transp(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + rP = cQ; cP = rQ; degP = degQ; + + P = zeros(rP,(degP+1)*cP); + + for i = 1:degP+1 + + P(:,(i-1)*cP+1:i*cP) = Q(:,(i-1)*cQ+1:i*cQ)''; + + end + + + endfunction; + + //User defined function + + //Forms a transfer function + + //Scilab: Co efficients are given in increasing power of variable + + //Matlab: Co efficients are given in decreasing power of variable + + //Hence co efficients are flipped here + + + //Input arguments: (1) Numerator co efficients(decreasing order) + + //(2) Denominator co efficients + + //(3) Variable to specify domain + + + // Updated (30-11-06) + + // System is continuous => a is not passed + + // System is discrete => a = -1 + + // System is discretized (sampled system) => a = Ts + + // Uses syslin + + + function trfu = tf(num,den,a) + + if argn(2) == 2 + + d = ''c''; + + elseif a == -1 + + d = ''d''; + + else + + d = a + + end; + + num = clean(num); + + den = clean(den); + + num1 = poly(num(length(num):-1:1),''x'',''coeff''); + + den1 = poly(den(length(den):-1:1),''x'',''coeff''); + + trfu = syslin(d,num1,den1); + + endfunction; + + + + + //User defined equivalent function to Matlab covar function + + //For discrete time domain only + + //Uses Lyapunov''s equation for computation + + //W: noise intensity (scalar) + + //Matlab result for unstable systems: + + //Warning: Unstable models have infinite covariance + + + function P = covar_m(sys,W) + + a = roots(sys(''den'')); + + b = length(a); + + c = abs(a) > 1; + + if b ~= 0 then + + for i = 1:b + + if c(i) == %t then + + disp(''Warning: System being unstable has infinite covariance''); + + P = %inf; + + else + + s = tf2ss(sys); + + [A,B,C,D] = s(2:5); + + //Sylvester and Lyapunov solver + + task = 2; flag = [1 0]; tran = 1; + + Q1 = -B*W*B''; + + Q = linmeq(task,A,Q1,flag,tran) + + P = C*Q*C'' + D*W*D''; + + end; + + end; + + else + + s = tf2ss(sys); + + [A,B,C,D] = s(2:5); + + //Sylvester and Lyapunov solver + + task = 2; flag = [1 0]; tran = 1; + + Q1 = -B*W*B''; + + Q = linmeq(task,A,Q1,flag,tran) + + P = C*Q*C'' + D*W*D''; + + end; + + endfunction; + + + //if d==0 | c==%f + + // disp(''Calc''); + + //else + + // disp(''Unstable''); + + //end; + + // Above logic can also solve our purpose + + // But it gives incorrect answer if roots are [1 -1 1] or + + // [1 -1 -1] .... + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // MacGregor''s first control problem + + A = [1 -1.4 0.45]; dA = 2; C = [1 -0.5]; dC = 1; + + B = 0.5*[1 -0.9]; dB = 1; k = 1; int1 = 0; + + [Sc,dSc,Rc,dRc] = mv(A,dA,B,dB,C,dC,k,int1); + + [Nu,dNu,Du,dDu,Ny,dNy,Dy,dDy,yvar,uvar] = ... + + cl(A,dA,B,dB,C,dC,k,Sc,dSc,Rc,dRc,int1); + + + // Simulation parameters for stb_disc.xcos + + Tc = Sc; gamm = 1; [zk,dzk] = zpowk(k); + + D = 1; N_var = 1; Ts = 1; st = 0; + + t_init = 0; t_final = 1000; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 646 + pk: 25 fields: save_id: gallery24 name: Ex7_6 description: 'Digital Control (Author: K. M. Moudgalya), 7) Structures and Specifications, 7.6) Verification of performance of lead controller on antenna system' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="g_s_cl2"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -29734,14 +33368,142 @@ as="geometry" height="40.0" width="40.0" x="460.0" y="360.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-75a601dc:14604d880d0:-7ffd" parent="-75a601dc:14604d880d0:-7ffc"/></XcosDiagram> media: gallery24.png + script_dump: '// Verification of performance of lead controller on antenna system, + as discussed in Example 7.3. + + // 7.6 + + + // Continuous time antenna model + + a = 0.1; + + F = [0 1;0 -a]; g = [0; a]; c = [1 0]; d = 0; + + Ga = syslin(''c'',F,g,c,d); [ds,num,den] = ss2tf(Ga); + + Num = clean(num); Den = clean(den); + + Ts = 0.2; + + G = dscr(Ga,Ts); + + + // lead controller + + beta1 = 0.8; + + N = [1 -0.9802]*(1-beta1)/(1-0.9802); Rc = [1 -beta1]; + + + // simulation parameters using g_s_cl2.cos + + gamm = 1; Sc = 1; Tc = 1; C = 0; D = 1; + + st = 1; st1 = 0; + + t_init = 0; t_final = 20; + + + // u1: -4 to 11 + + // y1: 0 to 1.4 + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // N/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 647 + pk: 26 fields: save_id: gallery25 name: Ex7_7 description: 'Digital Control (Author: K. M. Moudgalya), 7) Structures and Specifications, 7.7) Illustration of system type' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="stb_disc"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -32157,14 +35919,1008 @@ as="geometry" height="40.0" width="40.0" x="40.0" y="320.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-7476484f:145f8cd2a3c:-7be9" parent="-7476484f:145f8cd2a3c:-7be8"/></XcosDiagram> media: gallery25.png + script_dump: '// Illustration of system type, as explained in Example 7.10 on + page 275. + + // 7.7 + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // Solution to Aryabhatta''s identity arising in PID controller design, namely + Eq. 9.37 on page 363. + + // 9.20 + + + function [Rc,Sc] = pp_pid(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + dB = length(B) - 1; dA = length(A) - 1; + + [zk,dzk] = zpowk(k); + + [N,dN] = polmul(B,dB,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(A,dA,Delta,dDelta); + + dphi = length(phi)-1; + + [Sc,dSc,R,dR] = xdync(N,dN,D,dD,phi,dphi); + + Rc = convol(R,Delta); + + endfunction; + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Plant + + B = 1; A = [1 -1]; zk = [0 1]; Ts = 1; k = 1; + + // Value of k absent in original code + + // Specify closed loop characteristic polynomial + + phi = [1 -0.5]; + + + // Design the controller + + reject_ramps = 1; + + if reject_ramps == 1, + + Delta = [1 -1]; // to reject ramps another Delta + + else + + Delta = 1; // steps can be rejected by plant itself + + end + + [Rc,Sc] = pp_pid(B,A,k,phi,Delta); + + + // parameters for simulation using stb_disc.mdl + + Tc = Sc; gamm = 1; N = 1; + + C = 0; D = 1; N_var = 0; + + st = 1; t_init = 0; t_final = 20; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D + + + // Give appropriate path + + //xcos(''stb_disc.xcos'');' - model: saveAPI.gallery - pk: 648 + pk: 27 fields: save_id: gallery26 name: Ex9_10 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.10) Pole placement controller IBM Lotus Domino server' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="40.0" title="Ex9_10"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -34512,14 +39268,1101 @@ as="defaultParent" id="-2f864670:16fc63faf34:-7bc7" parent="-2f864670:16fc63faf34:-7bc6"/><mxPoint as="origin" x="-80.0"/></XcosDiagram> media: gallery26.png + script_dump: '// Pole placement controller IBM Lotus Domino server, discussed + in Example 9.9 on page 341. + + // 9.10 + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Pole placement controller using internal model principle, as discussed in + Sec. 9.4. + + // 9.8 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im(B,A,k,phi,Delta) + + // Calculates 2-DOF pole placement controller. + + + function [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + dphi = length(phi)-1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + endfunction; + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Control of IBM lotus domino server + + // Transfer function + + B = 0.47; A = [1 -0.43]; k = 1; + + [zk,dzk] = zpowk(k); + + + // Transient specifications + + rise = 10; epsilon = 0.01; Ts = 1; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + Delta = [1 -1]; // internal model of step used + + [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta); + + + // Simulation parameters for stb_disc.xcos + + st = 1; // desired change + + t_init = 0; // simulation start time + + t_final = 40; // simulation end time + + C = 0; D = 1; N_var = 0; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 649 + pk: 28 fields: save_id: gallery27 name: Ex9_11 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.11) Pole placement controller for motor problem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="Untitled - 10:43:53 AM"><!--Xcos - 1.0 - @@ -36812,14 +42655,1141 @@ as="points" scilabClass=""><mxPoint x="520.0" y="450.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-2f864670:16fc63faf34:-759a" parent="-2f864670:16fc63faf34:-7599"/></XcosDiagram> media: gallery27.png + script_dump: '// Pole placement controller for motor problem, discussed in Example + 9.10 on page 343. + + // 9.11 + + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Pole placement controller using internal model principle, as discussed in + Sec. 9.4. + + // 9.8 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im(B,A,k,phi,Delta) + + // Calculates 2-DOF pole placement controller. + + + function [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + dphi = length(phi)-1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + endfunction; + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Motor control problem + + // Transfer function + + a1 = [-1 0; 1 0]; b1 = [1; 0]; c1 = [0 1]; d1 = 0; + + G = syslin(''c'',a1,b1,c1,d1); Ts = 0.25; + + [B,A,k] = myc2d(G,Ts); + + + // Transient specifications + + rise = 3; epsilon = 0.05; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + Delta = 1; // No internal model of step used + + [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta); + + + // simulation parameters for c_ss_cl.xcos + + st = 1; //desired change in position + + t_init = 0; //simulation start time + + t_final = 10; //simulation end time + + xInitial = [0 0]; //initial conditions + + N = 1; C = 0; D = 1; N_var = 0; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 650 + pk: 29 fields: save_id: gallery28 name: Ex9_14 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.14) Controller design' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.5" title="Ex9_14"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -39360,14 +46330,1251 @@ as="geometry" height="40.0" width="40.0" x="680.0" y="400.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-2f864670:16fc63faf34:-72c4" parent="-2f864670:16fc63faf34:-72c3"/></XcosDiagram> media: gallery28.png + script_dump: '// Controller design for the case study presented in Example 9.12 + on page 347. + + // 9.14 + + + //User defined function + + //Forms a transfer function + + //Scilab: Co efficients are given in increasing power of variable + + //Matlab: Co efficients are given in decreasing power of variable + + //Hence co efficients are flipped here + + + //Input arguments: (1) Numerator co efficients(decreasing order) + + //(2) Denominator co efficients + + //(3) Variable to specify domain + + + // Updated (30-11-06) + + // System is continuous => a is not passed + + // System is discrete => a = -1 + + // System is discretized (sampled system) => a = Ts + + // Uses syslin + + + function trfu = tf(num,den,a) + + if argn(2) == 2 + + d = ''c''; + + elseif a == -1 + + d = ''d''; + + else + + d = a + + end; + + num = clean(num); + + den = clean(den); + + num1 = poly(num(length(num):-1:1),''x'',''coeff''); + + den1 = poly(den(length(den):-1:1),''x'',''coeff''); + + trfu = syslin(d,num1,den1); + + endfunction; + + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; + + end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // Pole placement controller without intra sample oscillations, as discussed + in Sec. 9.5. + + // 9.13 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im2(B,A,k,phi,Delta,a) + + // 2-DOF PP controller with internal model of Delta and without + + // hidden oscillations + + + function [Rc,Sc,Tc,gamm,phit] = pp_im2(B,A,k,phi,Delta,a) + + + if argn(2) == 5, a = 1; end + + dphi = length(phi)-1; + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A,a); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B,a); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + + // Total characteristic polynomial + + phit = convol(phi,convol(Ag,Bg)); + + endfunction; + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + + num = 200; + + den = convol([0.05 1],[0.05 1]); + + den = convol([10 1],den); + + G = tf(num,den); Ts = 0.025; + + num = G(''num''); den = G(''den''); + + // iodel = 0; + + [B,A,k] = myc2d(G,Ts); + + [zk,dzk] = zpowk(k); //int1 = 0; + + + // Transient specifications + + a = 0.9; rise = 0.24; epsilon = 0.05; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + Delta = [1 -1]; // internal model of step is present + + [Rc,Sc,Tc,gamm] = pp_im2(B,A,k,phi,Delta,a); + + + // margin calculation + + Lnum = convol(Sc,convol(B,zk)); + + Lden = convol(Rc,A); + + L = tf(Lnum,Lden,Ts); + + // Gm = g_margin(L); //---- Does not match --------------- (in dB) + + Pm = p_margin(L); //---- Convergence problem --------------- (in degree) + + + num1 = 100; den1 = [10 1]; + + Gd = tf(num1,den1); //------- + + [C,D,k1] = myc2d(Gd,Ts); + + [zk,dzk] = zpowk(k); + + C = convol(C,zk); + + + // simulation parameters g_s_cl2.xcos ------------ + + N = 1; + + st = 1; // desired change in setpoint + + st1 = 0; // magnitude of disturbance + + t_init = 0; // simulation start time + + t_final = 1.5; // simulation end time + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // N/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 651 + pk: 30 fields: save_id: gallery29 name: Ex9_15_1 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.15) Evaluation of continuous time controller' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex9_15_1"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -41866,14 +50073,308 @@ as="geometry" height="40.0" width="40.0" x="760.0" y="420.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-2f864670:16fc63faf34:-6b2d" parent="-2f864670:16fc63faf34:-6b2c"/></XcosDiagram> media: gallery29.png + script_dump: '// Evaluation of continuous time controller for the case study presented + in Example 9.13 on page 349. + + // 9.15 + + + //User defined function + + //Forms a transfer function + + //Scilab: Co efficients are given in increasing power of variable + + //Matlab: Co efficients are given in decreasing power of variable + + //Hence co efficients are flipped here + + + //Input arguments: (1) Numerator co efficients(decreasing order) + + //(2) Denominator co efficients + + //(3) Variable to specify domain + + + // Updated (30-11-06) + + // System is continuous => a is not passed + + // System is discrete => a = -1 + + // System is discretized (sampled system) => a = Ts + + // Uses syslin + + + function trfu = tf(num,den,a) + + if argn(2) == 2 + + d = ''c''; + + elseif a == -1 + + d = ''d''; + + else + + d = a + + end; + + num = clean(num); + + den = clean(den); + + num1 = poly(num(length(num):-1:1),''x'',''coeff''); + + den1 = poly(den(length(den):-1:1),''x'',''coeff''); + + trfu = syslin(d,num1,den1); + + endfunction; + + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + + num = 200; + + den = convol([0.05 1],[0.05 1]); + + den = convol([10 1],den); + + G = tf(num,den); Ts = 0.005; + + [B,A,k] = myc2d(G,Ts); + + [zk,dzk] = zpowk(k); //int = 0; + + + // Sigurd''s feedback controller'' + + numb = 0.5*convol([1 2],[0.05 1]); + + denb = convol([1 0],[0.005 1]); + + Gb = tf(numb,denb); + + [Sb,Rb,kb] = myc2d(Gb,Ts); + + [zkb,dzkb] = zpowk(kb); + + Sb = convol(Sb,zkb); + + + // Sigurd''s feed forward controller'' + + numf = [0.5 1]; + + denf = convol([0.65 1],[0.03 1]); + + Gf = tf(numf,denf); + + [Sf,Rf,kf] = myc2d(Gf,Ts); + + [zkf,dzkf] = zpowk(kf); + + Sf = convol(Sf,zkf); + + + // Margins + + simp_mode(%f); + + L = G*Gb; + + // Gm = g_margin(L); // ------ + + Pm = p_margin(L); // ------ + + Lnum = convol(Sb,convol(zk,B)); + + Lden = convol(Rb,A); + + L = tf(Lnum,Lden,Ts); + + // DGm = g_margin(L); // ------ + + DPm = p_margin(L); // ------ + + + // Noise + + num1 = 100; den1 = [10 1]; + + + // simulation parameters for + + // entirely continuous simulation: g_s_cl3.xcos + + // hybrid simulation: g_s_cl6.xcos + + st = 1; // desired change in setpoint + + st1 = 0; + + t_init = 0; // simulation start time + + t_final = 5; // simulation end time + + + num = polyno(num,''s''); den = polyno(den,''s''); + + Numb = polyno(numb,''s''); Denb = polyno(denb,''s''); + + Numf = polyno(numf,''s''); Denf = polyno(denf,''s''); + + Num1 = polyno(num1,''s''); Den1 = polyno(den1,''s''); + + + [Sbp,Rbp] = cosfil_ip(Sb,Rb); + + [Sfp,Rfp] = cosfil_ip(Sf,Rf);' - model: saveAPI.gallery - pk: 652 + pk: 31 fields: save_id: gallery30 name: Ex9_15_2 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.15) Evaluation of continuous time controller' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex9_15_2"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -44481,14 +52982,308 @@ as="defaultParent" id="-2f864670:16fc63faf34:-6546" parent="-2f864670:16fc63faf34:-6545"/><mxPoint as="origin" y="-10.0"/></XcosDiagram> media: gallery30.png + script_dump: '// Evaluation of continuous time controller for the case study presented + in Example 9.13 on page 349. + + // 9.15 + + + //User defined function + + //Forms a transfer function + + //Scilab: Co efficients are given in increasing power of variable + + //Matlab: Co efficients are given in decreasing power of variable + + //Hence co efficients are flipped here + + + //Input arguments: (1) Numerator co efficients(decreasing order) + + //(2) Denominator co efficients + + //(3) Variable to specify domain + + + // Updated (30-11-06) + + // System is continuous => a is not passed + + // System is discrete => a = -1 + + // System is discretized (sampled system) => a = Ts + + // Uses syslin + + + function trfu = tf(num,den,a) + + if argn(2) == 2 + + d = ''c''; + + elseif a == -1 + + d = ''d''; + + else + + d = a + + end; + + num = clean(num); + + den = clean(den); + + num1 = poly(num(length(num):-1:1),''x'',''coeff''); + + den1 = poly(den(length(den):-1:1),''x'',''coeff''); + + trfu = syslin(d,num1,den1); + + endfunction; + + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + + num = 200; + + den = convol([0.05 1],[0.05 1]); + + den = convol([10 1],den); + + G = tf(num,den); Ts = 0.005; + + [B,A,k] = myc2d(G,Ts); + + [zk,dzk] = zpowk(k); //int = 0; + + + // Sigurd''s feedback controller'' + + numb = 0.5*convol([1 2],[0.05 1]); + + denb = convol([1 0],[0.005 1]); + + Gb = tf(numb,denb); + + [Sb,Rb,kb] = myc2d(Gb,Ts); + + [zkb,dzkb] = zpowk(kb); + + Sb = convol(Sb,zkb); + + + // Sigurd''s feed forward controller'' + + numf = [0.5 1]; + + denf = convol([0.65 1],[0.03 1]); + + Gf = tf(numf,denf); + + [Sf,Rf,kf] = myc2d(Gf,Ts); + + [zkf,dzkf] = zpowk(kf); + + Sf = convol(Sf,zkf); + + + // Margins + + simp_mode(%f); + + L = G*Gb; + + // Gm = g_margin(L); // ------ + + Pm = p_margin(L); // ------ + + Lnum = convol(Sb,convol(zk,B)); + + Lden = convol(Rb,A); + + L = tf(Lnum,Lden,Ts); + + // DGm = g_margin(L); // ------ + + DPm = p_margin(L); // ------ + + + // Noise + + num1 = 100; den1 = [10 1]; + + + // simulation parameters for + + // entirely continuous simulation: g_s_cl3.xcos + + // hybrid simulation: g_s_cl6.xcos + + st = 1; // desired change in setpoint + + st1 = 0; + + t_init = 0; // simulation start time + + t_final = 5; // simulation end time + + + num = polyno(num,''s''); den = polyno(den,''s''); + + Numb = polyno(numb,''s''); Denb = polyno(denb,''s''); + + Numf = polyno(numf,''s''); Denf = polyno(denf,''s''); + + Num1 = polyno(num1,''s''); Den1 = polyno(den1,''s''); + + + [Sbp,Rbp] = cosfil_ip(Sb,Rb); + + [Sfp,Rfp] = cosfil_ip(Sf,Rf);' - model: saveAPI.gallery - pk: 653 + pk: 32 fields: save_id: gallery31 name: Ex9_16 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.16) System type with 2 DOF controller' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="Ex9_16"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -46908,14 +55703,1068 @@ as="defaultParent" id="-2f864670:16fc63faf34:-5f92" parent="-2f864670:16fc63faf34:-5f91"/><mxPoint as="origin" x="-350.0"/></XcosDiagram> media: gallery31.png + script_dump: '// System type with 2-DOF controller. It is used to arrive at the + results Example 9.14. + + // 9.16 + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // Pole placement controller using internal model principle, as discussed in + Sec. 9.4. + + // 9.8 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im(B,A,k,phi,Delta) + + // Calculates 2-DOF pole placement controller. + + + function [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + dphi = length(phi)-1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + endfunction; + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + B = 1; A = [1 -1]; k = 1; zk = zpowk(k); Ts = 1; + + phi = [1 -0.5]; + + + Delta = 1; // Choice of internal model of step + + [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta); + + + // simulation parameters for stb_disc.xcos + + st = 1; // desired step change + + t_init = 0; // simulation start time + + t_final = 20; // simulation end time + + xInitial = [0 0]; + + C = 0; D = 1; N_var = 0; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 654 + pk: 33 fields: save_id: gallery32 name: Ex9_17 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.17) Illustrating the benefit of cancellation' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="Ex9_17"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -49329,14 +59178,1056 @@ as="defaultParent" id="-2f864670:16fc63faf34:-5c8f" parent="-2f864670:16fc63faf34:-5c8e"/><mxPoint as="origin" x="-60.0"/></XcosDiagram> media: gallery32.png + script_dump: '// Illustrating the benefit of cancellation. It is used to arrive + at the results of Example 9.15. + + // 9.17 + + // Pole placement controller using internal model principle, as discussed in + Sec. 9.4. + + // 9.8 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im(B,A,k,phi,Delta) + + // Calculates 2-DOF pole placement controller. + + + function [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + dphi = length(phi)-1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + endfunction; + + // Solution to Aryabhatta''s identity arising in PID controller design, namely + Eq. 9.37 on page 363. + + // 9.20 + + + function [Rc,Sc] = pp_pid(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + dB = length(B) - 1; dA = length(A) - 1; + + [zk,dzk] = zpowk(k); + + [N,dN] = polmul(B,dB,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(A,dA,Delta,dDelta); + + dphi = length(phi)-1; + + [Sc,dSc,R,dR] = xdync(N,dN,D,dD,phi,dphi); + + Rc = convol(R,Delta); + + endfunction; + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // test problem to demonstrate benefits of 2_dof + + // Ts = 1; B = [1 0.9]; A = conv([1 -1],[1 -0.8]); k = 1; + + Ts = 1; k = 1; + + B = convol([1 0.9],[1 -0.8]); A = convol([1 -1],[1 -0.5]); + + + // closed loop characteristic polynomial + + phi = [1 -1 0.5]; + + + Delta = 1; // Choice of internal model of step + + control = 1; + + if control == 1, // 1-DOF with no cancellation + + [Rc,Sc] = pp_pid(B,A,k,phi,Delta); + + Tc = Sc; gamm = 1; + + else // 2-DOF + + [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta); + + end + + + // simulation parameters for stb_disc.mdl + + [zk,dzk] = zpowk(k); + + st = 1; // desired step change + + t_init = 0; // simulation start time + + t_final = 20; // simulation end time + + xInitial = [0 0]; + + C = 0; D = 1; N_var = 0; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 655 + pk: 34 fields: save_id: gallery33 name: Ex9_18 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.18) Anti windup control of IBM Lotus Domino server' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1000.0" title="stb_disc_sat"><!--Xcos - 1.0 - scilab-5.5.2 @@ -52361,14 +63252,1223 @@ as="geometry" height="20.0" width="60.0" x="670.0" y="160.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-98b0b2b:146d610f05a:-78c3" parent="-98b0b2b:146d610f05a:-78c2"/></XcosDiagram> media: gallery33.png + script_dump: '// Anti windup control (AWC) of IBM Lotus Domino server, studied + in Example 9.16 on page 357. It can be used for the follwoing situations: with + and without saturation, and with and without AWC. + + // 9.18 + + // Pole placement controller without intra sample oscillations, as discussed + in Sec. 9.5. + + // 9.13 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im2(B,A,k,phi,Delta,a) + + // 2-DOF PP controller with internal model of Delta and without + + // hidden oscillations + + + function [Rc,Sc,Tc,gamm,phit] = pp_im2(B,A,k,phi,Delta,a) + + + if argn(2) == 5, a = 1; end + + dphi = length(phi)-1; + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A,a); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B,a); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + + // Total characteristic polynomial + + phit = convol(phi,convol(Ag,Bg)); + + endfunction; + + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; + + end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + function [C,degC] = poladd(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= cB | rA ~= rB + + error(''poladd: Inconsistent dimensions''); + + end + + + degC = max(degA,degB); + + if degC >= degA + + A = [A zeros(rA,(degC-degA)*cA)]; + + end + + if degC >= degB + + B = [B zeros(rB,(degC-degB)*cB)]; + + end + + C = A+B; + + endfunction; + + + // Transfer function + + B = 0.47; A = [1 -0.43]; k = 1; + + [zk,dzk] = zpowk(k); + + + // Transient specifications + + rise = 10; epsilon = 0.01; Ts = 1; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + delta = [1 -1]; // internal model of step used + + [Rc,Sc,Tc,gamm,F] = pp_im2(B,A,k,phi,delta); + + + // Study of Antiwindup Controller + + + // Set key between 1 and 4 + + // key = 1: Simulate without any saturation limits + + // key = 2: Simulate saturation, but do not use AWC + + // key = 3: Simulate saturation with AWC in place + + // key = 4: Simulate with AWC, without saturation limits + + key=1 + + + if key ==0 + + disp(''Invalid choice''); + + return; + + elseif key == 1 + + U = 2; L = -2; P = 1; F = Rc; E = 0; PSc = Sc; PTc = Tc; + + elseif key == 2 + + U = 1; L = -1; P = 1; F = Rc; E = 0; PSc = Sc; PTc = Tc; + + else + + if key == 3 // Antiwindup controller and with saturation + + U = 1; L = -1; + + elseif key == 4 // Antiwindup controller, but no saturation + + U = 2; L = -2; + + else + + disp(''Invalid choice''); + + return; + + end + + P = A; + + dF = length(F) - 1; + + PRc = convol(P,Rc); dPRc = length(PRc) - 1; + + [E,dE] = poladd(F,dF,-PRc,dPRc); + + PSc = convol(P,Sc); PTc = convol(P,Tc); + + end + + + // Setting up simulation parameters for stb_disc_sat + + t_init = 0; // first step begins + + st = 1; // height of first step + + t_init2 = 500; // second step begins + + st2 = -2; // height of second step + + t_final = 1000; // simulation end time + + st1 = 0; // no disturbance input + + C = 0; D = 1; N_var = 0; + + + [PTcp1,PTcp2] = cosfil_ip(PTc,1); // PTc/1 + + [Fp1,Fp2] = cosfil_ip(1,F); // 1/F + + [Ep,Fp] = cosfil_ip(E,F); // E/F + + [PScp1,PScp2] = cosfil_ip(PSc,1); // PSc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 656 + pk: 35 fields: save_id: gallery34 name: Ex9_19 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.19) Demonstration of usefulness of negative PID parameters' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="g_s_cl"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -54844,14 +66944,1866 @@ as="geometry" height="40.0" width="100.0" x="450.0" y="420.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-7dc40e71:146d783a328:-7fa0" parent="-7dc40e71:146d783a328:-7f9f"/></XcosDiagram> media: gallery34.png + script_dump: '// Demonstration of usefulness of negative PID parameters, discussed + in Example 9.17 on page 361. + + // 9.19 + + funcprot(0) + + function Hd=iodelay(H,d) + + if or(size(H.num)<>size(d)) then error(''Dimension mismatch''),end + + Hd=mlist([''rd'',''H'',''iodelay''],H,d) + + endfunction + + + //element wise product overloading functions + + function H=%rd_x_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],H1.H.*H2.H,H1.iodelay+ H2.iodelay) + + endfunction + + function H=%rd_x_r(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],H1.H.*H2,H1.iodelay) + + endfunction + + function H=%r_x_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],H1.*H2.H,H2.iodelay) + + endfunction + + function H=%rd_x_s(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],H1.H.*H2,H1.iodelay) + + endfunction + + function H=%s_x_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],H1.*H2.H,H2.iodelay) + + endfunction + + + //column concatenation overloading functions + + function H=%rd_c_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1.H H2.H],[H1.iodelay,H2.iodelay]) + + endfunction + + function H=%rd_c_r(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1.H H2],[H1.iodelay,zeros(H2.num)]) + + endfunction + + function H=%r_c_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1 H2.H],[zeros(H1.num),H2.iodelay]) + + endfunction + + function H=%rd_c_s(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1.H H2],[H1.iodelay,zeros(H2.num)]) + + endfunction + + function H=%s_c_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1 H2.H],[zeros(H1.num),H2.iodelay]) + + endfunction + + + //row concatenation overloading functions + + function H=%rd_f_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1.H;H2.H],[H1.iodelay;H2.iodelay]) + + endfunction + + function H=%rd_f_r(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1.H;H2],[H1.iodelay;zeros(H2.num)]) + + endfunction + + function H=%r_f_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1;H2.H],[zeros(H1.num);H2.iodelay]) + + endfunction + + function H=%rd_f_s(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1.H;H2],[H1.iodelay;zeros(H2.num)]) + + endfunction + + function H=%s_f_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + H=mlist([''rd'',''H'',''iodelay''],[H1;H2.H],[zeros(H1.num);H2.iodelay]) + + endfunction + + + //matrix product overloading functions + + function H=%rd_m_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + D2=H2.iodelay + + D=D1*D2; + + for k=1;size(D2,2) + + for l=1:size(D1,1) + + d=D1(l,:)+(D2(:,k)'') + + if or(d(1)<>d) then error(''Delays mismatched''),end + + D(l,k)=d + + end + + end + + H=mlist([''rd'',''H'',''iodelay''],H1.H*H2.H,D) + + endfunction + + function H=%rd_m_r(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + for l=1:size(D1,1) + + if or(D1(l,1)<>D1(l,:)) then error(''Delays mismatched''),end + + end + + H=mlist([''rd'','''',''iodelay''],H1.H*H2,D1) + + endfunction + + function H=%rd_m_s(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + for l=1:size(D1,1) + + if or(D1(l,1)<>D1(l,:)) then error(''Delays mismatched''),end + + end + + H=mlist([''rd'',''H'',''iodelay''],H1.H*H2,D1) + + endfunction + + function H=%r_m_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D2=H2.iodelay + + for l=1:size(D2,2) + + if or(D2(1,l)<>D2(:,l)) then error(''Delays mismatched''),end + + end + + H=mlist([''rd'',''H'',''iodelay''],H1*H2.H,D2) + + endfunction + + function H=%s_m_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D2=H2.iodelay + + for l=1:size(D2,2) + + if or(D2(1,l)<>D2(:,l)) then error(''Delays mismatched''),end + + end + + H=mlist([''rd'',''H'',''iodelay''],H1*H2.H,D2) + + endfunction + + + //Addition overloading functions + + function H=%rd_a_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + D2=H2.iodelay + + if or(D1<>D2) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1.H+H2.H,D1) + + endfunction + + function H=%rd_a_r(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + if or(D1<>0) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1.H+H2,D1) + + endfunction + + function H=%rd_a_s(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + if or(D1<>0) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1.H+H2,D1) + + endfunction + + function H=%r_a_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D2=H2.iodelay + + if or(D2<>0) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1+H2.H,D2) + + endfunction + + + //Substraction overloading functions + + function H=%rd_a_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + D2=H2.iodelay + + if or(D1<>D2) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1.H-H2.H,D1) + + endfunction + + function H=%rd_a_r(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + if or(D1<>0) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1.H-H2,D1) + + endfunction + + function H=%rd_a_s(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D1=H1.iodelay + + if or(D1<>0) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1.H-H2,D1) + + endfunction + + function H=%r_a_rd(H1,H2) + + // Author: Serge Steer, Copyright INRIA + + D2=H2.iodelay + + if or(D2<>0) then error(''Delay mismatch''),end + + H=mlist([''rd'',''H'',''iodelay''],H1-H2.H,D2) + + endfunction + + + //extraction overloading functions + + function H=%rd_e(varargin) + + // Author: Serge Steer, Copyright INRIA + + H=varargin($) + + Hh= H.H;Hh.num=Hh.num(varargin(1:$-1));Hh.den=Hh.den(varargin(1:$-1)); + + H.H=Hh + + H.iodelay=H.iodelay(varargin(1:$-1)) + + endfunction + + + //insertion overloading functions + + function H=%rd_i_rd(varargin) + + // Author: Serge Steer, Copyright INRIA + + H=varargin($) + + Hfrom=varargin($-1) + + + Hh= H.H + + Hh.num(varargin(1:$-2))=Hfrom.H.num + + Hh.den(varargin(1:$-2))=Hfrom.H.den + + H.H=Hh + + H.iodelay(varargin(1:$-2))=Hfrom.iodelay + + endfunction + + function H=%r_i_rd(varargin) + + // Author: Serge Steer, Copyright INRIA + + H=varargin($) + + Hfrom=varargin($-1) + + + Hh= H.H + + Hh.num(varargin(1:$-2))=Hfrom.num + + Hh.den(varargin(1:$-2))=Hfrom.den + + H.H=Hh + + H.iodelay(varargin(1:$-2))=zeros(Hfrom.num) + + endfunction + + function H=%s_i_rd(varargin) + + // Author: Serge Steer, Copyright INRIA + + H=varargin($) + + Hfrom=varargin($-1) + + + Hh= H.H + + Hh.num(varargin(1:$-2))=Hfrom + + Hh.den(varargin(1:$-2))=ones(Hfrom) + + H.H=Hh + + H.iodelay(varargin(1:$-2))=zeros(Hfrom) + + endfunction + + function H=%rd_i_r(varargin) + + // Author: Serge Steer, Copyright INRIA + + Hh=varargin($) + + Hfrom=varargin($-1) + + Hh.num(varargin(1:$-2))=Hfrom.H.num + + Hh.den(varargin(1:$-2))=Hfrom.H.den + + D=zeros(Hh.num) + + D(varargin(1:$-2))=Hfrom.iodelay + + H=mlist([''rd'',''H'',''iodelay''],Hh,D) + + endfunction + + function H=%rd_i_s(varargin) + + // Author: Serge Steer, Copyright INRIA + + num=varargin($);den=ones(num) + + Hfrom=varargin($-1) + + + num(varargin(1:$-2))=Hfrom.H.num + + den(varargin(1:$-2))=Hfrom.H.den + + D=zeros(num) + + D(varargin(1:$-2))=Hfrom.iodelay + + H=mlist([''rd'',''H'',''iodelay''],rlist(num,den,''c''),D) + + endfunction + + + //transpostion overloading function + + function H=%rd_t(H) + + // Author: Serge Steer, Copyright INRIA + + H.H=H.H'' + + H.iodelay=H.iodelay'' + + endfunction + + + //string overloading function + + function txt=%rd_string(H) + + // Author: Serge Steer, Copyright INRIA + + r=H.H + + N=string(r.num) + + D=string(r.den) + + ln=max(matrix(length(N),2,-1),''r'') + + ld=max(matrix(length(D),2,-1),''r'') + + l=max(ln,ld) + + [m,n]=size(r.num); + + S=emptystr(m,n) + + + kz=find(H.iodelay==0);//zero delay entries + + w=''exp(''+string(-H.iodelay)+''*s)*'';w(kz)=''''; + + + for i=1:m*n + + s=2*i-1:2*i + + pw=part('' '',1:length(w(i))) + + N(s)=pw+part('' '',1:(l(i)-ln(i))/2)+N(s) + + D(s)=pw+part('' '',1:(l(i)-ld(i))/2)+D(s) + + S(i) =w(i)+part(''-'',ones(1,l(i))) + + end + + txt=emptystr(5*m,n); + + txt(1:5:$,:)=N(1:2:$,:) + + txt(2:5:$,:)=N(2:2:$,:) + + txt(3:5:$,:)=S(1:$,:) + + txt(4:5:$,:)=D(1:2:$,:) + + txt(5:5:$,:)=D(2:2:$,:) + + endfunction + + + + //Display overloading function + + function %rd_p(H) + + // Author: Serge Steer, Copyright INRIA + + //used to display rational fraction with complex coefficients + + //The real case is hard coded + + // Copyright INRIA + + T=string(H) + + l=max(length(T),''r'') + + Te=emptystr(size(T,1),1) + + for k=1:size(T,2) + + Te=Te+part(T(:,k),1:l(k)+1)+'' '' + + end + + mprintf("%s\n",Te) + + endfunction + + + + //frequency response computation overloading + + function [frq,repf,splitf]=repfreq(varargin) + + // Author: Serge Steer, Copyright INRIA + + H=varargin(1) + + autolib.repfreq + + if typeof(H)==''rd'' then + + D=H.iodelay + + varargin(1)=H.H + + [frq,repf,splitf]=repfreq(varargin(:)) + + + w=-2*%i*%pi*frq; + + for k=1:size(D,''*'') + + repf(k,:)=repf(k,:).*exp(D(k)*w) + + end + + else + + [frq,repf,splitf]=repfreq(varargin(:)) + + end + + endfunction + + + //bode plot computation overloading + + function bode(varargin) + + // Author: Serge Steer, Copyright INRIA + + H=varargin(1) + + xdesslib.bode + + if typeof(H)==''rd'' then + + if type(varargin($))==10 then //a comment + + cm=varargin($);varagin($)=null() + + else + + cm='''' + + end + + D=H.iodelay + + varargin(1)=H.H + + [frq,repf,splitf]=repfreq(varargin(1:$)) + + w=-2*%i*%pi*frq; + + for k=1:size(D,''*'') + + repf(k,:)=repf(k,:).*exp(D(k)*w) + + end + + bode(frq,repf) + + else + + bode(varargin(:)) + + end + + endfunction + + + //nyquist plot computation overloading + + function nyquist(varargin) + + // Author: Serge Steer, Copyright INRIA + + H=varargin(1) + + xdesslib.nyquist + + if typeof(H)==''rd'' then + + if type(varargin($))==10 then //a comment + + cm=varargin($);varagin($)=null() + + else + + cm='''' + + end + + D=H.iodelay + + varargin(1)=H.H + + [frq,repf,splitf]=repfreq(varargin(1:$)) + + w=-2*%i*%pi*frq; + + for k=1:size(D,''*'') + + repf(k,:)=repf(k,:).*exp(D(k)*w) + + end + + nyquist(frq,repf) + + else + + nyquist(varargin(:)) + + end + + endfunction + + + // Discretizing a tf with delay + + // Exact solution + + // Applicable for a 1st order system + + + // Ref.: pg.287,Digital Control,Prof.Kannan Moudgalya + + + // D: Delay + + // TF: e^(-Ds) OR e^(-Ds) + + // ------------ ------------ (gen.) + + // tau*s + 1 tau*s + a + + + //D = kTs + D'' (gen.) + + // G: TF with delay component + + // G1: TF with zero delay + + // Required because G cannot be directly used in Scilab + + // Coefficients are returned for ascending powers of z^-1 + + + function [B,A,k1] = delc2d(G,G1,Ts) + + D = G.iodelay; + + d = coeff(G1(''den'')); + + if d(1) == 1 + + tau = d(2); + + mu = 1; + + else + + tau = d(2)/d(1); + + mu = 1/d(1); + + end; + + + k = floor(D/Ts); + + Dpri = D - k*Ts; + + Dis = ((%z*(1 - (exp(-(Ts - Dpri)/tau)) ) )+ (exp(-(Ts - Dpri)/tau) - exp(-Ts/tau) + ))/ ((%z^(k+1))*(%z - exp(-Ts/tau))) + + Dis1 = Dis*mu; + + disp(''Warning: Exact discretization of first order system only''); + + k1 = degree(Dis1(''den'')) - degree(Dis1(''num'')); + + B = coeff(Dis1(''num'')); + + A = coeff(Dis1(''den'')); + + B = flip(B); + + A = flip(A); + + endfunction; + + + + + + + + + + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Solution to Aryabhatta''s identity arising in PID controller design, namely + Eq. 9.37 on page 363. + + // 9.20 + + + function [Rc,Sc] = pp_pid(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + dB = length(B) - 1; dA = length(A) - 1; + + [zk,dzk] = zpowk(k); + + [N,dN] = polmul(B,dB,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(A,dA,Delta,dDelta); + + dphi = length(phi)-1; + + [Sc,dSc,R,dR] = xdync(N,dN,D,dD,phi,dphi); + + Rc = convol(R,Delta); + + endfunction; + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + //User defined function + + //Forms a transfer function + + //Scilab: Co efficients are given in increasing power of variable + + //Matlab: Co efficients are given in decreasing power of variable + + //Hence co efficients are flipped here + + + //Input arguments: (1) Numerator co efficients(decreasing order) + + //(2) Denominator co efficients + + //(3) Variable to specify domain + + + // Updated (30-11-06) + + // System is continuous => a is not passed + + // System is discrete => a = -1 + + // System is discretized (sampled system) => a = Ts + + // Uses syslin + + + function trfu = tf(num,den,a) + + if argn(2) == 2 + + d = ''c''; + + elseif a == -1 + + d = ''d''; + + else + + d = a + + end; + + num = clean(num); + + den = clean(den); + + num1 = poly(num(length(num):-1:1),''x'',''coeff''); + + den1 = poly(den(length(den):-1:1),''x'',''coeff''); + + trfu = syslin(d,num1,den1); + + endfunction; + + + + + // 10.5 + + function b = flip(a) + + b = a(length(a):-1:1); + + endfunction; + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // Discretize the continuous plant + + num = 1; den = [2 1]; tau = 0.5; + + G1 = tf(num,den); + + G = iodelay(G1,tau); + + Ts = 0.5; + + [B,A,k] = delc2d(G,G1,Ts); + + + // Specify transient requirements + + epsilon = 0.05; rise = 5; + + phi = desired(Ts,rise,epsilon); + + + // Design the controller + + Delta = [1 -1]; + + [Rc,Sc] = pp_pid(B,A,k,phi,Delta); + + + // parameters for simulation using g_s_cl + + Tc = Sc; gamm = 1; N = 1; + + C = 0; D = 1; N_var = 0; + + st = 1; t_init = 0; t_final = 20; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // N/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D + + Num = numer(G1); + + Den = denom(G1);' - model: saveAPI.gallery - pk: 657 + pk: 36 fields: save_id: gallery35 name: Ex9_1_1 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.1) Pole placement controller for magnetically suspended ball problem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="basic"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -57029,14 +70981,1171 @@ as="geometry" height="40.0" width="50.0" x="530.0" y="290.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-64ce6d85:145ef6f2b4f:-7f9f" parent="-64ce6d85:145ef6f2b4f:-7f9e"/></XcosDiagram> media: gallery35.png + script_dump: '// Pole placement controller for magnetically suspended ball problem, + discussed in Example 9.3 on page 331. + + // 9.1 + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.2. + + // 9.3 + + // function [goodpoly,badpoly] = polsplit2(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. + + // Input is a polynomial in increasing degree of z^{-1} + + // Optional input is a, where a <= 1. + + // Factor that has roots of z^{-1} outside a is called + + // good and the rest bad. + + // If a is not specified, it will be assumed as 1-1.0e-5 + + + function [goodpoly,badpoly] = polsplit2(fac,a) + + if argn(2) == 1, a = 1-1.0e-5; end + + if a>1 error(''good polynomial is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts1 = roots(fac1); + + rts = rts1(length(rts1):-1:1); + + + // extract good and bad roots + + badindex = find(abs(rts)>=a); // mtlb_find has been replaced by find + + badpoly = coeff(poly((rts(badindex)),"z","roots")); + + goodindex = find(abs(rts)<a); // mtlb_find has been replaced by find + + goodpoly = coeff(poly(rts(goodindex),"z","roots")); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad1 = goodbad(length(goodbad):-1:1);//-- + + factor1 = fac(index)/goodbad1(index);//-- + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // Design of 2-DOF pole placement controller, as discussed in Sec. 9.2. + + // 9.5 + + + // function [Rc,Sc,Tc,gamma] = pp_basic(B,A,k,phi) + + // calculates pole placement controller + + + + function [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit2(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit2(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dphi = length(phi) - 1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,Ab,dAb,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,R1); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Magnetically suspended ball problem + + // Operating conditions + + M = 0.05; L = 0.01; R = 1; K = 0.0001; g = 9.81; + + + //Equilibrium conditions + + hs = 0.01; is = sqrt(M*g*hs/K); + + + // State space matrices + + a21 = K*is^2/M/hs^2; a23 = - 2*K*is/M/hs; a33 = - R/L; + + b3 = 1/L; + + a1 = [0 1 0; a21 0 a23; 0 0 a33]; + + b1 = [0; 0; b3]; c1 = [1 0 0]; d1 = 0; + + + // Transfer functions + + G = syslin(''c'',a1,b1,c1,d1); Ts = 0.01; + + [B,A,k] = myc2d(G,Ts); + + + //polynomials are returned + + [Ds,num,den] = ss2tf(G); + + num = clean(num); den = clean(den); + + + // Transient specifications + + rise = 0.15; epsilon = 0.05; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi); + + + // Setting up simulation parameters for basic.xcos + + st = 0.0001; // desired change in h, in m. + + t_init = 0; // simulation start time + + t_final = 0.5; // simulation end time + + + // Setting up simulation parameters for c_ss_cl.xcos + + N_var = 0; xInitial = [0 0 0]; N = 1; C = 0; D = 1; + + + [Tc1,Rc1] = cosfil_ip(Tc,Rc); // Tc/Rc + + [Sc2,Rc2] = cosfil_ip(Sc,Rc); // Sc/Rc + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 658 + pk: 37 fields: save_id: gallery36 name: Ex9_1_2 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.1) Pole placement controller for magnetically suspended ball problem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="Ex9_1_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -59365,14 +74474,1171 @@ as="geometry" height="40.0" width="60.0" x="560.0" y="230.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="3844e477:143914d2fde:-7fa0" parent="3844e477:143914d2fde:-7f9f"/></XcosDiagram> media: gallery36.png + script_dump: '// Pole placement controller for magnetically suspended ball problem, + discussed in Example 9.3 on page 331. + + // 9.1 + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.2. + + // 9.3 + + // function [goodpoly,badpoly] = polsplit2(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. + + // Input is a polynomial in increasing degree of z^{-1} + + // Optional input is a, where a <= 1. + + // Factor that has roots of z^{-1} outside a is called + + // good and the rest bad. + + // If a is not specified, it will be assumed as 1-1.0e-5 + + + function [goodpoly,badpoly] = polsplit2(fac,a) + + if argn(2) == 1, a = 1-1.0e-5; end + + if a>1 error(''good polynomial is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts1 = roots(fac1); + + rts = rts1(length(rts1):-1:1); + + + // extract good and bad roots + + badindex = find(abs(rts)>=a); // mtlb_find has been replaced by find + + badpoly = coeff(poly((rts(badindex)),"z","roots")); + + goodindex = find(abs(rts)<a); // mtlb_find has been replaced by find + + goodpoly = coeff(poly(rts(goodindex),"z","roots")); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad1 = goodbad(length(goodbad):-1:1);//-- + + factor1 = fac(index)/goodbad1(index);//-- + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // Design of 2-DOF pole placement controller, as discussed in Sec. 9.2. + + // 9.5 + + + // function [Rc,Sc,Tc,gamma] = pp_basic(B,A,k,phi) + + // calculates pole placement controller + + + + function [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit2(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit2(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dphi = length(phi) - 1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,Ab,dAb,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,R1); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Magnetically suspended ball problem + + // Operating conditions + + M = 0.05; L = 0.01; R = 1; K = 0.0001; g = 9.81; + + + //Equilibrium conditions + + hs = 0.01; is = sqrt(M*g*hs/K); + + + // State space matrices + + a21 = K*is^2/M/hs^2; a23 = - 2*K*is/M/hs; a33 = - R/L; + + b3 = 1/L; + + a1 = [0 1 0; a21 0 a23; 0 0 a33]; + + b1 = [0; 0; b3]; c1 = [1 0 0]; d1 = 0; + + + // Transfer functions + + G = syslin(''c'',a1,b1,c1,d1); Ts = 0.01; + + [B,A,k] = myc2d(G,Ts); + + + //polynomials are returned + + [Ds,num,den] = ss2tf(G); + + num = clean(num); den = clean(den); + + + // Transient specifications + + rise = 0.15; epsilon = 0.05; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi); + + + // Setting up simulation parameters for basic.xcos + + st = 0.0001; // desired change in h, in m. + + t_init = 0; // simulation start time + + t_final = 0.5; // simulation end time + + + // Setting up simulation parameters for c_ss_cl.xcos + + N_var = 0; xInitial = [0 0 0]; N = 1; C = 0; D = 1; + + + [Tc1,Rc1] = cosfil_ip(Tc,Rc); // Tc/Rc + + [Sc2,Rc2] = cosfil_ip(Sc,Rc); // Sc/Rc + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 659 + pk: 38 fields: save_id: gallery37 name: Ex9_21_1 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.21) DC motor with PID control tuned through pole placement technique' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="Ex9_21_1"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -61920,14 +78186,1121 @@ as="geometry" height="40.0" width="40.0" x="460.0" y="360.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-75a601dc:14604d880d0:-7ffd" parent="-75a601dc:14604d880d0:-7ffc"/></XcosDiagram> media: gallery37.png + script_dump: '// DC motor with PID control, tuned through pole placement technique, + as in Example 9.18. + + // 9.21 + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Solution to Aryabhatta''s identity arising in PID controller design, namely + Eq. 9.37 on page 363. + + // 9.20 + + + function [Rc,Sc] = pp_pid(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + dB = length(B) - 1; dA = length(A) - 1; + + [zk,dzk] = zpowk(k); + + [N,dN] = polmul(B,dB,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(A,dA,Delta,dDelta); + + dphi = length(phi)-1; + + [Sc,dSc,R,dR] = xdync(N,dN,D,dD,phi,dphi); + + Rc = convol(R,Delta); + + endfunction; + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // PD control law from polynomial coefficients, as explained in Sec. 9.8. + + // 9.22 + + + function [K,taud,N] = pd(Rc,Sc,Ts) + + + // Both Rc and Sc have to be degree one polynomials + + + s0 = Sc(1); s1 = Sc(2); + + r1 = Rc(2); + + K = (s0+s1)/(1+r1); + + N = (s1-s0*r1)/r1/(s0+s1); + + taudbyN = -Ts*r1/(1+r1); + + taud = taudbyN * N; + + endfunction; + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // Motor control problem + + // Transfer function + + + a = [-1 0; 1 0]; b = [1; 0]; c = [0 1]; d = 0; + + G = syslin(''c'',a,b,c,d); Ts = 0.25; + + [B,A,k] = myc2d(G,Ts); + + [Ds,num,den] = ss2tf(G); + + + // Transient specifications + + rise = 3; epsilon = 0.05; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + Delta = 1; //No internal model of step used + + [Rc,Sc] = pp_pid(B,A,k,phi,Delta); + + + // continuous time controller + + [K,taud,N] = pd(Rc,Sc,Ts); + + numb = K*[1 taud*(1+1/N)]; denb = [1 taud/N]; + + numf = 1; denf = 1; + + + // simulation parameters + + st = 1; // desired change in position + + t_init = 0; // simulation start time + + t_final = 20; // simulation end time + + st1 = 0; + + + // continuous controller simulation: g_s_cl3.xcos + + num1 = 0; den1 = 1; + + + // discrete controller simulation: g_s_cl2.xcos + + // u1: -0.1 to 0.8 + + // y1: 0 to 1.4 + + C = 0; D = 1; N = 1; gamm = 1; Tc = Sc; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // N/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D + + Numb = polyno(numb,''s''); + + Denb = polyno(denb,''s''); + + Numf = polyno(numf,''s''); + + Denf = polyno(denf,''s''); + + Num1 = polyno(num1,''s''); + + Den1 = polyno(den1,''s'');' - model: saveAPI.gallery - pk: 660 + pk: 39 fields: save_id: gallery38 name: Ex9_21_2 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.21) DC motor with PID control tuned through pole placement technique' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="Ex9_21_2"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -64457,14 +81830,1121 @@ x="540.0" y="210.0"/><mxPoint as="targetPoint" x="570.0" y="210.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="7b254bcc:14613988545:-7cfe" parent="7b254bcc:14613988545:-7cfd"/></XcosDiagram> media: gallery38.png + script_dump: '// DC motor with PID control, tuned through pole placement technique, + as in Example 9.18. + + // 9.21 + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Solution to Aryabhatta''s identity arising in PID controller design, namely + Eq. 9.37 on page 363. + + // 9.20 + + + function [Rc,Sc] = pp_pid(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + dB = length(B) - 1; dA = length(A) - 1; + + [zk,dzk] = zpowk(k); + + [N,dN] = polmul(B,dB,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(A,dA,Delta,dDelta); + + dphi = length(phi)-1; + + [Sc,dSc,R,dR] = xdync(N,dN,D,dD,phi,dphi); + + Rc = convol(R,Delta); + + endfunction; + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // PD control law from polynomial coefficients, as explained in Sec. 9.8. + + // 9.22 + + + function [K,taud,N] = pd(Rc,Sc,Ts) + + + // Both Rc and Sc have to be degree one polynomials + + + s0 = Sc(1); s1 = Sc(2); + + r1 = Rc(2); + + K = (s0+s1)/(1+r1); + + N = (s1-s0*r1)/r1/(s0+s1); + + taudbyN = -Ts*r1/(1+r1); + + taud = taudbyN * N; + + endfunction; + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // Motor control problem + + // Transfer function + + + a = [-1 0; 1 0]; b = [1; 0]; c = [0 1]; d = 0; + + G = syslin(''c'',a,b,c,d); Ts = 0.25; + + [B,A,k] = myc2d(G,Ts); + + [Ds,num,den] = ss2tf(G); + + + // Transient specifications + + rise = 3; epsilon = 0.05; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + Delta = 1; //No internal model of step used + + [Rc,Sc] = pp_pid(B,A,k,phi,Delta); + + + // continuous time controller + + [K,taud,N] = pd(Rc,Sc,Ts); + + numb = K*[1 taud*(1+1/N)]; denb = [1 taud/N]; + + numf = 1; denf = 1; + + + // simulation parameters + + st = 1; // desired change in position + + t_init = 0; // simulation start time + + t_final = 20; // simulation end time + + st1 = 0; + + + // continuous controller simulation: g_s_cl3.xcos + + num1 = 0; den1 = 1; + + + // discrete controller simulation: g_s_cl2.xcos + + // u1: -0.1 to 0.8 + + // y1: 0 to 1.4 + + C = 0; D = 1; N = 1; gamm = 1; Tc = Sc; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // N/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D + + Numb = polyno(numb,''s''); + + Denb = polyno(denb,''s''); + + Numf = polyno(numf,''s''); + + Denf = polyno(denf,''s''); + + Num1 = polyno(num1,''s''); + + Den1 = polyno(den1,''s'');' - model: saveAPI.gallery - pk: 661 + pk: 40 fields: save_id: gallery39 name: basic_disc description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.7) Simulation of closed loop system with an unstable controller' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1000.0" title="basic_disc"><!--Xcos - 1.0 - scilab-5.5.2 @@ -66643,14 +85123,1179 @@ scilabClass="ScilabList"><mxPoint x="750.0" y="290.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-7476484f:145f8cd2a3c:-7f9e" parent="-7476484f:145f8cd2a3c:-7f9d"/></XcosDiagram> media: gallery39.png + script_dump: '// Simulation of closed loop system with an unstable controller, + as discussed in Example 9.5 on page 335. + + // 9.7 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.2. + + // 9.3 + + // function [goodpoly,badpoly] = polsplit2(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. + + // Input is a polynomial in increasing degree of z^{-1} + + // Optional input is a, where a <= 1. + + // Factor that has roots of z^{-1} outside a is called + + // good and the rest bad. + + // If a is not specified, it will be assumed as 1-1.0e-5 + + + function [goodpoly,badpoly] = polsplit2(fac,a) + + if argn(2) == 1, a = 1-1.0e-5; end + + if a>1 error(''good polynomial is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts1 = roots(fac1); + + rts = rts1(length(rts1):-1:1); + + + // extract good and bad roots + + badindex = find(abs(rts)>=a); // mtlb_find has been replaced by find + + badpoly = coeff(poly((rts(badindex)),"z","roots")); + + goodindex = find(abs(rts)<a); // mtlb_find has been replaced by find + + goodpoly = coeff(poly(rts(goodindex),"z","roots")); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad1 = goodbad(length(goodbad):-1:1);//-- + + factor1 = fac(index)/goodbad1(index);//-- + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Design of 2-DOF pole placement controller, as discussed in Sec. 9.2. + + // 9.5 + + + // function [Rc,Sc,Tc,gamma] = pp_basic(B,A,k,phi) + + // calculates pole placement controller + + + + function [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit2(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit2(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dphi = length(phi) - 1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,Ab,dAb,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,R1); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + + Ts = 1; B = [1 -3]; A = [1 2 -8]; k = 1; + + // Since k=1, tf is of the form z^-1 + + [zk,dzk] = zpowk(k); // int1 = 0;//---- int1 + + + // Transient specifications + + rise = 10; epsilon = 0.1; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi); + + + // simulation parameters for basic_disc.xcos + + //While simulating for t_final = 100, set the limit of Y axis of each scope + + //u1: -0.2 to 3 + + //y1: -0.1 to 1.2 + + st = 1.0; // Desired change in setpoint + + t_init = 0; // Simulation start time + + t_final = 1000; // Simulation end time + + + // Simulation parameters for stb_disc.xcos + + N_var = 0; C = 0; D = 1; N = 1; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D + + + [Tcp,Rcp] = cosfil_ip(Tc,Rc); // Tc/Rc + + [Scp_b,Rcp_b] = cosfil_ip(Sc,Rc); // Sc/Rc' - model: saveAPI.gallery - pk: 662 + pk: 41 fields: save_id: gallery40 name: stb_disc description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.7) Simulation of closed loop system with an unstable controller' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="stb_disc"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -68994,15 +88639,1180 @@ x="370.0" y="140.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-7476484f:145f8cd2a3c:-7be9" parent="-7476484f:145f8cd2a3c:-7be8"/></XcosDiagram> media: gallery40.png + script_dump: '// Simulation of closed loop system with an unstable controller, + as discussed in Example 9.5 on page 335. + + // 9.7 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.2. + + // 9.3 + + // function [goodpoly,badpoly] = polsplit2(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. + + // Input is a polynomial in increasing degree of z^{-1} + + // Optional input is a, where a <= 1. + + // Factor that has roots of z^{-1} outside a is called + + // good and the rest bad. + + // If a is not specified, it will be assumed as 1-1.0e-5 + + + function [goodpoly,badpoly] = polsplit2(fac,a) + + if argn(2) == 1, a = 1-1.0e-5; end + + if a>1 error(''good polynomial is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts1 = roots(fac1); + + rts = rts1(length(rts1):-1:1); + + + // extract good and bad roots + + badindex = find(abs(rts)>=a); // mtlb_find has been replaced by find + + badpoly = coeff(poly((rts(badindex)),"z","roots")); + + goodindex = find(abs(rts)<a); // mtlb_find has been replaced by find + + goodpoly = coeff(poly(rts(goodindex),"z","roots")); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad1 = goodbad(length(goodbad):-1:1);//-- + + factor1 = fac(index)/goodbad1(index);//-- + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Design of 2-DOF pole placement controller, as discussed in Sec. 9.2. + + // 9.5 + + + // function [Rc,Sc,Tc,gamma] = pp_basic(B,A,k,phi) + + // calculates pole placement controller + + + + function [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit2(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit2(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dphi = length(phi) - 1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,Ab,dAb,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,R1); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + + Ts = 1; B = [1 -3]; A = [1 2 -8]; k = 1; + + // Since k=1, tf is of the form z^-1 + + [zk,dzk] = zpowk(k); // int1 = 0;//---- int1 + + + // Transient specifications + + rise = 10; epsilon = 0.1; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + [Rc,Sc,Tc,gamm] = pp_basic(B,A,k,phi); + + + // simulation parameters for basic_disc.xcos + + //While simulating for t_final = 100, set the limit of Y axis of each scope + + //u1: -0.2 to 3 + + //y1: -0.1 to 1.2 + + st = 1.0; // Desired change in setpoint + + t_init = 0; // Simulation start time + + t_final = 1000; // Simulation end time + + + // Simulation parameters for stb_disc.xcos + + N_var = 0; C = 0; D = 1; N = 1; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Rcp1,Rcp2] = cosfil_ip(1,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Bp,Ap] = cosfil_ip(B,A); // B/A + + [zkp1,zkp2] = cosfil_ip(zk,1); // zk/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D + + + [Tcp,Rcp] = cosfil_ip(Tc,Rc); // Tc/Rc + + [Scp_b,Rcp_b] = cosfil_ip(Sc,Rc); // Sc/Rc' - model: saveAPI.gallery - pk: 663 + pk: 42 fields: save_id: gallery41 name: Ex9_9 description: 'Digital Control (Author: K. M. Moudgalya), 9) Pole Placement Controllers, 9.9) Pole placement controller with internal model of a step for the magnetically suspended ball problem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2048 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="Ex9_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20150331 @@ -71289,15 +92099,1157 @@ x="510.0" y="340.0"/><Array as="points" scilabClass=""><mxPoint x="510.0" y="440.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="3af18dde:16fc1cf9366:-7cf3" parent="3af18dde:16fc1cf9366:-7cf2"/></XcosDiagram> media: gallery41.png + script_dump: '// Pole placement controller, with internal model of a step, for + the magnetically suspended ball problem, as discussed in Example 9.8 on page + 339. + + // 9.9 + + // Calculation of desired closed loop characteristic polynomial, as discussed + in Sec. 7.7. + + // 9.4 + + + // function [phi,dphi] = desired(Ts,rise,epsilon) + + // Based on transient requirements, + + // calculates closed loop characteristic polynomial + + + function [phi,dphi] = desired(Ts,rise,epsilon) + + Nr = rise/Ts; omega = %pi/2/Nr; rho = epsilon^(omega/%pi); + + phi = [1 -2*rho*cos(omega) rho^2]; dphi = length(phi)-1; + + endfunction; + + // Pole placement controller using internal model principle, as discussed in + Sec. 9.4. + + // 9.8 + + + // function [Rc,Sc,Tc,gamma,phit] = pp_im(B,A,k,phi,Delta) + + // Calculates 2-DOF pole placement controller. + + + function [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta) + + + // Setting up and solving Aryabhatta identity + + [Ag,Ab] = polsplit3(A); dAb = length(Ab) - 1; + + [Bg,Bb] = polsplit3(B); dBb = length(Bb) - 1; + + + [zk,dzk] = zpowk(k); + + + [N,dN] = polmul(Bb,dBb,zk,dzk); + + dDelta = length(Delta)-1; + + [D,dD] = polmul(Ab,dAb,Delta,dDelta); + + dphi = length(phi)-1; + + + [S1,dS1,R1,dR1] = xdync(N,dN,D,dD,phi,dphi); + + + // Determination of control law + + Rc = convol(Bg,convol(R1,Delta)); Sc = convol(Ag,S1); + + Tc = Ag; gamm = sum(phi)/sum(Bb); + + endfunction; + + // Discretization of continuous transfer function. The result is numerator and + denominator in powers of z^{-1} and the delay term k. + + // 9.2 + + // function [B,A,k] = myc2d(G,Ts) + + // Produces numerator and denominator of discrete transfer + + // function in powers of z^{-1} + + // G is continuous transfer function; time delays are not allowed + + // Ts is the sampling time, all in consistent time units + + + function [B,A,k] = myc2d(G,Ts) + + H = ss2tf(dscr(G,Ts)); + + num1 = coeff(H(''num'')); + + den1 = coeff(H(''den''));//------------- + + A = den1(length(den1):-1:1); + + num2 = num1(length(num1):-1:1); //flip + + nonzero = find(num1); + + first_nz = nonzero(1); + + B = num2(first_nz:length(num2)); //------------- + + k = length(den1) - length(num1); + + endfunction + + + // Procedure to split a polynomial into good and bad factors, as discussed in + Sec. 9.5. The factors that have roots outside unit circle or with negative real + parts are defined as bad. + + // 9.12 + + + // function [goodpoly,badpoly] = polsplit3(fac,a) + + // Splits a scalar polynomial of z^{-1} into good and bad + + // factors. Input is a polynomial in increasing degree of + + // z^{-1}. Optional input is a, where a <= 1. + + // Factors that have roots outside a circle of radius a or + + // with negative roots will be called bad and the rest + + // good. If a is not specified, it will be assumed as 1. + + + function [goodpoly,badpoly] = polsplit3(fac,a) + + if argn(2) == 1, a = 1; end + + if a>1 error(''good polynomial also is unstable''); end + + fac1 = poly(fac(length(fac):-1:1),''z'',''coeff''); + + rts = roots(fac1); + + rts = rts(length(rts):-1:1); + + + // extract good and bad roots + + badindex = mtlb_find((abs(rts)>=a-1.0e-5)|(real(rts)<-0.05)); + + badpoly = coeff(poly(rts(badindex),''z'')); + + goodindex = mtlb_find((abs(rts)<a-1.0e-5)&(real(rts)>=-0.05)); + + goodpoly = coeff(poly(rts(goodindex),''z'')); + + + // scale by equating the largest terms + + [m,index] = max(abs(fac)); + + goodbad = convol(goodpoly,badpoly); + + goodbad = goodbad(length(goodbad):-1:1); + + factor1 = fac(index)/goodbad(index); + + goodpoly = goodpoly * factor1; + + goodpoly = goodpoly(length(goodpoly):-1:1); + + badpoly = badpoly(length(badpoly):-1:1); + + endfunction; + + // Evaluates z^-k. + + // 9.6 + + + function [zk,dzk] = zpowk(k) + + zk = zeros(1,k+1); zk(1,k+1) = 1; + + dzk = k; + + endfunction + + // function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + // MATLAB FUNCTION rowjoin TO SUPERPOSE TWO POLYNOMIAL + + // MATRICES + + + // H. Kwakernaak, July, 1990 + + + function [P,degP] = rowjoin(P1,degP1,P2,degP2) + + + [rP1,cP1] = polsize(P1,degP1); + + [rP2,cP2] = polsize(P2,degP2); + + if cP1 ~= cP2 + + error(''rowjoin: Inconsistent numbers of columns''); + + end + + + rP = rP1+rP2; cP = cP1; + + if degP1 >= degP2 + + degP = degP1; + + else + + degP = degP2; + + end + + + if isempty(P1) + + P = P2; + + elseif isempty(P2) + + P = P1; + + else + + P = zeros(rP,(degP+1)*cP); + + P(1:rP1,1:(degP1+1)*cP1) = P1; + + P(rP1+1:rP,1:(degP2+1)*cP2) = P2; + + end + + endfunction + + // function [B,degB,A,degA,Y,degY,X,degX] = ... + + // left_prm(N,degN,D,degD,job,gap) + + // + + // does three different things according to integers that ''job'' takes + + // job = 1. + + // this is the default. It is always done for all jobs. + + // -1 -1 -1 + + // Given ND , returns coprime B and A where ND = A B + + // It is enough if one sends the first four input arguments + + // If gap is required to be sent, then one can send either 1 or a null + + // entry for job + + // job = 2. + + // first solve for job = 1 and then solve XA + YB = I + + // job = 3. + + // used in solving XD + YN = C + + // after finding coprime factorization, data are returned + + // + + // convention: the variable with prefix deg stand for degrees + + // of the corresponding polynomial matrices + + // + + // input: + + // N: right fraction numerator polynomial matrix + + // D: right fraction denominator polynomial matrix + + // N and D are not neccessarily coprime + + // gap: variable used to zero entries; default value is 1.0e+8 + + // + + // output + + // b and A are left coprime num. and den. polynomial matrices + + // X and Y are solutions to Aryabhatta identity, only for job = 2 + + + function [B,degB,A,degA,Y,degY,X,degX] = left_prm(N,degN,D,degD,job,gap) + + if argn(2) == 4 | argn(2) == 5 + + gap = 1.0e8 ; + + end + + // pause + + if argn(2) == 4, + + job = 1; end + + [F,degF] = rowjoin(D,degD,N,degN); + + [Frows,Fbcols] = polsize(F,degF); // Fbcols = block columns + + Fcols = Fbcols * (degF+1) ; // actual columns of F + + T1 = [];pr =[];degT1 = 0; T1rows = 0;shft = 0; + + S=F; sel = ones(Frows,1); T1bcols =1; + + abar = (Fbcols + 1):Frows; // a_super_bar of B-C.Chang + + while isempty(T1) | T1rows < Frows - Fbcols + + Srows = Frows*T1bcols; // max actual columns of result + + [T1,T1rows,sel,pr] = ... + + t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap); + + [T1rows,T1cols] = size(T1); + + if T1rows < Frows - Fbcols + + T1 = [T1 zeros(T1rows,Frows)]; + + T1bcols = T1bcols + 1; // max. block columns of result + + degT1 = degT1 + 1; // degree of result + + shft = shft +Fbcols; + + S = seshft(S,F,shft); + + sel = [sel;sel(Srows-Frows+1:Srows)]; + + rowvec = (T1bcols-1)*Frows+(Fbcols+1):T1bcols * Frows; + + abar = [abar rowvec]; // A_super_bar of B-C.chang + + end + + end + + + [B,degB,A,degA] = colsplit(T1,degT1,Fbcols,Frows-Fbcols); + + [B,degB] = clcoef(B,degB); + + B = -B; + + [A,degA] = clcoef(A,degA); + + // pause + + if job == 2 + + S = S(mtlb_logical(sel),:); // columns + + [redSrows,Scols] = size(S); + + C = [eye(Fbcols,Fbcols) zeros(Fbcols,Scols-Fbcols)]; // append with zeros + + T2 = C/S; + + T2 = makezero(T2,gap); + + T2 = move_sci(T2,find(sel),Srows); + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows - Fbcols); + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + elseif job == 3 + + Y = S; + + degY = sel; + + X = degT1; + + degX = Fbcols; + + else + + if job ~= 1 + + error(''Message from left_prm:no legal job number specified'') + + end + + end + + endfunction + + + + + // function [T1,T1rows,sel,pr] = ... + + // t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + // calculates the coefficient matrix T1 + + // redundant row information is kept in sel: redundant rows are marked + + // with zeros. The undeleted rows are marked with ones. + + + function [T1,T1rows,sel,pr] = t1calc(S,Srows,T1,T1rows,sel,pr,Frows,Fbcols,abar,gap) + + b = 1; // vector of primary red.rows + + + while (T1rows < Frows - Fbcols) & or(sel==1) & ~isempty(b) + + S = clean(S); + + b = indep(S(mtlb_logical(sel),:),gap); // send selected rows of S + + if ~isempty(b) + + b = clean(b); + + b = move_sci(b,find(sel),Srows); + + j = length(b); + + while ~(b(j) & or(abar==j)) // pick largest nonzero entry + + j = j-1; // of coeff. belonging to abar + + if ~j + + fprintf(''\nMessage from t1calc, called from left_prm\n\n'') + + error(''Denominator is noninvertible'') + + end + + end + + if ~or(j<pr & pmodulo(pr,Frows) == pmodulo(j,Frows)) // pr(2),pr(1) + + T1 = [T1; b]; // condition is not violated + + T1rows = T1rows +1; // accept this vector + + end // else don''t accept + + pr = [pr; j]; // update prime red row info + + while j <= Srows + + sel(j) = 0; + + j = j + Frows; + + end + + end + + end + + endfunction + + // function b = indep(S,gap) + + // determines the first row that is dependent on the previous rows of S. + + // The coefficients of dependence is returned in b + + function b = indep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + [rows,cols] = size(S); + + ind = 1; + + i = 2; + + eps = 2.2204e-016; + + while ind & i <= rows + + sigma = svd(S(1:i,:)); + + len = length(sigma); + + if(sigma(len)/sigma(1) < (eps*max(i,cols))) + + ind =0; + + else + + shsig = [sigma(2:len);sigma(len)]; + + if or( (sigma ./shsig) > gap) + + ind = 0; + + else + + ind = 1; + + i = i+1; + + end + + end + + + end + + if ind + + b =[]; + + + else + + c = S(i,:)/S(1:i-1,:); + + c = makezero(c,gap); + + b = [-c 1]; + + end + + endfunction + + + // function b = cindep( S,gap) + + // Used in XD + YN = C. All rows except the last of are assumed to + + // be independent. The aim is to check if the last row is dependent on the + + // rest and if so how. The coefficients of dependence are sent in b. + + function b = cindep( S,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + eps = 2.2204e-016; + + [rows,cols] = size(S); + + if rows > cols + + ind = 0; + + else + + sigma = svd(S); + + len = length(sigma); + + if (sigma(len)/sigma(1) <= (eps*max(i,cols))) + + ind = 0; //not independent + + else + + if or(sigma(1:len-1) ./sigma(2:len)>=gap) + + ind = 0; // not dependent + + else + + ind = 1; //independent + + end + + end + + end + + if ind + + b = []; + + else + + b = S(rows,:)/S(1:rows-1,:); + + b = makezero(b,gap); + + end + + endfunction + + + + // function C = seshft(A,B,N) + + //given A and B matrices, returns C = [<-A-> 0 + + // 0 <-B->] with B shifted east by N cols + + + function C = seshft(A,B,N) + + [Arows,Acols] = size(A); + + [Brows,Bcols] = size(B); + + if N >= 0 + + B = [zeros(Brows,N) B]; + + Bcols = Bcols + N; + + elseif N < 0 + + A = [zeros(Arows,abs(N)) A]; + + Acols = Acols +abs(N); + + end + + if Acols < Bcols + + A = [A zeros(Arows,Bcols-Acols)]; + + elseif Acols > Bcols + + B = [B zeros(Brows,Acols-Bcols)]; + + end + + C = [A + + B]; + + endfunction + + // function B = makezero(B,gap) + + // where B is a vector and gap acts as a tolerance + + + function B = makezero(B,gap) + + + if argn(2) == 1 + + gap = 1.0e8; + + end + + temp = B(find(B)); // non zero entries of B + + temp = -gsort(-abs(temp),''g'',''d''); // absolute values sorted in descending + order + + len = length(temp); + + ratio = temp(1:len-1) ./temp(2:len); // each ratio >1 + + min_ind = min(find(ratio>gap)); + + if ~isempty(min_ind) + + our_eps = temp(min_ind+1); + + zeroind = find(abs(B)<=our_eps); + + B(zeroind) = zeros(1,length(zeroind)); + + end + + endfunction + + // function result = move_sci(b,nonred,max_sci) + + // Moves matrix b to matrix result with the information on where to move, + + // decided by the indices of nonred. + + // The matrix result will have as many rows as b has and max number of columns. + + // b is augumented with zeros to have nonred number of columns; + + // The columns of b put into those of result as decided by nonred. + + + function result = move_sci(b,nonred,max_sci) + + [brows,bcols] = size(b); + + b = [b zeros(brows,length(nonred)-bcols)]; + + result = zeros(brows,max_sci); + + result(:,nonred'') = b; + + endfunction + + // colsplit + + // The command + + // [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + // produces two polynomial matrix P1 and P2. P1 consists of the first + + // p1 columns of P and P2 consists of the remaining p2 columns of P. + + + // H. Kwakernaak, July, 1990 + + + + function [P1,degP1,P2,degP2] = colsplit(P,degP,p1,p2) + + + if isempty(P) + + P1 = []; P2 = []; + + degP1 = 0; degP2 = 0; + + return; + + end + + + [rP,cP] = polsize(P,degP); + + if p1 < 0 | p1 > cP | p2 < 0 | p2 > cP | p1+p2 ~= cP + + error(''colsplit: Inconsistent numbers of columns''); + + end + + rP1 = rP; rP2 = rP; cP1 = p1; cP2 = p2; + + degP1= degP; degP2 = degP; + + + if p1 == 0 + + P1 == []; P2 = P; + + elseif p2 == 0 + + P1 = P; P2 = []; + + else + + P1 = zeros(rP1,(degP1+1)*cP1); P2 = zeros(rP2,(degP2+1)*cP2); + + for i = 1:degP+1 + + P1(:,(i-1)*cP1+1:i*cP1) = P(:,(i-1)*cP+1:(i-1)*cP+cP1); + + P2(:,(i-1)*cP2+1:i*cP2) = P(:,(i-1)*cP+cP1+1:i*cP); + + end + + end + + endfunction; + + // H. Kwakernaak, July, 1990 + + // Modified by Kannan Moudgalya in Nov. 1992 + + + function [P,degP] = clcoef(Q,degQ) + + + [rQ,cQ] = polsize(Q,degQ); + + + if and(and(Q==0)) + + P = zeros(rQ,cQ); + + degP = 0; + + else + + P = Q; degP = degQ; rP = rQ; cP = cQ; + + j = degP+1; + + while j >= 0 + + X = P(:,(j-1)*cP+1:j*cP) + + if max(sum(abs(X''))) < (1e-8)*max(sum(abs(P))) + + P = P(:,1:(j-1)*cP); + + degP = degP-1; + + else + + j = 0; + + end + + j = j-1; + + end + + end + + endfunction + + // polmul + + // The command + + // [C,degA] = polmul(A,degA,B,degB) + + // produces the polynomial matrix C that equals the product A*B of the + + // polynomial matrices A and B. + + // + + // H. Kwakernaak, July, 1990 + + + + function [C,degC] = polmul(A,degA,B,degB) + + [rA,cA] = polsize(A,degA); + + [rB,cB] = polsize(B,degB); + + if cA ~= rB + + error(''polmul: Inconsistent dimensions of input matrices''); + + end + + + degC = degA+degB; + + C = []; + + for k = 0:degA+degB + + mi = 0; + + if k-degB > mi + + mi = k-degB; + + end + + ma = degA; + + if k < ma + + ma = k; + + end + + Ck = zeros(rA,cB); + + for i = mi:ma + + Ck = Ck + A(:,i*cA+1:(i+1)*cA)*B(:,(k-i)*cB+1:(k-i+1)*cB); + + end + + C = [C Ck]; + + end + + endfunction + + // function [rQ,cQ] = polsize(Q,degQ) + + // FUNCTION polsize TO DETERMINE THE DIMENSIONS + + // OF A POLYNOMIAL MATRIX + + // + + // H. Kwakernaak, August, 1990 + + + function [rQ,cQ] = polsize(Q,degQ) + + + [rQ,cQ] = size(Q); cQ = cQ/(degQ+1); + + if abs(round(cQ)-cQ) > 1e-6 + + error(''polsize: Degree of input inconsistent with number of columns''); + + else + + cQ = round(cQ); + + end + + endfunction + + // function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + // given coefficient matrix in T1, primary redundant row information sel, + + // solves XD + YN = C + + + // calling order changed on 16 April 2005. Old order: + + // function [B,degB,A,degA,Y,degY,X,degX] = xdync(N,degN,D,degD,C,degC,gap) + + + function [Y,degY,X,degX,B,degB,A,degA] = xdync(N,degN,D,degD,C,degC,gap) + + if argn(2) == 6 + + gap = 1.0e+8; + + end + + + [F,degF] = rowjoin(D,degD,N,degN); + + + [Frows,Fbcols] = polsize(F,degF); //Fbcols = block columns + + + [B,degB,A,degA,S,sel,degT1,Fbcols] = left_prm(N,degN,D,degD,3,gap); + + //if issoln(D,degD,C,degC,B,degB,A,degA) + + [Crows,Ccols] = size(C); + + [Srows,Scols] = size(S); + + S = clean(S); + + S = S(mtlb_logical(sel),:); + + T2 =[]; + + + for i = 1:Crows, + + Saug = seshft(S,C(i,:),0); + + b = cindep(Saug); + + b = move_sci(b,find(sel),Srows); + + T2 =[T2; b]; + + end + + + [X,degX,Y,degY] = colsplit(T2,degT1,Fbcols,Frows-Fbcols); + + + [X,degX] = clcoef(X,degX); + + [Y,degY] = clcoef(Y,degY); + + Y = clean(Y); X = clean(X); + + endfunction + + // Input arguments are co efficients of numerator and denominator + + // polynomials in ascending powers of z^-1 + + + // Scicos/Xcos blocks need input polynomials + + // with positive powers of z + + + function [nume,deno] = cosfil_ip(num,den) + + + [Nn,Nd] = polyno(num,''z''); + + [Dn,Dd] = polyno(den,''z''); + + nume = Nn*Dd; + + deno = Nd*Dn; + + + endfunction; + + + // Updated(1-8-07) + + // Operations: + + // Polynomial definition + + // Flipping of coefficients + + // Variables ------- passed as input argument (either ''s'' or ''z'') + + // Both num and den are used mostly used in scicos files, + + // to get rid of negative powers of z + + + // Polynomials with powers of s need to + + // be flipped only + + + function [polynu,polyde] = polyno(zc,a) + + zc = clean(zc); + + polynu = poly(zc(length(zc):-1:1),a,''coeff''); + + if a == ''z'' + + polyde = %z^(length(zc) - 1); + + else + + polyde = 1; + + end + + + // Scicos(4.1) Filter block shouldn''t have constant/constant + + if type(polynu)==1 & type(polyde)==1 + + if a == ''z'' + + polynu = %z; polyde = %z; + + else + + polynu = %s; polyde = %s; + + end; + + end; + + + endfunction + + // Operating conditions + + M = 0.05; L = 0.01; R = 1; K = 0.0001; g = 9.81; + + + // Equilibrium conditions + + hs = 0.01; is = sqrt(M*g*hs/K); + + + // State space matrices + + a21 = K*is^2/M/hs^2; a23 = - 2*K*is/M/hs; a33 = - R/L; + + b3 = 1/L; + + a1 = [0 1 0; a21 0 a23; 0 0 a33]; + + b1 = [0; 0; b3]; c1 = [1 0 0]; d1 = 0; + + + // Transfer functions + + G = syslin(''c'',a1,b1,c1,d1); Ts = 0.01; [B,A,k] = myc2d(G,Ts); + + + // Transient specifications + + rise = 0.1; epsilon = 0.05; + + phi = desired(Ts,rise,epsilon); + + + // Controller design + + Delta = [1 -1]; //internal model of step used + + [Rc,Sc,Tc,gamm] = pp_im(B,A,k,phi,Delta); + + + // simulation parameters for c_ss_cl.xcos + + st = 0.0001; //desired change in h, in m. + + t_init = 0; // simulation start time + + t_final = 0.5; //simulation end time + + xInitial = [0 0 0]; + + N = 1; C = 0; D = 1; N_var = 0; + + + [Tcp1,Tcp2] = cosfil_ip(Tc,1); // Tc/1 + + [Np,Rcp] = cosfil_ip(N,Rc); // 1/Rc + + [Scp1,Scp2] = cosfil_ip(Sc,1); // Sc/1 + + [Cp,Dp] = cosfil_ip(C,D); // C/D' - model: saveAPI.gallery - pk: 664 + pk: 43 fields: save_id: gallery42 name: ex10_10 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 10) Sinusoidal Steady state Analysis, 10.10) Superposition Source Transformations and Thevenin theorem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ex10_10"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -72053,15 +94005,16 @@ x="760.0" y="120.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="7a2a91ff:134d8462990:-7b80" parent="7a2a91ff:134d8462990:-7b7f"/></XcosDiagram> media: gallery42.png + script_dump: '' - model: saveAPI.gallery - pk: 665 + pk: 44 fields: save_id: gallery43 name: ex10_11 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 10) Sinusoidal Steady state Analysis, 10.11) Superposition Source Transformations and Thevenin theorem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex10_11"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -73014,15 +94967,16 @@ x="910.0" y="230.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="7a2a91ff:134d8462990:-7955" parent="7a2a91ff:134d8462990:-7954"/></XcosDiagram> media: gallery43.png + script_dump: '' - model: saveAPI.gallery - pk: 666 + pk: 45 fields: save_id: gallery44 name: ex10_1 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 10) Sinusoidal Steady state Analysis, 10.1) Forced Response to sinusoidal functions' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="ex10_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -73743,14 +95697,15 @@ x="760.0" y="170.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-1fad1256:134d7ff92c3:-7ffe" parent="-1fad1256:134d7ff92c3:-7ffd"/></XcosDiagram> media: gallery44.png + script_dump: '' - model: saveAPI.gallery - pk: 667 + pk: 46 fields: save_id: gallery45 name: ex10_6 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 10) Sinusoidal Steady state Analysis, 10.6) Impedance' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="ex10_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -74343,14 +96298,15 @@ scilabClass=""><mxPoint x="400.0" y="90.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-1fad1256:134d7ff92c3:-7ef9" parent="-1fad1256:134d7ff92c3:-7ef8"/></XcosDiagram> media: gallery45.png + script_dump: '' - model: saveAPI.gallery - pk: 668 + pk: 47 fields: save_id: gallery46 name: ex10_7 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 10) Sinusoidal Steady state Analysis, 10.7) Nodal and Mesh analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ex10_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20200302--><mxGraphModel @@ -75277,14 +97233,15 @@ as="defaultParent" id="-1fad1256:134d7ff92c3:-7e4a" parent="-1fad1256:134d7ff92c3:-7e49"/><mxPoint as="origin" x="-10.0"/></XcosDiagram> media: gallery46.png + script_dump: '' - model: saveAPI.gallery - pk: 669 + pk: 48 fields: save_id: gallery47 name: ex10_8 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 10) Sinusoidal Steady state Analysis, 10.8) Nodal and Mesh analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.1" title="ex10_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -76388,15 +98345,16 @@ scilabClass=""><mxPoint x="230.0" y="250.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="7a2a91ff:134d8462990:-7ffe" parent="7a2a91ff:134d8462990:-7ffd"/></XcosDiagram> media: gallery47.png + script_dump: '' - model: saveAPI.gallery - pk: 670 + pk: 49 fields: save_id: gallery48 name: ex10_9 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 10) Sinusoidal Steady state Analysis, 10.9) Superposition Source Transformations and Thevenin theorem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ex10_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -77639,14 +99597,15 @@ x="130.0" y="180.0"/><Array as="points" scilabClass=""><mxPoint x="130.0" y="240.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="7a2a91ff:134d8462990:-7e88" parent="7a2a91ff:134d8462990:-7e87"/></XcosDiagram> media: gallery48.png + script_dump: '' - model: saveAPI.gallery - pk: 671 + pk: 50 fields: save_id: gallery49 name: ex12_1 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 12) Polyphase Circuits, 12.1) Single phase three wire systems' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ex12_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -78501,14 +100460,15 @@ y="80.0"/><mxPoint x="580.0" y="80.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-10514b51:134e53d5ed9:-7ffe" parent="-10514b51:134e53d5ed9:-7ffd"/></XcosDiagram> media: gallery49.png + script_dump: '' - model: saveAPI.gallery - pk: 672 + pk: 51 fields: save_id: gallery50 name: ex13_7 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 13) Magnetically coupled circuits, 13.7) The Ideal Transformer' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex13_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -79117,14 +101077,15 @@ scilabClass=""><mxPoint x="350.0" y="80.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="26015439:134e2b4e9d8:-7fd9" parent="26015439:134e2b4e9d8:-7fd8"/></XcosDiagram> media: gallery50.png + script_dump: '' - model: saveAPI.gallery - pk: 673 + pk: 52 fields: save_id: gallery51 name: ex17_4 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 17) Two Port Networks, 17.4) Admittance parameters' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex17_4"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -80505,15 +102466,16 @@ x="930.0" y="260.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-536a7494:134d5b6a3e7:-7ffa" parent="-536a7494:134d5b6a3e7:-7ff9"/></XcosDiagram> media: gallery51.png + script_dump: '' - model: saveAPI.gallery - pk: 674 + pk: 53 fields: save_id: gallery52 name: ex18_2 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 18) Fourier Circuit Analysis, 18.2) Complete Response to periodic Forcing Functions' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="6.5" title="ex18_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -81264,15 +103226,16 @@ scilabClass=""><mxPoint x="410.0" y="150.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="f4a86ca:134efd7fc02:-7ffe" parent="f4a86ca:134efd7fc02:-7ffd"/></XcosDiagram> media: gallery52.png + script_dump: '' - model: saveAPI.gallery - pk: 675 + pk: 54 fields: save_id: gallery53 name: ex18_8 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 18) Fourier Circuit Analysis, 18.8) The physical significance of system function' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="ex18_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -81811,14 +103774,15 @@ x="220.0" y="110.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="f4a86ca:134efd7fc02:-7e66" parent="f4a86ca:134efd7fc02:-7e65"/></XcosDiagram> media: gallery53.png + script_dump: '' - model: saveAPI.gallery - pk: 676 + pk: 55 fields: save_id: gallery54 name: ex3_11 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.11) Resistors in series and parallel' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_11"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -82420,14 +104384,15 @@ scilabClass=""><mxPoint x="70.0" y="110.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-3b708aba:134ce795dea:-8000" parent="-3b708aba:134ce795dea:-7fff"/></XcosDiagram> media: gallery54.png + script_dump: '' - model: saveAPI.gallery - pk: 677 + pk: 56 fields: save_id: gallery55 name: ex3_13 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.13) Voltage and Current division' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_13"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -83017,14 +104982,15 @@ x="510.0" y="170.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="73523f48:134cd91c16f:-7c19" parent="73523f48:134cd91c16f:-7c18"/></XcosDiagram> media: gallery55.png + script_dump: '' - model: saveAPI.gallery - pk: 678 + pk: 57 fields: save_id: gallery56 name: ex3_14 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.14) Voltage and Current division' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_14"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -83584,14 +105550,15 @@ as="points" scilabClass=""><mxPoint x="340.0" y="100.0"/></Array></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="73523f48:134cd91c16f:-7cca" parent="73523f48:134cd91c16f:-7cc9"/></XcosDiagram> media: gallery56.png + script_dump: '' - model: saveAPI.gallery - pk: 679 + pk: 58 fields: save_id: gallery57 name: ex3_1 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.1) Kirchoff current law' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -84218,14 +106185,15 @@ as="geometry" height="40.0" width="40.0" x="230.0" y="260.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-3721b5e:1319cfae9ac:-8000" parent="-3721b5e:1319cfae9ac:-7fff"/></XcosDiagram> media: gallery57.png + script_dump: '' - model: saveAPI.gallery - pk: 680 + pk: 59 fields: save_id: gallery58 name: ex3_2 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.2) Kirchoff voltage law' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -84767,14 +106735,15 @@ x="380.0" y="110.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-3721b5e:1319cfae9ac:-7f30" parent="-3721b5e:1319cfae9ac:-7f2f"/></XcosDiagram> media: gallery58.png + script_dump: '' - model: saveAPI.gallery - pk: 681 + pk: 60 fields: save_id: gallery59 name: ex3_3 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.3) Kirchoff voltage law' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_3"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -85368,14 +107337,15 @@ y="280.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-16593537:1319d63fbbf:-7f80" parent="-16593537:1319d63fbbf:-7f7f"/></XcosDiagram> media: gallery59.png + script_dump: '' - model: saveAPI.gallery - pk: 682 + pk: 61 fields: save_id: gallery60 name: ex3_4 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.4) Kirchoff voltage law' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_4"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -86012,14 +107982,15 @@ x="480.0" y="130.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-5fcba885:134ccedce1f:-8000" parent="-5fcba885:134ccedce1f:-7fff"/></XcosDiagram> media: gallery60.png + script_dump: '' - model: saveAPI.gallery - pk: 683 + pk: 62 fields: save_id: gallery61 name: ex3_5 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.5) The Single Loop Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_5"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -86933,14 +108904,15 @@ x="700.0" y="190.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-5fcba885:134ccedce1f:-7cf6" parent="-5fcba885:134ccedce1f:-7cf5"/></XcosDiagram> media: gallery61.png + script_dump: '' - model: saveAPI.gallery - pk: 684 + pk: 63 fields: save_id: gallery62 name: ex3_6 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.6) The single node pair circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -87810,14 +109782,15 @@ x="800.0" y="150.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-5005d4b1:131a4cd73b3:-7eb8" parent="-5005d4b1:131a4cd73b3:-7eb7"/></XcosDiagram> media: gallery62.png + script_dump: '' - model: saveAPI.gallery - pk: 685 + pk: 64 fields: save_id: gallery63 name: ex3_9 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 3) Voltage and Current laws, 3.9) Series and Parallel connected sources' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex3_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -88280,14 +110253,15 @@ x="190.0" y="130.0"/><mxPoint as="targetPoint" x="340.0" y="140.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-5005d4b1:131a4cd73b3:-7f84" parent="-5005d4b1:131a4cd73b3:-7f83"/></XcosDiagram> media: gallery63.png + script_dump: '' - model: saveAPI.gallery - pk: 686 + pk: 65 fields: save_id: gallery64 name: ex4_10 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.10) Mesh analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_10"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -88994,14 +110968,15 @@ width="40.0" x="90.0" y="30.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-5f02711f:131ec3f74c9:-7b98" parent="-5f02711f:131ec3f74c9:-7b97"/></XcosDiagram> media: gallery64.png + script_dump: '' - model: saveAPI.gallery - pk: 687 + pk: 66 fields: save_id: gallery65 name: ex4_11 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.11) The Supermesh' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_11"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -89797,14 +111772,15 @@ as="defaultParent" id="-5f02711f:131ec3f74c9:-7a7c" parent="-5f02711f:131ec3f74c9:-7a7b"/><mxPoint as="origin" x="-6.0" y="-6.0"/></XcosDiagram> media: gallery65.png + script_dump: '' - model: saveAPI.gallery - pk: 688 + pk: 67 fields: save_id: gallery66 name: ex4_12 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.12) The Supermesh' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_12"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -91144,14 +113120,15 @@ x="580.0" y="150.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="5e6a3066:134dff9ba34:-7ffe" parent="5e6a3066:134dff9ba34:-7ffd"/></XcosDiagram> media: gallery66.png + script_dump: '' - model: saveAPI.gallery - pk: 689 + pk: 68 fields: save_id: gallery67 name: ex4_1 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.1) Nodal analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -91806,14 +113783,15 @@ width="40.0" x="100.0" y="10.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-16b82e93:131e810ab25:-8000" parent="-16b82e93:131e810ab25:-7fff"/></XcosDiagram> media: gallery67.png + script_dump: '' - model: saveAPI.gallery - pk: 690 + pk: 69 fields: save_id: gallery68 name: ex4_2 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.2) Nodal analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -93108,14 +115086,15 @@ width="40.0" x="60.0" y="10.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-16b82e93:131e810ab25:-7f1e" parent="-16b82e93:131e810ab25:-7f1d"/></XcosDiagram> media: gallery68.png + script_dump: '' - model: saveAPI.gallery - pk: 691 + pk: 70 fields: save_id: gallery69 name: ex4_5 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.5) The supernode' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_5"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -93949,14 +115928,15 @@ width="40.0" x="70.0" y="10.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-5f02711f:131ec3f74c9:-8000" parent="-5f02711f:131ec3f74c9:-7fff"/></XcosDiagram> media: gallery69.png + script_dump: '' - model: saveAPI.gallery - pk: 692 + pk: 71 fields: save_id: gallery70 name: ex4_6 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.6) The supernode' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -96016,14 +117996,15 @@ x="720.0" y="230.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="5e6a3066:134dff9ba34:-7e89" parent="5e6a3066:134dff9ba34:-7e88"/></XcosDiagram> media: gallery70.png + script_dump: '' - model: saveAPI.gallery - pk: 693 + pk: 72 fields: save_id: gallery71 name: ex4_7 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.7) Mesh analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -96726,14 +118707,15 @@ width="40.0" x="50.0" y="10.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-5f02711f:131ec3f74c9:-7da1" parent="-5f02711f:131ec3f74c9:-7da0"/></XcosDiagram> media: gallery71.png + script_dump: '' - model: saveAPI.gallery - pk: 694 + pk: 73 fields: save_id: gallery72 name: ex4_8 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.8) Mesh analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -97807,14 +119789,15 @@ width="40.0" x="70.0" y="20.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-5f02711f:131ec3f74c9:-7c8d" parent="-5f02711f:131ec3f74c9:-7c8c"/></XcosDiagram> media: gallery72.png + script_dump: '' - model: saveAPI.gallery - pk: 695 + pk: 74 fields: save_id: gallery73 name: ex4_9 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 4) Basic Nodal and Mesh Analysis, 4.9) Mesh analysis' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex4_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -98467,15 +120450,16 @@ width="40.0" x="70.0" y="20.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-5f02711f:131ec3f74c9:-7e53" parent="-5f02711f:131ec3f74c9:-7e52"/></XcosDiagram> media: gallery73.png + script_dump: '' - model: saveAPI.gallery - pk: 696 + pk: 75 fields: save_id: gallery74 name: ex6_11 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.11) Thevenin and Norton Equivalent circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_11"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -98977,15 +120961,16 @@ x="320.0" y="100.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="2602728:132d47c9ecc:-8000" parent="2602728:132d47c9ecc:-7fff"/></XcosDiagram> media: gallery74.png + script_dump: '' - model: saveAPI.gallery - pk: 697 + pk: 76 fields: save_id: gallery75 name: ex6_13 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.13) Thevenin and Norton Equivalent circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_13"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -99749,15 +121734,16 @@ x="780.0" y="240.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="2602728:132d47c9ecc:-7f5b" parent="2602728:132d47c9ecc:-7f5a"/></XcosDiagram> media: gallery75.png + script_dump: '' - model: saveAPI.gallery - pk: 698 + pk: 77 fields: save_id: gallery76 name: ex6_14 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.14) Thevenin and Norton Equivalent circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_14"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -100771,15 +122757,16 @@ x="400.0" y="44.0"/><mxPoint as="targetPoint" x="400.0" y="70.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-1f470ada:134d070a228:-7f33" parent="-1f470ada:134d070a228:-7f32"/></XcosDiagram> media: gallery76.png + script_dump: '' - model: saveAPI.gallery - pk: 699 + pk: 78 fields: save_id: gallery77 name: ex6_15 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.15) Thevenin and Norton Equivalent circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_15"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -101321,15 +123308,16 @@ x="370.0" y="124.0"/><mxPoint as="targetPoint" x="370.0" y="150.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-1f470ada:134d070a228:-8000" parent="-1f470ada:134d070a228:-7fff"/></XcosDiagram> media: gallery77.png + script_dump: '' - model: saveAPI.gallery - pk: 700 + pk: 79 fields: save_id: gallery78 name: ex6_16 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.16) Maximum power transfer' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_16"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -102616,15 +124604,16 @@ as="defaultParent" id="6611b517:134eb867750:-7b61" parent="6611b517:134eb867750:-7b60"/><mxPoint as="origin" x="-2.5"/></XcosDiagram> media: gallery78.png + script_dump: '' - model: saveAPI.gallery - pk: 701 + pk: 80 fields: save_id: gallery79 name: ex6_1 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.1) The Superposition principle' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -103349,15 +125338,16 @@ as="sourcePoint" x="566.0" y="190.0"/><mxPoint as="targetPoint" x="550.0" y="190.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-5872192d:1324f245276:-8000" parent="-5872192d:1324f245276:-7fff"/></XcosDiagram> media: gallery79.png + script_dump: '' - model: saveAPI.gallery - pk: 702 + pk: 81 fields: save_id: gallery80 name: ex6_20 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.20) Compensation Theorem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ex6_20"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -104055,15 +126045,16 @@ x="570.0" y="100.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="6611b517:134eb867750:-7ffe" parent="6611b517:134eb867750:-7ffd"/></XcosDiagram> media: gallery80.png + script_dump: '' - model: saveAPI.gallery - pk: 703 + pk: 82 fields: save_id: gallery81 name: ex6_21 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.21) Compensation Theorem' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_21"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -104879,15 +126870,16 @@ y="180.0"/><mxPoint x="560.0" y="180.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="6611b517:134eb867750:-7ec6" parent="6611b517:134eb867750:-7ec5"/></XcosDiagram> media: gallery81.png + script_dump: '' - model: saveAPI.gallery - pk: 704 + pk: 83 fields: save_id: gallery82 name: ex6_23 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.23) Source Transformations' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_23"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -105436,15 +127428,16 @@ x="490.0" y="130.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="6611b517:134eb867750:-7be7" parent="6611b517:134eb867750:-7be6"/></XcosDiagram> media: gallery82.png + script_dump: '' - model: saveAPI.gallery - pk: 705 + pk: 84 fields: save_id: gallery83 name: ex6_24 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.24) Source Transformations' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_24"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -106624,15 +128617,16 @@ scilabClass="ScilabList"><mxPoint x="210.0" y="200.0"/><mxPoint x="210.0" y="120.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="6611b517:134eb867750:-7d3e" parent="6611b517:134eb867750:-7d3d"/></XcosDiagram> media: gallery83.png + script_dump: '' - model: saveAPI.gallery - pk: 706 + pk: 85 fields: save_id: gallery84 name: ex6_3 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.3) The Superposition principle' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_3"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -107489,15 +129483,16 @@ x="710.0" y="44.0"/><mxPoint as="targetPoint" x="710.0" y="60.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-5872192d:1324f245276:-7ee4" parent="-5872192d:1324f245276:-7ee3"/></XcosDiagram> media: gallery84.png + script_dump: '' - model: saveAPI.gallery - pk: 707 + pk: 86 fields: save_id: gallery85 name: ex6_4 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.4) The Superposition principle' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_4"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -108314,15 +130309,16 @@ y="120.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-5872192d:1324f245276:-7d2f" parent="-5872192d:1324f245276:-7d2e"/></XcosDiagram> media: gallery85.png + script_dump: '' - model: saveAPI.gallery - pk: 708 + pk: 87 fields: save_id: gallery86 name: ex6_5 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.5) The Superposition principle' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_5"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -108996,15 +130992,16 @@ x="570.0" y="70.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-5872192d:1324f245276:-7c11" parent="-5872192d:1324f245276:-7c10"/></XcosDiagram> media: gallery86.png + script_dump: '' - model: saveAPI.gallery - pk: 709 + pk: 88 fields: save_id: gallery87 name: ex6_6 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.6) The Superposition principle' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -109867,15 +131864,16 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="40.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="-5872192d:1324f245276:-7b3d" parent="-5872192d:1324f245276:-7b3c"/></XcosDiagram> media: gallery87.png + script_dump: '' - model: saveAPI.gallery - pk: 710 + pk: 89 fields: save_id: gallery88 name: ex6_8 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 6) Network Theorems and useful Circuit Analysis Techniques, 6.8) The Superposition principle' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex6_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -110958,14 +132956,15 @@ x="856.0" y="340.0"/><mxPoint as="targetPoint" x="830.0" y="340.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-1ed2b2d8:132d4611bb5:-7f3b" parent="-1ed2b2d8:132d4611bb5:-7f3a"/></XcosDiagram> media: gallery88.png + script_dump: '' - model: saveAPI.gallery - pk: 711 + pk: 90 fields: save_id: gallery89 name: ex7_11 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 7) Capacitors and Inductors, 7.11) Modeling Capacitors and Inductors' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ex7_11"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -111549,14 +133548,15 @@ x="500.0" y="100.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="3a97bac1:134ed06dad1:-7ffe" parent="3a97bac1:134ed06dad1:-7ffd"/></XcosDiagram> media: gallery89.png + script_dump: '' - model: saveAPI.gallery - pk: 712 + pk: 91 fields: save_id: gallery90 name: ex8_10 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 8) Basic RL and RC circuits, 8.10) Driven RC circuits' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="ex8_10"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -112700,14 +134700,15 @@ as="defaultParent" id="75a896ca:134d365eac8:-7b7b" parent="75a896ca:134d365eac8:-7b7a"/><mxPoint as="origin" y="-6.0"/></XcosDiagram> media: gallery90.png + script_dump: '' - model: saveAPI.gallery - pk: 713 + pk: 92 fields: save_id: gallery91 name: ex8_11 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 8) Basic RL and RC circuits, 8.11) Driven RC circuits' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.01" title="ex8_11"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -113316,14 +135317,15 @@ x="340.0" y="186.0"/><mxPoint as="targetPoint" x="340.0" y="120.0"/></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-5e5c20b5:13506c8a689:-8000" parent="-5e5c20b5:13506c8a689:-7fff"/></XcosDiagram> media: gallery91.png + script_dump: '' - model: saveAPI.gallery - pk: 714 + pk: 93 fields: save_id: gallery92 name: ex8_1 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 8) Basic RL and RC circuits, 8.1) The Source free RL Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.001" title="ex8_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -113814,14 +135816,15 @@ x="470.0" y="150.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="77dd482d:134d2cc3c9e:-7f9a" parent="77dd482d:134d2cc3c9e:-7f99"/></XcosDiagram> media: gallery92.png + script_dump: '' - model: saveAPI.gallery - pk: 715 + pk: 94 fields: save_id: gallery93 name: ex8_2 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 8) Basic RL and RC circuits, 8.2) The Source free RL Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0" title="ex8_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20200302--><mxGraphModel @@ -114503,14 +136506,15 @@ y="360.0"/><mxPoint x="70.0" y="360.0"/><mxPoint x="70.0" y="230.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-29171e7b:13894ec359c:-8000" parent="-29171e7b:13894ec359c:-7fff"/></XcosDiagram> media: gallery93.png + script_dump: '' - model: saveAPI.gallery - pk: 716 + pk: 95 fields: save_id: gallery94 name: ex8_3 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 8) Basic RL and RC circuits, 8.3) The Source free RC Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0E-4" title="ex8_3"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -115038,14 +137042,15 @@ x="420.0" y="120.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-7550ec02:134d2eb8d96:-7d27" parent="-7550ec02:134d2eb8d96:-7d26"/></XcosDiagram> media: gallery94.png + script_dump: '' - model: saveAPI.gallery - pk: 717 + pk: 96 fields: save_id: gallery95 name: ex8_4 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 8) Basic RL and RC circuits, 8.4) A more General Perspective' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="1.0E-4" title="ex8_4"><!--Xcos - 1.0 - scilab-5.5.2 - @@ -115783,14 +137788,15 @@ x="114.0" y="170.0"/><mxPoint as="targetPoint" x="170.0" y="170.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-7550ec02:134d2eb8d96:-7c3f" parent="-7550ec02:134d2eb8d96:-7c3e"/></XcosDiagram> media: gallery95.png + script_dump: '' - model: saveAPI.gallery - pk: 718 + pk: 97 fields: save_id: gallery96 name: ex8_8 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 8) Basic RL and RC circuits, 8.8) Natural and Forced Response' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex8_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20200302--><mxGraphModel @@ -116447,14 +138453,15 @@ x="560.0" y="120.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="75a896ca:134d365eac8:-7eb8" parent="75a896ca:134d365eac8:-7eb7"/></XcosDiagram> media: gallery96.png + script_dump: '' - model: saveAPI.gallery - pk: 719 + pk: 98 fields: save_id: gallery97 name: ex9_2 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 9) The RLC Circuit, 9.2) The Overdamped parallel circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.001" title="ex9_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -116991,14 +138998,15 @@ x="470.0" y="90.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="2adc5834:134f2773fd2:-7ffe" parent="2adc5834:134f2773fd2:-7ffd"/></XcosDiagram> media: gallery97.png + script_dump: '' - model: saveAPI.gallery - pk: 720 + pk: 99 fields: save_id: gallery98 name: ex9_3 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 9) The RLC Circuit, 9.3) The Overdamped parallel circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.001" title="ex9_3"><!--Xcos - 1.0 - scilab-5.5.2 - 20200302--><mxGraphModel @@ -117823,14 +139831,15 @@ x="850.0" y="180.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-67b45fed:134f41509ef:-7ffe" parent="-67b45fed:134f41509ef:-7ffd"/></XcosDiagram> media: gallery98.png + script_dump: '' - model: saveAPI.gallery - pk: 721 + pk: 100 fields: save_id: gallery99 name: ex9_6 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 9) The RLC Circuit, 9.6) The Underdamped parallel RLC circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="ex9_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -118327,14 +140336,15 @@ y="130.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-7cfb447d:134ed64a89d:-7ffe" parent="-7cfb447d:134ed64a89d:-7ffd"/></XcosDiagram> media: gallery99.png + script_dump: '' - model: saveAPI.gallery - pk: 722 + pk: 101 fields: save_id: gallery100 name: ex9_7 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 9) The RLC Circuit, 9.7) The Source free series RLC Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.001" title="ex9_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -118909,14 +140919,15 @@ x="440.0" y="110.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-3d3fe24b:134fb5bd9e1:-7d4a" parent="-3d3fe24b:134fb5bd9e1:-7d49"/></XcosDiagram> media: gallery100.png + script_dump: '' - model: saveAPI.gallery - pk: 723 + pk: 102 fields: save_id: gallery101 name: ex9_8 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 9) The RLC Circuit, 9.8) The Source free series RLC Circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="ex9_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -119611,14 +141622,15 @@ x="500.0" y="70.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="1f781c6f:13506286c0b:-7ffe" parent="1f781c6f:13506286c0b:-7ffd"/></XcosDiagram> media: gallery101.png + script_dump: '' - model: saveAPI.gallery - pk: 724 + pk: 103 fields: save_id: gallery102 name: ex9_9 description: 'Engineering Circuit Analysis (Author: W. Hayt, J. Kemmerly And S. Durbin), 9) The RLC Circuit, 9.9) The Complete response of RLC circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 215 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="ex9_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -120272,14 +142284,15 @@ x="600.0" y="180.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="1f781c6f:13506286c0b:-7d57" parent="1f781c6f:13506286c0b:-7d56"/></XcosDiagram> media: gallery102.png + script_dump: '' - model: saveAPI.gallery - pk: 725 + pk: 104 fields: save_id: gallery103 name: Ex6_23 description: 'Electrical Machines (Author: R. K. Srivastava), 6) Synchronous Machines, 6.23) To find maximum value of power angle and maximum value of overshoot' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 2777 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" title="Ex6_23"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 2040--><Array as="context" @@ -120795,14 +142808,116 @@ as="geometry" height="40.0" width="40.0" x="440.0" y="310.0"/></BasicBlock></root></mxGraphModel><mxCell as="defaultParent" id="6521d368:1479034e794:-7fa0" parent="6521d368:1479034e794:-7f9f"/></XcosDiagram> media: gallery103.png + script_dump: ' + + // ELECTRICAL MACHINES + + // R.K.Srivastava + + // First Impression 2011 + + // CENGAGE LEARNING INDIA PVT. LTD + + // CHAPTER : 6 : SYNCHRONOUS MACHINES + + + // EXAMPLE : 6.23 + + + // GIVEN DATA + + + p = 4; // Number of the poles in the Alternator + + f = 50; // Frequency in Hertz + + pkw = 500; // Alternator delivering load in kilo-watts + + pkwinc = 1000; // Generator increases its share of the common + elictrical in kilo-watts + + Kj = 1.5; // Inertia acceleration coefficient for the + combined prime mover-alternator in N-m/elec deg/second square + + Kd = 12; // Damping torque coefficient in N-m/elec deg/second + + delta1 = 9; // Initial value of the Power angle in degree + + + + // CALCULATIONS + + + delta2 = (pkwinc/pkw)*delta1; // Final value (maximum + value) of the Power angle in degree (considering Linear variation) + + ws = (4*%pi*f)/p; // Rotational speed + in Radians per second + + Ts = (pkw*1000)/ws; // Synchornizing + torque at 500kW in N-m + + Ks = Ts/delta1; // Synchornizing + torque cofficient at 500kW in N-m/elec-deg + + // Laplace transform of the swing Equation can be written as :- s^2 + ((Kd/Kj)*s) + + (Ks/Kj) = 0, s^2 + (12/1.5)s + (353.86/1.5) = 0 and compring with the standard + equation s^2 + s(2*zeta*Wn) + Wn^2 = 0 we get:- mentined below (refer page + no. 454 and 455) + + Wn = sqrt(Ks/Kj); // Natural frequency + of oscillations in Radians per second + + fn = Wn/(2*%pi); // Frequency of + natural oscillations in Hertz + + zeta = (1*Kd)/(2*Wn*Kj); // Damping ratio + + Wd = Wn*(sqrt(1-zeta^2)); // Frequency of + damped oscillations in radians/s + + fd = Wd/(2*%pi); // Frequency of + damped oscillations in Hertz + + ts = 5/(zeta*Wn); // Settling time + in second + + deltamax = delta1 + 1.42*(delta2-delta1); // The maximum overshoot + for damping ratio of 0.2604 is about 42% the maximum appoximate value of the + overshoot in terms of 1% tolearance band in Electrical degree + + + + // DISPLAY RESULTS + + + disp("EXAMPLE : 6.23: SOLUTION :-"); + + printf("\n (a.1) Final value (maximum value) of the Power angle (considering + Linear variation), delta2 = %.f degree \n",delta2) + + printf("\n (a.2) Natural frequency of oscillations, Ns = %.2f radians/s \n",Wn) + + printf("\n (a.3) Damping ratio, zeta = %.4f \n",zeta) + + printf("\n (a.4) Frequency of damped oscillations, Wd = %.2f radians/s \n",Wd) + + printf("\n (a.5) Settling time, ts = %.2f seconds \n",ts) + + printf("\n (b) The maximum overshoot for damping ratio of 0.2604 is about + 42 percent the maximum appoximate value of the overshoot in terms of 1 percent + tolearance band is, deltamax = %.2f degree \n",deltamax) + + printf("\n\n FOR CASE (C) CANNOT BE DO IT IN THIS BECAUSE AS IT REQUIRES MATLAB + SIMULINK \n")' - model: saveAPI.gallery - pk: 726 + pk: 105 fields: save_id: gallery104 name: eg12_2 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 12) Simplifying - logical functions, 12.2) Prove the given theorem' - save_time: 2025-01-23 16:04:57+00:00 + logical functions, 12.2) Prove the given theoram' + save_time: 2025-03-17 15:49:08+00:00 book: 293 data_dump: '<?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="4.0" title="eg12_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -122869,15 +144984,16 @@ id="47283b12:1341c9b3c8b:-78f7" parent="47283b12:1341c9b3c8b:-78f6"/><mxPoint as="origin" x="-10.0"/></XcosDiagram>' media: gallery104.png + script_dump: '' - model: saveAPI.gallery - pk: 727 + pk: 106 fields: save_id: gallery105 name: eg12_3a description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 12) Simplifying logical functions, 12.3.a) Design a digital logic circuit that provides logic 1 whenever majority votes yes' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="8.0" title="eg12_3a"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -125999,14 +148115,15 @@ as="geometry" height="40.0" width="40.0" x="520.0" y="200.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="47283b12:1341c9b3c8b:-8000" parent="47283b12:1341c9b3c8b:-7fff"/></XcosDiagram> media: gallery105.png + script_dump: '' - model: saveAPI.gallery - pk: 728 + pk: 107 fields: save_id: gallery106 name: eg12_3b description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 12) Simplifying logical functions, 12.3.b) Modify part A so that only NAND gates are used' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:08+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="8.0" title="eg12_3b"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -129126,14 +151243,15 @@ height="40.0" width="40.0" x="50.0" y="330.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="47283b12:1341c9b3c8b:-7c5b" parent="47283b12:1341c9b3c8b:-7c5a"/></XcosDiagram> media: gallery106.png + script_dump: '' - model: saveAPI.gallery - pk: 729 + pk: 108 fields: save_id: gallery107 name: eg2_10 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 2) The circuit elements, 2.10) Design an opamp circuit solution of the given equation' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg2_10"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -131666,14 +153784,15 @@ x="190.0" y="180.0"/><mxPoint as="targetPoint" x="310.0" y="180.0"/></mxGeometry></ImplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="200893ff:13428736452:-8000" parent="200893ff:13428736452:-7fff"/></XcosDiagram> media: gallery107.png + script_dump: '' - model: saveAPI.gallery - pk: 730 + pk: 109 fields: save_id: gallery108 name: eg3_10 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.10) Find the value of the node pair voltages V1 and V2' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_10"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -132519,14 +154638,15 @@ height="40.0" width="40.0" x="490.0" y="180.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-7b1d" parent="-108078b6:1345b8f2778:-7b1c"/></XcosDiagram> media: gallery108.png + script_dump: '' - model: saveAPI.gallery - pk: 731 + pk: 110 fields: save_id: gallery109 name: eg3_11 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.11) Find the branch current flowing through R2' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: '<?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_11"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -133145,14 +155265,15 @@ height="40.0" width="40.0" x="110.0" y="430.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-79f9" parent="-108078b6:1345b8f2778:-79f8"/></XcosDiagram>' media: gallery109.png + script_dump: '' - model: saveAPI.gallery - pk: 732 + pk: 111 fields: save_id: gallery110 name: eg3_14 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.14) Find the value of the output voltage' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_14"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -133758,14 +155879,15 @@ x="460.0" y="190.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-794d" parent="-108078b6:1345b8f2778:-794c"/></XcosDiagram> media: gallery110.png + script_dump: '' - model: saveAPI.gallery - pk: 733 + pk: 112 fields: save_id: gallery111 name: eg3_15 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.15) Find the current delivered to the source by the network' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_15"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -134438,14 +156560,15 @@ as="geometry" height="40.0" width="40.0" x="270.0" y="280.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-78b9" parent="-108078b6:1345b8f2778:-78b8"/></XcosDiagram> media: gallery111.png + script_dump: '' - model: saveAPI.gallery - pk: 734 + pk: 113 fields: save_id: gallery112 name: eg3_5 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.5) Determine the current which flows through R2' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_5"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -135092,14 +157215,15 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="40.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-8000" parent="-108078b6:1345b8f2778:-7fff"/></XcosDiagram> media: gallery112.png + script_dump: '' - model: saveAPI.gallery - pk: 735 + pk: 114 fields: save_id: gallery113 name: eg3_6 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.6) Find the power dissipation in R1' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -135832,14 +157956,15 @@ as="geometry" height="40.0" width="40.0" x="560.0" y="70.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-7edc" parent="-108078b6:1345b8f2778:-7edb"/></XcosDiagram> media: gallery113.png + script_dump: '' - model: saveAPI.gallery - pk: 736 + pk: 115 fields: save_id: gallery114 name: eg3_7 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.7) Find the current which flows through R2' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -136766,15 +158891,16 @@ width="40.0" x="380.0" y="280.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-7e22" parent="-108078b6:1345b8f2778:-7e21"/></XcosDiagram> media: gallery114.png + script_dump: '' - model: saveAPI.gallery - pk: 737 + pk: 116 fields: save_id: gallery115 name: eg3_9 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 3) Elementary network theory, 3.9) Find the magnitude and direction of each of the branch currents' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="eg3_9"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -137492,15 +159618,16 @@ as="geometry" height="40.0" width="40.0" x="200.0" y="380.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-108078b6:1345b8f2778:-7bff" parent="-108078b6:1345b8f2778:-7bfe"/></XcosDiagram> media: gallery115.png + script_dump: '' - model: saveAPI.gallery - pk: 738 + pk: 117 fields: save_id: gallery116 name: eg5_1 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 5) Circuit dynamics and forced responses, 5.1) Find the expression for the current flowing through the circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="eg5_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -138352,15 +160479,16 @@ x="120.0" y="20.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="7ce57742:133f8596f12:-7f12" parent="7ce57742:133f8596f12:-7f11"/></XcosDiagram> media: gallery116.png + script_dump: '' - model: saveAPI.gallery - pk: 739 + pk: 118 fields: save_id: gallery117 name: eg5_2 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 5) Circuit dynamics and forced responses, 5.2) Find the expression for the current flowing through the circuit and the total energy dissipated in the resistor' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="eg5_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -139101,15 +161229,32 @@ x="344.0" y="140.0"/><mxPoint as="targetPoint" x="420.0" y="140.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="4c3b265:134192dde3e:-7ed0" parent="4c3b265:134192dde3e:-7ecf"/></XcosDiagram> media: gallery117.png + script_dump: 'C = 10*10^-6 ; //capacitance(in farads) + + R = 0.2*10^6; //resistance (in ohms) + + Vi = 40; //initial voltage of the capacitor (in volts) + + Wc = (1/2)*C*Vi^2; //energy stored in the capacitor + + //current flowing in circuit as a function of time i(t) = 2*10^-4*exp(-t/2) + + //power dissipated in the resistor = R*i^2 + + Wr = integrate(''R*4*10^-8*exp(-t)'',''t'',0,100) + + disp(Wc,"energy stored in the capacitor(in Joules) = ") + + disp(Wr,"energy dissipated in the resistor(in Joules) = ")' - model: saveAPI.gallery - pk: 740 + pk: 119 fields: save_id: gallery118 name: eg5_3 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 5) Circuit dynamics and forced responses, 5.3) Determine the voltage which appears across each capacitor at steady state' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="50.0" title="eg5_3"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -140006,15 +162151,16 @@ height="40.0" width="40.0" x="260.0" y="390.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="4c3b265:134192dde3e:-7e2e" parent="4c3b265:134192dde3e:-7e2d"/></XcosDiagram> media: gallery118.png + script_dump: '' - model: saveAPI.gallery - pk: 741 + pk: 120 fields: save_id: gallery119 name: eg5_5 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 5) Circuit dynamics and forced responses, 5.5) Find the complete solution for the charge on the capacitor and show a plot of the response' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="eg5_5"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -140927,15 +163073,16 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="-8.0"/></ImplicitInputPort></root></mxGraphModel><mxCell as="defaultParent" id="4c3b265:134192dde3e:-7d26" parent="4c3b265:134192dde3e:-7d25"/></XcosDiagram> media: gallery119.png + script_dump: '' - model: saveAPI.gallery - pk: 742 + pk: 121 fields: save_id: gallery120 name: eg5_6 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 5) Circuit dynamics and forced responses, 5.6) Describe the dynamic behaviour of the given circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="eg5_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -141790,15 +163937,16 @@ width="40.0" x="230.0" y="360.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="4c3b265:134192dde3e:-7bc3" parent="4c3b265:134192dde3e:-7bc2"/></XcosDiagram> media: gallery120.png + script_dump: '' - model: saveAPI.gallery - pk: 743 + pk: 122 fields: save_id: gallery121 name: eg5_7 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 5) Circuit dynamics and forced responses, 5.7) Obtain the critically damped response for the circuit' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="eg5_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -142650,15 +164798,16 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="40.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="774ef901:13456c50b60:-7ee1" parent="774ef901:13456c50b60:-7ee0"/></XcosDiagram> media: gallery121.png + script_dump: '' - model: saveAPI.gallery - pk: 744 + pk: 123 fields: save_id: gallery122 name: eg5_8 description: 'Electrical Engineering Fundamentals (Author: V. Del Toro), 5) Circuit dynamics and forced responses, 5.8) Repeat the previous example for the case where the resistance R is changed' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 293 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="eg5_8"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -143511,15 +165660,16 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="40.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="774ef901:13456c50b60:-7e9f" parent="774ef901:13456c50b60:-7e9e"/></XcosDiagram> media: gallery122.png + script_dump: '' - model: saveAPI.gallery - pk: 745 + pk: 124 fields: save_id: gallery123 name: Ex6_14_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 6) The Frequency Response Design Method, 6.14) Lead compensation for DC motor' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex6_14_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -144742,15 +166892,28 @@ y="120.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery123.png + script_dump: '//Example 6.14 + + //Lead compensation for DC motor. + + + // the required value + + // for step response, set sw to 2 + + // for ramp response, set sw to 0 + + + sw=2' - model: saveAPI.gallery - pk: 746 + pk: 125 fields: save_id: gallery124 name: Ex7_32_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 7) State Space Design, 7.32) Redesign of the Dc servo compensator using SRL' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex7_32_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -145972,15 +168135,198 @@ as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/><mxPoint as="origin" y="-2.0"/></XcosDiagram> media: gallery124.png + script_dump: '//------------------------------------------------------------------ + + //------------------------------------------------------------------ + + //A function written by Deepti Khimani. + + //Usage:- + + //p=zpk_dk(sl) + + //[p, z]=zpk_dk(sl) + + //[p, z, k]=zpk_dk(sl) + + //p:- Poles of the system + + //z:- zeros of the system + + //k:- DC gain of the system + + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + + + function[pl,zr,k]=zpk_dk(sysmodel) + + [lhs,rhs]=argn(0) + + + if rhs == 0 then + + disp(["p=zpk_dk(sl)";"[p, z]=zpk_dk(sl)";"[p, z, k]=zpk_dk(sl)"]); + + disp(["p:- Poles of the system";"z:- zeros of the system"]); + + disp("k:- DC gain of the system"); + + return; + + end + + + if typeof(sysmodel)=="rational" then + + sys=tf2ss(sysmodel); + + pl=spec(sys.A); + + zr=trzeros(sys); + + temp1=poly(zr,''s'',''roots'')/poly(pl,''s'',''roots''); + + temp2=sysmodel/temp1; + + temp3=tf2ss(temp2); + + k=temp3.D; + + elseif typeof(sysmodel)=="state-space" then + + pl=spec(sysmodel.A); + + zr=trzeros(sysmodel); + + g=ss2tf(sysmodel); + + temp1=poly(zr,''s'',''roots'')/poly(pl,''s'',''roots''); + + temp2=g/temp1; + + temp3=tf2ss(temp2); + + k=temp3.D + + else + + error("Wrong type of input argument.") + + end + + endfunction + + + //Example 7.32 + + // Redesign of the Dc servo compensator using SRL + + + // State space representation + + //Transfer function model for DC Servo + + s=poly(0,''s''); + + num=10; + + den=s*(s+2)*(s+8); + + Gs=syslin(''c'',num/den); + + + // State space representation + + F=[-10 1 0;-16 0 1;0 0 0] + + G=[0 0 10]''; + + H=[1 0 0]; + + J=0; + + n=sqrt(length(F)); + + //Desired poles for the DC Servo system. + + Pc=[-2+1.56*%i -2-1.56*%i -8.04] + + + + // State feedback gain + + K=ppol(F,G,Pc) + + disp(K,''K='',"State feedback gain") + + + //Estimator - error roots are at + + Pe=[-4+4.49*%i -4-4.49*%i -9.169] + + Lt=ppol(F'',H'',Pe); + + L=clean(Lt''); + + disp(L,''L='',"Observer gain") + + //Error in book, Gain values are different in book. + + //------------------------------------------------------------------ + + //Compensator Design + + DK=-K*inv(s*eye(n,n)-F+G*K+L*H)*L; + + DK=syslin(''c'',DK) + + [pl,zr,Kp]=zpk_dk(DK); + + Dc=poly(zr,''s'',''roots'')/poly(pl,''s'',''roots'') + + //------------------------------------------------------------------ + + //symmetric root locus + + G_s=horner(Gs,-s); + + evans(Gs*G_s) + + //root locus + + evans(Gs*Dc) //Correct root locus + + //Discrete-time controller + + nc=94.5*conv([7.98 1],[2.52 1]) + + dc=conv([59.5348 8.56 1],[10.6 1]) + + sysDc=poly(nc,''s'',''coeff'')/poly(dc,''s'',''coeff''); + + sysDc_ss=syslin(''c'',tf2ss(sysDc)); + + ts=0.1; + + sysDd=dscr(sysDc_ss,ts) + + Gdz=ss2tf(sysDd); + + + disp(sysDc,"Continuous-time compensator") + + disp(Gdz,"Discrete-time compensator")' - model: saveAPI.gallery - pk: 747 + pk: 126 fields: save_id: gallery125 name: Ex7_34_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 7) State Space Design, 7.34) Servomechanism increasing the velocity constant through zero assignment' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex7_34_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -147464,15 +169810,238 @@ as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/><mxPoint as="origin" y="-12.0"/></XcosDiagram> media: gallery125.png + script_dump: '//Example 7.34 + + // Servomechanism, increasing the velocity constant through + + // zero assignment. + + + // State space representation + + //Transfer function model for DC Servo + + s=poly(0,''s''); + + num=1; + + den=s*(s+1); + + Gs=syslin(''c'',num/den); + + + // State space representation + + F=[0 1;0 -1] + + G=[0 1]''; + + H=[1 0]; + + J=0; + + n=sqrt(length(F)); + + //Desired poles for the DC Servo system. + + Pc=[-2 -2] + + + // State feedback gain + + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + + //A function written by Deepti Khimani. + + //Usage:- + + //[K, lambda]=acker_dk(a, b, pl) + + //K=acker_dk(a, b, pl) + + //a:- System matrix. + + //b:- input matrix. + + //p:- Desired poles. + + //K:-State feedback gain for the control law u=-Kx. + + //lambda:- Eigen values of (a-b*k) + + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + + + function [K, lambda]=acker_dk(a, b, pl) + + [lhs,rhs]=argn(0) + + + if rhs == 0 then + + disp(["K=acker_dk(a, b, pl)";"[K, lambda]=acker_dk(a, b, pl)"]); + + disp(["a:- System matrix";"b:- input matrix";"p:- Desired poles"]); + + disp(["K:-State feedback gain for the control law u=-Kx";... + + "lambda:- Eigen values of (a-b*k)"]); + + return; + + end + + [ra ca]=size(a); + + [rb cb]=size(b); + + l=length(pl); + + + CO=cont_mat(a,b); + + + if ra~=l then + + error(["Dimension error:";"number of desired poles must equal... + + to order of the system"]); + + elseif ra~=ca then + + error(["Dimension error:";"system matrix should be... + + a sqaure matrix"]); + + elseif rb~=ra then + + error (["Dimension error:","Input matrix should have... + + as many rows as a system matrix."]); + + elseif rank(CO)<ra then + + error("system is not controllable"); + + end + + //------------------------------------------------------------------ + + //controllable canonical form + + [Ac,Bc,T,ind]=canon(a,b); + + + //CO=zeros(ra,cb); + + for i=1:ra + + CO(:,ra+1-i)=Ac^(i-1)*Bc; + + end + + //------------------------------------------------------------------ + + chr_eq=poly(pl,''s''); + + des_chr_coeff=coeff(chr_eq); + + + des_chr_coeff=des_chr_coeff(1:ra); + + alpha_c=Ac^ra; + + + for k=1:ra + + alpha_c=alpha_c + des_chr_coeff(k)*Ac^(k-1) + + end + + //------------------------------------------------------------------ + + //State feedback gain + + temp=zeros(1,ra); + + temp(1)=1; + + K=temp*inv(CO)*alpha_c; + + K=K/T; + + lambda=spec(a-b*K); + + endfunction + + //------------------------------------------------------------------ + + K=acker_dk(F,G,Pc)//Gain computed in book is incorrect. + + disp(K,''K='',"State feedback gain") + + //------------------------------------------------------------------ + + //Overall transfer function with reduced order estimator. + + Gred=8.32*(0.096+s)/(0.1 +s)/(8 + 4*s+s^2) + + Gred=syslin(''c'',Gred) + + disp(Gred,''Ys/Rs'',"Overall transfer function with reduced... + + order estimator") + + + //Compensator + + D=(0.096+s)*(s+1)/(4.08 +s)/(0.0196+s) + + Ds=syslin(''c'',D*8.32) + + disp(Ds,''Ds='',"Compensator transfer function") + + //------------------------------------------------------------------ + + //root locus + + evans(D*Gs,100) //Correct root locus + + //------------------------------------------------------------------ + + //step response of the system with lag compensation + + t=0:0.1:5; + + ylag=csim(''step'',t,8.32*Gs*D/(1+8.32*Gs*D)); + + //------------------------------------------------------------------ + + //Discrete-time controller + + sysDc_ss=syslin(''c'',tf2ss(Ds)); + + ts=0.1; + + sysDd=dscr(sysDc_ss,ts) + + Gdz=ss2tf(sysDd) + + + disp(Gdz,"Discrete-time compensator")' - model: saveAPI.gallery - pk: 748 + pk: 127 fields: save_id: gallery126 name: Ex7_35_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 7) State Space Design, 7.35) Integral Control of a Motor Speed System' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex7_35_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -149302,15 +171871,74 @@ x="940.0" y="260.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery126.png + script_dump: '//Example 7.35 + + // Integral Control of a Motor Speed System + + + //Transfer function model + + num=1; + + s=poly(0,''s''); + + den=(s+3); + + G=syslin(''c'',num/den); + + sys=tf2ss(G) + + + // State space representation of augmented system + + F=[0 1; 0 -3]; + + G=[0 1]''; + + H=[1 0]; + + J=0; + + + //Desired poles for augmented system + + Pc=[-5 -5]; + + + // State feedback gain is + + K=ppol(F,G,Pc) + + + //Estimator + + Pe=[-10]; + + L=ppol(sys.A'',sys.C'',Pe) + + + // (c) Compare step reference and disturbance response. + + + // the required values + + // for step reference response switch, set r to 1 and w to 0 + + // for step disturbance response switch, set r to 0 and w to 1 + + + r=1 + + w=0' - model: saveAPI.gallery - pk: 749 + pk: 128 fields: save_id: gallery127 name: Ex8_1_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 8) Digital Control, 8.1) Digital Controller using tustin approximation' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="2.0" title="Ex8_1_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -150525,15 +173153,53 @@ as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/><mxPoint as="origin" y="-3.0"/></XcosDiagram> media: gallery127.png + script_dump: '///Example 8.1 + + // Digital Controller using tustin approximation. + + + //Cntroller + + s=poly(0,''s''); + + numD=s/2+1; + + denD=s/10+1; + + D=10*numD/denD; + + Ds=syslin(''c'',D); + + //sampling freq. = 25 times bandwidth + + Wbw=10; + + Ws=25*Wbw; + + fs=Ws/2/%pi; + + T=1/fs; //sampling time + + a=1;b=-1; + + c=1;d=1; + + //Digital controller + + z=poly(0,''z''); + + Dz=horner(Ds,2/T*(a*z+b)/(c*z+d)); + + disp(Dz,''Digital Controller : '')' - model: saveAPI.gallery - pk: 750 + pk: 129 fields: save_id: gallery128 name: Ex8_2_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 8) Digital Control, 8.2) Design of a Space Station Attitude Digital Controller using Discrete Equivalents' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex8_2_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -152228,15 +174894,73 @@ scilabClass=""><mxPoint x="810.0" y="160.0"/><mxPoint x="810.0" y="110.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery128.png + script_dump: '//Example 8.2 + + // Design of a Space Station Attitude Digital Controller using + + // Discrete Equivalents + + + // State space representation of continuous time system + + s=poly(0,''s''); + + num=1; + + den=(s^2); + + Gs=syslin(''c'',num/den); + + Ds=0.81*(s+0.2)/(s+2); + + Ds=syslin(''c'',Ds); + + sysc=Gs*Ds; + + + //Root locus + + evans(sysc) + + //Contonuous time response of the system + + tc=0:0.1:30; + + syscl=sysc/(1+sysc) + + yc=csim("step",tc,syscl); + + //------------------------------------------------------------------ + + // Discretization of the system at + + z=poly(0,''z'') + + // sampling time Ts=1 sec + + Ts=1; + + Dz1=horner(Ds,2/Ts*(z-1)/(z+1)) + + disp(Dz1,"Dz1=","Discrete-time controller with Ts=1 sec.") + + + // sampling time Ts=0.5 sec + + Ts2=0.5; + + Dz2=horner(Ds,2/Ts2*(z-1)/(z+1)) + + disp(Dz2,"Dz2=","Discrete-time controller with Ts=0.5 sec.")' - model: saveAPI.gallery - pk: 751 + pk: 130 fields: save_id: gallery129 name: Ex9_11_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.11) Describing Function for a relay with hysteresis non linearity' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex9_11_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -152800,15 +175524,61 @@ x="370.0" y="120.0"/><mxPoint as="targetPoint" x="370.0" y="170.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery129.png + script_dump: '//Example 9.11 + + //Describing Function for a relay with hysteresis nonlinearity. + + + //Response of the saturation noninearity to sinusoidal input + + ////Describing Functin for relay with hysteresis nonlinearity. + + h=0.1; + + N=1; + + i=1; + + + for a=0.1:0.025:1 + + if a<h then + + Keq(i,1)=0; + + ro(i,1)=0; + + theta(i,1)=0; + + else + + Keq(i,1)=4*N/(%pi*a)*(sqrt(1-(h/a)^2)-%i*h/a); + + [r th]=polar(Keq(i,1)); + + ro(i,1)=r; //magnitude + + theta(i,1)=clean(th); //angle in radians + + end + + i=i+1; + + end + + + a=0.1:0.025:1; + + a=a'';' - model: saveAPI.gallery - pk: 752 + pk: 131 fields: save_id: gallery130 name: Ex9_13_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.13) Determination of stability with a hysteresis nonlinearity' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="50.0" title="Ex9_13_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -153388,15 +176158,60 @@ x="590.0" y="170.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery130.png + script_dump: '//Example 9.13 + + //Determination of stability with a hysteresis nonlinearity. + + + //System Model + + s=poly(0,''s''); + + num=1; + + den=(s^2+s); + + Gs=syslin(''c'',num/den); + + + // Nyquist Plot of Describing Function for hysteresis nonlinearity + + N=1; + + h=0.1; + + i=1; + + + for omegat=0:0.05:%pi-0.1; + + a=sin(omegat); + + DF_nyq(i,1)=-%pi/4/N*(sqrt(a^2-h^2) + h * %i); + + i=i+1; + + end + + + //Response of the system + + K=2; + + + // the required value + + + r=1' - model: saveAPI.gallery - pk: 753 + pk: 132 fields: save_id: gallery131 name: Ex9_5_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.5) Changing Overshoot and Saturation nonlinearity' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex9_5_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -154061,15 +176876,43 @@ as="geometry" height="40.0" width="40.0" x="510.0" y="140.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery131.png + script_dump: '//Example 9.5 + + //Changing Overshoot and Saturation nonlinearity. + + + //System transfer function and its root locus + + + s=poly(0,''s''); + + num=(s+1) + + den=(s^2); + + Gs=syslin(''c'',num/den) + + + //Root locus + + evans(Gs,5) + + // Step response + + K=1; + + i=[2 4 6 8 10 12]; + + r=2' - model: saveAPI.gallery - pk: 754 + pk: 133 fields: save_id: gallery132 name: Ex9_6_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.6) Stability of conditionally stable system using root locus' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="20.0" title="Ex9_6_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -154674,15 +177517,41 @@ x="530.0" y="180.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery132.png + script_dump: '//Example 9.6 + + //Stability of conditionally stable system using root locus. + + //System transfer function and its root locus + + + s=poly(0,''s''); + + num=(s+1)^2 + + den=(s^3); + + Gs=syslin(''c'',num/den) + + //Root locus + + evans(Gs,7) + + //Response of the system + + K=2; + + i=[1 2 3 3.475]; + + r=1' - model: saveAPI.gallery - pk: 755 + pk: 134 fields: save_id: gallery133 name: Ex9_7_model_notch description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.7) Analysis and design of the system with limit cycle using the root locus' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: '<?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="50.0" title="Ex9_7_model_notch"><!--Xcos - 1.0 - scilab-5.5.2 @@ -155354,15 +178223,60 @@ x="740.0" y="170.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram>' media: gallery133.png + script_dump: '//Example 9.7 + + //Analysis and design of the system with limit cycle using the root locus. + + //System transfer function and its root locus + + + s=poly(0,''s''); + + num=0.1; + + den=(s^2+0.2*s+1)*(s); + + Gs=syslin(''c'',num/den); + + + //Root locus + + evans(Gs,40) + + //Response of the system + + K=0.5; + + i=[1 4 8]; + + r=1 + + + //System with notch compensation + + D=123*(s^2+0.18*s+0.81)/(s+10)^2; + + + //Root locus + + evans(Gs*D,40) + + //Response of the system witth notch filter + + K=0.5; + + i=[2 4]; + + r=2' - model: saveAPI.gallery - pk: 756 + pk: 135 fields: save_id: gallery134 name: Ex9_7_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.7) Analysis and design of the system with limit cycle using the root locus' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: '<?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="150.0" title="Ex9_7_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -155986,15 +178900,60 @@ x="750.0" y="170.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram>' media: gallery134.png + script_dump: '//Example 9.7 + + //Analysis and design of the system with limit cycle using the root locus. + + //System transfer function and its root locus + + + s=poly(0,''s''); + + num=0.1; + + den=(s^2+0.2*s+1)*(s); + + Gs=syslin(''c'',num/den); + + + //Root locus + + evans(Gs,40) + + //Response of the system + + K=0.5; + + i=[1 4 8]; + + r=1 + + + //System with notch compensation + + D=123*(s^2+0.18*s+0.81)/(s+10)^2; + + + //Root locus + + evans(Gs*D,40) + + //Response of the system witth notch filter + + K=0.5; + + i=[2 4]; + + r=2' - model: saveAPI.gallery - pk: 757 + pk: 136 fields: save_id: gallery135 name: Ex9_8_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.8) Antiwindup compensation for a PI controller' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="10.0" title="Ex9_8_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -157050,15 +180009,38 @@ x="890.0" y="100.0"/><Array as="points" scilabClass=""><mxPoint x="810.0" y="100.0"/></Array></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery135.png + script_dump: '//Example 9.8 + + //Antiwindup compensation for a PI controller. + + + //System Model + + + //Response of the system + + kp=2; + + ki=4; + + + //Without antiwindup + + ka=0; + + + //With antiwindup + + ka=10;' - model: saveAPI.gallery - pk: 758 + pk: 137 fields: save_id: gallery136 name: Ex9_9_model description: 'Feedback Control of Dynamic Systems (Author: G. F. Franklin, J. D. Powell and A. Emami-Naeini), 9) Nonlinear Systems, 9.9) Describing Function for a saturation nonlinearity' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3432 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="5.0" title="Ex9_9_model"><!--Xcos - 1.0 - scilab-5.5.2 @@ -157624,14 +180606,52 @@ as="geometry" height="40.0" width="40.0" x="360.0" y="140.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-2dd55334:14dcbdd0183:-7fd3" parent="-2dd55334:14dcbdd0183:-7fd2"/></XcosDiagram> media: gallery136.png + script_dump: '//Example 9.9 + + //Describing Function for a saturation nonlinearity. + + + //Response of the saturation nonlinearity to sinusoidal input + + //Describing Functin for saturation nonlinearity. + + k=1; + + N=1; + + i=1; + + Keq=[]; + + + for a=0:0.2:10 + + if k*a/N > 1 then + + Keq(i,1)=2/%pi*(k*asin(N/a/k)+N/a*sqrt(1-(N/k/a)^2)) + + else + + Keq(i,1)=k + + end + + i=i+1; + + end + + + a=0:0.2:10; + + a=a'';' - model: saveAPI.gallery - pk: 759 + pk: 138 fields: save_id: gallery137 name: Ex3_1 description: 'Control Systems (Author: A Nagoor Kani), 3) TIME RESPONSE ANALYSIS, 3.1) RESPONSE OF THE SYSTEM' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3885 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex3_1"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -158259,14 +181279,44 @@ x="180.0" y="200.0"/></Array></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery137.png + script_dump: '//control systems by Nagoor Kani A + + //Edition 3 + + //Year of publication 2015 + + //Scilab version 6.0.0 + + //operating systems windows 10 + + // Example 3.1 + + + s=%s + + p=poly([4],''s'',''coeff'') + + q=poly([0 5 1],''s'',''coeff'') + + g=p./q + + disp(g,''The given transfer function is'') + + c=g/(1+g) + + disp(c,''The closed loop transfer function is'') + + u=c/s + + disp(u,''The input is unit step signal'')' - model: saveAPI.gallery - pk: 760 + pk: 139 fields: save_id: gallery138 name: Ex3_2 description: 'Control Systems (Author: A Nagoor Kani), 3) TIME RESPONSE ANALYSIS, 3.2) RESPONSE OF THE SYSTEM' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3885 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex3_2"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -158852,14 +181902,46 @@ x="340.0" y="70.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery138.png + script_dump: '//control systems by Nagoor Kani A + + //Edition 3 + + //Year of publication 2015 + + //Scilab version 6.0.0 + + //operating systems windows 10 + + // Example 3.2 + + + s=%s + + p=poly([100],''s'',''coeff'') + + q=poly([0 2 1],''s'',''coeff'') + + h=poly([1 0.1 0 ],''s'',''coeff'') + + g=p./q + + disp(g,''the given transfer function is'') + + c=g/(1+(g*h)) + + disp(c,''the closed loop transfer function is'') + + u=c/s + + disp(u,''the in put is unit step signal'')' - model: saveAPI.gallery - pk: 761 + pk: 140 fields: save_id: gallery139 name: Ex3_6 description: 'Control Systems (Author: A Nagoor Kani), 3) TIME RESPONSE ANALYSIS, 3.6) RESPONSE OF THE SYSTEM' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3885 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex3_6"><!--Xcos - 1.0 - scilab-5.5.2 - 20181120--><mxGraphModel @@ -159445,14 +182527,76 @@ x="360.0" y="260.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery139.png + script_dump: '//control systems by Nagoor Kani A + + //Edition 3 + + //Year of publication 2015 + + //Scilab version 6.0.0 + + //operating systems windows 10 + + // Example 3.6 + + + s=poly(0,''s'') + + // the input is unit step signal + + h=syslin(''c'',16/(s^2+4*s+16))//the value of k is 0.2 + + zeta=0.5//given damping ratio + + disp(h,''the closed loop transfer function'') + + //standard form od second order system is w^2/s^2+2*zeta*w*s+w^2 + + //compaing h with the standard form + + w=4//natural frequency of oscillation + + disp(w,''natural frequency of oscillation in rad/sec'') + + k=(2*zeta*w-(0.8))/16 + + disp(k,''the value of k is'') + + mp=exp((-zeta*%pi)/sqrt(1-(zeta)^2))*100//percentage peak overshoot + + disp(mp,''percentage peak overshoot in percentage'') + + tp=%pi/(w*sqrt(1-(zeta)^2)) + + disp(tp,''peak time in seconds'') + + //constructing a right angle triangle with zeta and sqrt(1-zeta^2) + + theta=atan(0.866/0.5)//(1-zeta^2)/zeta + + disp(theta,''the value of theta is'') + + tr=(%pi- theta)/(w*sqrt(1-(zeta)^2)) + + disp(tr,''the rise time in seconds'') + + t=1/(zeta*w)//time constant + + ts1=3*t//settling time for 5% error + + disp(ts1,''settling time for 5% error in seconds'') + + ts2=4*t//settling time for 2% error + + disp(ts2,''settling time for 2% error in seconds'')' - model: saveAPI.gallery - pk: 762 + pk: 141 fields: save_id: gallery140 name: Ex3_7 description: 'Control Systems (Author: A Nagoor Kani), 3) TIME RESPONSE ANALYSIS, 3.7) RESPONSE OF THE SYSTEM' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3885 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex3_7"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -160038,14 +183182,64 @@ x="480.0" y="100.0"/><mxPoint as="targetPoint" x="480.0" y="170.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery140.png + script_dump: '//control systems by Nagoor Kani A + + //Edition 3 + + //Year of publication 2015 + + //Scilab version 6.0.0 + + //operating systems windows 10 + + // Example 3.7 + + + s=%s + + p=poly([1 0.4 0 ],''s'',''coeff'') + + q=poly([0 0.6 1],''s'',''coeff'') + + g=p./q + + disp(g,''the given transfer function is'') + + c=g/(1+g) + + disp(c,''the closed loop transfer function is'') + + u=c/s + + disp(u,''the in put is unit step signal'') + + //standard form od second order system is w^2/s^2+2*zeta*w*s+w^2 + + //compaing h with the standard form + + w=1//natural frequency of oscillation + + disp(w,''natural frequency of oscillation in rad/sec'') + + zeta=1/(2*w) + + disp(zeta,''the damping ratio is'') + + mp=exp((-zeta*%pi)/sqrt(1-(zeta)^2))*100//percentage peak overshoot + + disp(mp,''percentage peak overshoot in percentage'') + + tp=%pi/(w*sqrt(1-(zeta)^2)) + + disp(tp,''peak time in seconds'')' - model: saveAPI.gallery - pk: 763 + pk: 142 fields: save_id: gallery141 name: Ex7_10 description: 'Control Systems (Author: A Nagoor Kani), 7) STATE SPACE ANALYSIS, 7.10) STATE MODEL' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3885 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex7_10"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -160637,14 +183831,36 @@ x="360.0" y="110.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery141.png + script_dump: '//control systems by Nagoor Kani A + + //Edition 3 + + //Year of publication 2015 + + //Scilab version 6.0.0 + + //operating systems windows 10 + + // Example 7.10 + + + s=%s + + p=poly([10],''s'',''coeff'') + + q=poly([1 2 4 1],''s'',''coeff'') + + sm=cont_frm(p,q) + + disp(sm,''the state model in matrix form is'')' - model: saveAPI.gallery - pk: 764 + pk: 143 fields: save_id: gallery142 name: Ex7_11 description: 'Control Systems (Author: A Nagoor Kani), 7) STATE SPACE ANALYSIS, 7.11) STATE MODEL' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3885 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex7_11"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -161236,14 +184452,36 @@ x="270.0" y="210.0"/><mxPoint as="targetPoint" x="330.0" y="220.0"/></mxGeometry></ExplicitLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery142.png + script_dump: '//control systems by Nagoor Kani A + + //Edition 3 + + //Year of publication 2015 + + //Scilab version 6.0.0 + + //operating systems windows 10 + + // Example 7.11 + + + s=%s + + p=poly([40 10],''s'',''coeff'') + + q=poly([0 3 4 1],''s'',''coeff'') + + sm=cont_frm(p,q) + + disp(sm,''the state model in matrix form is'')' - model: saveAPI.gallery - pk: 765 + pk: 144 fields: save_id: gallery143 name: Ex7_12 description: 'Control Systems (Author: A Nagoor Kani), 7) STATE SPACE ANALYSIS, 7.12) STATE MODEL' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 3885 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="30.0" title="Ex7_12"><!--Xcos - 1.0 - scilab-5.5.2 - 20160406 @@ -161836,14 +185074,40 @@ as="sourcePoint" x="360.0" y="120.0"/><mxPoint as="targetPoint" x="360.0" y="140.0"/></mxGeometry></CommandControlLink></root></mxGraphModel><mxCell as="defaultParent" id="0:2:0" parent="0:1:0"/></XcosDiagram> media: gallery143.png + script_dump: '//control systems by Nagoor Kani A + + //Edition 3 + + //Year of publication 2015 + + //Scilab version 6.0.0 + + //operating systems windows 10 + + // Example 7.12 + + + s=%s + + h=syslin(''c'',(2*(s+5))/((s+2)*(s+3)*(s+4))) + + disp(h,''thr transfer function is'') + + ss=tf2ss(h) + + disp(ss,''the state space model is'') + + [Ac,Bc,U,ind]=canon(ss(2),ss(3)) + + disp(Ac,Bc,U,ind)' - model: saveAPI.gallery - pk: 766 + pk: 145 fields: save_id: gallery144 name: example_11_1 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 11) Unsymmetrical Fault Analysis, 11.1) LG and 3Phase faults Comparision' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.25" title="example_11_1"><!--Xcos - 1.0 - scilab-5.5.2 @@ -162975,15 +186239,49 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="-8.0"/></ImplicitInputPort></root></mxGraphModel><mxCell as="defaultParent" id="67e02cde:13157ae1f65:-8000" parent="67e02cde:13157ae1f65:-7fff"/></XcosDiagram> media: gallery144.png + script_dump: '//Chapter 11 + + //Example 11.1 + + //page 406 + + //To draw sequence networks of generator and to compare LG fault current will + be greater than three-phase fault current when neutral is solidly grounded + + + disp("Sequence networks of synchronous generator grounded through neutral impedance + has been drawn using XCOS "); + + + disp("Since the derivation can not be done here, let us do this problem by taking + a suitable values for the sequence reactances of the generator"); + + + disp("X1=j0.18, X2=j0.15, X0=j0.10 pu and Ea=1"); + + + disp("From the figs 11.13 and 11.14 in the textbook,we can find Ilg and I3L"); + + + Ea=1;X1=0.18*%i;X2=0.15*%i;X0=0.10*%i; + + + IaLG=3*Ea/(2*X1+X0) + + Ia3L=3*Ea/(3*X1) + + + disp("Same values of sequence impedance have been used in XCOS simulation also + to varify the result");' - model: saveAPI.gallery - pk: 767 + pk: 146 fields: save_id: gallery145 name: example_11_2 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 11) Unsymmetrical Fault Analysis, 11.2) Grounding Resistor voltage and Fault Current' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.25" title="example_11_2"><!--Xcos - 1.0 - scilab-5.5.2 @@ -164135,15 +187433,53 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="-8.0"/></ImplicitInputPort></root></mxGraphModel><mxCell as="defaultParent" id="67e02cde:13157ae1f65:-7afa" parent="67e02cde:13157ae1f65:-7af9"/></XcosDiagram> media: gallery145.png + script_dump: '//Chapter 11 + + //Example 11.2 + + //page 408 + + //To find fault current and voltage across the grounding resistor + + + X1eq=(%i*0.18)/2; + + X2eq=(%i*0.15)/2; + + Z0eq=(%i*0.10)+3*(2*20/(11^2)); + + + Ea=1; + + + //calculation of fault current + + printf(''\nFault current is given by ''); + + If=(3*Ea)/(X1eq+X2eq+Z0eq) + + + //current in grounding resistor + + Ifg=abs(If)*(20/(11*sqrt(3))); + + printf(''\n\nCurrent through grounding resistor Ifg=%0.2fkA'',Ifg); + + + //voltage across grounding resistor + + Vgr=abs(If*(2*20/(11^2))*(11/sqrt(3))); + + printf(''\n\nVoltage across grounding resistor Vgr=%0.2fkV\n\n'',Vgr);' - model: saveAPI.gallery - pk: 768 + pk: 147 fields: save_id: gallery146 name: example_11_3 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 11) Unsymmetrical Fault Analysis, 11.3) Fault and subtransient currents of the system' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.25" title="example_11_3"><!--Xcos - 1.0 - scilab-5.5.2 @@ -165468,14 +188804,153 @@ as="geometry" height="40.0" width="40.0" x="790.0" y="250.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="2af926ac:131590fb290:-7ef4" parent="2af926ac:131590fb290:-7ef3"/></XcosDiagram> media: gallery146.png + script_dump: '//Chapter 11 + + //Example 11.3 + + //page 409 + + //To find fault current and subtransient current in all parts of the system + + + a=-0.5+(sqrt(3)/2)*%i; + + + //neglecting prefault currents + + Vf0=10/11; + + Eg=Vf0; Em1=Vf0 ;Em2=Vf0; + + + //positive sequence network when it is replaced by its thevenin''s equvivalent + as shown in fig11.18 + + printf(''\nsequence impedances are given by \n''); + + Z1=(%i*0.525*%i*0.23)/(%i*0.755); + + Z2=Z1; + + Z0=%i*1.712; + + printf(''Z1=j%0.4f \nZ2=j%0.4f \nZ0=j%0.4f'',abs(imag(Z1)),abs(imag(Z2)),abs(imag(Z0))); + + //to find sequence current + + Ia1=Vf0/(Z1+Z2+Z0); + + Ia2=Ia1; + + Ia0=Ia1; + + + //to find fault current + + If=3*Ia0; + + printf(''\n\nFault Current= -j%0.4f'',abs(imag(If))); + + + + //component current flowing from generator and motor + + printf(''\n\nComponents currents flowing from Generator and motor are \n'') + + Ig1=Ia1*(0.23/0.755) ; + + Ig2=Ig1; + + Ig0=0; + + printf(''Ig1= -j%0.4f \nIg2= -j%0.4f \nIg0=%d'',abs(Ig1),abs(Ig2),abs(Ig0)); + + printf(''\n''); + + Im1=Ia1*(0.525/0.755); + + Im2=Im1; + + Im0=Ia0; + + printf(''\nIm1= -j%0.4f \nIm2= -j%0.4f \nIm0= -j%0.4f'',abs(Im1),abs(Im2),abs(Im0)); + + + //fault currents from the generator and motor towards g are + + printf(''\n\nFault current from the generator towards g are ''); + + Ig=[1 1 1;a^2 a 1;a a^2 1]*[Ig1;Ig2;Ig0]; + + disp(Ig); + + printf(''and to g from motors are''); + + Im=[1 1 1;a^2 a 1;a a^2 1]*[Im1;Im2;Im0]; + + disp(Im); + + + printf(''\nPositive sequence current =%0.3f pu'',(-%i*Ig1)); + + printf(''\nNegative sequence current =%0.3f pu'',(%i*Ig2)); + + printf(''\nZero sequence current=%d\n'',Ig0); + + + //under loaded condition,PU motor currents are + + Im1o=(15/(25*0.909*0.8))*(0.800103636+%i*0.5998617938); + + Im2o=(7.5/(25*0.909*0.8))*(0.800103636+%i*0.5998617938); + + printf(''\nThe per unit motor currents are:\n''); + + printf(''Motor1:%0.2f +j%0.3f pu'',real(Im1o),imag(Im1o)); + + printf(''\nMotor2:%0.2f +j%0.3f pu'',real(Im2o),imag(Im2o)); + + + //the voltages behind subtransient reactances are calculated below + + printf(''\n\nVoltage behind subtransient reactances:\n''); + + printf(''Motor1:''); + + Em1=Em1-(%i*0.345*Im1o); + + printf(''Em1= %0.4f-j%0.4f'',real(Em1),abs(imag(Em1))); + + + printf(''\nMotor2:''); + + Em2=Em2-(%i*0.69*Im2o); + + printf(''Em2= %0.4f-j%0.4f'',real(Em2),abs(imag(Em2))); + + + printf(''\nGenerator:''); + + Eg=Eg+(%i*0.525*(Im2o+Im1o)); + + printf(''Eg= %0.4fj+%0.4f'',real(Eg),abs(imag(Eg))); + + + //actual value of positive sequence current from generator and motor + + printf(''\n\nThe actual value of positive sequence current from the generator + towards fault is = %0.2f+j%0.3f'',real(Im1o+Im2o+Ig1),imag(Im1o+Im2o+Ig1)); + + printf(''\nThe actual value of positive sequence current from the motors towards + fault is = %0.2f-j%0.3f'',real(-Im1o-Im2o+Im1),abs(imag(-Im1o-Im2o+Im1)));' - model: saveAPI.gallery - pk: 769 + pk: 148 fields: save_id: gallery147 name: example_11_4 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 11) Unsymmetrical Fault Analysis, 11.4) LL Fault Current' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.25" title="example_11_4"><!--Xcos - 1.0 - scilab-5.5.2 @@ -166349,14 +189824,63 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="60.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="-1f09110a:1315ad634dc:-8000" parent="-1f09110a:1315ad634dc:-7fff"/></XcosDiagram> media: gallery147.png + script_dump: '//Chapter 11 + + //Example 11.4 + + //page 412 + + //To find L-L fault current and voltage of healthy phase + + X1eq=0.09*%i; + + X2eq=0.075*%i; + + Z0=0.99+(%i*0.1); + + Ea=1;Ia0=0; + + + //to calculate Ia1 + + Ia1=Ea/(X1eq+X2eq); + + + //to calculate fault current + + If=(-%i*sqrt(3))*(-%i*6.06); + + Va1=Ea-(Ia1*X1eq); + + Va0=(-Ia0*Z0); + + Va2=Va1; + + + //voltage in healthy phase + + Va=Va1+Va2+Va0; + + + //displaying the result + + printf(''\nIa1=-j%0.2f'',abs(Ia1)); + + printf(''\nIf=%0.3f'',If); + + printf(''\nVa1=Va2=%0.3f'',Va1); + + printf(''\nVa0=%d'',Va0); + + printf(''\nVa=Va1+Va2+Va0=%0.2f\n\n'',Va);' - model: saveAPI.gallery - pk: 770 + pk: 149 fields: save_id: gallery148 name: example_11_5 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 11) Unsymmetrical Fault Analysis, 11.5) Double line to ground Fault' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.25" title="example_11_5"><!--Xcos - 1.0 - scilab-5.5.2 @@ -167388,14 +190912,75 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="-8.0"/></ImplicitInputPort></root></mxGraphModel><mxCell as="defaultParent" id="-1f09110a:1315ad634dc:-8000" parent="-1f09110a:1315ad634dc:-7fff"/></XcosDiagram> media: gallery148.png + script_dump: '//Chapter 11 + + //Example 11.5 + + //page 413 + + //To find Double line to ground fault current and voltage of healthy phase + + + Z1eq=0.09*%i; + + Z2eq=0.075*%i; + + Z0=(%i*0.1); + + Ea=1; + + a=(-0.5+%i*sqrt(3)/2); + + + //to find the sequence components of healthy phase + + Ia1=Ea/(Z1eq+(Z2eq*Z0/(Z2eq+Z0))); + + Va1=Ea-(Ia1*Z1eq); + + Va2=Va1; + + Va0=Va1; + + + Ia2=-(Va2/Z2eq); + + Ia0=-(Va0/Z0); + + + I=[1 1 1;a^2 a 1;a a^2 1]*[Ia1; Ia2; Ia0]; + + + //voltage of the healthy phase + + Va=3*Va1; + + + //displaying the results + + printf(''Ia1=-j%0.3f\n'',abs(Ia1)); + + printf('' Ia2=j%0.3f\n'',abs(Ia2)); + + printf('' Ia0=j%0.3f\n\n'',abs(Ia0)); + + + printf('' Ia=%0.3f + j%0.3f\n'',real(I(1,1)),imag(I(1,1))); + + printf('' Ib=%0.3f + j%0.3f\n'',real(I(2,1)),imag(I(2,1))); + + printf('' Ic=%0.3f + j%0.3f\n\n'',real(I(3,1)),imag(I(3,1))); + + + printf('' Voltage of the healthy phase Va=3Va1=%0.3f'',Va);' - model: saveAPI.gallery - pk: 771 + pk: 150 fields: save_id: gallery149 name: example_9_1_3phase_plot description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 9) Symmetrical Fault Analysis, 9.1) Fault Current Calculation' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: '<?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.2" title="example_9_1_3phase_plot"><!--Xcos - 1.0 - @@ -170445,14 +194030,95 @@ x="1590.0" y="550.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="-62268d13:130f6b46d8a:-7eeb" parent="-62268d13:130f6b46d8a:-7eea"/></XcosDiagram>' media: gallery149.png + script_dump: '//Chapter 9 + + //Example 9.1 + + //page 335 + + //To calculate fault current + + //selecting base KVA and MVA + + mvab=100; + + Gmva=10; + + T1mva=10; T2mva=5; + + Gkvb=11; //generator kV base + + OHLkvb=33; //overhead line kV base + + Ckvb=6.6;// cable kB base + + xg1=%i*0.15; xg2=%i*0.125; xt1=%i*0.10; xt2=%i*0.08; + + xOHL=0.27+%i*0.36 ; xcab= 0.135+%i*0.08; + + + //clculating PU impedances + + + xg1=(xg1*mvab)/Gmva; + + xg2=(xg2*mvab)/Gmva; + + xt1=(xt1*mvab)/T1mva; + + xt2=(xt2*mvab)/T2mva; + + xOHL=(30*xOHL*mvab)/(OHLkvb^2); + + xcab=(3*xcab*mvab)/(Ckvb^2); + + //displaying results + + printf(''\n Reactance of G1= j%0.1f pu \n'',abs(imag(xg1))); + + printf('' Reactance of G2= j%0.1f pu\n'',abs(imag(xg2))); + + printf('' Reactance of T1= j%0.1f pu\n'',abs(imag(xt1))); + + printf('' Reactance of T2= j%0.1f pu\n'',abs(imag(xt2))); + + printf('' Overhead line impedance=(%0.3f + j%0.3f) pu\n'',real(xOHL),abs(imag(xOHL))); + + printf('' Cable impedance= (%0.3f + j%0.3f) pu\n'',real(xcab),abs(imag(xcab))); + + + // Impedance diagram is as shown in the figure9.7 in the textbook + + // A XCOS simulation for this proble is done to explain the subtransient,transient + and steady state periods of a symmetrical short circuit + + xtotal=((xg1*xg2)/(xg1+xg2)+xt1+xt2+xOHL+xcab); + + Isc_pu=(1/xtotal); + + Ibase=(mvab/(sqrt(3)*Ckvb))*1000; + + Isc=Isc_pu*Ibase; + + x_F_to_bus=(xt1+xt2+xOHL+xcab); + + v_11b=x_F_to_bus*Isc_pu*11; + + //displaying results + + printf(''\nTotal impedance= %0.1f < %0.2f deg pu \n'',abs(xtotal),atand(imag(xtotal)/real(xtotal))); + + printf(''Short circuit current= %d A\n'',abs(Isc)); + + printf(''Voltage at 11kV bus=%0.2f kV\n'',abs(v_11b));' - model: saveAPI.gallery - pk: 772 + pk: 151 fields: save_id: gallery150 name: example_9_2 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 9) Symmetrical Fault Analysis, 9.2) Subtransient and Momentary current Calculation' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="example_9_2"><!--Xcos - 1.0 - scilab-5.5.2 @@ -171708,14 +195374,95 @@ as="defaultParent" id="63eb11b3:131137cfac5:-8000" parent="63eb11b3:131137cfac5:-7fff"/><mxPoint as="origin" y="-20.0"/></XcosDiagram> media: gallery150.png + script_dump: '//Chapter 9 + + //Example 9.2 + + //page 337 + + //To calculate subtransient and momentary current + + mvab=25; + + Gmva=25; + + T1mva=25; T2mva=25; + + Gkvb=11; //generator kV base + + OHLkvb=66; //overhead line kV base + + Mkvb=6.6; //motor kV base + + Mmva=5; //motor mva + + + XdG=%i*0.2; //Generator''s subtransient reactance + + XdM=%i*0.25; //Motor''s subtransient reactance + + XdM2=%i*0.3; //Motor''s transient reactance + + Xt1=%i*0.1; // step up transformer''s reactance + + Xt2=%i*0.1;//step down transformer''s reactance + + Xtl=%i*0.15 ;//trnasmission line''s reactance + + + //per unit calculation + + XdM=(XdM*mvab)/Mmva ;//perunit impedance of each motor + + printf(''\nSubtransient reactance of each motor = j%0.2f pu\n'',abs(XdM)); + + + //(a)subtransient current in the fault + + Isc=(3*(1/XdM))+(1/(XdG+Xt1+Xt2+Xtl)); + + Ibase=(mvab*1000)/(sqrt(3)*Mkvb); + + Isc=Isc*Ibase; + + printf(''\nSubtransient current in the fault =%0.1fA\n'',abs(Isc)); + + + //(b)subtransient current in the breaker B + + IscB=(2*(1/XdM))+(1/(XdG+Xt1+Xt2+Xtl)); + + IscB=IscB*Ibase; + + printf(''\nSubtransient current in breaker B=%0.1fA\n'',abs(IscB)); + + + //(c) to find the momentary current through breaker B + + ImomB=1.6*IscB; + + printf(''\nMomentary current through the breaker B=%dA\n'',abs(ImomB)); + + + //(d) to compute current to be interrupted by breaker in 5 cycles + + XdM2=(XdM2*mvab)/Mmva ;//perunit transient impedance of each motor + + IscB=(2*(1/XdM2))+(1/(XdG+Xt1+Xt2+Xtl)); + + IscB=IscB*Ibase; + + ImomB=1.1*IscB; + + printf(''\nCurrent to be interrupted by breaker B in five cycles=%dA\n'',abs(ImomB));' - model: saveAPI.gallery - pk: 773 + pk: 152 fields: save_id: gallery151 name: example_9_3 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 9) Symmetrical Fault Analysis, 9.3) Subtransient Current Calculation' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="example_9_3"><!--Xcos - 1.0 - scilab-5.5.2 @@ -172773,14 +196520,79 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="-8.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="-487ef5e3:131246c8237:-8000" parent="-487ef5e3:131246c8237:-7fff"/></XcosDiagram> media: gallery151.png + script_dump: '//Chapter 9 + + //Example 9.3 + + //page 340 + + //To calculate subtransient current in Generator,Motor and fault + + mvab=25; + + kvb=11; + + Vo=10.6/kvb; //PU Prefault voltage + + printf(''\nPrefault Voltage = %0.4fpu\n'',Vo); + + + Load=15/mvab; //load PU with 0.8pf leading + + Io=(Load/(Vo*0.8))*(cosd(36.9)+%i*sind(36.9)); //Prefault current + + printf(''\nPrefault current = %0.4f at %0.1f deg PU'',abs(Io),atand(imag(Io)/real(Io))); + + + Eg=Vo+(%i*0.45*Io); //voltage behind subtransient reactance(generator) + + printf(''\n\nVoltage behind subtransient reactance(Generator) = %0.4f+j%0.2f + pu\n'''''',real(Eg),imag(Eg)); + + + Em=Vo-(%i*0.15*Io); //voltage behind subtransient reactance(motor) + + printf(''\nVoltage behind subtransient reactance(Motor) = %0.4f-j%0.4f pu'',real(Em),abs(imag(Em))); + + + Ig=Eg/(%i*0.45); //under fault condition + + Im=Em/(%i*0.15); //under fault condition + + printf(''\n\nUnder Faulted condition \n Ig""=%0.4f-j%0.4f pu'',real(Ig),abs(imag(Ig))); + + printf(''\n Im""=%0.4f-j%0.4f pu'',real(Im),abs(imag(Im))); + + If=Ig+Im; //Current in fault + + printf(''\n\nCurrent in fault= -j%0.4f pu'',abs(imag(If))); + + + Ib=(mvab*1000/(sqrt(3)*11)); //Base current + + //Actual Currents + + printf("\n\nNow"); + + Ig=Ig*Ib + + Im=Im*Ib + + If=If*Ib + + printf(''\nIg""= %0.1f-j%0.1f A'',real(Ig),abs(imag(Ig))); + + printf(''\nIm""= %0.1f-j%0.1f A'',real(Im),abs(imag(Im))); + + printf(''\nIf= -j%d A'',abs(imag(If)));' - model: saveAPI.gallery - pk: 774 + pk: 153 fields: save_id: gallery152 name: example_9_4 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 9) Symmetrical Fault Analysis, 9.4) Maximum MVA Calculation' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="example_9_4"><!--Xcos - 1.0 - scilab-5.5.2 @@ -173909,14 +197721,75 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="-8.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="-487ef5e3:131246c8237:-7cc8" parent="-487ef5e3:131246c8237:-7cc7"/></XcosDiagram> media: gallery152.png + script_dump: '//Chapter 9 + + //Example 9.4 + + //page 345 + + //To calculate maximum MVA + + mvab=50; + + kvb=6.6; + + mvaA=40; + + mvaB=50; + + mvaC=25; + + feeder_impedance=((0.06+%i*0.12)*mvab)/(kvb^2) + + + Gen_A_reactance=(%i*0.1*mvab/mvaA); + + Gen_B_reactance=(%i*0.1*mvab/mvaB); + + Gen_C_reactance=(%i*0.1*mvab/mvaC); + + + printf(''\nGenerator A reactance = j%0.3f pu'',abs(Gen_A_reactance)); + + printf(''\nGenerator B reactance = j%0.3f pu'',abs(Gen_B_reactance)); + + printf(''\nGenerator C reactance = j%0.3f pu'',abs(Gen_C_reactance)); + + + Reactor_A_reactance=(%i*0.12*mvab/mvaA); + + Reactor_B_reactance=(%i*0.12*mvab/mvaB); + + Reactor_C_reactance=(%i*0.12*mvab/mvaC); + + + printf(''\nReactor A reactance = j%0.3f pu'',abs(Reactor_A_reactance)); + + printf(''\nReactor B reactance = j%0.3f pu'',abs(Reactor_B_reactance)); + + printf(''\nReactor C reactance = j%0.3f pu'',abs(Reactor_C_reactance)); + + + function resistance=parallel(r1,r2) + + resistance=(r1*r2/(r1+r2)); + + endfunction + + + Z=(feeder_impedance)+parallel(%i*0.125,(%i*0.15 + parallel(%i*0.22,%i*0.44))); + + scmva=(1/abs(Z))*mvab; + + printf("\n\nSC MVA = %d MVA",scmva);' - model: saveAPI.gallery - pk: 775 + pk: 154 fields: save_id: gallery153 name: example_9_5 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 9) Symmetrical Fault Analysis, 9.5) Short Circuit Solution' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="0.5" title="example_9_5"><!--Xcos - 1.0 - scilab-5.5.2 @@ -175067,14 +198940,80 @@ as="geometry" height="8.0" width="8.0" x="16.0" y="60.0"/></ImplicitOutputPort></root></mxGraphModel><mxCell as="defaultParent" id="-487ef5e3:131246c8237:-799b" parent="-487ef5e3:131246c8237:-799a"/></XcosDiagram> media: gallery153.png + script_dump: '//Chapter 9 + + //Example 9.5 + + //page 347 + + //To calculate short circuit solution + + //referring to figures 9.19 in the text book,we get directly the fault current + + V4o=1.0; + + Zf=%i*0.13560; + + If=V4o/Zf; + + printf(''\nIf= -j%0.5f pu\n\n'',abs(If)); + + + //From Fig9.19d + + I1=If*((%i*0.19583)/(%i*0.37638)); + + I2=If*((%i*0.18055)/(%i*0.37638)); + + printf(''I1 = -j%0.5f pu \n\nI2 = -j%0.5f pu\n\n'',abs(I1),abs(I2)); + + + //voltage changes for bus 1,2 and 3 + + deltaV1=0-(%i*0.15)*I1; + + deltaV2=0-(%i*0.15)*I2; + + printf(''DeltaV1=%0.5f pu\n\nDeltaV2=%0.5f pu\n\n'',deltaV1,deltaV2); + + + //reffering to book + + V1f=1+deltaV1; + + V2f=1+deltaV2; + + printf(''V1f= %0.5f pu\n\nV2f=%0.5f pu\n\n'',V1f,V2f); + + I13=(V1f-V2f)/(%i*0.15+%i*0.1); + + printf(''I13=j%0.5f pu\n\n'',abs(I13)); + + deltaV3=0-((%i*0.15)*(I1)+(%i*0.15)*(I13)); + + Vf3=1+deltaV3; + + printf(''DeltaV3=%0.5f pu\n\n'',deltaV3); + + printf(''Vf3=%0.5f pu\n\n'',Vf3); + + Vf4=0; + + printf(''Vf4=%d\n\n'',Vf4); + + //short circuit MVA at bus 4 + + SC_MVA_4=abs(If)*100; + + printf(''Short circuit MVA at bus4 =%0.3f MVA'',SC_MVA_4);' - model: saveAPI.gallery - pk: 776 + pk: 155 fields: save_id: gallery154 name: example_9_7 description: 'Modern Power System Analysis (Author: D. P. Kothari And I. J. Nagrath), 9) Symmetrical Fault Analysis, 9.7) Current Injection Method' - save_time: 2025-01-23 16:04:57+00:00 + save_time: 2025-03-17 15:49:09+00:00 book: 83 data_dump: <?xml version="1.0" encoding="UTF-8"?><XcosDiagram background="-1" finalIntegrationTime="6.0" title="example_9_7"><!--Xcos - 1.0 - scilab-5.5.2 @@ -176287,3 +200226,37 @@ as="geometry" height="40.0" width="40.0" x="600.0" y="350.0"/></TextBlock></root></mxGraphModel><mxCell as="defaultParent" id="75289c83:1315698632f:-8000" parent="75289c83:1315698632f:-7fff"/></XcosDiagram> media: gallery154.png + script_dump: '//Chapter 9 + + //Example 9.7 + + //page 355 + + //To evaluate Zbus using Current Injection method + + + disp("We can approach this problem using XCOS simulation") + + disp("In this simulation"); + + disp("1)For injecting unit current at bus1 keeping bus2 open circuit,we use + a current source of 1 unit which is switched on from t=0 to t=2. During this + period we can observe the voltage waveforms of V1 and V2 and compare with the + results given in the textbook"); + + disp("2)For injecting unit current at bus2 keeping bus1 open circuit,we use + a current source of 1 unit which is switched on from t=4 to t=6. During this + period we can observe the voltage waveforms of V1 and V2 and compare with the + results given in the textbook"); + + + Z11=7; + + Z21=4; + + Z12=Z21; + + Z22=6; + + + Zbus=[Z11 Z12;Z21 Z22]' |