├── .gitattributes
├── .gitignore
├── LICENSE
├── Linear Quadratic Regulators.pdf
├── Matavecontrol.prj
├── Model Predictive Control for an artifical pancreas - Matias Sørensen og Simon Kristiansen.pdf
├── README.md
├── Table of functions.odt
├── Table of functions.pdf
├── examples
├── bodeExample.m
├── bodeExampleMATLAB.png
├── bodeExampleOctave.png
├── c2dExample.m
├── c2dExampleMATLAB.png
├── c2dExampleOctave.png
├── examples.md
├── kf_qmpcExample.m
├── kf_qmpcExampleMATLAB.png
├── mpcExample.m
├── mpcExampleMATLAB.png
├── nyquistExample.m
├── nyquistExampleMATLAB.png
├── nyquistExampleOctave.png
├── stateSpaceExample.m
├── stateSpaceExampleMATLAB.png
├── stateSpaceExampleOctave.png
├── stepExample.m
├── stepExampleMATLAB.png
├── stepExampleOctave.png
├── transferFunctionExmaple.m
├── transferFunctionExmapleMATLAB.png
└── transferFunctionExmapleOctave.png
├── listOfFunctions
├── matave
├── +mc
│ ├── acker.m
│ ├── allmargin.m
│ ├── append.m
│ ├── are.m
│ ├── arma.m
│ ├── balreal.m
│ ├── bode.m
│ ├── bodemag.m
│ ├── c2d.m
│ ├── c2dt.m
│ ├── chirp.m
│ ├── conv2fft.m
│ ├── covar.m
│ ├── ctrb.m
│ ├── d2c.m
│ ├── d2d.m
│ ├── damp.m
│ ├── db2mag.m
│ ├── dbdrop.m
│ ├── dcgain.m
│ ├── evalfr.m
│ ├── feedback.m
│ ├── findmaxgain.m
│ ├── fminsearch.m
│ ├── freqresp.m
│ ├── gensig.m
│ ├── gram.m
│ ├── hsvd.m
│ ├── imc.m
│ ├── impulse.m
│ ├── initial.m
│ ├── kf_qmpc.m
│ ├── linprog.m
│ ├── listOfFunctions
│ ├── lmpc.m
│ ├── loop.m
│ ├── lqe.m
│ ├── lqgreg.m
│ ├── lqi.m
│ ├── lqr.m
│ ├── lsim.m
│ ├── lyap.m
│ ├── mag2db.m
│ ├── margin.m
│ ├── minreal.m
│ ├── modred.m
│ ├── nlsim.m
│ ├── nyquist.m
│ ├── obsv.m
│ ├── pade.m
│ ├── parallel.m
│ ├── pid.m
│ ├── pipd.m
│ ├── pole.m
│ ├── pzmap.m
│ ├── qmpc.m
│ ├── quadprog.m
│ ├── ramp.m
│ ├── referencegain.m
│ ├── reg.m
│ ├── rlocfind.m
│ ├── rlocus.m
│ ├── satlsim.m
│ ├── sensitivity.m
│ ├── series.m
│ ├── sgrid.m
│ ├── sigma.m
│ ├── smithpredict.m
│ ├── ss.m
│ ├── ss2tf.m
│ ├── step.m
│ ├── tf.m
│ ├── tf2ss.m
│ ├── tzero.m
│ ├── updatematavecontrol.m
│ ├── zero.m
│ └── zpk.m
└── README.md
└── resources
└── project
├── EEtUlUb-dLAdf0KpMVivaUlztwA
├── yjq8T9-gQYy0f2NhORonQUngnPgd.xml
└── yjq8T9-gQYy0f2NhORonQUngnPgp.xml
├── NjSPEMsIuLUyIpr2u1Js5bVPsOs
├── 2kj09UetkV_lru3gvSPXnY6-nM4d.xml
├── 2kj09UetkV_lru3gvSPXnY6-nM4p.xml
├── KKyDJtbdIBOlaeHmIZd5VX6vqx8d.xml
├── KKyDJtbdIBOlaeHmIZd5VX6vqx8p.xml
├── QWNDYJD5mGW1bWYvPx9DtKnxzw4d.xml
├── QWNDYJD5mGW1bWYvPx9DtKnxzw4p.xml
├── R1RggVhA72agIvELiuhWPRS8F0Id.xml
├── R1RggVhA72agIvELiuhWPRS8F0Ip.xml
├── aEHSZBIY-yve10yGis12Zr5DLZod.xml
├── aEHSZBIY-yve10yGis12Zr5DLZop.xml
├── j4xwF_j8iFTVayUMfxLgMnTbencd.xml
├── j4xwF_j8iFTVayUMfxLgMnTbencp.xml
├── r8LR4nLmg9ai3oHrW1r_-KocQzkd.xml
└── r8LR4nLmg9ai3oHrW1r_-KocQzkp.xml
├── OfxnnyUcu5GSELEDRUyOXcMZW0c
├── 0svTqDZyxKsHr8tr9l_5tqIMcqwd.xml
├── 0svTqDZyxKsHr8tr9l_5tqIMcqwp.xml
├── 0tLh2TRaHNLS2qzQDqexHEHLXVMd.xml
├── 0tLh2TRaHNLS2qzQDqexHEHLXVMp.xml
├── 96SFBJ-bIQLnHvDLQUTQfLO8XDod.xml
├── 96SFBJ-bIQLnHvDLQUTQfLO8XDop.xml
├── _MRJWxV8DfREsKhDtvTq3Jjm_RQd.xml
├── _MRJWxV8DfREsKhDtvTq3Jjm_RQp.xml
├── icQfkkI3t1PC4Ek0YY0fHihS5Yod.xml
├── icQfkkI3t1PC4Ek0YY0fHihS5Yop.xml
├── oSQ_nBKlxRWiL15nEg7_Rn5-agId.xml
├── oSQ_nBKlxRWiL15nEg7_Rn5-agIp.xml
├── qzR9VwkbUp-oa5a1uN0CPiHvfNId.xml
├── qzR9VwkbUp-oa5a1uN0CPiHvfNIp.xml
├── ySuCV85gsbuVjl71P1huo8omBFQd.xml
└── ySuCV85gsbuVjl71P1huo8omBFQp.xml
├── Project.xml
├── Y0MXjQcTETsDYSfZOITJxehWTOQ
├── -CoAOABvy9cuGUC38ZyaKbdeLOwd.xml
├── -CoAOABvy9cuGUC38ZyaKbdeLOwp.xml
├── -SbeBzw66TzYB4FU3szMFT_cuxAd.xml
├── -SbeBzw66TzYB4FU3szMFT_cuxAp.xml
├── -uWRYmmAnEkaEOZhJsoOtba7DlEd.xml
├── -uWRYmmAnEkaEOZhJsoOtba7DlEp.xml
├── 11XmEjI_K5BBZNuXErv9HOmoVb4d.xml
├── 11XmEjI_K5BBZNuXErv9HOmoVb4p.xml
├── 1KTluOp16-oR5v3JUK0UHA8e6WUd.xml
├── 1KTluOp16-oR5v3JUK0UHA8e6WUp.xml
├── 1w-nJuyPlyAftYmX_f8A0UO2RoYd.xml
├── 1w-nJuyPlyAftYmX_f8A0UO2RoYp.xml
├── 2-za1lJr8fVK3PJ1MHlXunw5Oskd.xml
├── 2-za1lJr8fVK3PJ1MHlXunw5Oskp.xml
├── 2rEj_f0GPdtD554fpQNmyoBcu3Id.xml
├── 2rEj_f0GPdtD554fpQNmyoBcu3Ip.xml
├── 4DRfx5bQIrL3zJNHm7GLriyLfqUd.xml
├── 4DRfx5bQIrL3zJNHm7GLriyLfqUp.xml
├── 4PanJm-mPEJlkWhsC591LHn6aiYd.xml
├── 4PanJm-mPEJlkWhsC591LHn6aiYp.xml
├── 54Nzb97VcU2zBkaWOgRp2fge9pcd.xml
├── 54Nzb97VcU2zBkaWOgRp2fge9pcp.xml
├── 5623OBuXkEpLP79xKtBFRnkKHTwd.xml
├── 5623OBuXkEpLP79xKtBFRnkKHTwp.xml
├── 6Bh2D-xMzXRKqe6s6nncGX_LLq4d.xml
├── 6Bh2D-xMzXRKqe6s6nncGX_LLq4p.xml
├── 6oFg1XfxuDHhfjP4t4s5xOHzcrsd.xml
├── 6oFg1XfxuDHhfjP4t4s5xOHzcrsp.xml
├── 7IW8qVfB6kZF63giXtxVXReB9SUd.xml
├── 7IW8qVfB6kZF63giXtxVXReB9SUp.xml
├── 7oOVoMxiTqU8K6QQ4sUkZO9RP2Ud.xml
├── 7oOVoMxiTqU8K6QQ4sUkZO9RP2Up.xml
├── 7zY7EuVRFOGx43YZ-Y9TIffdlRMd.xml
├── 7zY7EuVRFOGx43YZ-Y9TIffdlRMp.xml
├── B67JrGieaCPkkHupmiFqKtCE6pUd.xml
├── B67JrGieaCPkkHupmiFqKtCE6pUp.xml
├── BWbN1hILgy2Xnv7NeEd_GOhnYVkd.xml
├── BWbN1hILgy2Xnv7NeEd_GOhnYVkp.xml
├── BdYYMugAhyen8aTKF0WVSC5CJMYd.xml
├── BdYYMugAhyen8aTKF0WVSC5CJMYp.xml
├── BrnqdsK_ogt7Lib0tBOndoDjD_Yd.xml
├── BrnqdsK_ogt7Lib0tBOndoDjD_Yp.xml
├── Cn9iMC8MNPNB5JDsln6zVltnWPYd.xml
├── Cn9iMC8MNPNB5JDsln6zVltnWPYp.xml
├── Cr5mcv7j6DQanwB6ElyAlI8bUJsd.xml
├── Cr5mcv7j6DQanwB6ElyAlI8bUJsp.xml
├── FFPwQdZhJJjzWviOr_Y8ow76HHEd.xml
├── FFPwQdZhJJjzWviOr_Y8ow76HHEp.xml
├── IdnWZbYNeczTHna-1KgMBVw3dTkd.xml
├── IdnWZbYNeczTHna-1KgMBVw3dTkp.xml
├── ItT4tYcXdZiwyGq2gNplYIZi-5kd.xml
├── ItT4tYcXdZiwyGq2gNplYIZi-5kp.xml
├── JyUYT_XYg4otoIQ8t01K4919hBUd.xml
├── JyUYT_XYg4otoIQ8t01K4919hBUp.xml
├── K73qDanDhcbDYKqjaFwytbLwGKgd.xml
├── K73qDanDhcbDYKqjaFwytbLwGKgp.xml
├── Ks44_1yuOlA02cwQtl9Hj_VSmGQd.xml
├── Ks44_1yuOlA02cwQtl9Hj_VSmGQp.xml
├── KyuCQK9P5YV7bEjabcSd4q48gY8d.xml
├── KyuCQK9P5YV7bEjabcSd4q48gY8p.xml
├── KzeaGeO1UH_COx-dXm2_DAEReEcd.xml
├── KzeaGeO1UH_COx-dXm2_DAEReEcp.xml
├── N2RPtkh5ZI7i2sSZ9SOs-pP9cw0d.xml
├── N2RPtkh5ZI7i2sSZ9SOs-pP9cw0p.xml
├── Q0mF6K2JACo0hwfoTHRiZIIs0UUd.xml
├── Q0mF6K2JACo0hwfoTHRiZIIs0UUp.xml
├── SeEYVLuQTDVvsjYSRnAtdr_2NhQd.xml
├── SeEYVLuQTDVvsjYSRnAtdr_2NhQp.xml
├── V0cZFTBU3_EpgkWw_Io5Y6jlFZgd.xml
├── V0cZFTBU3_EpgkWw_Io5Y6jlFZgp.xml
├── W-Du79i4Ko3EezEp2M74qz5SYusd.xml
├── W-Du79i4Ko3EezEp2M74qz5SYusp.xml
├── Yb-7rgk-EbjB7wP6z2IdIPPvUlAd.xml
├── Yb-7rgk-EbjB7wP6z2IdIPPvUlAp.xml
├── YopdEcictGnkIQ_5prpSJs34qMkd.xml
├── YopdEcictGnkIQ_5prpSJs34qMkp.xml
├── Yvbp9FUZKCSQJncgLoI5reinE8gd.xml
├── Yvbp9FUZKCSQJncgLoI5reinE8gp.xml
├── ZSr63X3mMNEhpHVxHT_0ldMLNqYd.xml
├── ZSr63X3mMNEhpHVxHT_0ldMLNqYp.xml
├── _K78ptPkoib18O_M5mDAripZWUkd.xml
├── _K78ptPkoib18O_M5mDAripZWUkp.xml
├── _dBbd0q9a5geL--6i8vH8WvsZbEd.xml
├── _dBbd0q9a5geL--6i8vH8WvsZbEp.xml
├── _yABYToFV-Vjbphro5wtF2zF0NAd.xml
├── _yABYToFV-Vjbphro5wtF2zF0NAp.xml
├── bhnlN9XOEJ1B6NEw30i-8lD3XSwd.xml
├── bhnlN9XOEJ1B6NEw30i-8lD3XSwp.xml
├── cVDmIEZqQ6RuSQlM-GFDxsJK8Fcd.xml
├── cVDmIEZqQ6RuSQlM-GFDxsJK8Fcp.xml
├── cj0dX_uC53Jt6gPqFnKbLR1-iJMd.xml
├── cj0dX_uC53Jt6gPqFnKbLR1-iJMp.xml
├── crViRB3JW-vZT9LEYWdXpvxIyIEd.xml
├── crViRB3JW-vZT9LEYWdXpvxIyIEp.xml
├── jMspD52-8pQRDJM84VawTeYB670d.xml
├── jMspD52-8pQRDJM84VawTeYB670p.xml
├── jXytGzI4O2iQkm5Iid_M99e7kl8d.xml
├── jXytGzI4O2iQkm5Iid_M99e7kl8p.xml
├── jegMYt-Jgzo1xmWNIPX-xdbhG18d.xml
├── jegMYt-Jgzo1xmWNIPX-xdbhG18p.xml
├── kFa7fP1qhyzvenZPkkRfV8neELgd.xml
├── kFa7fP1qhyzvenZPkkRfV8neELgp.xml
├── k_LDNoMhWM_ftCTzKT4LUnl8z1Id.xml
├── k_LDNoMhWM_ftCTzKT4LUnl8z1Ip.xml
├── kdyNwcW_EV1D4OcQHOT0h5ui6oUd.xml
├── kdyNwcW_EV1D4OcQHOT0h5ui6oUp.xml
├── lTNcbFF3WgZbJrqXWWqgs1AlWFUd.xml
├── lTNcbFF3WgZbJrqXWWqgs1AlWFUp.xml
├── mLjyaWT3h9G6pnHN4E1ZmZnWDDwd.xml
├── mLjyaWT3h9G6pnHN4E1ZmZnWDDwp.xml
├── nxHIvmYl91RxdSAAehuvNMiMvM0d.xml
├── nxHIvmYl91RxdSAAehuvNMiMvM0p.xml
├── q0SFswbWjtAqBsGhTVKi6kBxqmAd.xml
├── q0SFswbWjtAqBsGhTVKi6kBxqmAp.xml
├── qOqHwCrRHme4LTDtVseEt6L5eN8d.xml
├── qOqHwCrRHme4LTDtVseEt6L5eN8p.xml
├── qY_esZacgV_-CBdwSlj-x3tae5cd.xml
├── qY_esZacgV_-CBdwSlj-x3tae5cp.xml
├── qn_WO7trpHLQ8MBDNf14xTjUXv8d.xml
├── qn_WO7trpHLQ8MBDNf14xTjUXv8p.xml
├── sZsojGNj1Xsew2r2cjrxgTtJiz4d.xml
├── sZsojGNj1Xsew2r2cjrxgTtJiz4p.xml
├── t6G0dleSjZRdaE0mqOxDKu4M8xsd.xml
├── t6G0dleSjZRdaE0mqOxDKu4M8xsp.xml
├── t6Xz-myNiIJid1uOQBu3M-Z_hf4d.xml
├── t6Xz-myNiIJid1uOQBu3M-Z_hf4p.xml
├── tmzg2FyGbnUr4U5BapcMKI6CS7Ed.xml
├── tmzg2FyGbnUr4U5BapcMKI6CS7Ep.xml
├── utwGE9hQzpXV3PZxiEjFjWMyMeAd.xml
├── utwGE9hQzpXV3PZxiEjFjWMyMeAp.xml
├── x-l6L7vAJyYBtn-SDFTmhDDN-MAd.xml
├── x-l6L7vAJyYBtn-SDFTmhDDN-MAp.xml
├── x4GzzdUEvl5vK1S2qWPJ8s1NfPYd.xml
├── x4GzzdUEvl5vK1S2qWPJ8s1NfPYp.xml
├── xNX7uGtM_e36nIF5tMGLJYQgs_4d.xml
├── xNX7uGtM_e36nIF5tMGLJYQgs_4p.xml
├── xi57K6yo7qEW6cfchYEdjcWGnkcd.xml
├── xi57K6yo7qEW6cfchYEdjcWGnkcp.xml
├── xyaFs-562jwpSMpoHmrjkNpXI3kd.xml
├── xyaFs-562jwpSMpoHmrjkNpXI3kp.xml
├── yMp73CpOLXJfFwcL5zbkVD1Dgpod.xml
├── yMp73CpOLXJfFwcL5zbkVD1Dgpop.xml
├── yvnfTAHHm4btVWqLUrENzD5XMNsd.xml
├── yvnfTAHHm4btVWqLUrENzD5XMNsp.xml
├── zDJYuT22rAyRg0WvG1AdowAaXN4d.xml
├── zDJYuT22rAyRg0WvG1AdowAaXN4p.xml
├── zgQIfZQSIp7WL4NSqDq4njhDAOcd.xml
├── zgQIfZQSIp7WL4NSqDq4njhDAOcp.xml
├── zr_37WR-HxanuIcLCVDyLghcKzAd.xml
└── zr_37WR-HxanuIcLCVDyLghcKzAp.xml
├── fjRQtWiSIy7hIlj-Kmk87M7s21k
├── NjSPEMsIuLUyIpr2u1Js5bVPsOsd.xml
└── NjSPEMsIuLUyIpr2u1Js5bVPsOsp.xml
├── lPZI5oa5DxrsR-PK7aQQLq3WqrE
├── Miy75s7SKM4dtkSrAQrwPD2Pnvsd.xml
├── Miy75s7SKM4dtkSrAQrwPD2Pnvsp.xml
├── Y0MXjQcTETsDYSfZOITJxehWTOQd.xml
├── Y0MXjQcTETsDYSfZOITJxehWTOQp.xml
├── tzlQc0NLrARVg_2cChAq5muGE2Ud.xml
└── tzlQc0NLrARVg_2cChAq5muGE2Up.xml
├── qaw0eS1zuuY1ar9TdPn1GMfrjbQ
├── OfxnnyUcu5GSELEDRUyOXcMZW0cd.xml
├── OfxnnyUcu5GSELEDRUyOXcMZW0cp.xml
├── TMK4UzWHdRLhy_w-CHt9y11Q8XAd.xml
├── TMK4UzWHdRLhy_w-CHt9y11Q8XAp.xml
├── lPZI5oa5DxrsR-PK7aQQLq3WqrEd.xml
├── lPZI5oa5DxrsR-PK7aQQLq3WqrEp.xml
├── qD-kr16wmwlzR-nIg1IG_vvRrWkd.xml
└── qD-kr16wmwlzR-nIg1IG_vvRrWkp.xml
├── root
├── 6x1BhZX_fLnKpcwqra0qFwv1jIgp.xml
├── EEtUlUb-dLAdf0KpMVivaUlztwAp.xml
├── GiiBklLgTxteCEmomM8RCvWT0nQd.xml
├── GiiBklLgTxteCEmomM8RCvWT0nQp.xml
├── KAXfQgCar2Yb8zOxgvf9hdmLP1Ep.xml
├── NmGqIpAwUJcXFyLjFAGnU9uyN5Yp.xml
├── fjRQtWiSIy7hIlj-Kmk87M7s21kp.xml
└── qaw0eS1zuuY1ar9TdPn1GMfrjbQp.xml
├── rootp.xml
└── uuid-f651a9a5-b7b9-4361-b11c-7c91771b35e7.xml
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.fig binary
2 | *.mat binary
3 | *.mdl binary diff merge=mlAutoMerge
4 | *.mdlp binary
5 | *.mex* binary
6 | *.mlapp binary
7 | *.mldatx binary
8 | *.mlproj binary
9 | *.mlx binary
10 | *.p binary
11 | *.sfx binary
12 | *.sldd binary
13 | *.slreqx binary merge=mlAutoMerge
14 | *.slmx binary merge=mlAutoMerge
15 | *.sltx binary
16 | *.slxc binary
17 | *.slx binary merge=mlAutoMerge
18 | *.slxp binary
19 |
20 | ## Other common binary file types
21 | *.docx binary
22 | *.exe binary
23 | *.jpg binary
24 | *.pdf binary
25 | *.png binary
26 | *.xlsx binary
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Autosave files
2 | *.asv
3 | *.m~
4 | *.autosave
5 | *.slx.r*
6 | *.mdl.r*
7 |
8 | # Derived content-obscured files
9 | *.p
10 |
11 | # Compiled MEX files
12 | *.mex*
13 |
14 | # Packaged app and toolbox files
15 | *.mlappinstall
16 | *.mltbx
17 |
18 | # Deployable archives
19 | *.ctf
20 |
21 | # Generated helpsearch folders
22 | helpsearch*/
23 |
24 | # Code generation folders
25 | slprj/
26 | sccprj/
27 | codegen/
28 |
29 | # Cache files
30 | *.slxc
31 |
32 | # Cloud based storage dotfile
33 | .MATLABDriveTag
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Daniel Mårtensson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Linear Quadratic Regulators.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/Linear Quadratic Regulators.pdf
--------------------------------------------------------------------------------
/Matavecontrol.prj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Model Predictive Control for an artifical pancreas - Matias Sørensen og Simon Kristiansen.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/Model Predictive Control for an artifical pancreas - Matias Sørensen og Simon Kristiansen.pdf
--------------------------------------------------------------------------------
/Table of functions.odt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/Table of functions.odt
--------------------------------------------------------------------------------
/Table of functions.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/Table of functions.pdf
--------------------------------------------------------------------------------
/examples/bodeExample.m:
--------------------------------------------------------------------------------
1 | G = mc.tf(10,[1 2 3]);
2 |
3 | mc.bode(G,0.01, 100);
--------------------------------------------------------------------------------
/examples/bodeExampleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/bodeExampleMATLAB.png
--------------------------------------------------------------------------------
/examples/bodeExampleOctave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/bodeExampleOctave.png
--------------------------------------------------------------------------------
/examples/c2dExample.m:
--------------------------------------------------------------------------------
1 | G = mc.tf(10,[1 2 3])
2 |
3 | Gd = mc.c2d(G,0.5)
4 |
5 | mc.step(Gd);
--------------------------------------------------------------------------------
/examples/c2dExampleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/c2dExampleMATLAB.png
--------------------------------------------------------------------------------
/examples/c2dExampleOctave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/c2dExampleOctave.png
--------------------------------------------------------------------------------
/examples/examples.md:
--------------------------------------------------------------------------------
1 | # Examples
2 | This folder containts some simple examples.
3 |
--------------------------------------------------------------------------------
/examples/kf_qmpcExampleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/kf_qmpcExampleMATLAB.png
--------------------------------------------------------------------------------
/examples/mpcExample.m:
--------------------------------------------------------------------------------
1 | close all
2 | clear all
3 | clc
4 |
5 | sys = mc.ss(0, [0 1; -1 -1], [0;1], [1 0]); % SISO state space model
6 |
7 | sysd = mc.c2d(sys, 0.5); % To discrete
8 |
9 | R = [6]; % Reference for the SISO model. If MIMO -> R need to be a vector
10 | N = 10; % Horizon predict constant
11 | T = 35; % Horizon time constant
12 | lambda = 7; % Regularization for smoother inputs u
13 |
14 | [y, t, x, u] = mc.lmpc(sysd, N, R, T, lambda); % Simulate MPC with linear programming
15 | hold on
16 | plot(t, u)
17 |
18 | I = 0.2; % Integral action constant
19 | Umax = [0.4]; % Maximum input signal vector
20 | S = [2]; % Slack variable says that the output can be +2 over the reference R, in this case: 6+2 = 8
21 | lambda = 0.2; % Regularization for smoother inputs u
22 | figure(2); % New figure
23 | x0 = [-8; 20];
24 | [y, t, x, u] = mc.qmpc(sysd, N, R, T, lambda, Umax, S, I, x0); % Simulate MPC with quadratic programming
25 | hold on
26 | plot(t, u)
27 |
--------------------------------------------------------------------------------
/examples/mpcExampleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/mpcExampleMATLAB.png
--------------------------------------------------------------------------------
/examples/nyquistExample.m:
--------------------------------------------------------------------------------
1 | G = mc.tf(10,[1 2 3])
2 |
3 | mc.nyquist(G,0.01,100)
--------------------------------------------------------------------------------
/examples/nyquistExampleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/nyquistExampleMATLAB.png
--------------------------------------------------------------------------------
/examples/nyquistExampleOctave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/nyquistExampleOctave.png
--------------------------------------------------------------------------------
/examples/stateSpaceExample.m:
--------------------------------------------------------------------------------
1 | sys = mc.ss(3,[ 0 1; -2 -3],[0;1],[1 0;0 1],[0;0])
--------------------------------------------------------------------------------
/examples/stateSpaceExampleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/stateSpaceExampleMATLAB.png
--------------------------------------------------------------------------------
/examples/stateSpaceExampleOctave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/stateSpaceExampleOctave.png
--------------------------------------------------------------------------------
/examples/stepExample.m:
--------------------------------------------------------------------------------
1 | sys = mc.ss(3,[ 0 1; -2 -3],[0;1],[1 0;0 1],[0;0])
2 |
3 | mc.step(sys,5);
--------------------------------------------------------------------------------
/examples/stepExampleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/stepExampleMATLAB.png
--------------------------------------------------------------------------------
/examples/stepExampleOctave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/stepExampleOctave.png
--------------------------------------------------------------------------------
/examples/transferFunctionExmaple.m:
--------------------------------------------------------------------------------
1 | G = mc.tf(10,[1 2 3])
--------------------------------------------------------------------------------
/examples/transferFunctionExmapleMATLAB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/transferFunctionExmapleMATLAB.png
--------------------------------------------------------------------------------
/examples/transferFunctionExmapleOctave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DanielMartensson/MataveControl/36abe64cc9b00b17f6cff5e9c916321fb74a6d0a/examples/transferFunctionExmapleOctave.png
--------------------------------------------------------------------------------
/listOfFunctions:
--------------------------------------------------------------------------------
1 | acker.m
2 | allmargin.m
3 | append.m
4 | are.m
5 | balreal.m
6 | bode.m
7 | bodemag.m
8 | c2d.m
9 | c2dt.m
10 | covar.m
11 | ctrb.m
12 | d2c.m
13 | d2d.m
14 | damp.m
15 | db2mag.m
16 | dbdrop.m
17 | dcgain.m
18 | evalfr.m
19 | feedback.m
20 | findmaxgain.m
21 | freqresp.m
22 | gensig.m
23 | gram.m
24 | hsvd.m
25 | imc.m
26 | impulse.m
27 | initial.m
28 | loop.m
29 | lmpc.m
30 | qmpc.m
31 | lqe.m
32 | lqgreg.m
33 | lqi.m
34 | lqr.m
35 | lsim.m
36 | lyap.m
37 | mag2db.m
38 | margin.m
39 | minreal.m
40 | modred.m
41 | satlsim.m
42 | nyquist.m
43 | obsv.m
44 | pade.m
45 | parallel.m
46 | pid.m
47 | pipd.m
48 | pole.m
49 | pzmap.m
50 | ramp.m
51 | referencegain.m
52 | reg.m
53 | rlocus.m
54 | rlocfind.m
55 | sensitivity.m
56 | series.m
57 | sgrid.m
58 | sigma.m
59 | smithpredict.m
60 | ss.m
61 | ss2tf.m
62 | step.m
63 | tf.m
64 | tf2ss.m
65 | tzero.m
66 | updatematavecontrol.m
67 | zero.m
68 | zpk.m
69 | nlsim.m
70 | fminsearch.m
71 | arma.m
72 | chirp.m
73 | linprog.m
74 | quadprog.m
75 | conv2fft.m
76 | kf_qmpc.m
77 |
--------------------------------------------------------------------------------
/matave/+mc/acker.m:
--------------------------------------------------------------------------------
1 | % Generate control law gain matrix L of a state space model by using eigen values vector P
2 | % Input: G, sys, P
3 | % Example 1: [L] = mc.acker(sys, P)
4 | % Author: Daniel Mårtensson, October 2017
5 | % Source from Modern Control Engineering, Ogata, 3th edition.
6 |
7 | function [L] = acker(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % Get model
18 | sys = varargin{1};
19 | % Get matrecies
20 | A = sys.A;
21 | B = sys.B;
22 |
23 | % Check if B is SISO
24 | if(size(B, 2) > 1)
25 | error('Only SISO models!')
26 | end
27 |
28 | % Get eigen values
29 | if(length(varargin) >= 2)
30 | P = varargin{2};
31 | else
32 | error('Missing the closed loop poles')
33 | end
34 |
35 | % Vectorize P
36 | P = P(:);
37 | if(size(A,1) ~= length(P))
38 | error('Poles need to have the same dimension as matrix A')
39 | end
40 |
41 | % Create the control law gain matrix L
42 | %Formula from Ogata Modern Control Engineering
43 | Cm = mc.ctrb(sys); % Controllability matrix
44 | RealPoly = real(poly(P)); % Real polynomal of P
45 | L = Cm\polyvalm(RealPoly, A);
46 | L = L(size(A,2),:);
47 |
48 | % Check if the user has put in very bad pole locations
49 | P = sort(P);
50 | nonZeroPoles = find(P ~= 0);
51 | P = P(nonZeroPoles);
52 | % Sort the eigen values
53 | eigenvalues = sort(eig(A-B*L));
54 | % Ge the egenvalues which has non zero poles
55 | eigenvalues = eigenvalues(nonZeroPoles);
56 | % Get the absolute maximum value of P
57 | M = abs(P);
58 |
59 | % Get the difference between pole locations and eigen values
60 | Diff = abs(P-eigenvalues);
61 | if(max(Diff./M) > .05)
62 | disp('Warning: Pole locations are in more that 5% error')
63 | end
64 |
65 | elseif(strcmp(type, 'TF' ))
66 | disp('Only state space models only')
67 | else
68 | error('This is not TF or SS');
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/matave/+mc/allmargin.m:
--------------------------------------------------------------------------------
1 | % Print out all margins of a state space model or a
2 | % transfer function between frequencies w1 and w2
3 | % Input: sys, G, w1, w2
4 | % Example 1: S = mc.allmargin(sys, w1, w2)
5 | % Example 2: S = mc.allmargin(G, w1, w2)
6 | % Author: Daniel Mårtensson, Oktober 2017
7 |
8 | function [S] = allmargin(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | w2 = varargin{3};
21 | end
22 |
23 |
24 | % Get the type
25 | type = varargin{1}.type;
26 | % Check if there is a TF or SS model
27 | if(strcmp(type, 'SS' ))
28 | % SS to TF
29 | G = mc.ss2tf(varargin{1});
30 | % Call allmargin
31 | mc.allmargin(G, w1, w2);
32 | elseif(strcmp(type, 'TF' ))
33 | % If there is a MIMO TF
34 | G = varargin{1};
35 | for i = 1:size(G,1)
36 | for j = 1:size(G,2)
37 | % Get numerator vector and denomerator vector
38 | a = G(i,j).num;
39 | b = G(i,j).den;
40 | % Get delay
41 | delay = G(i,j).delay;
42 | % Get sample time
43 | sampleTime = G(i,j).sampleTime;
44 |
45 | % Numerator and denomerator need to be the same length
46 | if(length(a) > length(b))
47 | b = [zeros(1, size(a,2) - size(b,2)) b];
48 | elseif(length(a) < length(b))
49 | a = [zeros(1, size(b,2) - size(a,2)) a];
50 | end
51 |
52 | L = 10000; % Number of frequency elements
53 | N = length(b); % Number of denomerators
54 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
55 | % Evaluate transfer function
56 | H = zeros(1, L);
57 | h = sampleTime;
58 | if(sampleTime > 0) % Discrete model
59 | for k = 1 : L
60 | H(k) = (a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h));
61 | end
62 | else
63 | for k = 1 : L
64 | H(k) = (a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k));
65 | end
66 | end
67 | % Done!
68 |
69 | % Get wc, phim
70 | wc = inf;
71 | phim = inf;
72 | flag = false;
73 | for k = 1:length(H)
74 | % The dB need to be over 0 for flag = true
75 | if ((20*log10(abs(H(k))) > 0))
76 | flag = true;
77 | end
78 | % When dB is under 0 and flag = true
79 | if (and(20*log10(abs(H(k))) <= 0, flag == true ))
80 | wc = w(k);
81 | phim = 180 + angle(H(k)) * 180/pi;
82 | break;
83 | end
84 | end
85 |
86 | % Get wpi, Am
87 | wpi = inf;
88 | Am = inf;
89 | for k = 1:length(H)
90 | if (angle(H(k)) * 180/pi <= -180)
91 | wpi = w(k);
92 | Am = 20*log10(abs(H(k)));
93 | break;
94 | end
95 | end
96 |
97 | % Compute the delay margin
98 | Dm = pi*phim/(180*wc);
99 |
100 | % Check if it's stable
101 | p = mc.pole(G(i,j));
102 | stable = 1;
103 | for k = 1:length(p)
104 | if(real(p(k)) > 0)
105 | stable = 0; % Not stable! We got one positive pole!
106 | break;
107 | end
108 | end
109 |
110 | % Am
111 | Am = abs(Am);
112 |
113 | % Print it out
114 | % DMFrequency(Phidm) is the same as wc
115 | S(i,j) = {sprintf('Transfer function: %ix%i\nGainMargin(Am): %i\nGMFrequency(wpi): %i\nPhaseMargin(Phim): %i\nPMFrequency(Wc): %i\nDelayMargin(Dm): %i\nDMFrequency(Phidm): %i\nStable: %i\n', i, j, Am, wpi, phim, wc, Dm, wc, stable)};
116 |
117 |
118 | end
119 | end
120 | % Do cell2mat
121 | S = cell2mat(S);
122 | else
123 | error('Only transfer functions and state space models allowed')
124 | end
125 | end
126 |
--------------------------------------------------------------------------------
/matave/+mc/append.m:
--------------------------------------------------------------------------------
1 | % Append diffrent models into one large model and get a state space model
2 | % Input: G, sys
3 | % Example 1: sys = mc.append(G1, G2, sys1)
4 | % Example 2: sys = mc.append(sys1, sys2, G1, G2)
5 | % Author: Daniel Mårtensson, Oktober 2017
6 |
7 | function [sys] = append(varargin)
8 | if(isempty(varargin{1}))
9 | error ('Missing model')
10 | end
11 |
12 | % Get type from the first model
13 | type = varargin{1}.type;
14 |
15 | % State space
16 | if(or(strcmp(type, 'SS' ), strcmp(type, 'TF' )))
17 | for i = 1:length(varargin)
18 | % check if we need to convert that TF to SS
19 | type = varargin{i}.type;
20 | if(strcmp(type, 'TF' ))
21 | % Yes!
22 | sys = mc.tf2ss(varargin{i}, 'OCF');
23 | else
24 | % No!
25 | sys = varargin{i};
26 | end
27 | % Get the matrecies
28 | A = sys.A;
29 | B = sys.B;
30 | C = sys.C;
31 | D = sys.D;
32 |
33 | % The first one sets the default delay and sample time
34 | if(i == 1)
35 | firstdelay = sys.delay;
36 | firstsampleTime = sys.sampleTime;
37 | Apast = blkdiag([],A);
38 | Bpast = blkdiag([],B);
39 | Cpast = blkdiag([],C);
40 | Dpast = blkdiag([],D);
41 | else
42 | delay = sys.delay;
43 | sampleTime = sys.sampleTime;
44 | % The delay and sample time needs to be the same as the others
45 | if(and(firstdelay == delay, firstsampleTime == sampleTime))
46 | Apast = blkdiag(Apast,A);
47 | Bpast = blkdiag(Bpast,B);
48 | Cpast = blkdiag(Cpast,C);
49 | Dpast = blkdiag(Dpast,D);
50 | else
51 | error('Sample time or delay is not equal as the first model')
52 | end
53 | end
54 | end
55 | % Now we are done! Create the SS model now!
56 | sys = mc.ss(firstdelay, Apast, Bpast, Cpast, Dpast);
57 | sys.sampleTime = firstsampleTime;
58 | else
59 | error('No state space model or transfer function')
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/matave/+mc/arma.m:
--------------------------------------------------------------------------------
1 | % Generates a ARMA model from numerator vector and denomerator vector
2 | % Input: numerator, denomerator, sampleTime(optional), delay(optional)
3 | % Example 1: H = mc.arma(num, den)
4 | % Example 2: H = mc.arma(num, den, sampleTime)
5 | % Example 3: H = mc.arma(num, den, sampleTime, delay)
6 | % Author: Daniel Mårtensson, 2022 Oktober
7 |
8 | function [H] = arma(varargin)
9 | % Check if there is some input arguments
10 | if(isempty (varargin))
11 | error ('Missing arguments')
12 | end
13 | % OK. We have arguments!
14 |
15 | % Get numerator
16 | if(length(varargin) < 1)
17 | error('Missing numerator')
18 | else
19 | numerator = varargin{1};
20 | end
21 |
22 | % Get denomerator
23 | if(length(varargin) < 2)
24 | error('Missing denomerator')
25 | else
26 | denomerator = varargin{2};
27 | end
28 |
29 | % Get sampleTime
30 | if(length(varargin) >= 3)
31 | sampleTime = varargin{3};
32 | else
33 | sampleTime = 0;
34 | end
35 |
36 | % Check if there is some numerators
37 | if(isempty (numerator))
38 | error('Missing numerator');
39 | end
40 | % OK. We have numerators!
41 |
42 | % Check if there is some denomerators
43 | if(isempty (denomerator))
44 | error('Missing denomerator');
45 | end
46 | % OK. We have denomerator!
47 |
48 | % Make sure that we divide all with denomerator(1)
49 | if(denomerator(1) == 0)
50 | error('First number in the denomerator cannot be 0');
51 | else
52 | numerator = numerator/denomerator(1);
53 | denomerator = denomerator/denomerator(1);
54 | end
55 |
56 | % Create transfer function
57 | H.num = numerator;
58 | H.den = denomerator;
59 | H.delay = 0;
60 |
61 | % Add numerator
62 | tfnum = '';
63 | firstNumber = false;
64 | for i = 1:length(numerator)
65 | a = numerator(i);
66 | if(a > 0)
67 | if(or(i == 1, firstNumber == false))
68 | tfnum = strcat(tfnum, num2str(a), sprintf('z^-%i', i-1));
69 | firstNumber = true;
70 | else
71 | tfnum = strcat(tfnum, {' + '}, num2str(a), sprintf('z^-%i', i-1));
72 | end
73 | elseif(a < 0)
74 | tfnum = strcat(tfnum, {' '}, num2str(a), sprintf('z^-%i', i-1));
75 | end
76 | end
77 | H.tfnum = char(tfnum);
78 |
79 | % Add the dash lines
80 | H.tfdash = '-';
81 |
82 | % Add denomerator
83 | tfden = '1';
84 | for i = 2:length(denomerator)
85 | a = denomerator(i);
86 | if(a > 0)
87 | tfden = strcat(tfden, {' + '}, num2str(a), sprintf('z^-%i', i-1));
88 | elseif(a < 0)
89 | tfden = strcat(tfden, {' '}, num2str(a), sprintf('z^-%i', i-1));
90 | end
91 | end
92 | H.tfden = char(tfden(1,1));
93 |
94 | % Update the dash line
95 | H.tfdash = getDashedLine(H.tfnum, H.tfden);
96 |
97 | % Add type and sample time
98 | H.type = 'ARMA';
99 | H.sampleTime = sampleTime;
100 | end
101 |
102 |
103 | function [dash] = getDashedLine(numeratorString, denomeratorString)
104 | dash = '';
105 | if(length(numeratorString) <= length(denomeratorString))
106 | for i = 1:length(denomeratorString)
107 | dash = strcat(dash,'-');
108 | end
109 | else
110 | for i = 1:length(numeratorString)
111 | dash = strcat(dash,'-');
112 | end
113 | end
114 | end
115 |
--------------------------------------------------------------------------------
/matave/+mc/balreal.m:
--------------------------------------------------------------------------------
1 | % Generates the balanced realization of a state space model
2 | % Input: sys
3 | % Example 1: model = mc.balreal(sys)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 |
6 | function [model] = balreal(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing model')
10 | end
11 |
12 | % Get model type
13 | type = varargin{1}.type;
14 | % Check if there is a TF or SS model
15 | if(strcmp(type, 'SS' ))
16 | % Get sys
17 | sys = varargin{1};
18 | % Get gramians
19 | Q = mc.gram(sys, 'o');
20 | P = mc.gram(sys, 'c');
21 | % Get hankel singular values
22 | E = diag(mc.hsvd(sys));
23 |
24 | % Begin
25 | Q1 = chol(Q);
26 | U = chol(eye(size(Q)));
27 | E1 = chol(E);
28 |
29 | T = inv(E1)*U'*Q1;
30 |
31 | % Get matrecies
32 | A = sys.A;
33 | B = sys.B;
34 | C = sys.C;
35 | D = sys.D;
36 | delay = sys.delay;
37 | sampleTime = sys.sampleTime;
38 |
39 | model = mc.ss(delay, T*A*inv(T), T*B, C*inv(T), D);
40 | model.sampleTime = sampleTime;
41 | elseif(strcmp(type, 'TF' ))
42 | disp('Only state space model are allowed')
43 | else
44 | error('This is not TF or SS');
45 | end
46 |
47 | end
--------------------------------------------------------------------------------
/matave/+mc/bode.m:
--------------------------------------------------------------------------------
1 | % Plot the bode diagram of a state space model or a
2 | % transfer function between frequencies w1 and w2
3 | % Input: sys, G, w1, w2
4 | % Example 1: [mag, phase, wout] = mc.bode(sys, w1, w2)
5 | % Example 2: [mag, phase, wout] = mc.bode(G, w1, w2)
6 | % Author: Daniel Mårtensson, Oktober 2017
7 |
8 | function [mag, phase, wout] = bode(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | if(w1 == 0)
21 | w1 = 0.001;
22 | end
23 | w2 = varargin{3};
24 | end
25 |
26 | % Get the type
27 | type = varargin{1}.type;
28 | % Check if there is a TF or SS model
29 | if(strcmp(type, 'SS' ))
30 | % SS to TF
31 | G = mc.ss2tf(varargin{1});
32 | % Call bode
33 | [mag, phase, wout] = mc.bode(G, w1, w2);
34 | elseif(strcmp(type, 'TF' ))
35 | % If there is a MIMO TF
36 | G = varargin{1};
37 | for i = 1:size(G,1)
38 | for j = 1:size(G,2)
39 | % Get numerator vector and denomerator vector
40 | a = G(i,j).num;
41 | b = G(i,j).den;
42 | % Get delay
43 | delay = G(i,j).delay;
44 | % Get sample time
45 | sampleTime = G(i,j).sampleTime;
46 |
47 | % Numerator and denomerator need to be the same length
48 | if(length(a) > length(b))
49 | b = [zeros(1, size(a,2) - size(b,2)) b];
50 | elseif(length(a) < length(b))
51 | a = [zeros(1, size(b,2) - size(a,2)) a];
52 | end
53 |
54 | L = 1000; % Number of frequency elements
55 | N = length(b); % Number of denomerators
56 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
57 | % Evaluate transfer function
58 | H = zeros(1, L);
59 | h = sampleTime;
60 | if(sampleTime > 0) % Discrete model
61 | for k = 1 : L
62 | H(k) = (a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h));
63 | end
64 | else
65 | for k = 1 : L
66 | H(k) = (a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k));
67 | end
68 | end
69 |
70 | % Done!
71 | % Plot Bode diagram
72 | figure('Name', sprintf(strcat('Transfer function: ', num2str(i), 'x', num2str(j))))
73 | subplot(2,1,1)
74 | semilogx(w, 20*log10(abs(H)));
75 | ylabel('Magnitude [dB]');
76 | grid on
77 | subplot(2,1,2)
78 |
79 | BodeAngles = angle(H) * 180/pi;
80 | semilogx(w, BodeAngles);
81 | ylabel('Phase [deg]');
82 | xlabel('Frequency [rad/s]');
83 | grid on
84 |
85 | % Return these values
86 | mag = 20*log10(abs(H));
87 | phase = BodeAngles;
88 | wout = w;
89 | end
90 | end
91 | else
92 | error('Only transfer functions allowed')
93 | end
94 | end
95 |
--------------------------------------------------------------------------------
/matave/+mc/bodemag.m:
--------------------------------------------------------------------------------
1 | % Plot the bode diagram, without phase diagram, of a state space model or a
2 | % transfer function between frequencies w1 and w2
3 | % Input: sys, G, w1, w2
4 | % Example 1: mc.bodemag(sys, w1, w2)
5 | % Example 2: mc.bodemag(G, w1, w2)
6 | % Author: Daniel Mårtensson, Oktober 2017
7 |
8 | function [reval] = bodemag(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | if(w1 == 0)
21 | w1 = 0.001;
22 | end
23 | w2 = varargin{3};
24 | end
25 |
26 | % Get the type
27 | type = varargin{1}.type;
28 | % Check if there is a TF or SS model
29 | if(strcmp(type, 'SS' ))
30 | % SS to TF
31 | G = mc.ss2tf(varargin{1});
32 | % Call bode
33 | mc.bode(G, w1, w2);
34 | elseif(strcmp(type, 'TF' ))
35 | % If there is a MIMO TF
36 | G = varargin{1};
37 | for i = 1:size(G,1)
38 | for j = 1:size(G,2)
39 | % Get numerator vector and denomerator vector
40 | a = G(i,j).num;
41 | b = G(i,j).den;
42 | % Get delay
43 | delay = G(i,j).delay;
44 | % Get sample time
45 | sampleTime = G(i,j).sampleTime;
46 |
47 | % Numerator and denomerator need to be the same length
48 | if(length(a) > length(b))
49 | b = [zeros(1, size(a,2) - size(b,2)) b];
50 | elseif(length(a) < length(b))
51 | a = [zeros(1, size(b,2) - size(a,2)) a];
52 | end
53 |
54 | L = 1000; % Number of frequency elements
55 | N = length(b); % Number of denomerators
56 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
57 | % Evaluate transfer function
58 | H = zeros(1, L);
59 | h = sampleTime;
60 | if(sampleTime > 0) % Discrete model
61 | for k = 1 : L
62 | H(k) = (a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h));
63 | end
64 | else
65 | for k = 1 : L
66 | H(k) = (a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k));
67 | end
68 | end
69 |
70 |
71 | % Done!
72 | % Plot Bode diagram
73 |
74 | figure('Name', sprintf(strcat('Transfer function: ', num2str(i), 'x', num2str(j))))
75 | semilogx(w, 20*log10(abs(H)));
76 | ylabel('Magnitude [dB]');
77 | grid on
78 | end
79 | end
80 | else
81 | error('Only transfer functions allowed')
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/matave/+mc/c2d.m:
--------------------------------------------------------------------------------
1 | % Transform continuous time model to discrete model
2 | % Input: sys, G, sampeltime
3 | % Example 1: Gd = mc.c2d(G, sampleTime)
4 | % Example 2: sysd = mc.c2d(sys, sampleTime)
5 | % Author: Daniel Mårtensson, September 2017
6 |
7 | function [model] = c2d(varargin)
8 | if(isempty(varargin{1}))
9 | error ('Missing model')
10 | end
11 |
12 | if(isempty(varargin{2}))
13 | error ('Missing sampeltime')
14 | end
15 |
16 | % State space
17 | if(strcmp(varargin{1}.type, 'SS' ))
18 | % Get info
19 | A = varargin{1}.A;
20 | B = varargin{1}.B;
21 | C = varargin{1}.C;
22 | D = varargin{1}.D;
23 | delay = varargin{1}.delay;
24 | h = varargin{2};
25 | % Compute sizes
26 | a1 = size(A,2) + size(B,2) - size(A,1);
27 | b1 = size(A,2);
28 | a2 = size(A,2) + size(B,2) - size(B,1);
29 | b2 = size(B,2);
30 | % Compute square matrix
31 | M = [A B; zeros(a1, b1) zeros(a2, b2)];
32 | M = expm(M*h);
33 | % Find the discrete matrecies
34 | Ad = M(1:size(A,1), 1:size(A,2));
35 | Bd = M(1:size(B,1), (size(A,2) + 1):(size(A,2) + size(B,2)));
36 | model = mc.ss(delay, Ad, Bd, C, D);
37 | % Don't forget to add sample time
38 | model.sampleTime = h;
39 |
40 | % Transfer function
41 | elseif(strcmp(varargin{1}.type, 'TF' ))
42 | % Transform it to a state space model.
43 | sys = mc.tf2ss(varargin{1}, 'OCF');
44 | % Turn sys to discrete
45 | h = varargin{2};
46 | if(and(h > 0, sys.delay > 0))
47 | error('You cannot turn time continous transfer function with delay into discrete transfer function. Try state space instead: sys = mc.tf2ss(G) -> sysd = c2d(sys)');
48 | end
49 | model = mc.c2d(sys, h);
50 | % Turn it then into a tf
51 | model = mc.ss2tf(model);
52 | model.sampleTime = h;
53 | % Replace the delaytime to discrete delay time
54 | model.tfdash = strrep(model.tfdash, 'e', 'z');
55 | model.tfdash = strrep(model.tfdash, 's', '');
56 | % Remove all s -> s
57 | model.tfnum = strrep(model.tfnum, 's', 'z');
58 | model.tfden = strrep(model.tfden, 's', 'z');
59 | else
60 | error('No state space model or transfer function')
61 | end
62 |
63 | end
64 |
--------------------------------------------------------------------------------
/matave/+mc/c2dt.m:
--------------------------------------------------------------------------------
1 | % Transform a state space model or transfer function to discrete state space model with delay
2 | % Input: G, sys, sampleTime
3 | % Output: sysd(discrete state space model with delay), l(step prediction)
4 | % Example 1: [sysd, l] = mc.c2dt(G, sampleTime)
5 | % Example 2: [sysd, l] = mc.c2dt(sys, sampleTime)
6 | % Author: Daniel Mårtensson, Oktober 2017
7 | % Updated: 2018-03-04
8 |
9 | function [sysd, l] = c2dt(varargin)
10 | if(isempty(varargin{1}))
11 | error ('Missing model')
12 | end
13 |
14 | % Check sample time
15 | if(length(varargin) < 2)
16 | error ('Missing sample time')
17 | end
18 |
19 | % Get delay
20 | if(varargin{1}.delay <= 0)
21 | error('This model has no delay')
22 | end
23 |
24 | % Get type
25 | type = varargin{1}.type;
26 |
27 | % State space
28 | if(strcmp(type, 'SS' ))
29 | % Check if allready discrete
30 | if(varargin{1}.sampleTime > 0)
31 | % The model is allready discrete! Turn it back!
32 | sys = mc.d2c(varargin{1}, varargin{1}.sampleTime);
33 | A = sys.A;
34 | B = sys.B;
35 | C = sys.C;
36 | D = sys.D;
37 | sampleTime = sys.sampleTime; % Over write the sampleTime
38 | delay = sys.delay; % Get delay
39 | else
40 | % No! The model is not discrete!
41 | sys = varargin{1};
42 | A = sys.A;
43 | B = sys.B;
44 | C = sys.C;
45 | D = sys.D;
46 | sampleTime = varargin{2}; % Get the sample time
47 | delay = sys.delay;
48 | end
49 |
50 | % Original Source: Digital Control Of Dynamic Systems - G.F Franklin
51 | % Modified by me!
52 |
53 | % Get sizes of input and output matrix
54 | [bx,by] = size(B);
55 | [cx,cy] = size(C);
56 | l = ceil(delay/sampleTime); % Check of delay is less that sampleTime - Round up
57 | m = l*sampleTime - delay;
58 |
59 | % Create discrete matrecies s1, s2 s3 etc
60 | s1 = expm([A*m, B*m; zeros(by,bx+by)]);
61 | s2 = expm([A*(sampleTime-m), B*(sampleTime-m); zeros(by,bx+by)]);
62 | s3 = eye((l-1)*by);
63 | s4 = zeros(cy,(l-2)*by);
64 | s5 = zeros((l-1)*by,bx+by);
65 | s6 = zeros(by,bx+l*by);
66 |
67 | P = s1(1:bx, 1:bx)*s2(1:bx, 1:bx);
68 | H1 = s1(1:bx, 1:bx)*s2(1:bx, bx+1:bx+by);
69 | H2 = s1(1:bx, bx+1:bx+by);
70 | if(l == 1) % If the delay is less that sampleTime
71 | A = [P, H1; s6];
72 | B = [H2; eye(by)];
73 | C = [C, zeros(cx, by)];
74 | D = zeros(cx, by);
75 | else % If the delay is more that sampleTime
76 | A = [P, H1, H2, s4; s5, s3; s6];
77 | B = [zeros(bx+(l-1)*by, by); eye(by)];
78 | C = [C,zeros(cx, l*by)];
79 | D = zeros(cx, by);
80 | end
81 | % Get the discrete state space model now
82 | sysd = mc.ss(delay, A, B, C, D);
83 | sysd.sampleTime = sampleTime; % Get the sample time
84 |
85 | elseif(strcmp(type, 'TF' ))
86 | % Check if allready discrete
87 | if(varargin{1}.sampleTime > 0)
88 | % Yes! The model is discrete! Turn it back!
89 | G = mc.d2c(varargin{1}, varargin{1}.sampleTime);
90 | % TF to SS
91 | sys = mc.tf2ss(G, 'OCF');
92 | % Get the sample time
93 | sampleTime = varargin{1}.sampleTime;
94 | % Call c2dt
95 | [sysd, l] = mc.c2dt(sys, sampleTime);
96 | else
97 | % TF to SS
98 | G = varargin{1};
99 | sys = mc.tf2ss(G, 'OCF');
100 | % Get the sample time
101 | sampleTime = varargin{2};
102 | % Call c2dt
103 | [sysd, l] = mc.c2dt(sys, sampleTime);
104 | end
105 | else
106 | error('No state space model or transfer function')
107 | end
108 | end
109 |
--------------------------------------------------------------------------------
/matave/+mc/chirp.m:
--------------------------------------------------------------------------------
1 |
2 | % Chirp - Generates a frequency signal
3 | % Input: t(time), A(amplitude, optional)
4 | % Output: u(signal), fs(sampling frequency)
5 | % Example 1: [u, fs] = mc.chirp(t);
6 | % Example 1: [u, fs] = mc.chirp(t, A);
7 | % Author: Daniel Mårtensson, Oktober 29:e 2022
8 |
9 | function [u, fs] = chirp(varargin)
10 | % Check if there is any input
11 | if(isempty(varargin))
12 | error('Missing inputs')
13 | end
14 |
15 | % Get time
16 | if(length(varargin) >= 1)
17 | t = varargin{1};
18 | else
19 | error('Missing time');
20 | end
21 |
22 | % Get amplitude
23 | if(length(varargin) >= 2)
24 | A = varargin{2};
25 | else
26 | A = 1;
27 | end
28 |
29 | % Create the length
30 | N = length(t);
31 |
32 | % Create the difference chirp duration
33 | T = t(end) - t(1);
34 |
35 | % Create the sampling frequency
36 | fs = 1/(T/N);
37 |
38 | % Create the start frequency
39 | f0 = 0;
40 |
41 | % Create the final frequency
42 | f1 = fs/2;
43 |
44 | % Create the chirp rate
45 | c = (f1-f0)/T;
46 |
47 | % Create the frequency signal
48 | u = A*sin(2*pi*(c/2*t.^2 + f0*t));
49 |
50 | end
51 |
--------------------------------------------------------------------------------
/matave/+mc/conv2fft.m:
--------------------------------------------------------------------------------
1 | % Convolution via FFT2
2 | % Input: X(Data matrix), K(Kernel matrix)
3 | % Output: C(Filtered data matrix)
4 | % Example 1: [C] = mc.conv2fft(X, K);
5 | % Author: Daniel Mårtensson, 24 September 2023
6 |
7 | function [C] = conv2fft(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error('Missing input')
11 | end
12 |
13 | % Get input matrix X
14 | if(length(varargin) >= 1)
15 | X = varargin{1};
16 | else
17 | error('Missing input data matrix X')
18 | end
19 |
20 | % Get the sigma
21 | if(length(varargin) >= 2)
22 | K = varargin{2};
23 | else
24 | error('Missing kernel data matrix K')
25 | end
26 |
27 | % Create kernel
28 | [m, n] = size(X);
29 | kernel = zeros(m, n);
30 | [m, n] = size(K);
31 |
32 | % Compute the sizes
33 | m_middle = ceil(m/2);
34 | n_middle = m_middle;
35 |
36 | % Insert kernel
37 | kernel(1:m_middle, 1:n_middle) = K(m_middle:end, n_middle:end);
38 | kernel(end-m_middle+1:end, 1:n_middle) = K(1:m_middle, n_middle:end);
39 | kernel(1:m_middle, end-n_middle+1:end) = K(m_middle:end, 1:n_middle);
40 | kernel(end-m_middle+1:end, end-n_middle+1:end) = K(1:m_middle, 1:n_middle);
41 |
42 | % Do FFT2 on X and kernel
43 | A = fft2(X);
44 | B = fft2(kernel);
45 |
46 | % Compute the convolutional matrix - real to remove zero imaginary numbers
47 | C = real(ifft2(A.*B));
48 | end
49 |
--------------------------------------------------------------------------------
/matave/+mc/covar.m:
--------------------------------------------------------------------------------
1 | % Get the covariance matrix of a state space model with the intensity of Gaussian white noise matrix
2 | % Input: sys, W
3 | % Example: [P] = mc.covar(sys, W)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 |
6 | function [P] = covar(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing model')
10 | end
11 |
12 | % Get model type
13 | type = varargin{1}.type;
14 | % Check if there is a TF or SS model
15 | if(strcmp(type, 'SS' ))
16 | % Get sys
17 | sys = varargin{1};
18 | % Get sample time
19 | sampleTime = sys.sampleTime;
20 | % Get matrecies
21 | A = sys.A;
22 | B = sys.B;
23 | C = sys.C;
24 | D = sys.D;
25 |
26 | % Get W matrix
27 | if(length(varargin) >= 2)
28 | W = varargin{2};
29 | else
30 | error('Missing W matrix')
31 | end
32 |
33 | % Check W matrix
34 | if(or(size(B,2) ~= size(W,1), size(W, 1) ~= size(W,2)))
35 | error('W matrix need to be square or B matrix need to have same columns as rows as W matrix')
36 | end
37 |
38 | if(~issymmetric(W))
39 | error('W-matrix need to be symmetric')
40 | end
41 |
42 | % Check if W matrix is semi-definite
43 | EigenValues = eig(W);
44 | for i = 1:length(EigenValues)
45 | if(EigenValues(i) < 0)
46 | error('W matrix need to have non negative eigen values')
47 | end
48 | end
49 |
50 | % Get lyapunov
51 | if(sampleTime > 0)
52 | opt = 'd';
53 | else
54 | opt = 't';
55 | end
56 |
57 | % Get lyapunov solution
58 | X = mc.lyap(A, B*W*B', opt);
59 |
60 | % Get P matrix
61 | P = C*X*C' + D*W*D';
62 |
63 |
64 | elseif(strcmp(type, 'TF' ))
65 | disp('Only state space model are allowed')
66 | else
67 | error('This is not TF or SS');
68 | end
69 |
70 | end
--------------------------------------------------------------------------------
/matave/+mc/ctrb.m:
--------------------------------------------------------------------------------
1 | % Generates the controllability matrix of a state space model
2 | % Input: sys, n(optinal)
3 | % Example 1: [Cs] = mc.ctrb(sys)
4 | % Example 1: [Cs] = mc.ctrb(sys, n)
5 | % Author: Daniel Mårtensson, Oktober 2017
6 |
7 | function [Cs] = ctrb(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % Get SS
18 | sys = varargin{1};
19 |
20 | % Check if we got variable n for minimal realization
21 | if(length(varargin) > 1)
22 | n = varargin{2};
23 | else
24 | n = size(sys.A, 1); % Else, we only check the dimension of A
25 | end
26 |
27 | % Compute the controllability matrix now!
28 | Cs = [];
29 | for i = 0:(n-1)
30 | Cs = [Cs sys.A^i*sys.B];
31 | end
32 |
33 | elseif(strcmp(type, 'TF' ))
34 | % Get TF
35 | disp('Only state space models allowed');
36 | else
37 | error('This is not TF or SS');
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/matave/+mc/d2c.m:
--------------------------------------------------------------------------------
1 | % Transform discrete transfer function or state space model to continuous time
2 | % transfer function or state space model
3 | % Input: Gd, sysd
4 | % Example 1: G = mc.d2c(Gd)
5 | % Example 2: sys = mc.d2c(sysd)
6 | % Author: Daniel Mårtensson, September 2017
7 |
8 | function [model] = d2c(varargin)
9 | if(isempty(varargin{1}))
10 | error ('Missing model')
11 | end
12 |
13 | % State space
14 | if(strcmp(varargin{1}.type, 'SS' ))
15 | % Get info
16 | A = varargin{1}.A;
17 | B = varargin{1}.B;
18 | C = varargin{1}.C;
19 | D = varargin{1}.D;
20 | delay = varargin{1}.delay;
21 | sampleTime = varargin{1}.sampleTime;
22 | % Compute sizes
23 | a1 = size(A,2) + size(B,2) - size(A,1);
24 | b1 = size(A,2);
25 | a2 = size(A,2) + size(B,2) - size(B,1);
26 | b2 = size(B,2);
27 | % Compute square matrix
28 | M = [A B; zeros(a1, b1) eye(a2, b2)];
29 | M = round(logm(M)*1/sampleTime*1/1e-6)*1e-6; % Very important to remove small numbers!!
30 | M(abs(M) < 1e-6) = 0; % Very importat to turn -0 to 0.
31 | A = M(1:size(A,1), 1:size(A,2));
32 | B = M(1:size(B,1), (size(A,2) + 1):(size(A,2) + size(B,2)));
33 | % Return model
34 | model = mc.ss(delay, A, B, C, D);
35 | % Don't forget to add sample time to zero again
36 | model.sampleTime = 0;
37 | elseif(strcmp(varargin{1}.type, 'TF' ))
38 | % Turn TF to SS
39 | sysd = mc.tf2ss(varargin{1}, 'OCF');
40 | % Call d2c2
41 | G = mc.d2c(sysd);
42 | % SS to SS
43 | model = mc.ss2tf(G);
44 | else
45 | error('No state space model or transfer function')
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/matave/+mc/d2d.m:
--------------------------------------------------------------------------------
1 | % Rediscrete transfer function or state space model
2 | % Input: Gd, sysd, sampleTime
3 | % Example 1: G = mc.d2d(Gd, sampleTime)
4 | % Example 2: sys = mc.d2d(sysd, sampleTime)
5 | % Author: Daniel Mårtensson, September 2017
6 |
7 | function [model] = d2d(varargin)
8 | if(isempty(varargin{1}))
9 | error ('Missing model')
10 | end
11 |
12 | if(isempty(varargin{2}))
13 | error ('Missing sampeltime')
14 | end
15 |
16 | % State space
17 | if(strcmp(varargin{1}.type, 'SS' ))
18 | % To continuous from discrete
19 | sys = mc.d2c(varargin{1});
20 | % To discrete from continuous
21 | model = mc.c2d(sys, varargin{2});
22 | elseif(strcmp(varargin{1}.type, 'TF' ))
23 | % To continuous from discrete
24 | G = mc.d2c(varargin{1});
25 | % To discrete from continuous
26 | model = mc.c2d(G, varargin{2});
27 | else
28 | error('No state space model or transfer function')
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/matave/+mc/damp.m:
--------------------------------------------------------------------------------
1 | % Generates zeros from transfer functions or state space models
2 | % Input: G, sys
3 | % Example 1: [Frequency, Damping, Poles, TimeConstant] = mc.damp(G)
4 | % Example 2: [Frequency, Damping, Poles, TimeConstant] = mc.damp(sys)
5 | % Author: Daniel Mårtensson, September 2017
6 |
7 | function [Frequency, Damping, Poles] = damp(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Get sampleTime
16 | sampleTime = varargin{1}.sampleTime;
17 | % Check if there is a TF or SS model
18 | if(strcmp(type, 'SS' ))
19 | % Check if it's discrete
20 | if(sampleTime == 0)
21 | Poles = mc.pole(varargin{1})
22 | Frequency = abs(Poles)
23 | Damping = -cos(angle(Poles))
24 | TimeConstant = (1./(Frequency.*Damping))
25 | else
26 | % Discrete
27 | Poles = mc.pole(varargin{1})
28 | Frequency = abs(log(Poles)/sampleTime)
29 | Damping = -cos(angle(log(Poles)))
30 | TimeConstant = (1./(Frequency.*Damping))
31 | end
32 | elseif(strcmp(type, 'TF' ))
33 | % Check if it's discrete
34 | if(sampleTime == 0)
35 | Poles = mc.pole(varargin{1})
36 | Frequency = abs(Poles)
37 | Damping = -cos(angle(Poles))
38 | TimeConstant = (1./(Frequency.*Damping))
39 | else
40 | % Discrete
41 | Poles = mc.pole(varargin{1})
42 | Frequency = abs(log(Poles)/sampleTime)
43 | Damping = -cos(angle(log(Poles)))
44 | TimeConstant = (1./(Frequency.*Damping))
45 | end
46 | else
47 | error('This is not TF or SS');
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/matave/+mc/db2mag.m:
--------------------------------------------------------------------------------
1 | % Convert decibel to magnitude
2 | % Input dB
3 | % Example 1: [mag] = mc.db2mag(dB)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 | function [mag] = db2mag (dB)
6 | mag = 10.^(dB/20);
7 | end
8 |
--------------------------------------------------------------------------------
/matave/+mc/dbdrop.m:
--------------------------------------------------------------------------------
1 | % Plot the nyquist diagram of a state space model or a transfer function to find the
2 | % 3 dB gain drop between frequencies w1 and w2
3 | % Input: G, sys, w1, w2
4 | % Example 1: [drop] = mc.dbdrop(sys, w1, w2)
5 | % Example 2: [drop] = mc.dbdrop(G, w1, w2)
6 | % Author: Daniel Mårtensson, Oktober 2017
7 |
8 | function [drop] = dbdrop(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | if(w1 == 0)
21 | w1 = 0.001;
22 | end
23 | w2 = varargin{3};
24 | end
25 |
26 |
27 | % Get the type
28 | type = varargin{1}.type;
29 | % Check if there is a TF or SS model
30 | if(strcmp(type, 'SS' ))
31 | % SS to TF
32 | G = mc.ss2tf(varargin{1});
33 | % Call dBdrop
34 | mc.dbdrop(G, w1, w2);
35 | elseif(strcmp(type, 'TF' ))
36 | % If there is a MIMO TF
37 | G = varargin{1};
38 | for i = 1:size(G,1)
39 | for j = 1:size(G,2)
40 | % Get numerator vector and denomerator vector
41 | a = G(i,j).num;
42 | b = G(i,j).den;
43 | % Get delay
44 | delay = G(i,j).delay;
45 | % Get sample time
46 | sampleTime = G(i,j).sampleTime;
47 |
48 | % Numerator and denomerator need to be the same length
49 | if(length(a) > length(b))
50 | b = [zeros(1, size(a,2) - size(b,2)) b];
51 | elseif(length(a) < length(b))
52 | a = [zeros(1, size(b,2) - size(a,2)) a];
53 | end
54 |
55 | L = 1000; % Number of frequency elements
56 | N = length(b); % Number of denomerators
57 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
58 | % Evaluate transfer function
59 | H = zeros(1, L);
60 | h = sampleTime;
61 | if(sampleTime > 0) % Discrete model
62 | for k = 1 : L
63 | H(k) = (a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h));
64 | end
65 | else
66 | for k = 1 : L
67 | H(k) = (a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k));
68 | end
69 | end
70 | % Done!
71 | % Plot bode diagram
72 |
73 |
74 | dBstatic = 20*log10(abs(mc.freqresp(G(i,j), 0))); % The static G(0) dB gain
75 | dBinitial = dBstatic - 3;
76 | dropWc = NaN;
77 | drop = 0;
78 | for k = 1 : L
79 | if(20*log10(abs(H(k))) <= dBinitial)
80 | drop = w(k);
81 | break;
82 | end
83 | end
84 |
85 | % Check if drop has changed
86 | if(drop == 0)
87 | opts = struct('WindowStyle','modal', 'Interpreter','tex');
88 | warndlg('\color{blue} No dB drop of 3 dB was found. Try to increase the frequency range.', 'No dB', opts);
89 | return;
90 | end
91 |
92 | figure('Name', sprintf(strcat('Transfer function: ', num2str(i), 'x', num2str(j))))
93 | semilogx(w, 20*log10(abs(H)), 'b');
94 | hold on
95 | h = semilogx([drop drop], [dBinitial (dBinitial + 3)], 'r');
96 | ylabel('Magnitude [dB]');
97 | grid on
98 | legend(h,strcat('3 dB drop at: ', num2str(drop), ' rad/s'))
99 |
100 |
101 | end
102 | end
103 | else
104 | error('Only transfer functions and state space models allowed')
105 | end
106 | end
107 |
--------------------------------------------------------------------------------
/matave/+mc/dcgain.m:
--------------------------------------------------------------------------------
1 | % Generates the low frequency gain of a state space model or a transfer function
2 | % Input: sys, G
3 | % Example 1: dc = mc.dcgain(sys)
4 | % Example 2: dc = mc.dcgain(G)
5 | % Author: Daniel Mårtensson 2017 September
6 |
7 | function [dc] = dcgain(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get the type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % Get necessary info
18 | A = varargin{1}.A;
19 | B = varargin{1}.B;
20 | C = varargin{1}.C;
21 | D = varargin{1}.D;
22 | dc = C*inv(-A)*B + D;
23 | elseif(strcmp(type, 'TF' ))
24 | % Get necessary info
25 | for i = 1:size(varargin{1},1)
26 | for j = 1:size(varargin{1},2)
27 | % Get necessary info
28 | G = varargin{1}(i, j);
29 | % Get the static gain
30 | dc(i, j) = G.num(length(G.num))/G.den(length(G.den));
31 |
32 | % If divided by zero - Is not a number
33 | if isnan(dc(i, j))
34 | disp(sprintf('Divided my zero - mc.dcgain(%i, %i) set to 0', i, j))
35 | dc(i, j) = 0;
36 | end
37 | end
38 | end
39 | else
40 | error('This is not TF or SS');
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/matave/+mc/evalfr.m:
--------------------------------------------------------------------------------
1 | % Computes the frequency response from a transfer function or state space model at single frequency w
2 | % Input: G, sys, w
3 | % Example 1: frsp = mc.evalfr(sys, w)
4 | % Example 2: frsp = mc.evalfr(G, w)
5 | % Author: Daniel Mårtensson, Oktober 2017
6 |
7 | function [frsp] = evalfr(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error('Missing model')
11 | end
12 |
13 | % Check if there is any input
14 | if(length(varargin) < 2)
15 | error('Missing frequencies')
16 | end
17 |
18 | w = varargin{2};
19 |
20 | % Get the type
21 | type = varargin{1}.type;
22 | % Check if there is a TF or SS model
23 | if(strcmp(type, 'SS' ))
24 | % SS to TF
25 | G = mc.ss2tf(varargin{1});
26 | % Call evalfr
27 | [frsp] = mc.evalfr(G, w);
28 | elseif(strcmp(type, 'TF' ))
29 | % If there is a MIMO TF
30 | G = varargin{1};
31 | % Create H
32 | %L = 1000; % Number of frequency elements
33 | H = zeros(size(G,1),size(G,2), 1);
34 | for i = 1:size(G,1)
35 | for j = 1:size(G,2)
36 | % Get numerator vector and denomerator vector
37 | a = G(i,j).num;
38 | b = G(i,j).den;
39 | % Get delay
40 | delay = G(i,j).delay;
41 |
42 | % Numerator and denomerator need to be the same length
43 | if(length(a) > length(b))
44 | b = [zeros(1, size(a,2) - size(b,2)) b];
45 | elseif(length(a) < length(b))
46 | a = [zeros(1, size(b,2) - size(a,2)) a];
47 | end
48 |
49 | N = length(b); % Number of denomerators
50 | % Evaluate transfer function
51 | for k = 1 : 1
52 | H(i,j,k) = (a*fliplr((w(k)).^(0 : N-1)).')/(b*fliplr((w(k)).^(0 : N-1)).')*exp(-delay*w(k));
53 | end
54 |
55 |
56 | % Done!
57 | end
58 | end
59 | frsp = H;
60 | else
61 | error('Only transfer functions and state space models allowed')
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/matave/+mc/feedback.m:
--------------------------------------------------------------------------------
1 | % Computes the new transfer function or state space model of serial connection
2 | % Input: G, sys, sign(optinal)
3 | % Example 1: G = mc.feedback(G1, G2) % Negative feedback is used as default
4 | % Example 2: sys = mc.feedback(sys1, sys2) % Negative feedback is used as default
5 | % Example 3: sys = mc.feedback(sys1, sys2, sign) % sign = '+' Positive feedback
6 | % Author: Daniel Mårtensson, Oktober 2017
7 |
8 | function [model] = feedback(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error ('Missing input')
12 | end
13 |
14 | % Check if there is a second input
15 | if(isempty(varargin{2}))
16 | error ('Missing second model')
17 | end
18 |
19 | % Check feedback sign
20 | if(length(varargin) >= 3)
21 | f = varargin{3};
22 | if(or(strcmp(f,'+'),strcmp(f,'-')))
23 | f = varargin{3};
24 | else
25 | error('Unknow feedback sign');
26 | end
27 | else
28 | f = '-';
29 | end
30 |
31 | % Get model type
32 | type = varargin{1}.type;
33 | % Check if there is a TF or SS model
34 | if(strcmp(type, 'SS' ))
35 | % Get info
36 | sys1 = varargin{1};
37 | sys2 = varargin{2};
38 | if(sys1.sampleTime == sys2.sampleTime)
39 | % Get matrecies
40 | A1 = sys1.A;
41 | A2 = sys2.A;
42 | B1 = sys1.B;
43 | B2 = sys2.B;
44 | C1 = sys1.C;
45 | C2 = sys2.C;
46 | D1 = sys1.D;
47 | D2 = sys2.D;
48 |
49 | % Get feedback state space
50 | if(strcmp(f, '-'))
51 | A = [(A1 - B1*D2*C1) -B1*C2 ; B2*C1 (A2 - B2*D1*C2)];
52 | B = [B1; B2*D1];
53 | C = [C1 -D1*C2];
54 | D = D1;
55 | else % f = '+'
56 | A = [(A1 + B1*D2*C1) B1*C2 ; B2*C1 (A2 + B2*D1*C2)];
57 | B = [B1; B2*D1];
58 | C = [C1 D1*C2];
59 | D = D1;
60 | end
61 | if(sys1.delay ~= sys2.delay)
62 | error('It need to be the same delay for both of the systems')
63 | end
64 | delay = sys1.delay;
65 | model = mc.ss(delay, A, B, C, D);
66 | model.sampleTime = sys1.sampleTime;
67 | else
68 | error('Need to have the same sampling time')
69 | end
70 | elseif(strcmp(type, 'TF' ))
71 | % Get info
72 | G1 = varargin{1};
73 | G2 = varargin{2};
74 | if(G1.sampleTime == G2.sampleTime)
75 | % Get num and den for the model down
76 | G_down = mc.series(G1, G2);
77 | num_down = G_down.num;
78 | den_down = G_down.den;
79 | % Get num and den for model above
80 | G_up = G1;
81 | num_up = G_up.num;
82 | den_up = G_up.den;
83 | % Get delay
84 | delay = G1.delay;
85 |
86 | % Need to have same length for the down model
87 | num_down = [zeros(1, length(den_down) - length(num_down)) num_down];
88 | den_down = [zeros(1, length(num_down) - length(den_down)) den_down];
89 |
90 | % -1 feedback or +1 feedback
91 | % 1 - a/b = (b-a)/b
92 | % 1 + a/b = (b+a)/b
93 | if(strcmp(f, '-'))
94 | num_down = den_down + num_down;
95 | else % f = '+'
96 | num_down = den_down - num_down;
97 | end
98 |
99 | % (a/b)/(c/d) = a*d/(b*c)
100 | num = conv(num_up, den_down);
101 | den = conv(den_up, num_down);
102 |
103 | if(delay > 0)
104 | model = mc.tf(num, den, delay);
105 | else
106 | model = mc.tf(num, den);
107 | end
108 | model.sampleTime = G1.sampleTime;
109 |
110 | % Discrete or not?
111 | if (model.sampleTime > 0)
112 | % Replace the delaytime to discrete delay time
113 | model.tfdash = strrep(model.tfdash, 'e', 'z');
114 | model.tfdash = strrep(model.tfdash, 's', '');
115 | % Remove all s -> s
116 | model.tfnum = strrep(model.tfnum, 's', 'z');
117 | model.tfden = strrep(model.tfden, 's', 'z');
118 | end
119 | else
120 | error('Need to have the same sampling time')
121 | end
122 | else
123 | error('This is not TF or SS');
124 | end
125 | end
126 |
--------------------------------------------------------------------------------
/matave/+mc/findmaxgain.m:
--------------------------------------------------------------------------------
1 | % Find the maximum gain limit when the process becomes unstable.
2 | % Input: sys, G, maxgain
3 | % Example 1: [K] = mc.findmaxgain(sys, maxgain)
4 | % Example 2: [K] = mc.findmaxgain(G, maxgain)
5 | % Example 3: [K] = mc.findmaxgain(G)
6 | % Example 4: [K] = mc.findmaxgain(sys)
7 | % Author: Daniel Mårtensson, 2018 Februari
8 |
9 | function [K] = findmaxgain(varargin)
10 | % Check if there is any input
11 | if(isempty(varargin))
12 | error('Missing model')
13 | end
14 |
15 | % Get the type
16 | type = varargin{1}.type;
17 | % Check if there is a TF or SS model
18 | if(strcmp(type, 'SS' ))
19 | % SS to TF
20 | G = mc.ss2tf(varargin{1});
21 | if(length(varargin) >= 2)
22 | maxgain = varargin{2};
23 | else
24 | %disp('Default gain is 1000');
25 | maxgain = 1000;
26 | end
27 | % Call findmaxgain
28 | mc.findmaxgain(G, maxgain);
29 | elseif(strcmp(type, 'TF' ))
30 | % If there is a MIMO TF
31 | G = varargin{1};
32 | for i = 1:size(G,1)
33 | for j = 1:size(G,2)
34 | % Get sample time
35 | sampleTime = G(i,j).sampleTime;
36 | % Get num
37 | num = G(i,j).num;
38 | % Get den
39 | den = G(i, j).den;
40 | % Maximum Gain K
41 | if(length(varargin) >= 2)
42 | maxgain = varargin{2};
43 | else
44 | %disp('Default gain is 1000');
45 | maxgain = 1000;
46 | end
47 |
48 | % P-controller vector
49 | P = linspace(0, maxgain, 10000);
50 |
51 | % Turn them into equal length
52 | if length(den) < length(num)
53 | den = [zeros(1, length(num) - length(den)) den];
54 | elseif length(den) > length(num)
55 | num = [zeros(1, length(den) - length(num)) num];
56 | end
57 |
58 | % Do numerical calculation
59 | for k = 1:length(P)
60 | % Multiply P with num and add with den
61 | polynomal = P(k)*num + den; % Always begin with P(k) = 0. G(s) = K*num + den is the feedback G(s) = K*G/(1 + K*G)
62 | % Find the roots
63 | PolyRoots = roots(polynomal);
64 | % Check if the system is discrete or not
65 | if sampleTime > 0
66 | % Check if PolyRoots are stable - Discrete way
67 | Temp = and(abs(PolyRoots) <= 1, abs(PolyRoots) >= -1);
68 | Stable = prod(Temp); % If someone is 0, then Stable will be 0
69 | else
70 | % Check if PolyRoots are stable - Discrete way
71 | Temp = real(PolyRoots) <= 0;
72 | Stable = prod(Temp); % If someone is 0, then Stable will be 0
73 | end
74 |
75 |
76 | % Check if Stable is 1 or 0
77 | if Stable == 0
78 | K(i, j) = P(k); % Save this K because this is the limit
79 | break; % Break the for-loop for the numerical calculation
80 | end
81 |
82 | end
83 |
84 | end
85 | end
86 | else
87 | error('Only transfer functions and state space models allowed')
88 | end
89 | end
90 |
--------------------------------------------------------------------------------
/matave/+mc/freqresp.m:
--------------------------------------------------------------------------------
1 | % Computes the frequency response from a transfer function or state space model with the frequency vector w
2 | % Input: sys, G, w
3 | % Example 1: [H, wout] = mc.freqresp(sys, w)
4 | % Example 2: [H, wout] = mc.freqresp(G, w)
5 | % Author: Daniel Mårtensson, Oktober 2017
6 |
7 | function [H, wout] = freqresp(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error('Missing model')
11 | end
12 |
13 | % Check if there is any input
14 | if(length(varargin) < 2)
15 | error('Missing frequencies')
16 | end
17 |
18 | w = varargin{2};
19 |
20 | % Get the type
21 | type = varargin{1}.type;
22 | % Check if there is a TF or SS model
23 | if(strcmp(type, 'SS' ))
24 | % SS to TF
25 | G = mc.ss2tf(varargin{1});
26 | % Call freqresp
27 | [H, wout] = mc.freqresp(G, w);
28 | elseif(strcmp(type, 'TF' ))
29 | % If there is a MIMO TF
30 | G = varargin{1};
31 | % Create H
32 | L = length(w); % Number of frequency elements
33 | H = zeros(size(G,1),size(G,2), L);
34 | for i = 1:size(G,1)
35 | for j = 1:size(G,2)
36 | % Get numerator vector and denomerator vector
37 | a = G(i,j).num;
38 | b = G(i,j).den;
39 | % Get delay
40 | delay = G(i,j).delay;
41 | % Get sample time
42 | sampleTime = G(i,j).sampleTime;
43 |
44 | % Numerator and denomerator need to be the same length
45 | if(length(a) > length(b))
46 | b = [zeros(1, size(a,2) - size(b,2)) b];
47 | elseif(length(a) < length(b))
48 | a = [zeros(1, size(b,2) - size(a,2)) a];
49 | end
50 |
51 | N = length(b); % Number of denomerators
52 | wout = w;
53 | % Evaluate transfer function
54 | h = sampleTime;
55 | if(sampleTime > 0) % Discrete model
56 | for k = 1 : L
57 | H(i,j,k) = (a*fliplr((exp(1i*wout(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*wout(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*wout(k)*h));
58 | end
59 | else % Continous
60 | for k = 1 : L
61 | H(i,j,k) = (a*fliplr((1i*wout(k)).^(0 : N-1)).')/(b*fliplr((1i*wout(k)).^(0 : N-1)).')*exp(-delay*1i*wout(k));
62 | end
63 | end
64 |
65 | % Done!
66 | end
67 | end
68 | else
69 | error('Only transfer functions and state space models allowed')
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/matave/+mc/gensig.m:
--------------------------------------------------------------------------------
1 | % Generates a signal of sin, square or pulse
2 | % Input: type, amp, Tf, Ts
3 | % Example 1: [u, t] = mc.gensig(type, amp, Tf, Ts)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 |
6 | function [u, t] = gensig(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error('Missing input')
10 | end
11 | % Get type
12 | if(length(varargin) > 0)
13 | type = varargin{1};
14 | else
15 | error('Missing type')
16 | end
17 | % Get the amplitude
18 | if(length(varargin) > 1)
19 | amp = varargin{2};
20 | else
21 | amp = 1;
22 | end
23 | % Get the Tf
24 | if(length(varargin) > 2)
25 | Tf = varargin{3};
26 | else
27 | Tf = 1;
28 | end
29 | % Get time
30 | if(length(varargin) > 3)
31 | Ts = varargin{4};
32 | else
33 | Ts = 10;
34 | end
35 |
36 |
37 | switch type
38 | case 'sin'
39 | t = linspace(0,Ts, 1000);
40 | u = amp*sin(Tf*t + Ts);
41 | case 'square'
42 | t = linspace(0,Ts, 1000);
43 | u = [];
44 | n = 1;
45 | if(Tf == 1)
46 | Tf = 2;
47 | end
48 | for i = 1:length(t)
49 | if(i >= length(t)/(Tf)*n)
50 | u(i) = amp;
51 | if(i >= length(t)/(Tf)*(n + 1))
52 | n = n + 2;
53 | end
54 | else
55 | u(i) = 0;
56 | end
57 | end
58 | case 'pulse'
59 | t = linspace(0,Ts, 1000);
60 | u = [];
61 | n = 1;
62 | if(Tf == 1)
63 | Tf = 2;
64 | end
65 | for i = 1:length(t)
66 | if(i >= length(t)/(Tf)*n)
67 | u(i) = amp;
68 | n = n + 1;
69 | else
70 | u(i) = 0;
71 | end
72 | end
73 | u(end) = 0; % Remove the last peak
74 | end
75 | end
76 |
--------------------------------------------------------------------------------
/matave/+mc/gram.m:
--------------------------------------------------------------------------------
1 | % Generates the gramian a state space model, where opt = 'c' or opt = 'o'
2 | % Input: sys, opt
3 | % Example 1: X = mc.gram(sys, opt)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 |
6 | function [X] = gram(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing model')
10 | end
11 |
12 | if(length(varargin) >= 2)
13 | opt = varargin{2};
14 | else
15 | error('Missing option: ´c´ or ´o´');
16 | end
17 |
18 | % Get model type
19 | type = varargin{1}.type;
20 | % Check if there is a TF or SS model
21 | if(strcmp(type, 'SS' ))
22 | % Get sys
23 | sys = varargin{1};
24 | % Get sample time
25 | sampleTime = varargin{1}.sampleTime;
26 |
27 | if(sampleTime > 0)
28 | % Discrete way
29 | A = sys.A;
30 | B = sys.B;
31 | C = sys.C;
32 |
33 | if(strcmp(opt, 'c'))
34 | X = mc.lyap(A, B*B', 'd');
35 | elseif(strcmp(opt, 'o'))
36 | X = mc.lyap(A', C'*C, 'd');
37 | else
38 | disp(sprintf('Unknown option: %s', opt));
39 | end
40 |
41 | else
42 | % Continous way
43 | A = sys.A;
44 | B = sys.B;
45 | C = sys.C;
46 |
47 | if(strcmp(opt, 'c'))
48 | X = mc.lyap(A, B*B');
49 | elseif(strcmp(opt, 'o'))
50 | X = mc.lyap(A', C'*C);
51 | else
52 | disp(sprintf('Unknown option: %s', opt));
53 | end
54 |
55 | end
56 | elseif(strcmp(type, 'TF' ))
57 | disp('Only state space model are allowed')
58 | else
59 | error('This is not TF or SS');
60 | end
61 |
62 | end
--------------------------------------------------------------------------------
/matave/+mc/hsvd.m:
--------------------------------------------------------------------------------
1 | % Get the hankel singular values of a state space model
2 | % Input: SS, p(optional)
3 | % Example 1: hsv = mc.hsvd(sys)
4 | % Example 1: hsv = mc.hsvd(sys, p) % p = 'plot'
5 | % Author: Daniel Mårtensson, Oktober 2017
6 |
7 | function [hsv] = hsvd(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing model')
11 | end
12 |
13 | if(length(varargin) >= 2)
14 | p = varargin{2};
15 | else
16 | p = 'n';
17 | end
18 |
19 | % Get model type
20 | type = varargin{1}.type;
21 | % Check if there is a TF or SS model
22 | if(strcmp(type, 'SS' ))
23 | % Get sys
24 | sys = varargin{1};
25 | % Get gramians
26 | P = mc.gram(sys, 'c');
27 | Q = mc.gram(sys, 'o');
28 | % Get hankel singular values
29 | hsv = sqrt(eig(P*Q));
30 | % Plot them too!
31 | if(strcmp(p,'plot'))
32 | bar(hsv)
33 | title('Hankel Singular Values (State Contributions)')
34 | xlabel('State')
35 | ylabel('State Energy')
36 | legend('Stable modes')
37 | end
38 | elseif(strcmp(type, 'TF' ))
39 | disp('Only state space model are allowed')
40 | else
41 | error('This is not TF or SS');
42 | end
43 | end
--------------------------------------------------------------------------------
/matave/+mc/imc.m:
--------------------------------------------------------------------------------
1 | % An IMC controller
2 | % Input: G(System), K(Controller), Go(Forward Model)
3 | % Example 1: [G] = mc.imc(G, K, Go)
4 | % Author: Daniel Mårtensson, Februari 2018
5 |
6 |
7 | function [model] = imc(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Check if there is a second input
14 | if(isempty(varargin{2}))
15 | error ('Missing controller transfer function')
16 | end
17 |
18 | % Check if there is a third input
19 | if(isempty(varargin{3}))
20 | error ('Missing forward Modelr')
21 | end
22 |
23 | % Get model type
24 | type = varargin{1}.type;
25 | % Check if there is a TF or SS model
26 | if(strcmp(type, 'TF' ))
27 | % Get system G
28 | G = varargin{1};
29 | % Get controller K
30 | K = varargin{2};
31 | % Get system Go
32 | Go = varargin{3};
33 |
34 | % They must have the same sample time
35 | if(and(G.sampleTime == K.sampleTime, G.sampleTime == Go.sampleTime))
36 | % Get num and den
37 | num1 = G.num;
38 | den1 = G.den;
39 | num2 = Go.num;
40 | den2 = Go.den;
41 |
42 | % Extend - pad - Equal length
43 | num1 = [zeros(1, length(num2) - length(num1)) num1];
44 | den1 = [zeros(1, length(den2) - length(den1)) den1];
45 | num2 = [zeros(1, length(num1) - length(num2)) num2];
46 | den2 = [zeros(1, length(den1) - length(den2)) den2];
47 |
48 | % Substract - Importat to have -conv(num1, den2) + conv(num2, den1)
49 | % because we are doing negative feedback - This is parallel method of two TF's
50 | num = conv(num1, den2) - conv(num2, den1);
51 | den = conv(den1, den2);
52 |
53 | % Create a transfer function of num and den
54 | GGo = mc.tf(num, den);
55 | % Need to have the same sample time as G!
56 | GGo.sampleTime = G.sampleTime;
57 | % Do feedback witg GGo and K.
58 | F = mc.feedback(K, GGo);
59 | % Do serial connection with F and G.
60 | model = mc.series(F, G);
61 |
62 |
63 | else
64 | error('Not the same sample time')
65 | end
66 | else
67 | error('Only transfer functions');
68 | end
69 |
70 | end
71 |
--------------------------------------------------------------------------------
/matave/+mc/impulse.m:
--------------------------------------------------------------------------------
1 | % Do a impulse response of a transfer function or a state space model
2 | % Input: G, sys, t(optional)
3 | % Example 1: [y,t,x] = mc.impulse(G, t)
4 | % Example 2: [y,t,x] = mc.impulse(G)
5 | % Example 3: [y,t,x] = mc.impulse(sys, t)
6 | % Author: Daniel Mårtensson, September 2017
7 | % Update 2022-10-08: Simulate ARMA model
8 |
9 | function [y,t,X] = impulse(varargin)
10 | % Check if there is some input arguments or it's not a model
11 | if(isempty(varargin{1}))
12 | error ('Missing input')
13 | end
14 |
15 | % Check if there is a model
16 | if(strcmp(varargin{1}.type,'SS'))
17 |
18 | % Get time
19 | if(length(varargin) >= 2)
20 | t = varargin{2};
21 | else
22 | disp('Time assumed to be 10 seconds');
23 | t = 10;
24 | end
25 |
26 | % Get sample time to compute the new time vector
27 | sampleTime = varargin{1}.sampleTime;
28 | if(sampleTime > 0)
29 | t = 0:sampleTime:t;
30 | else
31 | t = 0:0.01:t; % Sample time assumed to be 0.01
32 | end
33 |
34 | % Multiple signals...or not!
35 | u = zeros(size(varargin{1}.B, 2), length(t)); % Creates 1 1 1 1 1 1 1
36 | u(:,1) = ones(size(u,1), 1);
37 | x0 = zeros(size(varargin{1}.A, 1), 1); % Assume x0 = [0; 0; 0; ..... ; 0]
38 |
39 | % Call lsim!
40 | [y,t,X] = mc.lsim(varargin{1}, u, t, x0);
41 | elseif(strcmp(varargin{1}.type,'TF'))
42 | % TF to SS
43 | sys = mc.tf2ss(varargin{1}, 'OCF');
44 |
45 | % Get time
46 | if(length(varargin) >= 2)
47 | t = varargin{2};
48 | else
49 | disp('Time assumed to be 10 seconds');
50 | t = 10;
51 | end
52 |
53 | % Call impulse
54 | [y,t,X] = mc.impulse(sys,t);
55 | elseif(strcmp(varargin{1}.type,'ARMA'))
56 |
57 | % Get end time
58 | if(length(varargin) >= 2)
59 | t = varargin{2};
60 | else
61 | disp('Time assumed to be 10 seconds');
62 | t = 10;
63 | end
64 |
65 | % Create time vector
66 | sampleTime = varargin{1}.sampleTime;
67 | if(sampleTime > 0)
68 | t = 0:sampleTime:t;
69 | else
70 | t = 0:0.01:t; % Sample time assumed to be 0.01
71 | end
72 |
73 | % Create input u
74 | u = linspace(0, 0, length(t));
75 | u(1) = 1;
76 |
77 | % Call lsim!
78 | [y,t,X] = mc.lsim(varargin{1}, u, t);
79 | else
80 | error('Not a state space model or a transfer function')
81 | end
82 | end
83 |
--------------------------------------------------------------------------------
/matave/+mc/initial.m:
--------------------------------------------------------------------------------
1 | % Simulate a transfer function or state space model with initial state vector x0
2 | % and time constant t, not time vector
3 | % Input: sys, t, x0
4 | % Example 1: [y,t,x] = mc.initial(sys, t, x0)
5 | % Author: Daniel Mårtensson, September 2017
6 |
7 | function [y,t,X] = initial(varargin)
8 | % Check if there is some input arguments or it's not a model
9 | if(isempty(varargin{1}))
10 | error ('Missing input')
11 | end
12 |
13 | % Check if there is a model
14 | if(strcmp(varargin{1}.type,'SS'))
15 |
16 | % Get time
17 | if(length(varargin) >= 2)
18 | t = varargin{2};
19 | else
20 | disp('Time assumed to be 10 seconds');
21 | t = 10;
22 | end
23 |
24 | % Get sample time to compute the new time vector
25 | sampleTime = varargin{1}.sampleTime;
26 | if(sampleTime > 0)
27 | t = 0:sampleTime:t;
28 | else
29 | t = 0:0.01:t; % Sample time assumed to be 0.01
30 | end
31 |
32 | % Multiple signals...or not!
33 | u = zeros(size(varargin{1}.B, 2), length(t)); % Creates 0 0 0 0 0 0 0
34 |
35 | % Get initial conditions
36 | if(length(varargin) >= 3)
37 | x0 = varargin{3};
38 | x0 = x0(:); % Turn them into a vector
39 | if(size(varargin{1}.A, 1) ~= size(x0, 1))
40 | error('The initial conditions vector has not the same row length as matrix A')
41 | end
42 | else
43 | error('Missing initial conditions');
44 | end
45 |
46 | % Call lsim!
47 | [y,t,X] = mc.lsim(varargin{1}, u, t, x0);
48 | elseif(strcmp(varargin{1}.type,'TF'))
49 | error('Only for state space models')
50 | else
51 | error('Not a state space model or a transfer function')
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/matave/+mc/listOfFunctions:
--------------------------------------------------------------------------------
1 | acker.m
2 | allmargin.m
3 | append.m
4 | are.m
5 | balreal.m
6 | bode.m
7 | bodemag.m
8 | c2d.m
9 | c2dt.m
10 | covar.m
11 | ctrb.m
12 | d2c.m
13 | d2d.m
14 | damp.m
15 | db2mag.m
16 | dbdrop.m
17 | dcgain.m
18 | evalfr.m
19 | feedback.m
20 | findmaxgain.m
21 | freqresp.m
22 | gensig.m
23 | gram.m
24 | hsvd.m
25 | imc.m
26 | impulse.m
27 | initial.m
28 | loop.m
29 | lmpc.m
30 | lqe.m
31 | lqgreg.m
32 | lqi.m
33 | lqr.m
34 | lsim.m
35 | lyap.m
36 | mag2db.m
37 | margin.m
38 | intss.m
39 | minreal.m
40 | modred.m
41 | satlsim.m
42 | nyquist.m
43 | obsv.m
44 | pade.m
45 | parallel.m
46 | pid.m
47 | pipd.m
48 | pole.m
49 | pzmap.m
50 | ramp.m
51 | reg.m
52 | rlocus.m
53 | sensitivity.m
54 | series.m
55 | sigma.m
56 | smithpredict.m
57 | ss.m
58 | ss2tf.m
59 | step.m
60 | tf.m
61 | tf2ss.m
62 | tzero.m
63 | updatematavecontrol.m
64 | zero.m
65 | zpk.m
66 |
--------------------------------------------------------------------------------
/matave/+mc/loop.m:
--------------------------------------------------------------------------------
1 | % Create the Complementary sensitivity, sensitivity of an open loop transfer function L
2 | % Input: L
3 | % Example 1: [S, T] = mc.loop(L)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 | function [S, T] = loop(varargin)
6 | % Check if there is any input
7 | if(isempty(varargin))
8 | error ('Missing transfer function')
9 | end
10 |
11 | % Get model type
12 | type = varargin{1}.type;
13 | % Check if there is a TF or SS model
14 | if(strcmp(type, 'SS' ))
15 | error('Only loop transfer functions');
16 | elseif(strcmp(type, 'TF' ))
17 | % Get open loop transfer function
18 | L = varargin{1};
19 | % Create S
20 | N = mc.tf(1,1); % Create a constant only for sensitivity function
21 | S = mc.feedback(L, N);
22 | % Create T
23 | T = mc.feedback(L, L);
24 | else
25 | error('This is not TF or SS');
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/matave/+mc/lqe.m:
--------------------------------------------------------------------------------
1 | % Compute the LQE kalman gain matrix with the weighing matricies Q and R and state space model
2 | % Input: SS, Q, R
3 | % Example 1: [K] = mc.lqe(sys, Q, R)
4 | % Author: Daniel Mårtensson, October 2017
5 |
6 | function [K] = lqe(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing model')
10 | end
11 |
12 | % Get Q R
13 | if(length(varargin) >= 2)
14 | Q = varargin{2};
15 | R = varargin{3};
16 | else
17 | error('Missing Q or R');
18 | end
19 |
20 | % Get model type
21 | type = varargin{1}.type;
22 | % Check if there is a TF or SS model
23 | if(strcmp(type, 'SS' ))
24 | % Get model
25 | sys = varargin{1};
26 | % Change matrecies due to the Kalman Duality!
27 | sys.A = sys.A'; % Transpose
28 | sys.B = sys.C'; % Transpose
29 | K = (mc.lqr(sys, Q, R))';
30 | elseif(strcmp(type, 'TF' ))
31 | disp('Only state space models only')
32 | else
33 | error('This is not TF or SS');
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/matave/+mc/lqi.m:
--------------------------------------------------------------------------------
1 | % Compute the LQI integral gain matrix control law L with the weighing matricies Q and R and state space model
2 | % Input: SS, Q, R
3 | % Example 1: [L, Li] = mc.lqi(sys, Q, R)
4 | % Example 2: [L, Li, sysi] = mc.lqi(sys, Q, R)
5 | % Author: Daniel Mårtensson, October 2017
6 | % Update 2019-06-07: Returning the model wth integral action
7 |
8 | function [L, Li, sys] = lqi(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error ('Missing model')
12 | end
13 |
14 | % Get Q R
15 | if(length(varargin) >= 2)
16 | Q = varargin{2};
17 | R = varargin{3};
18 | else
19 | error('Missing Q or R');
20 | end
21 |
22 | % Get model type
23 | type = varargin{1}.type;
24 | % Check if there is a TF or SS model
25 | if(strcmp(type, 'SS' ))
26 | % Get model
27 | sys = varargin{1};
28 | A = sys.A;
29 | B = sys.B;
30 | C = sys.C;
31 | D = sys.D;
32 |
33 | % Get info
34 | ny = size(C, 1); % Number outputs
35 | nu = size(B, 2); % Number inputs
36 | nx = size(A, 1); % Number states
37 |
38 | % Create the augmented state space model
39 | if(sys.sampleTime > 0)
40 | sys.A = [A zeros(nx, ny); -C ones(ny, ny)];
41 | sys.B = [B; -D];
42 | sys.C = [C zeros(ny, ny)];
43 | sys.D = D;
44 | else
45 | sys.A = [A zeros(nx, ny); -C zeros(ny, ny)];
46 | sys.B = [B; -D];
47 | sys.C = [C zeros(ny, ny)];
48 | sys.D = D;
49 | end
50 |
51 |
52 | % Get the LQR + LQI control law
53 | ControlLaw = mc.lqr(sys, Q, R);
54 | % Important to have a negative sign!
55 | Li = -ControlLaw(:, (1 + size(C, 2)):end); % We add +1 beacuse we want -Li from [L -Li].
56 | L = ControlLaw(:, 1:size(C, 2));
57 |
58 | elseif(strcmp(type, 'TF' ))
59 | disp('Only state space models only')
60 | else
61 | error('This is not TF or SS');
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/matave/+mc/lqr.m:
--------------------------------------------------------------------------------
1 | % Compute the LQR gain matrix control law L with the weighing matricies Q and R and state space model
2 | % Input: sys, Q, R
3 | % Example 1: [L] = mc.lqr(sys, Q, R)
4 | % Author: Daniel Mårtensson, October 2017
5 |
6 | function [L] = lqr(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing model')
10 | end
11 |
12 | % Get Q R
13 | if(length(varargin) >= 2)
14 | Q = varargin{2};
15 | R = varargin{3};
16 | else
17 | error('Missing Q or R');
18 | end
19 |
20 | % Get model type
21 | type = varargin{1}.type;
22 | % Check if there is a TF or SS model
23 | if(strcmp(type, 'SS' ))
24 | % Get model
25 | sys = varargin{1};
26 | % Solve the Algebraic Riccati Equation
27 | X = mc.are(sys, Q, R);
28 | % Return the control law L
29 | if(sys.sampleTime > 0)
30 | L = inv(sys.B'*X*sys.B + R)*(sys.B'*X*sys.A);
31 | else
32 | L = inv(R)*sys.B'*X;
33 | end
34 | elseif(strcmp(type, 'TF' ))
35 | disp('Only state space models only')
36 | else
37 | error('This is not TF or SS');
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/matave/+mc/lyap.m:
--------------------------------------------------------------------------------
1 | % Compute solution X of the Lyapunov equation
2 | % Input: A, Q, opt(optinal)
3 | % Example 1: [X] = mc.lyap(A, B*B'); % t = time contious as default
4 | % Example 2: [X] = mc.lyap(A, B*B', 'd'); % d = discrete
5 | % Author: Daniel Mårtensson, Oktober 2017
6 |
7 | function [X] = lyap(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing A, Q')
11 | end
12 |
13 | A = varargin{1};
14 | Q = varargin{2};
15 |
16 | if(length(varargin) <= 2)
17 | opt = 't';
18 | else
19 | opt = varargin{3};
20 | end
21 |
22 | if(strcmp(opt, 'd'))
23 | p = kron(conj(A), A);
24 | K = eye(size(p)) - p;
25 | X = K\Q(:);
26 | X = reshape(X, size(A));
27 | elseif(strcmp(opt, 't'))
28 | K = kron(eye(size(A)), A) + kron(conj(A), eye(size(A)));
29 | X = K\-Q(:);
30 | X = reshape(X, size(A));
31 | else
32 | disp(sprintf('Unknown option: %s', opt))
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/matave/+mc/mag2db.m:
--------------------------------------------------------------------------------
1 | % Convert magnitude to decibel
2 | % Input mag
3 | % Example 1: [dB] = mc.mag2db(mag)
4 | % Author: Daniel Mårtensson 2017, Oktober
5 | function [dB] = mag2db(mag)
6 | mag(mag < 0) = NaN;
7 | dB = 20*log10(mag);
8 | end
9 |
--------------------------------------------------------------------------------
/matave/+mc/margin.m:
--------------------------------------------------------------------------------
1 | % Plot the nyquist diagram of a state space model with margins or a transfer function with margins
2 | % between frequencies w1 and w2
3 | % Input: sys, G, w1, w2
4 | % Example 1: [Am, phim, wpi, wc] = mc.margin(sys, w1, w2)
5 | % Example 2: [Am, phim, wpi, wc] = mc.margin(G, w1, w2)
6 | % Author: Daniel Mårtensson 2017, Oktober
7 |
8 | function [Am, phim, wpi, wc] = margin(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | w2 = varargin{3};
21 | end
22 |
23 |
24 | % Get the type
25 | type = varargin{1}.type;
26 | % Check if there is a TF or SS model
27 | if(strcmp(type, 'SS' ))
28 | % SS to TF
29 | G = mc.ss2tf(varargin{1});
30 | % Call marin
31 | mc.margin(G, w1, w2);
32 | elseif(strcmp(type, 'TF' ))
33 | % If there is a MIMO TF
34 | G = varargin{1};
35 | for i = 1:size(G,1)
36 | for j = 1:size(G,2)
37 | % Get numerator vector and denomerator vector
38 | a = G(i,j).num;
39 | b = G(i,j).den;
40 | % Get delay
41 | delay = G(i,j).delay;
42 | % Get sample time
43 | sampleTime = G(i,j).sampleTime;
44 |
45 | % Numerator and denomerator need to be the same length
46 | if(length(a) > length(b))
47 | b = [zeros(1, size(a,2) - size(b,2)) b];
48 | elseif(length(a) < length(b))
49 | a = [zeros(1, size(b,2) - size(a,2)) a];
50 | end
51 |
52 | L = 10000; % Number of frequency elements
53 | N = length(b); % Number of denomerators
54 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
55 | % Evaluate transfer function
56 | H = zeros(1, L);
57 | h = sampleTime;
58 | if(sampleTime > 0) % Discrete model
59 | for k = 1 : L
60 | H(k) = (a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h));
61 | end
62 | else
63 | for k = 1 : L
64 | H(k) = (a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k));
65 | end
66 | end
67 | % Done!
68 | % Plot bode diagram
69 |
70 | % Get wc, phim
71 | wc = inf;
72 | phim = inf;
73 | flag = false;
74 | for k = 1:length(H)
75 | % The dB need to be over 0 for flag = true
76 | if ((20*log10(abs(H(k))) > 0))
77 | flag = true;
78 | end
79 | % When dB is under 0 and flag = true
80 | if (and(20*log10(abs(H(k))) <= 0, flag == true ))
81 | wc = w(k);
82 | phim = 180 + angle(H(k)) * 180/pi;
83 | break;
84 | end
85 | end
86 |
87 | % Get wpi, Am
88 | wpi = inf;
89 | Am = inf;
90 | for k = 1:length(H)
91 | if (angle(H(k)) * 180/pi <= -180)
92 | wpi = w(k);
93 | Am = 20*log10(abs(H(k)));
94 | break;
95 | end
96 | end
97 |
98 | figure('Name', sprintf(strcat('Transfer function: ', num2str(i), 'x', num2str(j))))
99 | subplot(2,1,1)
100 | semilogx(w, 20*log10(abs(H)), wc, 0, 'x', linspace(wpi, wpi), linspace(0, Am));
101 | legend('Mag', 'Wc', 'Am')
102 | ylabel('Magnitude [dB]');
103 | title(strcat('Am = ', num2str(abs(Am)), ' dB (at ', num2str(wpi), ' rad/s) , ', 'Phim = ', num2str(abs(phim)), ' deg (at ', num2str(wc), ' rad/s)'))
104 | grid on
105 | subplot(2,1,2)
106 |
107 | semilogx(w, angle(H) * 180/pi, linspace(wc, wc), linspace(-180, phim - 180), wpi, -180, 'x');
108 | ylabel('Phase [deg]');
109 | xlabel('Frequency [rad/s]');
110 | grid on
111 | legend('Phase', 'Phim', 'Am')
112 |
113 | % Am
114 | Am = abs(Am);
115 |
116 | end
117 | end
118 | else
119 | error('Only transfer functions and state space models allowed')
120 | end
121 | end
122 |
--------------------------------------------------------------------------------
/matave/+mc/minreal.m:
--------------------------------------------------------------------------------
1 | % Generates the minimal realization of a transfer function by cancle out poles against zeros wiht tolerance tol
2 | % Gernerates the minimal Ho-Kalman-Kung realization of a state space model by cansle out
3 | % non-controllable and non-observable states
4 | % The arbitrary variables r and s controlls the dimension of Hankel Matrix
5 | % Input: TF or SS, tol(optinal), r, s
6 | % Example 1: G = mc.minreal(G, tol)
7 | % Example 2: sys = mc.minreal(sys, s, r)
8 | % Author: Daniel Mårtensson, 2017 Oktober
9 |
10 | function [model] = minreal(varargin)
11 | % Check if there is any input
12 | if(isempty(varargin))
13 | error ('Missing model')
14 | end
15 |
16 | % Get tolerance
17 | if(length(varargin) < 2)
18 | tol = 1e-6;
19 | else
20 | tol = varargin{2};
21 | end
22 |
23 | % Get model type
24 | type = varargin{1}.type;
25 | % Check if there is a TF or SS model
26 | if(strcmp(type, 'SS' ))
27 |
28 | % Get s and r
29 | if(length(varargin) > 2)
30 | s = varargin{2};
31 | r = varargin{3};
32 | else
33 | error('Missing r or s');
34 | end
35 |
36 | % Create discrete model - Important for minimal realization
37 | if(varargin{1}.sampleTime > 0) % Allready Discrete!
38 | sysd = varargin{1};
39 | else % Time continous
40 | sysd = mc.c2d(varargin{1}, 0.1); % Sample time is 0.1 second
41 | end
42 |
43 | % Hankel matrix 0
44 | k = 0;
45 | H0 = mc.obsv(sysd, r)*sysd.A^k*mc.ctrb(sysd, s);
46 | [U,E,V] = svd(H0,'econ');
47 |
48 | % New rank n for finding En, Un, Vn
49 | n = rank(E);
50 | En = E(1:n, 1:n);
51 | Un = U(:, 1:n);
52 | Vn = V(:, 1:n);
53 |
54 | % Create identity matrecies
55 | p = size(sysd.C, 1); % number of outputs
56 | m = size(sysd.B, 2); % number of inputs
57 | Ey = [eye(p,p) zeros(p, (r-1)*p)]';
58 | Eu = [eye(m,m) zeros(m, (s-1)*m)]';
59 |
60 | % Hankel matrix 1
61 | k = 1;
62 | H1 = mc.obsv(sysd, r)*sysd.A^k*mc.ctrb(sysd, s);
63 |
64 | % The new minimal state space realization
65 | A = En^(-1/2)*Un'*H1*Vn*En^(-1/2);
66 | B = En^(1/2)*Vn'*Eu;
67 | C = Ey'*Un*En^(1/2);
68 | D = sysd.D;
69 | model = mc.ss(varargin{1}.delay, A, B, C, D);
70 | if(varargin{1}.sampleTime > 0)
71 | % The model was discrete in the input
72 | model.sampleTime = varargin{1}.sampleTime;
73 | else
74 | % The model was continous in the input
75 | model.sampleTime = 0.1;
76 | model = mc.d2c(model); % Turn it back!
77 | end
78 | % Done!
79 |
80 | elseif(strcmp(type, 'TF' ))
81 | % Get poles
82 | model = varargin{1};
83 | p = mc.pole(model);
84 | % Get zeros
85 | [z, k] = mc.zero(model);
86 | % Get delay
87 | delay = model.delay;
88 | % Get sample time
89 | sampleTime = model.sampleTime;
90 |
91 | % Check in which element they are equal
92 | [a, b, c] = intersect(round(z*1/tol)*tol, round(p*1/tol)*tol);
93 | % Remove zeros and poles if they are equal!
94 | z(b) = [];
95 | p(c) = [];
96 |
97 | % Check if the model has delay
98 | if(delay > 0)
99 | model = mc.zpk(z, p, k, delay);
100 | else
101 | model = mc.zpk(z, p, k);
102 | end
103 |
104 | % Insert sample time
105 | model.sampleTime = sampleTime;
106 |
107 | % Discrete or not?
108 | if (model.sampleTime > 0)
109 | % Replace the delaytime to discrete delay time
110 | model.tfdash = strrep(model.tfdash, 'e', 'z');
111 | model.tfdash = strrep(model.tfdash, 's', '');
112 | % Remove all s -> s
113 | model.tfnum = strrep(model.tfnum, 's', 'z');
114 | model.tfden = strrep(model.tfden, 's', 'z');
115 | end
116 |
117 | else
118 | error('This is not TF or SS');
119 | end
120 |
121 | end
--------------------------------------------------------------------------------
/matave/+mc/modred.m:
--------------------------------------------------------------------------------
1 | % Generates the balanced recuded state space model of a balanced state space model
2 | % Remove states with the tolerance of Hankel singular values
3 | % Input: SS, tol
4 | % Example 1: model = mc.modred(sys, tol)
5 | % Author: Daniel Mårtensson, 2017 October
6 |
7 | function [model] = modred(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing balanced state space model')
11 | end
12 |
13 | if(length(varargin) >= 2)
14 | tol = varargin{2};
15 | else
16 | error('Missing tolerance for the hankel signular values');
17 | end
18 |
19 | % Get model type
20 | type = varargin{1}.type;
21 | % Check if there is a TF or SS model
22 | if(strcmp(type, 'SS' ))
23 | % Get sys
24 | sys = varargin{1};
25 | A = sys.A;
26 | B = sys.B;
27 | C = sys.C;
28 | D = sys.D;
29 | sampleTime = sys.sampleTime;
30 | delay = sys.delay;
31 |
32 | % Get hankel singular values
33 | hsv = diag(mc.hsvd(sys));
34 | hsv = hsv(hsv >= tol);
35 | n = size(hsv, 1); % Dimension states
36 | A = A(1:n, 1:n);
37 | B = B(1:n, :);
38 | C = C(:,1:n);
39 |
40 | % Create the state space model
41 | model = mc.ss(delay, A, B, C, D);
42 | model.sampleTime = sampleTime;
43 |
44 | elseif(strcmp(type, 'TF' ))
45 | disp('Only state space model are allowed')
46 | else
47 | error('This is not TF or SS');
48 | end
49 |
50 | end
--------------------------------------------------------------------------------
/matave/+mc/nlsim.m:
--------------------------------------------------------------------------------
1 | % Do a nonlinear simulation of a nonlinear state space model
2 | % Input: model, u(inputs), x0(initial state vector), stepTime, simulationMethod('ode23', 'ode45', 'ode15s', 'ode23s'), options
3 | % Example 1: [x,t] = mc.nlsim(model, u, x0, stepTime);
4 | % Example 2: [x,t] = mc.nlsim(model, u, x0, stepTime, 'ode23');
5 | % Example 3: [x,t] = mc.nlsim(model, u, x0, stepTime, 'ode23', options);
6 | % Author: Daniel Mårtensson, April 2022
7 |
8 | function [x,t] = nlsim(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing inputs')
12 | end
13 |
14 | % Get model
15 | if(length(varargin) >= 1)
16 | model = varargin{1};
17 | else
18 | error('Missing model')
19 | end
20 |
21 | % Get inputs
22 | if(length(varargin) >= 2)
23 | u = varargin{2};
24 | else
25 | error('Missing inputs')
26 | end
27 |
28 | % Get initial state vector
29 | if(length(varargin) >= 3)
30 | x0 = varargin{3};
31 | else
32 | error('Missing initial state vector')
33 | end
34 |
35 | % Get stepTime
36 | if(length(varargin) >= 4)
37 | stepTime = varargin{4};
38 | else
39 | error('Missing sample time')
40 | end
41 |
42 | % Get simulation method
43 | if(length(varargin) >= 5)
44 | simulationMethod = varargin{5};
45 | else
46 | simulationMethod = 'ode45';
47 | end
48 |
49 | % Get options
50 | if(length(varargin) >= 6)
51 | options = varargin{6};
52 | else
53 | options = odeset();
54 | end
55 |
56 | % Savings
57 | L = length(u);
58 | x = zeros(size(x0, 1), L);
59 | t = zeros(1, L);
60 |
61 | % Loop
62 | for i = 1:L
63 | % Save time and output
64 | x(:, i) = x0;
65 | t(i) = stepTime*(i-1);
66 |
67 | % Simulate ode45, ode23, ode15s, ode23s
68 | tspan = [stepTime*(i-1) stepTime*i];
69 | if(strcmp('ode45', simulationMethod))
70 | [time, output] = ode45(@(t, x) model(t, x, u(:, i)), tspan, x0, options);
71 | elseif(strcmp('ode23', simulationMethod))
72 | [time, output] = ode23(@(t, x) model(t, x, u(:, i)), tspan, x0, options);
73 | elseif(strcmp('ode15s', simulationMethod))
74 | [time, output] = ode15s(@(t, x) model(t, x, u(:, i)), tspan, x0, options);
75 | elseif(strcmp('ode23s', simulationMethod))
76 | [time, output] = ode23s(@(t, x) model(t, x, u(:, i)), tspan, x0, options);
77 | else
78 | error('Choose simulation method such as ode45, ode23, ode15s, ode23s');
79 | end
80 |
81 | % Next state
82 | x0 = output(end, :)';
83 | end
84 |
85 | % This is for the sub plot - How many max rows should we have
86 | rows = max(size(x,1), size(u, 1));
87 |
88 | % Plot - How many subplots?
89 | for i = 1:size(x,1)
90 | subplot(rows,1,i)
91 | plot(t, x(i,:));
92 | ylabel(strcat('x', num2str(i)));
93 | xlabel(strcat(num2str(stepTime), ' time unit/step time'));
94 | grid on
95 | end
96 |
97 | % Plot the input signals as well
98 | for i = 1:size(u, 1)
99 | subplot(rows, 1, i)
100 | hold on
101 | plot(t, u(i, :))
102 | grid on
103 | if(i <= size(x,1))
104 | legend(strcat('x', num2str(i)), strcat('u', num2str(i)))
105 | else
106 | legend(strcat('u', num2str(i)))
107 | end
108 | end
109 |
110 | end
--------------------------------------------------------------------------------
/matave/+mc/nyquist.m:
--------------------------------------------------------------------------------
1 | % Plot the nyquist diagram of a state space model or a transfer function
2 | % between given frequencies w1 and w2
3 | % Input: sys, G
4 | % Example 1: mc.nyquist(sys, w1, w2)
5 | % Example 2: mc.nyquist(G, w1, w2)
6 | % Author: Daniel Mårtensson, 2017 Oktober
7 |
8 | function [reval] = nyquist(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | w2 = varargin{3};
21 | end
22 |
23 | % Get the type
24 | type = varargin{1}.type;
25 | % Check if there is a TF or SS model
26 | if(strcmp(type, 'SS' ))
27 | % SS to TF
28 | G = mc.ss2tf(varargin{1});
29 | % Call nyquist
30 | mc.nyquist(G, w1, w2);
31 | elseif(strcmp(type, 'TF' ))
32 | % If there is a MIMO TF
33 | G = varargin{1};
34 | for i = 1:size(G,1)
35 | for j = 1:size(G,2)
36 | % Get numerator vector and denomerator vector
37 | a = G(i,j).num;
38 | b = G(i,j).den;
39 | % Get delay
40 | delay = G(i,j).delay;
41 | % Get sample time
42 | sampleTime = G(i,j).sampleTime;
43 |
44 | % Numerator and denomerator need to be the same length
45 | if(length(a) > length(b))
46 | b = [zeros(1, size(a,2) - size(b,2)) b];
47 | elseif(length(a) < length(b))
48 | a = [zeros(1, size(b,2) - size(a,2)) a];
49 | end
50 |
51 | L = 10000; % Number of frequency elements - Need to be 10000 for the nyquist plot
52 | N = length(b); % Number of denomerators
53 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
54 | % Evaluate transfer function
55 | H = zeros(1, L);
56 | h = sampleTime;
57 | if(sampleTime > 0) % Discrete model
58 | for k = 1 : L
59 | H(k) = (a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h));
60 | end
61 | else
62 | for k = 1 : L
63 | H(k) = (a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k));
64 | end
65 | end
66 | % Done!
67 | % Plot nyquist diagram
68 |
69 | figure('Name', sprintf(strcat('Transfer function: ', num2str(i), 'x', num2str(j))))
70 | plot([real(H) nan real(H)], [imag(H) nan -imag(H)],-1, 0 ,'+')
71 | title('Nyquist diagram')
72 | xlabel('Real axis')
73 | ylabel('Imaginary axis')
74 | grid on
75 | end
76 | end
77 | else
78 | error('Only transfer functions and state space models allowed')
79 | end
80 | end
81 |
--------------------------------------------------------------------------------
/matave/+mc/obsv.m:
--------------------------------------------------------------------------------
1 | % Generates the observability matrix of a state space model
2 | % Input: sys, n(optinal)
3 | % Example 1: Or = mc.obsv(sys)
4 | % Example 2: Or = mc.obsv(sys, n)
5 | % Author: Daniel Mårtensson, 2017 Oktober
6 |
7 | function [Or] = obsv(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % Get SS
18 | sys = varargin{1};
19 |
20 | % If we specify n, that means we are using minreal.m
21 | if(length(varargin) > 1)
22 | n = varargin{2};
23 | else
24 | n = size(sys.A, 1); % Else, we only check the dimension of A
25 | end
26 |
27 | % Compute the observability matrix now!
28 | Or = [];
29 | for i = 0:(n-1)
30 | Or = [Or; sys.C*sys.A^i];
31 | end
32 |
33 | elseif(strcmp(type, 'TF' ))
34 | % Get TF
35 | disp('Only state space models allowed');
36 | else
37 | error('This is not TF or SS');
38 | end
39 | end
--------------------------------------------------------------------------------
/matave/+mc/pade.m:
--------------------------------------------------------------------------------
1 | % Do a pade approximation of a transfer function
2 | % Input: G, n
3 | % Example 1: G = mc.pade(G, n)
4 | % Author: Daniel Mårtensson, Februari 2018
5 |
6 | function [model] = pade(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error('Missing model')
10 | end
11 |
12 | % Check if there is any input
13 | if(length(varargin) < 2)
14 | error('Please, insert the order of Pade Approximation: 1, 2, 3 or 4')
15 | end
16 |
17 | % Get the type
18 | type = varargin{1}.type;
19 | % Check if there is a TF or SS model
20 | if(strcmp(type, 'TF' ))
21 | % If there is a MIMO TF
22 | G = varargin{1};
23 | PadeOrder = varargin{2};
24 | for i = 1:size(G,1)
25 | for j = 1:size(G,2)
26 | % Get numerator vector and denomerator vector
27 | a = G(i,j).num;
28 | b = G(i,j).den;
29 | % Get delay
30 | delay = G(i,j).delay;
31 | % Get sample time
32 | sampleTime = G(i,j).sampleTime;
33 | if(and(sampleTime > 0, delay > 0))
34 | error('You cannot turn time continous transfer function with delay into discrete transfer function. Try state space instead: sys = mc.tf2ss(G) -> sysd = mc.c2d(sys)');
35 | end
36 |
37 | switch PadeOrder
38 | case 1
39 | TFdelay = mc.tf([-delay 2],[delay 2]);
40 | case 2
41 | TFdelay = mc.tf([delay^2 -6*delay 12],[delay^2 6*delay 12]);
42 | case 3
43 | TFdelay = mc.tf([-delay^3 12*delay^2 -60*delay 120],[delay^3 12*delay^2 60*delay 120]);
44 | case 4
45 | TFdelay = mc.tf([delay^4 -20*delay^3 180*delay^2 -840*delay 1680],[delay^4 20*delay^3 180*delay^2 840*delay 1680]);
46 | otherwise
47 | error('Maximum Pade number is 4')
48 | end
49 |
50 | % Need to have the same sample time. Or else series.m won't work for us
51 | TFdelay.sampleTime = sampleTime;
52 |
53 | % Remove the delay because we don't want e^(-delay*s) notion
54 | G(i,j).delay = 0;
55 | model = mc.series(G(i,j), TFdelay);
56 | % Add sample time
57 | model.sampleTime = sampleTime;
58 | model.delay = delay;
59 |
60 | end
61 | end
62 | else
63 | error('Only transfer functions');
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/matave/+mc/parallel.m:
--------------------------------------------------------------------------------
1 | % Generates the new transfer function or new state space model of parallel connection
2 | % Input: G, sys
3 | % Example 1: G = mc.parallel(G1, G2)
4 | % Example 2: sys = mc.parallel(sys1, sys2)
5 | % Author: Daniel Mårtensson 2017 Oktober
6 |
7 | function [model] = parallel(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Check if there is a second input
14 | if(isempty(varargin{2}))
15 | error ('Missing second model')
16 | end
17 |
18 | % Get model type
19 | type = varargin{1}.type;
20 | % Check if there is a TF or SS model
21 | if(strcmp(type, 'SS' ))
22 | % Get info
23 | sys1 = varargin{1};
24 | sys2 = varargin{2};
25 | if(sys1.sampleTime == sys2.sampleTime)
26 | % Get matrecies
27 | A1 = sys1.A;
28 | A2 = sys2.A;
29 | B1 = sys1.B;
30 | B2 = sys2.B;
31 | C1 = sys1.C;
32 | C2 = sys2.C;
33 | D1 = sys1.D;
34 | D2 = sys2.D;
35 |
36 | % Get big state space
37 | A = [A1 zeros(size(A1, 1), size(A2, 2)); zeros(size(A2, 1), size(A1, 2)) A2];
38 | B = [B1; B2];
39 | C = [C1 C2];
40 | D = (D1 + D2);
41 | delay = max([sys1.delay sys2.delay]);
42 | model = mc.ss(delay, A, B, C, D);
43 | model.sampleTime = sys1.sampleTime;
44 | else
45 | error('Need to have the same sampling time')
46 | end
47 | elseif(strcmp(type, 'TF' ))
48 | % Get info
49 | G1 = varargin{1};
50 | G2 = varargin{2};
51 | if(G1.sampleTime == G2.sampleTime)
52 | % Get num and den
53 | num1 = G1.num;
54 | den1 = G1.den;
55 | num2 = G2.num;
56 | den2 = G2.den;
57 | % Get delay
58 | if(G1.delay > G2.delay)
59 | delay = G2.delay;
60 | else
61 | delay = G1.delay;
62 | end
63 |
64 |
65 | % Extend - pad
66 | num1 = [zeros(1, length(num2) - length(num1)) num1];
67 | den1 = [zeros(1, length(den2) - length(den1)) den1];
68 | num2 = [zeros(1, length(num1) - length(num2)) num2];
69 | den2 = [zeros(1, length(den1) - length(den2)) den2];
70 |
71 | % Sum
72 | num = conv(num1, den2) + conv(num2, den1);
73 | den = conv(den1, den2);
74 |
75 | if(delay > 0)
76 | model = mc.tf(num, den, delay);
77 | else
78 | model = mc.tf(num, den);
79 | end
80 | model.sampleTime = G1.sampleTime;
81 |
82 | % Discrete or not?
83 | if (model.sampleTime > 0)
84 | % Replace the delaytime to discrete delay time
85 | model.tfdash = strrep(model.tfdash, 'e', 'z');
86 | model.tfdash = strrep(model.tfdash, 's', '');
87 | % Remove all s -> s
88 | model.tfnum = strrep(model.tfnum, 's', 'z');
89 | model.tfden = strrep(model.tfden, 's', 'z');
90 | end
91 | else
92 | error('Need to have the same sampling time')
93 | end
94 | else
95 | error('This is not TF or SS');
96 | end
97 | end
98 |
--------------------------------------------------------------------------------
/matave/+mc/pid.m:
--------------------------------------------------------------------------------
1 | % Generates the parallel PID controller as a transfer function
2 | % Input: Kp, Ti(Integrator, Optinal), Td(Derivative, Optional), Tf(Low pass filter, Optinal), Ts(Sample time, Optinal)
3 | % Example 1: [Gpid] = mc.pid(Kp, Ti, Td, Tf, Ts)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 |
6 | function [Gpid] = pid(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing parameters')
10 | end
11 |
12 | % Input the parameters
13 | if(length(varargin) >= 1)
14 | Kp = mc.tf(varargin{1}, 1);
15 | Gpid = Kp;
16 | else
17 | error('Need to have at least Kp');
18 | end
19 |
20 | % Integrator
21 | if(length(varargin) >= 2)
22 | Ki = mc.tf(varargin{2}, [1 0]);
23 | Gpid = mc.parallel(Kp, Ki);
24 | else
25 | Ti = 0;
26 | end
27 |
28 | % Derivative
29 | if(length(varargin) >= 3)
30 | Td = varargin{3};
31 | else
32 | Td = 0;
33 | end
34 |
35 | % Low pass filter for derivative
36 | if(length(varargin) >= 4)
37 | Tf = varargin{4};
38 | Kd = mc.tf([Td 0], [Tf 1]);
39 | else
40 | Tf = 0;
41 | Kd = mc.tf([Td 0], [1]);
42 | end
43 |
44 | % Sampling time
45 | if(length(varargin) >= 5)
46 | Ts = varargin{5};
47 | else
48 | Ts = 0;
49 | end
50 |
51 | % Build the PID
52 | % Check if derivative was 0
53 | if Td > 0
54 | Gpid = mc.parallel(Gpid, Kd);
55 | end
56 |
57 | % Else - Just return Gpid as it is
58 |
59 | % Convert to discrete if needed
60 | if(Ts > 0)
61 | Gpid = mc.c2d(Gpid, Ts);
62 | end
63 |
64 | end
65 |
--------------------------------------------------------------------------------
/matave/+mc/pipd.m:
--------------------------------------------------------------------------------
1 | % Generates the serial PID controller as a transfer function
2 | % Input: Kp, Ti(optinal), Td(optional), b(optinal), Ts(optinal)
3 | % Example 1: [Gpipd] = mc.pipd(Kp, Ti, Td, b, Ts)
4 | % Author: Daniel Mårtensson, Oktober 2017
5 |
6 | function [Gpipd] = pipd(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing parameters')
10 | end
11 |
12 | % Input the parameters
13 | if(length(varargin) >= 1)
14 | Kp = varargin{1};
15 | else
16 | error('Need to have at least Kp');
17 | end
18 |
19 | % Integrator
20 | if(length(varargin) >= 2)
21 | Ti = varargin{2};
22 | else
23 | Ti = 0;
24 | end
25 |
26 | % Derivative
27 | if(length(varargin) >= 3)
28 | Td = varargin{3};
29 | else
30 | Td = 0;
31 | end
32 |
33 | % High pass filter
34 | if(length(varargin) >= 4)
35 | b = varargin{4};
36 | else
37 | b = 0;
38 | end
39 |
40 | % Sampling time
41 | if(length(varargin) >= 5)
42 | Ts = varargin{5};
43 | else
44 | Ts = 0;
45 | end
46 |
47 | % Build the PIPD
48 | Gpipd = mc.tf([Kp*Ti*Td Kp*(Ti+Td) Kp],[Ti*Td/b Ti 0]);
49 |
50 | % Convert to discrete if needed
51 | if(Ts > 0)
52 | Gpipd = mc.c2d(Gpipd, Ts);
53 | end
54 |
55 | end
56 |
--------------------------------------------------------------------------------
/matave/+mc/pole.m:
--------------------------------------------------------------------------------
1 | % Generates poles from transfer functions or state space models
2 | % Input: TF or SS
3 | % Example 1: p = mc.pole(G)
4 | % Example 2: p = mc.pole(sys)
5 | % Author: Daniel Mårtensson 2017 September
6 |
7 | function [p] = pole(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % Get poles
18 | A = varargin{1}.A;
19 | p = eig(A); % Eigenvalues
20 | elseif(strcmp(type, 'TF' ))
21 | % Get poles
22 | G = varargin{1};
23 | p = roots(G.den);
24 | else
25 | error('This is not TF or SS');
26 | end
27 |
28 | end
--------------------------------------------------------------------------------
/matave/+mc/pzmap.m:
--------------------------------------------------------------------------------
1 | % Plot poles and zeros of a transfer function or of a state space model
2 | % Input: G, sys
3 | % Example 1: [p, z] = mc.pzmap(G)
4 | % Example 2: [p, z] = mc.pzmap(sys)
5 | % Author: Daniel Mårtensson, 2017 September
6 |
7 | function [p, z] = pzmap(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % Get poles
18 | p = mc.pole(varargin{1})
19 | z = mc.tzero(varargin{1})
20 | plot(real(p), imag(p), 'o', real(z), imag(z), 'x');
21 | grid on
22 | title('Pole-Zero Map')
23 | xlabel('Real axis');
24 | ylabel('Imaginary axis');
25 |
26 | % If we have no zeros - It can happen!
27 | if isempty(z)
28 | legend('poles');
29 | else
30 | legend('poles', 'zeros');
31 | end
32 | elseif(strcmp(type, 'TF' ))
33 | % Get G
34 | G = varargin{1};
35 | % Get poles and zeros
36 | z = roots(G.num);
37 | p = roots(G.den);
38 | plot(real(p), imag(p), 'o', real(z), imag(z), 'x');
39 | grid on
40 | title('Pole-Zero Map')
41 | xlabel('Real axis');
42 | ylabel('Imaginary axis');
43 |
44 | % If we have no zeros - It can happen!
45 | if isempty(z)
46 | legend('poles');
47 | else
48 | legend('poles', 'zeros');
49 | end
50 | else
51 | error('This is not TF or SS');
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/matave/+mc/quadprog.m:
--------------------------------------------------------------------------------
1 | % This is quadratic programming with Hildreth's method
2 | % Min 1/2x^TQx + c^Tx
3 | % S.t Ax <= b
4 | %
5 | % If you want to do maximization, then turn Q and c negative. The constraints are the same
6 | %
7 | % Max 1/2x^T(-Q)x + (-c)^Tx
8 | % S.t Ax <= b
9 | %
10 | % Input: Q(Symmetric matrix), c(Objective function), A(Constraint matrix), b(Constraint vector)
11 | % Output: x(Solution vector), solution(boolean flag)
12 | % Example 1: [x, solution] = mc.quadprog(Q, c, A, b)
13 | % Author: Daniel Mårtensson 2022 September 3
14 |
15 | function [x, solution] = quadprog(Q, c, A, b)
16 | % Assume that the solution is true
17 | solution = true;
18 |
19 | % Same as in C code for Functions.h at CControl
20 | MIN_VALUE = 1e-11;
21 | MAX_ITERATIONS = 10000;
22 |
23 | % Unconstrained solution
24 | x = -linsolve(Q, c);
25 |
26 | % Constraints difference
27 | K = b - A*x;
28 |
29 | % Check if all the constraints are satisfied
30 | if(sum(K < 0) == 0)
31 | return; % All satisfied
32 | end
33 |
34 | % Create P
35 | P = linsolve(Q, A');
36 |
37 | % Create H = A*Q*A'
38 | H = A*P;
39 |
40 | % Solve lambda from H*lambda = -K, where lambda >= 0
41 | [m, n] = size(K);
42 | lambda = zeros(m, n);
43 | for km = 1:MAX_ITERATIONS
44 | lambda_p = lambda;
45 |
46 | % Use Gauss Seidel
47 | for i = 1:m
48 | w = -1.0/H(i,i)*(K(i) + H(i,:)*lambda - H(i,i)*lambda(i));
49 | lambda(i) = max(0, w);
50 | end
51 |
52 | % Check if the minimum convergence has been reached
53 | w = (lambda - lambda_p)'*(lambda - lambda_p);
54 | if (w < MIN_VALUE)
55 | break;
56 | end
57 |
58 | % Check if the maximum iteration have been reached
59 | if(km == MAX_ITERATIONS)
60 | solution = false;
61 | return;
62 | end
63 | end
64 |
65 | % Find the solution: x = -inv(Q)*c - inv(Q)*A'*lambda
66 | x = x - P*lambda;
67 | end
68 |
--------------------------------------------------------------------------------
/matave/+mc/ramp.m:
--------------------------------------------------------------------------------
1 | % Ramp a state space model or a transfer function
2 | % Input: sys, G, t(optinal)
3 | % Example 1: [y,t,x] = mc.ramp(G, t)
4 | % Example 2: [y,t,x] = mc.ramp(G)
5 | % Example 3: [y,t,x] = mc.ramp(sys, t)
6 | % Author: Daniel Mårtensson, 2017 September
7 |
8 | function [y,t,X] = ramp(varargin)
9 | % Check if there is some input arguments or it's not a model
10 | if(isempty(varargin{1}))
11 | error ('Missing input')
12 | end
13 |
14 | % Check if there is a model
15 | if(strcmp(varargin{1}.type,'SS'))
16 |
17 | % Get time
18 | if(length(varargin) >= 2)
19 | t = varargin{2};
20 | else
21 | disp('Time assumed to be 10 seconds');
22 | t = 10;
23 | end
24 |
25 | % Get sample time to compute the new time vector
26 | sampleTime = varargin{1}.sampleTime;
27 | if(sampleTime > 0)
28 | t = 0:sampleTime:t;
29 | else
30 | t = 0:0.01:t; % Sample time assumed to be 0.01
31 | end
32 |
33 | % Multiple signals...or not!
34 | u = linspace(0,1, length(t));
35 | u = repmat(u, size(varargin{1}.B, 2), 1); % Creates 0 -> 1
36 | x0 = zeros(size(varargin{1}.A, 1), 1); % Assume x0 = [0; 0; 0; ..... ; 0]
37 | % Call lsim!
38 | [y,t,X] = mc.lsim(varargin{1}, u, t, x0);
39 | elseif(strcmp(varargin{1}.type,'TF'))
40 | % TF to SS
41 | sys = mc.tf2ss(varargin{1}, 'OCF');
42 |
43 | % Get time
44 | if(length(varargin) >= 2)
45 | t = varargin{2};
46 | else
47 | disp('Time assumed to be 10 seconds');
48 | t = 10;
49 | end
50 |
51 | % Call ramp
52 | [y,t,X] = mc.ramp(sys,t);
53 | else
54 | error('Not a state space model or a transfer function')
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/matave/+mc/referencegain.m:
--------------------------------------------------------------------------------
1 | % Computes the reference gain Kr and give back a state space model with including the reference gain
2 | % Input: sys
3 | % Example 1: [sys_kr, Kr] = mc.referencegain(sys)
4 | % Author: Daniel Mårtensson, September 2018
5 |
6 | function [sys_kr, Kr] = referencegain(varargin)
7 | % Check if there is any input
8 | if(isempty(varargin))
9 | error ('Missing input')
10 | end
11 | % Get model type
12 | type = varargin{1}.type;
13 | % Check if there is a TF or SS model
14 | if(strcmp(type, 'SS' ))
15 | % Get A, B, C, D matrecies
16 | sys = varargin{1};
17 | A = sys.A;
18 | B = sys.B;
19 | C = sys.C;
20 | D = sys.D;
21 | delay = sys.delay;
22 | sampleTime = sys.sampleTime;
23 |
24 | if sampleTime > 0
25 | Kr = 1./(C*inv(eye(size(A)) - A)*B);
26 | else
27 | Kr = 1./(C*inv(-A)*B);
28 | end
29 | % Now create B matrix with precompensator factor - For better tracking
30 | B = B*Kr;
31 |
32 | sys_kr = mc.ss(delay, A, B, C, D);
33 | sys_kr.sampleTime = sampleTime;
34 |
35 | elseif(strcmp(type, 'TF' ))
36 | disp('Only state space models')
37 | else
38 | error('This is not TF or SS');
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/matave/+mc/reg.m:
--------------------------------------------------------------------------------
1 | % Generates the state feedback controler with the control law L and with integral action law Li
2 | % Input: sys, L, Li(optional), Kr(optional)
3 | % Example 1: [regsys] = mc.reg(sys, L)
4 | % Example 2: [regsys] = mc.reg(sys, L, Li)
5 | % Example 3: [regsys] = mc.reg(sys, L, Li)
6 | % Author: Daniel Mårtensson, November 2017
7 |
8 | function [regsys] = reg(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error ('Missing input')
12 | end
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 |
18 | % Get the control law L;
19 | if(length(varargin) >= 2)
20 | L = varargin{2};
21 | else
22 | error('Missing the control law L');
23 | end
24 |
25 | % Get the integral control law Li
26 | if(length(varargin) >= 3)
27 | Li = varargin{3};
28 | end
29 |
30 | % Check if what feedback controller you should use
31 | regulatorNumber = length(varargin);
32 |
33 | % Get A, B, C, D matrecies
34 | sys = varargin{1};
35 | A = sys.A;
36 | B = sys.B;
37 | C = sys.C;
38 | D = sys.D;
39 | delay = sys.delay;
40 | sampleTime = sys.sampleTime;
41 |
42 | % Create new feedback model
43 | switch regulatorNumber
44 | case 2 % Standard LQR
45 |
46 | %{
47 | From this:
48 | dx = Ax + Bu
49 | y = Cx + Du
50 | u = -uf + r = -Lx + r % Feedback control law
51 | To this:
52 | dx = (A-BL)x + Br
53 | [y;uf] = [C; L]x + [D;0]r
54 | %}
55 |
56 | % Create the A matrix
57 | A = (A-B*L);
58 | %B matrix is the same
59 | C = [C;L]; % This is for the uf = L*x control law
60 | D = [D; D*0]; % D need to have the same row length as C
61 |
62 | regsys = mc.ss(delay, A, B, C, D);
63 | regsys.sampleTime = sampleTime;
64 |
65 | case 3 % LQR with integral action LQI
66 | % Create A matrix
67 | A = [(A-B*L) B*Li; (D*L-C) -D*Li];
68 |
69 | % Create B matrix
70 | ny = size(C, 1); % Number outputs
71 | nu = size(B, 2); % Number inputs
72 | B = [0*B; ones(ny, nu)]; % <- precompensator for reference = 0
73 |
74 | % Create C matrix
75 | C = [(C-D*L) D*Li];
76 |
77 | % Matrix D will be created by it self
78 |
79 | regsys = mc.ss(delay, A, B, C, D);
80 | regsys.sampleTime = sampleTime;
81 | case 4 % LQR with integral action LQI + precompensator for reference
82 | % Create A matrix
83 | A = [(A-B*L) B*Li; (D*L-C) -D*Li];
84 |
85 | % Create B matrix
86 | ny = size(C, 1); % Number outputs
87 | nu = size(B, 2); % Number inputs
88 | B = [B; ones(ny, nu)];
89 |
90 | % Create C matrix
91 | C = [(C-D*L) D*Li];
92 |
93 | % Matrix D will be created by it self
94 |
95 | regsys = mc.ss(delay, A, B, C, D);
96 | regsys.sampleTime = sampleTime;
97 | end
98 |
99 | elseif(strcmp(type, 'TF' ))
100 | disp('Only state space models')
101 | else
102 | error('This is not TF or SS');
103 | end
104 | end
105 |
--------------------------------------------------------------------------------
/matave/+mc/rlocfind.m:
--------------------------------------------------------------------------------
1 |
2 | function [K] = rlocfind (varargin)
3 | % Check if there is any input
4 | if(isempty(varargin))
5 | error ('Missing input')
6 | end
7 |
8 | % Get pole location
9 | if(length(varargin) >= 2)
10 | p = varargin{2};
11 | else
12 | error('Missing pole location');
13 | end
14 |
15 | % Get model type
16 | type = varargin{1}.type;
17 | % Check if there is a TF or SS model
18 | if(strcmp(type, 'SS' ))
19 | % SS to TF
20 | G = mc.ss2tf(varargin{1});
21 | [k, poles] = mc.rlocfind(G, p);
22 | elseif(strcmp(type, 'TF' ))
23 | % If there is a MIMO TF
24 | G = varargin{1};
25 | K = zeros(size(G,1), size(G,2));
26 |
27 | for i = 1:size(G,1)
28 | for j = 1:size(G,2)
29 | % Get numerator vector and denomerator vector
30 | a = G(i,j).num;
31 | b = G(i,j).den;
32 | % Get delay
33 | delay = G(i,j).delay;
34 | % Get sample time
35 | sampleTime = G(i,j).sampleTime;
36 |
37 | % Numerator and denomerator need to be the same length
38 | if(length(a) > length(b))
39 | b = [zeros(1, size(a,2) - size(b,2)) b];
40 | elseif(length(a) < length(b))
41 | a = [zeros(1, size(b,2) - size(a,2)) a];
42 | end
43 |
44 | N = length(b);
45 | h = sampleTime;
46 | % Notice that a and b has been switched, compared to bode.m
47 | if sampleTime > 0
48 | K(i,j) = abs((b*fliplr((exp(p*h)).^(0 : N-1)).')/(a*fliplr((exp(p*h)).^(0 : N-1)).')*exp(-delay*exp(p*h)));
49 | else
50 | K(i,j) = abs(b*fliplr((p).^(0 : N-1)).'/(a*fliplr(p.^(0 : N-1)).')*exp(-delay*p));
51 | end
52 |
53 | end
54 | end
55 |
56 | else
57 | error('Error model structure - Unknow');
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/matave/+mc/rlocus.m:
--------------------------------------------------------------------------------
1 | % Plot root locus plot from a transfer function or state space model at given vector of gains gainvector
2 | % Input: sys, G, gainvector
3 | % Example 1: mc.rlocus(sys, gainvector)
4 | % Example 2: mc.rlocus(G, gainvector)
5 | % Author: Daniel Mårtensson, 2017 Oktober
6 |
7 | function [retval] = rlocus(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error('Missing model')
11 | end
12 |
13 | % Get the type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % SS to TF
18 | G = mc.ss2tf(varargin{1});
19 | if(length(varargin) >= 2)
20 | Kvector = varargin{2};
21 | else
22 | error('Missing K gain vector');
23 | end
24 | % Call rlocus
25 | mc.rlocus(G, Kvector);
26 | elseif(strcmp(type, 'TF' ))
27 | % If there is a MIMO TF
28 | G = varargin{1};
29 | for i = 1:size(G,1)
30 | for j = 1:size(G,2)
31 | % Get sample time
32 | sampleTime = G(i,j).sampleTime;
33 | % Gain K vector
34 | if(length(varargin) >= 2)
35 | Kvector = varargin{2};
36 | else
37 | error('Missing K gain vector');
38 | end
39 |
40 | % Size of the pole and zeros
41 | [npole,mpole] = size(mc.pole(G));
42 | [nzero,mzero] = size(mc.zero(G));
43 | % Create empty vectors for storeing the zeros and poles
44 | pvector = [];%zeros(npole, length(Kvector));
45 | zvector = [];%zeros(nzero, length(Kvector));
46 | for k = 1:length(Kvector)
47 | if(sampleTime > 0) % Discret
48 | GK = mc.tf(Kvector(k),1);
49 | GKd = mc.c2d(GK, sampleTime); % Sampleing time need to be the same
50 | Gfeedback = mc.feedback(G(i,j), GKd);
51 | else
52 | GK = mc.tf(Kvector(k),1);
53 | Gfeedback = mc.feedback(G(i,j), GK);
54 | end
55 | pvector(:,k) = mc.pole(Gfeedback);
56 | zvector(:,k) = mc.zero(Gfeedback);
57 | end
58 | % Done! Plot it now!
59 |
60 | figure('Name', sprintf(strcat('Transfer function: ', num2str(i), 'x', num2str(j))))
61 | plot(real(pvector), imag(pvector), '.r', real(zvector), imag(zvector), 'bo');
62 | grid on
63 |
64 | % Scale plot
65 | xlim([-10 10])
66 | ylim([-10 10])
67 |
68 | % Title
69 | title('Root Locus');
70 | xlabel('Real Axsis (Seconds^-1)');
71 | ylabel('Imaginary Axis (Seconds^-1)');
72 |
73 | end
74 | end
75 | else
76 | error('Only transfer functions and state space models allowed')
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/matave/+mc/sensitivity.m:
--------------------------------------------------------------------------------
1 | % Plot the nyquist diagram of a state space model or a transfer function
2 | % between given frequencies w1 and w2
3 | % Input: G, sys, w1, w2
4 | % Example 1: [Margin_Sensitivity] = mc.sensitivity(sys, w1, w2)
5 | % Example 2: [Margin_Sensitivity] = mc.sensitivity(G, w1, w2)
6 | % Author: Daniel Mårtensson, 2017 Oktober
7 |
8 | function [Ms] = sensitivity(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | w2 = varargin{3};
21 | end
22 |
23 |
24 | % Get the type
25 | type = varargin{1}.type;
26 | % Check if there is a TF or SS model
27 | if(strcmp(type, 'SS' ))
28 | % SS to TF
29 | G = mc.ss2tf(varargin{1});
30 | % Call sensitivity
31 | Ms = mc.sensitivity(G, w1, w2);
32 | elseif(strcmp(type, 'TF' ))
33 | % If there is a MIMO TF
34 | G = varargin{1};
35 | Ms = zeros(size(G,1), size(G,2)); % The return matrix
36 | for i = 1:size(G,1)
37 | for j = 1:size(G,2)
38 | % Get numerator vector and denomerator vector
39 | a = G(i,j).num;
40 | b = G(i,j).den;
41 | % Get delay
42 | delay = G(i,j).delay;
43 | % Get sample time
44 | sampleTime = G(i,j).sampleTime;
45 |
46 | % Numerator and denomerator need to be the same length
47 | if(length(a) > length(b))
48 | b = [zeros(1, size(a,2) - size(b,2)) b];
49 | elseif(length(a) < length(b))
50 | a = [zeros(1, size(b,2) - size(a,2)) a];
51 | end
52 |
53 | L = 10000; % Number of frequency elements - Need to be 10000 for the nyquist plot
54 | N = length(b); % Number of denomerators
55 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
56 | % Evaluate transfer function
57 | H = zeros(1, L);
58 | h = sampleTime;
59 | if(sampleTime > 0) % Discrete model
60 | for k = 1 : L
61 | H(k) = (a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h));
62 | end
63 | else
64 | for k = 1 : L
65 | H(k) = (a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k));
66 | end
67 | end
68 | % Done!
69 | % Plot nyquist diagram
70 | % Done!
71 | % Plot nyquist diagram
72 |
73 | % Get Ms
74 | Ms = min(1+H);
75 | Mt = 1.3;
76 | x0 = -Mt^2/(Mt^2 + 1);
77 | y0 = 0;
78 | r = Mt/(Mt^2+1);
79 |
80 | % Get the Mt circle
81 | ang = 0:0.01:2*pi;
82 | xp = r*cos(ang);
83 | yp = r*sin(ang);
84 |
85 | figure('Name', sprintf(strcat('Transfer function: ', num2str(i), 'x', num2str(j))))
86 | plot([real(H)], [imag(H)],-1, 0 ,'+', linspace(-1, -abs(1-real(Ms))), linspace(0, imag(Ms)), x0 + xp, y0 + yp)
87 | title('Nyquist diagram')
88 | xlabel('Real axis')
89 | ylabel('Imaginary axis')
90 | grid on
91 | legend('real imag', 'instability point', 'max(S(jw))', 'max(T(jw)) = 1.3')
92 |
93 | %Ms(i,j) = abs(min(1/1+H));
94 | Ms(i,j) = abs(Ms);
95 | end
96 | end
97 | else
98 | error('Only transfer functions and state space models allowed')
99 | end
100 | end
101 |
102 |
--------------------------------------------------------------------------------
/matave/+mc/series.m:
--------------------------------------------------------------------------------
1 | % Do a serial connection of transfer functions or state space models
2 | % Input: G, sys
3 | % Example 1: G = mc.series(G1, G2)
4 | % Example 2: sys = mc.series(sys1, sys2)
5 | % Author: Daniel Mårtensson, 2017 Oktober
6 |
7 | function [model] = series(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Check if there is a second input
14 | if(isempty(varargin{2}))
15 | error ('Missing second model')
16 | end
17 |
18 | % Get model type
19 | type = varargin{1}.type;
20 | % Check if there is a TF or SS model
21 | if(strcmp(type, 'SS' ))
22 | % Get info
23 | sys1 = varargin{1};
24 | sys2 = varargin{2};
25 | if(sys1.sampleTime == sys2.sampleTime)
26 | % Get matrecies
27 | A1 = sys1.A;
28 | A2 = sys2.A;
29 | B1 = sys1.B;
30 | B2 = sys2.B;
31 | C1 = sys1.C;
32 | C2 = sys2.C;
33 | D1 = sys1.D;
34 | D2 = sys2.D;
35 |
36 | % Get big state space
37 | A = [A1 zeros(size(A1, 1), size(A2, 2)); B2*C1 A2];
38 | B = [B1; B2*D1];
39 | C = [D2*C1 C2];
40 | D = D2*D1;
41 | delay = sys1.delay + sys2.delay;
42 | model = mc.ss(delay, A, B, C, D);
43 | model.sampleTime = sys1.sampleTime;
44 | else
45 | error('Need to have the same sampling time')
46 | end
47 | elseif(strcmp(type, 'TF' ))
48 | % Get TF
49 | G1 = varargin{1};
50 | G2 = varargin{2};
51 | if(G1.sampleTime == G2.sampleTime)
52 | % Get num and den
53 | num1 = G1.num;
54 | den1 = G1.den;
55 | num2 = G2.num;
56 | den2 = G2.den;
57 | % Get delay
58 | delay = G1.delay + G2.delay;
59 | num = conv(num1, num2);
60 | den = conv(den1, den2);
61 | if(delay > 0)
62 | model = mc.tf(num, den, delay);
63 | else
64 | model = mc.tf(num, den);
65 | end
66 | model.sampleTime = G1.sampleTime;
67 |
68 | % Discrete or not?
69 | if (model.sampleTime > 0)
70 | % Replace the delaytime to discrete delay time
71 | model.tfdash = strrep(model.tfdash, 'e', 'z');
72 | model.tfdash = strrep(model.tfdash, 's', '');
73 | % Remove all s -> s
74 | model.tfnum = strrep(model.tfnum, 's', 'z');
75 | model.tfden = strrep(model.tfden, 's', 'z');
76 | end
77 | else
78 | error('Need to have the same sampling time')
79 | end
80 | else
81 | error('This is not TF or SS');
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/matave/+mc/sgrid.m:
--------------------------------------------------------------------------------
1 | function sgrid(z, wn)
2 | % Do the circle
3 | ang=0:0.01:2*pi;
4 | xp=wn*cos(ang);
5 | yp=wn*sin(ang);
6 |
7 | % Do the slope lines
8 | y1 = [0 wn*sqrt(1-z^2)];
9 | y2 = [0 -wn*sqrt(1-z^2)];
10 | x1 = [0 -z*wn];
11 | x2 = [0 -z*wn];
12 |
13 | % Plot now
14 | hold on
15 | plot(xp, yp,'.-', x1, y1, '.-', x2, y2, '.-')
16 | end
--------------------------------------------------------------------------------
/matave/+mc/sigma.m:
--------------------------------------------------------------------------------
1 | % Plot sigma diagram from a transfer function or state space model
2 | % between given frequencies w1 and w2
3 | % Input: G, sys, w1, w2
4 | % Example 1: mc.sigma(sys, w1, w2)
5 | % Example 2: mc.sigma(G, w1, w2)
6 | % Author: Daniel Mårtensson, 2017 Oktober
7 |
8 | function [retval] = sigma(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error('Missing model')
12 | end
13 |
14 | % Check if there is any input
15 | if(length(varargin) < 3)
16 | w1 = 0.01;
17 | w2 = 100;
18 | else
19 | w1 = varargin{2};
20 | w2 = varargin{3};
21 | end
22 |
23 | % Get the type
24 | type = varargin{1}.type;
25 | % Check if there is a TF or SS model
26 | if(strcmp(type, 'SS' ))
27 | % SS to TF
28 | G = mc.ss2tf(varargin{1});
29 | % Call sigma
30 | mc.sigma(G, w1, w2);
31 | elseif(strcmp(type, 'TF' ))
32 | % If there is a MIMO TF
33 | G = varargin{1};
34 | % Create H
35 | L = 1000; % Number of frequency elements
36 | H = zeros(size(G,1),size(G,2), L);
37 | for i = 1:size(G,1)
38 | for j = 1:size(G,2)
39 | % Get numerator vector and denomerator vector
40 | a = G(i,j).num;
41 | b = G(i,j).den;
42 | % Get delay
43 | delay = G(i,j).delay;
44 | % Get sample time
45 | sampleTime = G(i,j).sampleTime;
46 |
47 | % Numerator and denomerator need to be the same length
48 | if(length(a) > length(b))
49 | b = [zeros(1, size(a,2) - size(b,2)) b];
50 | elseif(length(a) < length(b))
51 | a = [zeros(1, size(b,2) - size(a,2)) a];
52 | end
53 |
54 | N = length(b); % Number of denomerators
55 | w = logspace(log10(w1), log10(w2), L); % Angular frequencies
56 | % Evaluate transfer function
57 | % norm(A,2) = max(SVD(A))
58 | h = sampleTime;
59 | if(sampleTime > 0) % Discrete model
60 | for k = 1 : L
61 | H(i,j,k) = norm((a*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')/(b*fliplr((exp(1i*w(k)*h)).^(0 : N-1)).')*exp(-delay*exp(1i*w(k)*h)), 2);
62 | end
63 | else
64 | for k = 1 : L
65 | H(i,j,k) = norm((a*fliplr((1i*w(k)).^(0 : N-1)).')/(b*fliplr((1i*w(k)).^(0 : N-1)).')*exp(-delay*1i*w(k)), 2);
66 | end
67 | end
68 |
69 | % Done!
70 | end
71 | end
72 | % Plot now!
73 | legendStr = ['']; % Need to have '', or else legendStr is numeric
74 | for i = 1:size(H,1)
75 | for j = 1:size(H,2)
76 | y = H(i,j,:);
77 | semilogx(w, 20*log10(abs(y(:))), 'color', rand(1,3));
78 | grid on
79 | ylabel('Magnitude [dB]');
80 | xlabel('Frequency [rad/s]');
81 | title('Singular Values');
82 | legendStr = [legendStr strcat('TF:', num2str(i), 'x', num2str(j)), '#']; % # is there beacuse we need to split the string later
83 | hold on
84 | end
85 | end
86 | % Remove last #
87 | legendStr = strsplit(legendStr(1,1:end-1), '#');
88 | % Now plot the legendStr
89 | legend(legendStr);
90 | % Done!
91 | else
92 | error('Only transfer functions and state space models allowed')
93 | end
94 | end
95 |
--------------------------------------------------------------------------------
/matave/+mc/smithpredict.m:
--------------------------------------------------------------------------------
1 | % An Otto Smith predictor
2 | % Input: G(System with delay), K(Controller), n(Pade Approximation number)
3 | % Example 1: [G] = mc.smithpredict(G, K, n)
4 | % Author: Daniel Mårtensson, Februari 2018
5 | % Important! Discrete system may be very sensitive with Otto Smith predictor!
6 |
7 | function [model] = smithpredict(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Check if there is a second input
14 | if(isempty(varargin{2}))
15 | error ('Missing controller transfer function')
16 | end
17 |
18 | % Check if there is a third input
19 | if(isempty(varargin{3}))
20 | error ('Missing pade approximation number')
21 | end
22 |
23 | % Get model type
24 | type = varargin{1}.type;
25 | % Check if there is a TF or SS model
26 | if(strcmp(type, 'TF' ))
27 | % Get system G
28 | Gsystem = varargin{1};
29 |
30 | % Check if the system has delay
31 | if Gsystem.delay <= 0
32 | error('System missing delay.');
33 | end
34 |
35 | % Get pade approximation number
36 | n = varargin{3};
37 |
38 | % Create the system with delay
39 | Gdelaysystem = mc.pade(Gsystem, n);
40 |
41 | % Get the controller transfer function
42 | Gcontroller = varargin{2};
43 |
44 | % Check if the Gcontroller has a delay too!
45 | if Gcontroller.delay > 0
46 | error('The controller has delay.');
47 | end
48 |
49 | % They must have the same sample time
50 | if(Gsystem.sampleTime == Gcontroller.sampleTime)
51 | % Get num and den
52 | num1 = Gdelaysystem.num;
53 | den1 = Gdelaysystem.den;
54 | num2 = Gsystem.num;
55 | den2 = Gsystem.den;
56 |
57 | % Extend - pad - Equal length
58 | num1 = [zeros(1, length(num2) - length(num1)) num1];
59 | den1 = [zeros(1, length(den2) - length(den1)) den1];
60 | num2 = [zeros(1, length(num1) - length(num2)) num2];
61 | den2 = [zeros(1, length(den1) - length(den2)) den2];
62 |
63 | % Substract - Importat to have -conv(num1, den2) + conv(num2, den1)
64 | % because we are doing negative feedback
65 | num = -conv(num1, den2) + conv(num2, den1);
66 | den = conv(den1, den2);
67 |
68 | % Create a transfer function of num and den
69 | Gdelaysubstractsystem = mc.tf(num, den);
70 | % Need to have the same sample time as Gdelaysystem!
71 | Gdelaysubstractsystem.sampleTime = Gdelaysystem.sampleTime;
72 | % Create the predicive controller now
73 | predictController = mc.feedback(Gcontroller, Gdelaysubstractsystem);
74 | % Connect predictController with Gdelay
75 | Looptransferfunction = mc.series(Gdelaysystem, predictController);
76 |
77 | % This is only for scalar 1 in the feedback
78 | if Gsystem.sampleTime > 0
79 | M = mc.tf(1,1); % Just a scalar 1 of TF
80 | M = mc.c2d(M, Gsystem.sampleTime);
81 | else
82 | M = mc.tf(1,1); % Just a scalar 1 of TF
83 | end
84 |
85 | % Our smitth predictor system!
86 | model = mc.feedback(Looptransferfunction, M);
87 | else
88 | error('Not the same sample time')
89 | end
90 | else
91 | error('Only transfer functions');
92 | end
93 |
94 | end
95 |
--------------------------------------------------------------------------------
/matave/+mc/ss.m:
--------------------------------------------------------------------------------
1 | % Generates a state space model from matrix A, B, C, D
2 | % Input: delay, A, B, C(optional), D(optional)
3 | % Example 1: sys = mc.ss(delay, A, B) % C set to diagnoal matrix
4 | % Example 2: sys = mc.ss(delay, A, B, C) % D set to zero matrix
5 | % Example 3: sys = mc.ss(delay, A, B, C, D)
6 | % Author: Daniel Mårtensson, 2017 September
7 |
8 | function [sys] = ss(varargin)
9 |
10 | if(length(varargin) < 1)
11 | error('Missing delaytime, A-matrix and B-matrix')
12 | end
13 |
14 | if(length(varargin) < 2)
15 | error('Missing A-matrix and B-matrix')
16 | else
17 | sys.A = varargin{2};
18 | % Check if sys.A is square matrix
19 | if(size(sys.A,1) ~= size(sys.A,2))
20 | error('A is not a square');
21 | end
22 | end
23 |
24 | if(length(varargin) < 3)
25 | error('Missing B-matrix')
26 | else
27 | sys.B = varargin{3};
28 | % Check if sys.A and sys.B have the same lenght of rows
29 | if(size(sys.A, 1) ~= size(sys.B, 1))
30 | error('A and B have not the same row length');
31 | end
32 | end
33 |
34 | if(length(varargin) < 4)
35 | sprintf('C matrix assumed to be a diagonal %ix%i matrix', size(varargin{2}, 1),size(varargin{2}, 2))
36 | sys.C = eye(size(varargin{2}, 1));
37 | else
38 | sys.C = varargin{4};
39 | % Check if sys.A and sys.C have the same lenght of columns
40 | if(size(sys.A, 2) ~= size(sys.C, 2))
41 | error('A and C have not the same column length');
42 | end
43 | end
44 |
45 | if(length(varargin) < 5)
46 | sprintf('D matrix assumed to be a zero %ix%i matrix', size(sys.C, 1), size(sys.B, 2))
47 | sys.D = zeros(size(sys.C, 1), size(sys.B, 2));
48 | else
49 | sys.D = varargin{5};
50 | % Check if sys.C and sys.D have the same lenght of rows
51 | if(size(sys.C, 1) ~= size(sys.D, 1))
52 | error('C and D have not the same row length');
53 | end
54 | % and check if sys.B and sys.D have the same lenght of columns
55 | if(size(sys.B, 2) ~= size(sys.D, 2))
56 | error('D and B have not the same columns length');
57 | end
58 | end
59 |
60 | % Delay time
61 | sys.delay = varargin{1};
62 | sys.type = 'SS';
63 | %Sampel time
64 | sys.sampleTime = 0;
65 |
66 |
67 | end
--------------------------------------------------------------------------------
/matave/+mc/ss2tf.m:
--------------------------------------------------------------------------------
1 | % Transform state space model to transfer function
2 | % Input: sys
3 | % Example 1: G = mc.ss2tf(sys)
4 | % Author: Daniel Mårtensson, 2017 September
5 |
6 | function [G] = ss2tf(varargin)
7 | % Check if there is some input arguments or it's not a state space model
8 | if(or(isempty(varargin{1}), ~strcmp(varargin{1}.type, 'SS' )))
9 | error ('Missing state space model')
10 | end
11 |
12 | % Get the matrecies
13 | A = varargin{1}.A;
14 | B = varargin{1}.B;
15 | C = varargin{1}.C;
16 | D = varargin{1}.D;
17 | % Get the delay
18 | delay = varargin{1}.delay;
19 | % Get sampleTime
20 | sampleTime = varargin{1}.sampleTime;
21 | % Get the dc gain
22 | dc = mc.dcgain(varargin{1});
23 | % Get the poles
24 | p = mc.pole(varargin{1});
25 |
26 | % Create SISO state space models and convert them into a TF
27 | for i = 1:size(B,2)
28 | for j = 1:size(C,1)
29 | partialSys = mc.ss(delay, A, B(:,i), C(j,:), D(j,i));
30 | % Get the z,p,k values
31 | [z, gain] = mc.tzero(partialSys);
32 | % Get the numerators and denomerators
33 | partialG = mc.zpk(z, p, gain);
34 | partialnum = partialG.num;
35 | partialden = partialG.den;
36 | % Get TF with delay
37 | if(delay > 0)
38 | G(j,i) = mc.tf(partialnum, partialden, delay);
39 | else
40 | G(j,i) = mc.tf(partialnum, partialden);
41 | end
42 |
43 | % Get sample time
44 | G(j,i).sampleTime = sampleTime;
45 | % If the model is discrete - do this!
46 | if(sampleTime > 0)
47 | % Replace the delaytime to discrete delay time
48 | G(j,i).tfdash = strrep(G(j,i).tfdash, 'e', 'z');
49 | G(j,i).tfdash = strrep(G(j,i).tfdash, 's', '');
50 | % Remove all s -> s
51 | G(j,i).tfnum = strrep(G(j,i).tfnum, 's', 'z');
52 | G(j,i).tfden = strrep(G(j,i).tfden, 's', 'z');
53 | end
54 | % Done!
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/matave/+mc/step.m:
--------------------------------------------------------------------------------
1 | % Simulate continuous time model of a state space model or transfer function
2 | % Input: G, sys, t(optional)
3 | % Example 1: [y,t,x] = mc.step(G, t)
4 | % Example 2: [y,t,x] = mc.step(G)
5 | % Example 3: [y,t,x] = mc.step(sys, t)
6 | % Author: Daniel Mårtensson, 2017 September
7 | % Update 2022-10-08: Simulate ARMA model
8 |
9 | function [y,t,X] = step(varargin)
10 | % Check if there is some input arguments or it's not a model
11 | if(isempty(varargin{1}))
12 | error ('Missing input')
13 | end
14 |
15 | % Check if there is a model
16 | if(strcmp(varargin{1}.type,'SS'))
17 |
18 | % Get time
19 | if(length(varargin) >= 2)
20 | t = varargin{2};
21 | else
22 | disp('Time assumed to be 10 seconds');
23 | t = 10;
24 | end
25 |
26 | % Get sample time to compute the new time vector
27 | sampleTime = varargin{1}.sampleTime;
28 | if(sampleTime > 0)
29 | t = 0:sampleTime:t;
30 | else
31 | t = 0:0.01:t; % Sample time assumed to be 0.01
32 | end
33 |
34 | % Multiple signals...or not!
35 | u = ones(size(varargin{1}.B, 2), length(t)); % Creates 1 1 1 1 1 1 1
36 | x0 = zeros(size(varargin{1}.A, 1), 1); % Assume x0 = [0; 0; 0; ..... ; 0]
37 |
38 | % Call lsim!
39 | [y,t,X] = mc.lsim(varargin{1}, u, t, x0);
40 | elseif(strcmp(varargin{1}.type,'TF'))
41 | % TF to SS
42 | sys = mc.tf2ss(varargin{1}, 'OCF');
43 |
44 | % Get time
45 | if(length(varargin) >= 2)
46 | t = varargin{2};
47 | else
48 | disp('Time assumed to be 10 seconds');
49 | t = 10;
50 | end
51 |
52 | % Call step
53 | [y,t,X] = mc.step(sys,t);
54 | elseif(strcmp(varargin{1}.type,'ARMA'))
55 |
56 | % Get end time
57 | if(length(varargin) >= 2)
58 | t = varargin{2};
59 | else
60 | disp('Time assumed to be 10 seconds');
61 | t = 10;
62 | end
63 |
64 | % Create time
65 | sampleTime = varargin{1}.sampleTime;
66 | if(sampleTime > 0)
67 | t = 0:sampleTime:t;
68 | else
69 | t = 0:0.01:t; % Sample time assumed to be 0.01
70 | end
71 |
72 | % Create input u
73 | u = linspace(1, 1, length(t));
74 |
75 | % Call lsim!
76 | [y,t,X] = mc.lsim(varargin{1}, u, t);
77 | else
78 | error('Not a state space model or a transfer function')
79 | end
80 | end
81 |
--------------------------------------------------------------------------------
/matave/+mc/tf.m:
--------------------------------------------------------------------------------
1 | % Generates a transfer function from numerator vector and denomerator vector
2 | % Input: numerator, denomerator, delay(optional)
3 | % Example 1: G = mc.tf(num, den, delay)
4 | % Example 2: G = mc.tf(num, den)
5 | % Author: Daniel Mårtensson, 2017 September
6 | % Update: Added padé approximation 2020-06-29
7 |
8 | function [G] = tf(varargin)
9 | % Check if there is some input arguments
10 | if(isempty (varargin))
11 | error ('Missing arguments')
12 | end
13 | % OK. We have arguments!
14 |
15 | % Get numerator
16 | if(length(varargin) < 1)
17 | error('Missing numerator')
18 | else
19 | numerator = varargin{1};
20 | end
21 | % Get denomerator
22 | if(length(varargin) < 2)
23 | error('Missing denomerator')
24 | else
25 | denomerator = varargin{2};
26 | end
27 |
28 | % Check if there is some numerators
29 | if(isempty (numerator))
30 | error('Missing numerator');
31 | end
32 | % OK. We have numerators!
33 |
34 | % Check if there is some denomerators
35 | if(isempty (denomerator))
36 | error('Missing denomerator');
37 | end
38 | % OK. We have denomerator!
39 |
40 | % Remove the first 0's in the numerator and denomerator
41 | % Begin with the numerator
42 | for i = 1:length(numerator)
43 | % Find the first value which is larger that 0 or less that 0
44 | if(or(numerator(i) > 0, numerator(i) < 0))
45 | % Found it!
46 | numerator = numerator(1,i:length(numerator));
47 | break;
48 | end
49 | end
50 |
51 | % Then with the denomerator
52 | for i = 1:length(denomerator)
53 | % Find the first value which is larger that 0 or less that 0
54 | if(or(denomerator(i) > 0, denomerator(i) < 0))
55 | % Found it!
56 | denomerator = denomerator(1,i:length(denomerator));
57 | break;
58 | end
59 | end
60 |
61 | % Build the transfer function
62 | numeratorString = stringPoly(numerator); % Get the numerator string
63 | denomeratorString = stringPoly(denomerator); % Get the denomerator string
64 | dash = getDashedLine(numeratorString, denomeratorString); % Get the dashed line
65 |
66 | % Save the vale
67 | G.num = numerator;
68 | G.den = denomerator;
69 | % Delaytime
70 | if(length(varargin) >= 3)
71 | % Get dashed line delay
72 | delay = varargin{3};
73 | if(delay > 0)
74 | dash = strcat(dash, 'e^(', num2str(-delay), 's', ')');
75 | % Remove 1 to '' if delay = 1
76 | if delay == 1
77 | dash = regexprep(dash,'[1]','');
78 | end
79 | G.delay = delay;
80 | else
81 | G.delay = 0;
82 | end
83 | else
84 | G.delay = 0;
85 | end
86 | % Save
87 | G.tfnum = numeratorString;
88 | G.tfdash = dash;
89 | G.tfden = denomeratorString;
90 | G.type = 'TF';
91 | G.sampleTime = 0;
92 |
93 | % Padé approximation
94 | if(G.delay > 0)
95 | G = mc.pade(G, 4);
96 | end
97 | end
98 |
99 | % Get a dashed line with dynamical length depending on denomeratorString or numeratorString
100 | function [dash] = getDashedLine(numeratorString, denomeratorString)
101 | dash = '';
102 | if(length(numeratorString) <= length(denomeratorString))
103 | for i = 1:length(denomeratorString)
104 | dash = strcat(dash,'-');
105 | end
106 | else
107 | for i = 1:length(numeratorString)
108 | dash = strcat(dash,'-');
109 | end
110 | end
111 | end
112 |
113 | function [returnString] = stringPoly(array)
114 | polyString = {}; % Begin with empty cell string
115 |
116 | % Get all to a string cell
117 | for i = 1:length(array)
118 | if(and(array(i) ~= 0, length(array) - i ~= 0))
119 | if(length(array) - i > 1)
120 | if(and(array(i) <= 1.000001, array(i) >= 0.999999))
121 | polyString(1, i) = {strcat('s^', num2str(length(array) - i))};
122 | elseif(and(array(i) >= -1.000001, array(i) <= -0.999999))
123 | polyString(1, i) = {strcat('-s^', num2str(length(array) - i))};
124 | else
125 | polyString(1, i) = {strcat(num2str(array(i)), 's^', num2str(length(array) - i))};
126 | end
127 | else
128 | if(and(array(i) <= 1.000001, array(i) >= 0.999999))
129 | polyString(1, i) = {strcat('s')};
130 | elseif(and(array(i) >= -1.000001, array(i) <= -0.999999))
131 | polyString(1, i) = {strcat('-s')};
132 | else
133 | polyString(1, i) = {strcat(num2str(array(i)), 's')};
134 | end
135 | end
136 | else
137 | polyString(1, i) = {strcat(num2str(array(i)))};
138 | end
139 | end
140 |
141 | % Transform that string cell to a complete string
142 | returnString = '';
143 | for i = 1:length(polyString)
144 | % No only-zeros are allowed
145 | if(and(~strcmp(char(polyString(1,i)), '0'), ~strcmp(char(polyString(1,i)), '-0')))
146 | if(length(strfind(char(polyString(1,i)), '-')) > 0)
147 | returnString = [returnString,' ', char(polyString(1,i))];
148 | else
149 | if(length(returnString) == 0)
150 | returnString = [returnString,' ', char(polyString(1,i))];
151 | else
152 | returnString = [returnString,' + ', char(polyString(1,i))];
153 | end
154 | end
155 | end
156 | end
157 | end
158 |
--------------------------------------------------------------------------------
/matave/+mc/tzero.m:
--------------------------------------------------------------------------------
1 | % Generates the MIMO zeros from a transfer function or state space model
2 | % Input: G, sys
3 | % Example 1: [z, gain] = mc.tzero(G)
4 | % Example 2: [z, gain] = mc.tzero(sys)
5 | % Author: Daniel Mårtensson, 2017 Oktober
6 |
7 | function [z, gain] = tzero(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | % Get necessary info
18 | A = varargin{1}.A;
19 | sizeOrginalA = size(A, 2);
20 | B = varargin{1}.B;
21 | C = varargin{1}.C;
22 | D = varargin{1}.D;
23 | % Increase A at maximum size
24 | column = [size(B,2) size(C,2) size(D,2)];
25 | row = [size(B,1) size(C,1) size(D,1)];
26 | A = [A zeros(size(A,1), max(column) - size(A,2))];
27 | A = [A; zeros(max(row) - size(A,1), size(A,2))];
28 | % Make sure so matrix B, C, D have the same size as A
29 | C = rechange(A,C);
30 | B = rechange(A,B);
31 | D = rechange(A,D);
32 | % Compute the zeros
33 | M = [A B; C D];
34 | I = [eye(size(A,1), size(A,2)) B*0; C*0 D*0];
35 | z = eig(M, I);
36 | z = z(isfinite(z)); % Remove the inf and zero values from z
37 | % check the lengt of z so we can remove some 0 0 0 from z
38 | if(length(z) - sizeOrginalA > 0)
39 | % Ok! We have more zeros that orginal size of A
40 | % Remove all 0 0 0
41 | z = z(z ~= 0);
42 | % Then add new one!
43 | % if sizeOrginalA - length(z) <= 0, then it will be no change
44 | z = [z zeros(1, sizeOrginalA - length(z))]; % add 0 if needed
45 | end
46 | p = mc.pole(varargin{1});
47 | dc = mc.dcgain(varargin{1});
48 | gain = dc*prod(-p)/prod(-z);
49 | elseif(strcmp(type, 'TF' ))
50 | error('Only for state space models!')
51 | else
52 | error('This is not TF or SS');
53 | end
54 |
55 | end
56 | % Make sure so matrix B, C, D have the same size as A
57 | function [matrix] = rechange(A, mat)
58 | if(size(A, 1) - size(mat, 1) >= 0)
59 | matrix = [mat; zeros(size(A, 1) - size(mat, 1), size(mat,2))];
60 | end
61 | if(size(A, 2) - size(matrix, 2) >= 0)
62 | matrix = [matrix zeros(size(matrix,1), size(A, 2) - size(matrix, 2))];
63 | end
64 | end
--------------------------------------------------------------------------------
/matave/+mc/updatematavecontrol.m:
--------------------------------------------------------------------------------
1 | % Update the whole matavecontrol library by downloading from GitHub
2 | % Author: Daniel Mårtensson, Februari 2018
3 | % Update 2023-05-15 for MATLAB Control System Toolbox portability
4 |
5 | function updatematavecontrol()
6 | % Get the current working dictionary
7 | currentFolder = pwd;
8 |
9 | % Just update matavecontrol
10 | A = what('matave'); % Importat that it must stand 'matave'. Nothing else!
11 |
12 | % Get the information about where the files are
13 | path = strcat(A.path, '\', '+mc'); % File path
14 |
15 | % Go to path dictionary
16 | cd(path);
17 |
18 | % Downloading listOfFunctions
19 | if(exist('OCTAVE_VERSION', 'builtin') ~= 0)
20 | urlwrite('https://raw.githubusercontent.com/DanielMartensson/matavecontrol/master/listOfFunctions', 'listOfFunctions');
21 | else
22 | websave('https://raw.githubusercontent.com/DanielMartensson/matavecontrol/master/listOfFunctions', 'listOfFunctions');
23 | end
24 |
25 | % Read the listOfFunctions
26 | fid = fopen('listOfFunctions');
27 | txt = textscan(fid, '%s', 'delimiter', '\n'); % Importat to have the delimiter = '\n'
28 | % Remove this double struct
29 | fileList = txt{1,1};
30 |
31 | % Downloading all the other files
32 | [m, n] = size(fileList);
33 | for i = 1:m
34 | % Downloading
35 | nameOfFile = fileList{i, 1};
36 | URL = strcat('https://raw.githubusercontent.com/DanielMartensson/matavecontrol/master/matave/+mc/', nameOfFile)
37 | [saveplace, Success] = urlwrite(URL, nameOfFile);
38 | saveplace
39 | Success
40 | end
41 |
42 | disp('Matavecontrol is updated!')
43 |
44 | % Get to the current working dictionary
45 | cd(currentFolder);
46 |
47 | end
48 |
--------------------------------------------------------------------------------
/matave/+mc/zero.m:
--------------------------------------------------------------------------------
1 | % Generates zeros from SISO transfer function or SISO state space model
2 | % Input: G, sys
3 | % Example 1: [z, gain] = mc.zero(G)
4 | % Example 2: [z, gain] = mc.zero(sys)
5 | % Author: Daniel Mårtensson, 2017 September
6 |
7 | function [z, gain] = zero(varargin)
8 | % Check if there is any input
9 | if(isempty(varargin))
10 | error ('Missing input')
11 | end
12 |
13 | % Get model type
14 | type = varargin{1}.type;
15 | % Check if there is a TF or SS model
16 | if(strcmp(type, 'SS' ))
17 | A = varargin{1}.A;
18 | sizeOrginalA = size(A, 2);
19 | B = varargin{1}.B;
20 | C = varargin{1}.C;
21 | D = varargin{1}.D;
22 | % Check if it's SISO system
23 | if(or(size(B, 2) > 1, size(C, 1) > 1))
24 | error('This is only for SISO system, try to use tzero insted')
25 | end
26 | z = eig([A B; C D], [eye(size(A,1)) B*0; C*0 D*0]); % Get zeros
27 | z = z(isfinite(z)); % Remove the inf and zero values from z
28 | % check the lengt of z so we can remove some 0 0 0 from z
29 | if(length(z) - sizeOrginalA > 0)
30 | % Ok! We have more zeros that orginal size of A
31 | % Remove all 0 0 0
32 | z = z(z ~= 0);
33 | % Then add new one!
34 | % if sizeOrginalA - length(z) <= 0, then it will be no change
35 | z = [z zeros(1, sizeOrginalA - length(z))]; % add 0 if needed
36 | end
37 | p = mc.pole(varargin{1});
38 | dc = mc.dcgain(varargin{1});
39 | gain = dc*prod(-p)/prod(-z);
40 | elseif(strcmp(type, 'TF' ))
41 | % Get z, p, k
42 | G = varargin{1};
43 | if(or(size(G,1) > 1, size(G,2) > 1))
44 | error('This is only for SISO system, try to use tzero insted')
45 | end
46 | z = roots(G.num);
47 | p = roots(G.den);
48 | dc = mc.dcgain(G);
49 | gain = dc*prod(-p)/prod(-z);
50 | else
51 | error('This is not TF or SS');
52 | end
53 |
54 | end
55 |
--------------------------------------------------------------------------------
/matave/+mc/zpk.m:
--------------------------------------------------------------------------------
1 | % Generate a transfer function from vector of zero, vector of poles and vectior of gain
2 | % Input: z, p , k, delay(optional)
3 | % Example 1: G = mc.zpk(z, p, k)
4 | % Example 2: G = mc.zpk(z, p, k, delay)
5 | % Author: Daniel Mårtensson, 2017 September
6 |
7 |
8 | function [G] = zpk(varargin)
9 | % Check if there is any input
10 | if(isempty(varargin))
11 | error ('Missing input')
12 | end
13 |
14 | % Get zeros
15 | if(length(varargin) < 1)
16 | error('Missing zeros')
17 | else
18 | z = varargin{1};
19 | end
20 | % Get poles
21 | if(length(varargin) < 2)
22 | error('Missing zeros')
23 | else
24 | p = varargin{2};
25 | end
26 |
27 | % Get gain
28 | if(length(varargin) < 3)
29 | error('Missing gain')
30 | else
31 | k = varargin{3};
32 | end
33 |
34 | % Check if values are cells
35 | if(~iscell(z))
36 | z = {z};
37 | end
38 |
39 | if(~iscell(p))
40 | p = {p};
41 | end
42 |
43 | % The gain k is never cell
44 |
45 | % Get numerator and denomerator
46 | num = cellfun (@(zer, gain) real (gain * poly (zer)), z, num2cell(k), 'uniformoutput', false);
47 | den = cellfun (@(pol) real (poly (pol)), p, 'uniformoutput', false);
48 |
49 | % Get delay
50 | if(length(varargin) >= 4)
51 | delay = varargin{4};
52 | G = mc.tf(round(cell2mat(num)*1/1e-6)*1e-6, round(cell2mat(den)*1/1e-6)*1e-6, delay); % Tar bort alla 000000 på slutet
53 | else
54 | G = mc.tf(cell2mat(num), cell2mat(den));
55 | end
56 |
57 |
58 | end
59 |
--------------------------------------------------------------------------------
/matave/README.md:
--------------------------------------------------------------------------------
1 | This is the folder where all the matavecontrol files are.
2 |
3 | Books which has been used are:
4 | * Grundläggande reglerteknik, 2002, edition 4, ISBN: 91-44-02416-9 - Bengt Lennartsson, Chalmers, Sverige
5 | * System Modeling and Identification, 2017, edition 2, ISBN: 0-13-482308-7, Can be purchased at http://kfsab.se/, - Rolf Johansson, Lund, Sverige
6 |
--------------------------------------------------------------------------------
/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/yjq8T9-gQYy0f2NhORonQUngnPgd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/yjq8T9-gQYy0f2NhORonQUngnPgp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/2kj09UetkV_lru3gvSPXnY6-nM4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/2kj09UetkV_lru3gvSPXnY6-nM4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/KKyDJtbdIBOlaeHmIZd5VX6vqx8d.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/KKyDJtbdIBOlaeHmIZd5VX6vqx8p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/QWNDYJD5mGW1bWYvPx9DtKnxzw4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/QWNDYJD5mGW1bWYvPx9DtKnxzw4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/R1RggVhA72agIvELiuhWPRS8F0Id.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/R1RggVhA72agIvELiuhWPRS8F0Ip.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/aEHSZBIY-yve10yGis12Zr5DLZod.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/aEHSZBIY-yve10yGis12Zr5DLZop.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/j4xwF_j8iFTVayUMfxLgMnTbencd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/j4xwF_j8iFTVayUMfxLgMnTbencp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/r8LR4nLmg9ai3oHrW1r_-KocQzkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/NjSPEMsIuLUyIpr2u1Js5bVPsOs/r8LR4nLmg9ai3oHrW1r_-KocQzkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/0svTqDZyxKsHr8tr9l_5tqIMcqwd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/0svTqDZyxKsHr8tr9l_5tqIMcqwp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/0tLh2TRaHNLS2qzQDqexHEHLXVMd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/0tLh2TRaHNLS2qzQDqexHEHLXVMp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/96SFBJ-bIQLnHvDLQUTQfLO8XDod.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/96SFBJ-bIQLnHvDLQUTQfLO8XDop.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/_MRJWxV8DfREsKhDtvTq3Jjm_RQd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/_MRJWxV8DfREsKhDtvTq3Jjm_RQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/icQfkkI3t1PC4Ek0YY0fHihS5Yod.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/icQfkkI3t1PC4Ek0YY0fHihS5Yop.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/oSQ_nBKlxRWiL15nEg7_Rn5-agId.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/oSQ_nBKlxRWiL15nEg7_Rn5-agIp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/qzR9VwkbUp-oa5a1uN0CPiHvfNId.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/qzR9VwkbUp-oa5a1uN0CPiHvfNIp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/ySuCV85gsbuVjl71P1huo8omBFQd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/OfxnnyUcu5GSELEDRUyOXcMZW0c/ySuCV85gsbuVjl71P1huo8omBFQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/-CoAOABvy9cuGUC38ZyaKbdeLOwd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/-CoAOABvy9cuGUC38ZyaKbdeLOwp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/-SbeBzw66TzYB4FU3szMFT_cuxAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/-SbeBzw66TzYB4FU3szMFT_cuxAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/-uWRYmmAnEkaEOZhJsoOtba7DlEd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/-uWRYmmAnEkaEOZhJsoOtba7DlEp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/11XmEjI_K5BBZNuXErv9HOmoVb4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/11XmEjI_K5BBZNuXErv9HOmoVb4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/1KTluOp16-oR5v3JUK0UHA8e6WUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/1KTluOp16-oR5v3JUK0UHA8e6WUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/1w-nJuyPlyAftYmX_f8A0UO2RoYd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/1w-nJuyPlyAftYmX_f8A0UO2RoYp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/2-za1lJr8fVK3PJ1MHlXunw5Oskd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/2-za1lJr8fVK3PJ1MHlXunw5Oskp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/2rEj_f0GPdtD554fpQNmyoBcu3Id.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/2rEj_f0GPdtD554fpQNmyoBcu3Ip.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/4DRfx5bQIrL3zJNHm7GLriyLfqUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/4DRfx5bQIrL3zJNHm7GLriyLfqUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/4PanJm-mPEJlkWhsC591LHn6aiYd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/4PanJm-mPEJlkWhsC591LHn6aiYp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/54Nzb97VcU2zBkaWOgRp2fge9pcd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/54Nzb97VcU2zBkaWOgRp2fge9pcp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/5623OBuXkEpLP79xKtBFRnkKHTwd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/5623OBuXkEpLP79xKtBFRnkKHTwp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/6Bh2D-xMzXRKqe6s6nncGX_LLq4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/6Bh2D-xMzXRKqe6s6nncGX_LLq4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/6oFg1XfxuDHhfjP4t4s5xOHzcrsd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/6oFg1XfxuDHhfjP4t4s5xOHzcrsp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/7IW8qVfB6kZF63giXtxVXReB9SUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/7IW8qVfB6kZF63giXtxVXReB9SUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/7oOVoMxiTqU8K6QQ4sUkZO9RP2Ud.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/7oOVoMxiTqU8K6QQ4sUkZO9RP2Up.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/7zY7EuVRFOGx43YZ-Y9TIffdlRMd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/7zY7EuVRFOGx43YZ-Y9TIffdlRMp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/B67JrGieaCPkkHupmiFqKtCE6pUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/B67JrGieaCPkkHupmiFqKtCE6pUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/BWbN1hILgy2Xnv7NeEd_GOhnYVkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/BWbN1hILgy2Xnv7NeEd_GOhnYVkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/BdYYMugAhyen8aTKF0WVSC5CJMYd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/BdYYMugAhyen8aTKF0WVSC5CJMYp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/BrnqdsK_ogt7Lib0tBOndoDjD_Yd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/BrnqdsK_ogt7Lib0tBOndoDjD_Yp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Cn9iMC8MNPNB5JDsln6zVltnWPYd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Cn9iMC8MNPNB5JDsln6zVltnWPYp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Cr5mcv7j6DQanwB6ElyAlI8bUJsd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Cr5mcv7j6DQanwB6ElyAlI8bUJsp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/FFPwQdZhJJjzWviOr_Y8ow76HHEd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/FFPwQdZhJJjzWviOr_Y8ow76HHEp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/IdnWZbYNeczTHna-1KgMBVw3dTkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/IdnWZbYNeczTHna-1KgMBVw3dTkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/ItT4tYcXdZiwyGq2gNplYIZi-5kd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/ItT4tYcXdZiwyGq2gNplYIZi-5kp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/JyUYT_XYg4otoIQ8t01K4919hBUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/JyUYT_XYg4otoIQ8t01K4919hBUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/K73qDanDhcbDYKqjaFwytbLwGKgd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/K73qDanDhcbDYKqjaFwytbLwGKgp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Ks44_1yuOlA02cwQtl9Hj_VSmGQd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Ks44_1yuOlA02cwQtl9Hj_VSmGQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/KyuCQK9P5YV7bEjabcSd4q48gY8d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/KyuCQK9P5YV7bEjabcSd4q48gY8p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/KzeaGeO1UH_COx-dXm2_DAEReEcd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/KzeaGeO1UH_COx-dXm2_DAEReEcp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/N2RPtkh5ZI7i2sSZ9SOs-pP9cw0d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/N2RPtkh5ZI7i2sSZ9SOs-pP9cw0p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Q0mF6K2JACo0hwfoTHRiZIIs0UUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Q0mF6K2JACo0hwfoTHRiZIIs0UUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/SeEYVLuQTDVvsjYSRnAtdr_2NhQd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/SeEYVLuQTDVvsjYSRnAtdr_2NhQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/V0cZFTBU3_EpgkWw_Io5Y6jlFZgd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/V0cZFTBU3_EpgkWw_Io5Y6jlFZgp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/W-Du79i4Ko3EezEp2M74qz5SYusd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/W-Du79i4Ko3EezEp2M74qz5SYusp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Yb-7rgk-EbjB7wP6z2IdIPPvUlAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Yb-7rgk-EbjB7wP6z2IdIPPvUlAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/YopdEcictGnkIQ_5prpSJs34qMkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/YopdEcictGnkIQ_5prpSJs34qMkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Yvbp9FUZKCSQJncgLoI5reinE8gd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/Yvbp9FUZKCSQJncgLoI5reinE8gp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/ZSr63X3mMNEhpHVxHT_0ldMLNqYd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/ZSr63X3mMNEhpHVxHT_0ldMLNqYp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/_K78ptPkoib18O_M5mDAripZWUkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/_K78ptPkoib18O_M5mDAripZWUkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/_dBbd0q9a5geL--6i8vH8WvsZbEd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/_dBbd0q9a5geL--6i8vH8WvsZbEp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/_yABYToFV-Vjbphro5wtF2zF0NAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/_yABYToFV-Vjbphro5wtF2zF0NAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/bhnlN9XOEJ1B6NEw30i-8lD3XSwd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/bhnlN9XOEJ1B6NEw30i-8lD3XSwp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/cVDmIEZqQ6RuSQlM-GFDxsJK8Fcd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/cVDmIEZqQ6RuSQlM-GFDxsJK8Fcp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/cj0dX_uC53Jt6gPqFnKbLR1-iJMd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/cj0dX_uC53Jt6gPqFnKbLR1-iJMp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/crViRB3JW-vZT9LEYWdXpvxIyIEd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/crViRB3JW-vZT9LEYWdXpvxIyIEp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/jMspD52-8pQRDJM84VawTeYB670d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/jMspD52-8pQRDJM84VawTeYB670p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/jXytGzI4O2iQkm5Iid_M99e7kl8d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/jXytGzI4O2iQkm5Iid_M99e7kl8p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/jegMYt-Jgzo1xmWNIPX-xdbhG18d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/jegMYt-Jgzo1xmWNIPX-xdbhG18p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/kFa7fP1qhyzvenZPkkRfV8neELgd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/kFa7fP1qhyzvenZPkkRfV8neELgp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/k_LDNoMhWM_ftCTzKT4LUnl8z1Id.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/k_LDNoMhWM_ftCTzKT4LUnl8z1Ip.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/kdyNwcW_EV1D4OcQHOT0h5ui6oUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/kdyNwcW_EV1D4OcQHOT0h5ui6oUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/lTNcbFF3WgZbJrqXWWqgs1AlWFUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/lTNcbFF3WgZbJrqXWWqgs1AlWFUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/mLjyaWT3h9G6pnHN4E1ZmZnWDDwd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/mLjyaWT3h9G6pnHN4E1ZmZnWDDwp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/nxHIvmYl91RxdSAAehuvNMiMvM0d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/nxHIvmYl91RxdSAAehuvNMiMvM0p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/q0SFswbWjtAqBsGhTVKi6kBxqmAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/q0SFswbWjtAqBsGhTVKi6kBxqmAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/qOqHwCrRHme4LTDtVseEt6L5eN8d.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/qOqHwCrRHme4LTDtVseEt6L5eN8p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/qY_esZacgV_-CBdwSlj-x3tae5cd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/qY_esZacgV_-CBdwSlj-x3tae5cp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/qn_WO7trpHLQ8MBDNf14xTjUXv8d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/qn_WO7trpHLQ8MBDNf14xTjUXv8p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/sZsojGNj1Xsew2r2cjrxgTtJiz4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/sZsojGNj1Xsew2r2cjrxgTtJiz4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/t6G0dleSjZRdaE0mqOxDKu4M8xsd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/t6G0dleSjZRdaE0mqOxDKu4M8xsp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/t6Xz-myNiIJid1uOQBu3M-Z_hf4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/t6Xz-myNiIJid1uOQBu3M-Z_hf4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/tmzg2FyGbnUr4U5BapcMKI6CS7Ed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/tmzg2FyGbnUr4U5BapcMKI6CS7Ep.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/utwGE9hQzpXV3PZxiEjFjWMyMeAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/utwGE9hQzpXV3PZxiEjFjWMyMeAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/x-l6L7vAJyYBtn-SDFTmhDDN-MAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/x-l6L7vAJyYBtn-SDFTmhDDN-MAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/x4GzzdUEvl5vK1S2qWPJ8s1NfPYd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/x4GzzdUEvl5vK1S2qWPJ8s1NfPYp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/xNX7uGtM_e36nIF5tMGLJYQgs_4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/xNX7uGtM_e36nIF5tMGLJYQgs_4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/xi57K6yo7qEW6cfchYEdjcWGnkcd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/xi57K6yo7qEW6cfchYEdjcWGnkcp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/xyaFs-562jwpSMpoHmrjkNpXI3kd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/xyaFs-562jwpSMpoHmrjkNpXI3kp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/yMp73CpOLXJfFwcL5zbkVD1Dgpod.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/yMp73CpOLXJfFwcL5zbkVD1Dgpop.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/yvnfTAHHm4btVWqLUrENzD5XMNsd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/yvnfTAHHm4btVWqLUrENzD5XMNsp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/zDJYuT22rAyRg0WvG1AdowAaXN4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/zDJYuT22rAyRg0WvG1AdowAaXN4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/zgQIfZQSIp7WL4NSqDq4njhDAOcd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/zgQIfZQSIp7WL4NSqDq4njhDAOcp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/zr_37WR-HxanuIcLCVDyLghcKzAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/project/Y0MXjQcTETsDYSfZOITJxehWTOQ/zr_37WR-HxanuIcLCVDyLghcKzAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/fjRQtWiSIy7hIlj-Kmk87M7s21k/NjSPEMsIuLUyIpr2u1Js5bVPsOsd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/fjRQtWiSIy7hIlj-Kmk87M7s21k/NjSPEMsIuLUyIpr2u1Js5bVPsOsp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/lPZI5oa5DxrsR-PK7aQQLq3WqrE/Miy75s7SKM4dtkSrAQrwPD2Pnvsd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/lPZI5oa5DxrsR-PK7aQQLq3WqrE/Miy75s7SKM4dtkSrAQrwPD2Pnvsp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/lPZI5oa5DxrsR-PK7aQQLq3WqrE/Y0MXjQcTETsDYSfZOITJxehWTOQd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/lPZI5oa5DxrsR-PK7aQQLq3WqrE/Y0MXjQcTETsDYSfZOITJxehWTOQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/lPZI5oa5DxrsR-PK7aQQLq3WqrE/tzlQc0NLrARVg_2cChAq5muGE2Ud.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/lPZI5oa5DxrsR-PK7aQQLq3WqrE/tzlQc0NLrARVg_2cChAq5muGE2Up.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/OfxnnyUcu5GSELEDRUyOXcMZW0cd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/OfxnnyUcu5GSELEDRUyOXcMZW0cp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/TMK4UzWHdRLhy_w-CHt9y11Q8XAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/lPZI5oa5DxrsR-PK7aQQLq3WqrEd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/lPZI5oa5DxrsR-PK7aQQLq3WqrEp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qD-kr16wmwlzR-nIg1IG_vvRrWkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/6x1BhZX_fLnKpcwqra0qFwv1jIgp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/EEtUlUb-dLAdf0KpMVivaUlztwAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/GiiBklLgTxteCEmomM8RCvWT0nQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/KAXfQgCar2Yb8zOxgvf9hdmLP1Ep.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/NmGqIpAwUJcXFyLjFAGnU9uyN5Yp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/fjRQtWiSIy7hIlj-Kmk87M7s21kp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/root/qaw0eS1zuuY1ar9TdPn1GMfrjbQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/rootp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/project/uuid-f651a9a5-b7b9-4361-b11c-7c91771b35e7.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------