c++ - 如何在 C++ 中实现传递函数的控制系统 block ?

标签 c++ function controls system transfer

我想定义一个控制系统 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/

相关文章:

c - 如何在C中调用一个函数?另外,为什么几乎每一行代码都是错误的?

javascript - 有没有简单的 JavaScript slider ?

javascript - 在 Javascript 中优化和实现冗长的函数数组

ASP.net,为什么它使用长元素名称?

algorithm - 确定频率的持续时间和幅度

c++ - 接口(interface)的名称是否可以与其类中的名称不同? [C++]

c++ - 使用 openmp 在 C++ 中进行并行编程

c++ - 从 Python 使用 C++? (不是提升)

c++ - Do - Try/Catch - While block 内部有 2 个函数

c++ - 读函数被 main 调用,但没有执行