2010-12-28 9 views
1

Ich mag einen Steuersystemblock definieren, wie:Wie implementiere ich den Kontrollsystemblock einer Transferfunktion in C++?

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; 
    // ... 
}; 

Die Systemeingaben empfangen werden, und gemäß diesen Eingängen und benutzerdefinierte Übertragungsfunktion darin, wird sein Ausgabewert in der Zeit ändern.

Nehmen wir zum Beispiel an, dass ich die Übertragungsfunktion H(s) = 1/(s + 2) implementieren möchte. Wie mache ich es? Gibt es einen Algorithmus dafür?

+0

Ihre Frage ist mir nicht sehr klar ... Können Sie ein Beispiel geben, wie Ihre Übertragungsfunktion weitergegeben werden soll? –

Antwort

3

Was halten Sie von meinem Code:

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(); 
} 

Ich habe es gerade fertig.
Ich werde es bald testen.

+0

Ich weiß, dass diese Frage ein bisschen alt ist ... Aber, hat das funktioniert? – YuppieNetworking

+0

@YuppieNetworking Ja, ich benutze es seit mehr als einem Jahr. Es funktioniert ohne Probleme. Ich habe seitdem einige Änderungen am Code vorgenommen. – hkBattousai

+0

Nur eine weitere Frage: Sind Ihre Polynom- und Polynomfraktionsklassen Teil einer Bibliothek oder gehören sie Ihnen? – YuppieNetworking

0

Lassen Sie das System eine Funktion akzeptieren (d. H. std::function in C++ 0x oder die Entsprechungen in Boost), indem Sie ein Double und ein Double nehmen und diese Funktion für die eigentliche Berechnung verwenden.

Der Benutzer kann dann jede beliebige Funktion oder Funktor liefern (eine Klasse, die operator() überlädt), um die gewünschte Transformationsfunktion auszuführen.

Alternativ machen Sie Ihre Funktionen erfordern die willkürlichen Transformationsvorlage Funktionen und übergeben Sie den Funktor/Funktionszeiger in Wert, wie die STL-Algorithmen tun.

Verwandte Themen