作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想定义一个控制系统 block :
class ControlSystemBlock
{
public:
ControlSystemBlock()
{
m_dbTimeStep = 0.001; // time between two consequential inputs
}
// this method can be called anytime,
// but the object will assume
// that it was called
// after m_dbTimeStep before the last call
void LoadNewInput(double dbInputValue);
double GetCurrentOutput();
// ...
private:
double m_dbTimeStep;
// ...
};
系统将接收输入,并根据这些输入和其中用户定义的传递函数,其输出值将随时间变化。
例如,假设我想实现传递函数H(s) = 1/(s + 2)
。我该怎么做?有什么算法吗?
最佳答案
你觉得我的代码怎么样:
ControlSystemBlock.h
#ifndef CONTROLSYSTEMBLOCK_H
#define CONTROLSYSTEMBLOCK_H
#include <vector>
#include <deque>
#include "Polynomial.h"
#include "PolynomialFraction.h"
class ControlSystemBlock
{
public:
enum SIGNAL_TYPE
{
ST_DISCRETE = 1,
ST_CONTINUOUS = 2
};
ControlSystemBlock( long double dbSamplingPeriod = 0.001);
ControlSystemBlock( const std::vector<long double> & NominatorCoefficients,
const std::vector<long double> & DenominatorCoefficients,
SIGNAL_TYPE SignalType = SIGNAL_TYPE::ST_CONTINUOUS,
long double dbSamplingPeriod = 0.001);
ControlSystemBlock( const Polynomial<long double> & NominatorPolynomial,
const Polynomial<long double> & DenominatorPolynomial,
SIGNAL_TYPE SignalType = SIGNAL_TYPE::ST_CONTINUOUS,
long double dbSamplingPeriod = 0.001);
ControlSystemBlock( const PolynomialFraction<long double> & TransferFunction,
SIGNAL_TYPE SignalType = SIGNAL_TYPE::ST_CONTINUOUS,
long double dbSamplingPeriod = 0.001);
// Sends a new input to the system block
// Assuming that this input is sent just after m_dbSamplingPeriod seconds after the last input
// Returns the the new output value
long double SendInput(long double dbInput);
long double GetOutput() const;
protected:
long double m_dbSamplingPeriod;
std::deque<long double> m_InputMemory;
std::deque<long double> m_OutputMemory;
void SetTransferFunction(const PolynomialFraction<long double> & TransferFunction, SIGNAL_TYPE SignalType);
PolynomialFraction<long double> m_TransferFunction;
private:
PolynomialFraction<long double> ContinuousTimeToDiscreteTime(const PolynomialFraction<long double> & ContinuousTimeTransferFunction);
PolynomialFraction<long double> ContinuousTimeToDiscreteTime(const Polynomial<long double> & NominatorPolynomial,
const Polynomial<long double> & DenominatorPolynomial);
PolynomialFraction<long double> ContinuousTimeToDiscreteTime(const std::vector<long double> & NominatorCoefficients,
const std::vector<long double> & DenominatorCoefficients);
void ShiftMemoryRegisters(long double dbNewInput);
};
#endif
ControlSystemBlock.cpp
#include "ControlSystemBlock.h"
ControlSystemBlock::ControlSystemBlock( long double dbSamplingPeriod /*= 0.001*/)
{
m_dbSamplingPeriod = dbSamplingPeriod;
std::vector<long double> Coefficients;
Coefficients.push_back(1.0);
PolynomialFraction<long double> TransferFunction(Coefficients, Coefficients);
SetTransferFunction(TransferFunction, SIGNAL_TYPE::ST_DISCRETE);
}
ControlSystemBlock::ControlSystemBlock( const std::vector<long double> & NominatorCoefficients,
const std::vector<long double> & DenominatorCoefficients,
SIGNAL_TYPE SignalType /*= SIGNAL_TYPE::ST_CONTINUOUS*/,
long double dbSamplingPeriod /*= 0.001*/)
{
m_dbSamplingPeriod = dbSamplingPeriod;
PolynomialFraction<long double> TransferFunction = PolynomialFraction<long double>(NominatorCoefficients, DenominatorCoefficients);
SetTransferFunction(TransferFunction, SignalType);
}
ControlSystemBlock::ControlSystemBlock( const Polynomial<long double> & NominatorPolynomial,
const Polynomial<long double> & DenominatorPolynomial,
SIGNAL_TYPE SignalType /*= SIGNAL_TYPE::ST_CONTINUOUS*/,
long double dbSamplingPeriod /*= 0.001*/ )
{
m_dbSamplingPeriod = dbSamplingPeriod;
PolynomialFraction<long double> TransferFunction = PolynomialFraction<long double>(NominatorPolynomial, DenominatorPolynomial);
SetTransferFunction(TransferFunction, SignalType);
}
ControlSystemBlock::ControlSystemBlock( const PolynomialFraction<long double> & TransferFunction,
ControlSystemBlock::SIGNAL_TYPE SignalType /*= SIGNAL_TYPE::ST_CONTINUOUS*/,
long double dbSamplingPeriod /*= 0.001*/)
{
m_dbSamplingPeriod = dbSamplingPeriod;
if (SignalType == SIGNAL_TYPE::ST_CONTINUOUS)
SetTransferFunction(TransferFunction, SignalType);
}
long double ControlSystemBlock::SendInput(long double dbInput)
{
ShiftMemoryRegisters(dbInput);
long double dbSumX = 0.0, dbSumY = 0.0;
for (uint64_t i=0; i<m_TransferFunction.GetNominatorDegree()+1; i++)
{
dbSumX += m_TransferFunction.GetNominator().GetCoefficientAt(i) * m_InputMemory.at(i);
}
for (uint64_t i=1; i<m_TransferFunction.GetDenominatorDegree()+1; i++)
{
dbSumY += m_TransferFunction.GetDenominator().GetCoefficientAt(i) * m_OutputMemory.at(i);
}
return m_OutputMemory.at(0) = (dbSumX - dbSumY) / m_TransferFunction.GetDenominator().GetCoefficientAt(0);
}
long double ControlSystemBlock::GetOutput() const
{
return m_OutputMemory.at(0);
}
PolynomialFraction<long double> ControlSystemBlock::ContinuousTimeToDiscreteTime(const PolynomialFraction<long double> & ContinuousTimeTransferFunction)
{
// Generate an "s" term in terms of "z^(-1)" terms
std::vector<long double> nom, den;
nom.push_back(1);
nom.push_back(-1);
den.push_back(1);
den.push_back(1);
PolynomialFraction<long double> STerm(nom, den);
STerm *= static_cast<long double>(2) / m_dbSamplingPeriod;
// Define nominator and denominator terms of the discrete time transfer function separately
nom.clear();
den.clear();
nom.push_back(0);
nom.push_back(1);
PolynomialFraction<long double> NominatorOfDiscreteTimeTransferFunction(nom, den);
PolynomialFraction<long double> DenominatorOfDiscreteTimeTransferFunction(nom, den);
// Generate the nominator and denominator terms of the resulting discrete time transfer function
for (uint64_t i=0; i<ContinuousTimeTransferFunction.GetNominatorDegree()+1; i++)
{
NominatorOfDiscreteTimeTransferFunction += STerm.GetPower(i) * ContinuousTimeTransferFunction.GetNominator().GetCoefficientAt(i);
}
for (uint64_t i=0; i<ContinuousTimeTransferFunction.GetDenominatorDegree()+1; i++)
{
NominatorOfDiscreteTimeTransferFunction += STerm.GetPower(i) * ContinuousTimeTransferFunction.GetDenominator().GetCoefficientAt(i);
}
return NominatorOfDiscreteTimeTransferFunction / DenominatorOfDiscreteTimeTransferFunction;
}
PolynomialFraction<long double> ControlSystemBlock::ContinuousTimeToDiscreteTime(const Polynomial<long double> & NominatorPolynomial,
const Polynomial<long double> & DenominatorPolynomial)
{
PolynomialFraction<long double> ContinuousTimeTransferFunction(NominatorPolynomial, DenominatorPolynomial);
return ContinuousTimeToDiscreteTime(ContinuousTimeTransferFunction);
}
PolynomialFraction<long double> ControlSystemBlock::ContinuousTimeToDiscreteTime(const std::vector<long double> & NominatorCoefficients,
const std::vector<long double> & DenominatorCoefficients)
{
PolynomialFraction<long double> ContinuousTimeTransferFunction(NominatorCoefficients, DenominatorCoefficients);
return ContinuousTimeToDiscreteTime(ContinuousTimeTransferFunction);
}
void ControlSystemBlock::SetTransferFunction( const PolynomialFraction<long double> & TransferFunction, SIGNAL_TYPE SignalType)
{
if (SignalType == SIGNAL_TYPE::ST_CONTINUOUS)
{
m_TransferFunction = ContinuousTimeToDiscreteTime(TransferFunction);
}
else
{
m_TransferFunction = TransferFunction;
}
m_InputMemory.resize(m_TransferFunction.GetNominatorDegree() + 1, 0.0);
m_OutputMemory.resize(m_TransferFunction.GetDenominatorDegree() + 1, 0.0);
}
void ControlSystemBlock::ShiftMemoryRegisters(long double dbNewInput)
{
m_InputMemory.push_back(dbNewInput);
m_InputMemory.pop_front();
m_OutputMemory.push_back(0.0);
m_OutputMemory.pop_front();
}
我刚做完。
我很快就会测试它。
关于c++ - 如何在 C++ 中实现传递函数的控制系统 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4542837/
我是一名优秀的程序员,十分优秀!