#include "brick_link.h" BrickLinkTransferFunction::BrickLinkTransferFunction(const PIString & num, const PIString & denom): BrickLinkBase(1, 1, 2) { type = "TransferFunction"; setName(type); paramNames[1] = "Numerator"; paramNames[2] = "Denominator"; parameters[1] = num; parameters[2] = denom; interactive = true; parameterChanged(1); } void BrickLinkTransferFunction::parameterChanged(int index) { if (index == 0) { KF.setMethod((PIMathSolver::Method)parameters[0].toInt()); return; } PIString ts; note_ = "Your function:\n\n"; PIStringList sl = parameters[1].toString().split(" "); sl.removeStrings(""); sl.removeStrings("\t"); TF.vector_Bm.resize(sl.size()); for (int i = sl.size_s() - 1; i >= 0; --i) { TF.vector_Bm[i] = sl[sl.size_s() - 1 - i].toDouble(); ts += PIString::fromNumber(TF.vector_Bm[i]); if (i > 1) { ts += "s^{" + PIString::fromNumber(i) + "} + "; continue; } if (i > 0) ts += "s" + PIString(" + "); } if (ts.left(2) == "1s") ts.pop_front(); if (ts.left(3) == "-1s") ts.replace(0, 2, "-"); note_ += ts + "\n---\n"; sl = parameters[2].toString().split(" "); sl.removeStrings(""); sl.removeStrings("\t"); TF.vector_An.resize(sl.size()); ts.clear(); for (int i = sl.size_s() - 1; i >= 0; --i) { TF.vector_An[i] = sl[sl.size_s() - 1 - i].toDouble(); ts += PIString::fromNumber(TF.vector_An[i]); if (i > 1) { ts += "s^{" + PIString::fromNumber(i) + "} + "; continue; } if (i > 0) ts += "s" + PIString(" + "); } if (ts.left(2) == "1s") ts.pop_front(); if (ts.left(3) == "-1s") ts.replace(0, 2, "-"); note_ += ts; note_.replaceAll("+ -", "- "); note_.replaceAll(" + 1s", " + s"); note_.replaceAll(" - 1s", " - s"); } bool BrickLinkTransferFunction::tick_body(double time) { KF.setTime(time); KF.solve(inputs[0], dt); outputs[0] = KF.X[0]; return true; } BrickLinkFilter1Degree::BrickLinkFilter1Degree(double t, double k): BrickLinkBase(3, 2) { setParameters(t, k); type = "Filter1Degree"; setName(type); inNames[1] = "T"; inNames[2] = "K"; outNames[0] = "Low Pass"; outNames[1] = "High Pass"; s.setPreamp(1, -1.); makeConnections(); } bool BrickLinkFilter1Degree::tick_body(double time) { if (inputs[T] == 0.) return false; a.setGain(1. / inputs[T]); s.setPreamp(0, inputs[K]); s.setInputValue(0, inputs[Input]); s.tick(time); s.proceedConnections(); a.tick(time); a.proceedConnections(); i.tick(time); i.proceedConnections(); outputs[LowPass] = i.output(); outputs[HighPass] = s.output(); return true; } BrickLinkFilterBandpass::BrickLinkFilterBandpass(double lf, double hf): BrickLinkBase(3, 1) { TF.vector_Bm.resize(2); TF.vector_An.resize(3, 1.); type = "FilterBandpass"; setName(type); inNames[1] = "Low Freq"; inNames[2] = "High Freq"; setParameters(lf, hf); pl = ph = 0.; } bool BrickLinkFilterBandpass::tick_body(double time) { if (pl != inputs[LF] || ph != inputs[HF]) { pl = inputs[LF]; ph = inputs[HF]; if (pl != 0.) t0 = 1. / pl; else t0 = 0.; if (ph != 0.) t1 = 1. / ph; else t1 = 0.; TF.vector_Bm[0] = 0.; TF.vector_Bm[1] = t0; TF.vector_An[0] = 1.; TF.vector_An[1] = t0 + t1; TF.vector_An[2] = t0 * t1; KF.fromTF(TF); } KF.solve(inputs[0], dt); outputs[0] = KF.X[0]; return true; } BrickLinkFilterMedian::BrickLinkFilterMedian(int count): BrickLinkBase(1, 1, 0) { type = "FilterMedian"; setName(type); paramNames[0] = "Count"; parameters[0].setValue(count); note_ = "Size of window"; setParameters(count); } bool BrickLinkFilterMedian::tick_body(double time) { for (int i = 0; i < hist_.size_s() - 1; ++i) hist_[i] = hist_[i + 1]; hist_.back() = inputs[0]; hsort = hist_; hsort.sort(); int size = hsort.size_s(); if (size == 0) { outputs[0] = 0.; } else { if (size % 2 == 1) outputs[0] = hsort[size / 2]; else outputs[0] = (hsort[size / 2 - 1] + hsort[size / 2]) / 2.; } return true; }