我想定义一个控制系统块,如:
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)
。我该怎么做?那有什么算法吗?
答案 0 :(得分:3)
您如何看待我的代码:
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();
}
我刚刚完成它。
我很快就会测试它。
答案 1 :(得分:0)
使系统接受一个函数(即C ++ 0x中的std::function
或Boost中的等价物)取一个double并返回一个double,并使用该函数进行实际计算。
然后,用户可以提供任意函数或函子(类重载operator()
),以便执行所需的转换功能。
或者,使您的函数需要任意转换模板函数,并按值传递函子/函数指针,就像STL算法一样。