diff --git a/acme.html b/acme.html new file mode 100644 index 0000000000000000000000000000000000000000..8c60e6c82c36f1fe8e3a3b1e60c2048e0993f164 --- /dev/null +++ b/acme.html @@ -0,0 +1,1469 @@ +<!doctype html> +<html> +<head> + <meta charset="utf-8"></meta> + <meta content="IE=edge" http-equiv="X-UA-Compatible"></meta> + <title></title> + <style>/*<![CDATA[*/ +form.Hole { + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-right: 2px; + padding-left: 4 px; +} + +div.Hole { + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +span.Hole { + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +span.HoleId { + font-size: small; +} + +span.HoleDesc { + margin-left: 5px; + padding-left: 5px; + border-style: dotted; + border-width: 1px; +} + +hole::before { + content: " " attr(id) " "; + font-family: "Courier New",Courier,monospace; + font-size: 10pt; + font-weight: bold; +} + +hole { + display:block; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +p hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +span hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +h1 hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +h2 hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +h3 hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +h4 hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +h5 hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +h6 hole { + display:inline; + font-size: x-small; + color: #3333ff; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + padding-top: 2px; + padding-bottom: 2px; + padding-right: 2px; + padding-left: 8px; + border-radius: 5px; + background: #FFF482; + box-shadow: 0 0 0 2px #FFF482; +} + +dptemplate::before{ + content: "" attr(name) ""; + font-family: "Courier New",Courier,monospace; + font-weight: bold; + color: #3333ff; +} + +dptemplate { + margin-bottom: 4pt; + margin-top: 4pt; + border-style:dotted; + border-width:thin; + display:block; + background: #E6E6E6; +} + +@import url(hole.css); +@import url(docpart_templates.css); + +ol.toc > li { + list-style:none; +} + +ol.loc > li { + list-style:none; +} + +table { + border-collapse:collapse; + border-color:#000000; +} + +ttable.ReportGrid { + color: rgb(0,0,0); + border: 1px solid black; + border-collapse:collapse; +} + +thead.ReportGrid { + border: 1px solid black; + font-weight:bold; +} + + +th.ReportGrid { + border: 1px solid black; + font-weight:bold; + padding:5px; +} + +tr.ReportGrid { + margin-left: 2%; +} + +td.ReportGrid { + border: 1px solid black; + padding:5px; + text-align:center; +} + +ol.toc { + /*counter-reset: numsection;*/ + list-style-type: none; + padding-left: 32px; +} + +ol.toc > li { + /*counter-increment: numsection;*/ + text-indent: -12px; + padding-left: 12px; +} + +ol.toc > li > * { + text-indent: 0; +} + +ol.loc { + /*counter-reset: numsection;*/ + list-style-type: none; + padding-left: 32px; +} + +ol.loc > li { + /*counter-increment: numsection;*/ + text-indent: -12px; + padding-left: 12px; +} + +ol.loc > li > * { + text-indent: 0; +} + +a.toc_sec_title::before { + /*content: counters(numsection, ".") ". ";*/ + font-weight: bold; +} + +a.loc_sec_title::before { + /*content: counters(numsection, ".") ". ";*/ + font-weight: bold; +} + +a.loc_sec_title{ + color:blue; +} + +a.toc_no_title { + font-style: italic; +} + +table.rgMATLABTable { + text-align: center; + border: none; +} +table.rgMATLABTable th p { + padding: 0 0 0.03in 0; + margin: 0 0 0 0; +} +table.rgMATLABTable th { + font-weight: bold; + padding: 0 0.04in 0.05in 0.04in; +} +table.rgMATLABTable td p { + padding: 0 0 0 0; + margin: 0 0 0 0; +} +table.rgMATLABTable td { + padding: 0 0.04in 0 0.04in; +} + +/* Styles for TOC sidebar */ + +body { + margin: 0; +} + +.wrapper-sidebar { + height: 100%; + width: 200px; + background-color: #fff; + position: fixed!important; + display: none; + z-index: 5; + overflow: auto; + word-break: break-all; +} + +.sidebar-animate-left { + position: relative; + animation: animateleft 0.4s; +} + +@keyframes animateleft { + from { + left: -300px; + opacity: 0; + } + to { + left: 0; + opacity: 1; + } +} + +.overlay { + position: fixed; + display: none; + width: 100%; + height: 100%; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.2); + z-index: 2; +} + +.animate-opacity { + animation: opac 0.8s; +} + +@keyframes opac { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.sidebar-button { + border: none; + display: inline-block; + padding: 8px 16px; + font-size: 24px!important; + vertical-align: middle; + overflow: hidden; + text-decoration: none; + color: inherit; + background-color: inherit; + text-align: center; + cursor: pointer; + white-space: nowrap; + position: fixed; +} + +.sidebar-button:hover { + color: #000!important; + background-color: #ccc!important; +} + +.container { + padding: 0.01em 16px 16px 60px; +} + +.current-sidebar-item { + background-color: rgb(247, 175, 175); +} + +/*]]>*/</style> + <script> + //<![CDATA[ +var cssrule; +(function (cssrule) { + + function createStyleSheet() { + var style = document.createElement("style"); + + // Add a media (and/or media query) here if you'd like! + // style.setAttribute("media", "screen") + // style.setAttribute("media", "@media only screen and (max-width : 1024px)") + + // WebKit hack :( + style.appendChild(document.createTextNode("")); + + // Add the <style> element to the page + document.head.appendChild(style); + + return style.sheet; + } + + function addCSSRule(selector, rules, index) { + if (document.styleSheets) { + var sheet = createStyleSheet(); + if (sheet) { + if (sheet.insertRule) { + return sheet.insertRule(selector + " {" + rules + "}", index); + } + else { + return sheet.addRule(selector, rules, index); + } + } + } + return null; + } + cssrule.addCSSRule = addCSSRule; + +})(cssrule || (cssrule = {})); + //]]> + </script> + + <script> + //<![CDATA[ +var sidebar; +(function (sidebar) { + + function createSidebar() { + // Get all the body content now, this will exclude TOC/LOC. Wrap them in container div + var contentWrapper = document.createElement('div'); + contentWrapper.className = 'container'; + + // Move the body's children into this wrapper and then append wrapper to the body + while (document.body.firstChild) { + contentWrapper.appendChild(document.body.firstChild); + } + document.body.appendChild(contentWrapper); + + // Add button to open side bar + var sidebar_button = document.createElement('button'); + sidebar_button.innerHTML = '☰'; + sidebar_button.className = 'sidebar-button'; + + // Add mouse events to open and close sidebar + sidebar_button.addEventListener("mouseover", function () { + openSidebar(); + + highlightSelectedEntry(); + + var sideBar = document.getElementById("Sidebar"); + sideBar.addEventListener("mouseleave", closeSidebar); + }); + + // Add touch events to open and close Sidebar + sidebar_button.addEventListener("touchstart", function () { + openSidebar(); + + highlightSelectedEntry(); + + var overlay = document.getElementById("SidebarOverlay"); + overlay.addEventListener("touchstart", closeSidebar); + }); + + contentWrapper.parentNode.insertBefore(sidebar_button, contentWrapper); + + // Add div for overlay + var overlayDiv = document.createElement('div'); + overlayDiv.id = 'SidebarOverlay'; + overlayDiv.className = 'overlay animate-opacity'; + sidebar_button.parentNode.insertBefore(overlayDiv, sidebar_button); + + var sidebarWrapper = document.createElement('div'); + sidebarWrapper.id = 'Sidebar'; + sidebarWrapper.className = 'wrapper-sidebar sidebar-animate-left'; + overlayDiv.parentNode.insertBefore(sidebarWrapper, overlayDiv); + + // Function to open sidebar + function openSidebar() { + document.getElementById("Sidebar").style.display = "block"; + document.getElementById("SidebarOverlay").style.display = "block"; + } + + // Function to close sidebar + function closeSidebar() { + document.getElementById("Sidebar").style.display = "none"; + document.getElementById("SidebarOverlay").style.display = "none"; + } + + // Function to highlight the selected entry in the Sidebar + function highlightSelectedEntry() { + var sidebarItemList = document.getElementsByClassName('sidebar_sec_title'); + for (var i = 0; i < sidebarItemList.length; i++) { + sidebarItemList[i].addEventListener('click', function (event) { + for (var j = 0; j < sidebarItemList.length; j++) { + sidebarItemList[j].classList.remove('current-sidebar-item'); + } + event.target.classList.add('current-sidebar-item'); + }); + } + } + } + sidebar.createSidebar = createSidebar; + + function apppendData(data) { + var sidebarWrapper = document.getElementById("Sidebar"); + sidebarWrapper.appendChild(data); + } + sidebar.apppendData = apppendData; + +})(sidebar || (sidebar = {})); + + //]]> + </script> + + <script> + //<![CDATA[ +var loc; +(function (loc) { + + function getLOCElements(root, streamName) { + var str_prefix = streamName + "_loc_caption_id"; + count = 1; + + var ol = document.createElement("ol"); + ol.className = "loc"; + + var h4 = document.createElement("h4"); + h4.textContent = "List of " + streamName[0].toUpperCase() + streamName.slice(1) + "s"; + ol.appendChild(h4); + + var captions = document.getElementsByClassName("an_" + streamName); + for (var i = 0; i < captions.length; i++) { + var node = captions[i]; + var id = str_prefix + count; + count = count + 1; + node.parentElement.id = id; + var li = document.createElement("li"); + var title = document.createElement("a"); + title.className = "loc_sec_title sidebar_sec_title"; + + title.textContent = node.parentElement.textContent; + title.href = "#" + id; + + title.addEventListener("click", function (event) { + //event.preventDefault(); + node.scrollIntoView(); + }, false); + + li.appendChild(title); + ol.appendChild(li); + } + return ol; + } + loc.getLOCElements = getLOCElements; + +})(loc || (loc = {})); + + + //]]> + </script> + + <script> + //<![CDATA[ +var toc; +(function (toc) { + var showDetails = false; + + function createOutline(outline, levels, level) { + if (level <= levels) { + var ol = document.createElement("ol"); + ol.className = "toc"; + if(level === 1){ + var h4 = document.createElement("h4"); + h4.textContent = "Table of Contents"; + ol.appendChild(h4); + } + for (var i = 0; i < outline.length; i++) { + ol.appendChild(createSection(outline[i], levels, level)); + } + return ol; + } + return null; + } + toc.createOutline = createOutline; + + function createSection(section, levels, level) { + var li = document.createElement("li"); + + var title = document.createElement("a"); + title.className = "toc_sec_title sidebar_sec_title"; + li.appendChild(title); + + if (section.heading === null) { + switch (section.associatedNodes[0].nodeName.toLowerCase()) { + case "blockquote": + title.textContent = "Quoted content"; + break; + case "body": + title.textContent = "Document"; + break; + case "details": + title.textContent = "Widget"; + break; + case "fieldset": + title.textContent = "Form controls"; + break; + case "figure": + title.textContent = "Figure"; + break; + case "td": + title.textContent = "Data cell"; + break; + case "article": + title.textContent = "Article"; + break; + case "aside": + title.textContent = "Aside"; + break; + case "nav": + title.textContent = "Navigation"; + break; + case "section": + title.textContent = "Section"; + break; + } + title.className += "toc_no_title"; + } else { + title.textContent = section.heading.text; + } + + var node = section.associatedNodes[0]; + if ((node.sectionType !== 1 && node.sectionType !== 2) || + (node.nodeName.toLowerCase() === "body")) { + node = section.heading; + } + title.href = "#" + node.id; + + title.addEventListener("click", function (event) { + event.preventDefault(); + node.scrollIntoView(); + }, false); + + var nextlevel = createOutline(section.childSections, levels, level+1); + if (nextlevel) { + li.appendChild(nextlevel); + } + return li; + } + + function Section() { + this.parentSection = null; + this.childSections = []; + this.firstChild = null; + this.lastChild = null; + this.appendChild = function (section) { + section.parentSection = this; + this.childSections.push(section); + if (this.firstChild === null) { + this.firstChild = section; + } + this.lastChild = section; + }; + + this.heading = null; + + this.associatedNodes = []; + } + toc.Section = Section; + + function HTMLOutline(root) { + var currentOutlinee = null; + + var currentSection = null; + + var stack = { "lastIndex": -1, "isEmpty": null, "push": null, "pop": null, "top": null }; + stack.isEmpty = function () { + return stack.lastIndex === -1; + }; + stack.push = function (e) { + stack[++stack.lastIndex] = e; + stack.top = e; + }; + stack.pop = function () { + var e = stack.top; + delete stack[stack.lastIndex--]; + stack.top = stack[stack.lastIndex]; + return e; + }; + + function enter(node) { + if (isElement(node)) { + if (!stack.isEmpty() && (isHeadingElement(stack.top) || isHidden(stack.top))) { + } else if (isHidden(node)) { + stack.push(node); + } else if (isSectioningContentElement(node) || isSectioningRootElement(node)) { + if (currentOutlinee !== null) { + stack.push(currentOutlinee); + } + currentOutlinee = node; + currentSection = new Section(); + associateNodeWithSection(currentOutlinee, currentSection); + currentOutlinee.appendSection(currentSection); + } else if (currentOutlinee === null) { + } else if (isHeadingElement(node)) { + if (currentSection.heading === null) + currentSection.heading = node; +else if (currentOutlinee.lastSection.heading === null || node.rank >= currentOutlinee.lastSection.heading.rank) { + currentSection = new Section(); + currentSection.heading = node; + currentOutlinee.appendSection(currentSection); + } else { + var candidateSection = currentSection; + do { + if (node.rank < candidateSection.heading.rank) { + currentSection = new Section(); + currentSection.heading = node; + candidateSection.appendChild(currentSection); + break; + } + var newCandidate = candidateSection.parentSection; + candidateSection = newCandidate; + } while(true); + } + stack.push(node); + } + } + } + + function exit(node) { + if (isElement(node)) { + if (!stack.isEmpty() && node === stack.top) { + stack.pop(); + } else if (!stack.isEmpty() && (isHeadingElement(stack.top) || isHidden(stack.top))) { + } else if (!stack.isEmpty() && isSectioningContentElement(node)) { + currentOutlinee = stack.pop(); + currentSection = currentOutlinee.lastSection; + for (var i = 0; i < node.sectionList.length; i++) { + currentSection.appendChild(node.sectionList[i]); + } + } else if (!stack.isEmpty() && isSectioningRootElement(node)) { + currentOutlinee = stack.pop(); + currentSection = currentOutlinee.lastSection; + while (currentSection.childSections.length > 0) { + currentSection = currentSection.lastChild; + } + } else if (isSectioningContentElement(node) || isSectioningRootElement(node)) { + currentOutlinee = null; + currentSection = null; + } + } + if (node.associatedSection === null && currentSection !== null) { + associateNodeWithSection(node, currentSection); + } + } + + function associateNodeWithSection(node, section) { + section.associatedNodes.push(node); + node.associatedSection = section; + } + + function isElement(node) { + return node.nodeType === 1; + } + + function isHidden(node) { + return node.hidden; + } + + function isSectioningContentElement(node) { + return node.sectionType === 1; + } + + function isSectioningRootElement(node) { + return node.sectionType === 2; + } + + function isHeadingElement(node) { + return node.rank !== undefined; + } + + function extend(node) { + if (node.nodeType === 1) { + switch (node.nodeName.toLowerCase()) { + case "blockquote": + case "body": + case "details": + case "dialog": + case "fieldset": + case "figure": + case "td": + extendSectioningRootElement(node); + break; + case "article": + case "aside": + case "nav": + case "section": + extendSectioningContentElement(node); + break; + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": + extendHeadingElement(node); + break; + case "hgroup": + extendHeadingGroupElement(node); + break; + default: + extendNode(node); + } + } else + extendNode(node); + } + + function extendNode(node) { + node.associatedSection = null; + } + + function extendSectioningElement(node) { + extendNode(node); + node.sectionList = []; + node.firstSection = null; + node.lastSection = null; + + node.appendSection = function (section) { + this.sectionList.push(section); + if (this.firstSection === null) { + this.firstSection = section; + } + this.lastSection = section; + }; + } + + function extendSectioningContentElement(node) { + extendSectioningElement(node); + node.sectionType = 1; + } + + function extendSectioningRootElement(node) { + extendSectioningElement(node); + node.sectionType = 2; + } + + function extendHeadingContentElement(node) { + extendNode(node); + Object.defineProperty(node, "depth", { + "get": function () { + var section = node.associatedSection; + var depth = 1; + if (section !== null) { + while (section = section.parentSection) + ++depth; + } + return depth; + }, + "configurable": true, + "enumerable": true + }); + } + + function extendHeadingElement(node) { + extendHeadingContentElement(node); + node.rank = -parseInt(node.nodeName.charAt(1)); + node.text = node.textContent; + } + + function extendHeadingGroupElement(node) { + extendHeadingContentElement(node); + + for (var i = 1; i <= 6; i++) { + var h = node.getElementsByTagName("h" + i); + if (h.length > 0) { + node.rank = -i; + node.text = h[0].textContent; + break; + } + } + + if (node.rank === undefined) { + node.rank = -1; + node.text = ""; + } + } + + var node = root; + start: + while (node) { + extend(node); + enter(node); + if (node.firstChild) { + node = node.firstChild; + continue start; + } + while (node) { + exit(node); + if (node === root) { + break start; + } + if (node.nextSibling) { + node = node.nextSibling; + continue start; + } + node = node.parentNode; + } + } + } + toc.HTMLOutline = HTMLOutline; + +})(toc || (toc = {})); + //]]> + </script> + + <script> + //<![CDATA[ + var util; + (function (util) { + + function autoNumber() { + + function alphabetize(n) { + var ordA = 'A'.charCodeAt(0); + var ordZ = 'Z'.charCodeAt(0); + var len = ordZ - ordA + 1; + + var s = ""; + while(n >= 0) { + s = String.fromCharCode(n % len + ordA-1) + s; + n = Math.floor(n / len) - 1; + } + return s; + } + + function romanize (num) { + if (!+num){ + return false; + } + var digits = String(+num).split(""), + key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM", + "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC", + "","I","II","III","IV","V","VI","VII","VIII","IX"], + roman = "", + i = 3; + while (i--) { + roman = (key[+digits.pop() + (i * 10)] || "") + roman; + } + return Array(+digits.join("") + 1).join("M") + roman; + } + + function formatNumber(number, format) { + var formattedNumber = ""; + switch (format) { + case "n": + case "N": + formattedNumber = number.toString(); + break; + case "a": + formattedNumber = alphabetize(number).toLowerCase(); + break; + case "A": + formattedNumber = alphabetize(number); + break; + case "i": + formattedNumber = romanize(number).toLowerCase(); + break; + case "I": + formattedNumber = romanize(number); + break; + default: + formattedNumber = number.toString(); + } + return formattedNumber; + } + + var nodes = document.querySelectorAll("h1, h2, h3, h4, h5, h6, autonumber"); + var h1Counter = 0; + var h2Counter = 0; + var h3Counter = 0; + var h4Counter = 0; + var h5Counter = 0; + var h6Counter = 0; + var dict = {}; + for (var i = 0; i < nodes.length; i++) { + node = nodes[i]; + switch (node.nodeName.toLowerCase()) { + case "h1": + h1Counter = h1Counter + 1; + h2Counter = 0; + dict["figure"] = 0; + dict["table"] = 0; + break; + case "h2": + h2Counter = h2Counter + 1; + h3Counter = 0; + break; + case "h3": + h3Counter = h3Counter + 1; + h4Counter = 0; + break; + case "h4": + h4Counter = h4Counter + 1; + h5Counter = 0; + break; + case "h5": + h5Counter = h5Counter + 1; + h6Counter = 0; + break; + case "h6": + h6Counter = h6Counter + 1; + break; + case "autonumber": + var counterName = node.getAttribute("stream-name"); + var number = null; + switch (counterName.toLowerCase()) { + case "h1": + number = h1Counter; + break; + case "h2": + number = h2Counter; + break; + case "h3": + number = h3Counter; + break; + case "h4": + number = h4Counter; + break; + case "h5": + number = h5Counter; + break; + case "h6": + number = h6Counter; + break; + } + + var resetCtrs = node.parentElement.style["counter-reset"].split(" "); + for(reset_idx = 0; reset_idx < resetCtrs.length - 1; reset_idx++){ + dict[resetCtrs[reset_idx]] = 0; + } + + if (number == null) { + if (!dict[counterName]) + dict[counterName] = 0; + + var incrementCtrs = node.parentElement.style["counter-increment"].split(" "); + for(incr_idx = 0; incr_idx < incrementCtrs.length - 1; incr_idx++){ + if (incrementCtrs[incr_idx] == counterName) { + dict[incrementCtrs[incr_idx]] += 1; + } + } + + number = dict[counterName]; + } + var format = node.getAttribute("format"); + format = format ? format : "n"; + node.innerHTML = formatNumber(number, format); + break + default: + number = ""; + } + + + } + } + + util.autoNumber = autoNumber; + + function renameSpanToAutonumber() { + var nodes = document.querySelectorAll("span.an_sect1, span.an_figure, span.an_table, span[stream-name]"); + for (var i = 0; i < nodes.length; i++) { + node = nodes[i]; + var streamName = node.getAttribute("stream-name"); + if(!streamName){ + switch(node.className){ + case "an_sect1": + streamName = "h1"; + break; + case "an_table": + streamName = "table"; + break; + case "an_figure": + streamName = "figure"; + break; + } + } + node.setAttribute("stream-name", streamName); + node.outerHTML = node.outerHTML.replace(/span/g,"autonumber"); + + } + } + util.renameSpanToAutonumber = renameSpanToAutonumber; + + + })(util || (util = {})) + //]]> + </script> + + <script> + //<![CDATA[ + function outline() { + util.renameSpanToAutonumber(); + util.autoNumber(); + var toc_elements = document.querySelectorAll('div#toc, toc'); + var loc_elements = document.querySelectorAll('div#loc, loc'); + + var sidebar_display = false; + if (toc_elements.length != 0 || loc_elements.length != 0){ + sidebar.createSidebar(); + } + + if (toc_elements.length != 0) { + var content = document.body; + toc.HTMLOutline(content); + if (content.sectionList) { + for (var toc_index = 0; toc_index < toc_elements.length; ++toc_index) { + var toc_element = toc_elements[toc_index]; + var toc_levels = 6; + var toc_levels_attribute = toc_element.getAttribute('number-of-levels'); + if (toc_levels_attribute) { + toc_levels = Number(toc_levels_attribute); + } + toc_element.appendChild(toc.createOutline(content.sectionList, toc_levels, 1)); + } + } + var toc_element = document.querySelector('div#toc, toc'); + //document.body.removeChild(toc_element); + sidebar.apppendData(toc_element); + } + + var loc_elements = document.querySelectorAll('div#loc, loc'); + for (var i = 0; i < loc_elements.length; i++) { + var loc_element = loc_elements[i]; + var content = document.body; + var streamName = loc_element.getAttribute("an-stream-name"); + sidebar.apppendData(loc.getLOCElements(content, streamName)); + } + } + //]]> + </script> +<style> +/*<![CDATA[*//*CombinedCSS Placeholder*//*]]>*/ +</style></head> +<body onload="outline()"><a name="home"></a><h1><span>Project Upgrade Report</span></h1><h2><span>Description</span></h2><table><tr><td style="border-right-style:solid;border-right-width:1px;"><span>Generated by:</span></td><td><span>arthur</span></td></tr><tr><td style="border-right-style:solid;border-right-width:1px;"><span>Project name:</span></td><td><span>acme</span></td></tr><tr><td style="border-right-style:solid;border-right-width:1px;"><span>Generated at:</span></td><td><span>11-Nov-2021 10:45:33</span></td></tr><tr><td style="border-right-style:solid;border-right-width:1px;"><span>Project Root:</span></td><td><span>/home/arthur/Documents/acme</span></td></tr><tr><td style="border-right-style:solid;border-right-width:1px;"><span>Repository Location:</span></td><td><span>https://gitlab.aei.uni-hannover.de/arthur.reis/acme</span></td></tr></table><h2><span>Summary</span></h2><table><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file1"><span>$/core/dynamics/calcForcesTorques.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file2"><span>$/core/dynamics/a_calcForcesTorques.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file3"><span>$/core/actuators/actParaPlates.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file4"><span>$/core/dynamics/a_dblintSISOlinear_1DOF.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file5"><span>$/core/noises/noises.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file6"><span>$/core/noises/setPredefInjection.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file7"><span>$/core/noises/createAccelerationNoiseASD.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file8"><span>$/tests/component/dynamics/testscript_dblintSISOrotational_1DOF.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file9"><span>$/tests/component/noises/test_injection.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file10"><span>$/core/sensors/sensParaPlates2v1.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file11"><span>$/initAcme.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file12"><span>$/tests/component/dynamics/test_dblintSISO_linear.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file13"><span>$/utils/createFrequencyArray.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file14"><span>$/core/actuators/actuators.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file15"><span>$/tests/component/noises/testscript_injection.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file16"><span>$/core/dynamics/a_dblintSISO_6DOF.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file17"><span>$/core/dynamics/dblintSISOlinear_1DOF.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file18"><span>$/tests/component/noises/test_injection_multiple.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file19"><span>$/tests/component/noises/testscript_injection_readout.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file20"><span>$/tests/component/noises/testscript_injection_multiple.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file21"><span>$/core/sensors/sensParaPlates1v1.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file22"><span>$/core/dynamics/dblintSISOrotational_1DOF.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file23"><span>$/core/dynamics/dynamics.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file24"><span>$/core/noises/setReadoutBlock.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file25"><span>$/tests/component/noises/test_readout.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file26"><span>$/core/dynamics/setDoubleIntegrator_6DOF.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file27"><span>$/tests/component/dynamics/testscript_dblintSISOlinear_1DOF.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file28"><span>$/tests/component/dynamics/testscript_dblintSISO_6DOF.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file29"><span>$/core/dynamics/a_dblintSISOrotational_1DOF.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file30"><span>$/core/noises/injection.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file31"><span>$/tests/component/dynamics/test_dblintSISO_6DOF.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file32"><span>$/utils/libAcme.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file33"><span>$/tests/component/noises/test_injection_readout.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file34"><span>$/core/sensors/sensors.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Need Attention</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file35"><span>$/core/noises/setInjectionBlock_old.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file36"><span>$/core/actuators/a_actParaPlates.slx</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed With Fixes</span></td></tr><tr><td style="border-bottom-style:solid;border-bottom-width:1px;border-right-style:solid;border-right-width:1px;"><a href="#file37"><span>$/tests/component/noises/testscript_readout.m</span></a></td><td style="border-bottom-style:solid;border-bottom-width:1px;"><span>Passed</span></td></tr><tr><td style="border-right-style:solid;border-right-width:1px;"><a href="#file38"><span>$/core/dynamics/dblintSISO_6DOF.slx</span></a></td><td><span>Need Attention</span></td></tr></table><h2><a name="file1"></a><span>$/core/dynamics/calcForcesTorques.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file2"></a><span>$/core/dynamics/a_calcForcesTorques.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file3"></a><span>$/core/actuators/actParaPlates.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file4"></a><span>$/core/dynamics/a_dblintSISOlinear_1DOF.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file5"></a><span>$/core/noises/noises.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Model block cannot reference a Library or Subsystem. '<a href="matlab:open_system ('injection')">injection</a>' is a Library or Subsystem. Please specify a model name. +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Model block cannot reference a Library or Subsystem. '<a href="matlab:open_system ('injection')">injection</a>' is a Library or Subsystem. Please specify a model name.</font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file6"></a><span>$/core/noises/setPredefInjection.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file7"></a><span>$/core/noises/createAccelerationNoiseASD.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file8"></a><span>$/tests/component/dynamics/testscript_dblintSISOrotational_1DOF.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file9"></a><span>$/tests/component/noises/test_injection.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Diagnostic reported from block '<a href="matlab:open_and_hilite_hyperlink ('test_injection/injection/blkFromFile','error')">test_injection/injection/blkFromFile</a>' +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Diagnostic reported from block '<a href="matlab:open_and_hilite_hyperlink ('test_injection/injection/blkFromFile','error')">test_injection/injection/blkFromFile</a>'<br /><br /><br />signalFile2.mat: File not found.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file10"></a><span>$/core/sensors/sensParaPlates2v1.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file11"></a><span>$/initAcme.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file12"></a><span>$/tests/component/dynamics/test_dblintSISO_linear.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file13"></a><span>$/utils/createFrequencyArray.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file14"></a><span>$/core/actuators/actuators.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file15"></a><span>$/tests/component/noises/testscript_injection.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file16"></a><span>$/core/dynamics/a_dblintSISO_6DOF.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file17"></a><span>$/core/dynamics/dblintSISOlinear_1DOF.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Error evaluating properties of Simulink.Parameter object 'm' in workspace '<a href="matlab:open_system ('dblintSISOlinear_1DOF')">dblintSISOlinear_1DOF</a>' +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Error evaluating properties of Simulink.Parameter object 'm' in workspace '<a href="matlab:open_system ('dblintSISOlinear_1DOF')">dblintSISOlinear_1DOF</a>'<br /><br /><br />Unable to use model argument 'm' as an interface when model '<a href="matlab:open_system ('dblintSISOlinear_1DOF')">dblintSISOlinear_1DOF</a>' is being compiled as a top model. <br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file18"></a><span>$/tests/component/noises/test_injection_multiple.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file19"></a><span>$/tests/component/noises/testscript_injection_readout.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file20"></a><span>$/tests/component/noises/testscript_injection_multiple.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file21"></a><span>$/core/sensors/sensParaPlates1v1.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Invalid setting in '<a href="matlab:open_and_hilite_hyperlink ('sensParaPlates1v1/Multiply','error')">sensParaPlates1v1/Multiply</a>' for parameter 'Gain'. +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Invalid setting in '<a href="matlab:open_and_hilite_hyperlink ('sensParaPlates1v1/Multiply','error')">sensParaPlates1v1/Multiply</a>' for parameter 'Gain'.<br /><br /><br />The parameter supports only finite values.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file22"></a><span>$/core/dynamics/dblintSISOrotational_1DOF.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Error evaluating properties of Simulink.Parameter object 'momentInertia' in workspace '<a href="matlab:open_system ('dblintSISOrotational_1DOF')">dblintSISOrotational_1DOF</a>' +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Error evaluating properties of Simulink.Parameter object 'momentInertia' in workspace '<a href="matlab:open_system ('dblintSISOrotational_1DOF')">dblintSISOrotational_1DOF</a>'<br /><br /><br />Unable to use model argument 'momentInertia' as an interface when model '<a href="matlab:open_system ('dblintSISOrotational_1DOF')">dblintSISOrotational_1DOF</a>' is being compiled as a top model. <br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file23"></a><span>$/core/dynamics/dynamics.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_x'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_x','error')">dblintSISO_6DOF/dblint_x</a>'<br /><br /> +Unrecognized function or variable 'm'.<br /><br /> +Variable 'm' does not exist. <br /> +<br /> +Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_y'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_y','error')">dblintSISO_6DOF/dblint_y</a>'<br /><br /> +Unrecognized function or variable 'm'.<br /><br /> +Variable 'm' does not exist. <br /> +<br /> +Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_z'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_z','error')">dblintSISO_6DOF/dblint_z</a>'<br /><br /> +Unrecognized function or variable 'm'.<br /><br /> +Variable 'm' does not exist. <br /> +<br /> + +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_x'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_x','error')">dblintSISO_6DOF/dblint_x</a>'<br /><br /><br />Unrecognized function or variable 'm'.<br /><br /><br />Variable 'm' does not exist. <br /><br /><br /><br />Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_y'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_y','error')">dblintSISO_6DOF/dblint_y</a>'<br /><br /><br />Unrecognized function or variable 'm'.<br /><br /><br />Variable 'm' does not exist. <br /><br /><br /><br />Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_z'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_z','error')">dblintSISO_6DOF/dblint_z</a>'<br /><br /><br />Unrecognized function or variable 'm'.<br /><br /><br />Variable 'm' does not exist. <br /><br /><br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file24"></a><span>$/core/noises/setReadoutBlock.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file25"></a><span>$/tests/component/noises/test_readout.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file26"></a><span>$/core/dynamics/setDoubleIntegrator_6DOF.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file27"></a><span>$/tests/component/dynamics/testscript_dblintSISOlinear_1DOF.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file28"></a><span>$/tests/component/dynamics/testscript_dblintSISO_6DOF.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file29"></a><span>$/core/dynamics/a_dblintSISOrotational_1DOF.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file30"></a><span>$/core/noises/injection.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file31"></a><span>$/tests/component/dynamics/test_dblintSISO_6DOF.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file32"></a><span>$/utils/libAcme.slx</span></h2><h4><span>Run checks that require Update Diagram on library blocks</span></h4><b><span style="color:#F1B51C;"> Need attention </span></b><br>Unable to upgrade blocks unused by a model. Use the blocks in a model and then upgrade. <table cellspacing="3px" cellpadding="0" border="0"><tr><td>Unused Blocks:</td><td>libAcme/actParaPlates_LPF, libAcme/dblintSISO_6DOF, libAcme/sensParaPlates2v1, libAcme/dblintSISOrotational_1DOF, libAcme/actParaPlates_ONERA, libAcme/dblintSISOlinear_1DOF, libAcme/actParaPlates, libAcme/calcForcesTorques, libAcme/Model</td></tr></table> +<b><span style="color:Green;"> Passed </span></b><table cellspacing="3px" cellpadding="0" border="0"><tr><td>Block:</td><td>libAcme/injection</td></tr><tr><td>Used by:</td><td>test_injection_multiple.slx, test_injection_readout.slx, test_injection.slx</td></tr></table> +<b><span style="color:Green;"> Passed </span></b><table cellspacing="3px" cellpadding="0" border="0"><tr><td>Block:</td><td>libAcme/readout</td></tr><tr><td>Used by:</td><td>test_injection_readout.slx, test_readout.slx</td></tr></table> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file33"></a><span>$/tests/component/noises/test_injection_readout.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file34"></a><span>$/core/sensors/sensors.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Invalid setting in '<a href="matlab:open_and_hilite_hyperlink ('sensParaPlates1v1/Multiply','error')">sensParaPlates1v1/Multiply</a>' for parameter 'Gain'. +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Invalid setting in '<a href="matlab:open_and_hilite_hyperlink ('sensParaPlates1v1/Multiply','error')">sensParaPlates1v1/Multiply</a>' for parameter 'Gain'.<br /><br /><br />The parameter supports only finite values.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + +<h2><a name="file35"></a><span>$/core/noises/setInjectionBlock_old.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file36"></a><span>$/core/actuators/a_actParaPlates.slx</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file37"></a><span>$/tests/component/noises/testscript_readout.m</span></h2><span>All checks passed.</span><a href="#home"><span>Go to Top</span></a> + +<h2><a name="file38"></a><span>$/core/dynamics/dblintSISO_6DOF.slx</span></h2><h4><span>Check for virtual bus across model reference boundaries</span></h4><p /><font color="Red"> +Abnormal exit: Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_x'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_x','error')">dblintSISO_6DOF/dblint_x</a>'<br /><br /> +Unrecognized function or variable 'm'.<br /><br /> +Variable 'm' does not exist. <br /> +<br /> +Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_y'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_y','error')">dblintSISO_6DOF/dblint_y</a>'<br /><br /> +Unrecognized function or variable 'm'.<br /><br /> +Variable 'm' does not exist. <br /> +<br /> +Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_z'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_z','error')">dblintSISO_6DOF/dblint_z</a>'<br /><br /> +Unrecognized function or variable 'm'.<br /><br /> +Variable 'm' does not exist. <br /> +<br /> + +</font> + + +<h4><span>Check model for block upgrade issues requiring compile time information</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model for S-function upgrade issues</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check for root outports with constant sample time</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check model settings for migration to simplified initialization mode</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check virtual bus inputs to blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Merge blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br />Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_x'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_x','error')">dblintSISO_6DOF/dblint_x</a>'<br /><br /><br />Unrecognized function or variable 'm'.<br /><br /><br />Variable 'm' does not exist. <br /><br /><br /><br />Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_y'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_y','error')">dblintSISO_6DOF/dblint_y</a>'<br /><br /><br />Unrecognized function or variable 'm'.<br /><br /><br />Variable 'm' does not exist. <br /><br /><br /><br />Error evaluating parameter <a href="matlab:Simulink.internal.OpenBlockParamsDialog(['dblintSISO_6DOF/dblint_z'],'m');">'m'</a> in '<a href="matlab:open_and_hilite_hyperlink ('dblintSISO_6DOF/dblint_z','error')">dblintSISO_6DOF/dblint_z</a>'<br /><br /><br />Unrecognized function or variable 'm'.<br /><br /><br />Variable 'm' does not exist. <br /><br /><br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Outport blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check Delay, Unit Delay and Zero-Order Hold blocks for rate transition</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<h4><span>Check usage of Discrete-Time Integrator blocks</span></h4><!-- mdladv_ignore_start --><div class="subsection"><!-- mdladv_ignore_finish --><p /><p /><font color="#FF0000">Error occurred during model compile.<br /><br /></font><!-- mdladv_ignore_start --></div><!-- mdladv_ignore_finish --> + +<a href="#home"><span>Go to Top</span></a> + + + +</body> +</html> \ No newline at end of file diff --git a/core/AcmeBlock.m b/core/AcmeBlock.m deleted file mode 100644 index bd7fbf64a1e7be5f9110f9f5218585b3bf83ef00..0000000000000000000000000000000000000000 --- a/core/AcmeBlock.m +++ /dev/null @@ -1,47 +0,0 @@ -classdef AcmeBlock - %ACMEBLOCK Summary of this class goes here - % Detailed explanation goes here - - properties - name - model - blockhandle - blocktype - parameters - end - - methods - function obj = AcmeBlock(name, model, parameters) - %ACMEBLOCK Construct an instance of this class - % Detailed explanation goes here - % receives from AcmeBlockType - obj.name = name; - obj.model = model; - %obj.blockhandle = 1; - obj.blockhandle = Simulink.findBlocks(model,'Name',name); - assert(~isempty(obj.blockhandle), "Could not find block '%s' in model '%s'", name, model); - - obj.parameters = parameters; - for iparm = 1:length(obj.parameters.name) - setBlockParm(obj,obj.parameters.name{iparm},... - obj.parameters.value{iparm}); - end - end - - function setBlockParm(obj,name,value) - s = ""; - if isnumeric(value) - if isequal(size(value),[1 1]) - s = num2str(value); - else - s = mat2str(value); - end - elseif isstring(value) - s = value; - end - set_param(obj.blockhandle,name,s); - %set_param_test(obj.blockhandle,name,s); - end - end -end - diff --git a/core/actuators/actParaPlates.png b/core/actuators/actParaPlates.png deleted file mode 100644 index 767544ddea6642284091287d12656b0d55a91ec8..0000000000000000000000000000000000000000 Binary files a/core/actuators/actParaPlates.png and /dev/null differ diff --git a/core/actuators/actParaPlates.slx b/core/actuators/actParaPlates.slx deleted file mode 100644 index 41c91c24af4c6bf13adcf4380681d2655bc4327e..0000000000000000000000000000000000000000 Binary files a/core/actuators/actParaPlates.slx and /dev/null differ diff --git a/core/actuators/setActuatorParaPlates.m b/core/actuators/setActuatorParaPlates.m deleted file mode 100644 index 86c26ab8d2701e13d8cc857a6f7689e860e964b9..0000000000000000000000000000000000000000 --- a/core/actuators/setActuatorParaPlates.m +++ /dev/null @@ -1,77 +0,0 @@ -function blockHandle = setActuatorParaPlates(varargin)%model, block, Kp ,Ki ,Kd ,... - %Vp ,Vt ,eps0 ,faceArea ,gap) -%SETACTUATORPARAPLATES - Sets the initial parameters of a paralel plates -%actuator block. -%Sets the initial parameters of a paralel plates actuator block. The PID gains -%can be obtained with the tuning app -% -% Syntax: setActuatorParaPlates(Kp,Ki,Kd,Vp,Vt,eps0,faceArea,gap) -% -% Inputs: -% Kp - Proportional gain, double; -% Ki - Integral gain, double; -% Kd - Differential gain, double; -% Vp - Polarization voltage, double; -% Vt - sqrt of squares of the polarization and detection voltages; -% eps0 - Vacuum permittivity, F/m, double; -% faceArea - area of the plates, m^2, double; -% gap - nominal gap between the plates, m, double; -% -% See also: setSensParaPlates -% -% Author: Arthur Reis -% email: arthur.reis@aei.mpg.de -% Nov 2021; Last revision: 16.Feb.2022; - -% try to load from local json -% should be handle or name -if strcmp(varargin{1},'blockName') - blockName = varargin{2}; -elseif strcmp(varargin{1},'blockHandle') - blockName = get_param(varargin{2},'Name'); -end - -%if file exists -%blockName = get_param(varargin{1},'Name'); -%JSONFILE_name= sprintf(strcat(blockName,'.json')); -%fid=fopen(JSONFILE_name,'r'); -%raw = fread(fid,inf); -%str = char(raw'); -%j = jsondecode(str); -% parses existing json as defaults -% and allows updating - -p = inputParser; -addParameter(p, 'model' , ''); -addParameter(p, 'blockName', ''); -addParameter(p, 'Kp' , 0, @isnumeric); -addParameter(p, 'Ki' , 0, @isnumeric); -addParameter(p, 'Kd' , 0, @isnumeric); -addParameter(p, 'Vp' , 0, @isnumeric); -addParameter(p, 'Vt' , 0, @isnumeric); -addParameter(p, 'eps0' , 0, @isnumeric); -addParameter(p, 'faceArea' , 0, @isnumeric); -addParameter(p, 'gap' , 0, @isnumeric); -parse(p, varargin{:}); -j = p.Results; -js = jsonencode(j,'PrettyPrint',true); -%save p.Results as json -JSONFILE_name= sprintf(strcat(p.Results.blockName,'.json')); -fid=fopen(JSONFILE_name,'w'); -fprintf(fid, js); -fclose(fid); - - - -blockHandle = Simulink.findBlocks(j.model,'Name',j.blockName); -set_param(blockHandle, 'Kp' , num2str(j.Kp)); -set_param(blockHandle, 'Ki' , num2str(j.Ki)); -set_param(blockHandle, 'Kd' , num2str(j.Kd)); -set_param(blockHandle, 'Vp' , num2str(j.Vp)); -set_param(blockHandle, 'Vt' , num2str(j.Vt)); -set_param(blockHandle, 'eps0' , num2str(j.eps0)); -set_param(blockHandle, 'faceArea', num2str(j.faceArea)); -set_param(blockHandle, 'gap' , num2str(j.gap)); - -end - diff --git a/core/actuators/setSinglePlate.m b/core/actuators/setSinglePlate.m deleted file mode 100644 index 73cceb07d7429a1fd6d7d1920c13b91ce70011bb..0000000000000000000000000000000000000000 --- a/core/actuators/setSinglePlate.m +++ /dev/null @@ -1,66 +0,0 @@ -function blockHandle = setSinglePlate(varargin) -%SETACTUATORPARAPLATES - Sets the initial parameters of a paralel plates -%actuator block. -%Sets the initial parameters of a paralel plates actuator block. The PID gains -%can be obtained with the tuning app -% -% Syntax: setActuatorParaPlates(Kp,Ki,Kd,Vp,Vt,eps0,faceArea,gap) -% -% Inputs: -% Kp - Proportional gain, double; -% Ki - Integral gain, double; -% Kd - Differential gain, double; -% Vp - Polarization voltage, double; -% Vt - sqrt of squares of the polarization and detection voltages; -% eps0 - Vacuum permittivity, F/m, double; -% faceArea - area of the plates, m^2, double; -% gap - nominal gap between the plates, m, double; -% -% See also: setSensParaPlates -% -% Author: Arthur Reis -% email: arthur.reis@aei.mpg.de -% Nov 2021; Last revision: 16.Feb.2022; - -% try to load from local json -% should be handle or name -if strcmp(varargin{1},'blockName') - blockName = varargin{2}; -elseif strcmp(varargin{1},'blockHandle') - blockName = get_param(varargin{2},'Name'); -end - -%if file exists -%blockName = get_param(varargin{1},'Name'); -%JSONFILE_name= sprintf(strcat(blockName,'.json')); -%fid=fopen(JSONFILE_name,'r'); -%raw = fread(fid,inf); -%str = char(raw'); -%j = jsondecode(str); -% parses existing json as defaults -% and allows updating - -p = inputParser; -addParameter(p, 'model' , ''); -addParameter(p, 'blockName', ''); -addParameter(p, 'Vt' , 0, @isnumeric); -addParameter(p, 'eps0' , 0, @isnumeric); -addParameter(p, 'faceArea' , 0, @isnumeric); -addParameter(p, 'gap' , 0, @isnumeric); -parse(p, varargin{:}); -j = p.Results; -js = jsonencode(j,'PrettyPrint',true); -%save p.Results as json -JSONFILE_name= sprintf(strcat(p.Results.blockName,'.json')); -fid=fopen(JSONFILE_name,'w'); -fprintf(fid, js); -fclose(fid); - -blockHandle = Simulink.findBlocks(j.model,'Name',j.blockName); -set_param(blockHandle, 'Vt' , num2str(j.Vt)); -set_param(blockHandle, 'eps0' , num2str(j.eps0)); -set_param(blockHandle, 'faceArea', num2str(j.faceArea)); -set_param(blockHandle, 'gap' , num2str(j.gap)); - -end - diff --git a/core/actuators/setSinglePlate_Vsqr.m b/core/actuators/setSinglePlate_Vsqr.m deleted file mode 100644 index e32ceb26095fd01f45376475be0f9518cbbe02f6..0000000000000000000000000000000000000000 --- a/core/actuators/setSinglePlate_Vsqr.m +++ /dev/null @@ -1,66 +0,0 @@ -function blockHandle = setSinglePlate_Vsqr(varargin) -%SETACTUATORPARAPLATES - Sets the initial parameters of a paralel plates -%actuator block. -%Sets the initial parameters of a paralel plates actuator block. The PID gains -%can be obtained with the tuning app -% -% Syntax: setActuatorParaPlates(Kp,Ki,Kd,Vp,Vt,eps0,faceArea,gap) -% -% Inputs: -% Kp - Proportional gain, double; -% Ki - Integral gain, double; -% Kd - Differential gain, double; -% Vp - Polarization voltage, double; -% Vt - sqrt of squares of the polarization and detection voltages; -% eps0 - Vacuum permittivity, F/m, double; -% faceArea - area of the plates, m^2, double; -% gap - nominal gap between the plates, m, double; -% -% See also: setSensParaPlates -% -% Author: Arthur Reis -% email: arthur.reis@aei.mpg.de -% Nov 2021; Last revision: 16.Feb.2022; - -% try to load from local json -% should be handle or name -if strcmp(varargin{1},'blockName') - blockName = varargin{2}; -elseif strcmp(varargin{1},'blockHandle') - blockName = get_param(varargin{2},'Name'); -end - -%if file exists -%blockName = get_param(varargin{1},'Name'); -%JSONFILE_name= sprintf(strcat(blockName,'.json')); -%fid=fopen(JSONFILE_name,'r'); -%raw = fread(fid,inf); -%str = char(raw'); -%j = jsondecode(str); -% parses existing json as defaults -% and allows updating - -p = inputParser; -addParameter(p, 'model' , ''); -addParameter(p, 'blockName', ''); -addParameter(p, 'Vt' , 0, @isnumeric); -addParameter(p, 'eps0' , 0, @isnumeric); -addParameter(p, 'faceArea' , 0, @isnumeric); -addParameter(p, 'gap' , 0, @isnumeric); -parse(p, varargin{:}); -j = p.Results; -js = jsonencode(j,'PrettyPrint',true); -%save p.Results as json -JSONFILE_name= sprintf(strcat(p.Results.blockName,'.json')); -fid=fopen(JSONFILE_name,'w'); -fprintf(fid, js); -fclose(fid); - -blockHandle = Simulink.findBlocks(j.model,'Name',j.blockName); -set_param(blockHandle, 'Vt' , num2str(j.Vt)); -set_param(blockHandle, 'eps0' , num2str(j.eps0)); -set_param(blockHandle, 'faceArea', num2str(j.faceArea)); -set_param(blockHandle, 'gap' , num2str(j.gap)); - -end - diff --git a/core/actuators/singlePlate.slx b/core/actuators/singlePlate.slx deleted file mode 100644 index 570b8946cf717aa653812a28508c0b0b03ad7f17..0000000000000000000000000000000000000000 Binary files a/core/actuators/singlePlate.slx and /dev/null differ diff --git a/core/actuators/singlePlate_Vsqr.slx b/core/actuators/singlePlate_Vsqr.slx deleted file mode 100644 index fbad84bb2ab10f045f5450d1d417d3b3cffd94a5..0000000000000000000000000000000000000000 Binary files a/core/actuators/singlePlate_Vsqr.slx and /dev/null differ diff --git a/core/component/Electrode.m b/core/component/Electrode.m deleted file mode 100644 index dccf233078ff31226150b21332396744ded7a434..0000000000000000000000000000000000000000 --- a/core/component/Electrode.m +++ /dev/null @@ -1,15 +0,0 @@ -classdef Electrode < AcmeBlock - %ELECTRODE Summary of this class goes here - methods - function obj = Electrode(name, model, Vbias, pos0, theta0, area) - %ELECTRODE Construct an instance of this class - %setElectrode(model, block, Vbias, pos0, theta0, area) - - parameters.name = ["Vbias", "pos0", "theta0", "area"]; - parameters.value = {Vbias , pos0 , theta0 , area }; - obj = obj@AcmeBlock(name, model, parameters); - obj.blocktype = "electrode"; - end - end -end - diff --git a/core/component/SimpleElectrode.png b/core/component/SimpleElectrode.png deleted file mode 100644 index 22d697e1de818f967a21735280011ec0145b99a6..0000000000000000000000000000000000000000 Binary files a/core/component/SimpleElectrode.png and /dev/null differ diff --git a/core/component/TIA.slx b/core/component/TIA.slx new file mode 100644 index 0000000000000000000000000000000000000000..4e52a08a4a10b9803d1929772f30054c8de4b263 Binary files /dev/null and b/core/component/TIA.slx differ diff --git a/core/component/capBridge.png b/core/component/capBridge.png new file mode 100644 index 0000000000000000000000000000000000000000..1f6cb18468bab6672a9f415c680769efcc293f67 Binary files /dev/null and b/core/component/capBridge.png differ diff --git a/core/component/capBridge.slx b/core/component/capBridge.slx new file mode 100644 index 0000000000000000000000000000000000000000..c95da3abc3f78e3d12682c9569af3f59b7f5869a Binary files /dev/null and b/core/component/capBridge.slx differ diff --git a/core/component/electrode.slx b/core/component/electrode.slx index 12fdbc3806b43404edda0ebcd01b62287eb11281..8c31a0345d5f1296cd67d99cd81889e034e05ecb 100644 Binary files a/core/component/electrode.slx and b/core/component/electrode.slx differ diff --git a/core/component/planeCapacitor.slx b/core/component/planeCapacitor.slx index 66e557eb652c43e403e5dd847076d0657ad695fe..97f96224a5ca4ddb18d40eb0fb762668f180c5d6 100644 Binary files a/core/component/planeCapacitor.slx and b/core/component/planeCapacitor.slx differ diff --git a/core/component/setCapBridge.m b/core/component/setCapBridge.m new file mode 100644 index 0000000000000000000000000000000000000000..c510c6a99b73d568a0f34a656d928a16616debb9 --- /dev/null +++ b/core/component/setCapBridge.m @@ -0,0 +1,56 @@ +function [blockHandle, varargout] = setCapBridge(varargin) +% +% SETCAPBRIDGE - Sets the parameters of a simplified capacitive bridge +% +% Syntax: blockHandle = setCapBridge(model, block, L, Cp, C0, [Q]) +% +% Inputs: +% model - Name of the Simulink model, string; +% block - Name of the target instance of the Injection Block, string; +% L - Transformer inductance, H, double; +% Cp - Bridge tuning capacitance, F, double; +% C0 - capacitance at resting position; +% Q - transformer quality factor, optional, default 100 +% +% Output: +% blockHandle - Simulink block instance handle reference number; +% [Zbr] - Bridge impedance, function handle +% [f0] - Bridge renonant frequency, Hz +% See also: Davor Mance - PhD thesis Ch. 2 +% +% Author: Arthur Reis +% email: arthur.reis@aei.mpg.de +% Last revision: 27.Sep.2022; +defaultQ = 100; + +p = inputParser; + +addRequired(p, 'model'); +addRequired(p, 'block'); +addRequired(p, 'L' , @(x) isnumeric(x) && isscalar(x)); +addRequired(p, 'Cp', @(x) isnumeric(x) && isscalar(x)); +addRequired(p, 'C0', @(x) isnumeric(x) && isscalar(x)); +addOptional(p, 'Q', defaultQ, @(x) isnumeric(x) && isscalar(x)); + +parse(p, varargin{:}); +model = p.Results.model; +block = p.Results.block; +L = p.Results.L; +Cp = p.Results.Cp; +C0 = p.Results.C0; +Q = p.Results.Q; + +Ceq = 2*(Cp + C0); +f0 = (Q/sqrt(1+Q^2))*1/sqrt(L*Ceq)/(2*pi); +Zbr = eval(['@(f) j*2*pi*f.*' num2str(L) '*(1-j/' num2str(Q) ')./'... + '(1-(2*pi*f).^2.*' num2str(L*Ceq) '*(1-j/' num2str(Q) '))']); + +blockHandle = Simulink.findBlocks(model,'Name',block); + +set_param(blockHandle,'L' , num2str(L)); +set_param(blockHandle,'Q' , num2str(Q)); +set_param(blockHandle,'Ceq', num2str(Ceq)); + +varargout{1} = Zbr; +varargout{2} = f0; +end \ No newline at end of file diff --git a/core/component/setElectrode.m b/core/component/setElectrode.m index 6877aca5f4d0573e45fd533b2dba15525f99448e..12ea89ac90ea7d55c44b25940cf8f9e33d46427c 100644 --- a/core/component/setElectrode.m +++ b/core/component/setElectrode.m @@ -1,19 +1,20 @@ function blockHandle = setElectrode(varargin) % -%SETELECTRODE - Sets the initial parameters of a electrode +% SETELECTRODE - Sets the initial parameters of a electrode % Sets the initial parameters of a electrode, to be paired to form a parallel % plates capacitor. % -% Syntax: blockHandle = setElectrode(model, block, Vbias, pos0, n0, area) +% Syntax: blockHandle = setElectrode(model, block, area, pos0, V_DC, V_AC, f) % % Inputs: % model - Name of the Simulink model, string; % block - Name of the target instance of the Injection Block, string; -% Vbias - Offset voltage, V; -% pos0 - initial/nominal position of the center of the plate, m. -% theta0- initial/nominal direction of plate, comparing to the direction -% towards the other plate of the capacitor. % area - area of the plate, m^s +% pos0 - initial/nominal position of the center of the plate, m. +% V_DC - Offset DC voltage, V; +% V_AC - AC voltage, V (rms), optional; +% f - frequency of the AC voltage, Hz; +% solver- type of solver the model will use, parameter; % % Output: % blockHandle - Simulink block instance handle reference number; @@ -22,36 +23,37 @@ function blockHandle = setElectrode(varargin) % % Author: Arthur Reis % email: arthur.reis@aei.mpg.de -% Last revision: 7.Apr.2022; -%model, block, Vbias, pos0, theta0, area +% Last revision: 27.Sep.2022; + defaultSolver = "Variable-step"; -defaultTheta0 = 0; +defaultVAC = 0; +defaultf = 1; p = inputParser; addRequired(p, 'model'); addRequired(p, 'block'); -addRequired(p, 'Vbias', @(x) isnumeric(x) && isscalar(x)); -addRequired(p, 'pos0', @(x) isnumeric(x) && isscalar(x)); -addRequired(p, 'area', @(x) isnumeric(x) && isscalar(x)); -addOptional(p, 'theta0', defaultTheta0); +addRequired(p, 'area', @(x) isnumeric(x) && isscalar(x)); +addRequired(p, 'pos0', @(x) isnumeric(x) && isscalar(x)); +addRequired(p, 'V_DC', @(x) isnumeric(x) && isscalar(x)); +addOptional(p, 'V_AC', defaultVAC); +addOptional(p, 'f', defaultf); addParameter(p, "solver", defaultSolver); parse(p, varargin{:}); blockHandle = Simulink.findBlocks(p.Results.model,'Name',p.Results.block); -set_param(blockHandle,'Vbias', num2str(p.Results.Vbias)); -set_param(blockHandle,'pos0', num2str(p.Results.pos0)); -set_param(blockHandle,'theta0',num2str(p.Results.theta0)); set_param(blockHandle,'area', num2str(p.Results.area)); +set_param(blockHandle,'pos0', num2str(p.Results.pos0)); +set_param(blockHandle,'V_DC0', num2str(p.Results.V_DC)); +set_param(blockHandle,'V_AC0', num2str(p.Results.V_AC)); +set_param(blockHandle,'f0', num2str(p.Results.f)); if strcmp(p.Results.solver,defaultSolver) load_system("electrode"); set_param("electrode","SolverType","Variable-step"); elseif strcmp(p.Results.solver,'Fixed-step') - %set_param(blockHandle,'Vbias', num2str(Vbias)); load_system("electrode"); set_param("electrode","SolverType", "Fixed-step") end -end - +end \ No newline at end of file diff --git a/core/component/setPlaneCapacitor.m b/core/component/setPlaneCapacitor.m index d5877399f090568bc7abeaca8d402eb95cb090df..1ca4b8f2b38838341e068636e8978e49743878c8 100644 --- a/core/component/setPlaneCapacitor.m +++ b/core/component/setPlaneCapacitor.m @@ -1,13 +1,13 @@ function blockHandle = setPlaneCapacitor(varargin) -%SETPLANECAPACITOR - Sets the initial parameters of a capacitor. -%Sets the initial parameters of a capacitor. Based on a parallel planes capacitor. +% SETPLANECAPACITOR - Sets the initial parameters of a capacitor. +% Sets the initial parameters of a capacitor. Based on a parallel planes capacitor. % -% Syntax: blockHandle = setPlaneCapacitor(model, block, eps0) +% Syntax: blockHandle = setPlaneCapacitor(model, block, eps) % % Inputs: % model - Name of the Simulink model, string; % block - Name of the target instance of the Injection Block, string; -% eps0 - Vacuum permittivity, F/m, double; +% eps - Medium permittivity, F/m, double; % % Outputs: % blockHandle - Simulink block instance handle reference number; @@ -30,11 +30,11 @@ parse(p, varargin{:}); blockHandle = Simulink.findBlocks(p.Results.model,'Name',p.Results.block); set_param(blockHandle,'eps0', num2str(p.Results.eps0)); -% if strcmp(p.Results.solver,defaultSolver) -% set_param('planeCapacitor','SolverType','Variable-step'); -% elseif strcmp(p.Results.solver,'Fixed-step') -% %set_param(blockHandle,'Vbias', num2str(Vbias)); -% set_param('planeCapacitor', 'SolverType', 'Fixed-step') -% end +if strcmp(p.Results.solver,defaultSolver) + load_system("planeCapacitor"); + set_param("planeCapacitor",'SolverType','Variable-step'); +elseif strcmp(p.Results.solver,"Fixed-step") + load_system("planeCapacitor"); + set_param("planeCapacitor", 'SolverType', 'Fixed-step') end - +end \ No newline at end of file diff --git a/core/component/setSinglePlate.m b/core/component/setSinglePlate.m deleted file mode 100644 index 73cceb07d7429a1fd6d7d1920c13b91ce70011bb..0000000000000000000000000000000000000000 --- a/core/component/setSinglePlate.m +++ /dev/null @@ -1,66 +0,0 @@ -function blockHandle = setSinglePlate(varargin) -%SETACTUATORPARAPLATES - Sets the initial parameters of a paralel plates -%actuator block. -%Sets the initial parameters of a paralel plates actuator block. The PID gains -%can be obtained with the tuning app -% -% Syntax: setActuatorParaPlates(Kp,Ki,Kd,Vp,Vt,eps0,faceArea,gap) -% -% Inputs: -% Kp - Proportional gain, double; -% Ki - Integral gain, double; -% Kd - Differential gain, double; -% Vp - Polarization voltage, double; -% Vt - sqrt of squares of the polarization and detection voltages; -% eps0 - Vacuum permittivity, F/m, double; -% faceArea - area of the plates, m^2, double; -% gap - nominal gap between the plates, m, double; -% -% See also: setSensParaPlates -% -% Author: Arthur Reis -% email: arthur.reis@aei.mpg.de -% Nov 2021; Last revision: 16.Feb.2022; - -% try to load from local json -% should be handle or name -if strcmp(varargin{1},'blockName') - blockName = varargin{2}; -elseif strcmp(varargin{1},'blockHandle') - blockName = get_param(varargin{2},'Name'); -end - -%if file exists -%blockName = get_param(varargin{1},'Name'); -%JSONFILE_name= sprintf(strcat(blockName,'.json')); -%fid=fopen(JSONFILE_name,'r'); -%raw = fread(fid,inf); -%str = char(raw'); -%j = jsondecode(str); -% parses existing json as defaults -% and allows updating - -p = inputParser; -addParameter(p, 'model' , ''); -addParameter(p, 'blockName', ''); -addParameter(p, 'Vt' , 0, @isnumeric); -addParameter(p, 'eps0' , 0, @isnumeric); -addParameter(p, 'faceArea' , 0, @isnumeric); -addParameter(p, 'gap' , 0, @isnumeric); -parse(p, varargin{:}); -j = p.Results; -js = jsonencode(j,'PrettyPrint',true); -%save p.Results as json -JSONFILE_name= sprintf(strcat(p.Results.blockName,'.json')); -fid=fopen(JSONFILE_name,'w'); -fprintf(fid, js); -fclose(fid); - -blockHandle = Simulink.findBlocks(j.model,'Name',j.blockName); -set_param(blockHandle, 'Vt' , num2str(j.Vt)); -set_param(blockHandle, 'eps0' , num2str(j.eps0)); -set_param(blockHandle, 'faceArea', num2str(j.faceArea)); -set_param(blockHandle, 'gap' , num2str(j.gap)); - -end - diff --git a/core/component/setTIA.m b/core/component/setTIA.m new file mode 100644 index 0000000000000000000000000000000000000000..37c91df9292eb0ed99536fed715b36cfc23d64d1 --- /dev/null +++ b/core/component/setTIA.m @@ -0,0 +1,51 @@ +function [blockHandle, varargout] = setTIA(varargin) +% +% SETTIA - Sets the parameters of a transimpedance amplifier +% +% Syntax: [blockHandle, Zfb, Gtia_s] = +% setElectrode(model, block, Zbr, Cfb, Rfb +% +% Inputs: +% model - Name of the Simulink model, string; +% block - Name of the target instance of the Injection Block, string; +% RBr - real part of impedance of the capacitance bridge @ detection freq, ohm +% Cfb - TIA feedback capacitance, F +% Rfb - TIA feedback resistance, ohm +% +% Output: +% blockHandle - Simulink block instance handle reference number; +% [Zfb] - feedback impedance, function handle +% [Gtia_s] - simplified TIA gain, function handle +% See also: Davor Mance - PhD thesis +% +% Author: Arthur Reis +% email: arthur.reis@aei.mpg.de +% Last revision: 13.10.2022; + +p = inputParser; + +addRequired(p, 'model'); +addRequired(p, 'block'); +addRequired(p, 'Rbr'); +addRequired(p, 'Cfb'); +addRequired(p, 'Rfb'); + +parse(p, varargin{:}); +model = p.Results.model; +block = p.Results.block; +Rbr = real(p.Results.Rbr); +Cfb = p.Results.Cfb; +Rfb = p.Results.Rfb; + +% Mance eq. B12 +Zfb = eval(['@(f) ' num2str(Rfb) './(' num2str(i*2*pi*Rfb*Cfb) '.*f + 1)']); + +% Mance eq. 2.91 +blockHandle = Simulink.findBlocks(model,'Name',block); +set_param(blockHandle,'Cfb' , num2str(Cfb)); +set_param(blockHandle,'RBr' , num2str(Rbr)); + +Gtia_S = eval(['@(f) 2./(f.*' num2str(2*pi*Rbr*Cfb) ').^2']); +varargout{1} = Zfb; +varargout{2} = Gtia_S; +end \ No newline at end of file diff --git a/core/component/singlePlate.slx b/core/component/singlePlate.slx deleted file mode 100644 index 36a3ea468cc0b94e4ccd1b277154955f7f124021..0000000000000000000000000000000000000000 Binary files a/core/component/singlePlate.slx and /dev/null differ diff --git a/core/dynamics/dblIntTransFS.slx b/core/dynamics/dblIntTransFS.slx index 0f075a08ccb48fcfce3a9f221ef4a6defb3b370b..62b77aea70790f32dc517079734b033d8d70c896 100644 Binary files a/core/dynamics/dblIntTransFS.slx and b/core/dynamics/dblIntTransFS.slx differ diff --git a/core/dynamics/dblIntTransVS.slx b/core/dynamics/dblIntTransVS.slx index 7c5beb500ac64649823b98c6c8d6873809c0f8f5..82fbc661ad07d9d4e6a58223a32b5c0b8468517a 100644 Binary files a/core/dynamics/dblIntTransVS.slx and b/core/dynamics/dblIntTransVS.slx differ diff --git a/core/dynamics/setDblIntTrans.m b/core/dynamics/setDblIntTrans.m index 78f723bf9731c103249ace04e3067e2231a2d48f..160b57806368e10746493ca02fbf4eaffcaaaf15 100644 --- a/core/dynamics/setDblIntTrans.m +++ b/core/dynamics/setDblIntTrans.m @@ -12,7 +12,7 @@ function blockHandle = setDblIntTrans(model, block, varargin) % initial position % - dq0, initial velocity % -% See also: setDoubleIntegrator_6DOF +% See also: % % Author: Arthur Reis % email: arthur.reis@aei.mpg.de diff --git a/core/dynamics/setDoubleIntegrator.m b/core/dynamics/setDoubleIntegrator.m index 84f126417a137f77bb59b28794343d6a8fa10e8e..80ecf30d49999db2f4a6b55384f0a55ae776b722 100644 --- a/core/dynamics/setDoubleIntegrator.m +++ b/core/dynamics/setDoubleIntegrator.m @@ -29,8 +29,8 @@ blockHandle = Simulink.findBlocks(strcat(model),... %% process inputs defaultq0 = 0; defaultdq0 = 0; -defaultmode = 'linear'; -expectedmodes = {'linear', 'rotational'}; +%defaultmode = 'linear'; +%expectedmodes = {'linear', 'rotational'}; % parameter parsing, required parms will throw error w/ defaults; p = inputParser; diff --git a/core/libAcme.slx b/core/libAcme.slx index 79f927c1bdd7cfa45a69d8ca1c5271d97149eebb..f2cef80e53e25ac68cd6233f8ce60a11c4302944 100644 Binary files a/core/libAcme.slx and b/core/libAcme.slx differ diff --git a/core/noises/injection.png b/core/noises/injection.png deleted file mode 100644 index 2ce5949b0e3fc8c9c186fe0adcbc00a2199b36df..0000000000000000000000000000000000000000 Binary files a/core/noises/injection.png and /dev/null differ diff --git a/core/noises/readout.png b/core/noises/readout.png deleted file mode 100644 index 25be7fe7a11cc14b3de76d0d4555646e47488ff3..0000000000000000000000000000000000000000 Binary files a/core/noises/readout.png and /dev/null differ diff --git a/core/noises/setInjectionBlock.m b/core/noises/setInjectionBlock.m deleted file mode 100644 index 31eada7407a64a79f5a2ff9fbef440c71f68325a..0000000000000000000000000000000000000000 --- a/core/noises/setInjectionBlock.m +++ /dev/null @@ -1,76 +0,0 @@ -function blockHandle = setInjectionBlock(model, block, mode, varargin) -%SETINJECTIONBLOCK - Sets the initial parameters of a injection block. -%Sets the initial parameters for one instance of the injection block from -%Acme library. -% -% Syntax: setInjectionBlock(model, block, mode, varargin) -% setInjectionBlock(model, block, 'FromWorkspace', workspaceVarName) -% setInjectionBlock(model, block, 'FromFunction', funcHandle, t_timeseries) -% setInjectionBlock(model, block, 'FromASD', funcHandle, freqs, N, enbw) -% setInjectionBlock(model, block, 'FromFile', filename) -% -% Inputs: -% model - Name of the Simulink model, string -% block - Name of the target instance of the Injection Block, string -% mode - Specifies how the Injection signal is defined. -% 'FromWorkspace': will use a timeseries existing on the base workspace; -% 'FromFunction': passes a function of time and a timeseries -% argument; -% 'FromASD': passes a ASD, function of frequency and create a time series using -% the ENBW algorithm; -% 'FromFile': uses the data stored in a file. -% workspaceVarName - name of the variable in the workspace, string; -% funcHandle - function (either of t or f). Function handle; -% t_timeseries - time part of a timeseries to be used as argument; -% freqs - array containing [fMin, fMax, fSample]. -% N = number of points that the freqs array has; -% filename - name of the file containing the data -% -% See also: createFrequencyArray, createTimeseriesFromASD_ENBW -% -% Author: Arthur Reis -% email: arthur.reis@aei.mpg.de -% Nov 2021; Last revision: 10.Nov.2021; - - -if strcmp(mode,'FromWorkspace') - % varargin: - % model, block, mode, workspaceVarName - var = varargin{1}; - filename = strcat(block,'_tmp'); - eval(strcat('save(filename,''var'',''-v7.3'');')); - -elseif strcmp(mode,'FromFunction') - % varargin: - % model, block, mode, funcHandle, t_timeseries - func = varargin{1}; - tSeries = varargin{2}; - arr = timeseries(func(tSeries),tSeries); - filename = strcat(block,'_tmp'); - save(filename,'arr','-v7.3'); - -elseif strcmp(mode,'FromASD') - % varargin: - % model, block, mode, funcHandle, freqs - func = varargin{1}; - frequencies = varargin{2}; %[fMin, fMax, fSample] - N = varargin{3}; - fSeries = createFrequencyArray(frequencies(2),0,N,'lin', 2,'reverse'); - enbw = varargin{4}; - arr = createTimeseriesFromASD_ENBW(func,fSeries, enbw); - filename = strcat(block,'_tmp'); - save(filename,'arr','-v7.3'); - -elseif strcmp(mode,'FromFile') - % varargin: - % model, block, mode, filename - filename = varargin{1}; - -end - -blockHandle = Simulink.findBlocks(strcat(model,'/',block),... - 'Name','blkFromFile'); -set_param(blockHandle,'FileName',strcat(filename)); - -end - diff --git a/core/noises/setReadoutBlock.m b/core/noises/setReadoutBlock.m deleted file mode 100644 index 5145cc74ad7f5fffe4182e2939ab09d51abce24c..0000000000000000000000000000000000000000 --- a/core/noises/setReadoutBlock.m +++ /dev/null @@ -1,21 +0,0 @@ -function blockHandle = setReadoutBlock(model, block, varname, fSample) -%SETREADOUTBLOCK sets an instance of the readout block in a model. -% -% Syntax: setReadoutBlock(model, block, varname, fSample) -% -% Inputs: model - Name of the Simulink model, string; -% block - Name of the target instance of the block, string; -% varname - Name of the variable to be created in the workspace; -% fSample - sampling rate of the block; -% -% See also: setInjectionBlock -% -% Author: Arthur Reis -% email: arthur.reis@aei.mpg.de -% Nov 2021; Last revision: 10.Nov.2021; -blockHandle = Simulink.findBlocks(model, 'Name', block); -set_param(blockHandle,'simout',['''',varname,'''']); -set_param(blockHandle,'fSample',num2str(fSample)); - -end - diff --git a/core/sensors/diffTransformer.slx b/core/sensors/diffTransformer.slx index 9a34813060b7dccc511f8fd643f4fd7b35929f81..0e93622c1954d149a468e702bed7c4608b40aa6b 100644 Binary files a/core/sensors/diffTransformer.slx and b/core/sensors/diffTransformer.slx differ diff --git a/core/sensors/lockIn.slx b/core/sensors/lockIn.slx index f1edbc9ea66c19178d5de0798ea2a87f8ad688a9..36884818b130d9520df787d7a4109d67d01a94ab 100644 Binary files a/core/sensors/lockIn.slx and b/core/sensors/lockIn.slx differ diff --git a/initAcme.m b/initAcme.m new file mode 100644 index 0000000000000000000000000000000000000000..d0dbcbcabebec8e4ff252f09001056d5e7427b24 --- /dev/null +++ b/initAcme.m @@ -0,0 +1,5 @@ +addpath(genpath(erase(mfilename('fullpath'),'initAcme'))); + +license('test', 'control_toolbox') +license('test', 'simulink_control_design') +license('test', 'LTPDA') diff --git a/simulations/Capacitance sensor/capSensor.slx b/simulations/Capacitance sensor/capSensor.slx new file mode 100644 index 0000000000000000000000000000000000000000..80c8293eb098eb7324d0658d8c315a141ec34c1d Binary files /dev/null and b/simulations/Capacitance sensor/capSensor.slx differ diff --git a/simulations/Capacitance sensor/capSensorSimplified.slx b/simulations/Capacitance sensor/capSensorSimplified.slx new file mode 100644 index 0000000000000000000000000000000000000000..85fe740d3ba75f2c0c479d46ce6daed831c94864 Binary files /dev/null and b/simulations/Capacitance sensor/capSensorSimplified.slx differ diff --git a/simulations/Capacitance sensor/script_capSensor.m b/simulations/Capacitance sensor/script_capSensor.m new file mode 100644 index 0000000000000000000000000000000000000000..4ea1849863b1a3d6e5ecb5546304b3f188ec47ac --- /dev/null +++ b/simulations/Capacitance sensor/script_capSensor.m @@ -0,0 +1,136 @@ +%% ACME - Capacitive Sensor Simulator +% All references are from Mance's 2012 thesis, unless otherwise noted. +% This model is calculated in the frequency range 1e-4 - 1Hz. Effects of the +% 100kHz injection signal are accounted for but the signal is not fully +% simulated. +% Arthur Reis, 13.10.2022 +clear; + +mdl = 'capSensor'; +load_system(mdl); +%% Simulation parameters +% frequency and time +stopTime = 1e4; +nSteps = 1e6; +tStep = stopTime/nSteps; +fSample = 1/(stopTime/nSteps); +t = (0:tStep:(stopTime-tStep))'; +enbw = 1/stopTime; +freq = logspace(-4,0,100); +% Physical constants +eps0 = 8.86e-12; %F/m, vacuum permittivity +kb = 1.3806e-23; %boltzmann +T = 300; % K + +%% Accelerometer Parameters +% TM, Ch.2 +TM_side = 0.046; %m, +mass = 2; %kg +nominal_gap = 0.004; % m +area = TM_side^2; %m2 + +% Capacitive sensing +nominal_cap = 1.15e-12;% F +Cmax = 0.12e-12; %Tab. B-1 +fTypical = 1e-2; %Hz + +%% Voltage Reference +Vd = 4.8; % Vpp, Ch. 2.6 +fDetection = 1e5; %Hz +capAttenuation = 0.123; %Eq 2.60, from ratio between injection +% and all other capacitances +VRefUNoiseASD = @(f) (125e-9.*f.^0) + 1.5e-7.*f.^-.5; %V/sqrt(Hz) +%Ch. 2.5, LT1021 datasheet +VRefUNoiseTS = [t timeseriesFromASD(VRefUNoiseASD, enbw, fSample, nSteps).Data]; +% DAC Noise - AD660 +DACNoiseASD = @(f) (0.125e-6.*f.^0) + 0.800e-6.*f.^-.5; %V/sqrt(Hz) +% AD660 20V span, int ref +DACNoiseTS = [t timeseriesFromASD(DACNoiseASD, enbw, fSample, nSteps).Data]; + +%% Capacitance Bridge +% Tab. B-1 +L = 4.2e-3; %H +Cp = 320e-12; %F +C0 = 1.15e-12; %Mance tab B1 ??? +Q = 200; %Mance tab B1 + +[brBlk, Zbr, f0br] = setCapBridge(mdl, 'capBridge', L, Cp, C0, Q); +% Bridge Impedance Thermal Noise - Mance 2012 eq 2.24 +brRThNoise = sqrt(4*kb*T*real(Zbr(f0br))); +brRThNoiseASD = @(f) brRThNoise.*f.^0; +brRThNoiseTS = [t timeseriesFromASD(brRThNoiseASD, enbw, fSample, nSteps).Data]; + +%% Transimpedance Amplifier +% Tab. B-1 +tiaCfb = 3.3e-12; %F +tiaRfb = 10e6; %ohm +%brR = real(brZ(fDetection)); +[tiaBlk, tiaZfb,tiaGs] = setTIA(mdl, 'TIAmp', Zbr(f0br), tiaCfb, tiaRfb); +%tiaR = real(tiaZfb(brf0)); + +% TIA Feedback Impedance Thermal Noise - Mance 2012 +tiaRfbThNoise = 2*sqrt(4*kb*T*real(tiaZfb(f0br))); %V,sqrt(hz) eq 2.94 +tiaRfbThNoiseASD = @(f) tiaRfbThNoise.*f.^0; +tiaRfbThNoiseTS = [t timeseriesFromASD(tiaRfbThNoiseASD, enbw, fSample, nSteps).Data]; + +% TIA Current Noise - eq 2.95 +tiaINoise = 2*1.6e-15*real(tiaZfb(f0br)); % tab B1 +tiaINoiseASD = @(f) tiaINoise.*f.^0; +tiaINoiseTS = [t timeseriesFromASD(tiaINoiseASD, enbw, fSample, nSteps).Data]; + +% TIA Voltage Noise - eq 2.95 +NGs = 1 + 2*abs(tiaZfb(f0br)/Zbr(f0br)); +tiaUNoise = 4.5e-9*NGs*sqrt(2); % tab B1 +tiaUNoiseASD = @(f) tiaUNoise.*f.^0; +tiaUNoiseTS = [t timeseriesFromASD(tiaUNoiseASD, enbw, fSample, nSteps).Data]; + + +%% AC amplifier +acGain = 45.4; % Ch. 2.8.5 +% amplifier voltage noise +acUNoise = 5.2e-9; %V/sqrt(Hz) tab 2.15 +acUNoiseASD = @(f) acUNoise.*f.^0; +acUNoiseTS = [t timeseriesFromASD(acUNoiseASD, enbw, fSample, nSteps).Data]; + +%% Demodulator +% DC amp voltage noise +dcampgain = 1.2; %calibrate so max +- 2.5V +DCampUNoiseASD = @(f) (0.03e-6.*f.^0) ; %V/sqrt(Hz) AD8629, mance +%DCampUNoiseASD = @(f) (14e-9.*f.^0) + 6.5e-9.*f.^-.7; %V/sqrt(Hz) OP97 (arbitrary) +DCampUNoiseTS = [t timeseriesFromASD(DCampUNoiseASD, enbw, fSample, nSteps).Data]; + +%% ADC +% quantization noise +ADCqNoiseASD = @(f) (2.4e-6.*f.^0) ; %V/sqrt(Hz) from eq 2.104 +ADCqNoiseTS = [t timeseriesFromASD(ADCqNoiseASD, enbw, fSample, nSteps).Data]; + +%% Noise Budget +% this uses the SimulinkNB toolbox. +% it doesn't run the simulation. Instead, it finds the transfer functions of the +% linearized model and plots the noise budged +[noises, sys] = nbFromSimulink(mdl, freq, 'dof', 'x'); +nb = nbGroupNoises(mdl, noises, sys); +matlabNoisePlot(nb); + +%% Time domain simulation +mdlOutput = sim(mdl); +% lpsd +Kdes = 100; +olap = 30; +Jdes = 1000; +Lmin = 1; +order = 0; + +[axx,fxx] = flpsd( 'ts', mdlOutput.simout.Data, 'fs', fSample, 'Kdes', Kdes, 'Lmin', Lmin, ... + 'Jdes', Jdes, 'win', 'hanning', 'olap', olap, 'order', order,... + 'scale', 'ASD', 'LTPDAmode',false); + +%% +% finding the TF between displacement readout and input perturbation +io(1) = linio(strcat(mdl,'/C1'),1,'input'); +io(2) = linio(strcat(mdl,'/Sum13'),1,'output'); +readout2capTF = getTFresponse(mdl, io, fxx); % TF between readout and acc signal + +loglog(fxx, axx./readout2capTF,'k','LineWidth',1); +xlabel('Frequency [Hz]'); +ylabel('Measured capacitance [F]'); \ No newline at end of file diff --git a/simulations/Capacitance sensor/script_capSensorSimplified.m b/simulations/Capacitance sensor/script_capSensorSimplified.m new file mode 100644 index 0000000000000000000000000000000000000000..d43f7e9c5ceb1c5fbfb887c75cfbb4cc18262e8e --- /dev/null +++ b/simulations/Capacitance sensor/script_capSensorSimplified.m @@ -0,0 +1,117 @@ +%% ACME - Simplified Capacitive Sensor Simulator +% All references are from Mance's 2012 thesis, unless otherwise noted. +% This model is calculated in the frequency range 1e-4 - 1Hz. Effects of the +% 100kHz injection signal are accounted for but the signal is not fully +% simulated. +% Only the dominant noise sources from the complete model are included +% Arthur Reis, 13.10.2022 +clear; + +mdl = 'capSensorSimplified'; +load_system(mdl); +%% Simulation parameters +% frequency and time +stopTime = 1e4; +nSteps = 1e6; +tStep = stopTime/nSteps; +fSample = 1/(stopTime/nSteps); +t = (0:tStep:(stopTime-tStep))'; +enbw = 1/stopTime; +freq = logspace(-4,0,100); +% Physical constants +eps0 = 8.86e-12; %F/m, vacuum permittivity +kb = 1.3806e-23; %boltzmann +T = 300; % K + +%% Accelerometer Parameters +% TM, Ch.2 +TM_side = 0.046; %m, +mass = 2; %kg +nominal_gap = 0.004; % m +area = TM_side^2; %m2 + +% Capacitive sensing +nominal_cap = 1.15e-12;% F +Cmax = 0.12e-12; %Tab. B-1 +fTypical = 1e-2; %Hz + +%% Voltage Reference +Vd = 4.8; % Vpp, Ch. 2.6 +fDetection = 1e5; %Hz +capAttenuation = 0.123; %Eq 2.60, from ratio between injection +% and all other capacitances +% DAC Noise - AD660 +DACNoiseASD = @(f) (0.125e-6.*f.^0) + 0.800e-6.*f.^-.5; %V/sqrt(Hz) +% AD660 20V span, int ref +DACNoiseTS = [t timeseriesFromASD(DACNoiseASD, enbw, fSample, nSteps).Data]; + +%% Capacitance Bridge +% Tab. B-1 +L = 4.2e-3; %H +Cp = 320e-12; %F +C0 = 1.15e-12; %Mance tab B1 ??? +Q = 200; %Mance tab B1 + +[brBlk, Zbr, f0br] = setCapBridge(mdl, 'capBridge', L, Cp, C0, Q); +% Bridge Impedance Thermal Noise - Mance 2012 eq 2.24 +brRThNoise = sqrt(4*kb*T*real(Zbr(f0br))); +brRThNoiseASD = @(f) brRThNoise.*f.^0; +brRThNoiseTS = [t timeseriesFromASD(brRThNoiseASD, enbw, fSample, nSteps).Data]; + +%% Amplifier +% arbitrary gain for the simplified model, adjust if needed +% output should be max around +-2.5V +ampgain = 100; +%% Noise Budget +% this uses the SimulinkNB toolbox. +% it doesn't run the simulation. Instead, it finds the transfer functions of the +% linearized model and plots the noise budged +[noises, sys] = nbFromSimulink(mdl, freq, 'dof', 'x'); +nb = nbGroupNoises(mdl, noises, sys); + +%% Time domain simulation +mdlOutput = sim(mdl); +% lpsd options +Kdes = 100; +olap = 30; +Jdes = 1000; +Lmin = 1; +order = 0; +% lpsd +[axx,fxx] = flpsd( 'ts', mdlOutput.simout.Data, 'fs', fSample, 'Kdes', Kdes, 'Lmin', Lmin, ... + 'Jdes', Jdes, 'win', 'hanning', 'olap', olap, 'order', order,... + 'scale', 'ASD', 'LTPDAmode',false); +%% Finding the transfer functions +% finding the transfer function between recorded signal and the signal we wish +% to measure +io(1) = linio(strcat(mdl,'/C1'),1,'input'); +io(2) = linio(strcat(mdl,'/Amp'),1,'output'); +readout2capTF = getTFresponse(mdl, io, fxx); % TF between readout and Cap1 +sensorTFexp = fit(fxx,readout2capTF, 'poly2') + +%% Expression for the total noise ASD +% assuming ASD = A/f + B, where B is the high freq limit +x = nb.sumNoise.f'; +y = nb.sumNoise.asd'; +sensorASDexp = fit(x,y, fittype(str2func(['@(a, x) a./x + ' num2str(y(end))]))) + +%from time domain simulation +xsim = fxx; +ysim = axx./readout2capTF; +sensorASDexpsim = fit(xsim,ysim, fittype(... + str2func(['@(a, x) a./x + ' num2str(ysim(end))]))) + +%% Plots +matlabNoisePlot(nb); +xlabel('Frequency [Hz]'); +ylabel('Measured capacitance [F]'); +loglog(freq, sensorASDexp(freq),'b.', 'displayName', 'Fit from lin model'); +loglog(freq, sensorASDexpsim(freq),'k.','displayName', 'Fit from sim'); +loglog(fxx, axx./readout2capTF,'k-','LineWidth',1,'DisplayName', ... + 'ASD from time domain simulation'); + +%% Finding the transfer functions +% lpsd +[axxs,fxxs] = flpsd( 'ts', mdlOutput.simout1.Data, 'fs', fSample, 'Kdes', Kdes, 'Lmin', Lmin, ... + 'Jdes', Jdes, 'win', 'hanning', 'olap', olap, 'order', order,... + 'scale', 'ASD', 'LTPDAmode',false); \ No newline at end of file diff --git a/simulations/Electrostatic/LISA_EA.slx b/simulations/Electrostatic/LISA_EA.slx new file mode 100644 index 0000000000000000000000000000000000000000..751e59f932cdd8d26704c6557669c5e754f47469 Binary files /dev/null and b/simulations/Electrostatic/LISA_EA.slx differ diff --git a/simulations/Electrostatic/LISA_EA_script.m b/simulations/Electrostatic/LISA_EA_script.m new file mode 100644 index 0000000000000000000000000000000000000000..33c8eddf7e6f2342608119d3836cd83b8bd7ade9 --- /dev/null +++ b/simulations/Electrostatic/LISA_EA_script.m @@ -0,0 +1,102 @@ +%% Electrostatic ACC Model +% Following the description in Davor Mance's 2012 thesis. References are from +% that, unless otherwise mentioned. The capacitance sensor model +% Author: Arthur Reis +% email: arthur.reis@aei.mpg.de +% last review: 19.10.2022 +clear; + +mdl = 'LISA_EA'; +load_system(mdl); + +%% Simulation parameters +% frequency and time +stopTime = 1e4; +nSteps = 1e6; +tStep = stopTime/nSteps; +fSample = 1/(stopTime/nSteps); +t = (0:tStep:(stopTime-tStep))'; +enbw = 1/stopTime; +freq = logspace(-4,0,100); +% Physical constants +eps0 = 8.86e-12; %F/m, vacuum permittivity +kb = 1.3806e-23; %boltzmann +T = 300; % K + + +%% Accelerometer Parameters (Ch.2) +% TM +l_TM = 0.046; %m, +mass = 2; %kg +gap0 = 0.004; % m +area = l_TM^2; %m2 + +dblint = setDblIntTrans(mdl, 'dblInt', mass, gap0); + +% Electrodes +% There are four electrodes, 2 on the faces on the cage, at potential -V and +V, +% and 2 faces of the TM, at same potential +% setElectrode(model, block, area, pos0, V_DC, [V_AC], [f], [solver]) +Vd = 5; %V detection rms voltage +Vp = 1; %V polarizing voltage +fCar = 1e5; +el1 = setElectrode(mdl,'electrode1',area,-(l_TM/2+gap0),0 ,0 ,fCar); %Cage left +el2 = setElectrode(mdl,'electrode2',area,-l_TM/2 ,Vp,Vd,fCar); %TM left +el3 = setElectrode(mdl,'electrode3',area,+l_TM/2 ,Vp,Vd,fCar); %TM right +el4 = setElectrode(mdl,'electrode4',area,+(l_TM/2+gap0),0 ,0 ,fCar); %Cage right + +% Plane capacitors, each formed by two electrodes +% setPlaneCapacitor(model, block, eps0) +cap1 = setPlaneCapacitor(mdl, 'planeCapacitor1', eps0); +cap2 = setPlaneCapacitor(mdl, 'planeCapacitor2', eps0); +capSensorGain = 1.8e13; +capSensorNoiseASD = @(f) 5.0124e-19 + 1.852e-22./f; +capSensorNoiseTS = [t timeseriesFromASD(capSensorNoiseASD, enbw, fSample, nSteps).Data]; +% Capacitive sensing +nominal_cap = 1.15e-12;% F +Cmax = 0.12e-12; %Tab. B-1 +fTypical = 1e-2; %Hz + +% Control +Kp = 1; +Ki = 0; +Kd = 0; +driverGain = 1; + +%% Simulating +mdlOutput = sim(mdl); + +%% Analysing the spectrum + +[axx,fxx] = flpsd('ts', mdlOutput.simout.Data, 'fs', fSample, 'Kdes', 100, ... + 'Lmin', 1, 'Jdes', 1000, 'win', 'hanning', 'olap', 30, ... + 'order', 0, 'scale', 'ASD', 'LTPDAmode', false); + +% Comparing the results +% Capacitance sensor +io(1) = linio(strcat(mdl,'/Minus1'),1,'input'); +io(2) = linio(strcat(mdl,'/simplifiedCapSensor'),1,'output'); +readout2capTF = getTFresponse(mdl, io, fxx); % TF between readout and acc signal +figure(1); +loglog(fxx,axx./readout2capTF,fxx,capSensorNoiseASD(fxx),'linewidth',2); +legend('Simulated measurement','Simulated white noise input'); +xlabel('Frequency [Hz]'); +ylabel('Capacitance [F]'); + +% Accelerometer readout +io(1) = linio(strcat(mdl,'/Gain'),1,'input'); +io(2) = linio(strcat(mdl,'/simplifiedCapSensor'),1,'output'); +readout2accTF = getTFresponse(mdl, io, fxx); % TF between readout and acc signal +figure(2); +loglog(fxx,axx./readout2accTF); +legend('Simulated measurement','Simulated white noise input'); +xlabel('Frequency [Hz]'); +ylabel('Acceleration [m/s2]'); + +%% +dof = 'x'; +[noises, sys] = nbFromSimulink(mdl, freq, 'dof', dof); +nb = nbGroupNoises(mdl, noises, sys); +matlabNoisePlot(nb); +%loglog(fxx, axx./readout2accTF) + diff --git a/simulations/Tutorial/ex_01.slx b/simulations/Tutorial/ex_01.slx deleted file mode 100644 index 89bd4575d959ac512c91afd3408fe64c853151f6..0000000000000000000000000000000000000000 Binary files a/simulations/Tutorial/ex_01.slx and /dev/null differ diff --git a/simulations/Tutorial/ex_01_time_domain.slx b/simulations/Tutorial/ex_01_time_domain.slx new file mode 100644 index 0000000000000000000000000000000000000000..66e3ca05c3b6f3b957753361cef804ca72bfb391 Binary files /dev/null and b/simulations/Tutorial/ex_01_time_domain.slx differ diff --git a/simulations/Tutorial/ex_02.slx b/simulations/Tutorial/ex_02.slx deleted file mode 100644 index 76c9015dc4d5011469faeab3a36faab0feff482b..0000000000000000000000000000000000000000 Binary files a/simulations/Tutorial/ex_02.slx and /dev/null differ diff --git a/simulations/Tutorial/ex_02_noise_generation.slx b/simulations/Tutorial/ex_02_noise_generation.slx new file mode 100644 index 0000000000000000000000000000000000000000..cb183cf2834c35055747d1653eddf76a3a69fd8e Binary files /dev/null and b/simulations/Tutorial/ex_02_noise_generation.slx differ diff --git a/simulations/Tutorial/ex_03.slx b/simulations/Tutorial/ex_03.slx deleted file mode 100644 index a6b80054af0eef0a7661e48ea0cba06f1b52dfaa..0000000000000000000000000000000000000000 Binary files a/simulations/Tutorial/ex_03.slx and /dev/null differ diff --git a/simulations/Tutorial/ex_03_parametrization.slx b/simulations/Tutorial/ex_03_parametrization.slx new file mode 100644 index 0000000000000000000000000000000000000000..3bbc5b56a10c64f57c6391334920fafb9945baf7 Binary files /dev/null and b/simulations/Tutorial/ex_03_parametrization.slx differ diff --git a/simulations/Tutorial/ex_04.slx b/simulations/Tutorial/ex_04.slx deleted file mode 100644 index dd6be9470bcc5a8c14934929eba57473184d46cb..0000000000000000000000000000000000000000 Binary files a/simulations/Tutorial/ex_04.slx and /dev/null differ diff --git a/simulations/Tutorial/ex_04_noisy_sensor.slx b/simulations/Tutorial/ex_04_noisy_sensor.slx new file mode 100644 index 0000000000000000000000000000000000000000..42f556802e4e4d75338956c48beb973eedc234ad Binary files /dev/null and b/simulations/Tutorial/ex_04_noisy_sensor.slx differ diff --git a/simulations/Tutorial/ex_05a_noise_budget.slx b/simulations/Tutorial/ex_05a_noise_budget.slx new file mode 100644 index 0000000000000000000000000000000000000000..c7a137633a5577d8d7241a62ebe79974c204b351 Binary files /dev/null and b/simulations/Tutorial/ex_05a_noise_budget.slx differ diff --git a/simulations/Tutorial/ex_05b_noisebudget.slx b/simulations/Tutorial/ex_05b_noisebudget.slx new file mode 100644 index 0000000000000000000000000000000000000000..89420ac7929289a1d74c001ee97bcb3f10c4b430 Binary files /dev/null and b/simulations/Tutorial/ex_05b_noisebudget.slx differ diff --git a/simulations/Tutorial/script_ex_01.m b/simulations/Tutorial/script_ex_01_time_domain.m similarity index 89% rename from simulations/Tutorial/script_ex_01.m rename to simulations/Tutorial/script_ex_01_time_domain.m index 34a6dfaf5e7277de7dc7c20b9b875244026b4774..e5666fe852c35ba4066eba4ee7478abe2374fb62 100644 --- a/simulations/Tutorial/script_ex_01.m +++ b/simulations/Tutorial/script_ex_01_time_domain.m @@ -7,12 +7,12 @@ clear; % load the simulink model. -mdl = 'ex_01'; +mdl = 'ex_01_time_domain'; load_system(mdl); acme_dt_fixedstep = 0.01; stopTime = 10; -%% Setting the TM and control parameters +%% Setting the TM and control parameters mass = 0.08; %kg gap = 0.0003; %m % To set the block, the setter searches for a block named "dblInt" on the @@ -27,18 +27,20 @@ Kd = 1; % and the TM is impacted by an impulse of forceGain = 1e-6; % N + %% Run the simulation sim(mdl); open_system([mdl '/scopeAcc']); open_system([mdl '/scopePos']); - -%% -% other than an external input, we can simulate a TM that begins out of + +%% Simulate again +% other than an external input, we can also simulate a TM that begins out of % equilibrium forceGain = 0; x0 = 0.00005; dx0 = 0; dblint = setDblIntTrans(mdl, 'dblInt', mass, gap, x0, dx0); + sim(mdl); open_system([mdl '/scopePos']); diff --git a/simulations/Tutorial/script_ex_02.m b/simulations/Tutorial/script_ex_02_noise_generation.m similarity index 89% rename from simulations/Tutorial/script_ex_02.m rename to simulations/Tutorial/script_ex_02_noise_generation.m index 461ba7dc00247d956d809e629f33bea3b20b1ee2..830f83aab305ff2246b58f33ca16f828e3460e73 100644 --- a/simulations/Tutorial/script_ex_02.m +++ b/simulations/Tutorial/script_ex_02_noise_generation.m @@ -4,7 +4,7 @@ % parametrize your simulation clear; -mdl = 'ex_02'; +mdl = 'ex_02_noise_generation'; load_system(mdl); %% Setting the TM and control parameters @@ -18,7 +18,7 @@ dblint = setDblIntTrans(mdl, 'dblInt', mass, gap); %% Define the input noise % Will add a timeseries containing noise -% Automatically generated from expression for Amplitude Spectral Density +% generated from expression for Amplitude Spectral Density tslength = 1e4; dt = 1; @@ -28,10 +28,10 @@ nSteps = length(t); fSample = 1/dt; enbw = 1/tslength; -% Consider one of the ASDs: +% Consider the ASD: noisefunc = @(f) (1e-10 * sqrt( (1e-3./f).^4 ./ ((1e-5./f).^4+1) + 1 + (f/1e-1).^4)); -% define a "From Workspace" Block that reads the variable: +% define a "From Workspace" Block that contains the variable: noise_ts = [t timeseriesFromASD(noisefunc, enbw, fSample, nSteps).Data]; %% Run @@ -63,7 +63,7 @@ readout2accTF = getTFresponse(mdl, io, fxx); % TF between readout and acc signal %% output comparison loglog(fxx,noisefunc(fxx),fxx,axx./readout2accTF); -legend('input expression','calibrated acc measurement'); +legend('input expression','simulated measurement'); xlabel('Frequency [Hz]'); xlim([1e-6 1]); ylabel('Acceleration [m/s2]'); @@ -93,4 +93,5 @@ end loglog(frqs, amps./cals); legend(string(mass_var)); xlabel('Frequency [Hz]'); -ylabel('Acceleration [m/s2]'); \ No newline at end of file +ylabel('Acceleration [m/s2]'); +% nothing happens in an ideal, noiseless instrument \ No newline at end of file diff --git a/simulations/Tutorial/script_ex_03.m b/simulations/Tutorial/script_ex_03_parametrization.m similarity index 82% rename from simulations/Tutorial/script_ex_03.m rename to simulations/Tutorial/script_ex_03_parametrization.m index 9fdb84722d9d5361565110759888984756b981be..9955c08d6fb43a7155888d406a68a1088409a025 100644 --- a/simulations/Tutorial/script_ex_03.m +++ b/simulations/Tutorial/script_ex_03_parametrization.m @@ -4,7 +4,7 @@ % it uses the block name to locate and initialize the right one clear; -mdl = 'ex_03'; +mdl = 'ex_03_parametrization'; load_system(mdl); fMin = 1e-4; @@ -27,6 +27,14 @@ Kp = [0.04, 0.05, 0.06]; Ki = [0.003, 0.003, 0.003]; Kd = [0.1, 0.1, 0.12]; +for i = 1:3 + % the blocks should be carefully named, as the setting functions will use + % that name + setDblIntTrans(mdl, ['dblInt' num2str(i)], mass(i), gap(i)); + setPID(mdl, ['pid' num2str(i)], Kp(i), Ki(i), Kd(i)); +end + + % Consider the ASDs: noisefunc1 = @(f) 1e-12 * f.^-1; noisefunc2 = @(f) 1e-10 * (f.^2 + f.^0); @@ -47,10 +55,10 @@ noise_ts2 = [t timeseriesFromASD(noisefunc2, enbw, fSample, nSteps).Data]; 'Jdes', Jdes, 'win', 'hanning', 'olap', olap, 'order', order,... 'scale', 'ASD', 'LTPDAmode',true); loglog(fxx,axx,fxx2,axx2); +legend('noise1 asd', 'noise2 asd'); %% Run sim(mdl); open_system([mdl '/Scope1']); open_system([mdl '/Scope2']); -open_system([mdl '/Scope3']); - +open_system([mdl '/Scope3']); \ No newline at end of file diff --git a/simulations/Tutorial/script_ex_04.m b/simulations/Tutorial/script_ex_04.m deleted file mode 100644 index ac95d7bbddce72a703ec86da9d1699f32032f12e..0000000000000000000000000000000000000000 --- a/simulations/Tutorial/script_ex_04.m +++ /dev/null @@ -1,100 +0,0 @@ -%% Example 04 -% ACME Advanced - GRACE-like Electrostatic ACC -% The capacitive sensing as well as the electrostatic actuators are simulated -clear; - -mdl = 'ex_04'; -load_system(mdl); -%% Accelerometer Parameters -% TM -TM_side = 0.04; % m -nominal_gap = 0.000300; % m -area = (TM_side)^2; % m2 -mass = 0.08; % kg -kb = 1.3806e-23; %boltzmann -T = 300; % K - -% capacitive sensing, see Josselin 1999 -eps0 = 8.86e-12; %F/m, vacuum permittivity -Vd = 5; %V detection rms voltage -Vp = 10; %V polarizing voltage -Vt = sqrt(Vp^2 + Vd^2); -L = 50; -C0 = 5e-13; -Cp = 5e-13; -Q = 200; -fDetection = 1e5; -lockgain = 1; - -% control -Kp = 5e-4; -Ki = 1e-2; -Kd = 0; -driverGain = 1; - -%% block initialization -% there are four electrodes, 2 on the faces on the cage, at potential -V and +V, -% and 2 faces of the TM, at same potential -% -% setElectrode(model, block, Vbias, ... -% pos0, area) -el1 = setElectrode(mdl,'electrode1', 0, ... - TM_side/2+nominal_gap, area); % cage right -el2 = setElectrode(mdl,'electrode2', Vt, ... - TM_side/2, area); % TM right -el3 = setElectrode(mdl,'electrode3', Vt, ... - -TM_side/2, area); % TM left -el4 = setElectrode(mdl,'electrode4', 0, ... - -(TM_side/2+nominal_gap), area); % cage left - -% plane capacitors, each formed by two electrodes, simplified coulombic interaction -% setPlaneCapacitor(model, block, eps0) -cap1 = setPlaneCapacitor(mdl, 'planeCapacitor1', eps0); -cap2 = setPlaneCapacitor(mdl, 'planeCapacitor2', eps0); - -% differential transformer, see Josselin 1999 -% setDiffTransformer(model, block, C0, L, f0, Q, range) -dfTr = setDiffTransformer(mdl, 'diffTransformer', C0, L, fDetection, Q); - -dblint = setDblIntTrans(mdl, 'dblInt', mass, nominal_gap); - -%% simulation parameters -% frequency and time -stopTime = 1e3; -nSteps = 1e4; -tStep = stopTime/nSteps; -acme_dt_fixedstep = tStep; -fSample = 1/(stopTime/nSteps); -%fMax = fSample/2; -%fMin = 1/stopTime; -t = (0:tStep:(stopTime-tStep))'; -enbw = 1/stopTime; - -noisefunc = @(f) (1e-9 * f.^0); -noise_ts1 = [t timeseriesFromASD(noisefunc, enbw, fSample, nSteps).Data]; - -%% -mdlOutput = sim(mdl); -%% -% lpsd options - -Kdes = 100; -olap = 30; -Jdes = 1000; -Lmin = 1; -order = 0; - -[axx,fxx] = flpsd( 'ts', mdlOutput.simout.Data, 'fs', fSample, 'Kdes', Kdes, 'Lmin', Lmin, ... - 'Jdes', Jdes, 'win', 'hanning', 'olap', olap, 'order', order,... - 'scale', 'ASD', 'LTPDAmode',false); - -%% -% finding the TF between displacement readout and input perturbation -io(1) = linio(strcat(mdl,'/From Workspace'),1,'input'); -io(2) = linio(strcat(mdl,'/diffTransformer'),1,'output'); -readout2accTF = getTFresponse(mdl, io, fxx); % TF between readout and acc signal - -loglog(fxx,axx./readout2accTF,fxx,noisefunc(fxx)); -legend('calibrated acc measurement','input expression'); -xlabel('Frequency [Hz]'); -ylabel('Acceleration [m/s2]'); diff --git a/simulations/Tutorial/script_ex_04_noisy_sensor.m b/simulations/Tutorial/script_ex_04_noisy_sensor.m new file mode 100644 index 0000000000000000000000000000000000000000..cc225d32797d8cc0181ef8c91894fd3502e9bf60 --- /dev/null +++ b/simulations/Tutorial/script_ex_04_noisy_sensor.m @@ -0,0 +1,97 @@ +%% Example 04 +% ACME Advanced - GRACE-like Electrostatic ACC +% The capacitive sensing as well as the electrostatic actuators are simulated +clear; + +mdl = 'ex_04_noisy_sensor'; +load_system(mdl); + +%% Simulation parameters +% frequency and time +stopTime = 1e4; +nSteps = 1e6; +tStep = stopTime/nSteps; +fSample = 1/(stopTime/nSteps); +t = (0:tStep:(stopTime-tStep))'; +enbw = 1/stopTime; +freq = logspace(-4,0,100); +% Physical constants +eps0 = 8.86e-12; %F/m, vacuum permittivity +kb = 1.3806e-23; %boltzmann +T = 300; % K + + +%% Accelerometer Parameters (Ch.2) +% TM +l_TM = 0.046; %m, +mass = 2; %kg +gap0 = 0.004; % m +area = l_TM^2; %m2 + +dblint = setDblIntTrans(mdl, 'dblInt', mass, gap0); + +% Electrodes +% There are four electrodes, 2 on the faces on the cage, at potential -V and +V, +% and 2 faces of the TM, at same potential +% setElectrode(model, block, area, pos0, V_DC, [V_AC], [f], [solver]) +Vd = 5; %V detection rms voltage +Vp = 1; %V polarizing voltage +fCar = 1e5; +el1 = setElectrode(mdl,'electrode1',area,-(l_TM/2+gap0),0 ,0 ,fCar); %Cage left +el2 = setElectrode(mdl,'electrode2',area,-l_TM/2 ,Vp,Vd,fCar); %TM left +el3 = setElectrode(mdl,'electrode3',area,+l_TM/2 ,Vp,Vd,fCar); %TM right +el4 = setElectrode(mdl,'electrode4',area,+(l_TM/2+gap0),0 ,0 ,fCar); %Cage right + +% Plane capacitors, each formed by two electrodes, simplified coulombic interaction +% setPlaneCapacitor(model, block, eps0) +cap1 = setPlaneCapacitor(mdl, 'planeCapacitor1', eps0); +cap2 = setPlaneCapacitor(mdl, 'planeCapacitor2', eps0); +capSensorGain = 1.8e13; +capSensorNoiseASD = @(f) 5.0124e-19 + 1.852e-22./f; +capSensorNoiseTS = [t timeseriesFromASD(capSensorNoiseASD, enbw, fSample, nSteps).Data]; +% Capacitive sensing +nominal_cap = 1.15e-12;% F +Cmax = 0.12e-12; %Tab. B-1 +fTypical = 1e-2; %Hz + +% Control +Kp = 1; +Ki = 0; +Kd = 0; +driverGain = 1; + +%% Simulating +mdlOutput = sim(mdl); +%% Analysing the spectrum +% lpsd options + +Kdes = 100; +olap = 30; +Jdes = 1000; +Lmin = 1; +order = 0; + +[axx,fxx] = flpsd( 'ts', mdlOutput.simout.Data, 'fs', fSample, 'Kdes', Kdes, 'Lmin', Lmin, ... + 'Jdes', Jdes, 'win', 'hanning', 'olap', olap, 'order', order,... + 'scale', 'ASD', 'LTPDAmode',false); + +%% Comparing the results +% Capacitance sensor +io(1) = linio(strcat(mdl,'/Minus1'),1,'input'); +io(2) = linio(strcat(mdl,'/simplifiedCapSensor'),1,'output'); +readout2capTF = getTFresponse(mdl, io, fxx); % TF between readout and acc signal +figure(1); +loglog(fxx,axx./readout2capTF,fxx,capSensorNoiseASD(fxx),'linewidth',2); +legend('Simulated measurement','Simulated white noise input'); +xlabel('Frequency [Hz]'); +ylabel('Capacitance [F]'); + +% Accelerometer readout +io(1) = linio(strcat(mdl,'/Minus1'),1,'input'); +io(2) = linio(strcat(mdl,'/Minus'),1,'output'); +readout2accTF = getTFresponse(mdl, io, fxx); % TF between readout and acc signal +figure(2); +loglog(fxx,axx./(mass*readout2accTF)); +legend('Simulated measurement','Simulated white noise input'); +xlabel('Frequency [Hz]'); +ylabel('Acceleration [m/s2]'); diff --git a/simulations/Tutorial/script_ex_05_noise_budget.m b/simulations/Tutorial/script_ex_05_noise_budget.m new file mode 100644 index 0000000000000000000000000000000000000000..2ab177affb91a3df4c2f997c9f547bb9552dd60f --- /dev/null +++ b/simulations/Tutorial/script_ex_05_noise_budget.m @@ -0,0 +1,31 @@ +%% Example 07 +% Simulink Noise Budget +% These blocks are from https://github.com/cwipf/SimulinkNb +clear; + +mdl = 'ex_05a_noise_budget'; +load_system(mdl); +%% Accelerometer Parameters +% TM +mass = 1; % kg + +% control +Kp = 1; +Ki = 0; +Kd = 0; + +%% simulation parameters +% there is a difference between open and closed loop sink +freq = logspace(-2, 0, 100); +sensorNoiseASD = 1e-9 * freq.^-1; +dof = 'x'; +%% +[noises, sys] = nbFromSimulink(mdl, freq, 'dof', dof); +nb = nbGroupNoises(mdl, noises, sys); +matlabNoisePlot(nb); + +%% +mdl = 'ex_05b_noise_budget'; +[noises, sys] = nbFromSimulink(mdl, freq, 'dof', dof); +nb = nbGroupNoises(mdl, noises, sys); +matlabNoisePlot(nb); \ No newline at end of file diff --git a/simulations/Tutorial/xhps_integration/init_parameters.m b/simulations/Tutorial/xhps_integration/init_parameters.m deleted file mode 100644 index e23d5833d751973db168a6dbe45117ec6f7bd148..0000000000000000000000000000000000000000 --- a/simulations/Tutorial/xhps_integration/init_parameters.m +++ /dev/null @@ -1,259 +0,0 @@ -%% ex3 -% In this example additional blocks to model non-gravitational -% forces are added, atmospheric drag and solar radiation pressure. The -% computed forces and torques are feed back to the dynamics computatation. -% These models utilize the precomputed lookup tables for high precision -% disturbance modeling. As an example these are given for a simple GRACE -% model. -% There are two different blocks for atmospheric drag, the first one is -% simpler and utilzes a constant drag coefficient and the JB08 density -% model. The atmosphere is treated as co-rotating with the Earth. -% The second block utilizes a variable computation of the drag and lift -% coefficients. Depending on atmosphereic conditions and the satellite -% geometry (FE Model). The computation of the drag coefficient needs inputs -% from the NRLMSISE atmosphere model wich is additionally executed in the -% block. -% Like all Simulink elements, the blocks can be commented-out and -on by -% pressing ctrl + shift + x. -% All necessary parameters are set at the end of this file. - - -% The ordering of variables in the core_params and init_params structs may -% not be changed! This will cause errors in the underlying C-functions. - -clearvars('core_params','init_params'); - -%% core_params - - init_date = [2006,5,1,0,0,1]; - - % =============================== - % PLEASE UNCOMMENT THIS LINE - MJD = HPS_convertCalendarDate2MJD(init_date(1),init_date(2),init_date(3),init_date(4),init_date(5),init_date(6)); - % ==================================================== - core_params.start_date = [MJD,init_date(4:6)]; - -% GRAVITY OPTIONS - - % Gravity Model (simple (1), static spherical harmonics Gravity model (2), time dependent SH model (3)) - core_params.i_grav_model = 2; - % degree and order of gravity field (iN_max (degree) must be bigger or equal iM_max (order)) - core_params.iN_max = 12; - core_params.iM_max = 12; % also zonal degree (up to 6) for simple gravity model (than iM_max=1) - - % Ocean tide model (off (0), on (1)) - core_params.ocean_tides = 0; - % degree = order - core_params.ot_degree = 5; - - % Solid Earth tide model (off (0), with "zero tide" (1), with "tide free" (2) (default:1)) - core_params.solid_Earth_tides = 0; - % degree = order (min 2, maximal 4) - core_params.sEt_degree = 4; - - % Pole tide model (off (0), on (1)) - core_params.pole_tides = 0; - % degree = order (maximal 360) (actually d/o of pole ocean tide model, - % pole Earth tide model just affects the C21 and S21 SH coefficients) - core_params.pt_degree = 60; - - % Calculate gravity gradient matrix? (0 = no, 1 = yes) - core_params.i_gg = 0; - % effects of center of gravity != center of mass (0: off,1: spherical potential, 2: J2 potential) - core_params.i_cog = 0; - % post newtonian corrections to equations of motion (0: off, 1: add Schwarzschild corr., 2: (1)+Lense-Thirring corr., 3: (2)+ de Sitter corr.) - core_params.i_pN = 0; - % calculate gravity gradient torque (0: do not calc, 1: spherical pot. 2: with Gravity gradient matrix) - core_params.i_ggt = 0; - - % Chose ehpemeris model; analytical or JPL models (1: Analytical Montenbruck, 2: DE405, 3: DE430, 4: DE431) - core_params.ehp_model = 1; - - % include moon, planets (0 do not calculate, 1 calculate) - core_params.i_planets(1)=0; % sun - core_params.i_planets(2)=0; % mercury - core_params.i_planets(3)=0; % venus - core_params.i_planets(4)=0; % mars - core_params.i_planets(5)=0; % jupiter - core_params.i_planets(6)=0; % saturn - core_params.i_planets(7)=0; % uranus - core_params.i_planets(8)=1; % neptune - core_params.i_planets(9)=0; % pluto - core_params.i_planets(10)=0; % moon - - - % IERS2010 convention (0: compleat trafo, 1: in future setimated EOP, 2: z-onlyrotation, 3: GeoQ rotation) - core_params.T_e_i_opt = 0; - -% INTEGRATION OPTIONS - - % Integration time limit (integrate until tmax) - core_params.tmax = 18000; - - % step size of simulink simulation [s] - core_params.dt_sim = acme_dt_fixedstep; - - % integration method (0: runge-kutta dopri87 8th order (13 function evaluation), 1: runge-kutta ck54 5th order (6 function evaluation), 2: Adams-Bashforth-Moulton ABM one predictor and one corrector step (2 function evaluation); order specified by core_params.AMB_order ) - core_params.int_meth = 2; - - % only if ABM integrator is chosen - % order of ABM integrator, possible:2, 3, 4, 6, 8, 10, 12, 16, 18, 20, 24, 28 (1 is equal to simple euler scheme -> does not work conflict with loop indices!!!!) - core_params.ABM_order = 8; - - % For Runge Kutta Integrators and initialization of ABM integrator with DoPri87: - % local truncation error between two steps - core_params.eps = 1e-2; - % minimal time step allowed for step size control (if smaller step is proposed h set to hmin) - core_params.hmin = 0.5; - %first step size - core_params.h0 = core_params.dt_sim; - - % just for RKF methods - % option when T_e_i should be updated (0: just after every step in main - % integration loop 1: also inside the integration routine 2: use - % simplified T_e_i computation inside integration routine) 3: just - % every dt_sim time step - core_params.update_T_e_i = 2; - % option when gravity field should be updated (like T_e_i) (0: just - % after every step in main integration loop 1: also inside the - % integration routine 3: just every dt_sim time step (10: no update -> set accordingly in check_params.m) - core_params.update_gfc = 0; - - -% OUTPUT OPTIONS - - % output T_e_i Matrix (0: no 1: output) - core_params.T_e_i = 1; - - % option if position and velocity should be also transformed and saved in ECEF coordinates (0:off, 1: on) - core_params.save_ECEF = 1; - - % output sub steps in one dt_sim step just for RK methods (0: no, 1: output) - core_params.n_h =0; - - % output gravity gradient torque (0: no 1: output ggt is computed in next step so the output is delayed by one dt_sim time step - % 2: calculate ggt of actual step -> computationally more intensive because one more call of gravityfield) - core_params.output_ggt = 1; - - % output ephemeris (0: nein 1: ausgeben) - core_params.output_ehpemeris = 1; - % output ephemeris from which planets - - core_params.outp_eph_planets(1)=1; % sun - core_params.outp_eph_planets(2)=0; % mercury - core_params.outp_eph_planets(3)=0; % venus - core_params.outp_eph_planets(4)=0; % mars - core_params.outp_eph_planets(5)=0; % jupiter - core_params.outp_eph_planets(6)=0; % saturn - core_params.outp_eph_planets(7)=0; % uranus - core_params.outp_eph_planets(8)=0; % neptune - core_params.outp_eph_planets(9)=0; % pluto - core_params.outp_eph_planets(10)=0; % moon - - -% ADDITIONAL PARAMETERS - - % show integration status info (0: no info, 1: some 2: detailed info) - core_params.int_sts =1; - - % number of states (computed in mdlInizialize?!) - core_params.n = 13; - - -clear init_params -%% init_params -% parameter für mdlInitialize - - % Initial conditions (position and velocity) in eci (0) or in ecef (1) frame - init_params.frame = 1; - - init_params.y0(1)=0.883400652246999e-3; % w_x - init_params.y0(2)=0.679655234847646e-3; - init_params.y0(3)=0.018533696711896e-3; - - init_params.y0(4)=0.420661638681150; %q_1 - init_params.y0(5)= -0.215279353484945; - init_params.y0(6)= 0.792394972557636; - init_params.y0(7)= 0.385757427887756; - - % Initial GRACE values in ecef (polar orbit) - init_params.y0(8)= 2495.25780467829; - init_params.y0(9)= 3405.71999114539; - init_params.y0(10)= 6337.46591402429; - - init_params.y0(11)= 3084754.04939809; %x - init_params.y0(12)= 4802725.19816482; %y - init_params.y0(13)=-3808582.60527389; %z - - - %% check consistency of parameters - %core_params = HPS_check_params(core_params); - -%% Control law - -% simple quaternion control law -I = [1 0 0;... - 0 1 0;... - 0 0 1]; - -k = 2; % "geschwindigkeit" -K = k*I; - -c = 2; % "stärke" -C= c*I; - -% constant flight path angle cFPA: -phi1 = pi/180*0; -phi2 = pi/180*-1; -phi3 = pi/180*0; - -% compute quaternion for constant trafo from body frame -% =============================== - % PLEASE UNCOMMENT THIS LINES -% T_v_d = HPS_computeDCMFromEulerAngles( phi1, phi2, phi3, 123); -% q_v_d = HPS_computeQuaternionFromDCM(T_v_d); -% ==================================== - -%% Environment models - -% Additional values for C_d, C_l computation -Y1 = init_date(1)-1; -Y2 = init_date(1)+1; - -% Set C_D options -a_ref_opt = 1; -alpha_opt = 1; -alpha_val = 1; - -et = load('surface_tables/et.txt'); -nt = load('surface_tables/nt.txt'); - -% in case constant wall temp is assumed -n_elem = size(et,1); -T_Wall_const = ones(n_elem,1).*300; - -% Drag Coefficient -c_D = 2.5; - -% atmospheric indices -path_F107 = fullfile(XHPS_path, 'HPS_simulation', 'environment_data', 'activity_indices', 'FLUX', 'F107.txt'); -path_Ap = fullfile(XHPS_path, 'HPS_simulation', 'environment_data', 'activity_indices', 'KP_AP', 'Ap.txt'); - -% load satellite data for surface forces -load('surface_tables/angle_phi.txt'); -load('surface_tables/angle_tht.txt'); -load('surface_tables/force_FX.txt'); -load('surface_tables/force_FY.txt'); -load('surface_tables/force_FZ.txt'); -load('surface_tables/prespoint_X.txt'); -load('surface_tables/prespoint_Y.txt'); -load('surface_tables/prespoint_Z.txt'); -load('surface_tables/ref_area.txt'); -load('surface_tables/torque_TX.txt'); -load('surface_tables/torque_TY.txt'); -load('surface_tables/torque_TZ.txt'); - -% 3 dimensional L array containing absorption coefficients for each element -load('L3d.mat'); -elements_fe = 1:size(L3d,3); - diff --git a/simulations/Tutorial/xhps_integration/script_xhps_acme_01.m b/simulations/Tutorial/xhps_integration/script_xhps_acme_01.m deleted file mode 100644 index ce5a26f2826543ad0d4ae21f8079a2af20ead395..0000000000000000000000000000000000000000 --- a/simulations/Tutorial/xhps_integration/script_xhps_acme_01.m +++ /dev/null @@ -1,96 +0,0 @@ -%% Example Accelerometer -% Using ACME and XHPS together -% Using fixed-step solvers -clear; - -% =============================== - % PLEASE UNCOMMENT THIS LINE - hps_startup - % ============================= -mdl = 'xhps_acme_ex_01'; -load_system(mdl); - -%% Setting the TM and control parameters -mass = 0.08; %kg -gap = 0.0003; %m -M_sat = 478; % define the mass of the satellite (typical number for GRACE-FO) - -dblint = setDblIntTrans(mdl, 'dblInt', mass, gap); - -acme_dt_fixedstep = 1; - -init_parameters; - -I = [1 0 0;... - 0 1 0;... - 0 0 1]; - -k = 2; % "geschwindigkeit" -K = k*I; - -c = 2; % "stärke" -C= c*I; - -% constant flight path angle cFPA: -phi1 = pi/180*0; -phi2 = pi/180*-1; -phi3 = pi/180*0; - -% compute quaternion for constant trafo from body frame -T_v_d = HPS_computeDCMFromEulerAngles( phi1, phi2, phi3, 123); -q_v_d = HPS_computeQuaternionFromDCM(T_v_d); - -%% Environment models - -% Additional values for C_d, C_l computation - - init_date = [2006,5,1,0,0,1]; -Y1 = init_date(1)-1; -Y2 = init_date(1)+1; - -% Set C_D options -a_ref_opt = 1; -alpha_opt = 1; -alpha_val = 1; - -et = load('surface_tables/et.txt'); -nt = load('surface_tables/nt.txt'); - -% in case constant wall temp is assumed -n_elem = size(et,1); -T_Wall_const = ones(n_elem,1).*300; - -% Drag Coefficient -c_D = 2.5; - -% atmospheric indices -path_F107 = fullfile(XHPS_path, 'HPS_simulation', 'environment_data', 'activity_indices', 'FLUX', 'F107.txt'); -path_Ap = fullfile(XHPS_path, 'HPS_simulation', 'environment_data', 'activity_indices', 'KP_AP', 'Ap.txt'); - -% load satellite data for surface forces -load('surface_tables/angle_phi.txt'); -load('surface_tables/angle_tht.txt'); -load('surface_tables/force_FX.txt'); -load('surface_tables/force_FY.txt'); -load('surface_tables/force_FZ.txt'); -load('surface_tables/prespoint_X.txt'); -load('surface_tables/prespoint_Y.txt'); -load('surface_tables/prespoint_Z.txt'); -load('surface_tables/ref_area.txt'); -load('surface_tables/torque_TX.txt'); -load('surface_tables/torque_TY.txt'); -load('surface_tables/torque_TZ.txt'); - -% 3 dimensional L array containing absorption coefficients for each element -load('L3d.mat'); -elements_fe = 1:size(L3d,3); - -init_parameters %XHPS stuff -acme_dt_fixedstep = core_params.dt_sim; -%% -sim(mdl) - - - - - diff --git a/simulations/Tutorial/xhps_integration/xhps_acme_ex_01.slx b/simulations/Tutorial/xhps_integration/xhps_acme_ex_01.slx deleted file mode 100644 index ff2529cb060b48c931143d2e5b7f53cadcb7e27e..0000000000000000000000000000000000000000 Binary files a/simulations/Tutorial/xhps_integration/xhps_acme_ex_01.slx and /dev/null differ diff --git a/utils/SimulinkNbLite/NoiseModel/CalibrationHook.m b/utils/SimulinkNbLite/NoiseModel/CalibrationHook.m new file mode 100644 index 0000000000000000000000000000000000000000..99c1a76a49532dd5e250cc944b580e076031f1a4 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/CalibrationHook.m @@ -0,0 +1,20 @@ +classdef CalibrationHook + + properties + tf + end + + methods + function self = CalibrationHook(tf) + self.tf = tf; + end + + function newNoise = hook(self, noise) + newNoise.f = noise.f; + newNoise.name = noise.name; + newNoise.asd = noise.asd .* abs(self.tf.tf); + end + end + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/InterpolationHook.m b/utils/SimulinkNbLite/NoiseModel/InterpolationHook.m new file mode 100644 index 0000000000000000000000000000000000000000..59d6e4e2a107f5589eed92303b7c3351ae329b2e --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/InterpolationHook.m @@ -0,0 +1,20 @@ +classdef InterpolationHook + + properties + f + end + + methods + function self = InterpolationHook(f) + self.f = f; + end + + function newNoise = hook(self, noise) + newNoise.name = noise.name; + newNoise.f = self.f; + newNoise.asd = interp1(noise.f, noise.asd, newNoise.f); + end + end + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/LinkHook.m b/utils/SimulinkNbLite/NoiseModel/LinkHook.m new file mode 100644 index 0000000000000000000000000000000000000000..d2d903eedb6bb0167d9ec68c2bbb23e4ca5ebe40 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/LinkHook.m @@ -0,0 +1,24 @@ +classdef LinkHook + + properties + target + end + + methods + function self = LinkHook(target) + self.target = target; + end + + function newNoise = hook(self, noise) + newNoise.f = noise.f; + newNoise.asd = noise.asd; + if strfind(self.target, 'internal:') + newNoise.name = ['\hyperlink{' self.target '}{' noise.name '}']; + else + newNoise.name = ['\href{' self.target '}{' noise.name '}']; + end + end + end + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/MatlabPlotterFactory.m b/utils/SimulinkNbLite/NoiseModel/MatlabPlotterFactory.m new file mode 100644 index 0000000000000000000000000000000000000000..e1c7cd2b06c3b8ea21d36b52552880cde9924eff --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/MatlabPlotterFactory.m @@ -0,0 +1,67 @@ +classdef MatlabPlotterFactory < handle + + properties + fixedFigureNumber = 0; + handles = {} + end + + methods + function plotter = getPlotter(self, noiseModel, varargin) + plotter = NoisePlotter(noiseModel, varargin{:}); + plotter.prolog{end+1} = @self.setFigureNumber; + plotter.epilog{end+1} = @self.stripLinks; + plotter.epilog{end+1} = @self.harvestHandles; + end + + function setFigureNumber(self, noisePlotter, ~) + if self.fixedFigureNumber + noisePlotter.figureProperties.Number = self.fixedFigureNumber; + self.fixedFigureNumber = self.fixedFigureNumber + 1; + end + end + + function harvestHandles(self, noisePlotter, ~) + self.handles{end+1} = noisePlotter.handles; + end + + function stripLinks(~, noisePlotter, ~) + lineObjs = noisePlotter.handles.ln; + for n = 1:numel(lineObjs) + str = get(lineObjs(n), 'DisplayName'); + % strip href and hyperlink links (\href, \hyperlink) + % assume no latex inside the link text + str = regexprep(str, '\\href{[^}]*}{([^\\]*)}', '$1'); + str = regexprep(str, '\\hyperlink{[^}]*}{([^\\]*)}', '$1'); + set(lineObjs(n), 'DisplayName', str); + end + textObjs = findall(noisePlotter.handles.fg, 'Type', 'text'); + for n = 1:numel(textObjs) + str = get(textObjs(n), 'String'); + % string with line breaks is returned as a 2D array + % convert such strings to 1D array for regexprep + strL = cellstr(str); + str = [sprintf('%s\n', strL{1:end-1}), strL{end}]; + % strip hyperlink target (\hypertarget) + % assume target wraps the entire string, and may contain + % links inside the target text + str = regexprep(str, '\\hypertarget{[^}]*}{(.*)}', '$1'); + % strip href and hyperlink links (\href, \hyperlink) + % assume no latex inside the link text + str = regexprep(str, '\\href{[^}]*}{([^\\]*)}', '$1'); + str = regexprep(str, '\\hyperlink{[^}]*}{([^\\]*)}', '$1'); + set(textObjs(n), 'String', str); + end + end + + function finalize(~) + end + + function render(~) + end + + function cleanup(~) + end + end + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/NameHook.m b/utils/SimulinkNbLite/NoiseModel/NameHook.m new file mode 100644 index 0000000000000000000000000000000000000000..402988d991db0e2ff68de60fd4c00909e59a7d32 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/NameHook.m @@ -0,0 +1,20 @@ +classdef NameHook + + properties + name + end + + methods + function self = NameHook(name) + self.name = name; + end + + function newNoise = hook(self, noise) + newNoise.f = noise.f; + newNoise.asd = noise.asd; + newNoise.name = self.name; + end + end + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/Noise.m b/utils/SimulinkNbLite/NoiseModel/Noise.m new file mode 100644 index 0000000000000000000000000000000000000000..1e2b59efa2ce8a46ef9a2697cc540b435080ed69 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/Noise.m @@ -0,0 +1,48 @@ +classdef Noise + + properties + noiseData + getNoise + noiseHooks + end + + properties (Dependent) + f + asd + name + end + + methods + function self = Noise(noiseData) + self.noiseData = noiseData; + self.getNoise = @(self) self.noiseData; + self.noiseHooks = {}; + end + + function f = get.f(self) + noise = self.getNoise(self); + for n = 1:numel(self.noiseHooks) + noise = self.noiseHooks{n}.hook(noise); + end + f = noise.f; + end + + function asd = get.asd(self) + noise = self.getNoise(self); + for n = 1:numel(self.noiseHooks) + noise = self.noiseHooks{n}.hook(noise); + end + asd = noise.asd; + end + + function name = get.name(self) + noise = self.getNoise(self); + for n = 1:numel(self.noiseHooks) + noise = self.noiseHooks{n}.hook(noise); + end + name = noise.name; + end + end + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/NoiseModel.m b/utils/SimulinkNbLite/NoiseModel/NoiseModel.m new file mode 100644 index 0000000000000000000000000000000000000000..6105e88303120e6a4b47466eddf863502713a471 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/NoiseModel.m @@ -0,0 +1,167 @@ +classdef NoiseModel < handle + %NoiseModel holds a hierarchical collection of noises. + % + % Each component noise is a struct or object that defines fields 'f' + % (frequency vector), 'asd' (amplitude spectral density data), and + % 'name' (label used for plotting). Note that a NoiseModel itself can + % act as a noise object -- so that NoiseModels can be composed of + % other NoiseModels. This allows the class to represent a + % hierarchical drill-down noise budget. + + properties + modelNoises % cell array of noise terms that make up the NoiseModel + referenceNoises % cell array of noises that can be plotted alongside the model + getNoise % function handle that returns the NoiseModel's noise object + noiseHooks % cell array of hook objects, providing extensibility for the NoiseModel's noise object (see also the Noise class) + unit % label for the y axis in a noise budget plot + title % title for a noise budget plot + drilldownSkip % boolean that sets whether drilldown should process noises below this NoiseModel + drilldownProlog % cell array of function handles, providing extensibility for drilldown + end + + properties (Dependent) + f % frequency vector + asd % amplitude spectral density data + name % label used for plotting + sumNoise % quadrature sum of modelNoises + end + + properties (Access = private) + linked % boolean that records whether drilldown's link step has been performed already + end + + methods + function self = NoiseModel(modelNoises, varargin) + %NoiseModel object constructor + % + % NoiseModel(modelNoises) sets the modelNoises property. + % NoiseModel(modelNoises, referenceNoises) sets the referenceNoises property as well. + + % input sanity check + if ~iscell(modelNoises) + error('First argument to NoiseModel should be a 1xN cell array of noises'); + end + sz = size(modelNoises); + if length(sz) ~= 2 || min(sz) > 1 + error('First argument to NoiseModel should be a 1xN cell array of noises'); + elseif sz(1) ~= 1 + warning('First argument to NoiseModel should be a 1xN cell array of noises'); + modelNoises = modelNoises'; + end + + + self.modelNoises = modelNoises; + self.referenceNoises = {}; + self.getNoise = @(self) self.sumNoise; + self.noiseHooks = {}; + self.unit = ''; + self.title = ''; + self.drilldownSkip = false; + self.drilldownProlog = {}; + self.linked = false; + + if numel(varargin) > 0 + self.referenceNoises = varargin{1}; + end + if numel(varargin) > 1 + self.getNoise = varargin{2}; + end + end + + % the following methods implement the properties sumNoise, f, asd, and name + function sumNoise = get.sumNoise(self) + sumNoise = incoherentSum(self.modelNoises); + end + + function f = get.f(self) + noise = self.getNoise(self); + for n = 1:numel(self.noiseHooks) + noise = self.noiseHooks{n}.hook(noise); + end + f = noise.f; + end + + function asd = get.asd(self) + noise = self.getNoise(self); + for n = 1:numel(self.noiseHooks) + noise = self.noiseHooks{n}.hook(noise); + end + asd = noise.asd; + end + + function name = get.name(self) + noise = self.getNoise(self); + for n = 1:numel(self.noiseHooks) + noise = self.noiseHooks{n}.hook(noise); + end + name = noise.name; + end + + function sortModel(self, varargin) + %sortModel sorts the modelNoises. + % + % sortModel() sorts using a default weight function. + % sortModel(weightFunction) calls the specified weight + % function handle as weightFunction(f, asd, asdSum) on each + % noise, to determine its weight relative to the sumNoise. + weightFunction = @(f, asd, asdSum) trapz(log10(f), (asd./asdSum).^2); + if numel(varargin) > 0 + weightFunction = varargin{1}; + end + + weight = cellfun(@(noise) weightFunction(noise.f, noise.asd, self.sumNoise.asd), self.modelNoises); + [~, sortNoises] = sort(weight, 'descend'); + self.modelNoises = self.modelNoises(sortNoises); + end + + function drilldown(self, action, varargin) + %drilldown traverses the NoiseModel tree (breadth first), performing an action. + % + % drilldown(ACTION) specifies the action to be performed. + % ACTION is a class constructor handle that is called for + % each NoiseModel, passing the NoiseModel as an argument. + % Then the NoiseModel's drilldownHooks are called on the + % resulting object, and finally the 'process' method of the + % object is invoked on the NoiseModel. + % + % The NoiseModel's property 'drilldownSkip' can be set to + % control the traversal. + persistent serialNumber + if numel(varargin) > 0 + serialNumber = varargin{1}; + elseif isempty(serialNumber) + serialNumber = 1; + end + + queue = {self}; + while ~isempty(queue) + this = queue{1}; + queue = queue(2:end); + if ~this.drilldownSkip + for n = 1:numel(this.modelNoises) + if any(strcmp('drilldownSkip', properties(this.modelNoises{n}))) + queue{end+1} = this.modelNoises{n}; %#ok<AGROW> + if ~this.linked + this.modelNoises{n}.noiseHooks{end+1} = LinkHook(['internal:' num2str(serialNumber + numel(queue))]); + end + end + end + end + + if ~this.linked + this.title = ['\hypertarget{internal:' num2str(serialNumber) '}{' this.title '}']; + end + this.linked = true; + serialNumber = serialNumber + 1; + + worker = feval(action, this); + for n = 1:numel(this.drilldownProlog) + worker = feval(this.drilldownProlog{n}, worker); + end + worker.process(this); + end + end + end + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/NoisePlotter.m b/utils/SimulinkNbLite/NoiseModel/NoisePlotter.m new file mode 100644 index 0000000000000000000000000000000000000000..7f0cf1e4502c62bea9fb76bbcf5e7a3c2e67c4a9 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/NoisePlotter.m @@ -0,0 +1,260 @@ +classdef NoisePlotter < handle + %NoisePlotter is a configurable plotting engine for NoiseModel + % + % It maintains structures figureProperties, axesProperties, etc. for + % configuring the settings of each graphics object in the plot. The + % plot can be further customized by applying prolog and epilog + % functions. Individual model traces and the sum trace can be + % selectively included or omitted. + % + % NoisePlotter objects are typically created using a PlotterFactory + % object. + properties + prolog % cell array of function handles that are called before the plot is drawn + epilog % cell array of function handles that are called after the plot is drawn + handles % struct of graphics handles for each component of the plot + plotterProperties + figureProperties + axesProperties + linesProperties + legendProperties + titleProperties + xlabelProperties + ylabelProperties + skipModelNoises % boolean array specifying whether to plot each model noise trace + skipSumNoise % boolean specifying whether to plot the sum noise trace + end + + methods + function self = NoisePlotter(noiseModel, varargin) + %NoisePlotter object constructor + % + % NoisePlotter(noiseModel) prepares to plot a NoiseModel. + + %% Parse arguments + + opt = NoisePlotter.defaultOptions(noiseModel); + parser = inputParser(); + parser.addParamValue('prolog', opt.prolog, @iscell); + parser.addParamValue('epilog', opt.epilog, @iscell); + parser.addParamValue('plotterProperties', opt.plotterProperties, @isstruct); + parser.addParamValue('figureProperties', opt.figureProperties, @isstruct); + parser.addParamValue('axesProperties', opt.axesProperties, @isstruct); + parser.addParamValue('linesProperties', opt.linesProperties, @isstruct); + parser.addParamValue('legendProperties', opt.legendProperties, @isstruct); + parser.addParamValue('titleProperties', opt.titleProperties, @isstruct); + parser.addParamValue('xlabelProperties', opt.xlabelProperties, @isstruct); + parser.addParamValue('ylabelProperties', opt.ylabelProperties, @isstruct); + parser.parse(varargin{:}); + opt = parser.Results; + + %% Initialize object + + self.handles = struct(); + self.skipModelNoises = false(size(noiseModel.modelNoises)); + self.skipSumNoise = (numel(noiseModel.modelNoises) == 1); + + self.prolog = opt.prolog; + self.epilog = opt.epilog; + self.plotterProperties = opt.plotterProperties; + self.figureProperties = opt.figureProperties; + self.axesProperties = opt.axesProperties; + self.linesProperties = opt.linesProperties; + self.legendProperties = opt.legendProperties; + self.titleProperties = opt.titleProperties; + self.xlabelProperties = opt.xlabelProperties; + self.ylabelProperties = opt.ylabelProperties; + + end + + function process(self, noiseModel) + %process plots the NoiseModel + for n = 1:numel(self.prolog) + feval(self.prolog{n}, self, noiseModel); + end + + plotArgs = self.noisefun(@(noise) {noise.f noise.asd},... + noiseModel, 'UniformOutput', false); + plotArgs = [plotArgs{:}]; + legendArgs = self.noisefun(@(noise) noise.name, noiseModel,... + 'UniformOutput', false); + self.buildPlot(plotArgs, legendArgs); + + for n = 1:numel(self.epilog) + feval(self.epilog{n}, self, noiseModel); + end + end + + function output = noisefun(self, functionHandle, noiseModel, varargin) + %noisefun is a cellfun implementation that respects the skipModelNoises property + output = cellfun(functionHandle, noiseModel.referenceNoises, varargin{:}); + if ~self.skipSumNoise + output = [output cellfun(functionHandle, {noiseModel.sumNoise}, varargin{:})]; + end + if isempty(self.skipModelNoises) + self.skipModelNoises = false(size(noiseModel.modelNoises)); + end + output = [output cellfun(functionHandle, noiseModel.modelNoises(~self.skipModelNoises), varargin{:})]; + end + + function buildPlot(self, plotArgs, legendArgs) + %buildPlot generates the plot components + if isfield(self.figureProperties, 'Number') + % apply figure number property specially + % (it's read-only after figure creation) + fg = figure(self.figureProperties.Number); + self.handles.fg = fg; + set(fg, rmfield(self.figureProperties, 'Number')); + else + fg = figure(); + self.handles.fg = fg; + set(fg, self.figureProperties); + end + + ax = axes(); + self.handles.ax = ax; + set(ax, self.axesProperties); + + if ~isempty(plotArgs) + ln = plot(ax, plotArgs{:}); + self.handles.ln = ln; + if ~iscell(self.linesProperties) + set(ln, self.linesProperties); + else + for n = 1:numel(ln) + set(ln(n), self.linesProperties{n}); + end + end + else + warning('NoisePlotter:emptyplot', 'There are no noises available to plot'); + self.handles.ln = []; + end + + + if ~isempty(legendArgs) + lg = legend(ln, legendArgs{:}); + self.handles.lg = lg; + set(lg, self.legendProperties); + else + self.handles.lg = []; + end + + ti = title(ax, ''); + self.handles.ti = ti; + set(ti, self.titleProperties); + + xl = xlabel(ax, ''); + self.handles.xl = xl; + set(xl, self.xlabelProperties); + + yl = ylabel(ax, ''); + self.handles.yl = yl; + set(yl, self.ylabelProperties); + end + end + + methods (Static) + function skipNegligibleNoises(self, noiseModel) + %skipNegligibleNoises is a prolog function that omits noises contributing only a negligible amount to the sum everywhere + epsi = self.plotterProperties.NegligibleNoiseLevel; + for n = 1:numel(noiseModel.modelNoises) + if ~ismethod(noiseModel.modelNoises{n}, 'drilldown') && ... + all(noiseModel.modelNoises{n}.asd < epsi*noiseModel.sumNoise.asd) + self.skipModelNoises(n) = true; + end + end + end + + function setXLim(self, noiseModel) + %setXLim is a prolog function that sets the x-axis limits to a sane default + self.axesProperties.XLim = [min(noiseModel.f) max(noiseModel.f)]; + end + + function setYLim(self, noiseModel) + %setYLim is a prolog function that sets the y-axis limits to a sane default + + % Sanity check on the noises + nonFinite = cellfun(@(noise) ~any(isfinite(noise.asd)), noiseModel.modelNoises); + if any(nonFinite(~self.skipModelNoises)) + warning('NoisePlotter:nonfinitenoises', 'Model noises whose ASD is nonfinite everywhere are being skipped'); + self.skipModelNoises = self.skipModelNoises | nonFinite; + end + allZero = cellfun(@(noise) all(noise.asd==0), noiseModel.modelNoises); + if any(allZero(~self.skipModelNoises)) + warning('NoisePlotter:identicallyzeronoises', 'Model noises whose ASD is zero everywhere are being skipped'); + self.skipModelNoises = self.skipModelNoises | allZero; + end + if sum(~self.skipModelNoises) == 0 + return + end + + function [maxNoise, minNoise] = maxminNoise(noise) + asd = double(noise.asd); + maxNoise = max(asd(isfinite(asd))); + minNoise = min(asd(isfinite(asd))); + end + [modelMax, modelMin] = cellfun(@maxminNoise, noiseModel.modelNoises(~self.skipModelNoises)); + + sumData = noiseModel.sumNoise.asd; + sumMax = max(sumData(isfinite(sumData))); + sumMin = min(sumData(isfinite(sumData))); + + minY = min([min(modelMax) sumMin]); + maxY = max([max(modelMin) sumMax]); + + self.axesProperties.YLim = [10^floor(log10(minY)) 10^ceil(log10(maxY))]; + end + + function setLinesProperties(self, noiseModel) + %setLinesProperties is a prolog function that styles the reference and sum traces + countReferences = numel(noiseModel.referenceNoises); + countSum = ~self.skipSumNoise; + countLines = countReferences + countSum + sum(~self.skipModelNoises); + + if ~iscell(self.linesProperties) + self.linesProperties = num2cell(repmat(self.linesProperties, countLines, 1)); + end + + for n = 1:(countReferences+countSum) + self.linesProperties{n}.LineStyle = '-'; + end + if ~self.skipSumNoise + self.linesProperties{countReferences+countSum}.LineWidth = 4; + end + end + + function d = defaultOptions(noiseModel) + d = struct(); + d.prolog = {@NoisePlotter.skipNegligibleNoises @NoisePlotter.setXLim @NoisePlotter.setYLim @NoisePlotter.setLinesProperties}; + d.epilog = {}; + d.plotterProperties = struct(); + d.plotterProperties.NegligibleNoiseLevel = 0; + d.figureProperties = struct(); + d.figureProperties.DefaultTextInterpreter = 'none'; + d.axesProperties = struct(); + d.axesProperties.Box = 'on'; + d.axesProperties.XGrid = 'on'; + d.axesProperties.YGrid = 'on'; + d.axesProperties.XScale = 'log'; + d.axesProperties.YScale = 'log'; + %d.axesProperties.ColorOrder = distinguishable_colors(11); + % precomputed color vector - avoids depending on the image + % processing toolbox + d.axesProperties.ColorOrder = [0 0 1; 1 0 0; 0 1 0; 0 0 0.1724; ... + 1 0.1034 0.7241; 1 0.8276 0; 0 0.3448 0; 0.5172 0.5172 1; ... + 0.6207 0.3103 0.2759; 0 1 0.7586; 0 0.5172 0.5862]; + d.axesProperties.LineStyleOrder = {'--', '-.', ':'}; + d.axesProperties.NextPlot = 'add'; + d.linesProperties = struct(); + d.linesProperties.LineWidth = 2; + d.legendProperties = struct(); + d.legendProperties.interpreter = 'none'; + d.titleProperties = struct(); + d.titleProperties.String = noiseModel.title; + d.xlabelProperties = struct(); + d.xlabelProperties.String = 'Frequency [Hz]'; + d.ylabelProperties = struct(); + d.ylabelProperties.String = noiseModel.unit; + end + end +end \ No newline at end of file diff --git a/utils/SimulinkNbLite/NoiseModel/calibrated.m b/utils/SimulinkNbLite/NoiseModel/calibrated.m new file mode 100644 index 0000000000000000000000000000000000000000..71301a80a35872f2f8d5f88554a3ff0a95d279d8 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/calibrated.m @@ -0,0 +1,12 @@ +function calibratedNoise = calibrated(noise, tf) + +calibratedNoise = noise; + +if ~any(strcmp('noiseHooks', properties(calibratedNoise))) + calibratedNoise = Noise(calibratedNoise); +end + +calibratedNoise.noiseHooks{end+1} = CalibrationHook(tf); + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/incoherentSum.m b/utils/SimulinkNbLite/NoiseModel/incoherentSum.m new file mode 100644 index 0000000000000000000000000000000000000000..5f242179589fa2fa9a1bda7d8603b4a1b7d9b42e --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/incoherentSum.m @@ -0,0 +1,17 @@ +function sumNoise = incoherentSum(noises, varargin) + +name = 'Sum'; +if numel(varargin) > 0 + name = varargin{1}; +end + +sumPSD = zeros(size(noises{1}.asd)); +for n = 1:length(noises) + sumPSD = sumPSD + noises{n}.asd.^2; +end + +sumNoise.f = noises{1}.f; +sumNoise.asd = sqrt(sumPSD); +sumNoise.name = name; + +end \ No newline at end of file diff --git a/utils/SimulinkNbLite/NoiseModel/interpolated.m b/utils/SimulinkNbLite/NoiseModel/interpolated.m new file mode 100644 index 0000000000000000000000000000000000000000..3d9f5b7ebdedef9c0d0f86af5814cfeab183fb22 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/interpolated.m @@ -0,0 +1,12 @@ +function interpolatedNoise = interpolated(noise, f) + +interpolatedNoise = noise; + +if ~any(strcmp('noiseHooks', properties(interpolatedNoise))) + interpolatedNoise = Noise(interpolatedNoise); +end + +interpolatedNoise.noiseHooks{end+1} = InterpolationHook(f); + +end + diff --git a/utils/SimulinkNbLite/NoiseModel/matlabNoisePlot.m b/utils/SimulinkNbLite/NoiseModel/matlabNoisePlot.m new file mode 100644 index 0000000000000000000000000000000000000000..7661092d8ddc0074784d469beb54a57de9ea5c74 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/matlabNoisePlot.m @@ -0,0 +1,13 @@ +function handles = matlabNoisePlot(noiseModel, varargin) + +parser = inputParser(); +parser.KeepUnmatched = true; +parser.addParamValue('fixedFigureNumber', 0); +parser.parse(varargin{:}); + +plotterFactory = MatlabPlotterFactory(); +plotterFactory.fixedFigureNumber = parser.Results.fixedFigureNumber; +noiseModel.drilldown(@(noiseModel) plotterFactory.getPlotter(noiseModel, parser.Unmatched)); +handles = plotterFactory.handles; + +end \ No newline at end of file diff --git a/utils/SimulinkNbLite/NoiseModel/renamed.m b/utils/SimulinkNbLite/NoiseModel/renamed.m new file mode 100644 index 0000000000000000000000000000000000000000..f445217c89ba5419ac9cecca55e43a6ef53866e8 --- /dev/null +++ b/utils/SimulinkNbLite/NoiseModel/renamed.m @@ -0,0 +1,12 @@ +function renamedNoise = renamed(noise, name) + +renamedNoise = noise; + +if ~any(strcmp('noiseHooks', properties(renamedNoise))) + renamedNoise = Noise(renamedNoise); +end + +renamedNoise.noiseHooks{end+1} = NameHook(name); + +end + diff --git a/utils/SimulinkNbLite/README.md b/utils/SimulinkNbLite/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5cd002e1ac33450c10a946534666aa921cd298bc --- /dev/null +++ b/utils/SimulinkNbLite/README.md @@ -0,0 +1,15 @@ +# SimulinkNb - NoiseBudget toolbox for Simulink + +### How to graphically configure a noise budget for your Simulink model: + +1. Open SimulinkNb/NbLibrary.mdl and copy in a NbNoiseSink block. Connect it in series with the signal that you actually measure (for example, digitized photodetector output). Double-click the block to give a name to the DOF you are measuring (a string). + +2. Copy in a NbNoiseCal block. Sum it in to the signal that you "want" to measure and budget the noise of (for example, test mass displacement calibrated in meters). Double-click the block and set the DOF name (which must correspond with the Sink block) and the unit string (for example, 'displacement [m/rtHz]'). + +3. Copy in one or more NbNoiseSource blocks. Sum them in throughout the model wherever noise couples. Double-click each block and set the ASD of the noise source (which can be a constant or a vector). If desired, set one or more group strings, to name the noise source and/or form sub-budgets. + +4. Use the nbFromSimulink function to obtain the individual noise terms and calibration TFs. + +5. Use the nbGroupNoises function to organize the noise terms into a hierarchical noise budget (NoiseModel object). + +6. Plot the noise budget using a function such as matlabNoisePlot or fragNoisePlot. diff --git a/utils/SimulinkNbLite/SimulinkNb/NbLibrary.mdl b/utils/SimulinkNbLite/SimulinkNb/NbLibrary.mdl new file mode 100644 index 0000000000000000000000000000000000000000..81f61a08ba9d3258b9cd1f90a423cbc38a620ed0 Binary files /dev/null and b/utils/SimulinkNbLite/SimulinkNb/NbLibrary.mdl differ diff --git a/utils/SimulinkNbLite/SimulinkNb/README.txt b/utils/SimulinkNbLite/SimulinkNb/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..ee2b03e35ef1158c97f4e8a081fca12c8b486029 --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/README.txt @@ -0,0 +1,150 @@ +This directory contains a Simulink-based noise budget toolkit, and an +example based on the DARM Simulink model from the aligocalibration SVN +repository. + + + +============================== +Getting started: example model +============================== + +To run the example, go to the example/ subdirectory and use the +run_DARM_NB script. You'll need Matlab R2010a or newer, and a recent +checkout of the SUS and aligocalibration repositories. (The SUS SVN +is vast and not all of it is needed, but make sure to include at least +the paths listed at the top of darmParams.m. Also, edit the paths +there, and at the top of run_DARM_NB, if your SVN directories are in a +different location.) + +SVN repository URLs: +SUS -- https://redoubt.ligo-wa.caltech.edu/svn/sus +aligocalibration -- https://svn.ligo.caltech.edu/svn/aligocalibration + +The script should conclude by popping up a series of noise budget and +sub-budget plots. The following noise terms are modeled: +* ADC Noise +* ASPD Dark Noise +* BOSEM L Noise +* Laser Frequency Noise +* Laser Intensity Noise +* MICH Coupling Noise +* Oscillator Amplitude Noise +* Oscillator Phase Noise +* QUAD Actuator Noise +* Quantum Noise +* Scattered Light Ring Noise +* Squeezed Film Damping Noise + +Note: not all of these terms are broken out in the plots. Only the +leading contributors are shown. + +Also note: the example is supplied only as a demo to illustrate how +the various tools can be used. The DARM model included here has not +been gone over with a fine toothed comb, and is certainly not correct +in all particulars. Most of the input spectra are just placeholders. +There is absolutely no warranty on the output of this example. + + + +=============================== +Getting started: your own model +=============================== + +To substitute frequency response data for a Simulink block in your +model: + +1. Right-click the block and open its Properties. + +2. Type a FlexTf configuration line at the top of the block +description field in the General tab of the Block Properties window. +This is similar to how certain CDS parts are configured in the aLIGO +RCG. The FlexTf line should start with the identifier string +"FlexTf:". After the ":", type a Matlab expression (variable name or +function call). This expression, when evaluated, should yield a frd +object containing frequency response data to substitute for the block. + +3. To make the substitution more obvious, it's helpful to display the +block's description as an annotation under its name. To do this, go +the Block Annotation tab, choose the %<Description> token from the +list, and add it to the displayed annotations. + +4. Use the linFlexTf function (in place of linmod or linmod2) to +linearize the model. Note that linFlexTf has two outputs, a +linearized system with extra I/O ports for the FlexTf blocks, and a +cell array of frd objects describing the FlexTf blocks. + +5. Use the linFlexTfFold function to combine the two outputs of +linFlexTf. The output is a frd object containing the frequency +response of the linearized system. + + +To graphically configure a noise budget for your model: + +1. Open NbLibrary.mdl and copy in a NbNoiseSink block. Connect it in +series with the signal that you actually measure (for example, +digitized photodetector output). Double-click the block to set the +name of the DOF you are measuring (a string). + +2. Copy in a NbNoiseCal block. Sum it in to the signal that you +"want" to measure and budget the noise of (for example, test mass +displacement calibrated in meters). Double-click the block and set +the DOF name string (which must correspond with the Sink block) and +the unit string (for example, 'displacement [m/rtHz]'). + +3. Copy in one or more NbNoiseSource blocks. Sum them in throughout +the model wherever noise couples. Double-click each block and set the +ASD of the noise source (which can be a constant or a vector). If +desired, set one or more group strings, to name the noise source +and/or form sub-budgets. + +4. Use the nbFromSimulink function to obtain the individual noise +terms and calibration TFs. + +5. Use the nbGroupNoises function to organize the noise terms into a +hierarchical noise budget (NoiseModel object). + +6. A NoiseModel object can be plotted using a function such as +matlabNoisePlot or fragNoisePlot from the NoiseModel distribution. + + + +============= +File overview +============= + +* linFlexTf.m, linFlexTfFold.m +linFlexTf and linFlexTfFold are functions for incorporating frequency +response data into Simulink linearizations. These functions take the +place of linmod or linmod2, and should prove to be more robust and +accurate when frequency response data are available. They're really +just wrappers around Matlab's linlft and linlftfold functions. See +the help for more details. + +* nbFromSimulink.m, nbGroupNoises.m, NbLibrary.mdl +These are tools for processing Simulink-based noise budgets, to +automatically identify, calibrate, and organize all the noise terms +they contain. See the help for more details. + +* lisoFrd.m, optickleFrd.m, scb.m +lisoFrd imports LISO transfer functions for use with linFlexTf. +optickleFrd is a full-fledged Optickle interface for SimulinkNB, +developed by Nicolas Smith-Lefebvre. It automatically hooks up the +drives and probes of an Optickle object to a FlexTf block, and calls +tickle to compute the frequency response data if needed. scb is a +helper function used by linFlexTf and nbFromSimulink when they process +a block: it lets clever extension functions such as optickleFrd figure +out which block called them, and act accordingly. + +* example/run_DARM_NB.m +Main script used for the example. + +* example/DARM.mdl, example/darmParams.m, example/darmNbParams.m +Demo Simulink model for DARM, and functions to define its parameters +(adapted from Jeff Kissel's DARM model). Examples of how to configure +FlexTf and NbNoiseSource blocks can be seen in the Simulink model by +drilling down into the subsystems, such as: DARM.mdl/Actuation +Function/ETMX/Hierarchy Loops/Driver Electronics + +* example/DarmLentickle.mat +Lentickle model results used to supply the cavity response as a +FlexTf, and to add various noise couplings to the model. diff --git a/utils/SimulinkNbLite/SimulinkNb/example/OLvsCL/OLvsCL.mdl b/utils/SimulinkNbLite/SimulinkNb/example/OLvsCL/OLvsCL.mdl new file mode 100644 index 0000000000000000000000000000000000000000..adc6b822102ec078da4da3307a51b371db1bd22a Binary files /dev/null and b/utils/SimulinkNbLite/SimulinkNb/example/OLvsCL/OLvsCL.mdl differ diff --git a/utils/SimulinkNbLite/SimulinkNb/findInSystemOrRefs.m b/utils/SimulinkNbLite/SimulinkNb/findInSystemOrRefs.m new file mode 100644 index 0000000000000000000000000000000000000000..43e79b595a3573864b98f660beab6d4d1fc7c74c --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/findInSystemOrRefs.m @@ -0,0 +1,15 @@ +function blks = findInSystemOrRefs(mdl, varargin) +%FINDINSYSTEMORREFS locates blocks in the specified model or any models it references + +referencedMdls = find_system(mdl, 'FollowLinks', 'on', 'LookUnderMasks', 'all', 'BlockType', 'ModelReference'); +for n = 1:numel(referencedMdls) + referencedMdls{n} = get_param(referencedMdls{n}, 'ModelName'); + load_system(referencedMdls{n}); +end + +blks = find_system(mdl, 'FollowLinks', 'on', 'LookUnderMasks', 'all', varargin{:}); +for n = 1:numel(referencedMdls) + blks = [blks; findInSystemOrRefs(referencedMdls{n}, varargin{:})]; %#ok<AGROW> +end + +end \ No newline at end of file diff --git a/utils/SimulinkNbLite/SimulinkNb/linFlexTf.m b/utils/SimulinkNbLite/SimulinkNb/linFlexTf.m new file mode 100644 index 0000000000000000000000000000000000000000..507cb57cdefa9bb9e7695552430d1944cf511ddb --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/linFlexTf.m @@ -0,0 +1,153 @@ +function [sys, flexTfs] = linFlexTf(varargin) +% LINFLEXTF Linearizes a Simulink model while removing FlexTf blocks +% +% [sys, flexTfs] = linFlexTf(...) +% +% LINFLEXTF is a wrapper for Matlab's LINLFT, and can be called in almost +% the same way. The only difference is that it's not necessary to +% specify the set of blocks to be removed, since this is automatically +% determined by LINFLEXTF. The blocks removed are those that are +% annotated with a "FlexTf: EXPR" line at the top of their block +% description. +% +% For each FlexTf-tagged block, LINFLEXTF evaluates the EXPR. The result +% is expected to be a linear model (such as an FRD object containing +% frequency response data), which can be substituted in place of the +% block in question. +% +% Note: although the contents of a FlexTf-tagged subsystem are +% overridden, it is necessary that all inputs are connected inside the +% subsystem to the outputs that they affect. Otherwise the linearization +% may give incorrect results. +% +% LINFLEXTFFOLD (analogous to LINLFTFOLD) can be used to recombine the +% Simulink linearization and FlexTf models that are the output arguments +% of LINFLEXTF. It may be advantageous to call PRESCALE to improve the +% numerical accuracy before invoking LINFLEXTFFOLD. +% +% See also: LINFLEXTFFOLD, LINLFT, LINLFTFOLD, PRESCALE, FRD. + +%% Locate all FlexTf blocks within the model + +mdl = varargin{1}; +load_system(mdl); + +flexTfBlocks = findInSystemOrRefs(mdl, 'RegExp', 'on', 'Description', '^[Ff]lex[Tt][Ff]:'); +flexTfs = cell(size(flexTfBlocks)); +disp([num2str(numel(flexTfBlocks)) ' FlexTf blocks found in model ' strtrim(evalc('disp(mdl)'))]); + +if numel(flexTfBlocks) < 1 + warning('No FlexTf blocks found: standard linearization will be performed'); + sys = linearize(varargin{:}); + return; +end + +%% Check for nested FlexTfs +% Each FlexTf block 'shadows' any FlexTf blocks it contains. Shadowed +% blocks are disregarded. + +notShadowedAnywhere = true(size(flexTfBlocks)); +for n = 1:numel(flexTfBlocks) + blk = flexTfBlocks{n}; + shadowed = strncmp([blk '/'], flexTfBlocks, length(blk)+1); + % don't be fooled by block names with '/'s in them + shadowed = shadowed & ~strncmp([blk '//'], flexTfBlocks, length(blk)+2); + if any(shadowed) + shadowedBlocks = flexTfBlocks(shadowed); + warning(['FlexTf block ' blk ' shadows other FlexTf blocks: ' ... + sprintf('%s, ', shadowedBlocks{1:end-1}) shadowedBlocks{end}]); + notShadowedAnywhere = notShadowedAnywhere & ~shadowed; + end +end + +% Remove shadowed blocks from the list +flexTfBlocks = flexTfBlocks(notShadowedAnywhere); + +%% Check for linearization I/O points inside FlexTf blocks +% I/O points may be passed as arguments to this function. If one of them +% is located inside a FlexTf block, this should be flagged as an error. + +for n = 1:numel(varargin) + io = varargin{n}; + if ~isa(io, 'linearize.IOPoint') + continue; + end + ioBlocks = {io.Block}; + + for j = 1:numel(flexTfBlocks) + blk = flexTfBlocks{j}; + inFlexTf = strncmp([blk '/'], ioBlocks, length(blk)+1); + % don't be fooled by block names with '/'s in them + inFlexTf = inFlexTf & ~strncmp([blk '//'], ioBlocks, length(blk)+2); + if any(inFlexTf) + error(['One of the requested linearization I/O points is ' ... + 'contained in the FlexTf block ' blk]); + end + end +end + +%% Extract and evaluate each FlexTf block's expression + +for n = 1:numel(flexTfBlocks) + blk = flexTfBlocks{n}; + expr = get_param(blk, 'Description'); + expr = strtrim(expr(length('FlexTf:')+1:end)); + % If expr is inside a library block, then its name probably refers to a + % library parameter (mask variable), which has to be resolved before + % evaluating + expr = resolveLibraryParam(expr, blk); + disp([' ' blk ' :: ' expr]); + % Update the current block. This is to allow clever FlexTf functions + % to use gcb to figure out which block invoked them. + scb(blk); + % Note: evaluation is done in the base workspace + % Variables from the model workspace (if any) are ignored + flexTfs{n} = evalin('base', expr); +end + +%% Check that each FlexTf has the same I/O count as its corresponding block +% Note: this code can be omitted if it's too slow or causes problems. +% It's a useful debugging aid, but not required for the linearization. + +disp('Compiling model to check for I/O port mismatch'); +% A compile is needed in order to use the CompiledPortWidth block property. +% But compiling puts the model in a weird state where it cannot be closed +% by the user! The onCleanup routine is meant to ensure that the model +% is never left in that state. +feval(mdl, [], [], [], 'lincompile'); +cleanup = onCleanup(@() feval(mdl, [], [], [], 'term')); +for n = 1:numel(flexTfBlocks) + % Count the inputs and outputs to each block. This is tricky! If the + % I/O consists of scalars and vectors, it should be fine, but if the + % block uses buses/matrices/etc, watch out! + blk = flexTfBlocks{n}; + blkPorts = get_param(blk, 'PortHandles'); + [blkInputs, blkOutputs] = deal(0); + for j = 1:numel(blkPorts.Inport) + blkInputs = blkInputs + get_param(blkPorts.Inport(j), 'CompiledPortWidth'); + end + for j = 1:numel(blkPorts.Outport) + blkOutputs = blkOutputs + get_param(blkPorts.Outport(j), 'CompiledPortWidth'); + end + blkSize = [blkOutputs, blkInputs]; + + % Counting the FlexTf's inputs and outputs is much easier + flexTfSize = size(flexTfs{n}); + + if ~isequal(flexTfSize, blkSize) + clear cleanup; + error(['I/O port mismatch between block "' blk '" and FlexTf' char(10) ... + 'Block''s dimensions are (' strtrim(evalc('disp(blkSize)')) ') ' ... + 'and FlexTf''s dimensions are (' strtrim(evalc('disp(flexTfSize)')) ')']); + end +end +clear cleanup; + +%% Linearize the model with the FlexTf blocks factored out + +disp('Linearizing model'); +flexTfs = append(flexTfs{:}); +varargin{end+1} = flexTfBlocks; +sys = linlft(varargin{:}); + +end diff --git a/utils/SimulinkNbLite/SimulinkNb/linFlexTfFold.m b/utils/SimulinkNbLite/SimulinkNb/linFlexTfFold.m new file mode 100644 index 0000000000000000000000000000000000000000..f42e32c5286a868d52a2b65a15002f02c9aa0b1b --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/linFlexTfFold.m @@ -0,0 +1,19 @@ +function [ sysFold ] = linFlexTfFold(sys, flexTfs) +%LINFLEXTFFOLD Joins a linearized Simulink model and a collection of FlexTf block models +% +% sysFold = LINFLEXTFFOLD(sys, flexTfs) +% +% This function is analogous to LINLFTFOLD. Using PRESCALE before +% calling LINFLEXTFFOLD may improve the numerical accuracy. +% +% See also: LINFLEXTF, LINLFT, LINLFTFOLD, PRESCALE, FRD. + +if numel(flexTfs) < 1 + warning('No FlexTf blocks provided') + sysFold = sys; + return; +end + +sysFold = lft(sys, flexTfs); + +end \ No newline at end of file diff --git a/utils/SimulinkNbLite/SimulinkNb/nbFromSimulink.m b/utils/SimulinkNbLite/SimulinkNb/nbFromSimulink.m new file mode 100644 index 0000000000000000000000000000000000000000..ef12f2ed0132ef9690bc7f8872059ae2af948bea --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/nbFromSimulink.m @@ -0,0 +1,274 @@ +function [noises, sys] = nbFromSimulink(mdl, freq, varargin) +%NBFROMSIMULINK Generates noise budget terms from a Simulink model +% +% Syntax: +% +% [noises, sys] = nbFromSimulink(mdl, freq) +% [noises, sys] = nbFromSimulink(..., 'PropertyName', PropertyValue, ...) +% +% Description: +% +% nbFromSimulink(MDL, FREQ) generates noise budget terms from the +% Simulink model MDL, with frequency vector FREQ. It uses special +% "dummy" blocks in the model (which are tagged as "NbNoiseSource", +% "NbNoiseSink", or "NbNoiseCal") to generate noise budget terms. +% +% Each NbNoiseSource block has a user-defined parameter ASD, which should +% evaluate to the amplitude spectral density of the noise at the point +% where the source block is summed into the model. The ASD can be either +% a scalar value or an array. (If an array is used, you need to make +% sure it's interpolated to match the FREQ vector that's passed as an +% argument to NBFROMSIMULINK.) +% +% The NbNoiseSink and NbNoiseCal blocks have a user-defined parameter +% DOF. For each defined DOF, there should be exactly one sink and +% exactly one cal block. Connect the cal block to the signal in the +% model that you "want" to measure (for example, test mass displacement +% calibrated in meters). Connect the sink block in series with the +% signal that you actually measure (for example, digitized photodetector +% output). +% +% NBFROMSIMULINK linearizes the model (using LINFLEXTF) to obtain +% transfer functions from each source, and the cal block, to the sink +% (with the loop opened after the sink). These TFs are used to determine +% each source's contribution to the total calibrated noise. +% +% nbFromSimulink(..., 'PropertyName', PropertyValue, ...) allows the +% following options to be defined: +% +% 'dof' -- value should be a string containing the DOF name to use, in +% case more than one DOF has been defined in the model. (Any other DOFs +% that may be present are simply ignored.) +% +% Output arguments: +% +% NOISES -- contains the calibrated noise terms. Each is stored in a +% struct with fields 'f' (frequency vector), 'asd' (spectral density), +% and 'name' (path to the source block). NOISES is a cell array of these +% noise structs. +% +% SYS -- the linearized Simulink model containing the calibration TFs. +% +% See also: LINFLEXTF + +%% Parse the arguments + +% Validate required arguments +if ~ischar(mdl) + error('The model name is not a string'); +elseif ~isreal(freq) + error('The frequency vector is not real-valued'); +end + +% Parse parameter-value pairs in varargin +parser = inputParser(); +parser.addParamValue('dof', '', @ischar); +parser.parse(varargin{:}); +opt = parser.Results; + +%% Gather all NbNoiseSink and NbNoiseCal blocks + +load_system(mdl); +% getBlocksByDof() is a local function defined below +nbNoiseSinksByDof = getBlocksByDof(mdl, 'NbNoiseSink'); +nbNoiseCalsByDof = getBlocksByDof(mdl, 'NbNoiseCal'); + +% Check for one-to-one correspondence between the NbNoiseSink and NbNoiseCal blocks +mismatchedDofs = setxor(nbNoiseSinksByDof.keys(), nbNoiseCalsByDof.keys()); +if ~isempty(mismatchedDofs) + if ~nbNoiseSinksByDof.isKey(mismatchedDofs{1}) + error(['Missing NbNoiseSink block for DOF name ' mismatchedDofs{1}]); + else + error(['Missing NbNoiseCal block for DOF name ' mismatchedDofs{1}]); + end +end + +% Make sure at least one DOF is defined +availableDofs = nbNoiseSinksByDof.keys(); +if numel(availableDofs) < 1 + error('The model must contain at least one NbNoiseSink block and at least one NbNoiseCal block'); +end + +%% Choose a NbNoiseSink/Cal pair according to the requested DOF + +if isempty(opt.dof) + % No DOF name was given. If exactly one DOF was defined in the model, + % then use it. Otherwise, give up. + if numel(availableDofs) == 1 + opt.dof = availableDofs{1}; + else + error(['Since the model defines multiple DOFs, you must pick one' ... + ' and specify it in the input arguments of this function']); + end +end + +if nbNoiseSinksByDof.isKey(opt.dof) && nbNoiseCalsByDof.isKey(opt.dof) + nbNoiseSink = nbNoiseSinksByDof(opt.dof); + nbNoiseCal = nbNoiseCalsByDof(opt.dof); + disp([num2str(numel(availableDofs)) ' DOFs found; DOF ' opt.dof ' is selected']); +else + error(['The requested DOF name (' opt.dof ') is not defined in the model']); +end + +%% Evaluate the NbNoiseSink's measured ASD (if present) + +% getBlockNoise() is a local function defined below +sinkNoise = getBlockNoises(nbNoiseSink, freq); +sinkNoise = sinkNoise{1}; + +%% Find the NbNoiseSource blocks + +nbNoiseSources = findInSystemOrRefs(mdl, 'Tag', 'NbNoiseSource'); +disp([num2str(numel(nbNoiseSources)) ' NbNoiseSource blocks found']); +if numel(nbNoiseSources) < 1 + error('The model must contain at least one NbNoiseSource block'); +end + +%% Evaluate each NbNoiseSource block's ASD, and set up noise/calibration TFs + +noises = {}; +% Set numerator for noise/calibration TFs, and open the loop +% (also sets denominator for open loop gain around the sink) +ioSink = linio(nbNoiseSink, 1, 'outin', 'on'); +% Set denominator for calibration TF (cal to sink) +ioCal = linio(nbNoiseCal, 1, 'in'); +for n = 1:numel(nbNoiseSources) + blk = nbNoiseSources{n}; + % Set denominator for noise TF (source to sink) + ioSource(n) = linio(blk, 1, 'in'); %#ok<AGROW> + % getBlockNoise() is a local function defined below + noises = [noises getBlockNoises(blk, freq)]; %#ok<AGROW> +end +io = [ioSink ioCal ioSource]; + +%% Perform the linearization using FlexTf functions + +% Don't abbreviate I/O block names (it's faster that way) +linOpt = linoptions('UseFullBlockNameLabels', 'on'); +[sys, flexTfs] = linFlexTf(mdl, io, linOpt); +% Attempt to improve numerical accuracy with prescale +minPosFreq = min(freq(freq>0)); +maxPosFreq = max(freq(freq>0)); +if ~isempty(minPosFreq) && ~isempty(maxPosFreq) + sys = prescale(sys, {2*pi*minPosFreq, 2*pi*maxPosFreq}); +end +sys = linFlexTfFold(sys, flexTfs); +% Ensure sys gets converted to frequency response data +sys = frd(sys, freq, 'Units', 'Hz'); + +% Set sys input/output names to meaningful values +% (UseFullBlockNameLabels appends signal names to the block names) +sys.InputName = [{nbNoiseSink nbNoiseCal} nbNoiseSources']; +sys.OutputName = nbNoiseSink; + +%% Apply noise/calibration TFs to each NbNoiseSource's spectrum + +cal = 1/sys(2); +% Ensure the calibration TF is finite +if ~all(isfinite(freqresp(cal, 2*pi*freq))) + error('Can''t calibrate noises in the model because the TF from the NbNoiseCal block to the NbNoiseSink block can''t be inverted (is it zero?)'); +end + +for n = 1:numel(noises) + nameParts = regexp(noises{n}.name, '(.*)\{\d+\}', 'tokens'); + blk = nameParts{1}; + tfIdx = strcmp(blk, sys.InputName); + tf = abs(squeeze(freqresp(sys(tfIdx)*cal, 2*pi*freq)))'; + noises{n}.asd = noises{n}.asd .* tf; %#ok<AGROW> +end + +%% Prepend the NbNoiseSink's measured spectrum + +if ~isempty(sinkNoise.asd) + sinkNoise.asd = sinkNoise.asd .* abs(squeeze(freqresp((1-sys(1))*cal, 2*pi*freq)))'; +end +noises = [{sinkNoise} noises]; + +end + +function [ blockTable ] = getBlocksByDof(mdl, tag) +%% Locate the blocks with the requested tag + +blks = findInSystemOrRefs(mdl, 'Tag', tag); +disp([num2str(numel(blks)) ' ' tag ' blocks found']); + +%% Organize them in a hashtable (containers.Map object), indexed by the DOF name + +blockTable = containers.Map(); +for n = 1:numel(blks) + blk = blks{n}; + blkVars = get_param(blk, 'MaskWSVariables'); + blkVars = containers.Map({blkVars.Name}, {blkVars.Value}); + dofs = blkVars('dof'); + if ischar(dofs) + dofs = {dofs}; + end + if ~iscellstr(dofs) + error(['Invalid ' tag ' block ' blk char(10) ... + 'The DOF name (' get_param(blk, 'dof') ') must be a string or cell array']); + end + for nn = 1:numel(dofs) + disp([' ' blk ' :: ' dofs{nn}]); + if ~blockTable.isKey(dofs{nn}) + blockTable(dofs{nn}) = blk; + else + error(['The DOF name cannot be shared by multiple ' tag ' blocks' char(10) ... + 'Blocks ' blk ' and ' blockTable(dofs{nn}) ' both have dof=' dofs{nn}]); + end + end +end + +end + +function [ noises ] = getBlockNoises(blk, freq) + +tag = get_param(blk, 'Tag'); +expr = get_param(blk, 'asd'); +% If expr is inside a library block, then its name probably refers to a +% library parameter (mask variable), which has to be resolved before +% evaluating +expr = resolveLibraryParam(expr, blk); +% Permit NbNoiseSink block to have an empty ASD +if strcmp(tag, 'NbNoiseSink') + if isempty(expr) || strcmp(expr, '''''') || strcmp(expr, '[]') + noises = {struct('name', [blk '{1}'], 'f', freq, 'asd', [])}; + return; + end +end +disp([' ' blk ' :: ' expr]); +% Update the current block. This is to allow clever ASD functions +% to use gcb to figure out which block invoked them. +scb(blk); +% Evaluate the noise ASD +% Note: evaluation is done in the base workspace (any variables set in +% the model workspace are ignored). The NbNoiseSource block mask is +% set to NOT evaluate anything automatically. This way, the noise +% budget spectra don't have to be defined when the model is used for +% purposes other than making a noise budget. +asds = evalin('base', expr); + +if ~iscell(asds) + asds = {asds}; +end + +noises = cell(1, numel(asds)); +for n = 1:numel(asds) + noises{n} = struct('name', [blk '{' num2str(n) '}'], 'f', freq, 'asd', []); + asd = asds{n}; + % Sanity checks on the ASD + if ~isreal(asd) || min(size(asd)) > 1 + error(['Invalid ' tag ' block ' blk char(10) ... + 'ASD #' num2str(n) ' (from ' expr ') is not a real-valued 1D array']); + elseif numel(asd) ~= 1 && numel(asd) ~= numel(freq) + error(['Invalid ' tag ' block ' blk char(10) ... + 'Length of ASD #' num2str(n) ' (from ' expr ') doesn''t match the frequency vector' char(10) ... + '(ASD''s length is ' num2str(numel(asd)) ... + ' and frequency vector''s length is ' num2str(numel(freq)) ')']); + end + if size(asd, 1) ~= 1 + asd = asd'; + end + noises{n}.asd = asd; +end + +end diff --git a/utils/SimulinkNbLite/SimulinkNb/nbGroupNoises.m b/utils/SimulinkNbLite/SimulinkNb/nbGroupNoises.m new file mode 100644 index 0000000000000000000000000000000000000000..f1742f805c029403271824b9863a7652b5bd52fa --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/nbGroupNoises.m @@ -0,0 +1,126 @@ +function [ nb ] = nbGroupNoises(mdl, noises, sys) +%NBGROUPNOISES Organizes the noises array returned by NBFROMSIMULINK +% [ nb ] = NBGROUPNOISES(mdl, noises, sys) +% +% NBGROUPNOISES combines noises whose NbNoiseSource blocks share the same +% grouping parameters ("Group", "Sub-group", etc.). It returns a +% hierarchical NOISEMODEL object, whose title is set based on the +% NbNoiseCal block's "DOF name" parameter, and whose Y-label is set based +% on the "unit" parameter. +% +% See also: NBFROMSIMULINK, NOISEMODEL + +%% Validate the arguments + +if ~ischar(mdl) + error('The model name is not a string'); +elseif ~iscell(noises) + error('The noises are not a cell array'); +elseif ~isobject(sys) + error('The sys object is not an object'); +%elseif size(sys, 2) ~= numel(noises) + 1 +% error('The noises and the sys object have mismatched dimensions') +end + +%% Get the DOF and unit settings from the NbNoiseCal block + +load_system(mdl); +nbNoiseCal = sys(2).InputName{:}; +blkVars = get_param(nbNoiseCal, 'MaskWSVariables'); +blkVars = containers.Map({blkVars.Name}, {blkVars.Value}); +dof = blkVars('dof'); +unit = blkVars('unit'); +if ~ischar(dof) || ~ischar(unit) + error(['Invalid NbNoiseCal block ' nbNoiseCal char(10) ... + 'The DOF name (' get_param(nbNoiseCal, 'dof') ') ' ... + 'and unit (' get_param(nbNoiseCal, 'unit') ' must be strings']); +end +disp(['NbNoiseCal block is ' nbNoiseCal ' (DOF ' ... + blkVars('dof') ', unit ' blkVars('unit') ')']); + +%% Form groups and output a NoiseModel object + +% groupAtLevel is a (recursive) local function defined below +group = groupAtLevel(noises(2:end), 1, unit); + +nb = NoiseModel(group); +nb.title = [dof ' NoiseBudget']; +nb.unit = unit; + +if ~isempty(noises{1}.asd) + noises{1} = renamed(noises{1}, 'Measured'); + nb.referenceNoises = noises(1); +end + +end + +function [ groupedNoises ] = groupAtLevel(noises, level, unit) +%% Limit the recursion depth + +groupVar = {'group', 'subgroup', 'subsubgroup', 'subsubsubgroup'}; +if level > numel(groupVar) + groupedNoises = noises; + return; +end + +%% Organize the noises in a hashtable (containers.Map object), indexed by group + +noisesByGroup = containers.Map(); +for n = 1:numel(noises) + noise = noises{n}; + nameParts = regexp(noise.name, '(.*)\{(\d+)\}', 'tokens'); + blk = nameParts{1}{1}; + multiplex = str2double(nameParts{1}{2}); + blkVars = get_param(blk, 'MaskWSVariables'); + blkVars = containers.Map({blkVars.Name}, {blkVars.Value}); + if iscell(blkVars('group')) + groupInfo = blkVars('group'); + groupInfo = groupInfo{multiplex}; + else + groupInfo = struct('groupNest', blkVars('groupNest'), ... + 'group', blkVars('group'), 'subgroup', blkVars('subgroup'), ... + 'subsubgroup', blkVars('subsubgroup'), ... + 'subsubsubgroup', blkVars('subsubsubgroup')); + end + if groupInfo.groupNest >= level + groupName = groupInfo.(groupVar{level}); + if ~ischar(groupName) + error(['Invalid NbNoiseSource block ' noise.name char(10) ... + 'The ' groupVar{level} ' parameter (' ... + get_param(blk, groupVar{level}) ') must be a string']); + end + else + groupName = noise.name; + end + if isempty(groupName) + groupName = noise.name; + end + if ~noisesByGroup.isKey(groupName) + noisesByGroup(groupName) = {noise}; + else + noisesByGroup(groupName) = [noisesByGroup(groupName) {noise}]; + end +end + +%% Group the noises + +groupNames = noisesByGroup.keys(); +groupedNoises = cell(size(groupNames)); +disp([repmat(' ', 1, level - 1) 'Found ' num2str(numel(groupNames)) ' noise ' groupVar{level} 's:']); +for n = 1:numel(groupNames) + groupName = groupNames{n}; + group = noisesByGroup(groupName); + disp([repmat(' ', 1, level - 1) '* ' groupName]); + if numel(group) == 1 + group = group{1}; + else + group = groupAtLevel(group, level + 1, unit); + group = NoiseModel(group); + group.title = [groupName ' NoiseBudget']; + group.unit = unit; + end + group = renamed(group, groupName); + groupedNoises{n} = group; +end + +end \ No newline at end of file diff --git a/utils/SimulinkNbLite/SimulinkNb/resolveLibraryParam.m b/utils/SimulinkNbLite/SimulinkNb/resolveLibraryParam.m new file mode 100644 index 0000000000000000000000000000000000000000..2706f8247d3d414c78935e3404e45876853963ae --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/resolveLibraryParam.m @@ -0,0 +1,48 @@ +function expr = resolveLibraryParam(expr, blk) +%RESOLVELIBRARYPARAM Resolve the names of parameter structs inside masked library blocks +% This is a rather unsavory hack that handles the most common case: where +% inside the library there are variables like 'libraryPar.something', and +% in the library's mask 'libraryPar' is defined as 'par.somethingElse'. + + + +%% Input checks + +% If expr isn't simply accessing a struct, do nothing +structSplit = regexp(expr, '\.', 'split'); +if ~all(cellfun(@isvarname, structSplit)) + return; +end + +% If blk or parentBlk is empty, do nothing +if isempty(blk) + return; +end +parentBlk = get_param(blk, 'Parent'); +if isempty(parentBlk) + return; +end + +% If grandparent is empty (recursion stop condition), do nothing +blk = parentBlk; +if isempty(get_param(blk, 'Parent')); + return; +end + +%% Try to resolve the name of the struct referred to by expr + +structName = structSplit{1}; +maskVars = get_param(blk, 'MaskNames'); +if any(strcmp(structName, maskVars)) + newStructName = get_param(blk, structName); + if ~all(cellfun(@isvarname, regexp(newStructName, '\.', 'split'))) + error(['Block ' blk ' has invalid library parameter ' structName]); + end + expr = [newStructName expr(length(structName)+1:end)]; +end + +%% Recursive step + +expr = resolveLibraryParam(expr, blk); + +end diff --git a/utils/SimulinkNbLite/SimulinkNb/scb.m b/utils/SimulinkNbLite/SimulinkNb/scb.m new file mode 100644 index 0000000000000000000000000000000000000000..63e7b732ef15bd2b2ccb99109363c05c7051bef1 --- /dev/null +++ b/utils/SimulinkNbLite/SimulinkNb/scb.m @@ -0,0 +1,35 @@ +function scb(block) +%SCB Set current block. +% SCB(BLOCK) redefines the current block returned by GCB to be BLOCK. +% +% See also GCB, GCS. +% Downloaded from the Matlab File Exchange +% http://www.mathworks.com/matlabcentral/fileexchange/13833-scb +try + if ~strcmp('block',get_param(block,'Type')) + error('SCB:arg','Argument is not of type ''block''') + end +catch + error('SCB:obj','Invalid Simulink object name: %s',block) +end + +% Split Argument to System and Block-Name. +%[CurrentSystem,CurrentBlock] = fileparts(block); +% fix for block names containing '/' --ccw +CurrentSystem = get_param(block, 'Parent'); +CurrentBlock = get_param(block, 'Name'); + +% Get the Stateflow Root object. +root = sfroot; + +% Set the Current System to be the System of Block. +root.set('CurrentSystem',CurrentSystem); + +% Deselect Block that is Current Block in this System. +set_param(gcb,'Selected','off') + +% Set Current Block in this System to be Block. +root.getCurrentSystem.set('CurrentBlock',CurrentBlock) + +% Turn Selection on. +set_param(gcb,'Selected','on') diff --git a/utils/getTSfromTF.m b/utils/getTSfromTF.m new file mode 100644 index 0000000000000000000000000000000000000000..be1dab14836a3e497cb34ad9eca484d0f62344dc --- /dev/null +++ b/utils/getTSfromTF.m @@ -0,0 +1,51 @@ +function TFresponse = getTSfromTF(varargin) +%GETTFRESPONSE returns the response of the transfer function +%of the linearized model. +% Returns the response of the transfer function of the linearized +% model. First, linearizes the model around the given input and output. Then, +% it gets the frequency response of the linear TF. +% Syntax: TFresponse = getTFresponse(mdl, io, freqs) +% +% Inputs: mdl - simulink model, string; +% io - list of IO elements; +% u - ts +% t - time +% mode - direct/inverted +% +% Outputs: TFresponse - array containing the response, +% same size as the frequencies; +% +% See also: frd, linearize, linio, getInvertedTFresponse +% +% Author: Arthur Reis +% email: arthur.reis@aei.mpg.de +% Nov 2021; Last revision: Aug.2022; + +defaultMode = "direct"; + +p = inputParser; + +addRequired(p, 'mdl'); +addRequired(p, 'io'); +addRequired(p, 'u'); +addRequired(p, 't'); +addParameter(p, "mode", defaultMode); +parse(p, varargin{:}); + +mdl = p.Results.mdl; +io = p.Results.io; +u = p.Results.u; +t = p.Results.t; +mode = p.Results.mode; + +linearizedModel = linearize(mdl,io); +if strcmp(mode,defaultMode) + linearizedModel = linearize(mdl,io); +elseif strcmp(mode,"inverted") + linearizedModel = linearize(mdl,io); +end +lsim(linearizedModel,u,t); +linMdlResponse = frd(linearizedModel, freqs, 'unit', 'Hz'); +TFresponse = squeeze(abs(linMdlResponse.ResponseData)); +end + diff --git a/utils/masks/masks.odg b/utils/masks/masks.odg index 5b72cd7b0d4727ad84dcbb1922bc2c6586814b17..fee73ba144e5a0f11dc2c887a76c203c6516c397 100644 Binary files a/utils/masks/masks.odg and b/utils/masks/masks.odg differ